From 75aa20163100277a796a9f4387531c3a73f644e6 Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Thu, 13 Jun 2024 16:16:12 +0200 Subject: [PATCH] systemd-252-37 Resolves: RHEL-13159,RHEL-20322,RHEL-27512,RHEL-30372,RHEL-31070,RHEL-31219,RHEL-33890,RHEL-35703,RHEL-38864,RHEL-40878,RHEL-6589 --- ...HEL-9.1-and-RHEL-9.1.z-to-allowed-ve.patch | 25 + 0743-libsystemd-link-with-z-nodelete.patch | 30 + ...utf8_encoded_to_unichar-return-lengt.patch | 54 + ...d-new-test-to-show-that-unichar_iswi.patch | 67 + ...ass-ANSI-sequences-through-unchanged.patch | 320 ++ ...t-assert-when-unsealing-token-withou.patch | 75 + ...-the-existence-of-salt-by-salt_size-.patch | 29 + ...ount-8-fails-but-mount-disappeared-a.patch | 83 + ...g-level-of-header-limits-log-message.patch | 31 + ...otate-unrelated-journal-files-when-f.patch | 136 + ...with-an-equal-sign-since-it-expects-.patch | 41 + ...alloc-range.-ch-from-src-shared-src-.patch | 57 + ...d_for_system_journal-to-uid-alloc-ra.patch | 66 + ...SD_JOURNAL_CURRENT_USER-is-set-and-c.patch | 65 + ...t-journalctl-user-requires-Storage-p.patch | 46 + 0757-fix-prefix-of-dmesg-pstore-files.patch | 35 + 0758-backport-new-mkosi.patch | 2617 +++++++++++++++++ ...arious-tests-when-sys-is-not-mounted.patch | 335 +++ 0760-string-util-introduce-ascii_ishex.patch | 27 + 0761-sd-id128-several-cleanups.patch | 207 ++ ...128_read-or-friends-return-ENOPKG-wh.patch | 468 +++ ...or-uninitialized-string-handling-by-.patch | 49 + ...d128_get_machine-or-friend-may-retur.patch | 32 + ..._id128_get_boot-and-friend-return-EN.patch | 27 + ..._id128_get_boot-and-friend-return-EN.patch | 34 + ...-sd_id128_get_boot-and-friend-may-re.patch | 63 + ...ld-do_sync-flag-into-Id128FormatFlag.patch | 143 + ..._id128_get_machine-or-friends-return.patch | 229 ++ ...d_id128_get_machine-and-friend-to-be.patch | 90 + ...8-also-refuse-an-empty-invocation-ID.patch | 41 + ...ocuments-for-sd_id128_get_invocation.patch | 41 + ...test-id128-simplify-machine-id-check.patch | 48 + ...p-part-of-test_chase_symlinks-if-mac.patch | 30 + ...-unit-name-simplify-machine-id-check.patch | 34 + ...d-fragment-simplify-machine-id-check.patch | 34 + ...t-of-test-journal-interleaving-if-no.patch | 75 + ...l-tests-without-valid-etc-machine-id.patch | 111 + ...r-work-around-nftw-ignoring-symlinks.patch | 61 + ...t-Skip-test-recurse-dir-on-overlayfs.patch | 70 + ...-Ignore-ENOPKG-from-specifier_printf.patch | 28 + ...t-execute-Skip-when-sys-is-read-only.patch | 29 + ...ake-sure-KERNEL_INSTALL_BYPASS-is-di.patch | 25 + ...KERNEL_INSTALL_BYPASS-is-disabled-wh.patch | 42 + ...p-capabilities-when-testing-with-use.patch | 888 ++++++ ...-merge-support-for-copy-files-action.patch | 96 + ...nerator_open_unit_file_full-to-allow.patch | 116 + ...r-rewrite-unit-if-it-already-exists-.patch | 142 + 0789-ci-drop-super-linter-s-shellcheck.patch | 38 + ...-make-sure-we-build-use-RHEL-9-stuff.patch | 130 + ...mkosi-CI-configuration-from-upstream.patch | 217 ++ ...si-explicitly-enroll-SecureBoot-keys.patch | 23 + ...-execute-also-mount-tmpfs-on-dev-shm.patch | 37 + 0794-mkosi-fix-UKI-addons-test.patch | 106 + ...i-Disable-cmdline-addon-test-for-now.patch | 36 + ...-t-fail-on-systemd-vconsole-setup.se.patch | 31 + 0797-mkosi-make-shellcheck-happy.patch | 25 + ...si-use-pesign-for-signing-UKI-addons.patch | 67 + ...e-necessary-test-data-before-we-star.patch | 65 + ...d-dir-accessible-when-running-w-o-pr.patch | 39 + ...ange-oom-score-adj-before-running-te.patch | 74 + ...-ratelimit-add-ratelimit_left-helper.patch | 49 + ...-Dump-to-privileged-callers-or-ratel.patch | 264 ++ 0804-ci-define-runas-function-inline.patch | 60 + ...rop-dev-test-in-test-mountpoint-util.patch | 31 + ...nager-export-manager_dbus_is_running.patch | 69 + ...us-activation-if-dbus-is-not-running.patch | 61 + ...-Type-dbus-service-enqueuing-if-dbus.patch | 84 + ...ger-export-manager_dbus_is_running-a.patch | 93 + ...eloading-in-reload-or-restart-marked.patch | 127 + ...postun_with_reload-and-systemd_user_.patch | 98 + 0812-rpm-add-systemd_user_daemon_reexec.patch | 38 + systemd.spec | 146 +- 72 files changed, 9399 insertions(+), 1 deletion(-) create mode 100644 0742-ci-src-git-add-RHEL-9.1-and-RHEL-9.1.z-to-allowed-ve.patch create mode 100644 0743-libsystemd-link-with-z-nodelete.patch create mode 100644 0744-basic-utf8-make-utf8_encoded_to_unichar-return-lengt.patch create mode 100644 0745-test-gunicode-add-new-test-to-show-that-unichar_iswi.patch create mode 100644 0746-string-util-pass-ANSI-sequences-through-unchanged.patch create mode 100644 0747-cryptsetup-do-not-assert-when-unsealing-token-withou.patch create mode 100644 0748-cryptsetup-check-the-existence-of-salt-by-salt_size-.patch create mode 100644 0749-core-mount-if-umount-8-fails-but-mount-disappeared-a.patch create mode 100644 0750-Drop-log-level-of-header-limits-log-message.patch create mode 100644 0751-journal-do-not-rotate-unrelated-journal-files-when-f.patch create mode 100644 0752-man-suffix-unit-with-an-equal-sign-since-it-expects-.patch create mode 100644 0753-shared-move-uid-alloc-range.-ch-from-src-shared-src-.patch create mode 100644 0754-journald-move-uid_for_system_journal-to-uid-alloc-ra.patch create mode 100644 0755-sd-journal-when-SD_JOURNAL_CURRENT_USER-is-set-and-c.patch create mode 100644 0756-man-document-that-journalctl-user-requires-Storage-p.patch create mode 100644 0757-fix-prefix-of-dmesg-pstore-files.patch create mode 100644 0758-backport-new-mkosi.patch create mode 100644 0759-test-Skip-various-tests-when-sys-is-not-mounted.patch create mode 100644 0760-string-util-introduce-ascii_ishex.patch create mode 100644 0761-sd-id128-several-cleanups.patch create mode 100644 0762-sd-id128-make-id128_read-or-friends-return-ENOPKG-wh.patch create mode 100644 0763-test-add-tests-for-uninitialized-string-handling-by-.patch create mode 100644 0764-man-mention-sd_id128_get_machine-or-friend-may-retur.patch create mode 100644 0765-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch create mode 100644 0766-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch create mode 100644 0767-man-mention-that-sd_id128_get_boot-and-friend-may-re.patch create mode 100644 0768-sd-id128-fold-do_sync-flag-into-Id128FormatFlag.patch create mode 100644 0769-sd-id128-make-sd_id128_get_machine-or-friends-return.patch create mode 100644 0770-sd-id128-allow-sd_id128_get_machine-and-friend-to-be.patch create mode 100644 0771-sd-id128-also-refuse-an-empty-invocation-ID.patch create mode 100644 0772-man-update-documents-for-sd_id128_get_invocation.patch create mode 100644 0773-test-id128-simplify-machine-id-check.patch create mode 100644 0774-test-fs-util-skip-part-of-test_chase_symlinks-if-mac.patch create mode 100644 0775-test-unit-name-simplify-machine-id-check.patch create mode 100644 0776-test-load-fragment-simplify-machine-id-check.patch create mode 100644 0777-journal-skip-part-of-test-journal-interleaving-if-no.patch create mode 100644 0778-test-skip-journal-tests-without-valid-etc-machine-id.patch create mode 100644 0779-test-recurse-dir-work-around-nftw-ignoring-symlinks.patch create mode 100644 0780-test-Skip-test-recurse-dir-on-overlayfs.patch create mode 100644 0781-test-specifier-Ignore-ENOPKG-from-specifier_printf.patch create mode 100644 0782-test-execute-Skip-when-sys-is-read-only.patch create mode 100644 0783-kernel-install-Make-sure-KERNEL_INSTALL_BYPASS-is-di.patch create mode 100644 0784-tools-make-sure-KERNEL_INSTALL_BYPASS-is-disabled-wh.patch create mode 100644 0785-test-execute-drop-capabilities-when-testing-with-use.patch create mode 100644 0786-tmpfiles-Add-merge-support-for-copy-files-action.patch create mode 100644 0787-generator-add-generator_open_unit_file_full-to-allow.patch create mode 100644 0788-network-generator-rewrite-unit-if-it-already-exists-.patch create mode 100644 0789-ci-drop-super-linter-s-shellcheck.patch create mode 100644 0790-mkosi-make-sure-we-build-use-RHEL-9-stuff.patch create mode 100644 0791-ci-backport-mkosi-CI-configuration-from-upstream.patch create mode 100644 0792-mkosi-explicitly-enroll-SecureBoot-keys.patch create mode 100644 0793-test-execute-also-mount-tmpfs-on-dev-shm.patch create mode 100644 0794-mkosi-fix-UKI-addons-test.patch create mode 100644 0795-Revert-mkosi-Disable-cmdline-addon-test-for-now.patch create mode 100644 0796-Revert-mkosi-Don-t-fail-on-systemd-vconsole-setup.se.patch create mode 100644 0797-mkosi-make-shellcheck-happy.patch create mode 100644 0798-mkosi-use-pesign-for-signing-UKI-addons.patch create mode 100644 0799-test-copy-out-the-necessary-test-data-before-we-star.patch create mode 100644 0800-ci-make-the-build-dir-accessible-when-running-w-o-pr.patch create mode 100644 0801-ci-explicitly-change-oom-score-adj-before-running-te.patch create mode 100644 0802-ratelimit-add-ratelimit_left-helper.patch create mode 100644 0803-manager-restrict-Dump-to-privileged-callers-or-ratel.patch create mode 100644 0804-ci-define-runas-function-inline.patch create mode 100644 0805-Drop-dev-test-in-test-mountpoint-util.patch create mode 100644 0806-core-manager-export-manager_dbus_is_running.patch create mode 100644 0807-core-refuse-dbus-activation-if-dbus-is-not-running.patch create mode 100644 0808-core-only-refuse-Type-dbus-service-enqueuing-if-dbus.patch create mode 100644 0809-Revert-core-manager-export-manager_dbus_is_running-a.patch create mode 100644 0810-manager-fix-reloading-in-reload-or-restart-marked.patch create mode 100644 0811-rpm-add-systemd_postun_with_reload-and-systemd_user_.patch create mode 100644 0812-rpm-add-systemd_user_daemon_reexec.patch diff --git a/0742-ci-src-git-add-RHEL-9.1-and-RHEL-9.1.z-to-allowed-ve.patch b/0742-ci-src-git-add-RHEL-9.1-and-RHEL-9.1.z-to-allowed-ve.patch new file mode 100644 index 0000000..96f74e5 --- /dev/null +++ b/0742-ci-src-git-add-RHEL-9.1-and-RHEL-9.1.z-to-allowed-ve.patch @@ -0,0 +1,25 @@ +From 43373d851c9f6222f4523b9db7006fbfe14c3d70 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 23 May 2024 18:07:45 +0200 +Subject: [PATCH] ci(src-git): add RHEL-9.1 and RHEL-9.1.z to allowed versions + +rhel-only + +Related: RHEL-30372 +--- + .github/tracker-validator.yml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/.github/tracker-validator.yml b/.github/tracker-validator.yml +index 31ef28f6ea..21cbedd8b0 100644 +--- a/.github/tracker-validator.yml ++++ b/.github/tracker-validator.yml +@@ -8,6 +8,8 @@ products: + - CentOS Stream 9 + - rhel-9.0.0 + - rhel-9.0.0.z ++ - rhel-9.1.0 ++ - rhel-9.1.0.z + - rhel-9.2.0 + - rhel-9.2.0.z + - rhel-9.3.0 diff --git a/0743-libsystemd-link-with-z-nodelete.patch b/0743-libsystemd-link-with-z-nodelete.patch new file mode 100644 index 0000000..e904981 --- /dev/null +++ b/0743-libsystemd-link-with-z-nodelete.patch @@ -0,0 +1,30 @@ +From aa18f6b2b2cad6977f39e1e323705e2b11a7829c Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 23 May 2024 17:35:51 +0200 +Subject: [PATCH] libsystemd: link with '-z nodelete' + +We want to avoid reinitialization of our global variables with static +storage duration in case we get dlopened multiple times by the same +application. This will avoid potential resource leaks that could have +happened otherwise (e.g. leaking journal socket fd). + +(cherry picked from commit 9d8533b7152daf792356c601516b57c6412d3e52) + +Resolves: RHEL-6589 +--- + meson.build | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/meson.build b/meson.build +index 843d823e3e..274e43ba9e 100644 +--- a/meson.build ++++ b/meson.build +@@ -2004,6 +2004,8 @@ libsystemd = shared_library( + version : libsystemd_version, + include_directories : libsystemd_includes, + link_args : ['-shared', ++ # Make sure our library is never deleted from memory, so that our open logging fds don't leak on dlopen/dlclose cycles. ++ '-z', 'nodelete', + '-Wl,--version-script=' + libsystemd_sym_path], + link_with : [libbasic, + libbasic_gcrypt, diff --git a/0744-basic-utf8-make-utf8_encoded_to_unichar-return-lengt.patch b/0744-basic-utf8-make-utf8_encoded_to_unichar-return-lengt.patch new file mode 100644 index 0000000..160a4a5 --- /dev/null +++ b/0744-basic-utf8-make-utf8_encoded_to_unichar-return-lengt.patch @@ -0,0 +1,54 @@ +From d26e1ba4539a3a33224ca1019b9e6cf5590744f5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 23 Jun 2023 11:10:42 -0600 +Subject: [PATCH] basic/utf8: make utf8_encoded_to_unichar() return length of + the codepoint + +(cherry picked from commit 9579e9a5308573c3c9c82f1978456cc71f68760c) + +Related: RHEL-31219 +--- + src/basic/utf8.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/src/basic/utf8.c b/src/basic/utf8.c +index 2532fcf81a..9d9e76904e 100644 +--- a/src/basic/utf8.c ++++ b/src/basic/utf8.c +@@ -90,7 +90,7 @@ int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) { + switch (len) { + case 1: + *ret_unichar = (char32_t)str[0]; +- return 0; ++ return 1; + case 2: + unichar = str[0] & 0x1f; + break; +@@ -119,15 +119,14 @@ int utf8_encoded_to_unichar(const char *str, char32_t *ret_unichar) { + } + + *ret_unichar = unichar; +- +- return 0; ++ return len; + } + + bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newline) { + assert(str); + + for (const char *p = str; length > 0;) { +- int encoded_len, r; ++ int encoded_len; + char32_t val; + + encoded_len = utf8_encoded_valid_unichar(p, length); +@@ -135,8 +134,7 @@ bool utf8_is_printable_newline(const char* str, size_t length, bool allow_newlin + return false; + assert(encoded_len > 0 && (size_t) encoded_len <= length); + +- r = utf8_encoded_to_unichar(p, &val); +- if (r < 0 || ++ if (utf8_encoded_to_unichar(p, &val) < 0 || + unichar_is_control(val) || + (!allow_newline && val == '\n')) + return false; diff --git a/0745-test-gunicode-add-new-test-to-show-that-unichar_iswi.patch b/0745-test-gunicode-add-new-test-to-show-that-unichar_iswi.patch new file mode 100644 index 0000000..56eccf3 --- /dev/null +++ b/0745-test-gunicode-add-new-test-to-show-that-unichar_iswi.patch @@ -0,0 +1,67 @@ +From 0fc377b76f10eb283d4de76b8fe7c083b95f70b7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 23 Jun 2023 17:24:11 -0600 +Subject: [PATCH] test-gunicode: add new test to show that unichar_iswide() is + borked + +I discovered this while looking at the tests with wide characters in the next +patch. It's something to fix, but not directly relevant to the issue of +skipping ANSI in ellipsization. We will generate output that is wider than +expected in some cases, but wide characters are used very rarely so this isn't +such a big problem. + +(cherry picked from commit d9c72e54190db2a0845d1558b5beb734e9f629ff) + +Related: RHEL-31219 +--- + src/test/meson.build | 2 ++ + src/test/test-gunicode.c | 27 +++++++++++++++++++++++++++ + 2 files changed, 29 insertions(+) + create mode 100644 src/test/test-gunicode.c + +diff --git a/src/test/meson.build b/src/test/meson.build +index 5430e72ab5..1d61dc343f 100644 +--- a/src/test/meson.build ++++ b/src/test/meson.build +@@ -469,6 +469,8 @@ tests += [ + + [files('test-gpt.c')], + ++ [files('test-gunicode.c')], ++ + [files('test-log.c')], + + [files('test-ipcrm.c'), +diff --git a/src/test/test-gunicode.c b/src/test/test-gunicode.c +new file mode 100644 +index 0000000000..1836cdc04a +--- /dev/null ++++ b/src/test/test-gunicode.c +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++ ++#include "gunicode.h" ++#include "tests.h" ++#include "utf8.h" ++ ++TEST(unichar_iswide) { ++ char32_t c; ++ int r; ++ ++ /* FIXME: the cats are wide, but we get this wrong */ ++ for (const char *narrow = "abX_…ąęµ!" "😼😿🙀😸😻"; *narrow; narrow += r) { ++ r = utf8_encoded_to_unichar(narrow, &c); ++ bool w = unichar_iswide(c); ++ assert_se(r > 0); ++ assert_se(!w); ++ } ++ ++ for (const char *wide = "🐱/¥"; *wide; wide += r) { ++ r = utf8_encoded_to_unichar(wide, &c); ++ bool w = unichar_iswide(c); ++ assert_se(r > 0); ++ assert_se(w); ++ } ++} ++ ++DEFINE_TEST_MAIN(LOG_INFO); diff --git a/0746-string-util-pass-ANSI-sequences-through-unchanged.patch b/0746-string-util-pass-ANSI-sequences-through-unchanged.patch new file mode 100644 index 0000000..17bc5cd --- /dev/null +++ b/0746-string-util-pass-ANSI-sequences-through-unchanged.patch @@ -0,0 +1,320 @@ +From cec4cc86486d3e212b5e919595feb39c6cee4c2c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 23 Jun 2023 18:40:14 -0600 +Subject: [PATCH] string-util: pass ANSI sequences through unchanged +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Cutting off in the middle may leave the terminal in a bad state, breaking +further output. But we don't know what a given ANSI sequence does, e.g. +ANSI_NORMAL should not be skipped. But it is also nice to keep various +sequences intact, so that if we had part of the string in blue, and we cut out +the beginning of the blue part, we still want to keep the remainder in color. +So let's just pass them through, stripping out the characters that take up +actual space. + +Also, use memcpy_safe as we may end up copying zero bytes when ellipsizing at +the start/end of a string. + +Fixes: #24502 + +This also fixes an ugliness where we would ellipsize string with ANSI +sequences too much, leading to output that was narrower on screen than the +requested length: + + Starting AAAAAAAAAAAAAAAAAAAAA.service + Starting BBBBBBBBBBBBBBBBBBBBB.service + Starting LONG…ER.service + +Co-authored-by: Jan Janssen + +(cherry picked from commit cb558ab222f0dbda3afd985c2190f35693963ffa) + +Resolves: RHEL-31219 +--- + src/basic/string-util.c | 163 ++++++++++++++++++++++++++++++-------- + src/test/test-ellipsize.c | 41 ++++++++++ + 2 files changed, 172 insertions(+), 32 deletions(-) + +diff --git a/src/basic/string-util.c b/src/basic/string-util.c +index 17d35fe1a4..fe6e9e94ad 100644 +--- a/src/basic/string-util.c ++++ b/src/basic/string-util.c +@@ -288,6 +288,62 @@ static int write_ellipsis(char *buf, bool unicode) { + return 3; + } + ++static size_t ansi_sequence_length(const char *s, size_t len) { ++ assert(s); ++ ++ if (len < 2) ++ return 0; ++ ++ if (s[0] != 0x1B) /* ASCII 27, aka ESC, aka Ctrl-[ */ ++ return 0; /* Not the start of a sequence */ ++ ++ if (s[1] == 0x5B) { /* [, start of CSI sequence */ ++ size_t i = 2; ++ ++ if (i == len) ++ return 0; ++ ++ while (s[i] >= 0x30 && s[i] <= 0x3F) /* Parameter bytes */ ++ if (++i == len) ++ return 0; ++ while (s[i] >= 0x20 && s[i] <= 0x2F) /* Intermediate bytes */ ++ if (++i == len) ++ return 0; ++ if (s[i] >= 0x40 && s[i] <= 0x7E) /* Final byte */ ++ return i + 1; ++ return 0; /* Bad sequence */ ++ ++ } else if (s[1] >= 0x40 && s[1] <= 0x5F) /* other non-CSI Fe sequence */ ++ return 2; ++ ++ return 0; /* Bad escape? */ ++} ++ ++static bool string_has_ansi_sequence(const char *s, size_t len) { ++ const char *t = s; ++ ++ while ((t = memchr(s, 0x1B, len - (t - s)))) ++ if (ansi_sequence_length(t, len - (t - s)) > 0) ++ return true; ++ return false; ++} ++ ++static size_t previous_ansi_sequence(const char *s, size_t length, const char **ret_where) { ++ /* Locate the previous ANSI sequence and save its start in *ret_where and return length. */ ++ ++ for (size_t i = length - 2; i > 0; i--) { /* -2 because at least two bytes are needed */ ++ size_t slen = ansi_sequence_length(s + (i - 1), length - (i - 1)); ++ if (slen == 0) ++ continue; ++ ++ *ret_where = s + (i - 1); ++ return slen; ++ } ++ ++ *ret_where = NULL; ++ return 0; ++} ++ + static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) { + size_t x, need_space, suffix_len; + char *t; +@@ -347,7 +403,6 @@ static char *ascii_ellipsize_mem(const char *s, size_t old_length, size_t new_le + char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigned percent) { + size_t x, k, len, len2; + const char *i, *j; +- char *e; + int r; + + /* Note that 'old_length' refers to bytes in the string, while 'new_length' refers to character cells taken up +@@ -371,73 +426,117 @@ char *ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne + if (new_length == 0) + return strdup(""); + +- /* If no multibyte characters use ascii_ellipsize_mem for speed */ +- if (ascii_is_valid_n(s, old_length)) ++ bool has_ansi_seq = string_has_ansi_sequence(s, old_length); ++ ++ /* If no multibyte characters or ANSI sequences, use ascii_ellipsize_mem for speed */ ++ if (!has_ansi_seq && ascii_is_valid_n(s, old_length)) + return ascii_ellipsize_mem(s, old_length, new_length, percent); + +- x = ((new_length - 1) * percent) / 100; ++ x = (new_length - 1) * percent / 100; + assert(x <= new_length - 1); + + k = 0; +- for (i = s; i < s + old_length; i = utf8_next_char(i)) { +- char32_t c; +- int w; ++ for (i = s; i < s + old_length; ) { ++ size_t slen = has_ansi_seq ? ansi_sequence_length(i, old_length - (i - s)) : 0; ++ if (slen > 0) { ++ i += slen; ++ continue; /* ANSI sequences don't take up any space in output */ ++ } + ++ char32_t c; + r = utf8_encoded_to_unichar(i, &c); + if (r < 0) + return NULL; + +- w = unichar_iswide(c) ? 2 : 1; +- if (k + w <= x) +- k += w; +- else ++ int w = unichar_iswide(c) ? 2 : 1; ++ if (k + w > x) + break; ++ ++ k += w; ++ i += r; + } + +- for (j = s + old_length; j > i; ) { ++ const char *ansi_start = s + old_length; ++ size_t ansi_len = 0; ++ ++ for (const char *t = j = s + old_length; t > i && k < new_length; ) { + char32_t c; + int w; +- const char *jj; ++ const char *tt; ++ ++ if (has_ansi_seq && ansi_start >= t) ++ /* Figure out the previous ANSI sequence, if any */ ++ ansi_len = previous_ansi_sequence(s, t - s, &ansi_start); + +- jj = utf8_prev_char(j); +- r = utf8_encoded_to_unichar(jj, &c); ++ /* If the sequence extends all the way to the current position, skip it. */ ++ if (has_ansi_seq && ansi_len > 0 && ansi_start + ansi_len == t) { ++ t = ansi_start; ++ continue; ++ } ++ ++ tt = utf8_prev_char(t); ++ r = utf8_encoded_to_unichar(tt, &c); + if (r < 0) + return NULL; + + w = unichar_iswide(c) ? 2 : 1; +- if (k + w <= new_length) { +- k += w; +- j = jj; +- } else ++ if (k + w > new_length) + break; ++ ++ k += w; ++ j = t = tt; /* j should always point to the first "real" character */ + } +- assert(i <= j); + +- /* we don't actually need to ellipsize */ +- if (i == j) ++ /* We don't actually need to ellipsize */ ++ if (i >= j) + return memdup_suffix0(s, old_length); + +- /* make space for ellipsis, if possible */ +- if (j < s + old_length) +- j = utf8_next_char(j); +- else if (i > s) +- i = utf8_prev_char(i); ++ if (k >= new_length) { ++ /* Make space for ellipsis, if required and possible. We know that the edge character is not ++ * part of an ANSI sequence (because then we'd skip it). If the last character we looked at ++ * was wide, we don't need to make space. */ ++ if (j < s + old_length) ++ j = utf8_next_char(j); ++ else if (i > s) ++ i = utf8_prev_char(i); ++ } + + len = i - s; + len2 = s + old_length - j; +- e = new(char, len + 3 + len2 + 1); ++ ++ /* If we have ANSI, allow the same length as the source string + ellipsis. It'd be too involved to ++ * figure out what exact space is needed. Strings with ANSI sequences are most likely to be fairly ++ * short anyway. */ ++ size_t alloc_len = has_ansi_seq ? old_length + 3 + 1 : len + 3 + len2 + 1; ++ ++ char *e = new(char, alloc_len); + if (!e) + return NULL; + + /* +- printf("old_length=%zu new_length=%zu x=%zu len=%u len2=%u k=%u\n", ++ printf("old_length=%zu new_length=%zu x=%zu len=%zu len2=%zu k=%zu\n", + old_length, new_length, x, len, len2, k); + */ + +- memcpy(e, s, len); ++ memcpy_safe(e, s, len); + write_ellipsis(e + len, true); +- memcpy(e + len + 3, j, len2); +- *(e + len + 3 + len2) = '\0'; ++ ++ char *dst = e + len + 3; ++ ++ if (has_ansi_seq) ++ /* Copy over any ANSI sequences in full */ ++ for (const char *p = s + len; p < j; ) { ++ size_t slen = ansi_sequence_length(p, j - p); ++ if (slen > 0) { ++ memcpy(dst, p, slen); ++ dst += slen; ++ p += slen; ++ } else ++ p = utf8_next_char(p); ++ } ++ ++ memcpy_safe(dst, j, len2); ++ dst[len2] = '\0'; + + return e; + } +diff --git a/src/test/test-ellipsize.c b/src/test/test-ellipsize.c +index 7317193363..8f7e17bfe9 100644 +--- a/src/test/test-ellipsize.c ++++ b/src/test/test-ellipsize.c +@@ -4,6 +4,7 @@ + + #include "alloc-util.h" + #include "def.h" ++#include "escape.h" + #include "string-util.h" + #include "strv.h" + #include "terminal-util.h" +@@ -116,4 +117,44 @@ TEST(ellipsize) { + test_ellipsize_one("shórt"); + } + ++TEST(ellipsize_ansi) { ++ const char *s = ANSI_HIGHLIGHT_YELLOW_UNDERLINE "yęllow" ++ ANSI_HIGHLIGHT_GREY_UNDERLINE "grěy" ++ ANSI_HIGHLIGHT_BLUE_UNDERLINE "blue" ++ ANSI_NORMAL "nórmął"; ++ size_t len = strlen(s); ++ ++ for (unsigned percent = 0; percent <= 100; percent += 15) ++ for (ssize_t x = 21; x >= 0; x--) { ++ _cleanup_free_ char *t = ellipsize_mem(s, len, x, percent); ++ printf("%02zd: \"%s\"\n", x, t); ++ assert_se(utf8_is_valid(t)); ++ ++ if (DEBUG_LOGGING) { ++ _cleanup_free_ char *e = cescape(t); ++ printf(" : \"%s\"\n", e); ++ } ++ } ++} ++ ++TEST(ellipsize_ansi_cats) { ++ _cleanup_free_ char *e, *f, *g, *h; ++ ++ /* Make sure we don't cut off in the middle of an ANSI escape sequence. */ ++ ++ e = ellipsize("01" ANSI_NORMAL "23", 4, 0); ++ puts(e); ++ assert_se(streq(e, "01" ANSI_NORMAL "23")); ++ f = ellipsize("ab" ANSI_NORMAL "cd", 4, 90); ++ puts(f); ++ assert_se(streq(f, "ab" ANSI_NORMAL "cd")); ++ ++ g = ellipsize("🐱🐱" ANSI_NORMAL "🐱🐱" ANSI_NORMAL, 5, 0); ++ puts(g); ++ assert_se(streq(g, "…" ANSI_NORMAL "🐱🐱" ANSI_NORMAL)); ++ h = ellipsize("🐱🐱" ANSI_NORMAL "🐱🐱" ANSI_NORMAL, 5, 90); ++ puts(h); ++ assert_se(streq(h, "🐱…" ANSI_NORMAL "🐱" ANSI_NORMAL)); ++} ++ + DEFINE_TEST_MAIN(LOG_INFO); diff --git a/0747-cryptsetup-do-not-assert-when-unsealing-token-withou.patch b/0747-cryptsetup-do-not-assert-when-unsealing-token-withou.patch new file mode 100644 index 0000000..f9f0346 --- /dev/null +++ b/0747-cryptsetup-do-not-assert-when-unsealing-token-withou.patch @@ -0,0 +1,75 @@ +From eac6ff660b32656d2a39bdc13d729e7eb0288596 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Wed, 15 Feb 2023 00:44:01 +0000 +Subject: [PATCH] cryptsetup: do not assert when unsealing token without salt + +Salt was added in v253. We are not checking whether it was actually found +(non-zero size), so when an old tpm+pin enrollment is opened things go boom. +For good measure, check both the buffer and the size in both places. + +Assertion 'saltlen > 0' failed at src/shared/tpm2-util.c:2490, function tpm2_util_pbkdf2_hmac_sha256(). Aborting. + +(cherry picked from commit 504d0acf61c8472bc93c2a927e858074873b2eaf) + +Resolves: RHEL-38864 +--- + src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c | 3 ++- + src/cryptsetup/cryptsetup-tpm2.c | 4 +++- + src/shared/tpm2-util.c | 1 + + 3 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c +index 630a2d8d3e..e353e947aa 100644 +--- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c ++++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c +@@ -40,6 +40,7 @@ int acquire_luks2_key( + _cleanup_(erase_and_freep) char *b64_salted_pin = NULL; + int r; + ++ assert(salt || salt_size == 0); + assert(ret_decrypted_key); + assert(ret_decrypted_key_size); + +@@ -60,7 +61,7 @@ int acquire_luks2_key( + if ((flags & TPM2_FLAGS_USE_PIN) && salt && !pin) + return -ENOANO; + +- if (pin) { ++ if (pin && salt_size > 0) { + uint8_t salted_pin[SHA256_DIGEST_SIZE] = {}; + CLEANUP_ERASE(salted_pin); + r = tpm2_util_pbkdf2_hmac_sha256(pin, strlen(pin), salt, salt_size, salted_pin); +diff --git a/src/cryptsetup/cryptsetup-tpm2.c b/src/cryptsetup/cryptsetup-tpm2.c +index c049b8a313..036f3d3a00 100644 +--- a/src/cryptsetup/cryptsetup-tpm2.c ++++ b/src/cryptsetup/cryptsetup-tpm2.c +@@ -88,6 +88,8 @@ int acquire_tpm2_key( + const void *blob; + int r; + ++ assert(salt || salt_size == 0); ++ + if (!device) { + r = tpm2_find_device_auto(&auto_device); + if (r == -ENODEV) +@@ -165,7 +167,7 @@ int acquire_tpm2_key( + if (r < 0) + return r; + +- if (salt) { ++ if (salt_size > 0) { + uint8_t salted_pin[SHA256_DIGEST_SIZE] = {}; + CLEANUP_ERASE(salted_pin); + +diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c +index 4e382f691e..1d2d4ddda4 100644 +--- a/src/shared/tpm2-util.c ++++ b/src/shared/tpm2-util.c +@@ -6041,6 +6041,7 @@ int tpm2_util_pbkdf2_hmac_sha256(const void *pass, + */ + static const uint8_t block_cnt[] = { 0, 0, 0, 1 }; + ++ assert (salt); + assert (saltlen > 0); + assert (saltlen <= (SIZE_MAX - sizeof(block_cnt))); + assert (passlen > 0); diff --git a/0748-cryptsetup-check-the-existence-of-salt-by-salt_size-.patch b/0748-cryptsetup-check-the-existence-of-salt-by-salt_size-.patch new file mode 100644 index 0000000..ffc3c3f --- /dev/null +++ b/0748-cryptsetup-check-the-existence-of-salt-by-salt_size-.patch @@ -0,0 +1,29 @@ +From 661e3758451dc504eeb176194293c87f238d55dd Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 17 Feb 2023 08:24:54 +0900 +Subject: [PATCH] cryptsetup: check the existence of salt by salt_size > 0 + +Follow-up for 504d0acf61c8472bc93c2a927e858074873b2eaf. + +The function may be called with non-NULL salt and salt_size == 0. + +(cherry picked from commit 8c2264abb9c16bc2933f95be299f15ee66c21181) + +Related: RHEL-38864 +--- + src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c +index e353e947aa..5230a84025 100644 +--- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c ++++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c +@@ -58,7 +58,7 @@ int acquire_luks2_key( + return -ENOANO; + + /* If we're using a PIN, and the luks header has a salt, it better have a pin too */ +- if ((flags & TPM2_FLAGS_USE_PIN) && salt && !pin) ++ if ((flags & TPM2_FLAGS_USE_PIN) && salt_size > 0 && !pin) + return -ENOANO; + + if (pin && salt_size > 0) { diff --git a/0749-core-mount-if-umount-8-fails-but-mount-disappeared-a.patch b/0749-core-mount-if-umount-8-fails-but-mount-disappeared-a.patch new file mode 100644 index 0000000..e2225b6 --- /dev/null +++ b/0749-core-mount-if-umount-8-fails-but-mount-disappeared-a.patch @@ -0,0 +1,83 @@ +From 3e65e8111f7cc30ac38901dced3ed0defbd90206 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Sat, 17 Feb 2024 03:03:50 +0800 +Subject: [PATCH] core/mount: if umount(8) fails but mount disappeared, assume + success + +Fixes #31337 + +(cherry picked from commit 8e94bb62a5c1309c56c57e0a505aae13a2ac5f4f) + +Resolves: RHEL-13159 +--- + src/core/mount.c | 20 ++++++++++++-------- + 1 file changed, 12 insertions(+), 8 deletions(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index a46ac804d8..cfe3f40302 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1439,7 +1439,8 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { + + if (IN_SET(m->state, MOUNT_REMOUNTING, MOUNT_REMOUNTING_SIGKILL, MOUNT_REMOUNTING_SIGTERM)) + mount_set_reload_result(m, f); +- else if (m->result == MOUNT_SUCCESS) ++ else if (m->result == MOUNT_SUCCESS && !IN_SET(m->state, MOUNT_MOUNTING, MOUNT_UNMOUNTING)) ++ /* MOUNT_MOUNTING and MOUNT_UNMOUNTING states need to be patched, see below. */ + m->result = f; + + if (m->control_command) { +@@ -1462,11 +1463,11 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { + switch (m->state) { + + case MOUNT_MOUNTING: +- /* Our mount point has not appeared in mountinfo. Something went wrong. */ ++ /* Our mount point has not appeared in mountinfo. Something went wrong. */ + + if (f == MOUNT_SUCCESS) { +- /* Either /bin/mount has an unexpected definition of success, +- * or someone raced us and we lost. */ ++ /* Either /bin/mount has an unexpected definition of success, or someone raced us ++ * and we lost. */ + log_unit_warning(UNIT(m), "Mount process finished, but there is no mount."); + f = MOUNT_FAILURE_PROTOCOL; + } +@@ -1484,9 +1485,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { + break; + + case MOUNT_UNMOUNTING: +- + if (f == MOUNT_SUCCESS && m->from_proc_self_mountinfo) { +- + /* Still a mount point? If so, let's try again. Most likely there were multiple mount points + * stacked on top of each other. We might exceed the timeout specified by the user overall, + * but we will stop as soon as any one umount times out. */ +@@ -1499,13 +1498,18 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { + log_unit_warning(u, "Mount still present after %u attempts to unmount, giving up.", m->n_retry_umount); + mount_enter_mounted(m, f); + } ++ } else if (f == MOUNT_FAILURE_EXIT_CODE && !m->from_proc_self_mountinfo) { ++ /* Hmm, umount process spawned by us failed, but the mount disappeared anyway? ++ * Maybe someone else is trying to unmount at the same time. */ ++ log_unit_notice(u, "Mount disappeared even though umount process failed, continuing."); ++ mount_enter_dead(m, MOUNT_SUCCESS); + } else + mount_enter_dead_or_mounted(m, f); + + break; + +- case MOUNT_UNMOUNTING_SIGKILL: + case MOUNT_UNMOUNTING_SIGTERM: ++ case MOUNT_UNMOUNTING_SIGKILL: + mount_enter_dead_or_mounted(m, f); + break; + +@@ -2040,7 +2044,7 @@ static int mount_process_proc_self_mountinfo(Manager *m) { + * then remove it because of an internal error. E.g., fuse.sshfs seems + * to do that when the connection fails. See #17617. To handle such the + * case, let's once set the state back to mounting. Then, the unit can +- * correctly enter the failed state later in mount_sigchld(). */ ++ * correctly enter the failed state later in mount_sigchld_event(). */ + mount_set_state(mount, MOUNT_MOUNTING); + break; + diff --git a/0750-Drop-log-level-of-header-limits-log-message.patch b/0750-Drop-log-level-of-header-limits-log-message.patch new file mode 100644 index 0000000..97afae0 --- /dev/null +++ b/0750-Drop-log-level-of-header-limits-log-message.patch @@ -0,0 +1,31 @@ +From 82231e1834a5936216c666e3488bccb8b82de258 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Mon, 24 Apr 2023 20:55:15 +0200 +Subject: [PATCH] Drop log level of header limits log message + +Especially when using in-memory logging, these are too noisy so +let's drop them back to debug level. + +(cherry picked from commit afc47ee2af456d12670df862457dcc7f6b864d79) + +Related: RHEL-33890 +--- + src/journal/journald-server.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index cbcf1e9d9e..56f2ea8583 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -848,8 +848,9 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n + if (!f) + return; + +- if (journal_file_rotate_suggested(f->file, s->max_file_usec, LOG_INFO)) { +- log_info("%s: Journal header limits reached or header out-of-date, rotating.", f->file->path); ++ if (journal_file_rotate_suggested(f->file, s->max_file_usec, LOG_DEBUG)) { ++ log_debug("%s: Journal header limits reached or header out-of-date, rotating.", ++ f->file->path); + rotate = true; + } + } diff --git a/0751-journal-do-not-rotate-unrelated-journal-files-when-f.patch b/0751-journal-do-not-rotate-unrelated-journal-files-when-f.patch new file mode 100644 index 0000000..ec07ee3 --- /dev/null +++ b/0751-journal-do-not-rotate-unrelated-journal-files-when-f.patch @@ -0,0 +1,136 @@ +From 6e5dce6e2f9cc43375eb481c2d533606d2a07e1b Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 22 Apr 2024 17:25:31 +0900 +Subject: [PATCH] journal: do not rotate unrelated journal files when full or + corrupted + +When we fail to add an entry to a journal file, typically when the file +is full or corrupted, it is not necessary to rotate other journal files. + +Not only that's unnecessary, rotating all journal files allows +unprivileged users to wipe system or other user's journals by writing +many journal entries to their own user journal file. + +Let's rotate all journal files only when +- it is really requested by a privileged user (e.g. by journalctl --rotate), or +- the system time jumps backwards. +And, otherwise rotate only the journal file we are currently writing. + +(cherry picked from commit bd0ec61ae3bb7a5200b344bab46ba2d6b9406aac) + +Resolves: RHEL-33890 +--- + src/journal/journald-server.c | 67 +++++++++++++++++++++++++---------- + 1 file changed, 48 insertions(+), 19 deletions(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 56f2ea8583..0ff6a43e5b 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -667,6 +667,33 @@ void server_rotate(Server *s) { + server_process_deferred_closes(s); + } + ++static void server_rotate_journal(Server *s, ManagedJournalFile *f, uid_t uid) { ++ int r; ++ ++ assert(s); ++ assert(f); ++ ++ /* This is similar to server_rotate(), but rotates only specified journal file. ++ * ++ * 💣💣💣 This invalidate 'f', and the caller cannot reuse the passed JournalFile object. 💣💣💣 */ ++ ++ if (f == s->system_journal) ++ (void) do_rotate(s, &s->system_journal, "system", s->seal, /* uid= */ 0); ++ else if (f == s->runtime_journal) ++ (void) do_rotate(s, &s->runtime_journal, "runtime", /* seal= */ false, /* uid= */ 0); ++ else { ++ assert(ordered_hashmap_get(s->user_journals, UID_TO_PTR(uid)) == f); ++ r = do_rotate(s, &f, "user", s->seal, uid); ++ if (r >= 0) ++ ordered_hashmap_replace(s->user_journals, UID_TO_PTR(uid), f); ++ else if (!f) ++ /* Old file has been closed and deallocated */ ++ ordered_hashmap_remove(s->user_journals, UID_TO_PTR(uid)); ++ } ++ ++ server_process_deferred_closes(s); ++} ++ + void server_sync(Server *s) { + ManagedJournalFile *f; + int r; +@@ -819,7 +846,7 @@ static bool shall_try_append_again(JournalFile *f, int r) { + } + + static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n, int priority) { +- bool vacuumed = false, rotate = false; ++ bool vacuumed = false; + struct dual_timestamp ts; + ManagedJournalFile *f; + int r; +@@ -841,23 +868,25 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n + * bisection works correctly. */ + + log_info("Time jumped backwards, rotating."); +- rotate = true; +- } else { ++ server_rotate(s); ++ server_vacuum(s, /* verbose = */ false); ++ vacuumed = true; ++ } + +- f = find_journal(s, uid); +- if (!f) +- return; ++ f = find_journal(s, uid); ++ if (!f) ++ return; + +- if (journal_file_rotate_suggested(f->file, s->max_file_usec, LOG_DEBUG)) { +- log_debug("%s: Journal header limits reached or header out-of-date, rotating.", +- f->file->path); +- rotate = true; ++ if (journal_file_rotate_suggested(f->file, s->max_file_usec, LOG_DEBUG)) { ++ if (vacuumed) { ++ log_warning("Suppressing rotation, as we already rotated immediately before write attempt. Giving up."); ++ return; + } +- } + +- if (rotate) { +- server_rotate(s); +- server_vacuum(s, false); ++ log_debug("%s: Journal header limits reached or header out-of-date, rotating.", f->file->path); ++ ++ server_rotate_journal(s, TAKE_PTR(f), uid); ++ server_vacuum(s, /* verbose = */ false); + vacuumed = true; + + f = find_journal(s, uid); +@@ -883,8 +912,8 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, size_t n + else + log_ratelimit_full_errno(LOG_INFO, r, "Failed to write entry to %s (%zu items, %zu bytes), rotating before retrying: %m", f->file->path, n, IOVEC_TOTAL_SIZE(iovec, n)); + +- server_rotate(s); +- server_vacuum(s, false); ++ server_rotate_journal(s, TAKE_PTR(f), uid); ++ server_vacuum(s, /* verbose = */ false); + + f = find_journal(s, uid); + if (!f) +@@ -1211,10 +1240,10 @@ int server_flush_to_var(Server *s, bool require_flag_file) { + + log_info("Rotating system journal."); + +- server_rotate(s); +- server_vacuum(s, false); ++ server_rotate_journal(s, s->system_journal, /* uid = */ 0); ++ server_vacuum(s, /* verbose = */ false); + +- if (!s->system_journal) { ++ if (!s->system_journal->file) { + log_notice("Didn't flush runtime journal since rotation of system journal wasn't successful."); + r = -EIO; + goto finish; diff --git a/0752-man-suffix-unit-with-an-equal-sign-since-it-expects-.patch b/0752-man-suffix-unit-with-an-equal-sign-since-it-expects-.patch new file mode 100644 index 0000000..6adcd7c --- /dev/null +++ b/0752-man-suffix-unit-with-an-equal-sign-since-it-expects-.patch @@ -0,0 +1,41 @@ +From fd3e9815846aa1efe295e897faf1e57f38c6c165 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 7 Jun 2023 14:54:34 +0200 +Subject: [PATCH] man: suffix --unit with an equal sign, since it expects an + argument + +As per our usual syntax in the docs. + +(cherry picked from commit e754af353c494edfdd25412fae32876a2772a5cd) + +Related: RHEL-31070 +--- + man/journalctl.xml | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/man/journalctl.xml b/man/journalctl.xml +index 5bf895fce4..29d06aaef8 100644 +--- a/man/journalctl.xml ++++ b/man/journalctl.xml +@@ -110,8 +110,8 @@ + ). If neither is specified, show all messages that the user can see. + + +- The option affects how arguments are +- treated. See . ++ The option affects how arguments are ++ treated. See . + + + +@@ -285,8 +285,8 @@ + systemd.slice5 + unit, all logs of children of the slice will be shown. + +- With , all arguments will be converted to match +- user messages as if specified with . ++ With , all arguments will be converted to match ++ user messages as if specified with . + + This parameter can be specified multiple times. + diff --git a/0753-shared-move-uid-alloc-range.-ch-from-src-shared-src-.patch b/0753-shared-move-uid-alloc-range.-ch-from-src-shared-src-.patch new file mode 100644 index 0000000..9dea891 --- /dev/null +++ b/0753-shared-move-uid-alloc-range.-ch-from-src-shared-src-.patch @@ -0,0 +1,57 @@ +From f69edd2042ebf1db72ad1a2c6cbfd8887231da25 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 7 Jun 2023 15:15:42 +0200 +Subject: [PATCH] =?UTF-8?q?shared:=20move=20uid-alloc-range.[ch]=20from=20?= + =?UTF-8?q?src/shared/=20=E2=86=92=20src/basic/?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This way we can use it in libsystemd + +(cherry picked from commit 8a8b4a8784f48e941b6b460b4cb963929d1d6a8d) + +Related: RHEL-31070 +--- + src/basic/meson.build | 2 ++ + src/{shared => basic}/uid-alloc-range.c | 0 + src/{shared => basic}/uid-alloc-range.h | 0 + src/shared/meson.build | 2 -- + 4 files changed, 2 insertions(+), 2 deletions(-) + rename src/{shared => basic}/uid-alloc-range.c (100%) + rename src/{shared => basic}/uid-alloc-range.h (100%) + +diff --git a/src/basic/meson.build b/src/basic/meson.build +index bfe52d5879..c0f0b07418 100644 +--- a/src/basic/meson.build ++++ b/src/basic/meson.build +@@ -240,6 +240,8 @@ basic_sources = files( + 'time-util.h', + 'tmpfile-util.c', + 'tmpfile-util.h', ++ 'uid-alloc-range.c', ++ 'uid-alloc-range.h', + 'uid-range.c', + 'uid-range.h', + 'umask-util.h', +diff --git a/src/shared/uid-alloc-range.c b/src/basic/uid-alloc-range.c +similarity index 100% +rename from src/shared/uid-alloc-range.c +rename to src/basic/uid-alloc-range.c +diff --git a/src/shared/uid-alloc-range.h b/src/basic/uid-alloc-range.h +similarity index 100% +rename from src/shared/uid-alloc-range.h +rename to src/basic/uid-alloc-range.h +diff --git a/src/shared/meson.build b/src/shared/meson.build +index 9e11e13934..766e4f9506 100644 +--- a/src/shared/meson.build ++++ b/src/shared/meson.build +@@ -311,8 +311,6 @@ shared_sources = files( + 'tpm2-util.h', + 'udev-util.c', + 'udev-util.h', +- 'uid-alloc-range.c', +- 'uid-alloc-range.h', + 'user-record-nss.c', + 'user-record-nss.h', + 'user-record-show.c', diff --git a/0754-journald-move-uid_for_system_journal-to-uid-alloc-ra.patch b/0754-journald-move-uid_for_system_journal-to-uid-alloc-ra.patch new file mode 100644 index 0000000..924a150 --- /dev/null +++ b/0754-journald-move-uid_for_system_journal-to-uid-alloc-ra.patch @@ -0,0 +1,66 @@ +From c499486907937a823a8a3fe003b4d8bcf232fec6 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 7 Jun 2023 15:16:50 +0200 +Subject: [PATCH] journald: move uid_for_system_journal() to uid-alloc-range.h + +Let's move this helper call from journald specific code to src/basic/, +so that we can use it from sd-journal. + +While we are at it, slightly extend it to also cover container uids, +which are also routed to the system journal now. + +This places the call in uid-alloc-range.[ch] which contains similar +functions that match UID ranges for specific purposes. + +(cherry picked from commit 115d5145a257c1a27330acf9f063b5f4d910ca4d) + +Related: RHEL-31070 +--- + src/basic/uid-alloc-range.c | 7 +++++++ + src/basic/uid-alloc-range.h | 2 ++ + src/journal/journald-server.c | 7 ------- + 3 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/src/basic/uid-alloc-range.c b/src/basic/uid-alloc-range.c +index dcecdbe343..1b6d761a66 100644 +--- a/src/basic/uid-alloc-range.c ++++ b/src/basic/uid-alloc-range.c +@@ -121,3 +121,10 @@ bool gid_is_system(gid_t gid) { + + return gid <= defs->system_gid_max; + } ++ ++bool uid_for_system_journal(uid_t uid) { ++ ++ /* Returns true if the specified UID shall get its data stored in the system journal. */ ++ ++ return uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY || uid_is_container(uid); ++} +diff --git a/src/basic/uid-alloc-range.h b/src/basic/uid-alloc-range.h +index d3bf077045..5badde148a 100644 +--- a/src/basic/uid-alloc-range.h ++++ b/src/basic/uid-alloc-range.h +@@ -32,3 +32,5 @@ typedef struct UGIDAllocationRange { + + int read_login_defs(UGIDAllocationRange *ret_defs, const char *path, const char *root); + const UGIDAllocationRange *acquire_ugid_allocation_range(void); ++ ++bool uid_for_system_journal(uid_t uid); +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 0ff6a43e5b..6fa182a566 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -234,13 +234,6 @@ void server_space_usage_message(Server *s, JournalStorage *storage) { + NULL); + } + +-static bool uid_for_system_journal(uid_t uid) { +- +- /* Returns true if the specified UID shall get its data stored in the system journal. */ +- +- return uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY; +-} +- + static void server_add_acls(ManagedJournalFile *f, uid_t uid) { + assert(f); + diff --git a/0755-sd-journal-when-SD_JOURNAL_CURRENT_USER-is-set-and-c.patch b/0755-sd-journal-when-SD_JOURNAL_CURRENT_USER-is-set-and-c.patch new file mode 100644 index 0000000..a2d65e4 --- /dev/null +++ b/0755-sd-journal-when-SD_JOURNAL_CURRENT_USER-is-set-and-c.patch @@ -0,0 +1,65 @@ +From 8dfa6d7536994c1a75b5d8a2af009efa9135b395 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 7 Jun 2023 15:19:25 +0200 +Subject: [PATCH] sd-journal: when SD_JOURNAL_CURRENT_USER is set, and called + from system UID, imply SD_JOURNAL_SYSTEM + +Fixes: #26742 #23679 +(cherry picked from commit 97c621b72d8c5b5eb4bf7f177cd885bfc01518c9) + +Resolves: RHEL-31070 +--- + src/libsystemd/sd-journal/sd-journal.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c +index 9ab31fbbc8..723beec0e8 100644 +--- a/src/libsystemd/sd-journal/sd-journal.c ++++ b/src/libsystemd/sd-journal/sd-journal.c +@@ -41,6 +41,7 @@ + #include "string-util.h" + #include "strv.h" + #include "syslog-util.h" ++#include "uid-alloc-range.h" + + #define JOURNAL_FILES_MAX 7168 + +@@ -1217,25 +1218,32 @@ static bool file_has_type_prefix(const char *prefix, const char *filename) { + static bool file_type_wanted(int flags, const char *filename) { + assert(filename); + +- if (!endswith(filename, ".journal") && !endswith(filename, ".journal~")) ++ if (!ENDSWITH_SET(filename, ".journal", ".journal~")) + return false; + + /* no flags set → every type is OK */ + if (!(flags & (SD_JOURNAL_SYSTEM | SD_JOURNAL_CURRENT_USER))) + return true; + +- if (flags & SD_JOURNAL_SYSTEM && file_has_type_prefix("system", filename)) +- return true; +- +- if (flags & SD_JOURNAL_CURRENT_USER) { ++ if (FLAGS_SET(flags, SD_JOURNAL_CURRENT_USER)) { + char prefix[5 + DECIMAL_STR_MAX(uid_t) + 1]; + +- xsprintf(prefix, "user-"UID_FMT, getuid()); ++ xsprintf(prefix, "user-" UID_FMT, getuid()); + + if (file_has_type_prefix(prefix, filename)) + return true; ++ ++ /* If SD_JOURNAL_CURRENT_USER is specified and we are invoked under a system UID, then ++ * automatically enable SD_JOURNAL_SYSTEM too, because journald will actually put system user ++ * data into the system journal. */ ++ ++ if (uid_for_system_journal(getuid())) ++ flags |= SD_JOURNAL_SYSTEM; + } + ++ if (FLAGS_SET(flags, SD_JOURNAL_SYSTEM) && file_has_type_prefix("system", filename)) ++ return true; ++ + return false; + } + diff --git a/0756-man-document-that-journalctl-user-requires-Storage-p.patch b/0756-man-document-that-journalctl-user-requires-Storage-p.patch new file mode 100644 index 0000000..7b046ed --- /dev/null +++ b/0756-man-document-that-journalctl-user-requires-Storage-p.patch @@ -0,0 +1,46 @@ +From 6cee9dd4b39082ec7d5afcb1f4c0b91832e294d9 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 7 Jun 2023 16:23:45 +0200 +Subject: [PATCH] man: document that journalctl --user requires + Storage=persistent + +Fixes: #25061 +(cherry picked from commit cad8fa471b9133f38fbd6ddb6ee143f361525e5d) + +Related: RHEL-31070 +--- + man/journalctl.xml | 6 +++++- + man/journald.conf.xml | 3 +++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/man/journalctl.xml b/man/journalctl.xml +index 29d06aaef8..6be628caf8 100644 +--- a/man/journalctl.xml ++++ b/man/journalctl.xml +@@ -111,7 +111,11 @@ + + + The option affects how arguments are +- treated. See . ++ treated. See . ++ ++ Note that only works if persistent logging is enabled, via the ++ Storage= setting in ++ journald.conf5. + + + +diff --git a/man/journald.conf.xml b/man/journald.conf.xml +index 24cee4c8b2..a7c3da6653 100644 +--- a/man/journald.conf.xml ++++ b/man/journald.conf.xml +@@ -95,6 +95,9 @@ + /var/log/journal/, as the systemd-journald@.service service + file by default carries LogsDirectory=. To turn that off, add a unit file drop-in + file that sets LogsDirectory= to an empty string. ++ ++ Note that per-user journal files are not supported unless persistent storage is enabled, thus ++ making journalctl --user unavailable. + + + diff --git a/0757-fix-prefix-of-dmesg-pstore-files.patch b/0757-fix-prefix-of-dmesg-pstore-files.patch new file mode 100644 index 0000000..67c76d7 --- /dev/null +++ b/0757-fix-prefix-of-dmesg-pstore-files.patch @@ -0,0 +1,35 @@ +From ee2dd3cada129b39a2da5287f31e6d9e18a82764 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=94=D0=B0=D0=BC=D1=98=D0=B0=D0=BD=20=D0=93=D0=B5=D0=BE?= + =?UTF-8?q?=D1=80=D0=B3=D0=B8=D0=B5=D0=B2=D1=81=D0=BA=D0=B8?= + +Date: Fri, 1 Dec 2023 11:46:36 +0100 +Subject: [PATCH] fix: prefix of dmesg pstore files + +A change in the kernel[1] renamed the prefix of the pstore files from +`dmesg-efi-` to `dmesg-efi_pstore-`. + +[1] +https://git.kernel.org/linus/893c5f1de620 + +(cherry picked from commit ef87c84e812cbdca4ef160fb0536d1f1bc6a2400) + +Resolves: RHEL-20322 +--- + src/pstore/pstore.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c +index 7fff6cee62..76657da536 100644 +--- a/src/pstore/pstore.c ++++ b/src/pstore/pstore.c +@@ -233,7 +233,9 @@ static int process_dmesg_files(PStoreList *list) { + if (!startswith(pe->dirent.d_name, "dmesg-")) + continue; + +- if ((p = startswith(pe->dirent.d_name, "dmesg-efi-"))) { ++ /* The linux kernel changed the prefix from dmesg-efi- to dmesg-efi_pstore- ++ * so now we have to handle both cases. */ ++ if ((p = STARTSWITH_SET(pe->dirent.d_name, "dmesg-efi-", "dmesg-efi_pstore-"))) { + /* For the EFI backend, the 3 least significant digits of record id encodes a + * "count" number, the next 2 least significant digits for the dmesg part + * (chunk) number, and the remaining digits as the timestamp. See diff --git a/0758-backport-new-mkosi.patch b/0758-backport-new-mkosi.patch new file mode 100644 index 0000000..a644615 --- /dev/null +++ b/0758-backport-new-mkosi.patch @@ -0,0 +1,2617 @@ +From ff59ed4492b545e375a03e32877ef6142c2efe67 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Mon, 26 Feb 2024 15:34:30 +0100 +Subject: [PATCH] backport new mkosi + +RHEL-only + +Resolves: RHEL-27512 +--- + mkosi.build | 314 ------------------ + mkosi.conf | 39 +++ + mkosi.conf.d/05-qemu-mem.conf | 11 + + mkosi.conf.d/10-centos.conf | 10 + + mkosi.conf.d/10-debian.conf | 7 + + mkosi.conf.d/10-extra-search-paths.conf | 7 + + mkosi.conf.d/10-fedora.conf | 7 + + mkosi.conf.d/10-opensuse.conf | 7 + + mkosi.conf.d/10-tools.conf | 8 + + mkosi.conf.d/10-ubuntu.conf | 8 + + mkosi.default.d/10-systemd.conf | 73 ---- + mkosi.default.d/arch/10-mkosi.arch | 37 --- + mkosi.default.d/fedora/10-mkosi.fedora | 72 ---- + mkosi.default.d/ubuntu/10-mkosi.ubuntu | 70 ---- + mkosi.images/base/mkosi.build.chroot | 183 ++++++++++ + mkosi.images/base/mkosi.conf | 36 ++ + mkosi.images/base/mkosi.conf.d/10-arch.conf | 33 ++ + .../base/mkosi.conf.d/10-centos-fedora.conf | 53 ++- + .../base/mkosi.conf.d/10-debian-ubuntu.conf | 46 +-- + mkosi.images/base/mkosi.conf.d/10-debian.conf | 11 + + mkosi.images/base/mkosi.conf.d/10-fedora.conf | 9 + + .../base/mkosi.conf.d/10-opensuse.conf | 52 +-- + mkosi.images/base/mkosi.conf.d/10-ubuntu.conf | 12 + + .../lib/systemd/system-preset/00-mkosi.preset | 30 ++ + .../lib/systemd/system-preset/99-mkosi.preset | 4 + + .../usr/lib/tmpfiles.d/locale.conf | 1 + + mkosi.images/initrd/mkosi.conf | 30 ++ + .../initrd/mkosi.conf.d/10-centos.conf | 12 + + .../initrd/mkosi.conf.d/10-default.conf | 12 + + .../initrd/mkosi.conf.d/10-opensuse.conf | 11 + + mkosi.images/initrd/mkosi.postinst | 7 + + mkosi.images/system/mkosi.conf | 52 +++ + .../system/mkosi.conf.d/05-initrd.conf | 12 + + mkosi.images/system/mkosi.conf.d/10-arch.conf | 27 ++ + .../system/mkosi.conf.d/10-centos-fedora.conf | 33 ++ + .../system/mkosi.conf.d/10-centos/mkosi.conf | 8 + + .../usr/lib/repart.d/20-root.conf.d/xfs.conf | 5 + + .../mkosi.repart/10-usr.conf.d/squashfs.conf | 5 + + .../system/mkosi.conf.d/10-debian-amd64.conf | 10 + + .../system/mkosi.conf.d/10-debian-arm64.conf | 10 + + .../system/mkosi.conf.d/10-debian-ubuntu.conf | 30 ++ + .../system/mkosi.conf.d/10-fedora.conf | 11 + + .../system/mkosi.conf.d/10-opensuse.conf | 24 ++ + .../system/mkosi.conf.d/10-ubuntu.conf | 14 + + mkosi.images/system/mkosi.extra/etc/issue | 2 + + .../mkosi.extra/usr/lib/repart.d/15-swap.conf | 6 + + .../mkosi.extra/usr/lib/repart.d/20-root.conf | 8 + + .../journald.conf.d/50-persistent.conf | 8 + + .../lib/systemd/mkosi-check-and-shutdown.sh | 19 ++ + .../system/mkosi-check-and-shutdown.service | 15 + + .../usr/lib/tmpfiles.d/99-mkosi.conf | 3 + + .../share/factory/mkosi/gdbinit.d/systemd.gdb | 3 + + mkosi.images/system/mkosi.finalize | 4 + + mkosi.images/system/mkosi.postinst.chroot | 102 ++++++ + mkosi.images/system/mkosi.repart/00-esp.conf | 9 + + mkosi.images/system/mkosi.repart/10-usr.conf | 9 + + .../system/mkosi.repart/11-usr-verity.conf | 7 + + .../mkosi.repart/12-usr-verity-sig.conf | 6 + + mkosi.kernel.config | 286 ++++++++++++++++ + mkosi.postinst | 34 -- + 60 files changed, 1308 insertions(+), 666 deletions(-) + delete mode 100755 mkosi.build + create mode 100644 mkosi.conf + create mode 100644 mkosi.conf.d/05-qemu-mem.conf + create mode 100644 mkosi.conf.d/10-centos.conf + create mode 100644 mkosi.conf.d/10-debian.conf + create mode 100644 mkosi.conf.d/10-extra-search-paths.conf + create mode 100644 mkosi.conf.d/10-fedora.conf + create mode 100644 mkosi.conf.d/10-opensuse.conf + create mode 100644 mkosi.conf.d/10-tools.conf + create mode 100644 mkosi.conf.d/10-ubuntu.conf + delete mode 100644 mkosi.default.d/10-systemd.conf + delete mode 100644 mkosi.default.d/arch/10-mkosi.arch + delete mode 100644 mkosi.default.d/fedora/10-mkosi.fedora + delete mode 100644 mkosi.default.d/ubuntu/10-mkosi.ubuntu + create mode 100755 mkosi.images/base/mkosi.build.chroot + create mode 100644 mkosi.images/base/mkosi.conf + create mode 100644 mkosi.images/base/mkosi.conf.d/10-arch.conf + rename mkosi.default.d/centos_epel/10-mkosi.centos_epel => mkosi.images/base/mkosi.conf.d/10-centos-fedora.conf (67%) + rename mkosi.default.d/debian/10-mkosi.debian => mkosi.images/base/mkosi.conf.d/10-debian-ubuntu.conf (64%) + create mode 100644 mkosi.images/base/mkosi.conf.d/10-debian.conf + create mode 100644 mkosi.images/base/mkosi.conf.d/10-fedora.conf + rename mkosi.default.d/opensuse/10-mkosi.opensuse => mkosi.images/base/mkosi.conf.d/10-opensuse.conf (65%) + create mode 100644 mkosi.images/base/mkosi.conf.d/10-ubuntu.conf + create mode 100644 mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/00-mkosi.preset + create mode 100644 mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/99-mkosi.preset + create mode 100644 mkosi.images/base/mkosi.extra/usr/lib/tmpfiles.d/locale.conf + create mode 100644 mkosi.images/initrd/mkosi.conf + create mode 100644 mkosi.images/initrd/mkosi.conf.d/10-centos.conf + create mode 100644 mkosi.images/initrd/mkosi.conf.d/10-default.conf + create mode 100644 mkosi.images/initrd/mkosi.conf.d/10-opensuse.conf + create mode 100755 mkosi.images/initrd/mkosi.postinst + create mode 100644 mkosi.images/system/mkosi.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/05-initrd.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-arch.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-centos-fedora.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-centos/mkosi.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-centos/mkosi.extra/usr/lib/repart.d/20-root.conf.d/xfs.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-centos/mkosi.repart/10-usr.conf.d/squashfs.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-debian-amd64.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-debian-arm64.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-debian-ubuntu.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-fedora.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-opensuse.conf + create mode 100644 mkosi.images/system/mkosi.conf.d/10-ubuntu.conf + create mode 100644 mkosi.images/system/mkosi.extra/etc/issue + create mode 100644 mkosi.images/system/mkosi.extra/usr/lib/repart.d/15-swap.conf + create mode 100644 mkosi.images/system/mkosi.extra/usr/lib/repart.d/20-root.conf + create mode 100644 mkosi.images/system/mkosi.extra/usr/lib/systemd/journald.conf.d/50-persistent.conf + create mode 100755 mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh + create mode 100644 mkosi.images/system/mkosi.extra/usr/lib/systemd/system/mkosi-check-and-shutdown.service + create mode 100644 mkosi.images/system/mkosi.extra/usr/lib/tmpfiles.d/99-mkosi.conf + create mode 100644 mkosi.images/system/mkosi.extra/usr/share/factory/mkosi/gdbinit.d/systemd.gdb + create mode 100755 mkosi.images/system/mkosi.finalize + create mode 100755 mkosi.images/system/mkosi.postinst.chroot + create mode 100644 mkosi.images/system/mkosi.repart/00-esp.conf + create mode 100644 mkosi.images/system/mkosi.repart/10-usr.conf + create mode 100644 mkosi.images/system/mkosi.repart/11-usr-verity.conf + create mode 100644 mkosi.images/system/mkosi.repart/12-usr-verity-sig.conf + create mode 100644 mkosi.kernel.config + delete mode 100755 mkosi.postinst + +diff --git a/mkosi.build b/mkosi.build +deleted file mode 100755 +index f02a15ad4d..0000000000 +--- a/mkosi.build ++++ /dev/null +@@ -1,314 +0,0 @@ +-#!/bin/sh +-# SPDX-License-Identifier: LGPL-2.1-or-later +-set -e +- +-# This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi). +-# Simply invoke "mkosi" in the project directory to build an OS image. +- +-ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:disable_coredump=0:use_madv_dontdump=1 +-UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 +- +-# On Fedora "ld" is (unfortunately — if you ask me) managed via +-# "alternatives". Since we'd like to support building images in environments +-# with only /usr/ around (e.g. mkosi's UsrOnly=1 option), we have the problem +-# that /usr/bin/ld is a symlink that points to a non-existing file in +-# /etc/alternative/ in this mode. Let's work around this for now by manually +-# redirect "ld" to "ld.bfd", i.e. circumventing the /usr/bin/ld symlink. +-if [ ! -x /usr/bin/ld ] && [ -x /usr/bin/ld.bfd ]; then +- mkdir -p "$HOME"/bin +- ln -s /usr/bin/ld.bfd "$HOME"/bin/ld +- PATH="$HOME/bin:$PATH" +-fi +- +-# If mkosi.builddir/ exists mkosi will set $BUILDDIR to it, let's then use it +-# as out-of-tree build dir. Otherwise, let's make up our own builddir. +-[ -z "$BUILDDIR" ] && BUILDDIR=build +- +-# Meson uses Python 3 and requires a locale with an UTF-8 character map. +-# Not running under UTF-8 makes the `ninja test` step break with a CodecError. +-# So let's ensure we're running under UTF-8. +-# +-# If our current locale already is UTF-8, then we don't need to do anything: +-if [ "$(locale charmap 2>/dev/null)" != "UTF-8" ] ; then +- # Try using C.UTF-8 locale, if available. This locale is not shipped +- # by upstream glibc, so it's not available in all distros. +- # (In particular, it's not available in Arch Linux.) +- if locale -a | grep -q -E "C.UTF-8|C.utf8"; then +- export LC_CTYPE=C.UTF-8 +- # Finally, try something like en_US.UTF-8, which should be +- # available in Arch Linux, but is not present in Debian's +- # minimal image in our mkosi config. +- elif locale -a | grep -q en_US.utf8; then +- export LC_CTYPE=en_US.UTF-8 +- else +- # If nothing works, fail early. +- echo "*** Could not find a valid locale that supports UTF-8. ***" >&2 +- exit 1 +- fi +-fi +- +-# The bpftool script shipped by Ubuntu tries to find the actual program to run via querying `uname -r` and +-# using the current kernel version. This obviously doesn't work in containers. As a workaround, we override +-# the ubuntu script with a symlink to the first bpftool program we can find. +-for bpftool in /usr/lib/linux-tools/*/bpftool; do +- [ -x "$bpftool" ] || continue +- ln -sf "$bpftool" /usr/sbin/bpftool +- break +-done +- +-# CentOS Stream 8 includes bpftool 4.18.0 which is lower than what we need. However, they've backported the +-# specific feature we need ("gen skeleton") to this version, so we replace bpftool with a script that reports +-# version 5.6.0 to satisfy meson which makes bpf work on CentOS Stream 8 as well. +-if [ "$(grep '^ID=' /etc/os-release)" = "ID=\"centos\"" ] && [ "$(grep '^VERSION=' /etc/os-release)" = "VERSION=\"8\"" ]; then +- cp /usr/sbin/bpftool /usr/sbin/bpftool.real +- cat > /usr/sbin/bpftool </dev/null) +- if [ -z "$init_path" ] ; then +- rootprefix="" +- else +- rootprefix=${init_path%/lib/systemd/systemd} +- rootprefix=/${rootprefix#/} +- fi +- +- meson "$BUILDDIR" \ +- -D "sysvinit-path=$sysvinit_path" \ +- -D "rootprefix=$rootprefix" \ +- -D man=false \ +- -D translations=false \ +- -D version-tag="${VERSION_TAG}" \ +- -D mode=developer \ +- -D b_sanitize="${SANITIZERS:-none}" \ +- -D install-tests=true \ +- -D tests=unsafe \ +- -D slow-tests=true \ +- -D utmp=true \ +- -D hibernate=true \ +- -D ldconfig=true \ +- -D resolve=true \ +- -D efi=true \ +- -D tpm=true \ +- -D environment-d=true \ +- -D binfmt=true \ +- -D repart=true \ +- -D sysupdate=true \ +- -D coredump=true \ +- -D pstore=true \ +- -D oomd=true \ +- -D logind=true \ +- -D hostnamed=true \ +- -D localed=true \ +- -D machined=true \ +- -D portabled=true \ +- -D sysext=true \ +- -D userdb=true \ +- -D homed=true \ +- -D networkd=true \ +- -D timedated=true \ +- -D timesyncd=true \ +- -D remote=true \ +- -D nss-myhostname=true \ +- -D nss-mymachines=true \ +- -D nss-resolve=true \ +- -D nss-systemd=true \ +- -D firstboot=true \ +- -D randomseed=true \ +- -D backlight=true \ +- -D vconsole=true \ +- -D quotacheck=true \ +- -D sysusers=true \ +- -D tmpfiles=true \ +- -D importd=true \ +- -D hwdb=true \ +- -D rfkill=true \ +- -D xdg-autostart=true \ +- -D translations=true \ +- -D polkit=true \ +- -D acl=true \ +- -D audit=true \ +- -D blkid=true \ +- -D fdisk=true \ +- -D kmod=true \ +- -D pam=true \ +- -D pwquality=true \ +- -D microhttpd=true \ +- -D libcryptsetup=true \ +- -D libcurl=true \ +- -D idn=true \ +- -D libidn2=true \ +- -D qrencode=true \ +- -D gcrypt=true \ +- -D gnutls=true \ +- -D openssl=true \ +- -D cryptolib=openssl \ +- -D p11kit=true \ +- -D libfido2=true \ +- -D tpm2=true \ +- -D elfutils=true \ +- -D zstd=true \ +- -D xkbcommon=true \ +- -D pcre2=true \ +- -D glib=true \ +- -D dbus=true \ +- -D gnu-efi=true \ +- -D kernel-install=true \ +- -D analyze=true \ +- -D bpf-framework=true +-fi +- +-cd "$BUILDDIR" +-ninja "$@" +-if [ "$WITH_TESTS" = 1 ] ; then +- for id in 1 2 3; do +- getent group $id >/dev/null || echo "g testgroup$id $id -" | ./systemd-sysusers - +- done +- +- if [ -n "$SANITIZERS" ]; then +- export ASAN_OPTIONS="$ASAN_OPTIONS" +- export UBSAN_OPTIONS="$UBSAN_OPTIONS" +- TIMEOUT_MULTIPLIER=3 +- else +- TIMEOUT_MULTIPLIER=1 +- fi +- +- meson test --print-errorlogs --timeout-multiplier=$TIMEOUT_MULTIPLIER +-fi +-cd "$SRCDIR" +- +-# Ubuntu Focal is stuck with meson 0.53.0. +-if [ "$(meson -v | cut -d . -f 2)" -gt 53 ] ; then +- meson install -C "$BUILDDIR" --quiet --no-rebuild --only-changed +-else +- meson install -C "$BUILDDIR" --no-rebuild --only-changed +-fi +- +-mkdir -p "$DESTDIR"/etc +- +-cat >"$DESTDIR"/etc/issue <"${DESTDIR}/usr/lib/os-release" +- +- OSRELEASEFILE="$DESTDIR"/usr/lib/os-release +-else +- OSRELEASEFILE=/usr/lib/os-release +-fi +- +- +-if [ -n "$IMAGE_VERSION" ] ; then +- mkdir -p "$DESTDIR"/usr/lib +- sed -n \ +- -e '/^IMAGE_VERSION=/!p' \ +- -e "\$aIMAGE_VERSION=$IMAGE_VERSION" <$OSRELEASEFILE >"/tmp/os-release.tmp" +- +- cat /tmp/os-release.tmp > "$DESTDIR"/usr/lib/os-release +- rm /tmp/os-release.tmp +-fi +- +-# If $CI_BUILD is set, copy over the CI service which executes a service check +-# after boot and then shuts down the machine +-if [ -n "$CI_BUILD" ]; then +- mkdir -p "$DESTDIR/usr/lib/systemd/system" +- cp -v "$SRCDIR/test/mkosi-check-and-shutdown.service" "$DESTDIR/usr/lib/systemd/system/mkosi-check-and-shutdown.service" +- cp -v "$SRCDIR/test/mkosi-check-and-shutdown.sh" "$DESTDIR/usr/lib/systemd/mkosi-check-and-shutdown.sh" +- chmod +x "$DESTDIR/usr/lib/systemd/mkosi-check-and-shutdown.sh" +-fi +- +-if [ -n "$SANITIZERS" ]; then +- LD_PRELOAD=$(ldd $BUILDDIR/systemd | grep libasan.so | awk '{print $3}') +- +- mkdir -p "$DESTDIR/etc/systemd/system.conf.d" +- +- cat > "$DESTDIR/etc/systemd/system.conf.d/10-asan.conf" < "$DESTDIR/etc/systemd/system/systemd-journald.service.d/10-stdout-tty.conf" < "$DESTDIR/etc/systemd/system/console-getty.service.d/10-no-vhangup.conf" < "$DESTDIR/etc/systemd/system-preset/99-mkosi.preset" +- +-if [ -d mkosi.kernel/ ]; then +- cd "$SRCDIR/mkosi.kernel" +- mkdir -p "$BUILDDIR/mkosi.kernel" +- +- make O="$BUILDDIR/mkosi.kernel" defconfig +- +- scripts/config \ +- --file $BUILDDIR/mkosi.kernel/.config \ +- --enable BPF_SYSCALL \ +- --enable BPF_JIT \ +- --enable BPF_JIT_ALWAYS_ON \ +- --enable BPF_JIT_DEFAULT_ON \ +- --enable BPF_UNPRIV_DEFAULT_OFF \ +- --enable USERMODE_DRIVER \ +- --enable BPF_PRELOAD \ +- --enable BPF_PRELOAD_UMD \ +- --enable BPF_LSM \ +- --enable BTRFS_FS \ +- --enable BTRFS_FS_POSIX_ACL \ +- --enable PSI \ +- --enable CGROUPS \ +- --enable CGROUP_BPF \ +- --enable MEMCG \ +- --enable MEMCG_SWAP \ +- --enable MEMCG_KMEM +- +- # Make sure all unset options are set to their default value. +- make O="$BUILDDIR/mkosi.kernel" olddefconfig +- +- make O="$BUILDDIR/mkosi.kernel" -j "$(nproc)" +- +- KERNEL_RELEASE="$(make O=$BUILDDIR/mkosi.kernel -s kernelrelease)" +- mkdir -p "$DESTDIR/usr/lib/modules/$KERNEL_RELEASE" +- make O="$BUILDDIR/mkosi.kernel" INSTALL_MOD_PATH="$DESTDIR/usr" modules_install +- make O="$BUILDDIR/mkosi.kernel" INSTALL_PATH="$DESTDIR/usr/lib/modules/$KERNEL_RELEASE" install +-fi +diff --git a/mkosi.conf b/mkosi.conf +new file mode 100644 +index 0000000000..9ec4faf122 +--- /dev/null ++++ b/mkosi.conf +@@ -0,0 +1,39 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Config] ++Images=system ++ ++[Output] ++@OutputDirectory=mkosi.output ++BuildDirectory=mkosi.builddir ++CacheDirectory=mkosi.cache ++ ++[Content] ++# Prevent ASAN warnings when building the image and ship the real ASAN options prefixed with MKOSI_. ++Environment=ASAN_OPTIONS=verify_asan_link_order=false ++ MKOSI_ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1:disable_coredump=0:use_madv_dontdump=1 ++ MKOSI_UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 ++ ++[Host] ++@Incremental=yes ++@QemuMem=2G ++@RuntimeSize=8G ++ToolsTreePackages=virtiofsd ++KernelCommandLineExtra=systemd.crash_shell ++ systemd.log_level=debug ++ systemd.log_ratelimit_kmsg=0 ++ systemd.journald.forward_to_console ++ systemd.journald.max_level_console=warning ++ # Disable the kernel's ratelimiting on userspace logging to kmsg. ++ printk.devkmsg=on ++ # Make sure /sysroot is mounted rw in the initrd. ++ rw ++ # Lower the default device timeout so we get a shell earlier if the root device does ++ # not appear for some reason. ++ systemd.default_device_timeout_sec=10 ++ # Make sure no LSMs are enabled by default. ++ apparmor=0 ++ selinux=0 ++ enforcing=0 ++ systemd.early_core_pattern=/core ++ systemd.firstboot=no +diff --git a/mkosi.conf.d/05-qemu-mem.conf b/mkosi.conf.d/05-qemu-mem.conf +new file mode 100644 +index 0000000000..3a6f24a7b0 +--- /dev/null ++++ b/mkosi.conf.d/05-qemu-mem.conf +@@ -0,0 +1,11 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++# Arch and CentOS 8 Stream initrds are rather big so we need to give QEMU more memory so the kernel can load ++# them without OOMing. ++ ++[Match] ++Distribution=|arch ++Distribution=|centos ++ ++[Host] ++@QemuMem=3G +diff --git a/mkosi.conf.d/10-centos.conf b/mkosi.conf.d/10-centos.conf +new file mode 100644 +index 0000000000..ae2706c791 +--- /dev/null ++++ b/mkosi.conf.d/10-centos.conf +@@ -0,0 +1,10 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=centos ++ ++[Distribution] ++@Release=9 ++Repositories=epel ++ epel-next ++ hyperscale-packages-main +diff --git a/mkosi.conf.d/10-debian.conf b/mkosi.conf.d/10-debian.conf +new file mode 100644 +index 0000000000..8674e884fa +--- /dev/null ++++ b/mkosi.conf.d/10-debian.conf +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=debian ++ ++[Distribution] ++@Release=testing +diff --git a/mkosi.conf.d/10-extra-search-paths.conf b/mkosi.conf.d/10-extra-search-paths.conf +new file mode 100644 +index 0000000000..bd3cdb1de4 +--- /dev/null ++++ b/mkosi.conf.d/10-extra-search-paths.conf +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++PathExists=build/ ++ ++[Host] ++ExtraSearchPaths=build/ +diff --git a/mkosi.conf.d/10-fedora.conf b/mkosi.conf.d/10-fedora.conf +new file mode 100644 +index 0000000000..006cdeded8 +--- /dev/null ++++ b/mkosi.conf.d/10-fedora.conf +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=fedora ++ ++[Distribution] ++@Release=39 +diff --git a/mkosi.conf.d/10-opensuse.conf b/mkosi.conf.d/10-opensuse.conf +new file mode 100644 +index 0000000000..832c0d15fb +--- /dev/null ++++ b/mkosi.conf.d/10-opensuse.conf +@@ -0,0 +1,7 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=opensuse ++ ++[Distribution] ++@Release=tumbleweed +diff --git a/mkosi.conf.d/10-tools.conf b/mkosi.conf.d/10-tools.conf +new file mode 100644 +index 0000000000..9d276d43c4 +--- /dev/null ++++ b/mkosi.conf.d/10-tools.conf +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++PathExists=!build/ ++SystemdVersion=<254 ++ ++[Host] ++@ToolsTree=default +diff --git a/mkosi.conf.d/10-ubuntu.conf b/mkosi.conf.d/10-ubuntu.conf +new file mode 100644 +index 0000000000..b0ebbadd48 +--- /dev/null ++++ b/mkosi.conf.d/10-ubuntu.conf +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=ubuntu ++ ++[Distribution] ++@Release=jammy ++Repositories=universe +diff --git a/mkosi.default.d/10-systemd.conf b/mkosi.default.d/10-systemd.conf +deleted file mode 100644 +index c144c86816..0000000000 +--- a/mkosi.default.d/10-systemd.conf ++++ /dev/null +@@ -1,73 +0,0 @@ +-# SPDX-License-Identifier: LGPL-2.1-or-later +- +-# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +- +-[Output] +-Format=gpt_btrfs +-Bootable=yes +-HostonlyInitrd=yes +-# Prevent ASAN warnings when building the image +-Environment=ASAN_OPTIONS=verify_asan_link_order=false +-OutputDirectory=mkosi.output +- +-[Content] +-BuildDirectory=mkosi.builddir +-Cache=mkosi.cache +-SourceFileTransfer=mount +-SourceFileTransferFinal=copy-git-others +-Packages= +- acl +- bash-completion +- coreutils +- diffutils +- dnsmasq +- findutils +- gcc # For sanitizer libraries +- gdb +- grep +- kbd +- kexec-tools +- kmod +- less +- nano +- nftables +- openssl +- python3 +- qrencode +- sed +- strace +- tree +- util-linux +- valgrind +- wireguard-tools +- zsh +- +-BuildPackages= +- bc +- binutils +- bison +- clang +- flex +- gcc +- gettext +- git +- gnu-efi +- gperf +- llvm +- make +- meson +- pkgconf +- rpm +- rsync +- tar +- zstd +- +-[Host] +-QemuHeadless=yes +-Netdev=yes +-QemuMem=2G +-ExtraSearchPaths=build/ +- +-[Validation] +-Password= +-Autologin=yes +diff --git a/mkosi.default.d/arch/10-mkosi.arch b/mkosi.default.d/arch/10-mkosi.arch +deleted file mode 100644 +index 50194b960b..0000000000 +--- a/mkosi.default.d/arch/10-mkosi.arch ++++ /dev/null +@@ -1,37 +0,0 @@ +-# SPDX-License-Identifier: LGPL-2.1-or-later +-# +-# Copyright © 2016 Zeal Jagannatha +- +-# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +-# Symlink this file to mkosi.default in the project root directory and invoke "mkosi" to build an OS image. +- +-[Distribution] +-Distribution=arch +- +-[Content] +-Packages= +- compsize +- dhcp +- gnutls +- iproute +- libbpf +- libfido2 +- libmicrohttpd +- libpwquality +- libxkbcommon +- man-db +- openbsd-netcat +- polkit +- quota-tools +- tpm2-tss +- vim +- +-BuildPackages= +- bpf +- docbook-xsl +- libxslt +- linux-api-headers +- pahole +- perl +- python-jinja +- python-lxml +diff --git a/mkosi.default.d/fedora/10-mkosi.fedora b/mkosi.default.d/fedora/10-mkosi.fedora +deleted file mode 100644 +index ab230f0b24..0000000000 +--- a/mkosi.default.d/fedora/10-mkosi.fedora ++++ /dev/null +@@ -1,72 +0,0 @@ +-# SPDX-License-Identifier: LGPL-2.1-or-later +- +-# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +-# Symlink this file to mkosi.default in the project root directory and invoke "mkosi" to build an OS image. +- +-[Distribution] +-Distribution=fedora +-Release=37 +- +-[Content] +-Packages= +- compsize +- cryptsetup +- dhcp-server +- glib2 +- glibc-minimal-langpack +- gnutls +- iproute +- iproute-tc +- libbpf +- libfido2 +- libgcrypt +- libmicrohttpd +- libxcrypt +- libxkbcommon +- netcat +- pam +- polkit +- procps-ng +- quota +- tpm2-tss +- vim-common +- +-BuildPackages= +- bpftool +- docbook-xsl +- dwarves +- gnu-efi-devel +- pam-devel +- pkgconfig # pkgconf shim to provide /usr/bin/pkg-config +- pkgconfig(audit) +- pkgconfig(blkid) +- pkgconfig(dbus-1) +- pkgconfig(fdisk) +- pkgconfig(glib-2.0) +- pkgconfig(libacl) +- pkgconfig(libbpf) +- pkgconfig(libcap) +- pkgconfig(libcryptsetup) +- pkgconfig(libcurl) +- pkgconfig(libdw) +- pkgconfig(libfido2) +- pkgconfig(libgcrypt) +- pkgconfig(libidn2) +- pkgconfig(libkmod) +- pkgconfig(libmicrohttpd) +- pkgconfig(libpcre2-8) +- pkgconfig(libqrencode) +- pkgconfig(libseccomp) +- pkgconfig(libselinux) +- pkgconfig(libzstd) +- pkgconfig(mount) +- pkgconfig(openssl) +- pkgconfig(p11-kit-1) +- pkgconfig(pwquality) +- pkgconfig(tss2-esys) +- pkgconfig(tss2-mu) +- pkgconfig(tss2-rc) +- pkgconfig(valgrind) +- pkgconfig(xkbcommon) +- python3dist(jinja2) +- python3dist(lxml) +diff --git a/mkosi.default.d/ubuntu/10-mkosi.ubuntu b/mkosi.default.d/ubuntu/10-mkosi.ubuntu +deleted file mode 100644 +index 14f337b7ea..0000000000 +--- a/mkosi.default.d/ubuntu/10-mkosi.ubuntu ++++ /dev/null +@@ -1,70 +0,0 @@ +-# SPDX-License-Identifier: LGPL-2.1-or-later +- +-# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +-# Symlink this file to mkosi.default in the project root directory and invoke "mkosi" to build an OS image. +- +-[Distribution] +-Distribution=ubuntu +-Release=jammy +-Repositories=main,universe +- +-[Content] +-Packages= +- cryptsetup-bin +- fdisk +- iproute2 +- isc-dhcp-server +- libbpf0 +- libfdisk1 +- libfido2-1 +- libglib2.0-0 +- libidn2-0 +- libmicrohttpd12 +- libp11-kit0 +- libpwquality1 +- libqrencode4 +- libtss2-dev # Use the -dev package to avoid churn in updating version numbers +- linux-tools-common +- linux-tools-generic +- netcat-openbsd +- policykit-1 +- procps +- quota +- xxd +- +-BuildPackages= +- docbook-xsl +- g++ +- libacl1-dev +- libaudit-dev +- libblkid-dev +- libbpf-dev +- libbz2-dev +- libcap-dev +- libcryptsetup-dev +- libcurl4-openssl-dev +- libdbus-1-dev +- libdw-dev +- libfdisk-dev +- libfido2-dev +- libgcrypt20-dev +- libglib2.0-dev +- libgnutls28-dev +- libidn2-dev +- libiptc-dev +- libkmod-dev +- libmicrohttpd-dev +- libmount-dev +- libp11-kit-dev +- libpam0g-dev +- libpwquality-dev +- libqrencode-dev +- libseccomp-dev +- libsmartcols-dev +- libssl-dev +- libxkbcommon-dev +- libzstd-dev +- pahole +- python3-jinja2 +- python3-lxml +- xsltproc +diff --git a/mkosi.images/base/mkosi.build.chroot b/mkosi.images/base/mkosi.build.chroot +new file mode 100755 +index 0000000000..ba0c92eef2 +--- /dev/null ++++ b/mkosi.images/base/mkosi.build.chroot +@@ -0,0 +1,183 @@ ++#!/bin/bash ++# SPDX-License-Identifier: LGPL-2.1-or-later ++set -e ++ ++# This is a build script for OS image generation using mkosi (https://github.com/systemd/mkosi). ++# Simply invoke "mkosi" in the project directory to build an OS image. ++ ++# We don't want to install our build of systemd in the base image, but use it as an extra tree for the ++# initrd and system images, so override DESTDIR to store it in the output directory so we can reference it as ++# an extra tree in the initrd and system image builds. ++DESTDIR="$OUTPUTDIR/systemd" ++ ++# If mkosi.builddir/ exists mkosi will set $BUILDDIR to it, let's then use it ++# as out-of-tree build dir. Otherwise, let's make up our own builddir. ++[ -z "$BUILDDIR" ] && BUILDDIR="$PWD"/build ++ ++# Let's make sure we're using stuff from the build directory first if available there. ++PATH="$BUILDDIR:$PATH" ++export PATH ++ ++# The bpftool script shipped by Ubuntu tries to find the actual program to run via querying `uname -r` and ++# using the current kernel version. This obviously doesn't work in containers. As a workaround, we override ++# the ubuntu script with a symlink to the first bpftool program we can find. ++for bpftool in /usr/lib/linux-tools/*/bpftool; do ++ [ -x "$bpftool" ] || continue ++ ln -sf "$bpftool" "$BUILDDIR"/bpftool ++ break ++done ++ ++# CentOS Stream 8 includes bpftool 4.18.0 which is lower than what we need. However, they've backported the ++# specific feature we need ("gen skeleton") to this version, so we replace bpftool with a script that reports ++# version 5.6.0 to satisfy meson which makes bpf work on CentOS Stream 8 as well. ++. /usr/lib/os-release ++if [ "$ID" = "centos" ] && [ "$VERSION" = "8" ]; then ++ cat >"$BUILDDIR"/bpftool </. ++ # It is important to use the right one especially for cryptsetup plugins, otherwise they will be ++ # installed in the wrong directory and not be found by cryptsetup. Assume native build. ++ if grep -q -e "ID=debian" -e "ID_LIKE=debian" /usr/lib/os-release && command -v dpkg 2>/dev/null; then ++ CONFIGURE_OPTS+=( ++ -D libdir="/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)" ++ -D pamlibdir="/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)/security" ++ ) ++ fi ++ ++ # Set various uids and gids for which Fedora has "soft static" allocations. ++ # Without this, we would get warning about mismatched sysusers.d entries ++ # between the files that we and Fedora's setup package install. ++ if grep -q '^ID=fedora' /usr/lib/os-release; then ++ CONFIGURE_OPTS+=( ++ -D adm-gid=4 ++ -D audio-gid=63 ++ -D cdrom-gid=11 ++ -D dialout-gid=18 ++ -D disk-gid=6 ++ -D input-gid=104 ++ -D kmem-gid=9 ++ -D kvm-gid=36 ++ -D lp-gid=7 ++ -D render-gid=105 ++ -D sgx-gid=106 ++ -D tape-gid=33 ++ -D tty-gid=5 ++ -D users-gid=100 ++ -D utmp-gid=22 ++ -D video-gid=39 ++ -D wheel-gid=10 ++ -D systemd-journal-gid=190 ++ -D systemd-network-uid=192 ++ -D systemd-resolve-uid=193 ++ ) ++ fi ++ ++ if grep -q '^ID="opensuse' /usr/lib/os-release; then ++ CONFIGURE_OPTS+=( ++ -Dbpf-compiler=gcc ++ ) ++ fi ++ ++ ( set -x; meson setup "$BUILDDIR" "$SRCDIR" --auto-features=enabled "${CONFIGURE_OPTS[@]}" ) ++fi ++ ++( set -x; ninja -C "$BUILDDIR" "$@" ) ++if [ "$WITH_TESTS" = 1 ]; then ++ if [ -n "$SANITIZERS" ]; then ++ export ASAN_OPTIONS="$MKOSI_ASAN_OPTIONS" ++ export UBSAN_OPTIONS="$MKOSI_UBSAN_OPTIONS" ++ TIMEOUT_MULTIPLIER=3 ++ else ++ TIMEOUT_MULTIPLIER=1 ++ fi ++ ++ ( set -x; meson test -C "$BUILDDIR" --print-errorlogs --timeout-multiplier=$TIMEOUT_MULTIPLIER ) ++fi ++ ++( set -x; meson install -C "$BUILDDIR" --quiet --no-rebuild --only-changed ) ++ ++# Ensure that side-loaded PE addons are loaded if signed, and ignored if not ++if [ -d "${DESTDIR}/boot/loader" ]; then ++ addons_dir="${DESTDIR}/boot/loader/addons" ++elif [ -d "${DESTDIR}/efi/loader" ]; then ++ addons_dir="${DESTDIR}/efi/loader/addons" ++fi ++if [ -n "${addons_dir}" ]; then ++ mkdir -p "${addons_dir}" ++ ukify --secureboot-private-key mkosi.secure-boot.key --secureboot-certificate mkosi.secure-boot.crt --cmdline this_should_be_here -o "${addons_dir}/good.addon.efi" ++ ukify --cmdline this_should_not_be_here -o "${addons_dir}/bad.addon.efi" ++fi +diff --git a/mkosi.images/base/mkosi.conf b/mkosi.images/base/mkosi.conf +new file mode 100644 +index 0000000000..be8586ce3b +--- /dev/null ++++ b/mkosi.images/base/mkosi.conf +@@ -0,0 +1,36 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Output] ++Format=directory ++ ++[Content] ++Bootable=no ++CleanPackageMetadata=no ++ ++Packages= ++Packages= ++ kmod ++ less ++ util-linux ++ ++BuildPackages= ++ acl ++ binutils ++ clang ++ diffutils ++ gawk ++ gdb ++ gettext ++ git ++ gperf ++ grep ++ lld ++ llvm ++ make ++ meson ++ pkgconf ++ rsync ++ sed ++ strace ++ tar ++ zstd +diff --git a/mkosi.images/base/mkosi.conf.d/10-arch.conf b/mkosi.images/base/mkosi.conf.d/10-arch.conf +new file mode 100644 +index 0000000000..385c73979f +--- /dev/null ++++ b/mkosi.images/base/mkosi.conf.d/10-arch.conf +@@ -0,0 +1,33 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=arch ++ ++[Content] ++Packages= ++ cryptsetup ++ dbus ++ gnutls ++ libarchive ++ libbpf ++ libfido2 ++ libmicrohttpd ++ libnftnl ++ libpwquality ++ libseccomp ++ libxkbcommon ++ openssl ++ qrencode ++ tpm2-tss ++ ++BuildPackages= ++ bpf ++ docbook-xsl ++ glib2 ++ libxslt ++ linux-api-headers ++ python ++ python-jinja ++ python-lxml ++ python-pefile ++ python-pyelftools +diff --git a/mkosi.default.d/centos_epel/10-mkosi.centos_epel b/mkosi.images/base/mkosi.conf.d/10-centos-fedora.conf +similarity index 67% +rename from mkosi.default.d/centos_epel/10-mkosi.centos_epel +rename to mkosi.images/base/mkosi.conf.d/10-centos-fedora.conf +index c09eb41800..d7a135a5c0 100644 +--- a/mkosi.default.d/centos_epel/10-mkosi.centos_epel ++++ b/mkosi.images/base/mkosi.conf.d/10-centos-fedora.conf +@@ -1,49 +1,37 @@ + # SPDX-License-Identifier: LGPL-2.1-or-later + +-# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +-# Symlink this file to mkosi.default in the project root directory and invoke "mkosi" to build an OS image. +- +-[Distribution] +-Distribution=centos_epel +- +-[Output] +-Format=gpt_xfs +-HostonlyInitrd=no ++[Match] ++Distribution=|centos ++Distribution=|fedora + + [Content] + Packages= +- audit +- cryptsetup +- dhcp-server +- glib2 +- glibc-minimal-langpack ++ audit-libs ++ cryptsetup-libs + gnutls +- iproute +- iproute-tc +- kernel-modules-extra ++ libarchive ++ libasan + libbpf + libfido2 ++ libgcrypt + libmicrohttpd ++ libnftnl ++ libubsan + libxcrypt + libxkbcommon +- netcat +- p11-kit +- pam +- polkit +- procps-ng +- quota ++ openssl-libs ++ qrencode-libs + tpm2-tss +- vim-common ++ util-linux + + BuildPackages= ++ pkgconf + bpftool + docbook-xsl +- dwarves +- gnu-efi-devel ++ findutils + libgcrypt-devel # CentOS Stream 8 libgcrypt-devel doesn't ship a pkg-config file. + libxslt + pam-devel +- perl-interpreter + pkgconfig(audit) + pkgconfig(blkid) + pkgconfig(bzip2) +@@ -52,6 +40,7 @@ BuildPackages= + pkgconfig(glib-2.0) + pkgconfig(gnutls) + pkgconfig(libacl) ++ pkgconfig(libarchive) + pkgconfig(libbpf) + pkgconfig(libcap) + pkgconfig(libcryptsetup) +@@ -60,20 +49,30 @@ BuildPackages= + pkgconfig(libfido2) + pkgconfig(libidn2) + pkgconfig(libkmod) ++ pkgconfig(liblz4) + pkgconfig(libmicrohttpd) ++ pkgconfig(libnftnl) + pkgconfig(libpcre2-8) + pkgconfig(libqrencode) + pkgconfig(libseccomp) + pkgconfig(libselinux) + pkgconfig(libzstd) + pkgconfig(mount) ++ pkgconfig(numa) ++ pkgconfig(openssl) + pkgconfig(openssl) + pkgconfig(p11-kit-1) + pkgconfig(pwquality) + pkgconfig(tss2-esys) + pkgconfig(tss2-mu) + pkgconfig(tss2-rc) ++ pkgconfig(tss2-tcti-device) + pkgconfig(valgrind) + pkgconfig(xkbcommon) ++ python3 + python3dist(jinja2) + python3dist(lxml) ++ python3dist(pefile) ++ python3dist(pyelftools) ++ python3dist(pytest) ++ rpm +diff --git a/mkosi.default.d/debian/10-mkosi.debian b/mkosi.images/base/mkosi.conf.d/10-debian-ubuntu.conf +similarity index 64% +rename from mkosi.default.d/debian/10-mkosi.debian +rename to mkosi.images/base/mkosi.conf.d/10-debian-ubuntu.conf +index 3eea0c74b9..1d28be30f8 100644 +--- a/mkosi.default.d/debian/10-mkosi.debian ++++ b/mkosi.images/base/mkosi.conf.d/10-debian-ubuntu.conf +@@ -1,40 +1,41 @@ + # SPDX-License-Identifier: LGPL-2.1-or-later + +-# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +-# Symlink this file to mkosi.default in the project root directory and invoke "mkosi" to build an OS image. +- +-[Distribution] +-Distribution=debian +-Release=testing ++[Match] ++Distribution=|debian ++Distribution=|ubuntu + + [Content] + Packages= +- cryptsetup-bin +- fdisk +- iproute2 +- isc-dhcp-server +- libbpf0 ++ ^libtss2-esys-[0-9\.]+-0$ ++ dmsetup ++ libapparmor1 ++ libarchive13 ++ libfdisk1 + libfido2-1 + libglib2.0-0 + libgnutls30 + libidn2-0 ++ liblz4-1 + libmicrohttpd12 ++ libnftnl11 + libp11-kit0 + libpam0g + libpwquality1 + libqrencode4 +- libtss2-dev # Use the -dev package to avoid churn in updating version numbers +- netcat-openbsd +- policykit-1 +- procps +- quota +- xxd ++ libssl3 ++ libip4tc2 ++ ^libtss2-mu[0-9\.-]+$ ++ libtss2-rc0 ++ libtss2-tcti-device0 ++ tzdata + + BuildPackages= +- bpftool + docbook-xsl ++ dpkg-dev + g++ + libacl1-dev ++ libapparmor-dev ++ libarchive-dev + libaudit-dev + libblkid-dev + libbpf-dev +@@ -52,8 +53,10 @@ BuildPackages= + libidn2-dev + libiptc-dev + libkmod-dev ++ liblz4-dev + libmicrohttpd-dev + libmount-dev ++ libnftnl-dev + libp11-kit-dev + libpam0g-dev + libpwquality-dev +@@ -61,9 +64,14 @@ BuildPackages= + libseccomp-dev + libsmartcols-dev + libssl-dev ++ libtss2-dev ++ libxen-dev + libxkbcommon-dev + libzstd-dev +- pahole ++ python3 + python3-jinja2 + python3-lxml ++ python3-pefile ++ python3-pyelftools ++ python3-pytest + xsltproc +diff --git a/mkosi.images/base/mkosi.conf.d/10-debian.conf b/mkosi.images/base/mkosi.conf.d/10-debian.conf +new file mode 100644 +index 0000000000..020b02b61c +--- /dev/null ++++ b/mkosi.images/base/mkosi.conf.d/10-debian.conf +@@ -0,0 +1,11 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=debian ++ ++[Content] ++Packages= ++ libbpf1 ++ ++BuildPackages= ++ bpftool +diff --git a/mkosi.images/base/mkosi.conf.d/10-fedora.conf b/mkosi.images/base/mkosi.conf.d/10-fedora.conf +new file mode 100644 +index 0000000000..a8fbce47fb +--- /dev/null ++++ b/mkosi.images/base/mkosi.conf.d/10-fedora.conf +@@ -0,0 +1,9 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=fedora ++ ++[Content] ++BuildPackages= ++ python3dist(pytest-flakes) ++ pkgconfig(xencontrol) +diff --git a/mkosi.default.d/opensuse/10-mkosi.opensuse b/mkosi.images/base/mkosi.conf.d/10-opensuse.conf +similarity index 65% +rename from mkosi.default.d/opensuse/10-mkosi.opensuse +rename to mkosi.images/base/mkosi.conf.d/10-opensuse.conf +index 804213baab..941a50a6d1 100644 +--- a/mkosi.default.d/opensuse/10-mkosi.opensuse ++++ b/mkosi.images/base/mkosi.conf.d/10-opensuse.conf +@@ -1,17 +1,20 @@ + # SPDX-License-Identifier: LGPL-2.1-or-later + +-# This is a settings file for OS image generation using mkosi (https://github.com/systemd/mkosi). +-# Symlink this file to mkosi.default in the project root directory and invoke "mkosi" to build an OS image. +- +-[Distribution] ++[Match] + Distribution=opensuse +-Release=tumbleweed + + [Content] ++# We install gawk, gzip, grep, xz, sed, rsync and docbook-xsl-stylesheets here explicitly so that the busybox ++# versions don't get installed instead. + Packages= +- dbus-1 +- glibc-locale-base ++ device-mapper ++ distribution-release ++ docbook-xsl-stylesheets ++ gawk ++ grep ++ gzip + libbpf1 ++ libarchive13 + libcrypt1 + libcryptsetup12 + libdw1 +@@ -20,22 +23,30 @@ Packages= + libgcrypt20 + libglib-2_0-0 + libkmod2 +- liblz4-1 + libmount1 ++ libnftnl11 ++ libopenssl3 + libp11-kit0 + libqrencode4 + libseccomp2 ++ libtss2-esys0 ++ libtss2-mu0 ++ libtss2-rc0 ++ libtss2-tcti-device0 + libxkbcommon0 ++ libzstd1 + pam ++ rsync ++ sed ++ shadow + tpm2-0-tss +- vim ++ xz + + BuildPackages= + audit-devel + bpftool ++ cross-bpf-gcc13 + dbus-1-devel +- docbook-xsl-stylesheets +- dwarves + fdupes + gcc-c++ + glib2-devel +@@ -43,6 +54,7 @@ BuildPackages= + intltool + libacl-devel + libapparmor-devel ++ libarchive-devel + libblkid-devel + libbpf-devel + libbz2-devel +@@ -56,28 +68,28 @@ BuildPackages= + libgcrypt-devel + libgnutls-devel + libkmod-devel ++ liblz4-devel + libmicrohttpd-devel + libmount-devel ++ libnftnl-devel + libpwquality-devel + libseccomp-devel + libselinux-devel + libxkbcommon-devel + libxslt-tools +- liblz4-devel ++ libzstd-devel + openssl-devel + pam-devel +- pcre-devel + pciutils-devel ++ python3 + python3-Jinja2 + python3-lxml ++ python3-pefile ++ python3-pyelftools ++ python3-pytest ++ python3-pytest-flakes + qrencode-devel + shadow +- system-group-obsolete +- system-user-bin +- system-user-daemon +- system-user-nobody +- system-user-root +- systemd-sysvinit + timezone + tpm2-0-tss-devel +- zlib-devel ++ xen-devel +diff --git a/mkosi.images/base/mkosi.conf.d/10-ubuntu.conf b/mkosi.images/base/mkosi.conf.d/10-ubuntu.conf +new file mode 100644 +index 0000000000..717809fd03 +--- /dev/null ++++ b/mkosi.images/base/mkosi.conf.d/10-ubuntu.conf +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=ubuntu ++ ++[Content] ++Packages= ++ libbpf0 ++ ++BuildPackages= ++ linux-tools-common ++ linux-tools-generic +diff --git a/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/00-mkosi.preset b/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/00-mkosi.preset +new file mode 100644 +index 0000000000..070af4c67a +--- /dev/null ++++ b/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/00-mkosi.preset +@@ -0,0 +1,30 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++# mkosi adds its own ssh units via the --ssh switch so disable the default ones. ++disable ssh.service ++disable sshd.service ++ ++# These are started manually in integration tests so don't start them by default. ++disable dnsmasq.service ++disable isc-dhcp-server.service ++disable isc-dhcp-server6.service ++ ++# Pulled in via dracut-network by kexec-tools on Fedora. ++disable NetworkManager* ++ ++# Make sure dbus-broker is started by default on Debian/Ubuntu. ++enable dbus-broker.service ++ ++# systemd-networkd is disabled by default on Fedora so make sure it is enabled. ++enable systemd-networkd.service ++enable systemd-networkd-wait-online.service ++ ++# We install dnf in some images but it's only going to be used rarely, ++# so let's not have dnf create its cache. ++disable dnf-makecache.* ++ ++# We have journald to receive audit data so let's make sure we're not running auditd as well ++disable auditd.service ++ ++# systemd-timesyncd is not enabled by default in the default systemd preset so enable it here instead. ++enable systemd-timesyncd.service +diff --git a/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/99-mkosi.preset b/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/99-mkosi.preset +new file mode 100644 +index 0000000000..710ee7c6f9 +--- /dev/null ++++ b/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/99-mkosi.preset +@@ -0,0 +1,4 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++# Make sure that services are disabled by default (primarily for Debian/Ubuntu). ++disable * +diff --git a/mkosi.images/base/mkosi.extra/usr/lib/tmpfiles.d/locale.conf b/mkosi.images/base/mkosi.extra/usr/lib/tmpfiles.d/locale.conf +new file mode 100644 +index 0000000000..e1a8e8171a +--- /dev/null ++++ b/mkosi.images/base/mkosi.extra/usr/lib/tmpfiles.d/locale.conf +@@ -0,0 +1 @@ ++L /etc/default/locale - - - - ../locale.conf +diff --git a/mkosi.images/initrd/mkosi.conf b/mkosi.images/initrd/mkosi.conf +new file mode 100644 +index 0000000000..8e38dc1b78 +--- /dev/null ++++ b/mkosi.images/initrd/mkosi.conf +@@ -0,0 +1,30 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Config] ++Dependencies=base ++ ++[Output] ++Format=cpio ++ ++[Content] ++BaseTrees=../../mkosi.output/base ++ExtraTrees=../../mkosi.output/base-systemd ++MakeInitrd=yes ++Bootable=no ++BuildPackages= ++ ++Packages= ++Packages= ++ gzip ++ systemd ++ udev ++ ++# Arch Linux doesn't split their gcc-libs package so we manually remove unneeded stuff here to make sure it ++# doesn't end up in the initrd. ++RemoveFiles= ++ /usr/lib/libgfortran.so* ++ /usr/lib/libgo.so* ++ /usr/lib/libgomp.so* ++ /usr/lib/libgphobos.so* ++ /usr/lib/libobjc.so* ++ /usr/lib/libstdc++.so* +diff --git a/mkosi.images/initrd/mkosi.conf.d/10-centos.conf b/mkosi.images/initrd/mkosi.conf.d/10-centos.conf +new file mode 100644 +index 0000000000..3f92e52300 +--- /dev/null ++++ b/mkosi.images/initrd/mkosi.conf.d/10-centos.conf +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=centos ++ ++[Output] ++# TODO: Switch to zstd once we stop building CentOS Stream 8. ++CompressOutput=xz ++ ++[Content] ++Packages=xfsprogs ++ tpm2-tools +diff --git a/mkosi.images/initrd/mkosi.conf.d/10-default.conf b/mkosi.images/initrd/mkosi.conf.d/10-default.conf +new file mode 100644 +index 0000000000..9224b92dd0 +--- /dev/null ++++ b/mkosi.images/initrd/mkosi.conf.d/10-default.conf +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=!centos ++Distribution=!opensuse ++ ++[Output] ++CompressOutput=zst ++ ++[Content] ++Packages=btrfs-progs ++ tpm2-tools +diff --git a/mkosi.images/initrd/mkosi.conf.d/10-opensuse.conf b/mkosi.images/initrd/mkosi.conf.d/10-opensuse.conf +new file mode 100644 +index 0000000000..5cf2df397e +--- /dev/null ++++ b/mkosi.images/initrd/mkosi.conf.d/10-opensuse.conf +@@ -0,0 +1,11 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=opensuse ++ ++[Output] ++CompressOutput=zst ++ ++[Content] ++Packages=btrfs-progs ++ tpm2.0-tools +diff --git a/mkosi.images/initrd/mkosi.postinst b/mkosi.images/initrd/mkosi.postinst +new file mode 100755 +index 0000000000..de610dfeb6 +--- /dev/null ++++ b/mkosi.images/initrd/mkosi.postinst +@@ -0,0 +1,7 @@ ++#!/bin/sh ++# SPDX-License-Identifier: LGPL-2.1-or-later ++set -e ++ ++# OpenSUSE insists on blacklisting erofs by default because its supposedly a legacy filesystem. ++# See https://github.com/openSUSE/suse-module-tools/pull/71 ++rm -f "$BUILDROOT/usr/lib/modprobe.d/60-blacklist_fs-erofs.conf" +diff --git a/mkosi.images/system/mkosi.conf b/mkosi.images/system/mkosi.conf +new file mode 100644 +index 0000000000..9646bbefde +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf +@@ -0,0 +1,52 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Config] ++Dependencies=base ++ ++[Output] ++@Format=directory ++ ++[Content] ++Autologin=yes ++BaseTrees=../../mkosi.output/base ++ExtraTrees=../../mkosi.output/base-systemd ++Packages= ++ acl ++ bash-completion ++ coreutils ++ diffutils ++ dnsmasq ++ dosfstools ++ e2fsprogs ++ findutils ++ gcc # Sanitizer libraries ++ gdb ++ grep ++ gzip ++ kbd ++ kexec-tools ++ less ++ mtools ++ nano ++ nftables ++ openssl ++ qrencode ++ sed ++ socat ++ strace ++ systemd ++ tmux ++ tar ++ tree ++ udev ++ util-linux ++ valgrind ++ wireguard-tools ++ xfsprogs ++ zsh ++ ++BuildPackages= ++ ++[Validation] ++@SecureBoot=yes ++@SignExpectedPcr=yes +diff --git a/mkosi.images/system/mkosi.conf.d/05-initrd.conf b/mkosi.images/system/mkosi.conf.d/05-initrd.conf +new file mode 100644 +index 0000000000..9f21754058 +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/05-initrd.conf +@@ -0,0 +1,12 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Bootable=!no ++Format=|disk ++Format=|directory ++ ++[Config] ++Dependencies=initrd ++ ++[Content] ++Initrds=../../mkosi.output/initrd +diff --git a/mkosi.images/system/mkosi.conf.d/10-arch.conf b/mkosi.images/system/mkosi.conf.d/10-arch.conf +new file mode 100644 +index 0000000000..e1a511c979 +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-arch.conf +@@ -0,0 +1,27 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=arch ++ ++[Content] ++Packages= ++ bpf ++ btrfs-progs ++ compsize ++ dhcp ++ f2fs-tools ++ glib2 ++ iproute ++ linux ++ man-db ++ openbsd-netcat ++ openssh ++ pacman ++ polkit ++ python-pefile ++ python-psutil ++ python-pytest ++ python3 ++ quota-tools ++ shadow ++ vim +diff --git a/mkosi.images/system/mkosi.conf.d/10-centos-fedora.conf b/mkosi.images/system/mkosi.conf.d/10-centos-fedora.conf +new file mode 100644 +index 0000000000..871186d5ca +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-centos-fedora.conf +@@ -0,0 +1,33 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=|centos ++Distribution=|fedora ++ ++[Content] ++Packages= ++ bpftool ++ cryptsetup ++ dhcp-server ++ dnf ++ glib2 ++ integritysetup ++ iproute ++ iproute-tc ++ kernel-core ++ libcap-ng-utils ++ netcat ++ openssh-server ++ openssh-clients ++ p11-kit ++ pam ++ passwd ++ polkit ++ procps-ng ++ python3 ++ python3dist(pefile) ++ python3dist(pluggy) # python3-pluggy is a pytest dependency that's not installed for some reason. ++ python3dist(psutil) ++ python3dist(pytest) ++ quota ++ vim-common +diff --git a/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.conf b/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.conf +new file mode 100644 +index 0000000000..146e03a895 +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.conf +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=centos ++ ++[Content] ++Packages= ++ kernel-modules # For squashfs support +diff --git a/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.extra/usr/lib/repart.d/20-root.conf.d/xfs.conf b/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.extra/usr/lib/repart.d/20-root.conf.d/xfs.conf +new file mode 100644 +index 0000000000..99b846d3a8 +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.extra/usr/lib/repart.d/20-root.conf.d/xfs.conf +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++# CentOS does not support btrfs so we use xfs instead. ++[Partition] ++Format=xfs +diff --git a/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.repart/10-usr.conf.d/squashfs.conf b/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.repart/10-usr.conf.d/squashfs.conf +new file mode 100644 +index 0000000000..393d5f038c +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.repart/10-usr.conf.d/squashfs.conf +@@ -0,0 +1,5 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++# CentOS does not support erofs so we use squashfs instead. ++[Partition] ++Format=squashfs +diff --git a/mkosi.images/system/mkosi.conf.d/10-debian-amd64.conf b/mkosi.images/system/mkosi.conf.d/10-debian-amd64.conf +new file mode 100644 +index 0000000000..d3c89f3a8c +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-debian-amd64.conf +@@ -0,0 +1,10 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=debian ++Architecture=x86-64 ++ ++[Content] ++Packages= ++ bpftool ++ linux-image-cloud-amd64 +diff --git a/mkosi.images/system/mkosi.conf.d/10-debian-arm64.conf b/mkosi.images/system/mkosi.conf.d/10-debian-arm64.conf +new file mode 100644 +index 0000000000..76a6898111 +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-debian-arm64.conf +@@ -0,0 +1,10 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=debian ++Architecture=arm64 ++ ++[Content] ++Packages= ++ bpftool ++ linux-image-cloud-arm64 +diff --git a/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu.conf b/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu.conf +new file mode 100644 +index 0000000000..348bdb2992 +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu.conf +@@ -0,0 +1,30 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=|debian ++Distribution=|ubuntu ++ ++[Content] ++Packages= ++ apt ++ btrfs-progs ++ cryptsetup-bin ++ dbus-broker ++ default-dbus-session-bus ++ f2fs-tools ++ fdisk ++ iproute2 ++ isc-dhcp-server ++ libcap-ng-utils ++ netcat-openbsd ++ openssh-server ++ openssh-client ++ passwd ++ policykit-1 ++ procps ++ python3 ++ python3-pefile ++ python3-psutil ++ python3-pytest ++ quota ++ xxd +diff --git a/mkosi.images/system/mkosi.conf.d/10-fedora.conf b/mkosi.images/system/mkosi.conf.d/10-fedora.conf +new file mode 100644 +index 0000000000..5863f03b19 +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-fedora.conf +@@ -0,0 +1,11 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=fedora ++ ++[Content] ++Packages= ++ btrfs-progs ++ compsize ++ f2fs-tools ++ glibc-langpack-en +diff --git a/mkosi.images/system/mkosi.conf.d/10-opensuse.conf b/mkosi.images/system/mkosi.conf.d/10-opensuse.conf +new file mode 100644 +index 0000000000..71434b4560 +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-opensuse.conf +@@ -0,0 +1,24 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=opensuse ++ ++[Content] ++Packages= ++ bpftool ++ btrfs-progs ++ cryptsetup ++ dbus-broker ++ f2fs-tools ++ glibc-locale-base ++ kernel-kvmsmall ++ libcap-ng-utils ++ openssh-server ++ openssh-clients ++ python3 ++ python3-pefile ++ python3-psutil ++ python3-pytest ++ quota ++ shadow ++ vim +diff --git a/mkosi.images/system/mkosi.conf.d/10-ubuntu.conf b/mkosi.images/system/mkosi.conf.d/10-ubuntu.conf +new file mode 100644 +index 0000000000..b099e79132 +--- /dev/null ++++ b/mkosi.images/system/mkosi.conf.d/10-ubuntu.conf +@@ -0,0 +1,14 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Match] ++Distribution=ubuntu ++ ++[Content] ++Packages= ++ # We would like to use linux-image-kvm but it does not have support for SMBIOS credentials. ++ linux-image-generic ++ linux-tools-common ++ linux-tools-generic ++# "orphan_file" is enabled by default in recent versions of mkfs.ext4 but not supported by the Jammy kernel ++# so we explicitly disable it. ++Environment=SYSTEMD_REPART_MKFS_OPTIONS_EXT4="-O ^orphan_file" +diff --git a/mkosi.images/system/mkosi.extra/etc/issue b/mkosi.images/system/mkosi.extra/etc/issue +new file mode 100644 +index 0000000000..6aa6fc0ec0 +--- /dev/null ++++ b/mkosi.images/system/mkosi.extra/etc/issue +@@ -0,0 +1,2 @@ ++\S (built from systemd tree) ++Kernel \r on an \m (\l) +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/repart.d/15-swap.conf b/mkosi.images/system/mkosi.extra/usr/lib/repart.d/15-swap.conf +new file mode 100644 +index 0000000000..3755278462 +--- /dev/null ++++ b/mkosi.images/system/mkosi.extra/usr/lib/repart.d/15-swap.conf +@@ -0,0 +1,6 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Partition] ++Type=swap ++SizeMinBytes=100M ++SizeMaxBytes=100M +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/repart.d/20-root.conf b/mkosi.images/system/mkosi.extra/usr/lib/repart.d/20-root.conf +new file mode 100644 +index 0000000000..71eb9e38c4 +--- /dev/null ++++ b/mkosi.images/system/mkosi.extra/usr/lib/repart.d/20-root.conf +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++[Partition] ++Type=root ++Format=btrfs ++SizeMinBytes=1G ++Subvolumes=/home /var ++MakeDirectories=/home /var +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/systemd/journald.conf.d/50-persistent.conf b/mkosi.images/system/mkosi.extra/usr/lib/systemd/journald.conf.d/50-persistent.conf +new file mode 100644 +index 0000000000..2f953290d3 +--- /dev/null ++++ b/mkosi.images/system/mkosi.extra/usr/lib/systemd/journald.conf.d/50-persistent.conf +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++# We only ship /usr in the image so /var/log/journal won't exist on boot which means systemd-journald won't ++# persist any logs as the default Storage= setting is "auto". We can't create /var/log/journal using tmpfiles ++# as systemd-journal-flush.service runs before systemd-tmpfiles-setup.service so instead we explicitly set ++# Storage= to persistent to have systemd-journald create /var/log/journal itself. ++[Journal] ++Storage=persistent +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh b/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh +new file mode 100755 +index 0000000000..9bb246263e +--- /dev/null ++++ b/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh +@@ -0,0 +1,19 @@ ++#!/bin/bash -eux ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++# TODO: Figure out why this is failing ++systemctl reset-failed systemd-vconsole-setup.service ++ ++systemctl --failed --no-legend | tee /failed-services ++ ++# Check that secure boot keys were properly enrolled. ++if ! systemd-detect-virt --container; then ++ cmp /sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c <(printf '\6\0\0\0\1') ++ cmp /sys/firmware/efi/efivars/SetupMode-8be4df61-93ca-11d2-aa0d-00e098032b8c <(printf '\6\0\0\0\0') ++ # TODO: Figure out why this is failing ++ # grep -q this_should_be_here /proc/cmdline ++ # grep -q this_should_not_be_here /proc/cmdline && exit 1 ++fi ++ ++# Exit with non-zero EC if the /failed-services file is not empty (we have -e set) ++[[ ! -s /failed-services ]] +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/systemd/system/mkosi-check-and-shutdown.service b/mkosi.images/system/mkosi.extra/usr/lib/systemd/system/mkosi-check-and-shutdown.service +new file mode 100644 +index 0000000000..7942cbfa77 +--- /dev/null ++++ b/mkosi.images/system/mkosi.extra/usr/lib/systemd/system/mkosi-check-and-shutdown.service +@@ -0,0 +1,15 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++[Unit] ++Description=Check if any service failed and then shutdown the machine ++After=multi-user.target network-online.target ++Requires=multi-user.target ++Wants=systemd-resolved.service systemd-networkd.service network-online.target ++SuccessAction=exit ++FailureAction=exit ++# On success, exit with 123 so that we can check that we receive the actual exit code from the script on the ++# host. ++SuccessActionExitStatus=123 ++ ++[Service] ++Type=oneshot ++ExecStart=/usr/lib/systemd/mkosi-check-and-shutdown.sh +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/tmpfiles.d/99-mkosi.conf b/mkosi.images/system/mkosi.extra/usr/lib/tmpfiles.d/99-mkosi.conf +new file mode 100644 +index 0000000000..dac79ba4ed +--- /dev/null ++++ b/mkosi.images/system/mkosi.extra/usr/lib/tmpfiles.d/99-mkosi.conf +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++C+! /etc - - - - /usr/share/factory/mkosi +diff --git a/mkosi.images/system/mkosi.extra/usr/share/factory/mkosi/gdbinit.d/systemd.gdb b/mkosi.images/system/mkosi.extra/usr/share/factory/mkosi/gdbinit.d/systemd.gdb +new file mode 100644 +index 0000000000..26f882bc2b +--- /dev/null ++++ b/mkosi.images/system/mkosi.extra/usr/share/factory/mkosi/gdbinit.d/systemd.gdb +@@ -0,0 +1,3 @@ ++set debuginfod enabled off ++set build-id-verbose 0 ++set substitute-path ../src /root/src/systemd +diff --git a/mkosi.images/system/mkosi.finalize b/mkosi.images/system/mkosi.finalize +new file mode 100755 +index 0000000000..74b810c152 +--- /dev/null ++++ b/mkosi.images/system/mkosi.finalize +@@ -0,0 +1,4 @@ ++#!/bin/sh ++# SPDX-License-Identifier: LGPL-2.1-or-later ++ ++cp --archive --recursive --no-target-directory --reflink=auto "$BUILDROOT"/etc "$BUILDROOT"/usr/share/factory/mkosi +diff --git a/mkosi.images/system/mkosi.postinst.chroot b/mkosi.images/system/mkosi.postinst.chroot +new file mode 100755 +index 0000000000..692242da38 +--- /dev/null ++++ b/mkosi.images/system/mkosi.postinst.chroot +@@ -0,0 +1,102 @@ ++#!/bin/sh ++# SPDX-License-Identifier: LGPL-2.1-or-later ++set -e ++ ++if [ "$1" = "build" ]; then ++ exit 0 ++fi ++ ++if [ -n "$SANITIZERS" ]; then ++ LD_PRELOAD=$(ldd /usr/lib/systemd/systemd | grep libasan.so | awk '{print $3}') ++ ++ mkdir -p /etc/systemd/system.conf.d ++ ++ cat >/etc/systemd/system.conf.d/10-asan.conf </etc/systemd/system/systemd-journald.service.d/10-stdout-tty.conf </etc/systemd/system/console-getty.service.d/10-no-vhangup.conf < 50s when built with sanitizers so let's not run it by default. ++ systemctl mask systemd-hwdb-update.service ++fi ++ ++if [ -n "$IMAGE_ID" ] ; then ++ sed -n \ ++ -i \ ++ -e '/^IMAGE_ID=/!p' \ ++ -e "\$aIMAGE_ID=$IMAGE_ID" \ ++ /usr/lib/os-release ++fi ++ ++if [ -n "$IMAGE_VERSION" ] ; then ++ sed -n \ ++ -i \ ++ -e '/^IMAGE_VERSION=/!p' \ ++ -e "\$aIMAGE_VERSION=$IMAGE_VERSION" \ ++ /usr/lib/os-release ++fi ++ ++if command -v authselect >/dev/null; then ++ # authselect 1.5.0 renamed the minimal profile to the local profile without keeping backwards compat so ++ # let's use the new name if it exists. ++ if [ -d /usr/share/authselect/default/local ]; then ++ PROFILE=local ++ else ++ PROFILE=minimal ++ fi ++ ++ authselect select "$PROFILE" ++ ++ if authselect list-features "$PROFILE" | grep -q "with-homed"; then ++ authselect enable-feature with-homed ++ fi ++fi ++ ++# Let tmpfiles.d/systemd-resolve.conf handle the symlink. /etc/resolv.conf might be mounted over so undo that ++# if that's the case. ++mountpoint -q /etc/resolv.conf && umount /etc/resolv.conf ++rm -f /etc/resolv.conf ++ ++. /usr/lib/os-release ++ ++if [ "$ID" = "centos" ] && [ "$VERSION" = "8" ]; then ++ alternatives --install /usr/bin/python3 python3 /usr/bin/python3.9 1 ++ alternatives --set python3 /usr/bin/python3.9 ++fi ++ ++mkdir -p /usr/lib/sysusers.d ++cat >/usr/lib/sysusers.d/testuser.conf </usr/lib/tmpfiles.d/testuser.conf < /dev/null && [ -d "/efi" ]; then +- bootctl install +- fi +- +- cat >> /root/.gdbinit < 50s when built with sanitizers so let's not run it by default. +- systemctl mask systemd-hwdb-update.service +- fi +- +- # Make sure dnsmasq.service doesn't start on boot on Debian/Ubuntu. +- rm -f /etc/systemd/system/multi-user.target.wants/dnsmasq.service +-fi +- +-# Temporary workaround until https://github.com/openSUSE/suse-module-tools/commit/158643414ddb8d8208016a5f03a4484d58944d7a +-# gets into OpenSUSE repos +-if [ "$1" = "final" ] && grep -q openSUSE /etc/os-release; then +- if [ -e "/usr/lib/systemd/system/boot-sysctl.service" ] && \ +- ! grep -F -q 'ConditionPathExists=/boot/sysctl.conf' "/usr/lib/systemd/system/boot-sysctl.service"; then +- mkdir -p "/etc/systemd/system/boot-sysctl.service.d/" +- printf '[Unit]\nConditionPathExists=/boot/sysctl.conf-%%v' >"/etc/systemd/system/boot-sysctl.service.d/99-temporary-workaround.conf" +- fi +-fi diff --git a/0759-test-Skip-various-tests-when-sys-is-not-mounted.patch b/0759-test-Skip-various-tests-when-sys-is-not-mounted.patch new file mode 100644 index 0000000..7ff9b64 --- /dev/null +++ b/0759-test-Skip-various-tests-when-sys-is-not-mounted.patch @@ -0,0 +1,335 @@ +From 7b2bb541eba2795e0db1bfedd4b1fa64a6e28a55 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Tue, 19 Dec 2023 16:03:06 +0100 +Subject: [PATCH] test: Skip various tests when /sys is not mounted + +When running tests in a container, /sys might not be mounted, so +let's make sure we skip tests that depend on /sys in this case. + +(cherry picked from commit a412a1b92ab234a57c646f6779471772b2c355ec) + +Related: RHEL-27512 +--- + src/libsystemd/sd-bus/test-bus-creds.c | 2 +- + src/libsystemd/sd-device/test-sd-device-monitor.c | 4 ++++ + src/libsystemd/sd-device/test-sd-device-thread.c | 3 +++ + src/libsystemd/sd-device/test-sd-device.c | 10 +++++++++- + src/libsystemd/sd-login/test-login.c | 4 ++++ + src/libudev/test-udev-device-thread.c | 7 ++++++- + src/shared/tests.c | 3 ++- + src/test/meson.build | 4 ++-- + src/test/test-cgroup-util.c | 4 ++-- + src/test/test-cgroup.c | 4 ++-- + src/test/test-condition.c | 8 ++++---- + src/test/test-mountpoint-util.c | 8 ++++---- + src/test/test-udev-util.c | 4 ++++ + src/test/test-watch-pid.c | 2 +- + src/udev/test-udev-event.c | 4 ++++ + 15 files changed, 52 insertions(+), 19 deletions(-) + +diff --git a/src/libsystemd/sd-bus/test-bus-creds.c b/src/libsystemd/sd-bus/test-bus-creds.c +index 13801becc9..d18ce88a25 100644 +--- a/src/libsystemd/sd-bus/test-bus-creds.c ++++ b/src/libsystemd/sd-bus/test-bus-creds.c +@@ -12,7 +12,7 @@ int main(int argc, char *argv[]) { + + test_setup_logging(LOG_DEBUG); + +- if (cg_unified() == -ENOMEDIUM) ++ if (IN_SET(cg_unified(), -ENOMEDIUM, -ENOENT)) + return log_tests_skipped("/sys/fs/cgroup/ not available"); + + r = sd_bus_creds_new_from_pid(&creds, 0, _SD_BUS_CREDS_ALL); +diff --git a/src/libsystemd/sd-device/test-sd-device-monitor.c b/src/libsystemd/sd-device/test-sd-device-monitor.c +index 9e64ba01c6..a9a002b5ae 100644 +--- a/src/libsystemd/sd-device/test-sd-device-monitor.c ++++ b/src/libsystemd/sd-device/test-sd-device-monitor.c +@@ -10,6 +10,7 @@ + #include "device-private.h" + #include "device-util.h" + #include "macro.h" ++#include "mountpoint-util.h" + #include "path-util.h" + #include "stat-util.h" + #include "string-util.h" +@@ -302,6 +303,9 @@ int main(int argc, char *argv[]) { + if (getuid() != 0) + return log_tests_skipped("not root"); + ++ if (path_is_mount_point("/sys", NULL, 0) <= 0) ++ return log_tests_skipped("/sys is not mounted"); ++ + if (path_is_read_only_fs("/sys") > 0) + return log_tests_skipped("Running in container"); + +diff --git a/src/libsystemd/sd-device/test-sd-device-thread.c b/src/libsystemd/sd-device/test-sd-device-thread.c +index 644f3c2aee..bf3cd5ce25 100644 +--- a/src/libsystemd/sd-device/test-sd-device-thread.c ++++ b/src/libsystemd/sd-device/test-sd-device-thread.c +@@ -8,6 +8,7 @@ + #include "sd-device.h" + + #include "device-util.h" ++#include "tests.h" + + #define handle_error_errno(error, msg) \ + ({ \ +@@ -31,6 +32,8 @@ int main(int argc, char *argv[]) { + int r; + + r = sd_device_new_from_syspath(&loopback, "/sys/class/net/lo"); ++ if (r == -ENODEV) ++ return log_tests_skipped("Loopback device not found"); + if (r < 0) + return handle_error_errno(r, "Failed to create loopback device object"); + +diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c +index a1bcf18059..237681eab8 100644 +--- a/src/libsystemd/sd-device/test-sd-device.c ++++ b/src/libsystemd/sd-device/test-sd-device.c +@@ -11,6 +11,7 @@ + #include "errno-util.h" + #include "fd-util.h" + #include "hashmap.h" ++#include "mountpoint-util.h" + #include "nulstr-util.h" + #include "path-util.h" + #include "rm-rf.h" +@@ -656,4 +657,11 @@ TEST(devname_from_devnum) { + } + } + +-DEFINE_TEST_MAIN(LOG_INFO); ++static int intro(void) { ++ if (path_is_mount_point("/sys", NULL, 0) <= 0) ++ return log_tests_skipped("/sys is not mounted"); ++ ++ return EXIT_SUCCESS; ++} ++ ++DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro); +diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c +index f7cef6e304..84fcfab4a0 100644 +--- a/src/libsystemd/sd-login/test-login.c ++++ b/src/libsystemd/sd-login/test-login.c +@@ -9,6 +9,7 @@ + #include "fd-util.h" + #include "format-util.h" + #include "log.h" ++#include "mountpoint-util.h" + #include "string-util.h" + #include "strv.h" + #include "tests.h" +@@ -295,6 +296,9 @@ TEST(monitor) { + } + + static int intro(void) { ++ if (IN_SET(cg_unified(), -ENOENT, -ENOMEDIUM)) ++ return log_tests_skipped("cgroupfs is not mounted"); ++ + log_info("/* Information printed is from the live system */"); + return EXIT_SUCCESS; + } +diff --git a/src/libudev/test-udev-device-thread.c b/src/libudev/test-udev-device-thread.c +index c082fdca46..fdf0818863 100644 +--- a/src/libudev/test-udev-device-thread.c ++++ b/src/libudev/test-udev-device-thread.c +@@ -6,6 +6,7 @@ + #include + + #include "libudev.h" ++#include "tests.h" + + #define handle_error_errno(error, msg) \ + ({ \ +@@ -29,8 +30,12 @@ int main(int argc, char *argv[]) { + int r; + + loopback = udev_device_new_from_syspath(NULL, "/sys/class/net/lo"); +- if (!loopback) ++ if (!loopback) { ++ if (errno == ENODEV) ++ return log_tests_skipped_errno(errno, "Loopback device not found"); ++ + return handle_error_errno(errno, "Failed to create loopback device object"); ++ } + + entry = udev_device_get_properties_list_entry(loopback); + udev_list_entry_foreach(e, entry) +diff --git a/src/shared/tests.c b/src/shared/tests.c +index a65080cbf4..a4deb7b0d5 100644 +--- a/src/shared/tests.c ++++ b/src/shared/tests.c +@@ -28,6 +28,7 @@ + #include "fd-util.h" + #include "fs-util.h" + #include "log.h" ++#include "mountpoint-util.h" + #include "namespace-util.h" + #include "path-util.h" + #include "process-util.h" +@@ -285,7 +286,7 @@ static int enter_cgroup(char **ret_cgroup, bool enter_subroot) { + log_warning_errno(r, "Couldn't allocate a scope unit for this test, proceeding without."); + + r = cg_pid_get_path(NULL, 0, &cgroup_root); +- if (r == -ENOMEDIUM) ++ if (IN_SET(r, -ENOMEDIUM, -ENOENT)) + return log_warning_errno(r, "cg_pid_get_path(NULL, 0, ...) failed: %m"); + assert(r >= 0); + +diff --git a/src/test/meson.build b/src/test/meson.build +index 1d61dc343f..5547271ee7 100644 +--- a/src/test/meson.build ++++ b/src/test/meson.build +@@ -701,11 +701,11 @@ tests += [ + libsystemd_static]], + + [files('../libsystemd/sd-device/test-sd-device-thread.c'), +- [libsystemd], ++ [libbasic, libshared_static, libsystemd_static], + [threads]], + + [files('../libudev/test-udev-device-thread.c'), +- [libudev], ++ [libbasic, libshared_static, libsystemd_static, libudev], + [threads]], + ] + +diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c +index 7113b07a95..c6439e2fbb 100644 +--- a/src/test/test-cgroup-util.c ++++ b/src/test/test-cgroup-util.c +@@ -334,7 +334,7 @@ TEST(cg_tests) { + int all, hybrid, systemd, r; + + r = cg_unified(); +- if (r == -ENOMEDIUM) { ++ if (IN_SET(r, -ENOENT, -ENOMEDIUM)) { + log_tests_skipped("cgroup not mounted"); + return; + } +@@ -367,7 +367,7 @@ TEST(cg_get_keyed_attribute) { + int i, r; + + r = cg_get_keyed_attribute("cpu", "/init.scope", "no_such_file", STRV_MAKE("no_such_attr"), &val); +- if (r == -ENOMEDIUM || ERRNO_IS_PRIVILEGE(r)) { ++ if (IN_SET(r, -ENOMEDIUM, -ENOENT) || ERRNO_IS_PRIVILEGE(r)) { + log_info_errno(r, "Skipping most of %s, /sys/fs/cgroup not accessible: %m", __func__); + return; + } +diff --git a/src/test/test-cgroup.c b/src/test/test-cgroup.c +index 7341e5b022..a3d286a669 100644 +--- a/src/test/test-cgroup.c ++++ b/src/test/test-cgroup.c +@@ -44,8 +44,8 @@ TEST(cg_create) { + int r; + + r = cg_unified_cached(false); +- if (r == -ENOMEDIUM) { +- log_tests_skipped("cgroup not mounted"); ++ if (IN_SET(r, -ENOMEDIUM, -ENOENT)) { ++ log_tests_skipped("cgroupfs is not mounted"); + return; + } + assert_se(r >= 0); +diff --git a/src/test/test-condition.c b/src/test/test-condition.c +index 4cd23d8e21..57e7d35119 100644 +--- a/src/test/test-condition.c ++++ b/src/test/test-condition.c +@@ -138,8 +138,8 @@ TEST(condition_test_control_group_hierarchy) { + int r; + + r = cg_unified(); +- if (r == -ENOMEDIUM) { +- log_tests_skipped("cgroup not mounted"); ++ if (IN_SET(r, -ENOMEDIUM, -ENOENT)) { ++ log_tests_skipped("cgroupfs is not mounted"); + return; + } + assert_se(r >= 0); +@@ -162,8 +162,8 @@ TEST(condition_test_control_group_controller) { + int r; + + r = cg_unified(); +- if (r == -ENOMEDIUM) { +- log_tests_skipped("cgroup not mounted"); ++ if (IN_SET(r, -ENOMEDIUM, -ENOENT)) { ++ log_tests_skipped("cgroupfs is not mounted"); + return; + } + assert_se(r >= 0); +diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c +index 391e1c97ba..8555c5a7db 100644 +--- a/src/test/test-mountpoint-util.c ++++ b/src/test/test-mountpoint-util.c +@@ -138,10 +138,10 @@ TEST(path_is_mount_point) { + assert_se(path_is_mount_point("/proc/1/", NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point("/proc/1/", NULL, 0) == 0); + +- assert_se(path_is_mount_point("/sys", NULL, AT_SYMLINK_FOLLOW) > 0); +- assert_se(path_is_mount_point("/sys", NULL, 0) > 0); +- assert_se(path_is_mount_point("/sys/", NULL, AT_SYMLINK_FOLLOW) > 0); +- assert_se(path_is_mount_point("/sys/", NULL, 0) > 0); ++ assert_se(path_is_mount_point("/dev", NULL, AT_SYMLINK_FOLLOW) > 0); ++ assert_se(path_is_mount_point("/dev", NULL, 0) > 0); ++ assert_se(path_is_mount_point("/dev/", NULL, AT_SYMLINK_FOLLOW) > 0); ++ assert_se(path_is_mount_point("/dev/", NULL, 0) > 0); + + /* we'll create a hierarchy of different kinds of dir/file/link + * layouts: +diff --git a/src/test/test-udev-util.c b/src/test/test-udev-util.c +index 1db2dad4ff..ee089939fd 100644 +--- a/src/test/test-udev-util.c ++++ b/src/test/test-udev-util.c +@@ -4,6 +4,7 @@ + #include + + #include "macro.h" ++#include "mountpoint-util.h" + #include "string-util.h" + #include "tests.h" + #include "udev-util.h" +@@ -137,6 +138,9 @@ static void test_udev_resolve_subsys_kernel_one(const char *str, bool read_value + } + + TEST(udev_resolve_subsys_kernel) { ++ if (path_is_mount_point("/sys", NULL, 0) <= 0) ++ return (void) log_tests_skipped("/sys is not mounted"); ++ + test_udev_resolve_subsys_kernel_one("hoge", false, -EINVAL, NULL); + test_udev_resolve_subsys_kernel_one("[hoge", false, -EINVAL, NULL); + test_udev_resolve_subsys_kernel_one("[hoge/foo", false, -EINVAL, NULL); +diff --git a/src/test/test-watch-pid.c b/src/test/test-watch-pid.c +index 8c355c1d5f..34291fb539 100644 +--- a/src/test/test-watch-pid.c ++++ b/src/test/test-watch-pid.c +@@ -17,7 +17,7 @@ int main(int argc, char *argv[]) { + if (getuid() != 0) + return log_tests_skipped("not root"); + r = enter_cgroup_subroot(NULL); +- if (r == -ENOMEDIUM) ++ if (r < 0) + return log_tests_skipped("cgroupfs not available"); + + _cleanup_free_ char *unit_dir = NULL; +diff --git a/src/udev/test-udev-event.c b/src/udev/test-udev-event.c +index b6b2c91b2e..92cab2f354 100644 +--- a/src/udev/test-udev-event.c ++++ b/src/udev/test-udev-event.c +@@ -1,5 +1,6 @@ + /* SPDX-License-Identifier: LGPL-2.1-or-later */ + ++#include "mountpoint-util.h" + #include "path-util.h" + #include "signal-util.h" + #include "strv.h" +@@ -80,6 +81,9 @@ static void test2(void) { + int main(int argc, char *argv[]) { + _cleanup_free_ char *self = NULL; + ++ if (path_is_mount_point("/sys", NULL, 0) <= 0) ++ return log_tests_skipped("/sys is not mounted"); ++ + if (argc > 1) { + if (streq(argv[1], "test1")) + test1(); diff --git a/0760-string-util-introduce-ascii_ishex.patch b/0760-string-util-introduce-ascii_ishex.patch new file mode 100644 index 0000000..e16ce5a --- /dev/null +++ b/0760-string-util-introduce-ascii_ishex.patch @@ -0,0 +1,27 @@ +From 2241ee9563bbcb8bf729547926133619d4baa0cd Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 8 Dec 2022 14:13:47 +0900 +Subject: [PATCH] string-util: introduce ascii_ishex() + +(cherry picked from commit 0ce8870f19a839c7b09b4ef5b61c2d363050c7d9) + +Related: RHEL-27512 +--- + src/fundamental/string-util-fundamental.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/fundamental/string-util-fundamental.h b/src/fundamental/string-util-fundamental.h +index 523c612a17..c35ce5b88f 100644 +--- a/src/fundamental/string-util-fundamental.h ++++ b/src/fundamental/string-util-fundamental.h +@@ -110,6 +110,10 @@ static inline bool ascii_isdigit(sd_char a) { + return a >= '0' && a <= '9'; + } + ++static inline bool ascii_ishex(sd_char a) { ++ return ascii_isdigit(a) || (a >= 'a' && a <= 'f') || (a >= 'A' && a <= 'F'); ++} ++ + static inline bool ascii_isalpha(sd_char a) { + /* A pure ASCII, locale independent version of isalpha() */ + return (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z'); diff --git a/0761-sd-id128-several-cleanups.patch b/0761-sd-id128-several-cleanups.patch new file mode 100644 index 0000000..3a5ecb5 --- /dev/null +++ b/0761-sd-id128-several-cleanups.patch @@ -0,0 +1,207 @@ +From 961b82ca7bd6a14fb564a63ae37c6c2af0d87d89 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 8 Dec 2022 14:20:03 +0900 +Subject: [PATCH] sd-id128: several cleanups + +- use SD_ID128_STRING_MAX or friend, +- use sizeof(sd_id128_t), +- use newly introduced ascii_ishex(). + +(cherry picked from commit 28bf2de201e890193b57accbf736c7d3d82d813a) + +Related: RHEL-27512 +--- + src/libsystemd/sd-id128/id128-util.c | 58 ++++++++++------------------ + src/libsystemd/sd-id128/sd-id128.c | 21 +++++----- + 2 files changed, 33 insertions(+), 46 deletions(-) + +diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c +index cef340f3bc..2ec77bb9f3 100644 +--- a/src/libsystemd/sd-id128/id128-util.c ++++ b/src/libsystemd/sd-id128/id128-util.c +@@ -13,50 +13,35 @@ + #include "sync-util.h" + + bool id128_is_valid(const char *s) { +- size_t i, l; ++ size_t l; + + assert(s); + + l = strlen(s); +- if (l == 32) { + ++ if (l == SD_ID128_STRING_MAX - 1) + /* Plain formatted 128bit hex string */ ++ return in_charset(s, HEXDIGITS); + +- for (i = 0; i < l; i++) { +- char c = s[i]; +- +- if (!ascii_isdigit(c) && +- !(c >= 'a' && c <= 'f') && +- !(c >= 'A' && c <= 'F')) +- return false; +- } +- +- } else if (l == 36) { +- ++ if (l == SD_ID128_UUID_STRING_MAX - 1) { + /* Formatted UUID */ +- +- for (i = 0; i < l; i++) { ++ for (size_t i = 0; i < l; i++) { + char c = s[i]; + + if (IN_SET(i, 8, 13, 18, 23)) { + if (c != '-') + return false; +- } else { +- if (!ascii_isdigit(c) && +- !(c >= 'a' && c <= 'f') && +- !(c >= 'A' && c <= 'F')) +- return false; +- } ++ } else if (!ascii_ishex(c)) ++ return false; + } ++ return true; ++ } + +- } else +- return false; +- +- return true; ++ return false; + } + + int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { +- char buffer[36 + 2]; ++ char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */ + ssize_t l; + + assert(fd >= 0); +@@ -80,28 +65,28 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { + /* Treat an "uninitialized" id file like an empty one */ + return f == ID128_PLAIN_OR_UNINIT && strneq(buffer, "uninitialized\n", l) ? -ENOMEDIUM : -EINVAL; + +- case 33: /* plain UUID with trailing newline */ +- if (buffer[32] != '\n') ++ case SD_ID128_STRING_MAX: /* plain UUID with trailing newline */ ++ if (buffer[SD_ID128_STRING_MAX-1] != '\n') + return -EINVAL; + + _fallthrough_; +- case 32: /* plain UUID without trailing newline */ ++ case SD_ID128_STRING_MAX-1: /* plain UUID without trailing newline */ + if (f == ID128_UUID) + return -EINVAL; + +- buffer[32] = 0; ++ buffer[SD_ID128_STRING_MAX-1] = 0; + break; + +- case 37: /* RFC UUID with trailing newline */ +- if (buffer[36] != '\n') ++ case SD_ID128_UUID_STRING_MAX: /* RFC UUID with trailing newline */ ++ if (buffer[SD_ID128_UUID_STRING_MAX-1] != '\n') + return -EINVAL; + + _fallthrough_; +- case 36: /* RFC UUID without trailing newline */ ++ case SD_ID128_UUID_STRING_MAX-1: /* RFC UUID without trailing newline */ + if (IN_SET(f, ID128_PLAIN, ID128_PLAIN_OR_UNINIT)) + return -EINVAL; + +- buffer[36] = 0; ++ buffer[SD_ID128_UUID_STRING_MAX-1] = 0; + break; + + default: +@@ -122,7 +107,7 @@ int id128_read(const char *p, Id128Format f, sd_id128_t *ret) { + } + + int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) { +- char buffer[36 + 2]; ++ char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */ + size_t sz; + int r; + +@@ -131,14 +116,13 @@ int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) { + + if (f != ID128_UUID) { + assert_se(sd_id128_to_string(id, buffer)); +- buffer[SD_ID128_STRING_MAX - 1] = '\n'; + sz = SD_ID128_STRING_MAX; + } else { + assert_se(sd_id128_to_uuid_string(id, buffer)); +- buffer[SD_ID128_UUID_STRING_MAX - 1] = '\n'; + sz = SD_ID128_UUID_STRING_MAX; + } + ++ buffer[sz - 1] = '\n'; + r = loop_write(fd, buffer, sz, false); + if (r < 0) + return r; +diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c +index 709c8ffb57..07a13be2b2 100644 +--- a/src/libsystemd/sd-id128/sd-id128.c ++++ b/src/libsystemd/sd-id128/sd-id128.c +@@ -19,14 +19,17 @@ + #include "util.h" + + _public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) { ++ size_t k = 0; ++ + assert_return(s, NULL); + +- for (size_t n = 0; n < 16; n++) { +- s[n*2] = hexchar(id.bytes[n] >> 4); +- s[n*2+1] = hexchar(id.bytes[n] & 0xF); ++ for (size_t n = 0; n < sizeof(sd_id128_t); n++) { ++ s[k++] = hexchar(id.bytes[n] >> 4); ++ s[k++] = hexchar(id.bytes[n] & 0xF); + } + +- s[SD_ID128_STRING_MAX-1] = 0; ++ assert(k == SD_ID128_STRING_MAX - 1); ++ s[k] = 0; + + return s; + } +@@ -38,7 +41,7 @@ _public_ char *sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD + + /* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */ + +- for (size_t n = 0; n < 16; n++) { ++ for (size_t n = 0; n < sizeof(sd_id128_t); n++) { + + if (IN_SET(n, 4, 6, 8, 10)) + s[k++] = '-'; +@@ -53,14 +56,14 @@ _public_ char *sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD + return s; + } + +-_public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) { +- unsigned n, i; ++_public_ int sd_id128_from_string(const char *s, sd_id128_t *ret) { ++ size_t n, i; + sd_id128_t t; + bool is_guid = false; + + assert_return(s, -EINVAL); + +- for (n = 0, i = 0; n < 16;) { ++ for (n = 0, i = 0; n < sizeof(sd_id128_t);) { + int a, b; + + if (s[i] == '-') { +@@ -90,7 +93,7 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) { + t.bytes[n++] = (a << 4) | b; + } + +- if (i != (is_guid ? 36 : 32)) ++ if (i != (is_guid ? SD_ID128_UUID_STRING_MAX : SD_ID128_STRING_MAX) - 1) + return -EINVAL; + + if (s[i] != 0) diff --git a/0762-sd-id128-make-id128_read-or-friends-return-ENOPKG-wh.patch b/0762-sd-id128-make-id128_read-or-friends-return-ENOPKG-wh.patch new file mode 100644 index 0000000..fbbed75 --- /dev/null +++ b/0762-sd-id128-make-id128_read-or-friends-return-ENOPKG-wh.patch @@ -0,0 +1,468 @@ +From 0cb518ec9b1860e553cf539304310a573494743a Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 8 Dec 2022 14:30:31 +0900 +Subject: [PATCH] sd-id128: make id128_read() or friends return -ENOPKG when + the file contents is "uninitialized" + +Then, this drops ID128_PLAIN_OR_UNINIT. Also, this renames +Id128Format -> Id128FormatFlag, and make it bitfield. + +Fixes #25634. + +(cherry picked from commit 057bf780e9d45480fbacdd3b060dbe37b37f9693) + +Related: RHEL-27512 +--- + src/boot/bootctl.c | 2 +- + src/libsystemd/sd-id128/id128-util.c | 35 +++++++++++--------- + src/libsystemd/sd-id128/id128-util.h | 27 ++++++--------- + src/libsystemd/sd-id128/sd-id128.c | 4 +-- + src/libsystemd/sd-journal/journal-file.c | 2 +- + src/machine-id-setup/machine-id-setup-main.c | 2 +- + src/nspawn/nspawn.c | 6 ++-- + src/partition/repart.c | 4 +-- + src/shared/discover-image.c | 2 +- + src/shared/machine-id-setup.c | 12 +++---- + src/shared/specifier.c | 2 +- + src/test/test-condition.c | 2 +- + src/test/test-fs-util.c | 2 +- + src/test/test-id128.c | 26 +++++++-------- + 14 files changed, 63 insertions(+), 65 deletions(-) + +diff --git a/src/boot/bootctl.c b/src/boot/bootctl.c +index 00e8eda992..dc4dc0d391 100644 +--- a/src/boot/bootctl.c ++++ b/src/boot/bootctl.c +@@ -182,7 +182,7 @@ static int load_etc_machine_id(void) { + int r; + + r = sd_id128_get_machine(&arg_machine_id); +- if (IN_SET(r, -ENOENT, -ENOMEDIUM)) /* Not set or empty */ ++ if (IN_SET(r, -ENOENT, -ENOMEDIUM, -ENOPKG)) /* Not set or empty */ + return 0; + if (r < 0) + return log_error_errno(r, "Failed to get machine-id: %m"); +diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c +index 2ec77bb9f3..9b0ad48e6b 100644 +--- a/src/libsystemd/sd-id128/id128-util.c ++++ b/src/libsystemd/sd-id128/id128-util.c +@@ -40,17 +40,21 @@ bool id128_is_valid(const char *s) { + return false; + } + +-int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { ++int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) { + char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */ + ssize_t l; + + assert(fd >= 0); +- assert(f < _ID128_FORMAT_MAX); + + /* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both + * optionally followed by a newline and nothing else. ID files should really be newline terminated, but if they + * aren't that's OK too, following the rule of "Be conservative in what you send, be liberal in what you +- * accept". */ ++ * accept". ++ * ++ * This returns the following: ++ * -ENOMEDIUM: an empty string, ++ * -ENOPKG: "uninitialized" or "uninitialized\n", ++ * -EINVAL: other invalid strings. */ + + l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */ + if (l < 0) +@@ -60,10 +64,9 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { + + switch (l) { + +- case 13: +- case 14: +- /* Treat an "uninitialized" id file like an empty one */ +- return f == ID128_PLAIN_OR_UNINIT && strneq(buffer, "uninitialized\n", l) ? -ENOMEDIUM : -EINVAL; ++ case STRLEN("uninitialized"): ++ case STRLEN("uninitialized\n"): ++ return strneq(buffer, "uninitialized\n", l) ? -ENOPKG : -EINVAL; + + case SD_ID128_STRING_MAX: /* plain UUID with trailing newline */ + if (buffer[SD_ID128_STRING_MAX-1] != '\n') +@@ -71,7 +74,7 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { + + _fallthrough_; + case SD_ID128_STRING_MAX-1: /* plain UUID without trailing newline */ +- if (f == ID128_UUID) ++ if (!FLAGS_SET(f, ID128_FORMAT_PLAIN)) + return -EINVAL; + + buffer[SD_ID128_STRING_MAX-1] = 0; +@@ -83,7 +86,7 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { + + _fallthrough_; + case SD_ID128_UUID_STRING_MAX-1: /* RFC UUID without trailing newline */ +- if (IN_SET(f, ID128_PLAIN, ID128_PLAIN_OR_UNINIT)) ++ if (!FLAGS_SET(f, ID128_FORMAT_UUID)) + return -EINVAL; + + buffer[SD_ID128_UUID_STRING_MAX-1] = 0; +@@ -96,7 +99,7 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { + return sd_id128_from_string(buffer, ret); + } + +-int id128_read(const char *p, Id128Format f, sd_id128_t *ret) { ++int id128_read(const char *p, Id128FormatFlag f, sd_id128_t *ret) { + _cleanup_close_ int fd = -1; + + fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY); +@@ -106,15 +109,15 @@ int id128_read(const char *p, Id128Format f, sd_id128_t *ret) { + return id128_read_fd(fd, f, ret); + } + +-int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) { ++int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id, bool do_sync) { + char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */ + size_t sz; + int r; + + assert(fd >= 0); +- assert(f < _ID128_FORMAT_MAX); ++ assert(IN_SET((f & ID128_FORMAT_ANY), ID128_FORMAT_PLAIN, ID128_FORMAT_UUID)); + +- if (f != ID128_UUID) { ++ if (FLAGS_SET(f, ID128_FORMAT_PLAIN)) { + assert_se(sd_id128_to_string(id, buffer)); + sz = SD_ID128_STRING_MAX; + } else { +@@ -136,7 +139,7 @@ int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) { + return 0; + } + +-int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) { ++int id128_write(const char *p, Id128FormatFlag f, sd_id128_t id, bool do_sync) { + _cleanup_close_ int fd = -1; + + fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, 0444); +@@ -179,9 +182,9 @@ int id128_get_product(sd_id128_t *ret) { + /* Reads the systems product UUID from DMI or devicetree (where it is located on POWER). This is + * particularly relevant in VM environments, where VM managers typically place a VM uuid there. */ + +- r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &uuid); ++ r = id128_read("/sys/class/dmi/id/product_uuid", ID128_FORMAT_UUID, &uuid); + if (r == -ENOENT) +- r = id128_read("/proc/device-tree/vm,uuid", ID128_UUID, &uuid); ++ r = id128_read("/proc/device-tree/vm,uuid", ID128_FORMAT_UUID, &uuid); + if (r < 0) + return r; + +diff --git a/src/libsystemd/sd-id128/id128-util.h b/src/libsystemd/sd-id128/id128-util.h +index 9d8fe93641..d031c680f1 100644 +--- a/src/libsystemd/sd-id128/id128-util.h ++++ b/src/libsystemd/sd-id128/id128-util.h +@@ -10,22 +10,17 @@ + + bool id128_is_valid(const char *s) _pure_; + +-typedef enum Id128Format { +- ID128_ANY, +- ID128_PLAIN, /* formatted as 32 hex chars as-is */ +- ID128_PLAIN_OR_UNINIT, /* formatted as 32 hex chars as-is; allow special "uninitialized" +- * value when reading from file (id128_read() and id128_read_fd()). +- * +- * This format should be used when reading a machine-id file. */ +- ID128_UUID, /* formatted as 36 character uuid string */ +- _ID128_FORMAT_MAX, +-} Id128Format; +- +-int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret); +-int id128_read(const char *p, Id128Format f, sd_id128_t *ret); +- +-int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync); +-int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync); ++typedef enum Id128FormatFlag { ++ ID128_FORMAT_PLAIN = 1 << 0, /* formatted as 32 hex chars as-is */ ++ ID128_FORMAT_UUID = 1 << 1, /* formatted as 36 character uuid string */ ++ ID128_FORMAT_ANY = ID128_FORMAT_PLAIN | ID128_FORMAT_UUID, ++} Id128FormatFlag; ++ ++int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret); ++int id128_read(const char *p, Id128FormatFlag f, sd_id128_t *ret); ++ ++int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id, bool do_sync); ++int id128_write(const char *p, Id128FormatFlag f, sd_id128_t id, bool do_sync); + + void id128_hash_func(const sd_id128_t *p, struct siphash *state); + int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) _pure_; +diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c +index 07a13be2b2..5e9ec2b5f6 100644 +--- a/src/libsystemd/sd-id128/sd-id128.c ++++ b/src/libsystemd/sd-id128/sd-id128.c +@@ -127,7 +127,7 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { + assert_return(ret, -EINVAL); + + if (sd_id128_is_null(saved_machine_id)) { +- r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id); ++ r = id128_read("/etc/machine-id", ID128_FORMAT_PLAIN, &saved_machine_id); + if (r < 0) + return r; + +@@ -146,7 +146,7 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) { + assert_return(ret, -EINVAL); + + if (sd_id128_is_null(saved_boot_id)) { +- r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id); ++ r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID, &saved_boot_id); + if (r < 0) + return r; + } +diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c +index 3c1385ddb0..2b66b3caed 100644 +--- a/src/libsystemd/sd-journal/journal-file.c ++++ b/src/libsystemd/sd-journal/journal-file.c +@@ -421,7 +421,7 @@ static int journal_file_refresh_header(JournalFile *f) { + assert(f->header); + + r = sd_id128_get_machine(&f->header->machine_id); +- if (IN_SET(r, -ENOENT, -ENOMEDIUM)) ++ if (IN_SET(r, -ENOENT, -ENOMEDIUM, -ENOPKG)) + /* We don't have a machine-id, let's continue without */ + zero(f->header->machine_id); + else if (r < 0) +diff --git a/src/machine-id-setup/machine-id-setup-main.c b/src/machine-id-setup/machine-id-setup-main.c +index 8a3b1efb4c..b595b2ab37 100644 +--- a/src/machine-id-setup/machine-id-setup-main.c ++++ b/src/machine-id-setup/machine-id-setup-main.c +@@ -164,7 +164,7 @@ static int run(int argc, char *argv[]) { + return r; + + etc_machine_id = prefix_roota(arg_root, "/etc/machine-id"); +- r = id128_read(etc_machine_id, ID128_PLAIN, &id); ++ r = id128_read(etc_machine_id, ID128_FORMAT_PLAIN, &id); + if (r < 0) + return log_error_errno(r, "Failed to read machine ID back: %m"); + } else { +diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c +index df7b37ec4e..085f817dd3 100644 +--- a/src/nspawn/nspawn.c ++++ b/src/nspawn/nspawn.c +@@ -2195,7 +2195,7 @@ static int setup_boot_id(void) { + if (r < 0) + return log_error_errno(r, "Failed to generate random boot id: %m"); + +- r = id128_write(path, ID128_UUID, rnd, false); ++ r = id128_write(path, ID128_FORMAT_UUID, rnd, false); + if (r < 0) + return log_error_errno(r, "Failed to write boot id: %m"); + +@@ -2821,9 +2821,9 @@ static int setup_machine_id(const char *directory) { + + etc_machine_id = prefix_roota(directory, "/etc/machine-id"); + +- r = id128_read(etc_machine_id, ID128_PLAIN_OR_UNINIT, &id); ++ r = id128_read(etc_machine_id, ID128_FORMAT_PLAIN, &id); + if (r < 0) { +- if (!IN_SET(r, -ENOENT, -ENOMEDIUM)) /* If the file is missing or empty, we don't mind */ ++ if (!IN_SET(r, -ENOENT, -ENOMEDIUM, -ENOPKG)) /* If the file is missing, empty, or uninitialized, we don't mind */ + return log_error_errno(r, "Failed to read machine ID from container image: %m"); + + if (sd_id128_is_null(arg_uuid)) { +diff --git a/src/partition/repart.c b/src/partition/repart.c +index 2b3b384743..553d92e730 100644 +--- a/src/partition/repart.c ++++ b/src/partition/repart.c +@@ -4515,8 +4515,8 @@ static int context_read_seed(Context *context, const char *root) { + else if (fd < 0) + return log_error_errno(fd, "Failed to determine machine ID of image: %m"); + else { +- r = id128_read_fd(fd, ID128_PLAIN_OR_UNINIT, &context->seed); +- if (r == -ENOMEDIUM) ++ r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &context->seed); ++ if (IN_SET(r, -ENOMEDIUM, -ENOPKG)) + log_info("No machine ID set, using randomized partition UUIDs."); + else if (r < 0) + return log_error_errno(r, "Failed to parse machine ID of image: %m"); +diff --git a/src/shared/discover-image.c b/src/shared/discover-image.c +index 0488e215fd..75a42efe88 100644 +--- a/src/shared/discover-image.c ++++ b/src/shared/discover-image.c +@@ -1153,7 +1153,7 @@ int image_read_metadata(Image *i) { + if (fd < 0) + log_debug_errno(errno, "Failed to open %s: %m", path); + else { +- r = id128_read_fd(fd, ID128_PLAIN, &machine_id); ++ r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &machine_id); + if (r < 0) + log_debug_errno(r, "Image %s contains invalid machine ID.", i->name); + } +diff --git a/src/shared/machine-id-setup.c b/src/shared/machine-id-setup.c +index df4ac419cb..787c0765d0 100644 +--- a/src/shared/machine-id-setup.c ++++ b/src/shared/machine-id-setup.c +@@ -38,7 +38,7 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) { + dbus_machine_id = prefix_roota(root, "/var/lib/dbus/machine-id"); + fd = open(dbus_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd >= 0) { +- if (id128_read_fd(fd, ID128_PLAIN, ret) >= 0) { ++ if (id128_read_fd(fd, ID128_FORMAT_PLAIN, ret) >= 0) { + log_info("Initializing machine ID from D-Bus machine ID."); + return 0; + } +@@ -123,7 +123,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_ + if (sd_id128_is_null(machine_id)) { + + /* Try to read any existing machine ID */ +- if (id128_read_fd(fd, ID128_PLAIN, ret) >= 0) ++ if (id128_read_fd(fd, ID128_FORMAT_PLAIN, ret) >= 0) + return 0; + + /* Hmm, so, the id currently stored is not useful, then let's generate one */ +@@ -152,7 +152,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_ + if (r < 0) + return log_error_errno(r, "Failed to sync %s: %m", etc_machine_id); + } else { +- r = id128_write_fd(fd, ID128_PLAIN, machine_id, true); ++ r = id128_write_fd(fd, ID128_FORMAT_PLAIN, machine_id, true); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_machine_id); + else +@@ -168,7 +168,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_ + run_machine_id = prefix_roota(root, "/run/machine-id"); + + RUN_WITH_UMASK(0022) +- r = id128_write(run_machine_id, ID128_PLAIN, machine_id, false); ++ r = id128_write(run_machine_id, ID128_FORMAT_PLAIN, machine_id, false); + if (r < 0) { + (void) unlink(run_machine_id); + return log_error_errno(r, "Cannot write %s: %m", run_machine_id); +@@ -240,7 +240,7 @@ int machine_id_commit(const char *root) { + "%s is not on a temporary file system.", + etc_machine_id); + +- r = id128_read_fd(fd, ID128_PLAIN, &id); ++ r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &id); + if (r < 0) + return log_error_errno(r, "We didn't find a valid machine ID in %s: %m", etc_machine_id); + +@@ -261,7 +261,7 @@ int machine_id_commit(const char *root) { + return r; + + /* Update a persistent version of etc_machine_id */ +- r = id128_write(etc_machine_id, ID128_PLAIN, id, true); ++ r = id128_write(etc_machine_id, ID128_FORMAT_PLAIN, id, true); + if (r < 0) + return log_error_errno(r, "Cannot write %s. This is mandatory to get a persistent machine ID: %m", etc_machine_id); + +diff --git a/src/shared/specifier.c b/src/shared/specifier.c +index d54ab9f5a9..cd651768bd 100644 +--- a/src/shared/specifier.c ++++ b/src/shared/specifier.c +@@ -195,7 +195,7 @@ int specifier_machine_id(char specifier, const void *data, const char *root, con + /* Translate error for missing os-release file to EUNATCH. */ + return fd == -ENOENT ? -EUNATCH : fd; + +- r = id128_read_fd(fd, ID128_PLAIN, &id); ++ r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &id); + } else + r = sd_id128_get_machine(&id); + if (r < 0) +diff --git a/src/test/test-condition.c b/src/test/test-condition.c +index 57e7d35119..b16e8047c6 100644 +--- a/src/test/test-condition.c ++++ b/src/test/test-condition.c +@@ -250,7 +250,7 @@ TEST(condition_test_host) { + int r; + + r = sd_id128_get_machine(&id); +- if (IN_SET(r, -ENOENT, -ENOMEDIUM)) ++ if (IN_SET(r, -ENOENT, -ENOMEDIUM, -ENOPKG)) + return (void) log_tests_skipped("/etc/machine-id missing"); + assert_se(r >= 0); + +diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c +index 16f04d6889..0b1f11ebdf 100644 +--- a/src/test/test-fs-util.c ++++ b/src/test/test-fs-util.c +@@ -302,7 +302,7 @@ TEST(chase_symlinks) { + assert_se(fd >= 0); + safe_close(pfd); + +- assert_se(id128_read_fd(fd, ID128_PLAIN, &a) >= 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &a) >= 0); + assert_se(sd_id128_get_machine(&b) >= 0); + assert_se(sd_id128_equal(a, b)); + } +diff --git a/src/test/test-id128.c b/src/test/test-id128.c +index 4b71c5c00b..4175ac7b60 100644 +--- a/src/test/test-id128.c ++++ b/src/test/test-id128.c +@@ -86,17 +86,17 @@ TEST(id128) { + + /* First, write as UUID */ + assert_se(sd_id128_randomize(&id) >= 0); +- assert_se(id128_write_fd(fd, ID128_UUID, id, false) >= 0); ++ assert_se(id128_write_fd(fd, ID128_FORMAT_UUID, id, false) >= 0); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EINVAL); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + /* Second, write as plain */ +@@ -104,17 +104,17 @@ TEST(id128) { + assert_se(ftruncate(fd, 0) >= 0); + + assert_se(sd_id128_randomize(&id) >= 0); +- assert_se(id128_write_fd(fd, ID128_PLAIN, id, false) >= 0); ++ assert_se(id128_write_fd(fd, ID128_FORMAT_PLAIN, id, false) >= 0); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EINVAL); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + /* Third, write plain without trailing newline */ +@@ -125,13 +125,13 @@ TEST(id128) { + assert_se(write(fd, sd_id128_to_string(id, t), 32) == 32); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EINVAL); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + +- /* Third, write UUID without trailing newline */ ++ /* Fourth, write UUID without trailing newline */ + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(ftruncate(fd, 0) >= 0); + +@@ -139,10 +139,10 @@ TEST(id128) { + assert_se(write(fd, sd_id128_to_uuid_string(id, q), 36) == 36); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EINVAL); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + + if (sd_booted() > 0 && access("/etc/machine-id", F_OK) >= 0) { diff --git a/0763-test-add-tests-for-uninitialized-string-handling-by-.patch b/0763-test-add-tests-for-uninitialized-string-handling-by-.patch new file mode 100644 index 0000000..f5310b8 --- /dev/null +++ b/0763-test-add-tests-for-uninitialized-string-handling-by-.patch @@ -0,0 +1,49 @@ +From 845d23e9b10edfbd3ba28a81acf3871c4566c23b Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 8 Dec 2022 15:18:28 +0900 +Subject: [PATCH] test: add tests for "uninitialized" string handling by + id128_read_fd() + +(cherry picked from commit 66c7949e08a977a9d0c32dcfadef0bb843956b8d) + +Related: RHEL-27512 +--- + src/test/test-id128.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/src/test/test-id128.c b/src/test/test-id128.c +index 4175ac7b60..dccf3b7fb9 100644 +--- a/src/test/test-id128.c ++++ b/src/test/test-id128.c +@@ -145,6 +145,31 @@ TEST(id128) { + assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); + ++ /* Fifth, tests for "uninitialized" */ ++ assert_se(lseek(fd, 0, SEEK_SET) == 0); ++ assert_se(ftruncate(fd, 0) >= 0); ++ assert_se(write(fd, "uninitialized", STRLEN("uninitialized")) == STRLEN("uninitialized")); ++ assert_se(lseek(fd, 0, SEEK_SET) == 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -ENOPKG); ++ ++ assert_se(lseek(fd, 0, SEEK_SET) == 0); ++ assert_se(ftruncate(fd, 0) >= 0); ++ assert_se(write(fd, "uninitialized\n", STRLEN("uninitialized\n")) == STRLEN("uninitialized\n")); ++ assert_se(lseek(fd, 0, SEEK_SET) == 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -ENOPKG); ++ ++ assert_se(lseek(fd, 0, SEEK_SET) == 0); ++ assert_se(ftruncate(fd, 0) >= 0); ++ assert_se(write(fd, "uninitialized\nfoo", STRLEN("uninitialized\nfoo")) == STRLEN("uninitialized\nfoo")); ++ assert_se(lseek(fd, 0, SEEK_SET) == 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EINVAL); ++ ++ assert_se(lseek(fd, 0, SEEK_SET) == 0); ++ assert_se(ftruncate(fd, 0) >= 0); ++ assert_se(write(fd, "uninit", STRLEN("uninit")) == STRLEN("uninit")); ++ assert_se(lseek(fd, 0, SEEK_SET) == 0); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EINVAL); ++ + if (sd_booted() > 0 && access("/etc/machine-id", F_OK) >= 0) { + assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0); + assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0); diff --git a/0764-man-mention-sd_id128_get_machine-or-friend-may-retur.patch b/0764-man-mention-sd_id128_get_machine-or-friend-may-retur.patch new file mode 100644 index 0000000..556b361 --- /dev/null +++ b/0764-man-mention-sd_id128_get_machine-or-friend-may-retur.patch @@ -0,0 +1,32 @@ +From 1d0f2f8d806758a70e8fc81536e0cf54649f1bf5 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 8 Dec 2022 15:43:26 +0900 +Subject: [PATCH] man: mention sd_id128_get_machine() or friend may return + -ENOPKG + +(cherry picked from commit a237c6e0b0b294cebc084891a84173a19eb69172) + +Related: RHEL-27512 +--- + man/sd_id128_get_machine.xml | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml +index a778f8a2b0..8bc76b686b 100644 +--- a/man/sd_id128_get_machine.xml ++++ b/man/sd_id128_get_machine.xml +@@ -144,6 +144,14 @@ + empty or all zeros. + + ++ ++ -ENOPKG ++ ++ Returned by sd_id128_get_machine() and ++ sd_id128_get_machine_app_specific() when the content of ++ /etc/machine-id is uninitialized. ++ ++ + + -ENXIO + diff --git a/0765-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch b/0765-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch new file mode 100644 index 0000000..0d3d286 --- /dev/null +++ b/0765-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch @@ -0,0 +1,27 @@ +From 5e97c9d10934b54dfb93a4d236dd3a9c92840f26 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 8 Dec 2022 15:48:25 +0900 +Subject: [PATCH] sd-id128: make sd_id128_get_boot() and friend return + -ENOMEDIUM + +(cherry picked from commit 9be90c401e16cf04a9cea0b19fdefa7d0a47f056) + +Related: RHEL-27512 +--- + src/libsystemd/sd-id128/sd-id128.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c +index 5e9ec2b5f6..bff8074f19 100644 +--- a/src/libsystemd/sd-id128/sd-id128.c ++++ b/src/libsystemd/sd-id128/sd-id128.c +@@ -149,6 +149,9 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) { + r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID, &saved_boot_id); + if (r < 0) + return r; ++ ++ if (sd_id128_is_null(saved_boot_id)) ++ return -ENOMEDIUM; + } + + *ret = saved_boot_id; diff --git a/0766-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch b/0766-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch new file mode 100644 index 0000000..e9141ed --- /dev/null +++ b/0766-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch @@ -0,0 +1,34 @@ +From 44d5561daff4ffa94e394e18c41001244bc170dc Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 12 Dec 2022 22:03:52 +0900 +Subject: [PATCH] sd-id128: make sd_id128_get_boot() and friend return -ENOSYS + when /proc/ is not mounted + +(cherry picked from commit e2720340e9fdf3aee2e8998dc72798de50be3630) + +Related: RHEL-27512 +--- + src/libsystemd/sd-id128/sd-id128.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c +index bff8074f19..b3f4728988 100644 +--- a/src/libsystemd/sd-id128/sd-id128.c ++++ b/src/libsystemd/sd-id128/sd-id128.c +@@ -15,6 +15,7 @@ + #include "macro.h" + #include "missing_syscall.h" + #include "random-util.h" ++#include "stat-util.h" + #include "user-util.h" + #include "util.h" + +@@ -147,6 +148,8 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) { + + if (sd_id128_is_null(saved_boot_id)) { + r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID, &saved_boot_id); ++ if (r == -ENOENT && proc_mounted() == 0) ++ return -ENOSYS; + if (r < 0) + return r; + diff --git a/0767-man-mention-that-sd_id128_get_boot-and-friend-may-re.patch b/0767-man-mention-that-sd_id128_get_boot-and-friend-may-re.patch new file mode 100644 index 0000000..c6c362a --- /dev/null +++ b/0767-man-mention-that-sd_id128_get_boot-and-friend-may-re.patch @@ -0,0 +1,63 @@ +From 66c103ed26f623a54318a6f4fa48f895fb6efab8 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 8 Dec 2022 15:49:02 +0900 +Subject: [PATCH] man: mention that sd_id128_get_boot() and friend may return + -ENOSYS + +And drop to mention sd_id128_get_boot_app_specific() may return -ENOENT +or -ENOMEDIUM. The function does not read /etc/machine-id. But reads a +file in the procfs, which is a kind of the kernel API. Hence the +failures are caused only when the system has wrong setup. + +(cherry picked from commit c576920e673114529c5bfe5ea29891a24a443338) + +Related: RHEL-27512 +--- + man/sd_id128_get_machine.xml | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml +index 8bc76b686b..dbc6d4885d 100644 +--- a/man/sd_id128_get_machine.xml ++++ b/man/sd_id128_get_machine.xml +@@ -129,19 +129,17 @@ + + -ENOENT + +- Returned by sd_id128_get_machine(), +- sd_id128_get_machine_app_specific(), and +- sd_id128_get_boot_app_specific() when /etc/machine-id is +- missing. ++ Returned by sd_id128_get_machine() and ++ sd_id128_get_machine_app_specific() when /etc/machine-id ++ is missing. + + + + -ENOMEDIUM + +- Returned by sd_id128_get_machine(), +- sd_id128_get_machine_app_specific(), and +- sd_id128_get_boot_app_specific() when /etc/machine-id is +- empty or all zeros. ++ Returned by sd_id128_get_machine() and ++ sd_id128_get_machine_app_specific() when /etc/machine-id ++ is empty or all zeros. + + + +@@ -152,6 +150,14 @@ + /etc/machine-id is uninitialized. + + ++ ++ -ENOSYS ++ ++ Returned by sd_id128_get_boot() and ++ sd_id128_get_boot_app_specific() when /proc/ is not ++ mounted. ++ ++ + + -ENXIO + diff --git a/0768-sd-id128-fold-do_sync-flag-into-Id128FormatFlag.patch b/0768-sd-id128-fold-do_sync-flag-into-Id128FormatFlag.patch new file mode 100644 index 0000000..063df07 --- /dev/null +++ b/0768-sd-id128-fold-do_sync-flag-into-Id128FormatFlag.patch @@ -0,0 +1,143 @@ +From 77085bae51bcfaaa0ef356bca93e9aa883a43a89 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 9 Dec 2022 05:37:12 +0900 +Subject: [PATCH] sd-id128: fold do_sync flag into Id128FormatFlag + +(cherry picked from commit b40c8ebdc86b61df03207865b5a75cd37900ea4c) + +Related: RHEL-27512 +--- + src/libsystemd/sd-id128/id128-util.c | 8 ++++---- + src/libsystemd/sd-id128/id128-util.h | 6 ++++-- + src/nspawn/nspawn.c | 2 +- + src/shared/machine-id-setup.c | 6 +++--- + src/test/test-id128.c | 4 ++-- + 5 files changed, 14 insertions(+), 12 deletions(-) + +diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c +index 9b0ad48e6b..faacc55960 100644 +--- a/src/libsystemd/sd-id128/id128-util.c ++++ b/src/libsystemd/sd-id128/id128-util.c +@@ -109,7 +109,7 @@ int id128_read(const char *p, Id128FormatFlag f, sd_id128_t *ret) { + return id128_read_fd(fd, f, ret); + } + +-int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id, bool do_sync) { ++int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id) { + char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */ + size_t sz; + int r; +@@ -130,7 +130,7 @@ int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id, bool do_sync) { + if (r < 0) + return r; + +- if (do_sync) { ++ if (FLAGS_SET(f, ID128_SYNC_ON_WRITE)) { + r = fsync_full(fd); + if (r < 0) + return r; +@@ -139,14 +139,14 @@ int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id, bool do_sync) { + return 0; + } + +-int id128_write(const char *p, Id128FormatFlag f, sd_id128_t id, bool do_sync) { ++int id128_write(const char *p, Id128FormatFlag f, sd_id128_t id) { + _cleanup_close_ int fd = -1; + + fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, 0444); + if (fd < 0) + return -errno; + +- return id128_write_fd(fd, f, id, do_sync); ++ return id128_write_fd(fd, f, id); + } + + void id128_hash_func(const sd_id128_t *p, struct siphash *state) { +diff --git a/src/libsystemd/sd-id128/id128-util.h b/src/libsystemd/sd-id128/id128-util.h +index d031c680f1..887f443d69 100644 +--- a/src/libsystemd/sd-id128/id128-util.h ++++ b/src/libsystemd/sd-id128/id128-util.h +@@ -14,13 +14,15 @@ typedef enum Id128FormatFlag { + ID128_FORMAT_PLAIN = 1 << 0, /* formatted as 32 hex chars as-is */ + ID128_FORMAT_UUID = 1 << 1, /* formatted as 36 character uuid string */ + ID128_FORMAT_ANY = ID128_FORMAT_PLAIN | ID128_FORMAT_UUID, ++ ++ ID128_SYNC_ON_WRITE = 1 << 2, /* Sync the file after write. Used only when writing an ID. */ + } Id128FormatFlag; + + int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret); + int id128_read(const char *p, Id128FormatFlag f, sd_id128_t *ret); + +-int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id, bool do_sync); +-int id128_write(const char *p, Id128FormatFlag f, sd_id128_t id, bool do_sync); ++int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id); ++int id128_write(const char *p, Id128FormatFlag f, sd_id128_t id); + + void id128_hash_func(const sd_id128_t *p, struct siphash *state); + int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) _pure_; +diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c +index 085f817dd3..db45968cd3 100644 +--- a/src/nspawn/nspawn.c ++++ b/src/nspawn/nspawn.c +@@ -2195,7 +2195,7 @@ static int setup_boot_id(void) { + if (r < 0) + return log_error_errno(r, "Failed to generate random boot id: %m"); + +- r = id128_write(path, ID128_FORMAT_UUID, rnd, false); ++ r = id128_write(path, ID128_FORMAT_UUID, rnd); + if (r < 0) + return log_error_errno(r, "Failed to write boot id: %m"); + +diff --git a/src/shared/machine-id-setup.c b/src/shared/machine-id-setup.c +index 787c0765d0..f82a292ea3 100644 +--- a/src/shared/machine-id-setup.c ++++ b/src/shared/machine-id-setup.c +@@ -152,7 +152,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_ + if (r < 0) + return log_error_errno(r, "Failed to sync %s: %m", etc_machine_id); + } else { +- r = id128_write_fd(fd, ID128_FORMAT_PLAIN, machine_id, true); ++ r = id128_write_fd(fd, ID128_FORMAT_PLAIN | ID128_SYNC_ON_WRITE, machine_id); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_machine_id); + else +@@ -168,7 +168,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_ + run_machine_id = prefix_roota(root, "/run/machine-id"); + + RUN_WITH_UMASK(0022) +- r = id128_write(run_machine_id, ID128_FORMAT_PLAIN, machine_id, false); ++ r = id128_write(run_machine_id, ID128_FORMAT_PLAIN, machine_id); + if (r < 0) { + (void) unlink(run_machine_id); + return log_error_errno(r, "Cannot write %s: %m", run_machine_id); +@@ -261,7 +261,7 @@ int machine_id_commit(const char *root) { + return r; + + /* Update a persistent version of etc_machine_id */ +- r = id128_write(etc_machine_id, ID128_FORMAT_PLAIN, id, true); ++ r = id128_write(etc_machine_id, ID128_FORMAT_PLAIN | ID128_SYNC_ON_WRITE, id); + if (r < 0) + return log_error_errno(r, "Cannot write %s. This is mandatory to get a persistent machine ID: %m", etc_machine_id); + +diff --git a/src/test/test-id128.c b/src/test/test-id128.c +index dccf3b7fb9..6de0cec426 100644 +--- a/src/test/test-id128.c ++++ b/src/test/test-id128.c +@@ -86,7 +86,7 @@ TEST(id128) { + + /* First, write as UUID */ + assert_se(sd_id128_randomize(&id) >= 0); +- assert_se(id128_write_fd(fd, ID128_FORMAT_UUID, id, false) >= 0); ++ assert_se(id128_write_fd(fd, ID128_FORMAT_UUID, id) >= 0); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EINVAL); +@@ -104,7 +104,7 @@ TEST(id128) { + assert_se(ftruncate(fd, 0) >= 0); + + assert_se(sd_id128_randomize(&id) >= 0); +- assert_se(id128_write_fd(fd, ID128_FORMAT_PLAIN, id, false) >= 0); ++ assert_se(id128_write_fd(fd, ID128_FORMAT_PLAIN, id) >= 0); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EINVAL); diff --git a/0769-sd-id128-make-sd_id128_get_machine-or-friends-return.patch b/0769-sd-id128-make-sd_id128_get_machine-or-friends-return.patch new file mode 100644 index 0000000..ccf6bac --- /dev/null +++ b/0769-sd-id128-make-sd_id128_get_machine-or-friends-return.patch @@ -0,0 +1,229 @@ +From db28b72d475c4e9bbd14286c9ca9366e339dfa28 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 14 Dec 2022 14:31:09 +0900 +Subject: [PATCH] sd-id128: make sd_id128_get_machine() or friends return + -EUCLEAN when an ID is in an invalid format + +EINVAL suggests that the caller passes an invalid argument. EIO is +for "input/output error", i.e. the error you'd get if the disk or +file system is borked, and this error code could be returned by the +underlying read/write functions. + +Let's make the functions return an unambiguous error code. + +(cherry picked from commit e8a6625422db9d5598b6d640a9f4eec68921ce3d) + +Related: RHEL-27512 +--- + man/sd_id128_get_machine.xml | 2 +- + src/libsystemd/sd-id128/id128-util.c | 16 +++++++++------- + src/libsystemd/sd-id128/sd-id128.c | 18 ++++++++++-------- + src/test/test-id128.c | 12 ++++++------ + 4 files changed, 26 insertions(+), 22 deletions(-) + +diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml +index dbc6d4885d..4f6926fd7d 100644 +--- a/man/sd_id128_get_machine.xml ++++ b/man/sd_id128_get_machine.xml +@@ -166,7 +166,7 @@ + + + +- -EIO ++ -EUCLEAN + + Returned by any of the functions described here when the configured value has + invalid format. +diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c +index faacc55960..364df6a9c8 100644 +--- a/src/libsystemd/sd-id128/id128-util.c ++++ b/src/libsystemd/sd-id128/id128-util.c +@@ -43,6 +43,7 @@ bool id128_is_valid(const char *s) { + int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) { + char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */ + ssize_t l; ++ int r; + + assert(fd >= 0); + +@@ -54,7 +55,7 @@ int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) { + * This returns the following: + * -ENOMEDIUM: an empty string, + * -ENOPKG: "uninitialized" or "uninitialized\n", +- * -EINVAL: other invalid strings. */ ++ * -EUCLEAN: other invalid strings. */ + + l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */ + if (l < 0) +@@ -70,33 +71,34 @@ int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) { + + case SD_ID128_STRING_MAX: /* plain UUID with trailing newline */ + if (buffer[SD_ID128_STRING_MAX-1] != '\n') +- return -EINVAL; ++ return -EUCLEAN; + + _fallthrough_; + case SD_ID128_STRING_MAX-1: /* plain UUID without trailing newline */ + if (!FLAGS_SET(f, ID128_FORMAT_PLAIN)) +- return -EINVAL; ++ return -EUCLEAN; + + buffer[SD_ID128_STRING_MAX-1] = 0; + break; + + case SD_ID128_UUID_STRING_MAX: /* RFC UUID with trailing newline */ + if (buffer[SD_ID128_UUID_STRING_MAX-1] != '\n') +- return -EINVAL; ++ return -EUCLEAN; + + _fallthrough_; + case SD_ID128_UUID_STRING_MAX-1: /* RFC UUID without trailing newline */ + if (!FLAGS_SET(f, ID128_FORMAT_UUID)) +- return -EINVAL; ++ return -EUCLEAN; + + buffer[SD_ID128_UUID_STRING_MAX-1] = 0; + break; + + default: +- return -EINVAL; ++ return -EUCLEAN; + } + +- return sd_id128_from_string(buffer, ret); ++ r = sd_id128_from_string(buffer, ret); ++ return r == -EINVAL ? -EUCLEAN : r; + } + + int id128_read(const char *p, Id128FormatFlag f, sd_id128_t *ret) { +diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c +index b3f4728988..b2f0438edf 100644 +--- a/src/libsystemd/sd-id128/sd-id128.c ++++ b/src/libsystemd/sd-id128/sd-id128.c +@@ -207,22 +207,22 @@ static int get_invocation_from_keyring(sd_id128_t *ret) { + /* Chop off the final description string */ + d = strrchr(description, ';'); + if (!d) +- return -EIO; ++ return -EUCLEAN; + *d = 0; + + /* Look for the permissions */ + p = strrchr(description, ';'); + if (!p) +- return -EIO; ++ return -EUCLEAN; + + errno = 0; + perms = strtoul(p + 1, &e, 16); + if (errno > 0) + return -errno; + if (e == p + 1) /* Read at least one character */ +- return -EIO; ++ return -EUCLEAN; + if (e != d) /* Must reached the end */ +- return -EIO; ++ return -EUCLEAN; + + if ((perms & ~MAX_PERMS) != 0) + return -EPERM; +@@ -232,7 +232,7 @@ static int get_invocation_from_keyring(sd_id128_t *ret) { + /* Look for the group ID */ + g = strrchr(description, ';'); + if (!g) +- return -EIO; ++ return -EUCLEAN; + r = parse_gid(g + 1, &gid); + if (r < 0) + return r; +@@ -243,7 +243,7 @@ static int get_invocation_from_keyring(sd_id128_t *ret) { + /* Look for the user ID */ + u = strrchr(description, ';'); + if (!u) +- return -EIO; ++ return -EUCLEAN; + r = parse_uid(u + 1, &uid); + if (r < 0) + return r; +@@ -254,13 +254,14 @@ static int get_invocation_from_keyring(sd_id128_t *ret) { + if (c < 0) + return -errno; + if (c != sizeof(sd_id128_t)) +- return -EIO; ++ return -EUCLEAN; + + return 0; + } + + static int get_invocation_from_environment(sd_id128_t *ret) { + const char *e; ++ int r; + + assert(ret); + +@@ -268,7 +269,8 @@ static int get_invocation_from_environment(sd_id128_t *ret) { + if (!e) + return -ENXIO; + +- return sd_id128_from_string(e, ret); ++ r = sd_id128_from_string(e, ret); ++ return r == -EINVAL ? -EUCLEAN : r; + } + + _public_ int sd_id128_get_invocation(sd_id128_t *ret) { +diff --git a/src/test/test-id128.c b/src/test/test-id128.c +index 6de0cec426..b7a9b03403 100644 +--- a/src/test/test-id128.c ++++ b/src/test/test-id128.c +@@ -89,7 +89,7 @@ TEST(id128) { + assert_se(id128_write_fd(fd, ID128_FORMAT_UUID, id) >= 0); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EUCLEAN); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) >= 0); +@@ -107,7 +107,7 @@ TEST(id128) { + assert_se(id128_write_fd(fd, ID128_FORMAT_PLAIN, id) >= 0); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EUCLEAN); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) >= 0); +@@ -125,7 +125,7 @@ TEST(id128) { + assert_se(write(fd, sd_id128_to_string(id, t), 32) == 32); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EUCLEAN); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) >= 0); +@@ -139,7 +139,7 @@ TEST(id128) { + assert_se(write(fd, sd_id128_to_uuid_string(id, q), 36) == 36); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EUCLEAN); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) >= 0); +@@ -162,13 +162,13 @@ TEST(id128) { + assert_se(ftruncate(fd, 0) >= 0); + assert_se(write(fd, "uninitialized\nfoo", STRLEN("uninitialized\nfoo")) == STRLEN("uninitialized\nfoo")); + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EUCLEAN); + + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(ftruncate(fd, 0) >= 0); + assert_se(write(fd, "uninit", STRLEN("uninit")) == STRLEN("uninit")); + assert_se(lseek(fd, 0, SEEK_SET) == 0); +- assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EINVAL); ++ assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EUCLEAN); + + if (sd_booted() > 0 && access("/etc/machine-id", F_OK) >= 0) { + assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0); diff --git a/0770-sd-id128-allow-sd_id128_get_machine-and-friend-to-be.patch b/0770-sd-id128-allow-sd_id128_get_machine-and-friend-to-be.patch new file mode 100644 index 0000000..5b3490a --- /dev/null +++ b/0770-sd-id128-allow-sd_id128_get_machine-and-friend-to-be.patch @@ -0,0 +1,90 @@ +From 4af87f4d0643fa243aa1fd8e5c52cc5d4fbdd187 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 14 Dec 2022 13:34:15 +0900 +Subject: [PATCH] sd-id128: allow sd_id128_get_machine() and friend to be + called with NULL + +It may be useful to check if the machine ID or friends is set or not. + +(cherry picked from commit 786b652c8989834f9218ec82b2d824d5b753fad3) + +Related: RHEL-27512 +--- + src/libsystemd/sd-id128/sd-id128.c | 28 ++++++++++------------------ + 1 file changed, 10 insertions(+), 18 deletions(-) + +diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c +index b2f0438edf..dee0df2396 100644 +--- a/src/libsystemd/sd-id128/sd-id128.c ++++ b/src/libsystemd/sd-id128/sd-id128.c +@@ -125,8 +125,6 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { + static thread_local sd_id128_t saved_machine_id = {}; + int r; + +- assert_return(ret, -EINVAL); +- + if (sd_id128_is_null(saved_machine_id)) { + r = id128_read("/etc/machine-id", ID128_FORMAT_PLAIN, &saved_machine_id); + if (r < 0) +@@ -136,7 +134,8 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) { + return -ENOMEDIUM; + } + +- *ret = saved_machine_id; ++ if (ret) ++ *ret = saved_machine_id; + return 0; + } + +@@ -144,8 +143,6 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) { + static thread_local sd_id128_t saved_boot_id = {}; + int r; + +- assert_return(ret, -EINVAL); +- + if (sd_id128_is_null(saved_boot_id)) { + r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID, &saved_boot_id); + if (r == -ENOENT && proc_mounted() == 0) +@@ -157,7 +154,8 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) { + return -ENOMEDIUM; + } + +- *ret = saved_boot_id; ++ if (ret) ++ *ret = saved_boot_id; + return 0; + } + +@@ -277,26 +275,20 @@ _public_ int sd_id128_get_invocation(sd_id128_t *ret) { + static thread_local sd_id128_t saved_invocation_id = {}; + int r; + +- assert_return(ret, -EINVAL); +- + if (sd_id128_is_null(saved_invocation_id)) { + /* We first check the environment. The environment variable is primarily relevant for user + * services, and sufficiently safe as long as no privilege boundary is involved. */ + r = get_invocation_from_environment(&saved_invocation_id); +- if (r >= 0) { +- *ret = saved_invocation_id; +- return 0; +- } else if (r != -ENXIO) +- return r; +- +- /* The kernel keyring is relevant for system services (as for user services we don't store +- * the invocation ID in the keyring, as there'd be no trust benefit in that). */ +- r = get_invocation_from_keyring(&saved_invocation_id); ++ if (r == -ENXIO) ++ /* The kernel keyring is relevant for system services (as for user services we don't ++ * store the invocation ID in the keyring, as there'd be no trust benefit in that). */ ++ r = get_invocation_from_keyring(&saved_invocation_id); + if (r < 0) + return r; + } + +- *ret = saved_invocation_id; ++ if (ret) ++ *ret = saved_invocation_id; + return 0; + } + diff --git a/0771-sd-id128-also-refuse-an-empty-invocation-ID.patch b/0771-sd-id128-also-refuse-an-empty-invocation-ID.patch new file mode 100644 index 0000000..7ff72b3 --- /dev/null +++ b/0771-sd-id128-also-refuse-an-empty-invocation-ID.patch @@ -0,0 +1,41 @@ +From e9054375028335ef1e2946b80d9765f8e69cbb9c Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 14 Dec 2022 13:40:42 +0900 +Subject: [PATCH] sd-id128: also refuse an empty invocation ID + +(cherry picked from commit 75fa1f25c08a4b5dc2180893718473be9e4f6bab) + +Related: RHEL-27512 +--- + man/sd_id128_get_machine.xml | 3 ++- + src/libsystemd/sd-id128/sd-id128.c | 3 +++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml +index 4f6926fd7d..075caffb2b 100644 +--- a/man/sd_id128_get_machine.xml ++++ b/man/sd_id128_get_machine.xml +@@ -139,7 +139,8 @@ + + Returned by sd_id128_get_machine() and + sd_id128_get_machine_app_specific() when /etc/machine-id +- is empty or all zeros. ++ is empty or all zeros. Also returned by sd_id128_get_invocation() when the ++ invocation ID is all zeros. + + + +diff --git a/src/libsystemd/sd-id128/sd-id128.c b/src/libsystemd/sd-id128/sd-id128.c +index dee0df2396..ec53617fce 100644 +--- a/src/libsystemd/sd-id128/sd-id128.c ++++ b/src/libsystemd/sd-id128/sd-id128.c +@@ -285,6 +285,9 @@ _public_ int sd_id128_get_invocation(sd_id128_t *ret) { + r = get_invocation_from_keyring(&saved_invocation_id); + if (r < 0) + return r; ++ ++ if (sd_id128_is_null(saved_invocation_id)) ++ return -ENOMEDIUM; + } + + if (ret) diff --git a/0772-man-update-documents-for-sd_id128_get_invocation.patch b/0772-man-update-documents-for-sd_id128_get_invocation.patch new file mode 100644 index 0000000..f099168 --- /dev/null +++ b/0772-man-update-documents-for-sd_id128_get_invocation.patch @@ -0,0 +1,41 @@ +From 6715fc716fc843c3877160a8220af935c159e789 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 14 Dec 2022 14:29:25 +0900 +Subject: [PATCH] man: update documents for sd_id128_get_invocation() + +(cherry picked from commit f0d8358c245b4d0012d8db52dbf42bdebbe1b2bc) + +Related: RHEL-27512 +--- + man/sd_id128_get_machine.xml | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/man/sd_id128_get_machine.xml b/man/sd_id128_get_machine.xml +index 075caffb2b..cdab87ab63 100644 +--- a/man/sd_id128_get_machine.xml ++++ b/man/sd_id128_get_machine.xml +@@ -94,10 +94,20 @@ + has properties similar to the machine ID during that time. + + sd_id128_get_invocation() returns the invocation ID of the currently executed +- service. In its current implementation, this reads and parses the $INVOCATION_ID environment +- variable that the service manager sets when activating a service, see +- systemd.exec5 for details. The +- ID is cached internally. In future a different mechanism to determine the invocation ID may be added. ++ service. In its current implementation, this tries to read and parse the following: ++ ++ ++ The $INVOCATION_ID environment variable that the service manager sets when ++ activating a service. ++ ++ ++ An entry in the kernel keyring that the system service manager sets when activating a service. ++ ++ ++ ++ See systemd.exec5 ++ for details. The ID is cached internally. In future a different mechanism to determine the invocation ID ++ may be added. + + Note that sd_id128_get_machine_app_specific(), + sd_id128_get_boot(), sd_id128_get_boot_app_specific(), and diff --git a/0773-test-id128-simplify-machine-id-check.patch b/0773-test-id128-simplify-machine-id-check.patch new file mode 100644 index 0000000..3c2f8f0 --- /dev/null +++ b/0773-test-id128-simplify-machine-id-check.patch @@ -0,0 +1,48 @@ +From b54eb7dbdad4135fdcf846f6087ca29b6164b60b Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 27 Feb 2024 16:03:10 +0100 +Subject: [PATCH] test-id128: simplify machine-id check + +This also ensures that the test is skipped when /etc/machine-id exists, +but is not initialized. + +(cherry picked from commit 415eb50570744daf2257fc6fc96e2d5750532785) + +Related: RHEL-27512 +--- + src/test/test-id128.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/test/test-id128.c b/src/test/test-id128.c +index b7a9b03403..afdbf1e4b9 100644 +--- a/src/test/test-id128.c ++++ b/src/test/test-id128.c +@@ -38,7 +38,7 @@ TEST(id128) { + assert_se(!sd_id128_in_set(id, ID128_WALDI)); + assert_se(!sd_id128_in_set(id, ID128_WALDI, ID128_WALDI)); + +- if (sd_booted() > 0 && access("/etc/machine-id", F_OK) >= 0) { ++ if (sd_booted() > 0 && sd_id128_get_machine(NULL) >= 0) { + assert_se(sd_id128_get_machine(&id) == 0); + printf("machine: %s\n", sd_id128_to_string(id, t)); + +@@ -170,7 +170,7 @@ TEST(id128) { + assert_se(lseek(fd, 0, SEEK_SET) == 0); + assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EUCLEAN); + +- if (sd_booted() > 0 && access("/etc/machine-id", F_OK) >= 0) { ++ if (sd_booted() > 0 && sd_id128_get_machine(NULL) >= 0) { + assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0); + assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0); + assert_se(sd_id128_equal(id, id2)); +@@ -195,8 +195,8 @@ TEST(benchmark_sd_id128_get_machine_app_specific) { + unsigned iterations = slow_tests_enabled() ? 1000000 : 1000; + usec_t t, q; + +- if (access("/etc/machine-id", F_OK) < 0 && errno == ENOENT) +- return (void) log_tests_skipped("/etc/machine-id does not exist"); ++ if (sd_id128_get_machine(NULL) < 0) ++ return (void) log_tests_skipped("/etc/machine-id is not initialized"); + + log_info("/* %s (%u iterations) */", __func__, iterations); + diff --git a/0774-test-fs-util-skip-part-of-test_chase_symlinks-if-mac.patch b/0774-test-fs-util-skip-part-of-test_chase_symlinks-if-mac.patch new file mode 100644 index 0000000..d40ec91 --- /dev/null +++ b/0774-test-fs-util-skip-part-of-test_chase_symlinks-if-mac.patch @@ -0,0 +1,30 @@ +From 70754f42db910937021c74f85adba277c7db88a9 Mon Sep 17 00:00:00 2001 +From: Nick Rosbrook +Date: Mon, 12 Dec 2022 14:37:52 -0500 +Subject: [PATCH] test-fs-util: skip part of test_chase_symlinks if machine-id + is not initialized + +The part of test_chase_symlink in test-fs-util that calls +sd_id128_get_machine will fail if /etc/machine-id is empty, so skip this +block if the machine-id is not initialized. + +(cherry picked from commit 079fcdd04f57bfb1e333fea853e050c99eb16e02) + +Related: RHEL-27512 +--- + src/test/test-fs-util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c +index 0b1f11ebdf..ff248c1a9c 100644 +--- a/src/test/test-fs-util.c ++++ b/src/test/test-fs-util.c +@@ -292,7 +292,7 @@ TEST(chase_symlinks) { + assert_se(symlink("/usr/../etc/./machine-id", p) >= 0); + + r = chase_symlinks(p, NULL, 0, NULL, &pfd); +- if (r != -ENOENT) { ++ if (r != -ENOENT && sd_id128_get_machine(NULL) >= 0) { + _cleanup_close_ int fd = -1; + sd_id128_t a, b; + diff --git a/0775-test-unit-name-simplify-machine-id-check.patch b/0775-test-unit-name-simplify-machine-id-check.patch new file mode 100644 index 0000000..3eefb2c --- /dev/null +++ b/0775-test-unit-name-simplify-machine-id-check.patch @@ -0,0 +1,34 @@ +From 1358081487650f718ad84b26313bcc16a3093e04 Mon Sep 17 00:00:00 2001 +From: Nick Rosbrook +Date: Tue, 13 Dec 2022 12:22:37 -0500 +Subject: [PATCH] test-unit-name: simplify machine-id check + +(cherry picked from commit a635b6279cf35abad3abe169780ec899df9396df) + +Related: RHEL-27512 +--- + src/test/test-unit-name.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c +index eec4831b4e..1e230ba5f9 100644 +--- a/src/test/test-unit-name.c ++++ b/src/test/test-unit-name.c +@@ -3,6 +3,8 @@ + #include + #include + ++#include "sd-id128.h" ++ + #include "alloc-util.h" + #include "all-units.h" + #include "glob-util.h" +@@ -264,7 +266,7 @@ TEST_RET(unit_printf, .sd_booted = true) { + assert_se(short_hostname); + assert_se(specifier_pretty_hostname('q', NULL, NULL, NULL, &pretty_hostname) == 0); + assert_se(pretty_hostname); +- if (access("/etc/machine-id", F_OK) >= 0) { ++ if (sd_id128_get_machine(NULL) >= 0) { + assert_se(specifier_machine_id('m', NULL, NULL, NULL, &machine_id) >= 0); + assert_se(machine_id); + } diff --git a/0776-test-load-fragment-simplify-machine-id-check.patch b/0776-test-load-fragment-simplify-machine-id-check.patch new file mode 100644 index 0000000..ad7451a --- /dev/null +++ b/0776-test-load-fragment-simplify-machine-id-check.patch @@ -0,0 +1,34 @@ +From 5447ec5233b3079075dfac92ae3decf38f845e0e Mon Sep 17 00:00:00 2001 +From: Nick Rosbrook +Date: Tue, 13 Dec 2022 12:25:35 -0500 +Subject: [PATCH] test-load-fragment: simplify machine-id check + +(cherry picked from commit 2c6b738badf1404b3ceb7e322eeeb736b57f6162) + +Related: RHEL-27512 +--- + src/test/test-load-fragment.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/test/test-load-fragment.c b/src/test/test-load-fragment.c +index 3cf704134c..997c2b2524 100644 +--- a/src/test/test-load-fragment.c ++++ b/src/test/test-load-fragment.c +@@ -5,6 +5,8 @@ + #include + #include + ++#include "sd-id128.h" ++ + #include "all-units.h" + #include "alloc-util.h" + #include "capability-util.h" +@@ -518,7 +520,7 @@ TEST(install_printf, .sd_booted = true) { + + _cleanup_free_ char *mid = NULL, *bid = NULL, *host = NULL, *gid = NULL, *group = NULL, *uid = NULL, *user = NULL; + +- if (access("/etc/machine-id", F_OK) >= 0) ++ if (sd_id128_get_machine(NULL) >= 0) + assert_se(specifier_machine_id('m', NULL, NULL, NULL, &mid) >= 0 && mid); + if (sd_booted() > 0) + assert_se(specifier_boot_id('b', NULL, NULL, NULL, &bid) >= 0 && bid); diff --git a/0777-journal-skip-part-of-test-journal-interleaving-if-no.patch b/0777-journal-skip-part-of-test-journal-interleaving-if-no.patch new file mode 100644 index 0000000..a8a746c --- /dev/null +++ b/0777-journal-skip-part-of-test-journal-interleaving-if-no.patch @@ -0,0 +1,75 @@ +From 528e1178026b3f567139c994ce89992379618d2e Mon Sep 17 00:00:00 2001 +From: Nick Rosbrook +Date: Wed, 14 Dec 2022 10:07:40 -0500 +Subject: [PATCH] journal: skip part of test-journal-interleaving if no + machine-id exists + +When executed on a systemd with an empty /etc/machine-id, +test-journal-interleaving fails in test_sequence_numbers_one() when +re-opening the existing "two.journal". This is because opening the +existing journal file with managed_journal_file_open() causes +journal_file_verify_header() to be called. This function tries to +compare the current machine-id to the machine-id in the journal file +header, but does not handle the case where the machine-id is empty or +non-existent. + +Check if we have an initialized machine-id before executing this portion +of the test. + +(cherry picked from commit 3a9ca230363e6d1063a789492005d744723f5eed) + +Related: RHEL-27512 +--- + src/journal/test-journal-interleaving.c | 27 +++++++++++++++---------- + 1 file changed, 16 insertions(+), 11 deletions(-) + +diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c +index fb38cc7e82..e05eae034b 100644 +--- a/src/journal/test-journal-interleaving.c ++++ b/src/journal/test-journal-interleaving.c +@@ -3,6 +3,7 @@ + #include + #include + ++#include "sd-id128.h" + #include "sd-journal.h" + + #include "alloc-util.h" +@@ -263,22 +264,26 @@ static void test_sequence_numbers_one(void) { + + test_close(one); + +- /* restart server */ +- seqnum = 0; ++ /* If the machine-id is not initialized, the header file verification ++ * (which happens when re-opening a journal file) will fail. */ ++ if (sd_id128_get_machine(NULL) >= 0) { ++ /* restart server */ ++ seqnum = 0; + +- assert_se(managed_journal_file_open(-1, "two.journal", O_RDWR, JOURNAL_COMPRESS, 0, +- UINT64_MAX, NULL, m, NULL, NULL, &two) == 0); ++ assert_se(managed_journal_file_open(-1, "two.journal", O_RDWR, JOURNAL_COMPRESS, 0, ++ UINT64_MAX, NULL, m, NULL, NULL, &two) == 0); + +- assert_se(sd_id128_equal(two->file->header->seqnum_id, seqnum_id)); ++ assert_se(sd_id128_equal(two->file->header->seqnum_id, seqnum_id)); + +- append_number(two, 7, &seqnum); +- printf("seqnum=%"PRIu64"\n", seqnum); +- assert_se(seqnum == 5); ++ append_number(two, 7, &seqnum); ++ printf("seqnum=%"PRIu64"\n", seqnum); ++ assert_se(seqnum == 5); + +- /* So..., here we have the same seqnum in two files with the +- * same seqnum_id. */ ++ /* So..., here we have the same seqnum in two files with the ++ * same seqnum_id. */ + +- test_close(two); ++ test_close(two); ++ } + + log_info("Done..."); + diff --git a/0778-test-skip-journal-tests-without-valid-etc-machine-id.patch b/0778-test-skip-journal-tests-without-valid-etc-machine-id.patch new file mode 100644 index 0000000..c2fc2ca --- /dev/null +++ b/0778-test-skip-journal-tests-without-valid-etc-machine-id.patch @@ -0,0 +1,111 @@ +From 80b1fd81ec483b57444572f957e38b5fea5b3db6 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 27 Feb 2024 16:10:37 +0100 +Subject: [PATCH] test: skip journal tests without valid /etc/machine-id + +The journal stuff in RHEL 9 can't handle existing but uninitialized +/etc/machine-id and backporting all the necessary changes would mean +pulling in another 50+ commits (I stopped after 50, so it's probably +much more). And to make matters worse, upstream renamed +chase_symlinks*() stuff to chase_*(), which makes the backports even +more painful (and risky). + +Related PRs: + - https://github.com/systemd/systemd/pull/25734/commits + - https://github.com/systemd/systemd/pull/27137/commits + - https://github.com/systemd/systemd/pull/27122/commits + +RHEL-only + +Related: RHEL-27512 +--- + src/journal/test-journal-flush.c | 14 +++++++++++++- + src/journal/test-journal-interleaving.c | 2 +- + src/journal/test-journal-stream.c | 2 +- + src/journal/test-journal-verify.c | 4 ++++ + src/journal/test-journal.c | 2 +- + 5 files changed, 20 insertions(+), 4 deletions(-) + +diff --git a/src/journal/test-journal-flush.c b/src/journal/test-journal-flush.c +index 2a5f7fad5e..4b52544e7f 100644 +--- a/src/journal/test-journal-flush.c ++++ b/src/journal/test-journal-flush.c +@@ -16,6 +16,8 @@ + #include "string-util.h" + #include "tests.h" + ++static bool arg_keep = false; ++ + static void test_journal_flush_one(int argc, char *argv[]) { + _cleanup_(mmap_cache_unrefp) MMapCache *m = NULL; + _cleanup_free_ char *fn = NULL; +@@ -117,4 +119,14 @@ TEST(journal_flush_compact) { + test_journal_flush_one(saved_argc, saved_argv); + } + +-DEFINE_TEST_MAIN(LOG_INFO); ++static int intro(void) { ++ arg_keep = saved_argc > 1; ++ ++ /* managed_journal_file_open requires a valid machine id */ ++ if (sd_id128_get_machine(NULL) < 0) ++ return log_tests_skipped("/etc/machine-id not found"); ++ ++ return EXIT_SUCCESS; ++} ++ ++DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro); +diff --git a/src/journal/test-journal-interleaving.c b/src/journal/test-journal-interleaving.c +index e05eae034b..56b2489277 100644 +--- a/src/journal/test-journal-interleaving.c ++++ b/src/journal/test-journal-interleaving.c +@@ -306,7 +306,7 @@ TEST(sequence_numbers) { + + static int intro(void) { + /* managed_journal_file_open requires a valid machine id */ +- if (access("/etc/machine-id", F_OK) != 0) ++ if (sd_id128_get_machine(NULL) < 0) + return log_tests_skipped("/etc/machine-id not found"); + + arg_keep = saved_argc > 1; +diff --git a/src/journal/test-journal-stream.c b/src/journal/test-journal-stream.c +index ac5b7f0005..fe4bc40eaa 100644 +--- a/src/journal/test-journal-stream.c ++++ b/src/journal/test-journal-stream.c +@@ -179,7 +179,7 @@ static void run_test(void) { + int main(int argc, char *argv[]) { + + /* managed_journal_file_open requires a valid machine id */ +- if (access("/etc/machine-id", F_OK) != 0) ++ if (sd_id128_get_machine(NULL) < 0) + return log_tests_skipped("/etc/machine-id not found"); + + test_setup_logging(LOG_DEBUG); +diff --git a/src/journal/test-journal-verify.c b/src/journal/test-journal-verify.c +index e36ea8cae1..55be7f451b 100644 +--- a/src/journal/test-journal-verify.c ++++ b/src/journal/test-journal-verify.c +@@ -143,6 +143,10 @@ static int run_test(int argc, char *argv[]) { + } + + int main(int argc, char *argv[]) { ++ /* managed_journal_file_open requires a valid machine id */ ++ if (sd_id128_get_machine(NULL) < 0) ++ return log_tests_skipped("/etc/machine-id not found"); ++ + assert_se(setenv("SYSTEMD_JOURNAL_COMPACT", "0", 1) >= 0); + run_test(argc, argv); + +diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c +index 889673cae7..99beb671c5 100644 +--- a/src/journal/test-journal.c ++++ b/src/journal/test-journal.c +@@ -271,7 +271,7 @@ static int intro(void) { + arg_keep = saved_argc > 1; + + /* managed_journal_file_open requires a valid machine id */ +- if (access("/etc/machine-id", F_OK) != 0) ++ if (sd_id128_get_machine(NULL) < 0) + return log_tests_skipped("/etc/machine-id not found"); + + return EXIT_SUCCESS; diff --git a/0779-test-recurse-dir-work-around-nftw-ignoring-symlinks.patch b/0779-test-recurse-dir-work-around-nftw-ignoring-symlinks.patch new file mode 100644 index 0000000..4c47543 --- /dev/null +++ b/0779-test-recurse-dir-work-around-nftw-ignoring-symlinks.patch @@ -0,0 +1,61 @@ +From 36b71213e9f734fbf5ab3b032f61614c79737dac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 19 Oct 2023 16:46:56 +0200 +Subject: [PATCH] test-recurse-dir: work around nftw() ignoring symlinks() + +We have a test where we compare the results from nftw() and our own +resurce_dit_at(). nftw() skips a dangling symlink when running under mkosi and +the test fails. I don't understand why nftw() does that, but in our code we +don't need to test and care about the details of nftw(), which we don't use, +outside of the one test, so let's just skip symlinks in the test. + +Closes #29603. + +(cherry picked from commit 974959e6f6352b76355b76ab550c0e729b2a8c21) + +Related: RHEL-27512 +--- + src/test/test-recurse-dir.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/src/test/test-recurse-dir.c b/src/test/test-recurse-dir.c +index 2c2120b136..c194896a1b 100644 +--- a/src/test/test-recurse-dir.c ++++ b/src/test/test-recurse-dir.c +@@ -26,8 +26,7 @@ static int nftw_cb( + break; + + case FTW_SL: +- log_debug("ftw found symlink %s", fpath); +- assert_se(strv_extendf(&list_nftw, "%s→", fpath) >= 0); ++ log_debug("ftw found symlink %s, ignoring.", fpath); + break; + + case FTW_D: +@@ -71,11 +70,10 @@ static int recurse_dir_callback( + case RECURSE_DIR_ENTRY: + assert_se(!IN_SET(de->d_type, DT_UNKNOWN, DT_DIR)); + +- log_debug("found %s", path); ++ log_debug("found %s%s", path, ++ de->d_type == DT_LNK ? ", ignoring." : ""); + +- if (de->d_type == DT_LNK) +- assert_se(strv_extendf(l, "%s→", path) >= 0); +- else ++ if (de->d_type != DT_LNK) + assert_se(strv_extend(l, path) >= 0); + break; + +@@ -131,7 +129,10 @@ int main(int argc, char *argv[]) { + else + p = "/usr/share/man"; /* something hopefully reasonably stable while we run (and limited in size) */ + +- /* Enumerate the specified dirs in full, once via nftw(), and once via recurse_dir(), and ensure the results are identical */ ++ /* Enumerate the specified dirs in full, once via nftw(), and once via recurse_dir(), and ensure the ++ * results are identical. nftw() sometimes skips symlinks (see ++ * https://github.com/systemd/systemd/issues/29603), so ignore them to avoid bogus errors. */ ++ + t1 = now(CLOCK_MONOTONIC); + r = recurse_dir_at(AT_FDCWD, p, 0, UINT_MAX, RECURSE_DIR_SORT|RECURSE_DIR_ENSURE_TYPE|RECURSE_DIR_SAME_MOUNT, recurse_dir_callback, &list_recurse_dir); + t2 = now(CLOCK_MONOTONIC); diff --git a/0780-test-Skip-test-recurse-dir-on-overlayfs.patch b/0780-test-Skip-test-recurse-dir-on-overlayfs.patch new file mode 100644 index 0000000..ec2c310 --- /dev/null +++ b/0780-test-Skip-test-recurse-dir-on-overlayfs.patch @@ -0,0 +1,70 @@ +From d4290244c49c6cc341225151cf0dfd5329dde943 Mon Sep 17 00:00:00 2001 +From: Richard Maw +Date: Wed, 25 Oct 2023 18:12:58 +0100 +Subject: [PATCH] test: Skip test-recurse-dir on overlayfs + +(cherry picked from commit 31cfcf50088b69c973b9335a2383fa6502d90419) + +Related: RHEL-27512 +--- + src/test/test-recurse-dir.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/src/test/test-recurse-dir.c b/src/test/test-recurse-dir.c +index c194896a1b..3e42526679 100644 +--- a/src/test/test-recurse-dir.c ++++ b/src/test/test-recurse-dir.c +@@ -2,7 +2,9 @@ + + #include + ++#include "fd-util.h" + #include "log.h" ++#include "missing_magic.h" + #include "recurse-dir.h" + #include "strv.h" + #include "tests.h" +@@ -119,7 +121,7 @@ int main(int argc, char *argv[]) { + _cleanup_strv_free_ char **list_recurse_dir = NULL; + const char *p; + usec_t t1, t2, t3, t4; +- int r; ++ _cleanup_close_ int fd = -EBADF; + + log_show_color(true); + test_setup_logging(LOG_INFO); +@@ -129,18 +131,28 @@ int main(int argc, char *argv[]) { + else + p = "/usr/share/man"; /* something hopefully reasonably stable while we run (and limited in size) */ + ++ fd = open(p, O_DIRECTORY|O_CLOEXEC); ++ if (fd < 0 && errno == ENOENT) { ++ log_warning_errno(errno, "Couldn't open directory %s, ignoring: %m", p); ++ return EXIT_TEST_SKIP; ++ } ++ assert_se(fd >= 0); ++ ++ /* If the test directory is on an overlayfs then files and their direcory may return different st_dev ++ * in stat results, which confuses nftw into thinking they're on different filesystems ++ * and won't return the result when the FTW_MOUNT flag is set. */ ++ if (fd_is_fs_type(fd, OVERLAYFS_SUPER_MAGIC)) { ++ log_tests_skipped("nftw mountpoint detection produces false-positives on overlayfs"); ++ return EXIT_TEST_SKIP; ++ } ++ + /* Enumerate the specified dirs in full, once via nftw(), and once via recurse_dir(), and ensure the + * results are identical. nftw() sometimes skips symlinks (see + * https://github.com/systemd/systemd/issues/29603), so ignore them to avoid bogus errors. */ + + t1 = now(CLOCK_MONOTONIC); +- r = recurse_dir_at(AT_FDCWD, p, 0, UINT_MAX, RECURSE_DIR_SORT|RECURSE_DIR_ENSURE_TYPE|RECURSE_DIR_SAME_MOUNT, recurse_dir_callback, &list_recurse_dir); ++ assert_se(recurse_dir(fd, p, 0, UINT_MAX, RECURSE_DIR_SORT|RECURSE_DIR_ENSURE_TYPE|RECURSE_DIR_SAME_MOUNT, recurse_dir_callback, &list_recurse_dir) >= 0); + t2 = now(CLOCK_MONOTONIC); +- if (r == -ENOENT) { +- log_warning_errno(r, "Couldn't open directory %s, ignoring: %m", p); +- return EXIT_TEST_SKIP; +- } +- assert_se(r >= 0); + + t3 = now(CLOCK_MONOTONIC); + assert_se(nftw(p, nftw_cb, 64, FTW_PHYS|FTW_MOUNT) >= 0); diff --git a/0781-test-specifier-Ignore-ENOPKG-from-specifier_printf.patch b/0781-test-specifier-Ignore-ENOPKG-from-specifier_printf.patch new file mode 100644 index 0000000..ca0d4d2 --- /dev/null +++ b/0781-test-specifier-Ignore-ENOPKG-from-specifier_printf.patch @@ -0,0 +1,28 @@ +From 62cbc9f00697003069f1c263c0ab3361f0ea4b6a Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Sat, 6 May 2023 11:33:22 +0200 +Subject: [PATCH] test-specifier: Ignore -ENOPKG from specifier_printf() + +If /etc/machine-id contains "uninitialized", specifier_printf() with +%m will fail with ENOPKG, so ignore that error as well. + +(cherry picked from commit 7429c8fe57bef84c3ff6ebd94b560356752af0bc) + +Related: RHEL-27512 +--- + src/test/test-specifier.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/test/test-specifier.c b/src/test/test-specifier.c +index 4a8ff4bd10..d0adc1a87d 100644 +--- a/src/test/test-specifier.c ++++ b/src/test/test-specifier.c +@@ -136,7 +136,7 @@ TEST(specifiers) { + xsprintf(spec, "%%%c", s->specifier); + + r = specifier_printf(spec, SIZE_MAX, specifier_table, NULL, NULL, &resolved); +- if (s->specifier == 'm' && IN_SET(r, -ENOENT, -ENOMEDIUM)) /* machine-id might be missing in build chroots */ ++ if (s->specifier == 'm' && IN_SET(r, -ENOENT, -ENOMEDIUM, -ENOPKG)) /* machine-id might be missing in build chroots */ + continue; + assert_se(r >= 0); + diff --git a/0782-test-execute-Skip-when-sys-is-read-only.patch b/0782-test-execute-Skip-when-sys-is-read-only.patch new file mode 100644 index 0000000..6d8d4e3 --- /dev/null +++ b/0782-test-execute-Skip-when-sys-is-read-only.patch @@ -0,0 +1,29 @@ +From db9c5f759c7c4163d9de1db398b72ef01abaec24 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Wed, 25 Jan 2023 09:39:13 +0100 +Subject: [PATCH] test-execute: Skip when /sys is read-only + +The test depends on /sys being writable, so let's skip it when /sys +is read-only. + +(cherry picked from commit 34b5977015a557840988e825ac116a7f09d0be75) + +Related: RHEL-27512 +--- + src/test/test-execute.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/test/test-execute.c b/src/test/test-execute.c +index 0283caeca6..ce3489d708 100644 +--- a/src/test/test-execute.c ++++ b/src/test/test-execute.c +@@ -1228,6 +1228,9 @@ int main(int argc, char *argv[]) { + if (r == -ENOMEDIUM) + return log_tests_skipped("cgroupfs not available"); + ++ if (path_is_read_only_fs("/sys") > 0) ++ return log_tests_skipped("/sys is mounted read-only"); ++ + _cleanup_free_ char *unit_dir = NULL, *unit_paths = NULL; + assert_se(get_testdata_dir("test-execute/", &unit_dir) >= 0); + assert_se(runtime_dir = setup_fake_runtime_dir()); diff --git a/0783-kernel-install-Make-sure-KERNEL_INSTALL_BYPASS-is-di.patch b/0783-kernel-install-Make-sure-KERNEL_INSTALL_BYPASS-is-di.patch new file mode 100644 index 0000000..e85bc2c --- /dev/null +++ b/0783-kernel-install-Make-sure-KERNEL_INSTALL_BYPASS-is-di.patch @@ -0,0 +1,25 @@ +From bc68683e1ed1579718291a74edc7c6406ce078a0 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Mon, 31 Jul 2023 20:58:31 +0200 +Subject: [PATCH] kernel-install: Make sure KERNEL_INSTALL_BYPASS is disabled + in tests + +(cherry picked from commit 4435da1f1732e2078e42b0ee43ad56fde2b021a3) + +Related: RHEL-27512 +--- + src/kernel-install/test-kernel-install.sh | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/kernel-install/test-kernel-install.sh b/src/kernel-install/test-kernel-install.sh +index 2e44063668..3b9ff76e60 100755 +--- a/src/kernel-install/test-kernel-install.sh ++++ b/src/kernel-install/test-kernel-install.sh +@@ -32,6 +32,7 @@ export KERNEL_INSTALL_CONF_ROOT="$D/sources" + export KERNEL_INSTALL_PLUGINS="$plugin" + export BOOT_ROOT="$D/boot" + export MACHINE_ID='3e0484f3634a418b8e6a39e8828b03e3' ++export KERNEL_INSTALL_BYPASS="no" + + "$kernel_install" -v add 1.1.1 "$D/sources/linux" "$D/sources/initrd" + diff --git a/0784-tools-make-sure-KERNEL_INSTALL_BYPASS-is-disabled-wh.patch b/0784-tools-make-sure-KERNEL_INSTALL_BYPASS-is-disabled-wh.patch new file mode 100644 index 0000000..df0847f --- /dev/null +++ b/0784-tools-make-sure-KERNEL_INSTALL_BYPASS-is-disabled-wh.patch @@ -0,0 +1,42 @@ +From d2fcb75822d85a1516bca2fc2e87e1d94d7691c3 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 27 Feb 2024 16:59:23 +0100 +Subject: [PATCH] tools: make sure $KERNEL_INSTALL_BYPASS is disabled when + checking help +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Upstream mkosi sets $KERNEL_INSTALL_BYPASS to 1 by default [0] which +then trip over check-help tests, as the message about +$KERNEL_INSTALL_BYPASS is not printed out to stderr. Upstream systemd +doesn't have this issue, since kernel-install there was rewritten in C, +so the code base is completely different. + + 1068/1073 systemd:dist-check / check-help-kernel-install FAIL 0.02s exit status 4 +>>> MALLOC_PERTURB_=212 /work/src/tools/check-help.sh /work/build/kernel-install +――――――――――――――――――――――――――――――――――――― ✀ ――――――――――――――――――――――――――――――――――――― +kernel-install with an unknown parameter does not print to stderr +―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― + +[0] https://github.com/systemd/mkosi/commit/deaaa831d4379ef400ffdc5f71bc0eabed072044 + +RHEL-only + +Related: RHEL-27512 +--- + tools/check-help.sh | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/check-help.sh b/tools/check-help.sh +index f97429364e..2f062a7515 100755 +--- a/tools/check-help.sh ++++ b/tools/check-help.sh +@@ -9,6 +9,7 @@ set -o pipefail + + BINARY="${1:?}" + export SYSTEMD_LOG_LEVEL=info ++export KERNEL_INSTALL_BYPASS="no" + + if [[ ! -x "$BINARY" ]]; then + echo "$BINARY is not an executable" diff --git a/0785-test-execute-drop-capabilities-when-testing-with-use.patch b/0785-test-execute-drop-capabilities-when-testing-with-use.patch new file mode 100644 index 0000000..2ee2431 --- /dev/null +++ b/0785-test-execute-drop-capabilities-when-testing-with-use.patch @@ -0,0 +1,888 @@ +From bdde465ad1df52cb9b9fbaab37d5d7541601d774 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 3 Feb 2023 12:28:31 +0900 +Subject: [PATCH] test-execute: drop capabilities when testing with user + manager + +Before this, tests are split into two categories, system and user, but +both are running in fully privileged environment. Hence, unprivileged +user scope was mostly not covered by the test. + +Let's run all tests in both system and user scopes, and drop capabilities +when Manager is running in user scope. + +This also makes the host environment protected more from the test run. + +(cherry picked from commit 4e032f654b94c2544ccf937209303766dfa66c24) + +Related: RHEL-27512 +--- + src/test/test-execute.c | 351 +++++++++++------- + ...dynamicuser-statedir-migrate-step1.service | 16 +- + ...dynamicuser-statedir-migrate-step2.service | 32 +- + .../exec-dynamicuser-statedir.service | 122 +++--- + .../exec-privatenetwork-yes.service | 1 + + .../exec-specifier-system.service | 11 + + test/test-execute/exec-specifier-user.service | 11 + + test/test-execute/exec-specifier.service | 5 - + test/test-execute/exec-specifier@.service | 5 - + 9 files changed, 333 insertions(+), 221 deletions(-) + create mode 100644 test/test-execute/exec-specifier-system.service + create mode 100644 test/test-execute/exec-specifier-user.service + +diff --git a/src/test/test-execute.c b/src/test/test-execute.c +index ce3489d708..665ae8a833 100644 +--- a/src/test/test-execute.c ++++ b/src/test/test-execute.c +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: LGPL-2.1-or-later */ + + #include ++#include + #include + #include + +@@ -18,6 +19,7 @@ + #include "manager.h" + #include "missing_prctl.h" + #include "mkdir.h" ++#include "mount-util.h" + #include "path-util.h" + #include "process-util.h" + #include "rm-rf.h" +@@ -35,6 +37,8 @@ + #include "util.h" + #include "virt.h" + ++#define PRIVATE_UNIT_DIR "/run/test-execute-unit-dir" ++ + static char *user_runtime_unit_dir = NULL; + static bool can_unshare; + +@@ -414,7 +418,7 @@ static void test_exec_privatedevices(Manager *m) { + test(m, "exec-privatedevices-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + test(m, "exec-privatedevices-no.service", 0, CLD_EXITED); + test(m, "exec-privatedevices-disabled-by-prefix.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); +- test(m, "exec-privatedevices-yes-with-group.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); ++ test(m, "exec-privatedevices-yes-with-group.service", can_unshare ? 0 : MANAGER_IS_SYSTEM(m) ? EXIT_FAILURE : EXIT_GROUP, CLD_EXITED); + + /* We use capsh to test if the capabilities are + * properly set, so be sure that it exists */ +@@ -425,9 +429,9 @@ static void test_exec_privatedevices(Manager *m) { + } + + test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED); +- test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED); ++ test(m, "exec-privatedevices-no-capability-mknod.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_FAILURE, CLD_EXITED); + test(m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED); +- test(m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED); ++ test(m, "exec-privatedevices-no-capability-sys-rawio.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_FAILURE, CLD_EXITED); + } + + static void test_exec_protecthome(Manager *m) { +@@ -457,7 +461,7 @@ static void test_exec_protectkernelmodules(Manager *m) { + return; + } + +- test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED); ++ test(m, "exec-protectkernelmodules-no-capabilities.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_FAILURE, CLD_EXITED); + test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED); + test(m, "exec-protectkernelmodules-yes-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED); + } +@@ -778,7 +782,7 @@ static void test_exec_systemcallfilter_system(Manager *m) { + return; + } + +- test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED); ++ test(m, "exec-systemcallfilter-system-user.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); + + if (!check_nobody_user_and_group()) { + log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__); +@@ -790,12 +794,12 @@ static void test_exec_systemcallfilter_system(Manager *m) { + return; + } + +- test(m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED); ++ test(m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); + #endif + } + + static void test_exec_user(Manager *m) { +- test(m, "exec-user.service", 0, CLD_EXITED); ++ test(m, "exec-user.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); + + if (!check_nobody_user_and_group()) { + log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__); +@@ -807,11 +811,11 @@ static void test_exec_user(Manager *m) { + return; + } + +- test(m, "exec-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED); ++ test(m, "exec-user-" NOBODY_USER_NAME ".service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); + } + + static void test_exec_group(Manager *m) { +- test(m, "exec-group.service", 0, CLD_EXITED); ++ test(m, "exec-group.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); + + if (!check_nobody_user_and_group()) { + log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__); +@@ -823,16 +827,17 @@ static void test_exec_group(Manager *m) { + return; + } + +- test(m, "exec-group-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED); ++ test(m, "exec-group-" NOBODY_GROUP_NAME ".service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); + } + + static void test_exec_supplementarygroups(Manager *m) { +- test(m, "exec-supplementarygroups.service", 0, CLD_EXITED); +- test(m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED); +- test(m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED); +- test(m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED); +- test(m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED); +- test(m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED); ++ int status = MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP; ++ test(m, "exec-supplementarygroups.service", status, CLD_EXITED); ++ test(m, "exec-supplementarygroups-single-group.service", status, CLD_EXITED); ++ test(m, "exec-supplementarygroups-single-group-user.service", status, CLD_EXITED); ++ test(m, "exec-supplementarygroups-multiple-groups-default-group-user.service", status, CLD_EXITED); ++ test(m, "exec-supplementarygroups-multiple-groups-withgid.service", status, CLD_EXITED); ++ test(m, "exec-supplementarygroups-multiple-groups-withuid.service", status, CLD_EXITED); + } + + static char* private_directory_bad(Manager *m) { +@@ -864,14 +869,16 @@ static void test_exec_dynamicuser(Manager *m) { + return; + } + +- test(m, "exec-dynamicuser-fixeduser.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); ++ int status = can_unshare ? 0 : MANAGER_IS_SYSTEM(m) ? EXIT_NAMESPACE : EXIT_GROUP; ++ ++ test(m, "exec-dynamicuser-fixeduser.service", status, CLD_EXITED); + if (check_user_has_group_with_same_name("adm")) +- test(m, "exec-dynamicuser-fixeduser-adm.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); ++ test(m, "exec-dynamicuser-fixeduser-adm.service", status, CLD_EXITED); + if (check_user_has_group_with_same_name("games")) +- test(m, "exec-dynamicuser-fixeduser-games.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); +- test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); +- test(m, "exec-dynamicuser-supplementarygroups.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); +- test(m, "exec-dynamicuser-statedir.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); ++ test(m, "exec-dynamicuser-fixeduser-games.service", status, CLD_EXITED); ++ test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", status, CLD_EXITED); ++ test(m, "exec-dynamicuser-supplementarygroups.service", status, CLD_EXITED); ++ test(m, "exec-dynamicuser-statedir.service", status, CLD_EXITED); + + (void) rm_rf("/var/lib/quux", REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); +@@ -883,7 +890,7 @@ static void test_exec_dynamicuser(Manager *m) { + (void) rm_rf("/var/lib/private/waldo", REMOVE_ROOT|REMOVE_PHYSICAL); + + test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED); +- test(m, "exec-dynamicuser-statedir-migrate-step2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); ++ test(m, "exec-dynamicuser-statedir-migrate-step2.service", status, CLD_EXITED); + test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED); + + (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); +@@ -891,9 +898,9 @@ static void test_exec_dynamicuser(Manager *m) { + (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL); + (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL); + +- test(m, "exec-dynamicuser-runtimedirectory1.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); +- test(m, "exec-dynamicuser-runtimedirectory2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); +- test(m, "exec-dynamicuser-runtimedirectory3.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); ++ test(m, "exec-dynamicuser-runtimedirectory1.service", status, CLD_EXITED); ++ test(m, "exec-dynamicuser-runtimedirectory2.service", status, CLD_EXITED); ++ test(m, "exec-dynamicuser-runtimedirectory3.service", status, CLD_EXITED); + } + + static void test_exec_environment(Manager *m) { +@@ -959,9 +966,12 @@ static void test_exec_umask(Manager *m) { + } + + static void test_exec_runtimedirectory(Manager *m) { ++ (void) rm_rf("/run/test-exec_runtimedirectory2", REMOVE_ROOT|REMOVE_PHYSICAL); + test(m, "exec-runtimedirectory.service", 0, CLD_EXITED); ++ (void) rm_rf("/run/test-exec_runtimedirectory2", REMOVE_ROOT|REMOVE_PHYSICAL); ++ + test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED); +- test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED); ++ test(m, "exec-runtimedirectory-owner.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); + + if (!check_nobody_user_and_group()) { + log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__); +@@ -973,7 +983,7 @@ static void test_exec_runtimedirectory(Manager *m) { + return; + } + +- test(m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED); ++ test(m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_GROUP, CLD_EXITED); + } + + static void test_exec_capabilityboundingset(Manager *m) { +@@ -1047,7 +1057,7 @@ static void test_exec_privatenetwork(Manager *m) { + return; + } + +- test(m, "exec-privatenetwork-yes.service", can_unshare ? 0 : EXIT_NETWORK, CLD_EXITED); ++ test(m, "exec-privatenetwork-yes.service", can_unshare ? 0 : MANAGER_IS_SYSTEM(m) ? EXIT_NETWORK : EXIT_FAILURE, CLD_EXITED); + } + + static void test_exec_oomscoreadjust(Manager *m) { +@@ -1057,7 +1067,7 @@ static void test_exec_oomscoreadjust(Manager *m) { + log_notice("Testing in container, skipping remaining tests in %s", __func__); + return; + } +- test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED); ++ test(m, "exec-oomscoreadjust-negative.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_FAILURE, CLD_EXITED); + } + + static void test_exec_ioschedulingclass(Manager *m) { +@@ -1069,7 +1079,7 @@ static void test_exec_ioschedulingclass(Manager *m) { + log_notice("Testing in container, skipping remaining tests in %s", __func__); + return; + } +- test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED); ++ test(m, "exec-ioschedulingclass-realtime.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_IOPRIO, CLD_EXITED); + } + + static void test_exec_unsetenvironment(Manager *m) { +@@ -1078,9 +1088,13 @@ static void test_exec_unsetenvironment(Manager *m) { + + static void test_exec_specifier(Manager *m) { + test(m, "exec-specifier.service", 0, CLD_EXITED); ++ if (MANAGER_IS_SYSTEM(m)) ++ test(m, "exec-specifier-system.service", 0, CLD_EXITED); ++ else ++ test(m, "exec-specifier-user.service", 0, CLD_EXITED); + test(m, "exec-specifier@foo-bar.service", 0, CLD_EXITED); + test(m, "exec-specifier-interpolation.service", 0, CLD_EXITED); +- test(m, "exec-specifier-credentials-dir.service", 0, CLD_EXITED); ++ test(m, "exec-specifier-credentials-dir.service", MANAGER_IS_SYSTEM(m) ? 0 : EXIT_CREDENTIALS, CLD_EXITED); + } + + static void test_exec_standardinput(Manager *m) { +@@ -1113,7 +1127,7 @@ static void test_exec_umask_namespace(Manager *m) { + log_notice("Testing without inaccessible, skipping %s", __func__); + return; + } +- test(m, "exec-umask-namespace.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED); ++ test(m, "exec-umask-namespace.service", can_unshare ? 0 : MANAGER_IS_SYSTEM(m) ? EXIT_NAMESPACE : EXIT_GROUP, CLD_EXITED); + } + + typedef struct test_entry { +@@ -1123,40 +1137,27 @@ typedef struct test_entry { + + #define entry(x) {x, #x} + +-static int run_tests(LookupScope scope, const test_entry tests[], char **patterns) { ++static void run_tests(LookupScope scope, char **patterns) { ++ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; ++ _cleanup_free_ char *unit_paths = NULL; + _cleanup_(manager_freep) Manager *m = NULL; + int r; + +- assert_se(tests); +- +- r = manager_new(scope, MANAGER_TEST_RUN_BASIC, &m); +- m->default_std_output = EXEC_OUTPUT_NULL; /* don't rely on host journald */ +- if (manager_errno_skip_test(r)) +- return log_tests_skipped_errno(r, "manager_new"); +- assert_se(r >= 0); +- assert_se(manager_startup(m, NULL, NULL, NULL) >= 0); +- +- for (const test_entry *test = tests; test->f; test++) +- if (strv_fnmatch_or_empty(patterns, test->name, FNM_NOESCAPE)) +- test->f(m); +- else +- log_info("Skipping %s because it does not match any pattern.", test->name); +- +- return 0; +-} +- +-int main(int argc, char *argv[]) { +- _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL; +- +- static const test_entry user_tests[] = { ++ static const test_entry tests[] = { + entry(test_exec_basic), + entry(test_exec_ambientcapabilities), + entry(test_exec_bindpaths), + entry(test_exec_capabilityboundingset), + entry(test_exec_condition), + entry(test_exec_cpuaffinity), ++ entry(test_exec_dynamicuser), + entry(test_exec_environment), + entry(test_exec_environmentfile), ++ entry(test_exec_execsearchpath), ++ entry(test_exec_execsearchpath_environment), ++ entry(test_exec_execsearchpath_environment_files), ++ entry(test_exec_execsearchpath_passenvironment), ++ entry(test_exec_execsearchpath_specifier), + entry(test_exec_group), + entry(test_exec_ignoresigpipe), + entry(test_exec_inaccessiblepaths), +@@ -1175,6 +1176,7 @@ int main(int argc, char *argv[]) { + entry(test_exec_readwritepaths), + entry(test_exec_restrictnamespaces), + entry(test_exec_runtimedirectory), ++ entry(test_exec_specifier), + entry(test_exec_standardinput), + entry(test_exec_standardoutput), + entry(test_exec_standardoutput_append), +@@ -1182,35 +1184,15 @@ int main(int argc, char *argv[]) { + entry(test_exec_supplementarygroups), + entry(test_exec_systemcallerrornumber), + entry(test_exec_systemcallfilter), ++ entry(test_exec_systemcallfilter_system), + entry(test_exec_temporaryfilesystem), + entry(test_exec_umask), ++ entry(test_exec_umask_namespace), + entry(test_exec_unsetenvironment), + entry(test_exec_user), + entry(test_exec_workingdirectory), +- entry(test_exec_execsearchpath), +- entry(test_exec_execsearchpath_environment), +- entry(test_exec_execsearchpath_environment_files), +- entry(test_exec_execsearchpath_passenvironment), +- {}, +- }; +- static const test_entry system_tests[] = { +- entry(test_exec_dynamicuser), +- entry(test_exec_specifier), +- entry(test_exec_execsearchpath_specifier), +- entry(test_exec_systemcallfilter_system), +- entry(test_exec_umask_namespace), + {}, + }; +- int r; +- +- test_setup_logging(LOG_DEBUG); +- +-#if HAS_FEATURE_ADDRESS_SANITIZER +- if (strstr_ptr(ci_environment(), "travis") || strstr_ptr(ci_environment(), "github-actions")) { +- log_notice("Running on Travis CI/GH Actions under ASan, skipping, see https://github.com/systemd/systemd/issues/10696"); +- return EXIT_TEST_SKIP; +- } +-#endif + + assert_se(unsetenv("USER") == 0); + assert_se(unsetenv("LOGNAME") == 0); +@@ -1218,68 +1200,185 @@ int main(int argc, char *argv[]) { + assert_se(unsetenv("HOME") == 0); + assert_se(unsetenv("TMPDIR") == 0); + +- can_unshare = have_namespaces(); +- +- /* It is needed otherwise cgroup creation fails */ +- if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) +- return log_tests_skipped("not privileged"); +- +- r = enter_cgroup_subroot(NULL); +- if (r == -ENOMEDIUM) +- return log_tests_skipped("cgroupfs not available"); +- +- if (path_is_read_only_fs("/sys") > 0) +- return log_tests_skipped("/sys is mounted read-only"); ++ /* Unset VARx, especially, VAR1, VAR2 and VAR3, which are used in the PassEnvironment test cases, ++ * otherwise (and if they are present in the environment), `manager_default_environment` will copy ++ * them into the default environment which is passed to each created job, which will make the tests ++ * that expect those not to be present to fail. */ ++ assert_se(unsetenv("VAR1") == 0); ++ assert_se(unsetenv("VAR2") == 0); ++ assert_se(unsetenv("VAR3") == 0); ++ assert_se(unsetenv("VAR4") == 0); ++ assert_se(unsetenv("VAR5") == 0); + +- _cleanup_free_ char *unit_dir = NULL, *unit_paths = NULL; +- assert_se(get_testdata_dir("test-execute/", &unit_dir) >= 0); + assert_se(runtime_dir = setup_fake_runtime_dir()); + assert_se(user_runtime_unit_dir = path_join(runtime_dir, "systemd/user")); +- assert_se(unit_paths = strjoin(unit_dir, ":", user_runtime_unit_dir)); ++ assert_se(unit_paths = strjoin(PRIVATE_UNIT_DIR, ":", user_runtime_unit_dir)); + assert_se(set_unit_path(unit_paths) >= 0); + +- /* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test +- * cases, otherwise (and if they are present in the environment), +- * `manager_default_environment` will copy them into the default +- * environment which is passed to each created job, which will make the +- * tests that expect those not to be present to fail. +- */ +- assert_se(unsetenv("VAR1") == 0); +- assert_se(unsetenv("VAR2") == 0); +- assert_se(unsetenv("VAR3") == 0); ++ r = manager_new(scope, MANAGER_TEST_RUN_BASIC, &m); ++ if (manager_errno_skip_test(r)) ++ return (void) log_tests_skipped_errno(r, "manager_new"); ++ assert_se(r >= 0); ++ ++ m->default_std_output = EXEC_OUTPUT_NULL; /* don't rely on host journald */ ++ assert_se(manager_startup(m, NULL, NULL, NULL) >= 0); ++ ++ /* Uncomment below if you want to make debugging logs stored to journal. */ ++ //manager_override_log_target(m, LOG_TARGET_AUTO); ++ //manager_override_log_level(m, LOG_DEBUG); ++ ++ for (const test_entry *test = tests; test->f; test++) ++ if (strv_fnmatch_or_empty(patterns, test->name, FNM_NOESCAPE)) ++ test->f(m); ++ else ++ log_info("Skipping %s because it does not match any pattern.", test->name); ++} ++ ++static int prepare_ns(const char *process_name) { ++ int r; ++ ++ r = safe_fork(process_name, ++ FORK_RESET_SIGNALS | ++ FORK_CLOSE_ALL_FDS | ++ FORK_DEATHSIG | ++ FORK_WAIT | ++ FORK_REOPEN_LOG | ++ FORK_LOG | ++ FORK_NEW_MOUNTNS | ++ FORK_MOUNTNS_SLAVE, ++ NULL); ++ assert_se(r >= 0); ++ if (r == 0) { ++ _cleanup_free_ char *unit_dir = NULL; ++ ++ /* Make "/" read-only. */ ++ assert_se(mount_nofollow_verbose(LOG_DEBUG, NULL, "/", NULL, MS_BIND|MS_REMOUNT, NULL) >= 0); ++ ++ /* Creating a new user namespace in the above means all MS_SHARED mounts become MS_SLAVE. ++ * Let's put them back to MS_SHARED here, since that's what we want as defaults. (This will ++ * not reconnect propagation, but simply create new peer groups for all our mounts). */ ++ assert_se(mount_follow_verbose(LOG_DEBUG, NULL, "/", NULL, MS_SHARED|MS_REC, NULL) >= 0); ++ ++ assert_se(mkdir_p(PRIVATE_UNIT_DIR, 0755) >= 0); ++ ++ /* Mount tmpfs on the following directories to make not StateDirectory= or friends disturb the host. */ ++ FOREACH_STRING(p, "/root", "/tmp", "/var/tmp", "/var/lib", PRIVATE_UNIT_DIR) ++ assert_se(mount_nofollow_verbose(LOG_DEBUG, "tmpfs", p, "tmpfs", MS_NOSUID|MS_NODEV, NULL) >= 0); + +- r = run_tests(LOOKUP_SCOPE_USER, user_tests, argv + 1); +- if (r != 0) +- return r; ++ /* Copy unit files to make them accessible even when unprivileged. */ ++ assert_se(get_testdata_dir("test-execute/", &unit_dir) >= 0); ++ assert_se(copy_directory(unit_dir, PRIVATE_UNIT_DIR, COPY_MERGE_EMPTY) >= 0); + +- r = run_tests(LOOKUP_SCOPE_SYSTEM, system_tests, argv + 1); +- if (r != 0) +- return r; ++ /* Prepare credstore like tmpfiles.d/credstore.conf for LoadCredential= tests. */ ++ FOREACH_STRING(p, "/run/credstore", "/run/credstore.encrypted") { ++ assert_se(mkdir_p(p, 0) >= 0); ++ assert_se(mount_nofollow_verbose(LOG_DEBUG, "tmpfs", p, "tmpfs", MS_NOSUID|MS_NODEV, "mode=0000") >= 0); ++ } ++ } ++ ++ return r; ++} ++ ++TEST(run_tests_root) { ++ _cleanup_strv_free_ char **filters = NULL; ++ ++ if (!have_namespaces()) ++ return (void) log_tests_skipped("unshare() is disabled"); ++ ++ /* safe_fork() clears saved_argv in the child process. Let's copy it. */ ++ assert_se(filters = strv_copy(strv_skip(saved_argv, 1))); ++ ++ if (prepare_ns("(test-execute-root)") == 0) { ++ can_unshare = true; ++ run_tests(LOOKUP_SCOPE_SYSTEM, filters); ++ _exit(EXIT_SUCCESS); ++ } ++} ++ ++TEST(run_tests_without_unshare) { ++ if (!have_namespaces()) { ++ /* unshare() is already filtered. */ ++ can_unshare = false; ++ run_tests(LOOKUP_SCOPE_SYSTEM, strv_skip(saved_argv, 1)); ++ return; ++ } + + #if HAVE_SECCOMP ++ _cleanup_strv_free_ char **filters = NULL; ++ int r; ++ + /* The following tests are for 1beab8b0d0ff2d7d1436b52d4a0c3d56dc908962. */ +- if (!is_seccomp_available()) { +- log_notice("Seccomp not available, skipping unshare() filtered tests."); +- return 0; +- } ++ if (!is_seccomp_available()) ++ return (void) log_tests_skipped("Seccomp not available, cannot run unshare() filtered tests"); ++ ++ /* safe_fork() clears saved_argv in the child process. Let's copy it. */ ++ assert_se(filters = strv_copy(strv_skip(saved_argv, 1))); + +- _cleanup_hashmap_free_ Hashmap *s = NULL; +- assert_se(s = hashmap_new(NULL)); +- r = seccomp_syscall_resolve_name("unshare"); +- assert_se(r != __NR_SCMP_ERROR); +- assert_se(hashmap_put(s, UINT32_TO_PTR(r + 1), INT_TO_PTR(-1)) >= 0); +- assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EOPNOTSUPP), true) >= 0); +- assert_se(unshare(CLONE_NEWNS) < 0); +- assert_se(errno == EOPNOTSUPP); ++ if (prepare_ns("(test-execute-without-unshare)") == 0) { ++ _cleanup_hashmap_free_ Hashmap *s = NULL; + +- can_unshare = false; ++ r = seccomp_syscall_resolve_name("unshare"); ++ assert_se(r != __NR_SCMP_ERROR); ++ assert_se(hashmap_ensure_put(&s, NULL, UINT32_TO_PTR(r + 1), INT_TO_PTR(-1)) >= 0); ++ assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EOPNOTSUPP), true) >= 0); + +- r = run_tests(LOOKUP_SCOPE_USER, user_tests, argv + 1); +- if (r != 0) +- return r; ++ /* Check unshare() is actually filtered. */ ++ assert_se(unshare(CLONE_NEWNS) < 0); ++ assert_se(errno == EOPNOTSUPP); + +- return run_tests(LOOKUP_SCOPE_SYSTEM, system_tests, argv + 1); ++ can_unshare = false; ++ run_tests(LOOKUP_SCOPE_SYSTEM, filters); ++ _exit(EXIT_SUCCESS); ++ } + #else +- return 0; ++ log_tests_skipped("Built without seccomp support, cannot run unshare() filtered tests"); ++#endif ++} ++ ++TEST(run_tests_unprivileged) { ++ _cleanup_strv_free_ char **filters = NULL; ++ ++ if (!have_namespaces()) ++ return (void) log_tests_skipped("unshare() is disabled"); ++ ++ /* safe_fork() clears saved_argv in the child process. Let's copy it. */ ++ assert_se(filters = strv_copy(strv_skip(saved_argv, 1))); ++ ++ if (prepare_ns("(test-execute-unprivileged)") == 0) { ++ assert_se(capability_bounding_set_drop(0, /* right_now = */ true) >= 0); ++ ++ can_unshare = false; ++ run_tests(LOOKUP_SCOPE_USER, filters); ++ _exit(EXIT_SUCCESS); ++ } ++} ++ ++static int intro(void) { ++#if HAS_FEATURE_ADDRESS_SANITIZER ++ if (strstr_ptr(ci_environment(), "travis") || strstr_ptr(ci_environment(), "github-actions")) ++ return log_tests_skipped("Running on Travis CI/GH Actions under ASan, see https://github.com/systemd/systemd/issues/10696"); + #endif ++ /* It is needed otherwise cgroup creation fails */ ++ if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) ++ return log_tests_skipped("not privileged"); ++ ++ if (enter_cgroup_subroot(NULL) == -ENOMEDIUM) ++ return log_tests_skipped("cgroupfs not available"); ++ ++ if (path_is_read_only_fs("/sys") > 0) ++ return log_tests_skipped("/sys is mounted read-only"); ++ ++ /* Create dummy network interface for testing PrivateNetwork=yes */ ++ (void) system("ip link add dummy-test-exec type dummy"); ++ ++ return EXIT_SUCCESS; + } ++ ++static int outro(void) { ++ (void) system("ip link del dummy-test-exec"); ++ (void) rmdir(PRIVATE_UNIT_DIR); ++ ++ return EXIT_SUCCESS; ++} ++ ++DEFINE_TEST_MAIN_FULL(LOG_DEBUG, intro, outro); +diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service +index 1c79e4f722..2a5a1e1ff3 100644 +--- a/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service ++++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service +@@ -3,14 +3,14 @@ + Description=Test DynamicUser= migrate StateDirectory= (preparation) + + [Service] +-ExecStart=test -w /var/lib/test-dynamicuser-migrate +-ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge +-ExecStart=test ! -L /var/lib/test-dynamicuser-migrate +-ExecStart=test ! -L /var/lib/test-dynamicuser-migrate2/hoge +-ExecStart=test -d /var/lib/test-dynamicuser-migrate +-ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge +-ExecStart=touch /var/lib/test-dynamicuser-migrate/yay +-ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay ++ExecStart=test -w %S/test-dynamicuser-migrate ++ExecStart=test -w %S/test-dynamicuser-migrate2/hoge ++ExecStart=test ! -L %S/test-dynamicuser-migrate ++ExecStart=test ! -L %S/test-dynamicuser-migrate2/hoge ++ExecStart=test -d %S/test-dynamicuser-migrate ++ExecStart=test -d %S/test-dynamicuser-migrate2/hoge ++ExecStart=touch %S/test-dynamicuser-migrate/yay ++ExecStart=touch %S/test-dynamicuser-migrate2/hoge/yayyay + ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/test-dynamicuser-migrate:%S/test-dynamicuser-migrate2/hoge"' + + Type=oneshot +diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service +index 015b74ce22..e89f0c5aae 100644 +--- a/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service ++++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service +@@ -3,22 +3,22 @@ + Description=Test DynamicUser= migrate StateDirectory= + + [Service] +-ExecStart=test -w /var/lib/test-dynamicuser-migrate +-ExecStart=test -w /var/lib/test-dynamicuser-migrate2/hoge +-ExecStart=test -L /var/lib/test-dynamicuser-migrate +-ExecStart=test -L /var/lib/test-dynamicuser-migrate2/hoge +-ExecStart=test -d /var/lib/test-dynamicuser-migrate +-ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge +-ExecStart=test -f /var/lib/test-dynamicuser-migrate/yay +-ExecStart=test -f /var/lib/test-dynamicuser-migrate2/hoge/yayyay +-ExecStart=test -d /var/lib/private/test-dynamicuser-migrate +-ExecStart=test -d /var/lib/private/test-dynamicuser-migrate2/hoge +-ExecStart=test -f /var/lib/private/test-dynamicuser-migrate/yay +-ExecStart=test -f /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay +-ExecStart=touch /var/lib/test-dynamicuser-migrate/yay +-ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay +-ExecStart=touch /var/lib/private/test-dynamicuser-migrate/yay +-ExecStart=touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay ++ExecStart=test -w %S/test-dynamicuser-migrate ++ExecStart=test -w %S/test-dynamicuser-migrate2/hoge ++ExecStart=test -L %S/test-dynamicuser-migrate ++ExecStart=test -L %S/test-dynamicuser-migrate2/hoge ++ExecStart=test -d %S/test-dynamicuser-migrate ++ExecStart=test -d %S/test-dynamicuser-migrate2/hoge ++ExecStart=test -f %S/test-dynamicuser-migrate/yay ++ExecStart=test -f %S/test-dynamicuser-migrate2/hoge/yayyay ++ExecStart=test -d %S/private/test-dynamicuser-migrate ++ExecStart=test -d %S/private/test-dynamicuser-migrate2/hoge ++ExecStart=test -f %S/private/test-dynamicuser-migrate/yay ++ExecStart=test -f %S/private/test-dynamicuser-migrate2/hoge/yayyay ++ExecStart=touch %S/test-dynamicuser-migrate/yay ++ExecStart=touch %S/test-dynamicuser-migrate2/hoge/yayyay ++ExecStart=touch %S/private/test-dynamicuser-migrate/yay ++ExecStart=touch %S/private/test-dynamicuser-migrate2/hoge/yayyay + ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/test-dynamicuser-migrate:%S/test-dynamicuser-migrate2/hoge"' + + Type=oneshot +diff --git a/test/test-execute/exec-dynamicuser-statedir.service b/test/test-execute/exec-dynamicuser-statedir.service +index b33b4da74a..b7e36f529e 100644 +--- a/test/test-execute/exec-dynamicuser-statedir.service ++++ b/test/test-execute/exec-dynamicuser-statedir.service +@@ -3,71 +3,71 @@ + Description=Test DynamicUser= with StateDirectory= + + [Service] +-ExecStart=test -w /var/lib/waldo +-ExecStart=test -w /var/lib/quux/pief +-ExecStart=test -w /var/lib/aaa +-ExecStart=test -w /var/lib/aaa/bbb +-ExecStart=test -w /var/lib/aaa/ccc +-ExecStart=test -w /var/lib/xxx +-ExecStart=test -w /var/lib/xxx/yyy +-ExecStart=test -w /var/lib/xxx/zzz +-ExecStart=test -w /var/lib/aaa/111 +-ExecStart=test -w /var/lib/aaa/222 +-ExecStart=test -w /var/lib/aaa/333 ++ExecStart=test -w %S/waldo ++ExecStart=test -w %S/quux/pief ++ExecStart=test -w %S/aaa ++ExecStart=test -w %S/aaa/bbb ++ExecStart=test -w %S/aaa/ccc ++ExecStart=test -w %S/xxx ++ExecStart=test -w %S/xxx/yyy ++ExecStart=test -w %S/xxx/zzz ++ExecStart=test -w %S/aaa/111 ++ExecStart=test -w %S/aaa/222 ++ExecStart=test -w %S/aaa/333 + +-ExecStart=test -d /var/lib/waldo +-ExecStart=test -d /var/lib/quux/pief +-ExecStart=test -d /var/lib/aaa +-ExecStart=test -d /var/lib/aaa/bbb +-ExecStart=test -d /var/lib/aaa/ccc +-ExecStart=test -d /var/lib/xxx +-ExecStart=test -d /var/lib/xxx/yyy +-ExecStart=test -d /var/lib/xxx/zzz +-ExecStart=test -L /var/lib/aaa/111 +-ExecStart=test -L /var/lib/aaa/222 +-ExecStart=test -L /var/lib/aaa/333 ++ExecStart=test -d %S/waldo ++ExecStart=test -d %S/quux/pief ++ExecStart=test -d %S/aaa ++ExecStart=test -d %S/aaa/bbb ++ExecStart=test -d %S/aaa/ccc ++ExecStart=test -d %S/xxx ++ExecStart=test -d %S/xxx/yyy ++ExecStart=test -d %S/xxx/zzz ++ExecStart=test -L %S/aaa/111 ++ExecStart=test -L %S/aaa/222 ++ExecStart=test -L %S/aaa/333 + +-ExecStart=touch /var/lib/waldo/hoge +-ExecStart=touch /var/lib/quux/pief/hoge +-ExecStart=touch /var/lib/aaa/hoge +-ExecStart=touch /var/lib/aaa/bbb/hoge +-ExecStart=touch /var/lib/aaa/ccc/hoge +-ExecStart=touch /var/lib/xxx/hoge +-ExecStart=touch /var/lib/xxx/yyy/hoge +-ExecStart=touch /var/lib/xxx/zzz/hoge +-ExecStart=touch /var/lib/aaa/111/foo +-ExecStart=touch /var/lib/aaa/222/foo +-ExecStart=touch /var/lib/aaa/333/foo ++ExecStart=touch %S/waldo/hoge ++ExecStart=touch %S/quux/pief/hoge ++ExecStart=touch %S/aaa/hoge ++ExecStart=touch %S/aaa/bbb/hoge ++ExecStart=touch %S/aaa/ccc/hoge ++ExecStart=touch %S/xxx/hoge ++ExecStart=touch %S/xxx/yyy/hoge ++ExecStart=touch %S/xxx/zzz/hoge ++ExecStart=touch %S/aaa/111/foo ++ExecStart=touch %S/aaa/222/foo ++ExecStart=touch %S/aaa/333/foo + +-ExecStart=test -f /var/lib/waldo/hoge +-ExecStart=test -f /var/lib/quux/pief/hoge +-ExecStart=test -f /var/lib/aaa/hoge +-ExecStart=test -f /var/lib/aaa/bbb/hoge +-ExecStart=test -f /var/lib/aaa/ccc/hoge +-ExecStart=test -f /var/lib/xxx/hoge +-ExecStart=test -f /var/lib/xxx/yyy/hoge +-ExecStart=test -f /var/lib/xxx/zzz/hoge +-ExecStart=test -f /var/lib/aaa/111/foo +-ExecStart=test -f /var/lib/aaa/222/foo +-ExecStart=test -f /var/lib/aaa/333/foo +-ExecStart=test -f /var/lib/xxx/foo +-ExecStart=test -f /var/lib/xxx/yyy/foo +-ExecStart=test -f /var/lib/xxx/zzz/foo ++ExecStart=test -f %S/waldo/hoge ++ExecStart=test -f %S/quux/pief/hoge ++ExecStart=test -f %S/aaa/hoge ++ExecStart=test -f %S/aaa/bbb/hoge ++ExecStart=test -f %S/aaa/ccc/hoge ++ExecStart=test -f %S/xxx/hoge ++ExecStart=test -f %S/xxx/yyy/hoge ++ExecStart=test -f %S/xxx/zzz/hoge ++ExecStart=test -f %S/aaa/111/foo ++ExecStart=test -f %S/aaa/222/foo ++ExecStart=test -f %S/aaa/333/foo ++ExecStart=test -f %S/xxx/foo ++ExecStart=test -f %S/xxx/yyy/foo ++ExecStart=test -f %S/xxx/zzz/foo + +-ExecStart=test -f /var/lib/private/waldo/hoge +-ExecStart=test -f /var/lib/private/quux/pief/hoge +-ExecStart=test -f /var/lib/private/aaa/hoge +-ExecStart=test -f /var/lib/private/aaa/bbb/hoge +-ExecStart=test -f /var/lib/private/aaa/ccc/hoge +-ExecStart=test -f /var/lib/private/xxx/hoge +-ExecStart=test -f /var/lib/private/xxx/yyy/hoge +-ExecStart=test -f /var/lib/private/xxx/zzz/hoge +-ExecStart=test -f /var/lib/private/aaa/111/foo +-ExecStart=test -f /var/lib/private/aaa/222/foo +-ExecStart=test -f /var/lib/private/aaa/333/foo +-ExecStart=test -f /var/lib/private/xxx/foo +-ExecStart=test -f /var/lib/private/xxx/yyy/foo +-ExecStart=test -f /var/lib/private/xxx/zzz/foo ++ExecStart=test -f %S/private/waldo/hoge ++ExecStart=test -f %S/private/quux/pief/hoge ++ExecStart=test -f %S/private/aaa/hoge ++ExecStart=test -f %S/private/aaa/bbb/hoge ++ExecStart=test -f %S/private/aaa/ccc/hoge ++ExecStart=test -f %S/private/xxx/hoge ++ExecStart=test -f %S/private/xxx/yyy/hoge ++ExecStart=test -f %S/private/xxx/zzz/hoge ++ExecStart=test -f %S/private/aaa/111/foo ++ExecStart=test -f %S/private/aaa/222/foo ++ExecStart=test -f %S/private/aaa/333/foo ++ExecStart=test -f %S/private/xxx/foo ++ExecStart=test -f %S/private/xxx/yyy/foo ++ExecStart=test -f %S/private/xxx/zzz/foo + + ExecStart=sh -x -c 'test "$$STATE_DIRECTORY" = "%S/aaa:%S/aaa/bbb:%S/aaa/ccc:%S/quux/pief:%S/waldo:%S/xxx:%S/xxx/yyy:%S/xxx/zzz"' + +diff --git a/test/test-execute/exec-privatenetwork-yes.service b/test/test-execute/exec-privatenetwork-yes.service +index 0fff048b94..360099d337 100644 +--- a/test/test-execute/exec-privatenetwork-yes.service ++++ b/test/test-execute/exec-privatenetwork-yes.service +@@ -4,5 +4,6 @@ Description=Test for PrivateNetwork + + [Service] + ExecStart=/bin/sh -x -c '! ip link | grep -E "^[0-9]+: " | grep -Ev ": (lo|(erspan|gre|gretap|ip_vti|ip6_vti|ip6gre|ip6tnl|sit|tunl)0@.*):"' ++ExecStart=/bin/sh -x -c '! ip link | grep -E "^[0-9]+: " | grep -F ": dummy-test-exec:"' + Type=oneshot + PrivateNetwork=yes +diff --git a/test/test-execute/exec-specifier-system.service b/test/test-execute/exec-specifier-system.service +new file mode 100644 +index 0000000000..9e8ee567aa +--- /dev/null ++++ b/test/test-execute/exec-specifier-system.service +@@ -0,0 +1,11 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++[Unit] ++Description=Test for specifiers (system) ++ ++[Service] ++Type=oneshot ++ExecStart=test %t = /run ++ExecStart=test %S = /var/lib ++ExecStart=test %C = /var/cache ++ExecStart=test %L = /var/log ++ExecStart=test %E = /etc +diff --git a/test/test-execute/exec-specifier-user.service b/test/test-execute/exec-specifier-user.service +new file mode 100644 +index 0000000000..ee0301a426 +--- /dev/null ++++ b/test/test-execute/exec-specifier-user.service +@@ -0,0 +1,11 @@ ++# SPDX-License-Identifier: LGPL-2.1-or-later ++[Unit] ++Description=Test for specifiers ++ ++[Service] ++Type=oneshot ++ExecStart=sh -c 'test %t = $$XDG_RUNTIME_DIR' ++ExecStart=sh -c 'test %S = %h/.config' ++ExecStart=sh -c 'test %C = %h/.cache' ++ExecStart=sh -c 'test %L = %h/.config/log' ++ExecStart=sh -c 'test %E = %h/.config' +diff --git a/test/test-execute/exec-specifier.service b/test/test-execute/exec-specifier.service +index 2b487bae8c..512f786f83 100644 +--- a/test/test-execute/exec-specifier.service ++++ b/test/test-execute/exec-specifier.service +@@ -13,11 +13,6 @@ ExecStart=test %I = "" + ExecStart=test %j = specifier + ExecStart=test %J = specifier + ExecStart=test %f = /exec/specifier +-ExecStart=test %t = /run +-ExecStart=test %S = /var/lib +-ExecStart=test %C = /var/cache +-ExecStart=test %L = /var/log +-ExecStart=test %E = /etc + ExecStart=test %T = /tmp + ExecStart=test %V = /var/tmp + ExecStart=test %d = %t/credentials/%n +diff --git a/test/test-execute/exec-specifier@.service b/test/test-execute/exec-specifier@.service +index 69e969f716..cb9d0a182a 100644 +--- a/test/test-execute/exec-specifier@.service ++++ b/test/test-execute/exec-specifier@.service +@@ -13,11 +13,6 @@ ExecStart=test %I = foo/bar + ExecStart=test %j = specifier + ExecStart=test %J = specifier + ExecStart=test %f = /foo/bar +-ExecStart=test %t = /run +-ExecStart=test %S = /var/lib +-ExecStart=test %C = /var/cache +-ExecStart=test %L = /var/log +-ExecStart=test %E = /etc + ExecStart=sh -c 'test %u = $$(id -un)' + ExecStart=sh -c 'test %U = $$(id -u)' + ExecStart=sh -c 'test %g = $$(id -gn)' diff --git a/0786-tmpfiles-Add-merge-support-for-copy-files-action.patch b/0786-tmpfiles-Add-merge-support-for-copy-files-action.patch new file mode 100644 index 0000000..5b5d87a --- /dev/null +++ b/0786-tmpfiles-Add-merge-support-for-copy-files-action.patch @@ -0,0 +1,96 @@ +From 129f8896018377cfe9a64e2877517124b79ca87f Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Tue, 9 May 2023 13:45:16 +0200 +Subject: [PATCH] tmpfiles: Add merge support for copy files action + +If '+' is specified with 'C', let's merge the tree with any existing +tree. + +(cherry picked from commit 1fd5ec5697680e2ec6277431bd74cabf48dbc94f) + +Related: RHEL-27512 +--- + man/tmpfiles.d.xml | 22 +++++++++++----------- + src/tmpfiles/tmpfiles.c | 2 +- + test/units/testsuite-22.02.sh | 16 ++++++++++++++++ + 3 files changed, 28 insertions(+), 12 deletions(-) + +diff --git a/man/tmpfiles.d.xml b/man/tmpfiles.d.xml +index bd3bc33ab4..fe2a1dadab 100644 +--- a/man/tmpfiles.d.xml ++++ b/man/tmpfiles.d.xml +@@ -58,10 +58,11 @@ c+ /dev/char-device-to-[re]create mode user group - major + b /dev/block-device-to-create mode user group - major:minor + b+ /dev/block-device-to-[re]create mode user group - major:minor + C /target/to/create - - - cleanup-age /source/to/copy ++C+ /target/to/create - - - cleanup-age /source/to/copy + x /path-or-glob/to/ignore/recursively - - - cleanup-age - + X /path-or-glob/to/ignore - - - cleanup-age - +-r /empty/dir/to/remove - - - - - +-R /dir/to/remove/recursively - - - - - ++r /path-or-glob/to/remove - - - - - ++R /path-or-glob/to/remove/recursively - - - - - + z /path-or-glob/to/adjust/mode mode user group - - + Z /path-or-glob/to/adjust/mode/recursively mode user group - - + t /path-or-glob/to/set/xattrs - - - - xattrs +@@ -325,15 +326,14 @@ L /tmp/foobar - - - - /dev/null + + + C +- Recursively copy a file or directory, if the +- destination files or directories do not exist yet or the +- destination directory is empty. Note that this command will not +- descend into subdirectories if the destination directory already +- exists and is not empty. Instead, the entire copy operation is +- skipped. If the argument is omitted, files from the source directory +- /usr/share/factory/ with the same name +- are copied. Does not follow symlinks. Contents of the directories +- are subject to time based cleanup if the age argument is specified. ++ C+ ++ Recursively copy a file or directory, if the destination files or directories do ++ not exist yet or the destination directory is empty. Note that this command will not descend into ++ subdirectories if the destination directory already exists and is not empty, unless the action is ++ suffixed with +. Instead, the entire copy operation is skipped. If the argument ++ is omitted, files from the source directory /usr/share/factory/ with the same ++ name are copied. Does not follow symlinks. Contents of the directories are subject to time-based ++ cleanup if the age argument is specified. + + + +diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c +index 18bb75715b..ead5c49874 100644 +--- a/src/tmpfiles/tmpfiles.c ++++ b/src/tmpfiles/tmpfiles.c +@@ -1648,7 +1648,7 @@ static int copy_files(Item *i) { + dfd, bn, + i->uid_set ? i->uid : UID_INVALID, + i->gid_set ? i->gid : GID_INVALID, +- COPY_REFLINK | COPY_MERGE_EMPTY | COPY_MAC_CREATE | COPY_HARDLINKS); ++ COPY_REFLINK | ((i->append_or_force) ? COPY_MERGE : COPY_MERGE_EMPTY) | COPY_MAC_CREATE | COPY_HARDLINKS); + + fd = openat(dfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH); + if (fd < 0) { +diff --git a/test/units/testsuite-22.02.sh b/test/units/testsuite-22.02.sh +index 49c55f136b..f233be2499 100755 +--- a/test/units/testsuite-22.02.sh ++++ b/test/units/testsuite-22.02.sh +@@ -121,3 +121,19 @@ EOF + + test "$(stat -c %U:%G:%a /tmp/C/3/f1)" = "root:root:644" + test ! -e /tmp/C/4 ++ ++touch /tmp/C/3-origin/f{2,3,4} ++echo -n ABC > /tmp/C/3/f1 ++ ++systemd-tmpfiles --create - < +Date: Mon, 10 Apr 2023 15:18:33 +0200 +Subject: [PATCH] generator: add generator_open_unit_file_full to allow + creating temporary units + +This function is like `generator_open_unit_file`, but if `ret_temp_path` is +passed, a temporary unit is created instead. + +(cherry picked from commit 8a84e0d7960b7970c16a4efd4c5b0b26c810d22d) + +Related: RHEL-27512 +--- + src/shared/generator.c | 46 ++++++++++++++++++++++++++++-------------- + src/shared/generator.h | 10 ++++----- + 2 files changed, 36 insertions(+), 20 deletions(-) + +diff --git a/src/shared/generator.c b/src/shared/generator.c +index 284e5fc580..29de8ada6b 100644 +--- a/src/shared/generator.c ++++ b/src/shared/generator.c +@@ -20,42 +20,58 @@ + #include "specifier.h" + #include "string-util.h" + #include "time-util.h" ++#include "tmpfile-util.h" + #include "unit-name.h" + #include "util.h" + +-int generator_open_unit_file( ++int generator_open_unit_file_full( + const char *dir, + const char *source, + const char *fn, +- FILE **ret) { ++ FILE **ret_file, ++ char **ret_temp_path) { + + _cleanup_free_ char *p = NULL; + FILE *f; + int r; + + assert(dir); +- assert(fn); +- assert(ret); ++ assert(ret_file); + +- p = path_join(dir, fn); +- if (!p) +- return log_oom(); ++ /* If is specified, it creates a temporary unit file and also returns its ++ * temporary path. */ + +- r = fopen_unlocked(p, "wxe", &f); +- if (r < 0) { +- if (source && r == -EEXIST) +- return log_error_errno(r, +- "Failed to create unit file '%s', as it already exists. Duplicate entry in '%s'?", +- p, source); ++ if (ret_temp_path) { ++ r = fopen_temporary(dir, &f, &p); ++ if (r < 0) ++ return log_error_errno(r, "Failed to create temporary unit file in '%s': %m", dir); ++ ++ (void) fchmod(fileno(f), 0644); + +- return log_error_errno(r, "Failed to create unit file '%s': %m", p); ++ *ret_temp_path = TAKE_PTR(p); ++ } else { ++ assert(fn); ++ ++ p = path_join(dir, fn); ++ if (!p) ++ return log_oom(); ++ ++ r = fopen_unlocked(p, "wxe", &f); ++ if (r < 0) { ++ if (source && r == -EEXIST) ++ return log_error_errno(r, ++ "Failed to create unit file '%s', as it already exists. Duplicate entry in '%s'?", ++ p, source); ++ ++ return log_error_errno(r, "Failed to create unit file '%s': %m", p); ++ } + } + + fprintf(f, + "# Automatically generated by %s\n\n", + program_invocation_short_name); + +- *ret = f; ++ *ret_file = f; + return 0; + } + +diff --git a/src/shared/generator.h b/src/shared/generator.h +index 111900fd45..d97d6edc67 100644 +--- a/src/shared/generator.h ++++ b/src/shared/generator.h +@@ -6,11 +6,11 @@ + #include "macro.h" + #include "main-func.h" + +-int generator_open_unit_file( +- const char *dest, +- const char *source, +- const char *name, +- FILE **file); ++int generator_open_unit_file_full(const char *dest, const char *source, const char *name, FILE **ret_file, char **ret_temp_path); ++ ++static inline int generator_open_unit_file(const char *dest, const char *source, const char *name, FILE **ret_file) { ++ return generator_open_unit_file_full(dest, source, name, ret_file, NULL); ++} + + int generator_add_symlink_full(const char *dir, const char *dst, const char *dep_type, const char *src, const char *instance); + diff --git a/0788-network-generator-rewrite-unit-if-it-already-exists-.patch b/0788-network-generator-rewrite-unit-if-it-already-exists-.patch new file mode 100644 index 0000000..7ece237 --- /dev/null +++ b/0788-network-generator-rewrite-unit-if-it-already-exists-.patch @@ -0,0 +1,142 @@ +From 8d7665b3e327deb0868b97a159acfdb266a6a5e9 Mon Sep 17 00:00:00 2001 +From: Antonio Alvarez Feijoo +Date: Mon, 10 Apr 2023 15:18:53 +0200 +Subject: [PATCH] network-generator: rewrite unit if it already exists and its + content changed + +When the `systemd-network-generator` is included in the initrd and runs from +there first, the next times it runs after switching to real root it +thinks there is a duplicate entry on the kernel command line. + +This patch rewrites the unit file if the content has changed, instead of +displaying an error message. + +(cherry picked from commit f3e4d04298bb73b836dd7ca90f7c7b09de1e776b) + +Related: RHEL-27512 +--- + src/network/generator/main.c | 55 ++++++++++++++++++++++++++++-------- + 1 file changed, 43 insertions(+), 12 deletions(-) + +diff --git a/src/network/generator/main.c b/src/network/generator/main.c +index a36fe98c86..2574bc1136 100644 +--- a/src/network/generator/main.c ++++ b/src/network/generator/main.c +@@ -3,6 +3,7 @@ + #include + + #include "fd-util.h" ++#include "fs-util.h" + #include "generator.h" + #include "macro.h" + #include "main-func.h" +@@ -16,67 +17,97 @@ + static const char *arg_root = NULL; + + static int network_save(Network *network, const char *dest_dir) { +- _cleanup_free_ char *filename = NULL; ++ _cleanup_free_ char *filename = NULL, *p = NULL; ++ _cleanup_(unlink_and_freep) char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(network); + ++ r = generator_open_unit_file_full(dest_dir, NULL, NULL, &f, &temp_path); ++ if (r < 0) ++ return r; ++ ++ network_dump(network, f); ++ + r = asprintf(&filename, "%s-%s.network", + isempty(network->ifname) ? "91" : "90", + isempty(network->ifname) ? "default" : network->ifname); + if (r < 0) + return log_oom(); + +- r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f); ++ p = path_join(dest_dir, filename); ++ if (!p) ++ return log_oom(); ++ ++ r = conservative_rename(temp_path, p); + if (r < 0) + return r; + +- network_dump(network, f); +- ++ temp_path = mfree(temp_path); + return 0; + } + + static int netdev_save(NetDev *netdev, const char *dest_dir) { +- _cleanup_free_ char *filename = NULL; ++ _cleanup_free_ char *filename = NULL, *p = NULL; ++ _cleanup_(unlink_and_freep) char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(netdev); + ++ r = generator_open_unit_file_full(dest_dir, NULL, NULL, &f, &temp_path); ++ if (r < 0) ++ return r; ++ ++ netdev_dump(netdev, f); ++ + r = asprintf(&filename, "90-%s.netdev", + netdev->ifname); + if (r < 0) + return log_oom(); + +- r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f); ++ p = path_join(dest_dir, filename); ++ if (!p) ++ return log_oom(); ++ ++ r = conservative_rename(temp_path, p); + if (r < 0) + return r; + +- netdev_dump(netdev, f); +- ++ temp_path = mfree(temp_path); + return 0; + } + + static int link_save(Link *link, const char *dest_dir) { +- _cleanup_free_ char *filename = NULL; ++ _cleanup_free_ char *filename = NULL, *p = NULL; ++ _cleanup_(unlink_and_freep) char *temp_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + int r; + + assert(link); + ++ r = generator_open_unit_file_full(dest_dir, NULL, NULL, &f, &temp_path); ++ if (r < 0) ++ return r; ++ ++ link_dump(link, f); ++ + filename = strjoin(!isempty(link->ifname) ? "90" : + !hw_addr_is_null(&link->mac) ? "91" : "92", + "-", link->filename, ".link"); + if (!filename) + return log_oom(); + +- r = generator_open_unit_file(dest_dir, "kernel command line", filename, &f); ++ p = path_join(dest_dir, filename); ++ if (!p) ++ return log_oom(); ++ ++ r = conservative_rename(temp_path, p); + if (r < 0) + return r; + +- link_dump(link, f); +- ++ temp_path = mfree(temp_path); + return 0; + } + diff --git a/0789-ci-drop-super-linter-s-shellcheck.patch b/0789-ci-drop-super-linter-s-shellcheck.patch new file mode 100644 index 0000000..53662a6 --- /dev/null +++ b/0789-ci-drop-super-linter-s-shellcheck.patch @@ -0,0 +1,38 @@ +From 696206a798647adc73faab26ab5b7543df939372 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 17 Jul 2023 17:54:59 +0200 +Subject: [PATCH] ci: drop super-linter's shellcheck + +It's been a while since we introduced Differential ShellCheck and it +proved to be quite useful (and in some ways even better than the shellcheck +run by super-linter). So, to have only one linter scream at us for not +knowing how to write bash properly, let's drop the super-linter's one in +favor of Differential ShellCheck. + +Follow-up for https://github.com/systemd/systemd/pull/24328#pullrequestreview-1074127504 + +(cherry picked from commit c4b167f857fe5c228da4d4950a3eae13f53c645c) + +Related: RHEL-27512 +--- + .github/workflows/linter.yml | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml +index eddd350122..8dd3b075ad 100644 +--- a/.github/workflows/linter.yml ++++ b/.github/workflows/linter.yml +@@ -32,13 +32,5 @@ jobs: + uses: github/super-linter/slim@01d3218744765b55c3b5ffbb27e50961e50c33c5 + env: + DEFAULT_BRANCH: main +- MULTI_STATUS: false +- # Excludes: +- # - man/.* - all snippets in man pages (false positives due to +- # missing shebangs) +- # - .*\.(in|SKELETON) - all template/skeleton files +- # except kernel-install +- FILTER_REGEX_EXCLUDE: .*/(man/.*|([^k]|k(k|ek)*([^ek]|e[^kr]))*(k(k|ek)*e?)?\.(in|SKELETON))$ + VALIDATE_ALL_CODEBASE: false +- VALIDATE_BASH: true + VALIDATE_GITHUB_ACTIONS: true diff --git a/0790-mkosi-make-sure-we-build-use-RHEL-9-stuff.patch b/0790-mkosi-make-sure-we-build-use-RHEL-9-stuff.patch new file mode 100644 index 0000000..9433ba7 --- /dev/null +++ b/0790-mkosi-make-sure-we-build-use-RHEL-9-stuff.patch @@ -0,0 +1,130 @@ +From 57d14d938573b0670d3205bf27a416bcf18424d4 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Wed, 28 Feb 2024 12:15:44 +0100 +Subject: [PATCH] mkosi: make sure we build & use RHEL 9 stuff + +- drop Hyperscale SIG repos, so we don't pull in btrfs stuff +- use XFS for rootfs +- install gnu-efi headers, since RHEL 9 sd-boot still requires it + +RHEL-only + +Related: RHEL-27512 +--- + mkosi.conf | 2 +- + mkosi.conf.d/10-centos.conf | 2 +- + mkosi.images/base/mkosi.build.chroot | 8 ++++++++ + .../base/mkosi.conf.d/10-centos-fedora.conf | 2 ++ + .../usr/lib/systemd/system-preset/00-mkosi.preset | 13 ++++--------- + .../system/mkosi.conf.d/10-centos-fedora.conf | 1 + + .../mkosi.extra/usr/lib/repart.d/20-root.conf | 3 +-- + 7 files changed, 18 insertions(+), 13 deletions(-) + +diff --git a/mkosi.conf b/mkosi.conf +index 9ec4faf122..d5cde391dd 100644 +--- a/mkosi.conf ++++ b/mkosi.conf +@@ -23,7 +23,7 @@ KernelCommandLineExtra=systemd.crash_shell + systemd.log_level=debug + systemd.log_ratelimit_kmsg=0 + systemd.journald.forward_to_console +- systemd.journald.max_level_console=warning ++ systemd.journald.max_level_console=info + # Disable the kernel's ratelimiting on userspace logging to kmsg. + printk.devkmsg=on + # Make sure /sysroot is mounted rw in the initrd. +diff --git a/mkosi.conf.d/10-centos.conf b/mkosi.conf.d/10-centos.conf +index ae2706c791..a740548d46 100644 +--- a/mkosi.conf.d/10-centos.conf ++++ b/mkosi.conf.d/10-centos.conf +@@ -7,4 +7,4 @@ Distribution=centos + @Release=9 + Repositories=epel + epel-next +- hyperscale-packages-main ++ crb +diff --git a/mkosi.images/base/mkosi.build.chroot b/mkosi.images/base/mkosi.build.chroot +index ba0c92eef2..3427d0e241 100755 +--- a/mkosi.images/base/mkosi.build.chroot ++++ b/mkosi.images/base/mkosi.build.chroot +@@ -106,6 +106,14 @@ if [ ! -f "$BUILDDIR"/build.ninja ]; then + -D xenctrl="$([[ "$ID" =~ debian|ubuntu|fedora|opensuse ]] && echo true || echo false)" + -D libiptc="$([[ "$ID" =~ debian|ubuntu ]] && echo true || echo false)" + -D libcryptsetup-plugins="$([[ "$ID" = "centos" ]] && [[ "$VERSION" = "8" ]] && echo false || echo true)" ++ # Necessary on RHEL 9 to build sd-boot stuff ++ -D gnu-efi=true ++ # Disable stuff we don't build on RHEL ++ -D timesyncd=false ++ -D homed=false ++ -D userdb=false ++ -D portabled=false ++ -D networkd=false + ) + + # On debian-like systems the library directory is not /usr/lib64 but /usr/lib//. +diff --git a/mkosi.images/base/mkosi.conf.d/10-centos-fedora.conf b/mkosi.images/base/mkosi.conf.d/10-centos-fedora.conf +index d7a135a5c0..b25b7b4185 100644 +--- a/mkosi.images/base/mkosi.conf.d/10-centos-fedora.conf ++++ b/mkosi.images/base/mkosi.conf.d/10-centos-fedora.conf +@@ -29,6 +29,8 @@ BuildPackages= + bpftool + docbook-xsl + findutils ++ gnu-efi-compat # Necessary for sd-boot on RHEL 9 ++ gnu-efi-devel # Necessary for sd-boot on RHEL 9 + libgcrypt-devel # CentOS Stream 8 libgcrypt-devel doesn't ship a pkg-config file. + libxslt + pam-devel +diff --git a/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/00-mkosi.preset b/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/00-mkosi.preset +index 070af4c67a..42e5af3ec9 100644 +--- a/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/00-mkosi.preset ++++ b/mkosi.images/base/mkosi.extra/usr/lib/systemd/system-preset/00-mkosi.preset +@@ -9,16 +9,9 @@ disable dnsmasq.service + disable isc-dhcp-server.service + disable isc-dhcp-server6.service + +-# Pulled in via dracut-network by kexec-tools on Fedora. +-disable NetworkManager* +- + # Make sure dbus-broker is started by default on Debian/Ubuntu. + enable dbus-broker.service + +-# systemd-networkd is disabled by default on Fedora so make sure it is enabled. +-enable systemd-networkd.service +-enable systemd-networkd-wait-online.service +- + # We install dnf in some images but it's only going to be used rarely, + # so let's not have dnf create its cache. + disable dnf-makecache.* +@@ -26,5 +19,7 @@ disable dnf-makecache.* + # We have journald to receive audit data so let's make sure we're not running auditd as well + disable auditd.service + +-# systemd-timesyncd is not enabled by default in the default systemd preset so enable it here instead. +-enable systemd-timesyncd.service ++# We don't ship sd-networkd on RHEL 9, so replace it with NM ++disable systemd-networkd.service ++disable systemd-networkd-wait-online.service ++enable NetworkManager* +diff --git a/mkosi.images/system/mkosi.conf.d/10-centos-fedora.conf b/mkosi.images/system/mkosi.conf.d/10-centos-fedora.conf +index 871186d5ca..23cfd4ecc0 100644 +--- a/mkosi.images/system/mkosi.conf.d/10-centos-fedora.conf ++++ b/mkosi.images/system/mkosi.conf.d/10-centos-fedora.conf +@@ -31,3 +31,4 @@ Packages= + python3dist(pytest) + quota + vim-common ++ vim +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/repart.d/20-root.conf b/mkosi.images/system/mkosi.extra/usr/lib/repart.d/20-root.conf +index 71eb9e38c4..31e8313263 100644 +--- a/mkosi.images/system/mkosi.extra/usr/lib/repart.d/20-root.conf ++++ b/mkosi.images/system/mkosi.extra/usr/lib/repart.d/20-root.conf +@@ -2,7 +2,6 @@ + + [Partition] + Type=root +-Format=btrfs ++Format=xfs + SizeMinBytes=1G +-Subvolumes=/home /var + MakeDirectories=/home /var diff --git a/0791-ci-backport-mkosi-CI-configuration-from-upstream.patch b/0791-ci-backport-mkosi-CI-configuration-from-upstream.patch new file mode 100644 index 0000000..41afffd --- /dev/null +++ b/0791-ci-backport-mkosi-CI-configuration-from-upstream.patch @@ -0,0 +1,217 @@ +From 45bcebd103f23fb595d0ff1d5e02ea5edd25f12d Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 27 Feb 2024 12:53:35 +0100 +Subject: [PATCH] ci: backport mkosi CI configuration from upstream + +Notes: + - on RHEL 9 we don't have vsock support in systemd, so we have to fall + back to some "older" checks (i.e. pre-6aca147f82). + - our systemd-repart doesn't automatically fall back to Format=swap + for Type=swap partitions, so we have to do that explicitely + - don't pull in sd-resolved and sd-networkd, since the former needs + some extra configuration to work alongsideNM, and we don't + build the latter at all on RHEL 9 + +RHEL-only + +Related: RHEL-27512 +--- + .github/workflows/mkosi.yml | 139 ++++++++++++++++++ + .../mkosi.extra/usr/lib/repart.d/15-swap.conf | 1 + + .../lib/systemd/mkosi-check-and-shutdown.sh | 3 + + .../system/mkosi-check-and-shutdown.service | 5 +- + 4 files changed, 144 insertions(+), 4 deletions(-) + create mode 100644 .github/workflows/mkosi.yml + +diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml +new file mode 100644 +index 0000000000..f9b6d9ba58 +--- /dev/null ++++ b/.github/workflows/mkosi.yml +@@ -0,0 +1,139 @@ ++--- ++# vi: ts=2 sw=2 et: ++# SPDX-License-Identifier: LGPL-2.1-or-later ++# Simple boot tests that build and boot the mkosi images generated by the mkosi config files in mkosi.conf.d/. ++name: mkosi ++ ++on: ++ push: ++ branches: ++ - main ++ - v[0-9]+-stable ++ paths: ++ - '**' ++ - '!README*' ++ - '!LICENSE*' ++ - '!LICENSES/**' ++ - '!TODO' ++ - '!docs/**' ++ - '!man/**' ++ - '!catalog/**' ++ - '!shell-completion/**' ++ - '!po/**' ++ - '!.**' ++ - '.github/**' ++ ++ pull_request: ++ branches: ++ - main ++ - v[0-9]+-stable ++ paths: ++ - '**' ++ - '!README*' ++ - '!LICENSE*' ++ - '!LICENSES/**' ++ - '!TODO' ++ - '!docs/**' ++ - '!man/**' ++ - '!catalog/**' ++ - '!shell-completion/**' ++ - '!po/**' ++ - '!.**' ++ - '.github/**' ++ ++permissions: ++ contents: read ++ ++jobs: ++ ci: ++ runs-on: ubuntu-22.04 ++ concurrency: ++ group: ${{ github.workflow }}-${{ matrix.distro }}-${{ matrix.release }}-${{ github.ref }} ++ cancel-in-progress: true ++ strategy: ++ fail-fast: false ++ matrix: ++ include: ++ - distro: centos ++ release: "9" ++ ++ env: ++ SYSTEMD_LOG_LEVEL: debug ++ ++ steps: ++ - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 ++ - uses: systemd/mkosi@070528fec478fc93af7ec057a5d2fd0045123c99 ++ ++ - name: Configure ++ run: | ++ tee mkosi.local.conf < +Date: Wed, 28 Feb 2024 19:51:17 +0100 +Subject: [PATCH] mkosi: explicitly enroll SecureBoot keys + +The automagic enrollment works only with systemd v253 onwards, on v252 +we need to do this one extra step. + +RHEL-only + +Related: RHEL-27512 +--- + mkosi.images/system/mkosi.extra/efi/loader/loader.conf | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 mkosi.images/system/mkosi.extra/efi/loader/loader.conf + +diff --git a/mkosi.images/system/mkosi.extra/efi/loader/loader.conf b/mkosi.images/system/mkosi.extra/efi/loader/loader.conf +new file mode 100644 +index 0000000000..f7a9445d89 +--- /dev/null ++++ b/mkosi.images/system/mkosi.extra/efi/loader/loader.conf +@@ -0,0 +1 @@ ++secure-boot-enroll force diff --git a/0793-test-execute-also-mount-tmpfs-on-dev-shm.patch b/0793-test-execute-also-mount-tmpfs-on-dev-shm.patch new file mode 100644 index 0000000..b80a67e --- /dev/null +++ b/0793-test-execute-also-mount-tmpfs-on-dev-shm.patch @@ -0,0 +1,37 @@ +From ad27f1973d24a051ddfc80efcd00446eddf4380d Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 17 Feb 2023 10:21:58 +0900 +Subject: [PATCH] test-execute: also mount tmpfs on /dev/shm + +Otherwise, if /dev/shm has a directory that cannot be accessible by +unprivileged user, then we cannot pick a dynamic user, and test service +may fail with unexpected error code: +--- +Failed to enter shared memory directory /dev/shm/systemd-watch-bind-BqAGlN: Permission denied +exec-dynamicuser-supplementarygroups.service: Failed to update dynamic user credentials: Device or resource busy +exec-dynamicuser-supplementarygroups.service: Failed at step USER spawning /bin/sh: Device or resource busy +src/test/test-execute.c:885:test_exec_dynamicuser: exec-dynamicuser-supplementarygroups.service: can_unshare=no: exit status 217, expected 216 +--- + +Follow-up for 4e032f654b94c2544ccf937209303766dfa66c24. + +(cherry picked from commit d51e31ac4197d971a468ff41f15593bb6fdb29f3) + +Related: RHEL-27512 +--- + src/test/test-execute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/test/test-execute.c b/src/test/test-execute.c +index 665ae8a833..f37da945b6 100644 +--- a/src/test/test-execute.c ++++ b/src/test/test-execute.c +@@ -1262,7 +1262,7 @@ static int prepare_ns(const char *process_name) { + assert_se(mkdir_p(PRIVATE_UNIT_DIR, 0755) >= 0); + + /* Mount tmpfs on the following directories to make not StateDirectory= or friends disturb the host. */ +- FOREACH_STRING(p, "/root", "/tmp", "/var/tmp", "/var/lib", PRIVATE_UNIT_DIR) ++ FOREACH_STRING(p, "/dev/shm", "/root", "/tmp", "/var/tmp", "/var/lib", PRIVATE_UNIT_DIR) + assert_se(mount_nofollow_verbose(LOG_DEBUG, "tmpfs", p, "tmpfs", MS_NOSUID|MS_NODEV, NULL) >= 0); + + /* Copy unit files to make them accessible even when unprivileged. */ diff --git a/0794-mkosi-fix-UKI-addons-test.patch b/0794-mkosi-fix-UKI-addons-test.patch new file mode 100644 index 0000000..ca52e56 --- /dev/null +++ b/0794-mkosi-fix-UKI-addons-test.patch @@ -0,0 +1,106 @@ +From 8fd8b29eda64dd09ea01f1b87cc4c65950fb5e3a Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 5 Mar 2024 11:49:30 +0100 +Subject: [PATCH] mkosi: fix UKI addons test + +The test hasn't been working for a while, since there's no /efi or /boot +in $DESTDIR. + +(cherry picked from commit 374fa8e8533e4834337a22613c7bada205dc1853) + +Related: RHEL-27512 +--- + mkosi.images/base/mkosi.build.chroot | 12 ------------ + mkosi.images/system/mkosi.conf.d/10-arch.conf | 1 + + .../system/mkosi.conf.d/10-debian-ubuntu.conf | 1 + + mkosi.images/system/mkosi.conf.d/10-fedora.conf | 1 + + mkosi.images/system/mkosi.conf.d/10-opensuse.conf | 1 + + mkosi.images/system/mkosi.postinst.chroot | 11 ++++++++++- + 6 files changed, 14 insertions(+), 13 deletions(-) + +diff --git a/mkosi.images/base/mkosi.build.chroot b/mkosi.images/base/mkosi.build.chroot +index 3427d0e241..c46d667a90 100755 +--- a/mkosi.images/base/mkosi.build.chroot ++++ b/mkosi.images/base/mkosi.build.chroot +@@ -177,15 +177,3 @@ if [ "$WITH_TESTS" = 1 ]; then + fi + + ( set -x; meson install -C "$BUILDDIR" --quiet --no-rebuild --only-changed ) +- +-# Ensure that side-loaded PE addons are loaded if signed, and ignored if not +-if [ -d "${DESTDIR}/boot/loader" ]; then +- addons_dir="${DESTDIR}/boot/loader/addons" +-elif [ -d "${DESTDIR}/efi/loader" ]; then +- addons_dir="${DESTDIR}/efi/loader/addons" +-fi +-if [ -n "${addons_dir}" ]; then +- mkdir -p "${addons_dir}" +- ukify --secureboot-private-key mkosi.secure-boot.key --secureboot-certificate mkosi.secure-boot.crt --cmdline this_should_be_here -o "${addons_dir}/good.addon.efi" +- ukify --cmdline this_should_not_be_here -o "${addons_dir}/bad.addon.efi" +-fi +diff --git a/mkosi.images/system/mkosi.conf.d/10-arch.conf b/mkosi.images/system/mkosi.conf.d/10-arch.conf +index e1a511c979..a3d008d10f 100644 +--- a/mkosi.images/system/mkosi.conf.d/10-arch.conf ++++ b/mkosi.images/system/mkosi.conf.d/10-arch.conf +@@ -23,5 +23,6 @@ Packages= + python-pytest + python3 + quota-tools ++ sbsigntools + shadow + vim +diff --git a/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu.conf b/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu.conf +index 348bdb2992..d6e3f20222 100644 +--- a/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu.conf ++++ b/mkosi.images/system/mkosi.conf.d/10-debian-ubuntu.conf +@@ -19,6 +19,7 @@ Packages= + netcat-openbsd + openssh-server + openssh-client ++ sbsigntool + passwd + policykit-1 + procps +diff --git a/mkosi.images/system/mkosi.conf.d/10-fedora.conf b/mkosi.images/system/mkosi.conf.d/10-fedora.conf +index 5863f03b19..7554ad2dc3 100644 +--- a/mkosi.images/system/mkosi.conf.d/10-fedora.conf ++++ b/mkosi.images/system/mkosi.conf.d/10-fedora.conf +@@ -9,3 +9,4 @@ Packages= + compsize + f2fs-tools + glibc-langpack-en ++ sbsigntools +diff --git a/mkosi.images/system/mkosi.conf.d/10-opensuse.conf b/mkosi.images/system/mkosi.conf.d/10-opensuse.conf +index 71434b4560..ffcb664224 100644 +--- a/mkosi.images/system/mkosi.conf.d/10-opensuse.conf ++++ b/mkosi.images/system/mkosi.conf.d/10-opensuse.conf +@@ -20,5 +20,6 @@ Packages= + python3-psutil + python3-pytest + quota ++ sbsigntools + shadow + vim +diff --git a/mkosi.images/system/mkosi.postinst.chroot b/mkosi.images/system/mkosi.postinst.chroot +index 692242da38..330fa3b73e 100755 +--- a/mkosi.images/system/mkosi.postinst.chroot ++++ b/mkosi.images/system/mkosi.postinst.chroot +@@ -1,4 +1,4 @@ +-#!/bin/sh ++#!/bin/bash + # SPDX-License-Identifier: LGPL-2.1-or-later + set -e + +@@ -100,3 +100,12 @@ mkdir -p /usr/lib/tmpfiles.d + cat >/usr/lib/tmpfiles.d/testuser.conf </dev/null; then ++ # Ensure that side-loaded PE addons are loaded if signed, and ignored if not ++ addons_dir=/efi/loader/addons ++ mkdir -p "$addons_dir" ++ ukify build --secureboot-private-key mkosi.key --secureboot-certificate mkosi.crt --cmdline this_should_be_here -o "$addons_dir/good.addon.efi" ++ ukify build --cmdline this_should_not_be_here -o "$addons_dir/bad.addon.efi" ++fi diff --git a/0795-Revert-mkosi-Disable-cmdline-addon-test-for-now.patch b/0795-Revert-mkosi-Disable-cmdline-addon-test-for-now.patch new file mode 100644 index 0000000..3da703d --- /dev/null +++ b/0795-Revert-mkosi-Disable-cmdline-addon-test-for-now.patch @@ -0,0 +1,36 @@ +From c77533f7cc265ce7fc4c933f8ebb3828c0c9ff57 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 5 Mar 2024 11:51:52 +0100 +Subject: [PATCH] Revert "mkosi: Disable cmdline addon test for now" + +Let's see if this finally works. + +This reverts commit e167a8283d5964ca0f903b3e362ab7e48a1ed2ab. + +(cherry picked from commit d9c8cf40b5c920ae59a02fa2bab32e93dad33542) + +Related: RHEL-27512 +--- + .../usr/lib/systemd/mkosi-check-and-shutdown.sh | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh b/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh +index 210fa78850..076026d097 100755 +--- a/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh ++++ b/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh +@@ -12,9 +12,12 @@ systemctl --failed --no-legend | tee /failed-services + if ! systemd-detect-virt --container; then + cmp /sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c <(printf '\6\0\0\0\1') + cmp /sys/firmware/efi/efivars/SetupMode-8be4df61-93ca-11d2-aa0d-00e098032b8c <(printf '\6\0\0\0\0') +- # TODO: Figure out why this is failing +- # grep -q this_should_be_here /proc/cmdline +- # grep -q this_should_not_be_here /proc/cmdline && exit 1 ++ ++ if command -v sbsign &>/dev/null; then ++ cat /proc/cmdline ++ grep -q this_should_be_here /proc/cmdline ++ (! grep -q this_should_not_be_here /proc/cmdline) ++ fi + fi + + # Exit with non-zero EC if the /failed-services file is not empty (we have -e set) diff --git a/0796-Revert-mkosi-Don-t-fail-on-systemd-vconsole-setup.se.patch b/0796-Revert-mkosi-Don-t-fail-on-systemd-vconsole-setup.se.patch new file mode 100644 index 0000000..057be4f --- /dev/null +++ b/0796-Revert-mkosi-Don-t-fail-on-systemd-vconsole-setup.se.patch @@ -0,0 +1,31 @@ +From fd051e3de351860b52ff1bbe6cab1fa9c153be76 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 5 Mar 2024 12:18:40 +0100 +Subject: [PATCH] Revert "mkosi: Don't fail on systemd-vconsole-setup.service + failure for now" + +This doesn't seem to fail anymore. + +This reverts commit 84c7929cd461f6f1cc2c44c69877b9fd0676c794. + +(cherry picked from commit 193fa9d7fe383801bf3ff53e5ee5a2c52107270f) + +Related: RHEL-27512 +--- + .../mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh b/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh +index 076026d097..4011ab930b 100755 +--- a/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh ++++ b/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh +@@ -3,9 +3,6 @@ + + rm -f /testok + +-# TODO: Figure out why this is failing +-systemctl reset-failed systemd-vconsole-setup.service +- + systemctl --failed --no-legend | tee /failed-services + + # Check that secure boot keys were properly enrolled. diff --git a/0797-mkosi-make-shellcheck-happy.patch b/0797-mkosi-make-shellcheck-happy.patch new file mode 100644 index 0000000..98ba82e --- /dev/null +++ b/0797-mkosi-make-shellcheck-happy.patch @@ -0,0 +1,25 @@ +From f3646608832288bb08b705de9b54a04a618a1ce3 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 5 Mar 2024 12:41:30 +0100 +Subject: [PATCH] mkosi: make shellcheck happy + +(cherry picked from commit e86b1a9b0f1d2fc150edde18ea6f748b9423df3c) + +Related: RHEL-27512 +--- + mkosi.images/base/mkosi.build.chroot | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/mkosi.images/base/mkosi.build.chroot b/mkosi.images/base/mkosi.build.chroot +index c46d667a90..69430c304d 100755 +--- a/mkosi.images/base/mkosi.build.chroot ++++ b/mkosi.images/base/mkosi.build.chroot +@@ -8,7 +8,7 @@ set -e + # We don't want to install our build of systemd in the base image, but use it as an extra tree for the + # initrd and system images, so override DESTDIR to store it in the output directory so we can reference it as + # an extra tree in the initrd and system image builds. +-DESTDIR="$OUTPUTDIR/systemd" ++export DESTDIR="$OUTPUTDIR/systemd" + + # If mkosi.builddir/ exists mkosi will set $BUILDDIR to it, let's then use it + # as out-of-tree build dir. Otherwise, let's make up our own builddir. diff --git a/0798-mkosi-use-pesign-for-signing-UKI-addons.patch b/0798-mkosi-use-pesign-for-signing-UKI-addons.patch new file mode 100644 index 0000000..47f9e1c --- /dev/null +++ b/0798-mkosi-use-pesign-for-signing-UKI-addons.patch @@ -0,0 +1,67 @@ +From de81c5b27d15ffc61a2c586f8b9a6a7943c061c7 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 5 Mar 2024 20:22:19 +0100 +Subject: [PATCH] mkosi: use pesign for signing UKI addons + +In C9S/RHEL9 we don't ship sbsign, so we have to use pesign instead. +Unfortunately, ukify doesn't support singing with pesign, so we have to +do that manually. + +Related: RHEL-27512 +RHEL-only +--- + .../system/mkosi.conf.d/10-centos/mkosi.conf | 3 +++ + .../usr/lib/systemd/mkosi-check-and-shutdown.sh | 2 +- + mkosi.images/system/mkosi.postinst.chroot | 13 ++++++++++--- + 3 files changed, 14 insertions(+), 4 deletions(-) + +diff --git a/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.conf b/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.conf +index 146e03a895..c79ced5130 100644 +--- a/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.conf ++++ b/mkosi.images/system/mkosi.conf.d/10-centos/mkosi.conf +@@ -6,3 +6,6 @@ Distribution=centos + [Content] + Packages= + kernel-modules # For squashfs support ++ nss-tools ++ openssl ++ pesign +diff --git a/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh b/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh +index 4011ab930b..f32128ead2 100755 +--- a/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh ++++ b/mkosi.images/system/mkosi.extra/usr/lib/systemd/mkosi-check-and-shutdown.sh +@@ -10,7 +10,7 @@ if ! systemd-detect-virt --container; then + cmp /sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c <(printf '\6\0\0\0\1') + cmp /sys/firmware/efi/efivars/SetupMode-8be4df61-93ca-11d2-aa0d-00e098032b8c <(printf '\6\0\0\0\0') + +- if command -v sbsign &>/dev/null; then ++ if command -v pesign &>/dev/null; then + cat /proc/cmdline + grep -q this_should_be_here /proc/cmdline + (! grep -q this_should_not_be_here /proc/cmdline) +diff --git a/mkosi.images/system/mkosi.postinst.chroot b/mkosi.images/system/mkosi.postinst.chroot +index 330fa3b73e..8d2c3d6a37 100755 +--- a/mkosi.images/system/mkosi.postinst.chroot ++++ b/mkosi.images/system/mkosi.postinst.chroot +@@ -101,11 +101,18 @@ cat >/usr/lib/tmpfiles.d/testuser.conf </dev/null; then ++# RHEL 9 only: we don't ship sbsigntools in RHEL 9 so we have to use pesign ++# instead. Unfortunately, ATTOW ukify doesn't support signing with pesign, so we ++# have to do it manually :( ++if command -v pesign &>/dev/null; then + # Ensure that side-loaded PE addons are loaded if signed, and ignored if not + addons_dir=/efi/loader/addons + mkdir -p "$addons_dir" +- ukify build --secureboot-private-key mkosi.key --secureboot-certificate mkosi.crt --cmdline this_should_be_here -o "$addons_dir/good.addon.efi" ++ ukify build --cmdline this_should_be_here -o "good.addon.efi" + ukify build --cmdline this_should_not_be_here -o "$addons_dir/bad.addon.efi" ++ ++ openssl pkcs12 -name "mkosi" -passin "pass:" -passout "pass:" -export -out mkosi.p12 -inkey mkosi.key -in mkosi.crt ++ pk12util -W "" -i mkosi.p12 -d /etc/pki/pesign ++ pesign -v -s -c "mkosi" -i "good.addon.efi" -o "$addons_dir/good.addon.efi" ++ pesign -S -i"$addons_dir/good.addon.efi" + fi diff --git a/0799-test-copy-out-the-necessary-test-data-before-we-star.patch b/0799-test-copy-out-the-necessary-test-data-before-we-star.patch new file mode 100644 index 0000000..365a05e --- /dev/null +++ b/0799-test-copy-out-the-necessary-test-data-before-we-star.patch @@ -0,0 +1,65 @@ +From 59162dc947e9c9538f98f0a00ab9eeef9c7bae71 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 11 Jul 2023 21:03:22 +0200 +Subject: [PATCH] test: copy out the necessary test data before we start + overmounting stuff + +Otherwise the get_testdata_dir() call fails if the source tree is under +/root (which is usually the case in CIs). + +I got bitten by this after leaving the source tree under /root but moving the +$BUILD_DIR elsewhere. This used to work by accident, as load_testdata_env() +would try to read $BUILD_DIR/systemd-runtest.env, but would fail if the +$BUILD_DIR is also under /root and fall back to SYSTEMD_TEST_DATA +(/lib/systemd/tests/testdata), which usually exist as we install the just built +revision. However, if the $BUILD_DIR is outside of /root we'd read +$BUILD_DIR/systemd-runtest.env which contains +SYSTEMD_TEST_DATA=/path/to/source/tree/test and that source tree is not visible +once we overmount /root with tmpfs making the test fail: + +/* test_run_tests_unprivileged */ +Successfully forked off '(test-execute-unprivileged)' as PID 10672. +Changing mount flags / (MS_REMOUNT|MS_BIND "")... +Changing mount propagation / (MS_REC|MS_SHARED "") +Mounting tmpfs (tmpfs) on /dev/shm (MS_NOSUID|MS_NODEV "")... +Mounting tmpfs (tmpfs) on /root (MS_NOSUID|MS_NODEV "")... +Mounting tmpfs (tmpfs) on /tmp (MS_NOSUID|MS_NODEV "")... +Mounting tmpfs (tmpfs) on /var/tmp (MS_NOSUID|MS_NODEV "")... +Mounting tmpfs (tmpfs) on /var/lib (MS_NOSUID|MS_NODEV "")... +Mounting tmpfs (tmpfs) on /run/test-execute-unit-dir (MS_NOSUID|MS_NODEV "")... +ERROR: $SYSTEMD_TEST_DATA directory [/root/systemd/test] not accessible: No such file or directory +Assertion 'get_testdata_dir("test-execute/", &unit_dir) >= 0' failed at src/test/test-execute.c:1306, function prepare_ns(). Aborting. +(test-execute-unprivileged) terminated by signal ABRT. + +(cherry picked from commit c109cff9f998876c3b5abd62501132d0fb0f80a2) + +Related: RHEL-27512 +--- + src/test/test-execute.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/src/test/test-execute.c b/src/test/test-execute.c +index f37da945b6..e6bd21b6b9 100644 +--- a/src/test/test-execute.c ++++ b/src/test/test-execute.c +@@ -1260,15 +1260,16 @@ static int prepare_ns(const char *process_name) { + assert_se(mount_follow_verbose(LOG_DEBUG, NULL, "/", NULL, MS_SHARED|MS_REC, NULL) >= 0); + + assert_se(mkdir_p(PRIVATE_UNIT_DIR, 0755) >= 0); +- +- /* Mount tmpfs on the following directories to make not StateDirectory= or friends disturb the host. */ +- FOREACH_STRING(p, "/dev/shm", "/root", "/tmp", "/var/tmp", "/var/lib", PRIVATE_UNIT_DIR) +- assert_se(mount_nofollow_verbose(LOG_DEBUG, "tmpfs", p, "tmpfs", MS_NOSUID|MS_NODEV, NULL) >= 0); ++ assert_se(mount_nofollow_verbose(LOG_DEBUG, "tmpfs", PRIVATE_UNIT_DIR, "tmpfs", MS_NOSUID|MS_NODEV, NULL) >= 0); + + /* Copy unit files to make them accessible even when unprivileged. */ + assert_se(get_testdata_dir("test-execute/", &unit_dir) >= 0); + assert_se(copy_directory(unit_dir, PRIVATE_UNIT_DIR, COPY_MERGE_EMPTY) >= 0); + ++ /* Mount tmpfs on the following directories to make not StateDirectory= or friends disturb the host. */ ++ FOREACH_STRING(p, "/dev/shm", "/root", "/tmp", "/var/tmp", "/var/lib") ++ assert_se(mount_nofollow_verbose(LOG_DEBUG, "tmpfs", p, "tmpfs", MS_NOSUID|MS_NODEV, NULL) >= 0); ++ + /* Prepare credstore like tmpfiles.d/credstore.conf for LoadCredential= tests. */ + FOREACH_STRING(p, "/run/credstore", "/run/credstore.encrypted") { + assert_se(mkdir_p(p, 0) >= 0); diff --git a/0800-ci-make-the-build-dir-accessible-when-running-w-o-pr.patch b/0800-ci-make-the-build-dir-accessible-when-running-w-o-pr.patch new file mode 100644 index 0000000..9fac0f9 --- /dev/null +++ b/0800-ci-make-the-build-dir-accessible-when-running-w-o-pr.patch @@ -0,0 +1,39 @@ +From 5bc5e4eccfccb2935ededa6976d3346b1b6fbdaf Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Wed, 6 Mar 2024 15:04:22 +0100 +Subject: [PATCH] ci: make the build dir accessible when running w/o privileges + +Otherwise the unprivileged part of test-execute gets silently skipped: + +/* test_run_tests_unprivileged */ +Successfully forked off '(test-execute-unprivileged)' as PID 20998. +... +pin_callout_binary: build dir binary: /home/runner/work/systemd/systemd/build/systemd-executor +pin_callout_binary: open(/home/runner/work/systemd/systemd/build/systemd-executor)=-13 +Failed to pin executor binary: No such file or directory +(test-execute-unprivileged): manager_new, skipping tests: No such file or directory +(test-execute-unprivileged) succeeded. + +(cherry picked from commit c538fecc617d7a5fe0048b1df49f69dead92353f) + +Related: RHEL-27512 +--- + .github/workflows/unit_tests.sh | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/.github/workflows/unit_tests.sh b/.github/workflows/unit_tests.sh +index 9a9fbb36ab..cb8ea332aa 100755 +--- a/.github/workflows/unit_tests.sh ++++ b/.github/workflows/unit_tests.sh +@@ -52,6 +52,11 @@ for phase in "${PHASES[@]}"; do + apt-get -y build-dep systemd + apt-get -y install "${ADDITIONAL_DEPS[@]}" + pip3 install -r .github/workflows/requirements.txt --require-hashes ++ ++ # Make sure the build dir is accessible even when drop privileges, otherwise the unprivileged ++ # part of test-execute gets skipped, since it can't run systemd-executor ++ chmod o+x /home/runner ++ capsh --drop=all -- -c "stat $PWD/meson.build" + ;; + RUN|RUN_GCC|RUN_CLANG|RUN_CLANG_RELEASE) + if [[ "$phase" =~ ^RUN_CLANG ]]; then diff --git a/0801-ci-explicitly-change-oom-score-adj-before-running-te.patch b/0801-ci-explicitly-change-oom-score-adj-before-running-te.patch new file mode 100644 index 0000000..209f3c1 --- /dev/null +++ b/0801-ci-explicitly-change-oom-score-adj-before-running-te.patch @@ -0,0 +1,74 @@ +From 5a310f31d5d42bb7a556c274c3839c34c600e9f5 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Wed, 6 Mar 2024 15:21:10 +0100 +Subject: [PATCH] ci: explicitly change oom-{score}-adj before running tests + +For some reason root in GH actions is able to _decrease_ its oom score +even after dropping all capabilities (including CAP_SYS_RESOURCE), until +the oom score is changed explicitly after sudo: + +$ systemd-detect-virt +microsoft +$ sudo su - +~# capsh --drop=all -- -c 'capsh --print; grep -H . /proc/self/oom*; choom -p $$ -n -101' +Current: = +Bounding set = +Ambient set = +Current IAB: !cap_chown,!cap_dac_override,!cap_dac_read_search,...,!cap_sys_resource,...,!cap_checkpoint_restore +Securebits: 00/0x0/1'b0 + secure-noroot: no (unlocked) + secure-no-suid-fixup: no (unlocked) + secure-keep-caps: no (unlocked) + secure-no-ambient-raise: no (unlocked) +uid=0(root) euid=0(root) +gid=0(root) +groups=0(root) +Guessed mode: UNCERTAIN (0) +/proc/self/oom_adj:8 +/proc/self/oom_score:1000 +/proc/self/oom_score_adj:500 +pid 22180's OOM score adjust value changed from 500 to -101 +~# choom -p $$ -n 500 +pid 22027's OOM score adjust value changed from 500 to 500 +~# capsh --drop=all -- -c 'capsh --print; grep -H . /proc/self/oom*; choom -p $$ -n -101' +Current: = +Bounding set = +Ambient set = +... +uid=0(root) euid=0(root) +gid=0(root) +groups=0(root) +Guessed mode: UNCERTAIN (0) +/proc/self/oom_adj:8 +/proc/self/oom_score:1000 +/proc/self/oom_score_adj:500 +choom: failed to set score adjust value: Permission denied + +I have no idea what's going on, but it breaks +exec-oomscoreadjust-negative.service from test-execute when running +unprivileged. + +(cherry picked from commit 7161af9612d2d4f79cfbe8ed34ea7614d08901f7) + +Related: RHEL-27512 +--- + .github/workflows/unit_tests.sh | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/.github/workflows/unit_tests.sh b/.github/workflows/unit_tests.sh +index cb8ea332aa..6dcbc393fd 100755 +--- a/.github/workflows/unit_tests.sh ++++ b/.github/workflows/unit_tests.sh +@@ -41,6 +41,12 @@ set -ex + + MESON_ARGS=(-Dcryptolib=${CRYPTOLIB:-auto}) + ++# (Re)set the current oom-{score-}adj. For some reason root on GH actions is able to _decrease_ ++# its oom-score even after dropping all capabilities (including CAP_SYS_RESOURCE), until the ++# score is explicitly changed after sudo. No idea what's going on, but it breaks ++# exec-oomscoreadjust-negative.service from test-execute when running unprivileged. ++choom -p $$ -n 0 ++ + for phase in "${PHASES[@]}"; do + case $phase in + SETUP) diff --git a/0802-ratelimit-add-ratelimit_left-helper.patch b/0802-ratelimit-add-ratelimit_left-helper.patch new file mode 100644 index 0000000..c0a5bd3 --- /dev/null +++ b/0802-ratelimit-add-ratelimit_left-helper.patch @@ -0,0 +1,49 @@ +From 90c92458355a64d96f3167bcb510f690446bd76a Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Fri, 28 Apr 2023 13:10:23 +0100 +Subject: [PATCH] ratelimit: add ratelimit_left helper + +(cherry picked from commit 53d6987f9e46927bbc9ad683c091c070ebe06658) + +Resolves: RHEL-35703 +--- + src/basic/ratelimit.c | 17 +++++++++++++++++ + src/basic/ratelimit.h | 3 +++ + 2 files changed, 20 insertions(+) + +diff --git a/src/basic/ratelimit.c b/src/basic/ratelimit.c +index c16c8f7103..134ed7c2d8 100644 +--- a/src/basic/ratelimit.c ++++ b/src/basic/ratelimit.c +@@ -43,3 +43,20 @@ unsigned ratelimit_num_dropped(RateLimit *r) { + + return r->num > r->burst ? r->num - r->burst : 0; + } ++ ++usec_t ratelimit_end(const RateLimit *rl) { ++ assert(rl); ++ if (rl->begin == 0) ++ return 0; ++ ++ return usec_add(rl->begin, rl->interval); ++} ++ ++usec_t ratelimit_left(const RateLimit *rl) { ++ assert(rl); ++ ++ if (rl->begin == 0) ++ return 0; ++ ++ return usec_sub_unsigned(ratelimit_end(rl), now(CLOCK_MONOTONIC)); ++} +diff --git a/src/basic/ratelimit.h b/src/basic/ratelimit.h +index 2236189851..bb7160a895 100644 +--- a/src/basic/ratelimit.h ++++ b/src/basic/ratelimit.h +@@ -23,3 +23,6 @@ static inline bool ratelimit_configured(RateLimit *rl) { + bool ratelimit_below(RateLimit *r); + + unsigned ratelimit_num_dropped(RateLimit *r); ++ ++usec_t ratelimit_end(const RateLimit *rl); ++usec_t ratelimit_left(const RateLimit *rl); diff --git a/0803-manager-restrict-Dump-to-privileged-callers-or-ratel.patch b/0803-manager-restrict-Dump-to-privileged-callers-or-ratel.patch new file mode 100644 index 0000000..a386dd2 --- /dev/null +++ b/0803-manager-restrict-Dump-to-privileged-callers-or-ratel.patch @@ -0,0 +1,264 @@ +From 10e811e931efd55cab87b85eb75cbe73139cec43 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Thu, 27 Apr 2023 23:23:30 +0100 +Subject: [PATCH] manager: restrict Dump*() to privileged callers or ratelimit + +Dump*() methods can take quite some time due to the amount of data to +serialize, so they can potentially stall the manager. Make them +privileged, as they are debugging tools anyway. Use a new 'dump' +capability for polkit, and the 'reload' capability for SELinux, as +that's also non-destructive but slow. + +If the caller is not privileged, allow it but rate limited to 10 calls +every 10 minutes. + +(cherry picked from commit d936595672cf3ee7c1c547f8fd30512f82be8784) + +Resolves: RHEL-35703 +--- + man/org.freedesktop.systemd1.xml | 7 +++-- + man/systemd-analyze.xml | 2 +- + src/core/dbus-manager.c | 34 +++++++++++++++++++-- + src/core/dbus.c | 3 ++ + src/core/dbus.h | 1 + + src/core/manager-serialize.c | 23 ++++++++++++++ + src/core/manager.c | 5 +++ + src/core/manager.h | 3 ++ + src/core/org.freedesktop.systemd1.policy.in | 10 ++++++ + test/units/testsuite-65.sh | 15 +++++++++ + 10 files changed, 98 insertions(+), 5 deletions(-) + +diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml +index c18428a092..7ee649f6a7 100644 +--- a/man/org.freedesktop.systemd1.xml ++++ b/man/org.freedesktop.systemd1.xml +@@ -1363,7 +1363,8 @@ node /org/freedesktop/systemd1 { + DumpByFileDescriptor()/DumpUnitsMatchingPatternsByFileDescriptor() + are usually the preferred interface, since it ensures the data can be passed reliably from the service + manager to the client. Note though that they cannot work when communicating with the service manager +- remotely, as file descriptors are strictly local to a system. ++ remotely, as file descriptors are strictly local to a system. All the Dump*() ++ methods are rate limited for unprivileged users. + + Reload() may be invoked to reload all unit files. + +@@ -1726,7 +1727,9 @@ node /org/freedesktop/systemd1 { + UnsetAndSetEnvironment()) require + org.freedesktop.systemd1.set-environment. Reload() + and Reexecute() require +- org.freedesktop.systemd1.reload-daemon. ++ org.freedesktop.systemd1.reload-daemon. Operations which dump internal ++ state require org.freedesktop.systemd1.bypass-dump-ratelimit to avoid ++ rate limits. + + + +diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml +index 5ba0d40fa0..ff5c84108d 100644 +--- a/man/systemd-analyze.xml ++++ b/man/systemd-analyze.xml +@@ -249,7 +249,7 @@ multi-user.target @47.820s + Without any parameter, this command outputs a (usually very long) human-readable serialization of + the complete service manager state. Optional glob pattern may be specified, causing the output to be + limited to units whose names match one of the patterns. The output format is subject to change without +- notice and should not be parsed by applications. ++ notice and should not be parsed by applications. This command is rate limited for unprivileged users. + + + Show the internal state of user manager +diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c +index 00380cc9c1..44b1027588 100644 +--- a/src/core/dbus-manager.c ++++ b/src/core/dbus-manager.c +@@ -1357,17 +1357,47 @@ static int dump_impl( + + assert(message); + +- /* Anyone can call this method */ +- ++ /* 'status' access is the bare minimum always needed for this, as the policy might straight out ++ * forbid a client from querying any information from systemd, regardless of any rate limiting. */ + r = mac_selinux_access_check(message, "status", error); + if (r < 0) + return r; + ++ /* Rate limit reached? Check if the caller is privileged/allowed by policy to bypass this. We ++ * check the rate limit first to avoid the expensive roundtrip to polkit when not needed. */ ++ if (!ratelimit_below(&m->dump_ratelimit)) { ++ /* We need a way for SELinux to constrain the operation when the rate limit is active, even ++ * if polkit would allow it, but we cannot easily add new named permissions, so we need to ++ * use an existing one. Reload/reexec are also slow but non-destructive/modifying ++ * operations, and can cause PID1 to stall. So it seems similar enough in terms of security ++ * considerations and impact, and thus use the same access check for dumps which, given the ++ * large amount of data to fetch, can stall PID1 for quite some time. */ ++ r = mac_selinux_access_check(message, "reload", error); ++ if (r < 0) ++ goto ratelimited; ++ ++ r = bus_verify_bypass_dump_ratelimit_async(m, message, error); ++ if (r < 0) ++ goto ratelimited; ++ if (r == 0) ++ /* No authorization for now, but the async polkit stuff will call us again when it ++ * has it */ ++ return 1; ++ } ++ + r = manager_get_dump_string(m, patterns, &dump); + if (r < 0) + return r; + + return reply(message, dump); ++ ++ratelimited: ++ log_warning("Dump request rejected due to rate limit on unprivileged callers, blocked for %s.", ++ FORMAT_TIMESPAN(ratelimit_left(&m->dump_ratelimit), USEC_PER_SEC)); ++ return sd_bus_error_setf(error, ++ SD_BUS_ERROR_LIMITS_EXCEEDED, ++ "Dump request rejected due to rate limit on unprivileged callers, blocked for %s.", ++ FORMAT_TIMESPAN(ratelimit_left(&m->dump_ratelimit), USEC_PER_SEC)); + } + + static int reply_dump(sd_bus_message *message, char *dump) { +diff --git a/src/core/dbus.c b/src/core/dbus.c +index 141c3ffe12..3cbe9c5cfd 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -1177,6 +1177,9 @@ int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_erro + int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { + return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.set-environment", NULL, false, UID_INVALID, &m->polkit_registry, error); + } ++int bus_verify_bypass_dump_ratelimit_async(Manager *m, sd_bus_message *call, sd_bus_error *error) { ++ return bus_verify_polkit_async(call, CAP_SYS_ADMIN, "org.freedesktop.systemd1.bypass-dump-ratelimit", NULL, false, UID_INVALID, &m->polkit_registry, error); ++} + + uint64_t manager_bus_n_queued_write(Manager *m) { + uint64_t c = 0; +diff --git a/src/core/dbus.h b/src/core/dbus.h +index 369d9f56a2..50e7bb400e 100644 +--- a/src/core/dbus.h ++++ b/src/core/dbus.h +@@ -27,6 +27,7 @@ int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error + int bus_verify_manage_unit_files_async(Manager *m, sd_bus_message *call, sd_bus_error *error); + int bus_verify_reload_daemon_async(Manager *m, sd_bus_message *call, sd_bus_error *error); + int bus_verify_set_environment_async(Manager *m, sd_bus_message *call, sd_bus_error *error); ++int bus_verify_bypass_dump_ratelimit_async(Manager *m, sd_bus_message *call, sd_bus_error *error); + + int bus_forward_agent_released(Manager *m, const char *path); + +diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c +index 27cb0925ae..f3b2d7ee16 100644 +--- a/src/core/manager-serialize.c ++++ b/src/core/manager-serialize.c +@@ -164,6 +164,14 @@ int manager_serialize( + (void) serialize_item_format(f, "user-lookup", "%i %i", copy0, copy1); + } + ++ (void) serialize_item_format(f, ++ "dump-ratelimit", ++ USEC_FMT " " USEC_FMT " %u %u", ++ m->dump_ratelimit.begin, ++ m->dump_ratelimit.interval, ++ m->dump_ratelimit.num, ++ m->dump_ratelimit.burst); ++ + bus_track_serialize(m->subscribed, f, "subscribed"); + + r = dynamic_user_serialize(m, f, fds); +@@ -549,6 +557,21 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { + * remains set until all serialized contents are handled. */ + if (deserialize_varlink_sockets) + (void) varlink_server_deserialize_one(m->varlink_server, val, fds); ++ } else if ((val = startswith(l, "dump-ratelimit="))) { ++ usec_t begin, interval; ++ unsigned num, burst; ++ ++ if (sscanf(val, USEC_FMT " " USEC_FMT " %u %u", &begin, &interval, &num, &burst) != 4) ++ log_notice("Failed to parse dump ratelimit, ignoring: %s", val); ++ else { ++ /* If we changed the values across versions, flush the counter */ ++ if (interval != m->dump_ratelimit.interval || burst != m->dump_ratelimit.burst) ++ m->dump_ratelimit.num = 0; ++ else ++ m->dump_ratelimit.num = num; ++ m->dump_ratelimit.begin = begin; ++ } ++ + } else { + ManagerTimestamp q; + +diff --git a/src/core/manager.c b/src/core/manager.c +index eeee395b90..b44c7785cf 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -866,6 +866,11 @@ int manager_new(LookupScope scope, ManagerTestRunFlags test_run_flags, Manager * + .test_run_flags = test_run_flags, + + .default_oom_policy = OOM_STOP, ++ ++ .dump_ratelimit = { ++ .interval = 10 * USEC_PER_MINUTE, ++ .burst = 10, ++ }, + }; + + #if ENABLE_EFI +diff --git a/src/core/manager.h b/src/core/manager.h +index 87e63c3b68..86e7e40989 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -461,6 +461,9 @@ struct Manager { + struct restrict_fs_bpf *restrict_fs; + + char *default_smack_process_label; ++ ++ /* Dump*() are slow, so always rate limit them to 10 per 10 minutes */ ++ RateLimit dump_ratelimit; + }; + + static inline usec_t manager_default_timeout_abort_usec(Manager *m) { +diff --git a/src/core/org.freedesktop.systemd1.policy.in b/src/core/org.freedesktop.systemd1.policy.in +index 74adeadf38..9e9a20f66f 100644 +--- a/src/core/org.freedesktop.systemd1.policy.in ++++ b/src/core/org.freedesktop.systemd1.policy.in +@@ -70,4 +70,14 @@ + + + ++ ++ Dump the systemd state without rate limits ++ Authentication is required to dump the systemd state without rate limits. ++ ++ auth_admin ++ auth_admin ++ auth_admin_keep ++ ++ ++ + +diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh +index 7c34948f82..f416194922 100755 +--- a/test/units/testsuite-65.sh ++++ b/test/units/testsuite-65.sh +@@ -51,6 +51,21 @@ systemd-analyze dot --require systemd-journald.service systemd-logind.service >/ + systemd-analyze dot "systemd-*.service" >/dev/null + (! systemd-analyze dot systemd-journald.service systemd-logind.service "*" bbb ccc) + # dump ++# this should be rate limited to 10 calls in 10 minutes for unprivileged callers ++for _ in {1..10}; do ++ runas testuser systemd-analyze dump systemd-journald.service >/dev/null ++done ++(! runas testuser systemd-analyze dump >/dev/null) ++# still limited after a reload ++systemctl daemon-reload ++(! runas testuser systemd-analyze dump >/dev/null) ++# and a re-exec ++systemctl daemon-reexec ++(! runas testuser systemd-analyze dump >/dev/null) ++# privileged call, so should not be rate limited ++for _ in {1..10}; do ++ systemd-analyze dump systemd-journald.service >/dev/null ++done + systemd-analyze dump >/dev/null + systemd-analyze dump "*" >/dev/null + systemd-analyze dump "*.socket" >/dev/null diff --git a/0804-ci-define-runas-function-inline.patch b/0804-ci-define-runas-function-inline.patch new file mode 100644 index 0000000..b89b813 --- /dev/null +++ b/0804-ci-define-runas-function-inline.patch @@ -0,0 +1,60 @@ +From 3e5091146213b8b4abf0c5f5577a98b9da9c9f2c Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Tue, 11 Jun 2024 15:21:14 +0200 +Subject: [PATCH] ci: define `runas` function inline + +We don't have `test/units/util.sh`, which provides the definition of `runas` function in the RHEL9 codebase + +Also partially backport https://github.com/systemd/systemd/commit/c7bf1959d7580e1b7e918b75f852b3bf3fb6eb3c + +rhel-only + +Related: RHEL-35703 +--- + test/test-functions | 5 +++-- + test/units/testsuite-65.sh | 7 +++++++ + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/test/test-functions b/test/test-functions +index 947f8589c5..52eff07510 100644 +--- a/test/test-functions ++++ b/test/test-functions +@@ -206,6 +206,7 @@ BASICTOOLS=( + seq + setfattr + setfont ++ setpriv + setsid + sfdisk + sh +@@ -2616,10 +2617,10 @@ inst_binary() { + # Same as above, but we need to wrap certain libraries unconditionally + # + # chown, getent, login, su, useradd, userdel - dlopen()s (not only) systemd's PAM modules +- # ls, stat - pulls in nss_systemd with certain options (like ls -l) when ++ # ls, setpriv, stat - pulls in nss_systemd with certain options (like ls -l) when + # nsswitch.conf uses [SUCCESS=merge] (like on Arch Linux) + # tar - called by machinectl in TEST-25 +- if get_bool "$IS_BUILT_WITH_ASAN" && [[ "$bin" =~ /(chown|getent|login|id|ls|stat|su|tar|useradd|userdel)$ ]]; then ++ if get_bool "$IS_BUILT_WITH_ASAN" && [[ "$bin" =~ /(chown|getent|login|id|ls|setpriv|stat|su|tar|useradd|userdel)$ ]]; then + wrap_binary=1 + fi + +diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh +index f416194922..0fb143bde7 100755 +--- a/test/units/testsuite-65.sh ++++ b/test/units/testsuite-65.sh +@@ -6,6 +6,13 @@ set -eux + # shellcheck source=test/units/assert.sh + . "$(dirname "$0")"/assert.sh + ++# On RHEL9 we don't have the `util.sh` script, so we need to define the `runas` function here ++runas() { ++ local userid="${1:?}" ++ shift ++ XDG_RUNTIME_DIR=/run/user/"$(id -u "$userid")" setpriv --reuid="$userid" --init-groups "$@" ++} ++ + systemctl log-level debug + export SYSTEMD_LOG_LEVEL=debug + diff --git a/0805-Drop-dev-test-in-test-mountpoint-util.patch b/0805-Drop-dev-test-in-test-mountpoint-util.patch new file mode 100644 index 0000000..31e5067 --- /dev/null +++ b/0805-Drop-dev-test-in-test-mountpoint-util.patch @@ -0,0 +1,31 @@ +From f6fdbbe989e54480882b9eeda452d168eea804a2 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Thu, 21 Dec 2023 19:46:54 +0100 +Subject: [PATCH] Drop /dev test in test-mountpoint-util + +Even /dev isn't always guaranteed to be a mount point, so let's drop +this part of the test. + +(cherry picked from commit bacad14f94a4e98c3e81d821c56dbe7e2e4726ff) + +Related: RHEL-30372 +--- + src/test/test-mountpoint-util.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c +index 8555c5a7db..d8e56c0365 100644 +--- a/src/test/test-mountpoint-util.c ++++ b/src/test/test-mountpoint-util.c +@@ -138,11 +138,6 @@ TEST(path_is_mount_point) { + assert_se(path_is_mount_point("/proc/1/", NULL, AT_SYMLINK_FOLLOW) == 0); + assert_se(path_is_mount_point("/proc/1/", NULL, 0) == 0); + +- assert_se(path_is_mount_point("/dev", NULL, AT_SYMLINK_FOLLOW) > 0); +- assert_se(path_is_mount_point("/dev", NULL, 0) > 0); +- assert_se(path_is_mount_point("/dev/", NULL, AT_SYMLINK_FOLLOW) > 0); +- assert_se(path_is_mount_point("/dev/", NULL, 0) > 0); +- + /* we'll create a hierarchy of different kinds of dir/file/link + * layouts: + * diff --git a/0806-core-manager-export-manager_dbus_is_running.patch b/0806-core-manager-export-manager_dbus_is_running.patch new file mode 100644 index 0000000..03fe874 --- /dev/null +++ b/0806-core-manager-export-manager_dbus_is_running.patch @@ -0,0 +1,69 @@ +From 7302d5d45efc1b157ddbfb04c387d83a87c8384f Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Mon, 8 May 2023 23:10:07 +0800 +Subject: [PATCH] core/manager: export manager_dbus_is_running + +(cherry picked from commit e8863150653931ae2ffc91757623f179ce763628) + +Resolves: RHEL-40878 +--- + src/core/manager.c | 8 ++++---- + src/core/manager.h | 5 +++++ + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index b44c7785cf..fd6e711c65 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -1680,7 +1680,7 @@ static void manager_distribute_fds(Manager *m, FDSet *fds) { + } + } + +-static bool manager_dbus_is_running(Manager *m, bool deserialized) { ++bool manager_dbus_is_running_full(Manager *m, bool deserialized) { + Unit *u; + + assert(m); +@@ -1722,7 +1722,7 @@ static void manager_setup_bus(Manager *m) { + (void) bus_init_system(m); + + /* Let's connect to the bus now, but only if the unit is supposed to be up */ +- if (manager_dbus_is_running(m, MANAGER_IS_RELOADING(m))) { ++ if (manager_dbus_is_running_full(m, MANAGER_IS_RELOADING(m))) { + (void) bus_init_api(m); + + if (MANAGER_IS_SYSTEM(m)) +@@ -2815,7 +2815,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t + break; + + case SIGUSR1: +- if (manager_dbus_is_running(m, false)) { ++ if (manager_dbus_is_running(m)) { + log_info("Trying to reconnect to bus..."); + + (void) bus_init_api(m); +@@ -3930,7 +3930,7 @@ void manager_recheck_dbus(Manager *m) { + if (MANAGER_IS_RELOADING(m)) + return; /* don't check while we are reloading… */ + +- if (manager_dbus_is_running(m, false)) { ++ if (manager_dbus_is_running(m)) { + (void) bus_init_api(m); + + if (MANAGER_IS_SYSTEM(m)) +diff --git a/src/core/manager.h b/src/core/manager.h +index 86e7e40989..1479813de4 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -491,6 +491,11 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); + + int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *root); + ++bool manager_dbus_is_running_full(Manager *m, bool deserialized); ++static inline bool manager_dbus_is_running(Manager *m) { ++ return manager_dbus_is_running_full(m, false); ++} ++ + Job *manager_get_job(Manager *m, uint32_t id); + Unit *manager_get_unit(Manager *m, const char *name); + diff --git a/0807-core-refuse-dbus-activation-if-dbus-is-not-running.patch b/0807-core-refuse-dbus-activation-if-dbus-is-not-running.patch new file mode 100644 index 0000000..4a76f8e --- /dev/null +++ b/0807-core-refuse-dbus-activation-if-dbus-is-not-running.patch @@ -0,0 +1,61 @@ +From 40f8600cfd866e4956fb09ca29bc5dc74e605450 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Tue, 9 May 2023 00:07:45 +0800 +Subject: [PATCH] core: refuse dbus activation if dbus is not running + +dbus-broker issues StartUnit directly for activation requests, +so let's add a check on bus state in bus_unit_queue_job to refuse +that if dbus is not running. + +Replaces #27570 +Closes #26799 + +(cherry picked from commit 53964fd26b4a01191609ffc064aa8ccccd28e377) + +Resolves: RHEL-40878 +--- + src/core/dbus-unit.c | 7 +++++++ + src/core/dbus.c | 5 ++--- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index 19a71b6cb3..685d45fc23 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -21,6 +21,7 @@ + #include "path-util.h" + #include "process-util.h" + #include "selinux-access.h" ++#include "service.h" + #include "signal-util.h" + #include "special.h" + #include "string-table.h" +@@ -1845,6 +1846,12 @@ int bus_unit_queue_job( + (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start)) + return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id); + ++ /* dbus-broker issues StartUnit for activation requests, so let's apply the same check ++ * used in signal_activation_request(). */ ++ if (type == JOB_START && u->type == UNIT_SERVICE && ++ SERVICE(u)->type == SERVICE_DBUS && !manager_dbus_is_running(u->manager)) ++ return sd_bus_error_set(error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is not running."); ++ + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; +diff --git a/src/core/dbus.c b/src/core/dbus.c +index 3cbe9c5cfd..b4564f79a2 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -160,9 +160,8 @@ static int signal_activation_request(sd_bus_message *message, void *userdata, sd + return 0; + } + +- if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) || +- manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) { +- r = sd_bus_error_set(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down."); ++ if (!manager_dbus_is_running(m)) { ++ r = sd_bus_error_set(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is not running."); + goto failed; + } + diff --git a/0808-core-only-refuse-Type-dbus-service-enqueuing-if-dbus.patch b/0808-core-only-refuse-Type-dbus-service-enqueuing-if-dbus.patch new file mode 100644 index 0000000..f6b033f --- /dev/null +++ b/0808-core-only-refuse-Type-dbus-service-enqueuing-if-dbus.patch @@ -0,0 +1,84 @@ +From 6e61224e554decd747d6537a4d6839cff6b19909 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Wed, 10 May 2023 13:54:15 +0800 +Subject: [PATCH] core: only refuse Type=dbus service enqueuing if dbus has + stop job + +Follow-up for #27579 + +In #27579 we refused all StartUnit requests for Type=dbus units +if dbus is not running, which means if dbus is manually stopped, +user can't use systemctl to start Type=dbus units again, which +is incorrect. + +The only culprit that leads to the cancellation of the whole +transaction mentioned in #26799 is job type conflict on dbus. +So let's relax the restriction and only refuse job enqueuing +if dbus has a stop job. + +To summarize, the case we want to avoid is: + +1. dbus has a stop job installed +2. StartUnit/ActivationRequest is received +3. Type=dbus service gets started, which has Requires=dbus.socket +4. dbus is pulled in again, resulting in job type conflict + +What we can support is: + +1. dbus is already stopped +2. StartUnit is received (possibly through systemctl, i.e. on private bus) +3. Type=dbus service gets started, which will wait for dbus to start +4. dbus is started again, thus the job for Type=dbus service + +Replaces #27590 +Fixes #27588 + +(cherry picked from commit bee6e755bb8e53a7a436e221b015ce0232ed87c0) + +Resolves: RHEL-40878 +--- + src/core/dbus-unit.c | 31 ++++++++++++++++++++++++------- + 1 file changed, 24 insertions(+), 7 deletions(-) + +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index 685d45fc23..49eacc977c 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -1844,13 +1844,30 @@ int bus_unit_queue_job( + (type == JOB_STOP && u->refuse_manual_stop) || + (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) || + (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start)) +- return sd_bus_error_setf(error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", u->id); +- +- /* dbus-broker issues StartUnit for activation requests, so let's apply the same check +- * used in signal_activation_request(). */ +- if (type == JOB_START && u->type == UNIT_SERVICE && +- SERVICE(u)->type == SERVICE_DBUS && !manager_dbus_is_running(u->manager)) +- return sd_bus_error_set(error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is not running."); ++ return sd_bus_error_setf(error, ++ BUS_ERROR_ONLY_BY_DEPENDENCY, ++ "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", ++ u->id); ++ ++ /* dbus-broker issues StartUnit for activation requests, and Type=dbus services automatically ++ * gain dependency on dbus.socket. Therefore, if dbus has a pending stop job, the new start ++ * job that pulls in dbus again would cause job type conflict. Let's avoid that by rejecting ++ * job enqueuing early. ++ * ++ * Note that unlike signal_activation_request(), we can't use unit_inactive_or_pending() ++ * here. StartUnit is a more generic interface, and thus users are allowed to use e.g. systemctl ++ * to start Type=dbus services even when dbus is inactive. */ ++ if (type == JOB_START && u->type == UNIT_SERVICE && SERVICE(u)->type == SERVICE_DBUS) ++ FOREACH_STRING(dbus_unit, SPECIAL_DBUS_SOCKET, SPECIAL_DBUS_SERVICE) { ++ Unit *dbus; ++ ++ dbus = manager_get_unit(u->manager, dbus_unit); ++ if (dbus && unit_stop_pending(dbus)) ++ return sd_bus_error_setf(error, ++ BUS_ERROR_SHUTTING_DOWN, ++ "Operation for unit %s refused, D-Bus is shutting down.", ++ u->id); ++ } + + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) diff --git a/0809-Revert-core-manager-export-manager_dbus_is_running-a.patch b/0809-Revert-core-manager-export-manager_dbus_is_running-a.patch new file mode 100644 index 0000000..3103ca7 --- /dev/null +++ b/0809-Revert-core-manager-export-manager_dbus_is_running-a.patch @@ -0,0 +1,93 @@ +From 07ec0810cf4dc638c138735eccda78e37ff42be7 Mon Sep 17 00:00:00 2001 +From: Mike Yuan +Date: Thu, 11 May 2023 18:55:43 +0800 +Subject: [PATCH] Revert "core/manager: export manager_dbus_is_running" and + partially "core: refuse dbus activation if dbus is not running" + +This reverts commit e8863150653931ae2ffc91757623f179ce763628 +and partially 53964fd26b4a01191609ffc064aa8ccccd28e377. + +Specifically, changes to signal_activation_request() +is not desired. + +(cherry picked from commit 2b680534c9667341551b39f4cc9735cd6e8c014e) + +Resolves: RHEL-40878 +--- + src/core/dbus.c | 5 +++-- + src/core/manager.c | 8 ++++---- + src/core/manager.h | 5 ----- + 3 files changed, 7 insertions(+), 11 deletions(-) + +diff --git a/src/core/dbus.c b/src/core/dbus.c +index b4564f79a2..1431e079c2 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -160,8 +160,9 @@ static int signal_activation_request(sd_bus_message *message, void *userdata, sd + return 0; + } + +- if (!manager_dbus_is_running(m)) { +- r = sd_bus_error_set(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is not running."); ++ if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET) || ++ manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE)) { ++ r = sd_bus_error_set(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down."); + goto failed; + } + +diff --git a/src/core/manager.c b/src/core/manager.c +index fd6e711c65..b44c7785cf 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -1680,7 +1680,7 @@ static void manager_distribute_fds(Manager *m, FDSet *fds) { + } + } + +-bool manager_dbus_is_running_full(Manager *m, bool deserialized) { ++static bool manager_dbus_is_running(Manager *m, bool deserialized) { + Unit *u; + + assert(m); +@@ -1722,7 +1722,7 @@ static void manager_setup_bus(Manager *m) { + (void) bus_init_system(m); + + /* Let's connect to the bus now, but only if the unit is supposed to be up */ +- if (manager_dbus_is_running_full(m, MANAGER_IS_RELOADING(m))) { ++ if (manager_dbus_is_running(m, MANAGER_IS_RELOADING(m))) { + (void) bus_init_api(m); + + if (MANAGER_IS_SYSTEM(m)) +@@ -2815,7 +2815,7 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t + break; + + case SIGUSR1: +- if (manager_dbus_is_running(m)) { ++ if (manager_dbus_is_running(m, false)) { + log_info("Trying to reconnect to bus..."); + + (void) bus_init_api(m); +@@ -3930,7 +3930,7 @@ void manager_recheck_dbus(Manager *m) { + if (MANAGER_IS_RELOADING(m)) + return; /* don't check while we are reloading… */ + +- if (manager_dbus_is_running(m)) { ++ if (manager_dbus_is_running(m, false)) { + (void) bus_init_api(m); + + if (MANAGER_IS_SYSTEM(m)) +diff --git a/src/core/manager.h b/src/core/manager.h +index 1479813de4..86e7e40989 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -491,11 +491,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); + + int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *root); + +-bool manager_dbus_is_running_full(Manager *m, bool deserialized); +-static inline bool manager_dbus_is_running(Manager *m) { +- return manager_dbus_is_running_full(m, false); +-} +- + Job *manager_get_job(Manager *m, uint32_t id); + Unit *manager_get_unit(Manager *m, const char *name); + diff --git a/0810-manager-fix-reloading-in-reload-or-restart-marked.patch b/0810-manager-fix-reloading-in-reload-or-restart-marked.patch new file mode 100644 index 0000000..887f9ca --- /dev/null +++ b/0810-manager-fix-reloading-in-reload-or-restart-marked.patch @@ -0,0 +1,127 @@ +From 758cd9ddac150342dbac49ed4c80c68531c169b7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 28 Jul 2023 17:54:59 +0200 +Subject: [PATCH] manager: fix reloading in reload-or-restart --marked + +bus_unit_queue_job_one has two callers: +- bus_unit_queue_job which would do the appropriate transormations + to turn JOB_TRY_RESTART into JOB_TRY_RELOAD, +- and method_enqueue_marked_jobs which did not. +In effect, method_enqueue_marked_jobs() would queue restart jobs for +units which has Markers= needs-reload or needs-restart. + +When the chunk of code which does the transformations is moved from +bus_unit_queue_job to bus_unit_queue_job_one, there is no change for +bus_unit_queue_job, and method_enqueue_marked_jobs is fixed. + +The additional checks that are done seem reasonable to do from +method_enqueue_marked_jobs: we shouldn't be restarting units which are +configured to not allow that, or force unwanted start of dbus-broker. + +(cherry picked from commit 8ea8e23f4013dbc4f4a66c81eb786f0505434f2e) + +Resolves: RHEL-40878 +--- + src/core/dbus-unit.c | 82 ++++++++++++++++++++++---------------------- + 1 file changed, 41 insertions(+), 41 deletions(-) + +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index 49eacc977c..b45b3fdb53 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -1736,6 +1736,47 @@ int bus_unit_queue_job_one( + Job *j, *a; + int r; + ++ if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) { ++ if (type == JOB_RESTART) ++ type = JOB_RELOAD_OR_START; ++ else if (type == JOB_TRY_RESTART) ++ type = JOB_TRY_RELOAD; ++ } ++ ++ if (type == JOB_STOP && ++ IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) && ++ unit_active_state(u) == UNIT_INACTIVE) ++ return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id); ++ ++ if ((type == JOB_START && u->refuse_manual_start) || ++ (type == JOB_STOP && u->refuse_manual_stop) || ++ (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) || ++ (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start)) ++ return sd_bus_error_setf(error, ++ BUS_ERROR_ONLY_BY_DEPENDENCY, ++ "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", ++ u->id); ++ ++ /* dbus-broker issues StartUnit for activation requests, and Type=dbus services automatically ++ * gain dependency on dbus.socket. Therefore, if dbus has a pending stop job, the new start ++ * job that pulls in dbus again would cause job type conflict. Let's avoid that by rejecting ++ * job enqueuing early. ++ * ++ * Note that unlike signal_activation_request(), we can't use unit_inactive_or_pending() ++ * here. StartUnit is a more generic interface, and thus users are allowed to use e.g. systemctl ++ * to start Type=dbus services even when dbus is inactive. */ ++ if (type == JOB_START && u->type == UNIT_SERVICE && SERVICE(u)->type == SERVICE_DBUS) ++ FOREACH_STRING(dbus_unit, SPECIAL_DBUS_SOCKET, SPECIAL_DBUS_SERVICE) { ++ Unit *dbus; ++ ++ dbus = manager_get_unit(u->manager, dbus_unit); ++ if (dbus && unit_stop_pending(dbus)) ++ return sd_bus_error_setf(error, ++ BUS_ERROR_SHUTTING_DOWN, ++ "Operation for unit %s refused, D-Bus is shutting down.", ++ u->id); ++ } ++ + if (FLAGS_SET(flags, BUS_UNIT_QUEUE_VERBOSE_REPLY)) { + affected = set_new(NULL); + if (!affected) +@@ -1828,47 +1869,6 @@ int bus_unit_queue_job( + if (r < 0) + return r; + +- if (FLAGS_SET(flags, BUS_UNIT_QUEUE_RELOAD_IF_POSSIBLE) && unit_can_reload(u)) { +- if (type == JOB_RESTART) +- type = JOB_RELOAD_OR_START; +- else if (type == JOB_TRY_RESTART) +- type = JOB_TRY_RELOAD; +- } +- +- if (type == JOB_STOP && +- IN_SET(u->load_state, UNIT_NOT_FOUND, UNIT_ERROR, UNIT_BAD_SETTING) && +- unit_active_state(u) == UNIT_INACTIVE) +- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id); +- +- if ((type == JOB_START && u->refuse_manual_start) || +- (type == JOB_STOP && u->refuse_manual_stop) || +- (IN_SET(type, JOB_RESTART, JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop)) || +- (type == JOB_RELOAD_OR_START && job_type_collapse(type, u) == JOB_START && u->refuse_manual_start)) +- return sd_bus_error_setf(error, +- BUS_ERROR_ONLY_BY_DEPENDENCY, +- "Operation refused, unit %s may be requested by dependency only (it is configured to refuse manual start/stop).", +- u->id); +- +- /* dbus-broker issues StartUnit for activation requests, and Type=dbus services automatically +- * gain dependency on dbus.socket. Therefore, if dbus has a pending stop job, the new start +- * job that pulls in dbus again would cause job type conflict. Let's avoid that by rejecting +- * job enqueuing early. +- * +- * Note that unlike signal_activation_request(), we can't use unit_inactive_or_pending() +- * here. StartUnit is a more generic interface, and thus users are allowed to use e.g. systemctl +- * to start Type=dbus services even when dbus is inactive. */ +- if (type == JOB_START && u->type == UNIT_SERVICE && SERVICE(u)->type == SERVICE_DBUS) +- FOREACH_STRING(dbus_unit, SPECIAL_DBUS_SOCKET, SPECIAL_DBUS_SERVICE) { +- Unit *dbus; +- +- dbus = manager_get_unit(u->manager, dbus_unit); +- if (dbus && unit_stop_pending(dbus)) +- return sd_bus_error_setf(error, +- BUS_ERROR_SHUTTING_DOWN, +- "Operation for unit %s refused, D-Bus is shutting down.", +- u->id); +- } +- + r = sd_bus_message_new_method_return(message, &reply); + if (r < 0) + return r; diff --git a/0811-rpm-add-systemd_postun_with_reload-and-systemd_user_.patch b/0811-rpm-add-systemd_postun_with_reload-and-systemd_user_.patch new file mode 100644 index 0000000..f2fb33b --- /dev/null +++ b/0811-rpm-add-systemd_postun_with_reload-and-systemd_user_.patch @@ -0,0 +1,98 @@ +From 8f9211463be196fee3acaba8d0d3aaff1dc166a0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 26 Jul 2023 09:02:04 +0200 +Subject: [PATCH] rpm: add `systemd_postun_with_reload` and + `systemd_user_postun_with_reload` + +For some units, the package would like to issue a reload. The machinery was +already in place since c9615f73521986b3607b852c139036d58973043c: + + systemctl reload-or-restart --marked + + Enqueues restart jobs for all units that have the 'needs-restart' + mark, and reload jobs for units that have the 'needs-reload' mark. + When a unit marked for reload does not support reload, restart will + be queued. + +The new macros allow a reload to be issued instead of a restart. + +Based on the discussion on fedora-devel: +https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/message/IJSUGIEJNYZZRE53FF4YFUEBRHRAVIXR/ + +Tested using dummy package https://github.com/keszybz/rpm-test-reload. + +(cherry picked from commit 631d2b05ec5195d1f8f8fbff8a2dfcbf23d0b7aa) + +Resolves: RHEL-40878 +--- + src/rpm/macros.systemd.in | 16 ++++++++++++++++ + src/rpm/systemd-update-helper.in | 22 ++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +diff --git a/src/rpm/macros.systemd.in b/src/rpm/macros.systemd.in +index 8880078b1b..fc607346e3 100644 +--- a/src/rpm/macros.systemd.in ++++ b/src/rpm/macros.systemd.in +@@ -101,6 +101,22 @@ if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ + fi \ + %{nil} + ++%systemd_postun_with_reload() \ ++%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_reload}} \ ++if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ ++ # Package upgrade, not uninstall \ ++ {{SYSTEMD_UPDATE_HELPER_PATH}} mark-reload-system-units %{?*} || : \ ++fi \ ++%{nil} ++ ++%systemd_user_postun_with_reload() \ ++%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_postun_with_reload}} \ ++if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ ++ # Package upgrade, not uninstall \ ++ {{SYSTEMD_UPDATE_HELPER_PATH}} mark-reload-user-units %{?*} || : \ ++fi \ ++%{nil} ++ + %udev_hwdb_update() %{nil} + + %udev_rules_update() %{nil} +diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in +index b35d952fab..1e00877de4 100755 +--- a/src/rpm/systemd-update-helper.in ++++ b/src/rpm/systemd-update-helper.in +@@ -47,6 +47,15 @@ case "$command" in + wait + ;; + ++ mark-reload-system-units) ++ [ -d /run/systemd/system ] || exit 0 ++ ++ for unit in "$@"; do ++ systemctl set-property "$unit" Markers=+needs-reload & ++ done ++ wait ++ ;; ++ + mark-restart-user-units) + [ -d /run/systemd/system ] || exit 0 + +@@ -60,6 +69,19 @@ case "$command" in + wait + ;; + ++ mark-reload-user-units) ++ [ -d /run/systemd/system ] || exit 0 ++ ++ users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p') ++ for user in $users; do ++ for unit in "$@"; do ++ SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \ ++ systemctl --user -M "$user@" set-property "$unit" Markers=+needs-reload & ++ done ++ done ++ wait ++ ;; ++ + system-reload-restart|system-reload|system-restart) + if [ -n "$*" ]; then + echo "Unexpected arguments for '$command': $*" diff --git a/0812-rpm-add-systemd_user_daemon_reexec.patch b/0812-rpm-add-systemd_user_daemon_reexec.patch new file mode 100644 index 0000000..f932588 --- /dev/null +++ b/0812-rpm-add-systemd_user_daemon_reexec.patch @@ -0,0 +1,38 @@ +From 2400e5c6395459fa3629747168c36df8ef543811 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 28 Jul 2023 19:24:58 +0200 +Subject: [PATCH] rpm: add `systemd_user_daemon_reexec` + +This macros wraps the call to daemon-reexec in all user managers. It would be +called for example from systemd %post right after the call to systemctl +daemon-reexec. + +This will be used in the Fedora systemd package to fix a long-standing FIXME. + +Tested via building and reinstalling the systemd package with the patches. + +(cherry picked from commit 9ff28e312bffe7567aa5d3f2c41303dd456f1691) + +Resolves: RHEL-40878 +--- + src/rpm/macros.systemd.in | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/rpm/macros.systemd.in b/src/rpm/macros.systemd.in +index fc607346e3..8d5895eba1 100644 +--- a/src/rpm/macros.systemd.in ++++ b/src/rpm/macros.systemd.in +@@ -117,6 +117,13 @@ if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ + fi \ + %{nil} + ++%systemd_user_daemon_reexec() \ ++if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \ ++ # Package upgrade, not uninstall \ ++ {{SYSTEMD_UPDATE_HELPER_PATH}} user-reexec || : \ ++fi \ ++%{nil} ++ + %udev_hwdb_update() %{nil} + + %udev_rules_update() %{nil} diff --git a/systemd.spec b/systemd.spec index cbf8403..1c6518f 100644 --- a/systemd.spec +++ b/systemd.spec @@ -25,7 +25,7 @@ Name: systemd Url: https://systemd.io Version: 252 -Release: 35%{?dist} +Release: 37%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -830,6 +830,77 @@ Patch0738: 0738-bootspec-fix-null-dereference-read.patch Patch0739: 0739-units-don-t-install-pcrphase-related-units-without-g.patch Patch0740: 0740-kernel-install-fix-uki-copy-deinstall.patch Patch0741: 0741-ci-packit-explicitly-clone-c9s-branch.patch +Patch0742: 0742-ci-src-git-add-RHEL-9.1-and-RHEL-9.1.z-to-allowed-ve.patch +Patch0743: 0743-libsystemd-link-with-z-nodelete.patch +Patch0744: 0744-basic-utf8-make-utf8_encoded_to_unichar-return-lengt.patch +Patch0745: 0745-test-gunicode-add-new-test-to-show-that-unichar_iswi.patch +Patch0746: 0746-string-util-pass-ANSI-sequences-through-unchanged.patch +Patch0747: 0747-cryptsetup-do-not-assert-when-unsealing-token-withou.patch +Patch0748: 0748-cryptsetup-check-the-existence-of-salt-by-salt_size-.patch +Patch0749: 0749-core-mount-if-umount-8-fails-but-mount-disappeared-a.patch +Patch0750: 0750-Drop-log-level-of-header-limits-log-message.patch +Patch0751: 0751-journal-do-not-rotate-unrelated-journal-files-when-f.patch +Patch0752: 0752-man-suffix-unit-with-an-equal-sign-since-it-expects-.patch +Patch0753: 0753-shared-move-uid-alloc-range.-ch-from-src-shared-src-.patch +Patch0754: 0754-journald-move-uid_for_system_journal-to-uid-alloc-ra.patch +Patch0755: 0755-sd-journal-when-SD_JOURNAL_CURRENT_USER-is-set-and-c.patch +Patch0756: 0756-man-document-that-journalctl-user-requires-Storage-p.patch +Patch0757: 0757-fix-prefix-of-dmesg-pstore-files.patch +Patch0758: 0758-backport-new-mkosi.patch +Patch0759: 0759-test-Skip-various-tests-when-sys-is-not-mounted.patch +Patch0760: 0760-string-util-introduce-ascii_ishex.patch +Patch0761: 0761-sd-id128-several-cleanups.patch +Patch0762: 0762-sd-id128-make-id128_read-or-friends-return-ENOPKG-wh.patch +Patch0763: 0763-test-add-tests-for-uninitialized-string-handling-by-.patch +Patch0764: 0764-man-mention-sd_id128_get_machine-or-friend-may-retur.patch +Patch0765: 0765-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch +Patch0766: 0766-sd-id128-make-sd_id128_get_boot-and-friend-return-EN.patch +Patch0767: 0767-man-mention-that-sd_id128_get_boot-and-friend-may-re.patch +Patch0768: 0768-sd-id128-fold-do_sync-flag-into-Id128FormatFlag.patch +Patch0769: 0769-sd-id128-make-sd_id128_get_machine-or-friends-return.patch +Patch0770: 0770-sd-id128-allow-sd_id128_get_machine-and-friend-to-be.patch +Patch0771: 0771-sd-id128-also-refuse-an-empty-invocation-ID.patch +Patch0772: 0772-man-update-documents-for-sd_id128_get_invocation.patch +Patch0773: 0773-test-id128-simplify-machine-id-check.patch +Patch0774: 0774-test-fs-util-skip-part-of-test_chase_symlinks-if-mac.patch +Patch0775: 0775-test-unit-name-simplify-machine-id-check.patch +Patch0776: 0776-test-load-fragment-simplify-machine-id-check.patch +Patch0777: 0777-journal-skip-part-of-test-journal-interleaving-if-no.patch +Patch0778: 0778-test-skip-journal-tests-without-valid-etc-machine-id.patch +Patch0779: 0779-test-recurse-dir-work-around-nftw-ignoring-symlinks.patch +Patch0780: 0780-test-Skip-test-recurse-dir-on-overlayfs.patch +Patch0781: 0781-test-specifier-Ignore-ENOPKG-from-specifier_printf.patch +Patch0782: 0782-test-execute-Skip-when-sys-is-read-only.patch +Patch0783: 0783-kernel-install-Make-sure-KERNEL_INSTALL_BYPASS-is-di.patch +Patch0784: 0784-tools-make-sure-KERNEL_INSTALL_BYPASS-is-disabled-wh.patch +Patch0785: 0785-test-execute-drop-capabilities-when-testing-with-use.patch +Patch0786: 0786-tmpfiles-Add-merge-support-for-copy-files-action.patch +Patch0787: 0787-generator-add-generator_open_unit_file_full-to-allow.patch +Patch0788: 0788-network-generator-rewrite-unit-if-it-already-exists-.patch +Patch0789: 0789-ci-drop-super-linter-s-shellcheck.patch +Patch0790: 0790-mkosi-make-sure-we-build-use-RHEL-9-stuff.patch +Patch0791: 0791-ci-backport-mkosi-CI-configuration-from-upstream.patch +Patch0792: 0792-mkosi-explicitly-enroll-SecureBoot-keys.patch +Patch0793: 0793-test-execute-also-mount-tmpfs-on-dev-shm.patch +Patch0794: 0794-mkosi-fix-UKI-addons-test.patch +Patch0795: 0795-Revert-mkosi-Disable-cmdline-addon-test-for-now.patch +Patch0796: 0796-Revert-mkosi-Don-t-fail-on-systemd-vconsole-setup.se.patch +Patch0797: 0797-mkosi-make-shellcheck-happy.patch +Patch0798: 0798-mkosi-use-pesign-for-signing-UKI-addons.patch +Patch0799: 0799-test-copy-out-the-necessary-test-data-before-we-star.patch +Patch0800: 0800-ci-make-the-build-dir-accessible-when-running-w-o-pr.patch +Patch0801: 0801-ci-explicitly-change-oom-score-adj-before-running-te.patch +Patch0802: 0802-ratelimit-add-ratelimit_left-helper.patch +Patch0803: 0803-manager-restrict-Dump-to-privileged-callers-or-ratel.patch +Patch0804: 0804-ci-define-runas-function-inline.patch +Patch0805: 0805-Drop-dev-test-in-test-mountpoint-util.patch +Patch0806: 0806-core-manager-export-manager_dbus_is_running.patch +Patch0807: 0807-core-refuse-dbus-activation-if-dbus-is-not-running.patch +Patch0808: 0808-core-only-refuse-Type-dbus-service-enqueuing-if-dbus.patch +Patch0809: 0809-Revert-core-manager-export-manager_dbus_is_running-a.patch +Patch0810: 0810-manager-fix-reloading-in-reload-or-restart-marked.patch +Patch0811: 0811-rpm-add-systemd_postun_with_reload-and-systemd_user_.patch +Patch0812: 0812-rpm-add-systemd_user_daemon_reexec.patch # Downstream-only patches (9000–9999) @@ -1710,6 +1781,79 @@ systemd-hwdb update &>/dev/null || : %{_prefix}/lib/dracut/modules.d/70rhel-net-naming-sysattrs/* %changelog +* Thu Jun 13 2024 systemd maintenance team - 252-37 +- ci(src-git): add RHEL-9.1 and RHEL-9.1.z to allowed versions (RHEL-30372) +- libsystemd: link with '-z nodelete' (RHEL-6589) +- basic/utf8: make utf8_encoded_to_unichar() return length of the codepoint (RHEL-31219) +- test-gunicode: add new test to show that unichar_iswide() is borked (RHEL-31219) +- string-util: pass ANSI sequences through unchanged (RHEL-31219) +- cryptsetup: do not assert when unsealing token without salt (RHEL-38864) +- cryptsetup: check the existence of salt by salt_size > 0 (RHEL-38864) +- core/mount: if umount(8) fails but mount disappeared, assume success (RHEL-13159) +- Drop log level of header limits log message (RHEL-33890) +- journal: do not rotate unrelated journal files when full or corrupted (RHEL-33890) +- man: suffix --unit with an equal sign, since it expects an argument (RHEL-31070) +- shared: move uid-alloc-range.[ch] from src/shared/ → src/basic/ (RHEL-31070) +- journald: move uid_for_system_journal() to uid-alloc-range.h (RHEL-31070) +- sd-journal: when SD_JOURNAL_CURRENT_USER is set, and called from system UID, imply SD_JOURNAL_SYSTEM (RHEL-31070) +- man: document that journalctl --user requires Storage=persistent (RHEL-31070) +- fix: prefix of dmesg pstore files (RHEL-20322) +- backport new mkosi (RHEL-27512) +- test: Skip various tests when /sys is not mounted (RHEL-27512) +- string-util: introduce ascii_ishex() (RHEL-27512) +- sd-id128: several cleanups (RHEL-27512) +- sd-id128: make id128_read() or friends return -ENOPKG when the file contents is "uninitialized" (RHEL-27512) +- test: add tests for "uninitialized" string handling by id128_read_fd() (RHEL-27512) +- man: mention sd_id128_get_machine() or friend may return -ENOPKG (RHEL-27512) +- sd-id128: make sd_id128_get_boot() and friend return -ENOMEDIUM (RHEL-27512) +- sd-id128: make sd_id128_get_boot() and friend return -ENOSYS when /proc/ is not mounted (RHEL-27512) +- man: mention that sd_id128_get_boot() and friend may return -ENOSYS (RHEL-27512) +- sd-id128: fold do_sync flag into Id128FormatFlag (RHEL-27512) +- sd-id128: make sd_id128_get_machine() or friends return -EUCLEAN when an ID is in an invalid format (RHEL-27512) +- sd-id128: allow sd_id128_get_machine() and friend to be called with NULL (RHEL-27512) +- sd-id128: also refuse an empty invocation ID (RHEL-27512) +- man: update documents for sd_id128_get_invocation() (RHEL-27512) +- test-id128: simplify machine-id check (RHEL-27512) +- test-fs-util: skip part of test_chase_symlinks if machine-id is not initialized (RHEL-27512) +- test-unit-name: simplify machine-id check (RHEL-27512) +- test-load-fragment: simplify machine-id check (RHEL-27512) +- journal: skip part of test-journal-interleaving if no machine-id exists (RHEL-27512) +- test: skip journal tests without valid /etc/machine-id (RHEL-27512) +- test-recurse-dir: work around nftw() ignoring symlinks() (RHEL-27512) +- test: Skip test-recurse-dir on overlayfs (RHEL-27512) +- test-specifier: Ignore -ENOPKG from specifier_printf() (RHEL-27512) +- test-execute: Skip when /sys is read-only (RHEL-27512) +- kernel-install: Make sure KERNEL_INSTALL_BYPASS is disabled in tests (RHEL-27512) +- tools: make sure $KERNEL_INSTALL_BYPASS is disabled when checking help (RHEL-27512) +- test-execute: drop capabilities when testing with user manager (RHEL-27512) +- tmpfiles: Add merge support for copy files action (RHEL-27512) +- generator: add generator_open_unit_file_full to allow creating temporary units (RHEL-27512) +- network-generator: rewrite unit if it already exists and its content changed (RHEL-27512) +- ci: drop super-linter's shellcheck (RHEL-27512) +- mkosi: make sure we build & use RHEL 9 stuff (RHEL-27512) +- ci: backport mkosi CI configuration from upstream (RHEL-27512) +- mkosi: explicitly enroll SecureBoot keys (RHEL-27512) +- test-execute: also mount tmpfs on /dev/shm (RHEL-27512) +- mkosi: fix UKI addons test (RHEL-27512) +- Revert "mkosi: Disable cmdline addon test for now" (RHEL-27512) +- Revert "mkosi: Don't fail on systemd-vconsole-setup.service failure for now" (RHEL-27512) +- mkosi: make shellcheck happy (RHEL-27512) +- mkosi: use pesign for signing UKI addons (RHEL-27512) +- test: copy out the necessary test data before we start overmounting stuff (RHEL-27512) +- ci: make the build dir accessible when running w/o privileges (RHEL-27512) +- ci: explicitly change oom-{score}-adj before running tests (RHEL-27512) +- ratelimit: add ratelimit_left helper (RHEL-35703) +- manager: restrict Dump*() to privileged callers or ratelimit (RHEL-35703) +- ci: define `runas` function inline (RHEL-35703) +- Drop /dev test in test-mountpoint-util (RHEL-30372) +- core/manager: export manager_dbus_is_running (RHEL-40878) +- core: refuse dbus activation if dbus is not running (RHEL-40878) +- core: only refuse Type=dbus service enqueuing if dbus has stop job (RHEL-40878) +- Revert "core/manager: export manager_dbus_is_running" and partially "core: refuse dbus activation if dbus is not running" (RHEL-40878) +- manager: fix reloading in reload-or-restart --marked (RHEL-40878) +- rpm: add `systemd_postun_with_reload` and `systemd_user_postun_with_reload` (RHEL-40878) +- rpm: add `systemd_user_daemon_reexec` (RHEL-40878) + * Wed May 22 2024 Jan Macku - 252-35 - spec: return selinux dependencies (RHEL-35732)