diff --git a/SOURCES/1251-cryptsetup-Add-optional-support-for-linking-volume-k.patch b/SOURCES/1251-cryptsetup-Add-optional-support-for-linking-volume-k.patch new file mode 100644 index 0000000..e10fe61 --- /dev/null +++ b/SOURCES/1251-cryptsetup-Add-optional-support-for-linking-volume-k.patch @@ -0,0 +1,167 @@ +From a8c056f2847f080e8ceb5d43fe0d36b5c5ee8655 Mon Sep 17 00:00:00 2001 +From: Ondrej Kozina +Date: Wed, 31 Jan 2024 13:11:21 +0100 +Subject: [PATCH] cryptsetup: Add optional support for linking volume key in + keyring. + +cryptsetup 2.7.0 adds feature to link effective volume key in custom +kernel keyring during device activation. It can be used later to pass +linked volume key to other services. + +For example: kdump enabled systems installed on LUKS2 device. +This feature allows it to store volume key linked in a kernel keyring +to the kdump reserved memory and reuse it to reactivate LUKS2 device +in case of kernel crash. + +(cherry picked from commit c5daf14c88ba44cefabe052de93a29d28b6b0175) + +Resolves: RHEL-118294 +--- + man/crypttab.xml | 21 ++++++++++++ + meson.build | 3 +- + src/cryptsetup/cryptsetup.c | 65 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 88 insertions(+), 1 deletion(-) + +diff --git a/man/crypttab.xml b/man/crypttab.xml +index 1dd9bb1bb6..bd49e025fa 100644 +--- a/man/crypttab.xml ++++ b/man/crypttab.xml +@@ -239,6 +239,27 @@ + + + ++ ++ ++ ++ Specifies the kernel keyring and key description ++ (see keyrings7) ++ where LUKS2 volume key gets linked during device activation. The kernel keyring ++ description and key description must be separated by ::. ++ ++ The kernel keyring part can be a string description or a predefined ++ kernel keyring prefixed with @ (e.g.: to use @s session or ++ @u user keyring directly). The type prefix text in the kernel keyring description ++ is not required. The specified kernel keyring must already exist at the time of device activation. ++ ++ The key part is a string description optionally prefixed by a %key_type:. ++ If no type is specified, the user type key is linked by default. See ++ keyctl1 ++ for more information on key descriptions (KEY IDENTIFIERS section). ++ ++ Note that the linked volume key is not cleaned up automatically when the device is detached. ++ ++ + + + +diff --git a/meson.build b/meson.build +index cbde702211..684324c6d7 100644 +--- a/meson.build ++++ b/meson.build +@@ -1316,7 +1316,8 @@ if want_libcryptsetup != 'false' and not skip_deps + + foreach ident : ['crypt_set_metadata_size', + 'crypt_activate_by_signed_key', +- 'crypt_token_max'] ++ 'crypt_token_max', ++ 'crypt_set_keyring_to_link'] + have_ident = have and cc.has_function( + ident, + prefix : '#include ', +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index 3f2cab1e41..f9130e2568 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -101,6 +101,9 @@ static bool arg_headless = false; + static usec_t arg_token_timeout_usec = 30*USEC_PER_SEC; + static unsigned arg_tpm2_measure_pcr = UINT_MAX; /* This and the following field is about measuring the unlocked volume key to the local TPM */ + static char **arg_tpm2_measure_banks = NULL; ++static char *arg_link_keyring = NULL; ++static char *arg_link_key_type = NULL; ++static char *arg_link_key_description = NULL; + + STATIC_DESTRUCTOR_REGISTER(arg_cipher, freep); + STATIC_DESTRUCTOR_REGISTER(arg_hash, freep); +@@ -113,6 +116,9 @@ STATIC_DESTRUCTOR_REGISTER(arg_fido2_rp_id, freep); + STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep); + STATIC_DESTRUCTOR_REGISTER(arg_tpm2_signature, freep); + STATIC_DESTRUCTOR_REGISTER(arg_tpm2_measure_banks, strv_freep); ++STATIC_DESTRUCTOR_REGISTER(arg_link_keyring, freep); ++STATIC_DESTRUCTOR_REGISTER(arg_link_key_type, freep); ++STATIC_DESTRUCTOR_REGISTER(arg_link_key_description, freep); + + static const char* const passphrase_type_table[_PASSPHRASE_TYPE_MAX] = { + [PASSPHRASE_REGULAR] = "passphrase", +@@ -486,6 +492,56 @@ static int parse_one_option(const char *option) { + if (r < 0) + log_warning_errno(r, "Failed to parse %s, ignoring: %m", option); + ++ } else if ((val = startswith(option, "link-volume-key="))) { ++#ifdef HAVE_CRYPT_SET_KEYRING_TO_LINK ++ const char *sep, *c; ++ _cleanup_free_ char *keyring = NULL, *key_type = NULL, *key_description = NULL; ++ ++ /* Stick with cryptsetup --link-vk-to-keyring format ++ * ::%:, ++ * where % is optional and defaults to 'user'. ++ */ ++ if (!(sep = strstr(val, "::"))) ++ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse link-volume-key= option value: %m"); ++ ++ /* cryptsetup (cli) supports passed in various formats: ++ * - well-known keyrings prefixed with '@' (@u user, @s session, etc) ++ * - text descriptions prefixed with "%:" or "%keyring:". ++ * - text desription with no prefix. ++ * - numeric keyring id (ignored in current patch set). */ ++ if (*val == '@' || *val == '%') ++ keyring = strndup(val, sep - val); ++ else ++ /* add type prefix if missing (crypt_set_keyring_to_link() expects it) */ ++ keyring = strnappend("%:", val, sep - val); ++ if (!keyring) ++ return log_oom(); ++ ++ sep += 2; ++ ++ /* % is optional (and defaults to 'user') */ ++ if (*sep == '%') { ++ /* must be separated by colon */ ++ if (!(c = strchr(sep, ':'))) ++ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse link-volume-key= option value: %m"); ++ ++ key_type = strndup(sep + 1, c - sep - 1); ++ if (!key_type) ++ return log_oom(); ++ ++ sep = c + 1; ++ } ++ ++ key_description = strdup(sep); ++ if (!key_description) ++ return log_oom(); ++ ++ free_and_replace(arg_link_keyring, keyring); ++ free_and_replace(arg_link_key_type, key_type); ++ free_and_replace(arg_link_key_description, key_description); ++#else ++ log_error("Build lacks libcryptsetup support for linking volume keys in user specified kernel keyrings upon device activation, ignoring: %s", option); ++#endif + } else if (!streq(option, "x-initrd.attach")) + log_warning("Encountered unknown /etc/crypttab option '%s', ignoring.", option); + +@@ -2207,6 +2263,15 @@ static int run(int argc, char *argv[]) { + if (r < 0) + return log_error_errno(r, "Failed to load LUKS superblock on device %s: %m", crypt_get_device_name(cd)); + ++/* since cryptsetup 2.7.0 (Jan 2024) */ ++#if HAVE_CRYPT_SET_KEYRING_TO_LINK ++ if (arg_link_key_description) { ++ r = crypt_set_keyring_to_link(cd, arg_link_key_description, NULL, arg_link_key_type, arg_link_keyring); ++ if (r < 0) ++ log_warning_errno(r, "Failed to set keyring or key description to link volume key in, ignoring: %m"); ++ } ++#endif ++ + if (arg_header) { + r = crypt_set_data_device(cd, source); + if (r < 0) diff --git a/SOURCES/1252-cryptsetup-fix-typo.patch b/SOURCES/1252-cryptsetup-fix-typo.patch new file mode 100644 index 0000000..11bb7e1 --- /dev/null +++ b/SOURCES/1252-cryptsetup-fix-typo.patch @@ -0,0 +1,27 @@ +From 9807259b544cbf4f7a0a05bd426b95c788a89bd4 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 14 Feb 2024 04:01:36 +0900 +Subject: [PATCH] cryptsetup: fix typo + +Follow-up for c5daf14c88ba44cefabe052de93a29d28b6b0175. + +(cherry picked from commit a14d3b48f7647676a0c43bceaecd56d9a77e3de6) + +Resolves: RHEL-118294 +--- + src/cryptsetup/cryptsetup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index f9130e2568..1f672f19f1 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -507,7 +507,7 @@ static int parse_one_option(const char *option) { + /* cryptsetup (cli) supports passed in various formats: + * - well-known keyrings prefixed with '@' (@u user, @s session, etc) + * - text descriptions prefixed with "%:" or "%keyring:". +- * - text desription with no prefix. ++ * - text description with no prefix. + * - numeric keyring id (ignored in current patch set). */ + if (*val == '@' || *val == '%') + keyring = strndup(val, sep - val); diff --git a/SOURCES/1253-cryptsetup-HAVE_CRYPT_SET_KEYRING_TO_LINK-is-always-.patch b/SOURCES/1253-cryptsetup-HAVE_CRYPT_SET_KEYRING_TO_LINK-is-always-.patch new file mode 100644 index 0000000..e7d5c1d --- /dev/null +++ b/SOURCES/1253-cryptsetup-HAVE_CRYPT_SET_KEYRING_TO_LINK-is-always-.patch @@ -0,0 +1,27 @@ +From 4920d1ca6823abe29e8cf2eceea497d9b677ee95 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 17 Aug 2025 21:05:24 +0900 +Subject: [PATCH] cryptsetup: HAVE_CRYPT_SET_KEYRING_TO_LINK is always defined + +Follow-up for c5daf14c88ba44cefabe052de93a29d28b6b0175 (v256). + +(cherry picked from commit fb4aabf4432d523b97376099ce4353b5c268ae82) + +Resolves: RHEL-118294 +--- + src/cryptsetup/cryptsetup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index 1f672f19f1..4dc315e810 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -493,7 +493,7 @@ static int parse_one_option(const char *option) { + log_warning_errno(r, "Failed to parse %s, ignoring: %m", option); + + } else if ((val = startswith(option, "link-volume-key="))) { +-#ifdef HAVE_CRYPT_SET_KEYRING_TO_LINK ++#if HAVE_CRYPT_SET_KEYRING_TO_LINK + const char *sep, *c; + _cleanup_free_ char *keyring = NULL, *key_type = NULL, *key_description = NULL; + diff --git a/SOURCES/1254-basic-add-PIDFS-magic-31709.patch b/SOURCES/1254-basic-add-PIDFS-magic-31709.patch new file mode 100644 index 0000000..e531f77 --- /dev/null +++ b/SOURCES/1254-basic-add-PIDFS-magic-31709.patch @@ -0,0 +1,51 @@ +From 4d9bb355df2ba60d734a73a62bf489abbb8ec54c Mon Sep 17 00:00:00 2001 +From: cpackham-atlnz <85916201+cpackham-atlnz@users.noreply.github.com> +Date: Tue, 12 Mar 2024 00:55:36 +1300 +Subject: [PATCH] basic: add PIDFS magic (#31709) + +Kernel commit cb12fd8e0dabb9a1c8aef55a6a41e2c255fcdf4b added pidfs. +Update filesystems-gperf.gperf and missing_magic.h accordingly. + +This fixes the following error building against a bleeding edge kernel. +``` +../src/basic/meson.build:234:8: ERROR: Problem encountered: Unknown filesystems defined in kernel headers: + +Filesystem found in kernel header but not in filesystems-gperf.gperf: PID_FS_MAGIC +``` + +(cherry picked from commit ed01b92e1c92871bbd92711f280e2b2d15753f0e) + +Resolves: RHEL-118294 +--- + src/basic/filesystems-gperf.gperf | 1 + + src/basic/missing_magic.h | 5 +++++ + 2 files changed, 6 insertions(+) + +diff --git a/src/basic/filesystems-gperf.gperf b/src/basic/filesystems-gperf.gperf +index e8c5357f91..1cd66b5a5f 100644 +--- a/src/basic/filesystems-gperf.gperf ++++ b/src/basic/filesystems-gperf.gperf +@@ -91,6 +91,7 @@ ocfs2, {OCFS2_SUPER_MAGIC} + openpromfs, {OPENPROM_SUPER_MAGIC} + orangefs, {ORANGEFS_DEVREQ_MAGIC} + overlay, {OVERLAYFS_SUPER_MAGIC} ++pidfs, {PID_FS_MAGIC} + pipefs, {PIPEFS_MAGIC} + ppc-cmm, {PPC_CMM_MAGIC} + proc, {PROC_SUPER_MAGIC} +diff --git a/src/basic/missing_magic.h b/src/basic/missing_magic.h +index c104fcfba3..82ede1873e 100644 +--- a/src/basic/missing_magic.h ++++ b/src/basic/missing_magic.h +@@ -128,6 +128,11 @@ + #define DEVMEM_MAGIC 0x454d444d + #endif + ++/* cb12fd8e0dabb9a1c8aef55a6a41e2c255fcdf4b (6.8) */ ++#ifndef PID_FS_MAGIC ++#define PID_FS_MAGIC 0x50494446 ++#endif ++ + /* Not in mainline but included in Ubuntu */ + #ifndef SHIFTFS_MAGIC + #define SHIFTFS_MAGIC 0x6a656a62 diff --git a/SOURCES/1255-time-util-make-USEC_TIMESTAMP_FORMATTABLE_MAX-for-32.patch b/SOURCES/1255-time-util-make-USEC_TIMESTAMP_FORMATTABLE_MAX-for-32.patch new file mode 100644 index 0000000..907986b --- /dev/null +++ b/SOURCES/1255-time-util-make-USEC_TIMESTAMP_FORMATTABLE_MAX-for-32.patch @@ -0,0 +1,74 @@ +From a8ef307f05961e142b99cbbdda8855a24a44d4a1 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 12 Mar 2023 20:57:16 +0900 +Subject: [PATCH] time-util: make USEC_TIMESTAMP_FORMATTABLE_MAX for 32bit + system off by one day + +As the same reason why we take one day off for 64bit case. + +This also makes both upper bounds always defined for testing. + +(cherry picked from commit bd5770da76ee157d3b31323ed2d22f5d9082bb36) + +Related: RHEL-118294 +--- + src/basic/time-util.h | 14 +++++++++----- + src/test/test-date.c | 4 ++-- + src/test/test-time-util.c | 2 +- + 3 files changed, 12 insertions(+), 8 deletions(-) + +diff --git a/src/basic/time-util.h b/src/basic/time-util.h +index 9d44cac747..7f8bda0948 100644 +--- a/src/basic/time-util.h ++++ b/src/basic/time-util.h +@@ -200,13 +200,17 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) { + return usec_sub_unsigned(timestamp, (usec_t) delta); + } + ++/* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit ++ * year territory. However, since we want to stay away from this in all timezones we take one day off. */ ++#define USEC_TIMESTAMP_FORMATTABLE_MAX_64BIT ((usec_t) 253402214399000000) /* Thu 9999-12-30 23:59:59 UTC */ ++/* With a 32bit time_t we can't go beyond 2038... ++ * We parse timestamp with RFC-822/ISO 8601 (e.g. +06, or -03:00) as UTC, hence the upper bound must be off ++ * by USEC_PER_DAY. See parse_timestamp() for more details. */ ++#define USEC_TIMESTAMP_FORMATTABLE_MAX_32BIT (((usec_t) INT32_MAX) * USEC_PER_SEC - USEC_PER_DAY) + #if SIZEOF_TIME_T == 8 +- /* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit +- * year territory. However, since we want to stay away from this in all timezones we take one day off. */ +-# define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 253402214399000000) ++# define USEC_TIMESTAMP_FORMATTABLE_MAX USEC_TIMESTAMP_FORMATTABLE_MAX_64BIT + #elif SIZEOF_TIME_T == 4 +-/* With a 32bit time_t we can't go beyond 2038... */ +-# define USEC_TIMESTAMP_FORMATTABLE_MAX ((usec_t) 2147483647000000) ++# define USEC_TIMESTAMP_FORMATTABLE_MAX USEC_TIMESTAMP_FORMATTABLE_MAX_32BIT + #else + # error "Yuck, time_t is neither 4 nor 8 bytes wide?" + #endif +diff --git a/src/test/test-date.c b/src/test/test-date.c +index cc11bd999e..ef316eeca7 100644 +--- a/src/test/test-date.c ++++ b/src/test/test-date.c +@@ -104,8 +104,8 @@ int main(int argc, char *argv[]) { + test_should_fail("9999-12-31 00:00:00 UTC"); + test_should_fail("10000-01-01 00:00:00 UTC"); + #elif SIZEOF_TIME_T == 4 +- test_should_pass("2038-01-19 03:14:07 UTC"); +- test_should_fail("2038-01-19 03:14:08 UTC"); ++ test_should_pass("2038-01-18 03:14:07 UTC"); ++ test_should_fail("2038-01-18 03:14:08 UTC"); + #endif + + return 0; +diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c +index 21b05a3010..71ef5906ba 100644 +--- a/src/test/test-time-util.c ++++ b/src/test/test-time-util.c +@@ -550,7 +550,7 @@ TEST(format_timestamp_utc) { + test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Thu 9999-12-30 23:59:59 UTC"); + test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX"); + #elif SIZEOF_TIME_T == 4 +- test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Tue 2038-01-19 03:14:07 UTC"); ++ test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Mon 2038-01-18 03:14:07 UTC"); + test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX + 1, "--- XXXX-XX-XX XX:XX:XX"); + #endif + diff --git a/SOURCES/1256-coredump-make-check-that-all-argv-meta-data-fields-a.patch b/SOURCES/1256-coredump-make-check-that-all-argv-meta-data-fields-a.patch new file mode 100644 index 0000000..3c805bd --- /dev/null +++ b/SOURCES/1256-coredump-make-check-that-all-argv-meta-data-fields-a.patch @@ -0,0 +1,34 @@ +From a257453e7febc1c984b180e14095c2e6092dc850 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 31 Oct 2024 17:02:59 +0100 +Subject: [PATCH] coredump: make check that all argv[] meta data fields are + passed strict + +Otherwise, if some field is not supplied we might end up parsing a NULL +string later. Let's catch that early. + +(cherry picked from commit 098c3975acb3df61eedfe471fca27c21f13cf04c) + +Related: RHEL-104138 +--- + src/coredump/coredump.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c +index dca78fa72c..b24f4c8cc3 100644 +--- a/src/coredump/coredump.c ++++ b/src/coredump/coredump.c +@@ -1067,9 +1067,10 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) { + } + } + +- if (!context->meta[META_ARGV_PID]) +- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), +- "Failed to find the PID of crashing process"); ++ /* The basic fields from argv[] should always be there, refuse early if not */ ++ for (int i = 0; i < _META_ARGV_MAX; i++) ++ if (!context->meta[i]) ++ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "A required (%s) has not been sent, aborting.", meta_field_names[i]); + + r = parse_pid(context->meta[META_ARGV_PID], &context->pid); + if (r < 0) diff --git a/SOURCES/1257-coredump-restore-compatibility-with-older-patterns.patch b/SOURCES/1257-coredump-restore-compatibility-with-older-patterns.patch new file mode 100644 index 0000000..0403e83 --- /dev/null +++ b/SOURCES/1257-coredump-restore-compatibility-with-older-patterns.patch @@ -0,0 +1,122 @@ +From de05f30a12a0f1ce03dc21a29a606c70e42d1de4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 29 Apr 2025 14:47:59 +0200 +Subject: [PATCH] coredump: restore compatibility with older patterns + +This was broken in f45b8015513d38ee5f7cc361db9c5b88c9aae704. Unfortunately +the review does not talk about backward compatibility at all. There are +two places where it matters: +- During upgrades, the replacement of kernel.core_pattern is asynchronous. + For example, during rpm upgrades, it would be updated a post-transaction + file trigger. In other scenarios, the update might only happen after + reboot. We have a potentially long window where the old pattern is in + place. We need to capture coredumps during upgrades too. +- With --backtrace. The interface of --backtrace, in hindsight, is not + great. But there are users of --backtrace which were written to use + a specific set of arguments, and we can't just break compatiblity. + One example is systemd-coredump-python, but there are also reports of + users using --backtrace to generate coredump logs. + +Thus, we require the original set of args, and will use the additional args if +found. + +A test is added to verify that --backtrace works with and without the optional +args. + +(cherry picked from commit ded0aac389e647d35bce7ec4a48e718d77c0435b) + +Related: RHEL-104138 +--- + src/coredump/coredump.c | 23 +++++++++++++++-------- + test/units/testsuite-74.coredump.sh | 18 +++++++++++------- + 2 files changed, 26 insertions(+), 15 deletions(-) + +diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c +index b24f4c8cc3..458857ffb2 100644 +--- a/src/coredump/coredump.c ++++ b/src/coredump/coredump.c +@@ -94,8 +94,12 @@ enum { + META_ARGV_SIGNAL, /* %s: number of signal causing dump */ + META_ARGV_TIMESTAMP, /* %t: time of dump, expressed as seconds since the Epoch (we expand this to µs granularity) */ + META_ARGV_RLIMIT, /* %c: core file size soft resource limit */ +- META_ARGV_HOSTNAME, /* %h: hostname */ ++ _META_ARGV_REQUIRED, ++ /* The fields below were added to kernel/core_pattern at later points, so they might be missing. */ ++ META_ARGV_HOSTNAME = _META_ARGV_REQUIRED, /* %h: hostname */ + _META_ARGV_MAX, ++ /* If new fields are added, they should be added here, to maintain compatibility ++ * with callers which don't know about the new fields. */ + + /* The following indexes are cached for a couple of special fields we use (and + * thereby need to be retrieved quickly) for naming coredump files, and attaching +@@ -106,7 +110,7 @@ enum { + _META_MANDATORY_MAX, + + /* The rest are similar to the previous ones except that we won't fail if one of +- * them is missing. */ ++ * them is missing in a message sent over the socket. */ + + META_EXE = _META_MANDATORY_MAX, + META_UNIT, +@@ -1068,7 +1072,7 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) { + } + + /* The basic fields from argv[] should always be there, refuse early if not */ +- for (int i = 0; i < _META_ARGV_MAX; i++) ++ for (int i = 0; i < _META_ARGV_REQUIRED; i++) + if (!context->meta[i]) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "A required (%s) has not been sent, aborting.", meta_field_names[i]); + +@@ -1286,14 +1290,17 @@ static int gather_pid_metadata_from_argv( + char *t; + + /* We gather all metadata that were passed via argv[] into an array of iovecs that +- * we'll forward to the socket unit */ ++ * we'll forward to the socket unit. ++ * ++ * We require at least _META_ARGV_REQUIRED args, but will accept more. ++ * We know how to parse _META_ARGV_MAX args. The rest will be ignored. */ + +- if (argc < _META_ARGV_MAX) ++ if (argc < _META_ARGV_REQUIRED) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), +- "Not enough arguments passed by the kernel (%i, expected %i).", +- argc, _META_ARGV_MAX); ++ "Not enough arguments passed by the kernel (%i, expected between %i and %i).", ++ argc, _META_ARGV_REQUIRED, _META_ARGV_MAX); + +- for (int i = 0; i < _META_ARGV_MAX; i++) { ++ for (int i = 0; i < MIN(argc, _META_ARGV_MAX); i++) { + + t = argv[i]; + +diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh +index 1093cad8a9..0163131096 100755 +--- a/test/units/testsuite-74.coredump.sh ++++ b/test/units/testsuite-74.coredump.sh +@@ -218,14 +218,18 @@ rm -f /tmp/core.{output,redirected} + (! "${UNPRIV_CMD[@]}" coredumpctl dump "$CORE_TEST_BIN" >/dev/null) + + # --backtrace mode +-# Pass one of the existing journal coredump records to systemd-coredump and +-# use our PID as the source to make matching the coredump later easier +-# systemd-coredump args: PID UID GID SIGNUM TIMESTAMP CORE_SOFT_RLIMIT HOSTNAME ++# Pass one of the existing journal coredump records to systemd-coredump. ++# Use our PID as the source to be able to create a PIDFD and to make matching easier. ++# systemd-coredump args: PID UID GID SIGNUM TIMESTAMP CORE_SOFT_RLIMIT [HOSTNAME] + journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" | +- /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509994 12345 mymachine +-# Wait a bit for the coredump to get processed +-timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -eq 0 ]]; do sleep 1; done" +-coredumpctl info "$$" ++ /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509900 12345 ++journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" | ++ /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509901 12345 mymachine ++# Wait a bit for the coredumps to get processed ++timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -lt 2 ]]; do sleep 1; done" ++coredumpctl info $$ ++coredumpctl info COREDUMP_TIMESTAMP=1679509900000000 ++coredumpctl info COREDUMP_TIMESTAMP=1679509901000000 + coredumpctl info COREDUMP_HOSTNAME="mymachine" + + # This used to cause a stack overflow diff --git a/SOURCES/1258-coredump-use-d-in-kernel-core-pattern.patch b/SOURCES/1258-coredump-use-d-in-kernel-core-pattern.patch new file mode 100644 index 0000000..e50a8d2 --- /dev/null +++ b/SOURCES/1258-coredump-use-d-in-kernel-core-pattern.patch @@ -0,0 +1,158 @@ +From 58550ccfee8cdf87e623aa70318a45a5e7c19901 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 29 Apr 2025 14:47:59 +0200 +Subject: [PATCH] coredump: use %d in kernel core pattern +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The kernel provides %d which is documented as +"dump mode—same as value returned by prctl(2) PR_GET_DUMPABLE". + +We already query /proc/pid/auxv for this information, but unfortunately this +check is subject to a race, because the crashed process may be replaced by an +attacker before we read this data, for example replacing a SUID process that +was killed by a signal with another process that is not SUID, tricking us into +making the coredump of the original process readable by the attacker. + +With this patch, we effectively add one more check to the list of conditions +that need be satisfied if we are to make the coredump accessible to the user. + +Reportedy-by: Qualys Security Advisory + +In principle, %d might return a value other than 0, 1, or 2 in the future. +Thus, we accept those, but emit a notice. + +(cherry picked from commit 0c49e0049b7665bb7769a13ef346fef92e1ad4d6) + +Related: RHEL-104138 +--- + man/systemd-coredump.xml | 10 ++++++++++ + src/coredump/coredump.c | 22 +++++++++++++++++++--- + sysctl.d/50-coredump.conf.in | 2 +- + test/units/testsuite-74.coredump.sh | 5 +++++ + 4 files changed, 35 insertions(+), 4 deletions(-) + +diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml +index cb9f47745b..6cfa04f466 100644 +--- a/man/systemd-coredump.xml ++++ b/man/systemd-coredump.xml +@@ -259,6 +259,16 @@ COREDUMP_FILENAME=/var/lib/systemd/coredump/core.Web….552351.….zst + + + ++ ++ COREDUMP_DUMPABLE= ++ ++ The PR_GET_DUMPABLE field as reported by the kernel, see ++ prctl2. ++ ++ ++ ++ + + COREDUMP_OPEN_FDS= + +diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c +index 458857ffb2..cd10678c43 100644 +--- a/src/coredump/coredump.c ++++ b/src/coredump/coredump.c +@@ -97,7 +97,9 @@ enum { + _META_ARGV_REQUIRED, + /* The fields below were added to kernel/core_pattern at later points, so they might be missing. */ + META_ARGV_HOSTNAME = _META_ARGV_REQUIRED, /* %h: hostname */ ++ META_ARGV_DUMPABLE, /* %d: as set by the kernel */ + _META_ARGV_MAX, ++ + /* If new fields are added, they should be added here, to maintain compatibility + * with callers which don't know about the new fields. */ + +@@ -126,6 +128,7 @@ static const char * const meta_field_names[_META_MAX] = { + [META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=", + [META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=", + [META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=", ++ [META_ARGV_DUMPABLE] = "COREDUMP_DUMPABLE=", + [META_COMM] = "COREDUMP_COMM=", + [META_EXE] = "COREDUMP_EXE=", + [META_UNIT] = "COREDUMP_UNIT=", +@@ -138,6 +141,7 @@ typedef struct Context { + pid_t pid; + uid_t uid; + gid_t gid; ++ unsigned dumpable; + bool is_pid1; + bool is_journald; + } Context; +@@ -453,14 +457,16 @@ static int grant_user_access(int core_fd, const Context *context) { + if (r < 0) + return r; + +- /* We allow access if we got all the data and at_secure is not set and +- * the uid/gid matches euid/egid. */ ++ /* We allow access if %d/dumpable on the command line was exactly 1, we got all the data, ++ * at_secure is not set, and the uid/gid match euid/egid. */ + bool ret = ++ context->dumpable == 1 && + at_secure == 0 && + uid != UID_INVALID && euid != UID_INVALID && uid == euid && + gid != GID_INVALID && egid != GID_INVALID && gid == egid; +- log_debug("Will %s access (uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)", ++ log_debug("Will %s access (dumpable=%u uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)", + ret ? "permit" : "restrict", ++ context->dumpable, + uid, euid, gid, egid, yes_no(at_secure)); + return ret; + } +@@ -1089,6 +1095,16 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) { + return log_error_errno(r, "Failed to parse GID \"%s\": %m", context->meta[META_ARGV_GID]); + + ++ /* The value is set to contents of /proc/sys/fs/suid_dumpable, which we set to 2, ++ * if the process is marked as not dumpable, see PR_SET_DUMPABLE(2const). */ ++ if (context->meta[META_ARGV_DUMPABLE]) { ++ r = safe_atou(context->meta[META_ARGV_DUMPABLE], &context->dumpable); ++ if (r < 0) ++ return log_error_errno(r, "Failed to parse dumpable field \"%s\": %m", context->meta[META_ARGV_DUMPABLE]); ++ if (context->dumpable > 2) ++ log_notice("Got unexpected %%d/dumpable value %u.", context->dumpable); ++ } ++ + unit = context->meta[META_UNIT]; + context->is_pid1 = streq(context->meta[META_ARGV_PID], "1") || streq_ptr(unit, SPECIAL_INIT_SCOPE); + context->is_journald = streq_ptr(unit, SPECIAL_JOURNALD_SERVICE); +diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in +index 5fb551a8cf..9c10a89828 100644 +--- a/sysctl.d/50-coredump.conf.in ++++ b/sysctl.d/50-coredump.conf.in +@@ -13,7 +13,7 @@ + # the core dump. + # + # See systemd-coredump(8) and core(5). +-kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h ++kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d + + # Allow 16 coredumps to be dispatched in parallel by the kernel. + # We collect metadata from /proc/%P/, and thus need to make sure the crashed +diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh +index 0163131096..b72313672c 100755 +--- a/test/units/testsuite-74.coredump.sh ++++ b/test/units/testsuite-74.coredump.sh +@@ -225,12 +225,17 @@ journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE + /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509900 12345 + journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" | + /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509901 12345 mymachine ++journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" | ++ /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509902 12345 youmachine 1 + # Wait a bit for the coredumps to get processed + timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -lt 2 ]]; do sleep 1; done" + coredumpctl info $$ + coredumpctl info COREDUMP_TIMESTAMP=1679509900000000 + coredumpctl info COREDUMP_TIMESTAMP=1679509901000000 + coredumpctl info COREDUMP_HOSTNAME="mymachine" ++coredumpctl info COREDUMP_TIMESTAMP=1679509902000000 ++coredumpctl info COREDUMP_HOSTNAME="youmachine" ++coredumpctl info COREDUMP_DUMPABLE="1" + + # This used to cause a stack overflow + systemd-run -t --property CoredumpFilter=all ls /tmp diff --git a/SOURCES/1259-pidref-add-structure-that-can-reference-a-pid-via-bo.patch b/SOURCES/1259-pidref-add-structure-that-can-reference-a-pid-via-bo.patch new file mode 100644 index 0000000..1356990 --- /dev/null +++ b/SOURCES/1259-pidref-add-structure-that-can-reference-a-pid-via-bo.patch @@ -0,0 +1,230 @@ +From c762a9a8764f8c6ce6640579ae8cf04f80360d16 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Sat, 9 Sep 2023 09:29:27 +0200 +Subject: [PATCH] pidref: add structure that can reference a pid via both pidfd + and pid_t + +Let's start with the conversion of PID 1 to pidfds. Let's add a simple +structure with just two fields that can be used to maintain a reference +to arbitrary processes via both pid_t and pidfd. + +This is an embeddable struct, to keep it in line with where we +previously used a pid_t directly to track a process. + +Of course, since this might contain an fd on systems where we have pidfd +this structure has a proper lifecycle. + +(Note that this is quite different from sd_event_add_child() event +source objects as that one is only for child processes and collects +process results, while this infra is much simpler and more generic and +can be used to reference any process, anywhere in the tree.) + +(cherry picked from commit 3bda3f17fa84557eeb28fa7c330cbd3a3f876d47) + +Related: RHEL-104138 +--- + src/basic/meson.build | 1 + + src/basic/pidref.c | 145 ++++++++++++++++++++++++++++++++++++++++++ + src/basic/pidref.h | 29 +++++++++ + 3 files changed, 175 insertions(+) + create mode 100644 src/basic/pidref.c + create mode 100644 src/basic/pidref.h + +diff --git a/src/basic/meson.build b/src/basic/meson.build +index 11053a5ecd..b8b4213c70 100644 +--- a/src/basic/meson.build ++++ b/src/basic/meson.build +@@ -182,6 +182,7 @@ basic_sources = files( + 'path-util.h', + 'percent-util.c', + 'percent-util.h', ++ 'pidref.c', + 'prioq.c', + 'prioq.h', + 'proc-cmdline.c', +diff --git a/src/basic/pidref.c b/src/basic/pidref.c +new file mode 100644 +index 0000000000..f41460938c +--- /dev/null ++++ b/src/basic/pidref.c +@@ -0,0 +1,145 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++ ++#include "errno-util.h" ++#include "fd-util.h" ++#include "missing_syscall.h" ++#include "parse-util.h" ++#include "pidref.h" ++#include "process-util.h" ++ ++int pidref_set_pid(PidRef *pidref, pid_t pid) { ++ int fd; ++ ++ assert(pidref); ++ ++ if (pid < 0) ++ return -ESRCH; ++ if (pid == 0) ++ pid = getpid_cached(); ++ ++ fd = pidfd_open(pid, 0); ++ if (fd < 0) { ++ /* Graceful fallback in case the kernel doesn't support pidfds or is out of fds */ ++ if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno) && !ERRNO_IS_RESOURCE(errno)) ++ return -errno; ++ ++ fd = -EBADF; ++ } ++ ++ *pidref = (PidRef) { ++ .fd = fd, ++ .pid = pid, ++ }; ++ ++ return 0; ++} ++ ++int pidref_set_pidstr(PidRef *pidref, const char *pid) { ++ pid_t nr; ++ int r; ++ ++ assert(pidref); ++ ++ r = parse_pid(pid, &nr); ++ if (r < 0) ++ return r; ++ ++ return pidref_set_pid(pidref, nr); ++} ++ ++int pidref_set_pidfd(PidRef *pidref, int fd) { ++ int r; ++ ++ assert(pidref); ++ ++ if (fd < 0) ++ return -EBADF; ++ ++ int fd_copy = fcntl(fd, F_DUPFD_CLOEXEC, 3); ++ if (fd_copy < 0) { ++ pid_t pid; ++ ++ if (!ERRNO_IS_RESOURCE(errno)) ++ return -errno; ++ ++ /* Graceful fallback if we are out of fds */ ++ r = pidfd_get_pid(fd, &pid); ++ if (r < 0) ++ return r; ++ ++ *pidref = (PidRef) { ++ .fd = -EBADF, ++ .pid = pid, ++ }; ++ ++ return 0; ++ } ++ ++ return pidref_set_pidfd_consume(pidref, fd_copy); ++} ++ ++int pidref_set_pidfd_take(PidRef *pidref, int fd) { ++ pid_t pid; ++ int r; ++ ++ assert(pidref); ++ ++ if (fd < 0) ++ return -EBADF; ++ ++ r = pidfd_get_pid(fd, &pid); ++ if (r < 0) ++ return r; ++ ++ *pidref = (PidRef) { ++ .fd = fd, ++ .pid = pid, ++ }; ++ ++ return 0; ++} ++ ++int pidref_set_pidfd_consume(PidRef *pidref, int fd) { ++ int r; ++ ++ r = pidref_set_pidfd_take(pidref, fd); ++ if (r < 0) ++ safe_close(fd); ++ ++ return r; ++} ++ ++void pidref_done(PidRef *pidref) { ++ assert(pidref); ++ ++ *pidref = (PidRef) { ++ .fd = safe_close(pidref->fd), ++ }; ++} ++ ++int pidref_kill(PidRef *pidref, int sig) { ++ ++ if (!pidref) ++ return -ESRCH; ++ ++ if (pidref->fd >= 0) ++ return RET_NERRNO(pidfd_send_signal(pidref->fd, sig, NULL, 0)); ++ ++ if (pidref->pid > 0) ++ return RET_NERRNO(kill(pidref->pid, sig)); ++ ++ return -ESRCH; ++} ++ ++int pidref_kill_and_sigcont(PidRef *pidref, int sig) { ++ int r; ++ ++ r = pidref_kill(pidref, sig); ++ if (r < 0) ++ return r; ++ ++ if (!IN_SET(sig, SIGCONT, SIGKILL)) ++ (void) pidref_kill(pidref, SIGCONT); ++ ++ return 0; ++} +diff --git a/src/basic/pidref.h b/src/basic/pidref.h +new file mode 100644 +index 0000000000..2411e510f1 +--- /dev/null ++++ b/src/basic/pidref.h +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: LGPL-2.1-or-later */ ++#pragma once ++ ++#include "macro.h" ++ ++/* An embeddable structure carrying a reference to a process. Supposed to be used when tracking processes continously. */ ++typedef struct PidRef { ++ pid_t pid; /* always valid */ ++ int fd; /* only valid if pidfd are available in the kernel, and we manage to get an fd */ ++} PidRef; ++ ++#define PIDREF_NULL (PidRef) { .fd = -EBADF } ++ ++static inline bool pidref_is_set(const PidRef *pidref) { ++ return pidref && pidref->pid > 0; ++} ++ ++int pidref_set_pid(PidRef *pidref, pid_t pid); ++int pidref_set_pidstr(PidRef *pidref, const char *pid); ++int pidref_set_pidfd(PidRef *pidref, int fd); ++int pidref_set_pidfd_take(PidRef *pidref, int fd); /* takes ownership of the passed pidfd on success*/ ++int pidref_set_pidfd_consume(PidRef *pidref, int fd); /* takes ownership of the passed pidfd in both success and failure */ ++ ++void pidref_done(PidRef *pidref); ++ ++int pidref_kill(PidRef *pidref, int sig); ++int pidref_kill_and_sigcont(PidRef *pidref, int sig); ++ ++#define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL) diff --git a/SOURCES/1260-fd-util-introduce-parse_fd.patch b/SOURCES/1260-fd-util-introduce-parse_fd.patch new file mode 100644 index 0000000..edb8207 --- /dev/null +++ b/SOURCES/1260-fd-util-introduce-parse_fd.patch @@ -0,0 +1,54 @@ +From 9cf24f219925df6e449eb0838af6e309d84cbb0c Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Fri, 5 May 2023 08:09:14 +0200 +Subject: [PATCH] fd-util: introduce parse_fd() + +It's a simple wrapper for safe_atoi() that returns error if the parsed +fd is < 0 . + +(cherry picked from commit b8f83d7f0c35dca6ca3a23c42215d566e2815ca5) + +Related: RHEL-104138 +--- + src/basic/parse-util.c | 15 +++++++++++++++ + src/basic/parse-util.h | 1 + + 2 files changed, 16 insertions(+) + +diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c +index 3b3efb0ab8..4161211c49 100644 +--- a/src/basic/parse-util.c ++++ b/src/basic/parse-util.c +@@ -313,6 +313,21 @@ int parse_errno(const char *t) { + return e; + } + ++int parse_fd(const char *t) { ++ int r, fd; ++ ++ assert(t); ++ ++ r = safe_atoi(t, &fd); ++ if (r < 0) ++ return r; ++ ++ if (fd < 0) ++ return -ERANGE; ++ ++ return fd; ++} ++ + static const char *mangle_base(const char *s, unsigned *base) { + const char *k; + +diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h +index 8d8d52327b..5c012d702a 100644 +--- a/src/basic/parse-util.h ++++ b/src/basic/parse-util.h +@@ -20,6 +20,7 @@ int parse_mtu(int family, const char *s, uint32_t *ret); + int parse_size(const char *t, uint64_t base, uint64_t *size); + int parse_range(const char *t, unsigned *lower, unsigned *upper); + int parse_errno(const char *t); ++int parse_fd(const char *t); + + #define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30) + #define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29) diff --git a/SOURCES/1261-coredump-add-support-for-new-F-PIDFD-specifier.patch b/SOURCES/1261-coredump-add-support-for-new-F-PIDFD-specifier.patch new file mode 100644 index 0000000..b41991a --- /dev/null +++ b/SOURCES/1261-coredump-add-support-for-new-F-PIDFD-specifier.patch @@ -0,0 +1,245 @@ +From bbd5aec472b90aa55e184f58691085142b7e3aaa Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Sun, 13 Apr 2025 22:10:36 +0100 +Subject: [PATCH] coredump: add support for new %F PIDFD specifier + +A new core_pattern specifier was added, %F, to provide a PIDFD +to the usermode helper process referring to the crashed process. +This removes all possible race conditions, ensuring only the +crashed process gets inspected by systemd-coredump. + +(cherry picked from commit 868d95577ec9f862580ad365726515459be582fc) + +Resolves: RHEL-104138 +--- + man/systemd-coredump.xml | 9 ++++ + src/coredump/coredump.c | 89 ++++++++++++++++++++++++++++++++---- + sysctl.d/50-coredump.conf.in | 2 +- + 3 files changed, 89 insertions(+), 11 deletions(-) + +diff --git a/man/systemd-coredump.xml b/man/systemd-coredump.xml +index 6cfa04f466..b3d81d838a 100644 +--- a/man/systemd-coredump.xml ++++ b/man/systemd-coredump.xml +@@ -186,6 +186,15 @@ COREDUMP_FILENAME=/var/lib/systemd/coredump/core.Web….552351.….zst + + + ++ ++ COREDUMP_BY_PIDFD= ++ If the crashed process was analyzed using a PIDFD provided by the kernel (requires ++ kernel v6.16) then this field will be present and set to 1. If this field is ++ not set, then the crashed process was analyzed via a PID, which is known to be subject to race ++ conditions. ++ ++ ++ + + COREDUMP_TIMESTAMP= + The time of the crash as reported by the kernel (in µs since the epoch). +diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c +index cd10678c43..e0aac3c8d0 100644 +--- a/src/coredump/coredump.c ++++ b/src/coredump/coredump.c +@@ -39,6 +39,7 @@ + #include "mkdir-label.h" + #include "namespace-util.h" + #include "parse-util.h" ++#include "pidref.h" + #include "process-util.h" + #include "signal-util.h" + #include "socket-util.h" +@@ -98,8 +99,8 @@ enum { + /* The fields below were added to kernel/core_pattern at later points, so they might be missing. */ + META_ARGV_HOSTNAME = _META_ARGV_REQUIRED, /* %h: hostname */ + META_ARGV_DUMPABLE, /* %d: as set by the kernel */ ++ META_ARGV_PIDFD, /* %F: pidfd of the process, since v6.16 */ + _META_ARGV_MAX, +- + /* If new fields are added, they should be added here, to maintain compatibility + * with callers which don't know about the new fields. */ + +@@ -129,6 +130,7 @@ static const char * const meta_field_names[_META_MAX] = { + [META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=", + [META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=", + [META_ARGV_DUMPABLE] = "COREDUMP_DUMPABLE=", ++ [META_ARGV_PIDFD] = "COREDUMP_BY_PIDFD=", + [META_COMM] = "COREDUMP_COMM=", + [META_EXE] = "COREDUMP_EXE=", + [META_UNIT] = "COREDUMP_UNIT=", +@@ -136,6 +138,7 @@ static const char * const meta_field_names[_META_MAX] = { + }; + + typedef struct Context { ++ PidRef pidref; + const char *meta[_META_MAX]; + size_t meta_size[_META_MAX]; + pid_t pid; +@@ -146,6 +149,14 @@ typedef struct Context { + bool is_journald; + } Context; + ++#define CONTEXT_NULL \ ++ (Context) { \ ++ .pidref = PIDREF_NULL, \ ++ .uid = UID_INVALID, \ ++ .gid = GID_INVALID, \ ++ } ++ ++ + typedef enum CoredumpStorage { + COREDUMP_STORAGE_NONE, + COREDUMP_STORAGE_EXTERNAL, +@@ -171,6 +182,12 @@ static uint64_t arg_journal_size_max = JOURNAL_SIZE_MAX; + static uint64_t arg_keep_free = UINT64_MAX; + static uint64_t arg_max_use = UINT64_MAX; + ++static void context_done(Context *c) { ++ assert(c); ++ ++ pidref_done(&c->pidref); ++} ++ + static int parse_config(void) { + static const ConfigTableItem items[] = { + { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage }, +@@ -1114,7 +1131,7 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) { + + static int process_socket(int fd) { + _cleanup_close_ int input_fd = -EBADF, mntns_fd = -EBADF; +- Context context = {}; ++ _cleanup_(context_done) Context context = CONTEXT_NULL; + struct iovec_wrapper iovw = {}; + struct iovec iovec; + int iterations = 0, r; +@@ -1215,7 +1232,7 @@ static int process_socket(int fd) { + goto finish; + + /* Make sure we received at least all fields we need. */ +- for (int i = 0; i < _META_MANDATORY_MAX; i++) ++ for (int i = 0; i < _META_ARGV_REQUIRED; i++) + if (!context.meta[i]) { + r = log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "A mandatory argument (%i) has not been sent, aborting.", +@@ -1301,9 +1318,9 @@ static int gather_pid_metadata_from_argv( + Context *context, + int argc, char **argv) { + ++ _cleanup_(pidref_done) PidRef local_pidref = PIDREF_NULL; + _cleanup_free_ char *free_timestamp = NULL; +- int r, signo; +- char *t; ++ int r, signo, kernel_fd = -EBADF; + + /* We gather all metadata that were passed via argv[] into an array of iovecs that + * we'll forward to the socket unit. +@@ -1317,8 +1334,7 @@ static int gather_pid_metadata_from_argv( + argc, _META_ARGV_REQUIRED, _META_ARGV_MAX); + + for (int i = 0; i < MIN(argc, _META_ARGV_MAX); i++) { +- +- t = argv[i]; ++ const char *t = argv[i]; + + switch (i) { + +@@ -1343,6 +1359,47 @@ static int gather_pid_metadata_from_argv( + break; + } + ++ if (i == META_ARGV_PID) { ++ /* Store this so that we can check whether the core will be forwarded to a container ++ * even when the kernel doesn't provide a pidfd. Can be dropped once baseline is ++ * >= v6.16. */ ++ r = pidref_set_pidstr(&local_pidref, t); ++ if (r < 0) ++ return log_error_errno(r, "Failed to initialize pidref from pid %s: %m", t); ++ } ++ ++ if (i == META_ARGV_PIDFD) { ++ /* If the current kernel doesn't support the %F specifier (which resolves to a ++ * pidfd), but we included it in the core_pattern expression, we'll receive an empty ++ * string here. Deal with that gracefully. */ ++ if (isempty(t)) ++ continue; ++ ++ assert(!pidref_is_set(&context->pidref)); ++ assert(kernel_fd < 0); ++ ++ kernel_fd = parse_fd(t); ++ if (kernel_fd < 0) ++ return log_error_errno(kernel_fd, "Failed to parse pidfd \"%s\": %m", t); ++ ++ r = pidref_set_pidfd(&context->pidref, kernel_fd); ++ if (r < 0) ++ return log_error_errno(r, "Failed to initialize pidref from pidfd %d: %m", kernel_fd); ++ ++ /* If there are containers involved with different versions of the code they might ++ * not be using pidfds, so it would be wrong to set the metadata, skip it. */ ++ r = in_same_namespace(getpid_cached(), context->pidref.pid, NAMESPACE_PID); ++ if (r < 0) ++ log_debug_errno(r, "Failed to check pidns of crashing process, ignoring: %m"); ++ if (r <= 0) ++ continue; ++ ++ /* We don't print the fd number in the journal as it's meaningless, but we still ++ * record that the parsing was done with a kernel-provided fd as it means it's safe ++ * from races, which is valuable information to provide in the journal record. */ ++ t = "1"; ++ } ++ + r = iovw_put_string_field(iovw, meta_field_names[i], t); + if (r < 0) + return r; +@@ -1350,7 +1407,19 @@ static int gather_pid_metadata_from_argv( + + /* Cache some of the process metadata we collected so far and that we'll need to + * access soon */ +- return save_context(context, iovw); ++ r = save_context(context, iovw); ++ if (r < 0) ++ return r; ++ ++ /* If the kernel didn't give us a PIDFD, then use the one derived from the ++ * PID immediately, given we have it. */ ++ if (!pidref_is_set(&context->pidref)) ++ context->pidref = TAKE_PIDREF(local_pidref); ++ ++ /* Close the kernel-provided FD as the last thing after everything else succeeded. */ ++ kernel_fd = safe_close(kernel_fd); ++ ++ return 0; + } + + static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) { +@@ -1466,7 +1535,7 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) { + } + + static int process_kernel(int argc, char* argv[]) { +- Context context = {}; ++ _cleanup_(context_done) Context context = CONTEXT_NULL; + struct iovec_wrapper *iovw; + int r, mntns_fd = -EBADF; + +@@ -1543,7 +1612,7 @@ static int process_kernel(int argc, char* argv[]) { + } + + static int process_backtrace(int argc, char *argv[]) { +- Context context = {}; ++ _cleanup_(context_done) Context context = CONTEXT_NULL; + struct iovec_wrapper *iovw; + char *message; + int r; +diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in +index 9c10a89828..1c6230ad93 100644 +--- a/sysctl.d/50-coredump.conf.in ++++ b/sysctl.d/50-coredump.conf.in +@@ -13,7 +13,7 @@ + # the core dump. + # + # See systemd-coredump(8) and core(5). +-kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d ++kernel.core_pattern=|{{ROOTLIBEXECDIR}}/systemd-coredump %P %u %g %s %t %c %h %d %F + + # Allow 16 coredumps to be dispatched in parallel by the kernel. + # We collect metadata from /proc/%P/, and thus need to make sure the crashed diff --git a/SOURCES/1262-test-rename-TEST-53-ISSUE-16347-to-TEST-53-TIMER.patch b/SOURCES/1262-test-rename-TEST-53-ISSUE-16347-to-TEST-53-TIMER.patch new file mode 100644 index 0000000..6afb209 --- /dev/null +++ b/SOURCES/1262-test-rename-TEST-53-ISSUE-16347-to-TEST-53-TIMER.patch @@ -0,0 +1,99 @@ +From 1e97dc426766eef1590d9054952aa0d7d5882b79 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 23 Sep 2025 14:28:33 +0200 +Subject: [PATCH] test: rename TEST-53-ISSUE-16347 to TEST-53-TIMER + +And split the existing test into a separate subtest. + +(cherry picked from commit 953c347fb6f293acbd6da009646bfc071b68ddd7) + +Related: RHEL-127022 +--- + .../Makefile | 0 + .../test.sh | 0 + test/units/testsuite-53.issue-16347.sh | 27 ++++++++++++++++++ + test/units/testsuite-53.sh | 28 +++---------------- + 4 files changed, 31 insertions(+), 24 deletions(-) + rename test/{TEST-53-ISSUE-16347 => TEST-53-TIMER}/Makefile (100%) + rename test/{TEST-53-ISSUE-16347 => TEST-53-TIMER}/test.sh (100%) + create mode 100755 test/units/testsuite-53.issue-16347.sh + +diff --git a/test/TEST-53-ISSUE-16347/Makefile b/test/TEST-53-TIMER/Makefile +similarity index 100% +rename from test/TEST-53-ISSUE-16347/Makefile +rename to test/TEST-53-TIMER/Makefile +diff --git a/test/TEST-53-ISSUE-16347/test.sh b/test/TEST-53-TIMER/test.sh +similarity index 100% +rename from test/TEST-53-ISSUE-16347/test.sh +rename to test/TEST-53-TIMER/test.sh +diff --git a/test/units/testsuite-53.issue-16347.sh b/test/units/testsuite-53.issue-16347.sh +new file mode 100755 +index 0000000000..8b266145cd +--- /dev/null ++++ b/test/units/testsuite-53.issue-16347.sh +@@ -0,0 +1,27 @@ ++#!/usr/bin/env bash ++# SPDX-License-Identifier: LGPL-2.1-or-later ++set -eux ++set -o pipefail ++ ++# Reset host date to current time, 3 days in the past. ++date -s "-3 days" ++trap 'date -s "+3 days"' EXIT ++ ++# Run a timer for every 15 minutes. ++systemd-run --unit test-timer --on-calendar "*:0/15:0" true ++ ++next_elapsed=$(systemctl show test-timer.timer -p NextElapseUSecRealtime --value) ++next_elapsed=$(date -d "${next_elapsed}" +%s) ++now=$(date +%s) ++time_delta=$((next_elapsed - now)) ++ ++# Check that the timer will elapse in less than 20 minutes. ++if [[ "$time_delta" -lt 0 || "$time_delta" -gt 1200 ]]; then ++ echo 'Timer elapse outside of the expected 20 minute window.' ++ echo " next_elapsed=${next_elapsed}" ++ echo " now=${now}" ++ echo " time_delta=${time_delta}" ++ echo ++ ++ exit 1 ++fi +diff --git a/test/units/testsuite-53.sh b/test/units/testsuite-53.sh +index 84cd66129d..9c2a033aa9 100755 +--- a/test/units/testsuite-53.sh ++++ b/test/units/testsuite-53.sh +@@ -3,29 +3,9 @@ + set -eux + set -o pipefail + +-: >/failed ++# shellcheck source=test/units/test-control.sh ++. "$(dirname "$0")"/test-control.sh + +-# Reset host date to current time, 3 days in the past. +-date -s "-3 days" ++run_subtests + +-# Run a timer for every 15 minutes. +-systemd-run --unit test-timer --on-calendar "*:0/15:0" true +- +-next_elapsed=$(systemctl show test-timer.timer -p NextElapseUSecRealtime --value) +-next_elapsed=$(date -d "${next_elapsed}" +%s) +-now=$(date +%s) +-time_delta=$((next_elapsed - now)) +- +-# Check that the timer will elapse in less than 20 minutes. +-((0 < time_delta && time_delta < 1200)) || { +- echo 'Timer elapse outside of the expected 20 minute window.' +- echo " next_elapsed=${next_elapsed}" +- echo " now=${now}" +- echo " time_delta=${time_delta}" +- echo '' +-} >>/failed +- +-if test ! -s /failed ; then +- rm -f /failed +- touch /testok +-fi ++touch /testok diff --git a/SOURCES/1263-test-restarting-elapsed-timer-shouldn-t-trigger-the-.patch b/SOURCES/1263-test-restarting-elapsed-timer-shouldn-t-trigger-the-.patch new file mode 100644 index 0000000..43879f4 --- /dev/null +++ b/SOURCES/1263-test-restarting-elapsed-timer-shouldn-t-trigger-the-.patch @@ -0,0 +1,101 @@ +From 9fbd356a6453822d0472d8f1488adfc902a8d241 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 23 Sep 2025 17:42:01 +0200 +Subject: [PATCH] test: restarting elapsed timer shouldn't trigger the + corresponding service + +Provides coverage for: + - https://github.com/systemd/systemd/issues/31231 + - https://github.com/systemd/systemd/issues/35805 + +(cherry picked from commit 5730a400fd5ee82566fe03eb832121a0d4bc26b6) + +Related: RHEL-127022 +--- + test/units/testsuite-53.restart-trigger.sh | 77 ++++++++++++++++++++++ + 1 file changed, 77 insertions(+) + create mode 100755 test/units/testsuite-53.restart-trigger.sh + +diff --git a/test/units/testsuite-53.restart-trigger.sh b/test/units/testsuite-53.restart-trigger.sh +new file mode 100755 +index 0000000000..057f379ddc +--- /dev/null ++++ b/test/units/testsuite-53.restart-trigger.sh +@@ -0,0 +1,77 @@ ++#!/usr/bin/env bash ++# SPDX-License-Identifier: LGPL-2.1-or-later ++# ++# Restarting an already elapsed timer shouldn't immediately trigger the corresponding service unit. ++# ++# Provides coverage for: ++# - https://github.com/systemd/systemd/issues/31231 ++# - https://github.com/systemd/systemd/issues/35805 ++set -eux ++set -o pipefail ++ ++# shellcheck source=test/units/test-control.sh ++. "$(dirname "$0")"/util.sh ++ ++UNIT_NAME="timer-restart-$RANDOM" ++TEST_MESSAGE="Hello from timer $RANDOM" ++ ++# Setup ++cat >"/run/systemd/system/$UNIT_NAME.timer" <"/run/systemd/system/$UNIT_NAME.service" <"/run/systemd/system/$UNIT_NAME.timer.d/99-override.conf" < +Date: Tue, 23 Sep 2025 21:04:12 +0200 +Subject: [PATCH] test: check the next elapse timer timestamp after + deserialization + +When deserializing a serialized timer unit with RandomizedDelaySec= set, +systemd should use the last inactive exit timestamp instead of current +realtime to calculate the new next elapse, so the timer unit actually +runs in the given calendar window. + +Provides coverage for: + - https://github.com/systemd/systemd/issues/18678 + - https://github.com/systemd/systemd/pull/27752 + +(cherry picked from commit f4c3c107d9be4e922a080fc292ed3889c4e0f4a5) + +Related: RHEL-127022 +--- + .../testsuite-53.RandomizedDelaySec-reload.sh | 97 +++++++++++++++++++ + test/units/util.sh | 18 ++++ + 2 files changed, 115 insertions(+) + create mode 100755 test/units/testsuite-53.RandomizedDelaySec-reload.sh + +diff --git a/test/units/testsuite-53.RandomizedDelaySec-reload.sh b/test/units/testsuite-53.RandomizedDelaySec-reload.sh +new file mode 100755 +index 0000000000..08f4f469d6 +--- /dev/null ++++ b/test/units/testsuite-53.RandomizedDelaySec-reload.sh +@@ -0,0 +1,97 @@ ++#!/usr/bin/env bash ++# SPDX-License-Identifier: LGPL-2.1-or-later ++# ++# When deserializing a serialized timer unit with RandomizedDelaySec= set, systemd should use the last ++# inactive exit timestamp instead of current realtime to calculate the new next elapse, so the timer unit ++# actually runs in the given calendar window. ++# ++# Provides coverage for: ++# - https://github.com/systemd/systemd/issues/18678 ++# - https://github.com/systemd/systemd/pull/27752 ++set -eux ++set -o pipefail ++ ++# shellcheck source=test/units/test-control.sh ++. "$(dirname "$0")"/util.sh ++ ++UNIT_NAME="timer-RandomizedDelaySec-$RANDOM" ++TARGET_TS="$(date --date="tomorrow 00:10")" ++TARGET_TS_S="$(date --date="$TARGET_TS" "+%s")" ++# Maximum possible next elapse timestamp: $TARGET_TS (OnCalendar=) + 22 hours (RandomizedDelaySec=) ++MAX_NEXT_ELAPSE_REALTIME_S="$((TARGET_TS_S + 22 * 60 * 60))" ++MAX_NEXT_ELAPSE_REALTIME="$(date --date="@$MAX_NEXT_ELAPSE_REALTIME_S")" ++ ++# Let's make sure to return the date & time back to the original state once we're done with our time ++# shenigans. One way to do this would be to use hwclock, but the RTC in VMs can be unreliable or slow to ++# respond, causing unexpected test fails/timeouts. ++# ++# Instead, let's save the realtime timestamp before we start with the test together with a current monotonic ++# timestamp, after the test ends take the difference between the current monotonic timestamp and the "start" ++# one, add it to the originally saved realtime timestamp, and finally use that timestamp to set the system ++# time. This should advance the system time by the amount of time the test actually ran, and hence restore it ++# to some sane state after the time jumps performed by the test. It won't be perfect, but it should be close ++# enough for our needs. ++START_REALTIME="$(date "+%s")" ++START_MONOTONIC="$(cut -d . -f 1 /proc/uptime)" ++at_exit() { ++ : "Restore the system date to a sane state" ++ END_MONOTONIC="$(cut -d . -f 1 /proc/uptime)" ++ date --set="@$((START_REALTIME + END_MONOTONIC - START_MONOTONIC))" ++} ++trap at_exit EXIT ++ ++# Set some predictable time so we can schedule the first timer elapse in a deterministic-ish way ++date --set="23:00" ++ ++# Setup ++cat >"/run/systemd/system/$UNIT_NAME.timer" <"/run/systemd/system/$UNIT_NAME.service" < '$2'" >&2 ++ exit 1 ++ fi ++)} ++ ++assert_ge() {( ++ set +ex ++ ++ if [[ "${1:?}" -lt "${2:?}" ]]; then ++ echo "FAIL: '$1' < '$2'" >&2 ++ exit 1 ++ fi ++)} ++ + assert_in() {( + set +ex + diff --git a/SOURCES/1265-timer-don-t-run-service-immediately-after-restart-of.patch b/SOURCES/1265-timer-don-t-run-service-immediately-after-restart-of.patch new file mode 100644 index 0000000..aef5939 --- /dev/null +++ b/SOURCES/1265-timer-don-t-run-service-immediately-after-restart-of.patch @@ -0,0 +1,29 @@ +From 7dc588429e48ba6017fd75f6a266288768230025 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Tue, 9 Sep 2025 15:24:22 +0200 +Subject: [PATCH] timer: don't run service immediately after restart of a timer + +When a timer is restarted, don't reset the last_trigger field. +This prevents the timer from triggering immediately. + +Fixes: #31231 +(cherry picked from commit 3fc44a0f68412b649e16f12ff2f97a36c615457d) + +Resolves: RHEL-127022 +--- + src/core/timer.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/core/timer.c b/src/core/timer.c +index 60e8fea79f..2eadca4f1a 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -635,8 +635,6 @@ static int timer_start(Unit *u) { + if (r < 0) + return r; + +- t->last_trigger = DUAL_TIMESTAMP_NULL; +- + /* Reenable all timers that depend on unit activation time */ + LIST_FOREACH(value, v, t->values) + if (v->base == TIMER_ACTIVE) diff --git a/SOURCES/1266-test-store-and-compare-just-the-property-value.patch b/SOURCES/1266-test-store-and-compare-just-the-property-value.patch new file mode 100644 index 0000000..96fb11d --- /dev/null +++ b/SOURCES/1266-test-store-and-compare-just-the-property-value.patch @@ -0,0 +1,49 @@ +From 5f0eda80175f04929c34cdb46cd85e3f4d64b6d1 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 29 Sep 2025 16:11:27 +0200 +Subject: [PATCH] test: store and compare just the property value + +Follow-up for 5730a400fd5ee82566fe03eb832121a0d4bc26b6. + +(cherry picked from commit 0cb252d50f35256bff569fa6213784f2d45ad6a1) + +Related: RHEL-127022 +--- + test/units/testsuite-53.restart-trigger.sh | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/test/units/testsuite-53.restart-trigger.sh b/test/units/testsuite-53.restart-trigger.sh +index 057f379ddc..e5cd575d66 100755 +--- a/test/units/testsuite-53.restart-trigger.sh ++++ b/test/units/testsuite-53.restart-trigger.sh +@@ -45,15 +45,15 @@ assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" -- + + # Restarting the timer unit shouldn't trigger neither the timer nor the service, so these + # fields should remain constant through the following tests +-SERVICE_INV_ID="$(systemctl show --property=InvocationID "$UNIT_NAME.service")" +-TIMER_LAST_TRIGGER="$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")" ++SERVICE_INV_ID="$(systemctl show -P InvocationID "$UNIT_NAME.service")" ++TIMER_LAST_TRIGGER="$(systemctl show -P LastTriggerUSec "$UNIT_NAME.timer")" + + # Now restart the timer and check if the timer and the service weren't triggered again + systemctl restart "$UNIT_NAME.timer" + sleep 5 + assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1" +-assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")" +-assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")" ++assert_eq "$SERVICE_INV_ID" "$(systemctl show -P InvocationID "$UNIT_NAME.service")" ++assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show -P LastTriggerUSec "$UNIT_NAME.timer")" + + # Set the timer into the past, restart it, and again check if it wasn't triggered + TIMER_TS="$(date --date="-1 day" "+%Y-%m-%d %H:%M:%S")" +@@ -68,8 +68,8 @@ assert_in "OnCalendar=$TIMER_TS" "$(systemctl show -P TimersCalendar "$UNIT_NAME + systemctl restart "$UNIT_NAME.timer" + sleep 5 + assert_eq "$(journalctl -q -p info --since="@$JOURNAL_TS" --unit="$UNIT_NAME" --grep="$TEST_MESSAGE" | wc -l)" "1" +-assert_eq "$SERVICE_INV_ID" "$(systemctl show --property=InvocationID "$UNIT_NAME.service")" +-assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show --property=LastTriggerUSec "$UNIT_NAME.timer")" ++assert_eq "$SERVICE_INV_ID" "$(systemctl show -P InvocationID "$UNIT_NAME.service")" ++assert_eq "$TIMER_LAST_TRIGGER" "$(systemctl show -P LastTriggerUSec "$UNIT_NAME.timer")" + + # Cleanup + systemctl stop "$UNIT_NAME".{timer,service} diff --git a/SOURCES/1267-timer-rebase-the-next-elapse-timestamp-only-if-timer.patch b/SOURCES/1267-timer-rebase-the-next-elapse-timestamp-only-if-timer.patch new file mode 100644 index 0000000..8303a89 --- /dev/null +++ b/SOURCES/1267-timer-rebase-the-next-elapse-timestamp-only-if-timer.patch @@ -0,0 +1,131 @@ +From e71140d217b3a2a75a52b488da39568d6ea942bd Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Mon, 13 Oct 2025 17:36:55 +0200 +Subject: [PATCH] timer: rebase the next elapse timestamp only if timer didn't + already run +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The test added in f4c3c107d9be4e922a080fc292ed3889c4e0f4a5 uncovered a +corner case while recalculating the next elapse timestamp of a timer unit +that uses RandomizedDelaySec= during deserialization. + +If the scheduled time (without RandomizedDelaySec=) already elapsed, +systemd "rebases" the next elapse timestamp to the time when systemd +first started, to make the RandomizedDelaySec= feature work even at +boot. However, since it was done unconditionally, it always overrode the +next elapse timestamp, which could then cause the final next elapse +timestamp to fall out of the expected window. + +With a couple of additional debug logs one of the test fail looks like +this: + +[ 132.129815] TEST-53-TIMER.sh[384]: + : 'Next elapse timestamp after daemon-reload, try #328' +[ 132.129815] TEST-53-TIMER.sh[384]: + systemctl daemon-reload +[ 132.136352] systemd[1]: Reload requested from client PID 16399 ('systemctl') (unit TEST-53-TIMER.service)... +[ 132.136636] systemd[1]: Reloading... +[ 132.446160] systemd[1]: Rebasing next elapse timestamp +[ 132.446168] systemd[1]: v->next_elapse: Tue 2025-10-14 00:10:00 CEST +[ 132.446170] systemd[1]: rebased: Tue 2025-10-14 00:10:56 CEST +[ 132.446172] systemd[1]: v->next_elapse after rebase: Tue 2025-10-14 00:10:56 CEST +[ 132.447361] systemd[1]: Reloading finished in 310 ms. +[ 132.484041] TEST-53-TIMER.sh[384]: + check_elapse_timestamp +[ 132.484041] TEST-53-TIMER.sh[384]: + systemctl status timer-RandomizedDelaySec-16377.timer +[ 132.533657] TEST-53-TIMER.sh[16440]: ● timer-RandomizedDelaySec-16377.timer +[ 132.533657] TEST-53-TIMER.sh[16440]: Loaded: loaded (/run/systemd/system/timer-RandomizedDelaySec-16377.timer; static) +[ 132.533657] TEST-53-TIMER.sh[16440]: Active: active (waiting) since Mon 2025-10-13 23:00:00 CEST; 1h 13min ago +[ 132.533657] TEST-53-TIMER.sh[16440]: Invocation: 5555d4f060114a5493ff228013830d17 +[ 132.533657] TEST-53-TIMER.sh[16440]: Trigger: Tue 2025-10-14 22:10:04 CEST; 21h left +[ 132.533657] TEST-53-TIMER.sh[16440]: Triggers: ● timer-RandomizedDelaySec-16377.service +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Adding 15h 35min 1.230173s random time. +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Realtime timer elapses at Tue 2025-10-14 15:45:58 CEST. +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Adding 16h 29min 44.084409s random time. +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Realtime timer elapses at Tue 2025-10-14 16:40:41 CEST. +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Adding 21h 59min 7.955828s random time. +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Realtime timer elapses at Tue 2025-10-14 22:10:04 CEST. +[ 132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting +[ 132.535386] TEST-53-TIMER.sh[384]: + systemctl show -p InactiveExitTimestamp timer-RandomizedDelaySec-16377.timer +[ 132.537727] TEST-53-TIMER.sh[16442]: InactiveExitTimestamp=Mon 2025-10-13 23:00:00 CEST +[ 132.540317] TEST-53-TIMER.sh[16444]: ++ systemctl show -P NextElapseUSecRealtime timer-RandomizedDelaySec-16377.timer +[ 132.547745] TEST-53-TIMER.sh[384]: + NEXT_ELAPSE_REALTIME='Tue 2025-10-14 22:10:04 CEST' +[ 132.548020] TEST-53-TIMER.sh[16445]: ++ date '--date=Tue 2025-10-14 22:10:04 CEST' +%s +[ 132.550218] TEST-53-TIMER.sh[384]: + NEXT_ELAPSE_REALTIME_S=1760472604 +[ 132.550218] TEST-53-TIMER.sh[384]: + : 'Next elapse timestamp should be Tue 2025-10-14 00:10:00 CEST <= Tue 2025-10-14 22:10:04 CEST <= Tue 2025-10-14 22:10:00 CEST' +[ 132.550218] TEST-53-TIMER.sh[384]: + assert_ge 1760472604 1760393400 +[ 132.550555] TEST-53-TIMER.sh[16446]: + set +ex +[ 132.550702] TEST-53-TIMER.sh[384]: + assert_le 1760472604 1760472600 +[ 132.550832] TEST-53-TIMER.sh[16447]: + set +ex +[ 132.551091] TEST-53-TIMER.sh[16447]: FAIL: '1760472604' > '1760472600' + +Here the original next elapse timestamp was Tue 2025-10-14 00:10:00 CEST +as expected, but it was overridden by the rebased timestamp: +Tue 2025-10-14 00:10:56 CEST. And when a new randomized delay was added +to it (21h 59min 7.955828s) the final next elapse timestamp fell out of +the expected window, i.e. Tue 2025-10-14 00:10:00 (scheduled time) < +Tue 2025-10-14 22:10:04 CEST (rebased elapse timestamp + randomized +delay) < Tue 2025-10-14 22:10:00 CEST (scheduled time + maximum from +RandomizedDelaySec=, i.e. 22h). + +By limiting the timestamp rebase only the case where the unit hasn't +already run should prevent this from happening during daemon-reload. + +(cherry picked from commit bdb8e584f4509de0daebbe2357d23156160c3a90) + +Related: RHEL-127022 +--- + src/core/timer.c | 25 +++++++++++++++---------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +diff --git a/src/core/timer.c b/src/core/timer.c +index 2eadca4f1a..4b0266bc68 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -392,7 +392,8 @@ static void timer_enter_waiting(Timer *t, bool time_change) { + continue; + + if (v->base == TIMER_CALENDAR) { +- usec_t b, rebased; ++ bool rebase_after_boot_time = false; ++ usec_t b; + + /* If we know the last time this was + * triggered, schedule the job based relative +@@ -403,21 +404,25 @@ static void timer_enter_waiting(Timer *t, bool time_change) { + b = t->last_trigger.realtime; + else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp)) + b = UNIT(t)->inactive_exit_timestamp.realtime; +- else ++ else { + b = ts.realtime; ++ rebase_after_boot_time = true; ++ } + + r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse); + if (r < 0) + continue; + +- /* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled +- * time has already passed, set the time when systemd first started as the scheduled +- * time. Note that we base this on the monotonic timestamp of the boot, not the +- * realtime one, since the wallclock might have been off during boot. */ +- rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic, +- CLOCK_MONOTONIC, CLOCK_REALTIME); +- if (v->next_elapse < rebased) +- v->next_elapse = rebased; ++ if (rebase_after_boot_time) { ++ /* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled ++ * time has already passed, set the time when systemd first started as the scheduled ++ * time. Note that we base this on the monotonic timestamp of the boot, not the ++ * realtime one, since the wallclock might have been off during boot. */ ++ usec_t rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic, ++ CLOCK_MONOTONIC, CLOCK_REALTIME); ++ if (v->next_elapse < rebased) ++ v->next_elapse = rebased; ++ } + + if (!found_realtime) + t->next_elapse_realtime = v->next_elapse; diff --git a/SOURCES/1268-coredump-handle-ENOBUFS-and-EMSGSIZE-the-same-way.patch b/SOURCES/1268-coredump-handle-ENOBUFS-and-EMSGSIZE-the-same-way.patch new file mode 100644 index 0000000..54acd91 --- /dev/null +++ b/SOURCES/1268-coredump-handle-ENOBUFS-and-EMSGSIZE-the-same-way.patch @@ -0,0 +1,34 @@ +From 6ae4c19c78b0daac097b4a7d88566f95daa9e60b Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 24 Oct 2025 12:55:20 +0200 +Subject: [PATCH] coredump: handle ENOBUFS and EMSGSIZE the same way + +Depending on the runtime configuration, e.g. sysctls +net.core.wmem_default= and net.core.rmem_default and on the actual +message size, sendmsg() can fail also with ENOBUFS. E.g. alloc_skb() +failure caused by net.core.[rw]mem_default=64MiB and huge fdinfo list +from process that has 90k opened FDs. + +We should handle this case in the same way as EMSGSIZE and drop part of +the message. + +(cherry picked from commit 28e62e684b631f928f1d857b04f45f0d34441675) + +Resolves: RHEL-126114 +--- + src/coredump/coredump.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c +index e0aac3c8d0..28dabf017b 100644 +--- a/src/coredump/coredump.c ++++ b/src/coredump/coredump.c +@@ -1273,7 +1273,7 @@ static int send_iovec(const struct iovec_wrapper *iovw, int input_fd, int mntns_ + if (sendmsg(fd, &mh, MSG_NOSIGNAL) >= 0) + break; + +- if (errno == EMSGSIZE && mh.msg_iov[0].iov_len > 0) { ++ if (IN_SET(errno, EMSGSIZE, ENOBUFS) && mh.msg_iov[0].iov_len > 0) { + /* This field didn't fit? That's a pity. Given that this is + * just metadata, let's truncate the field at half, and try + * again. We append three dots, in order to show that this is diff --git a/SOURCES/1269-timer-rebase-last_trigger-timestamp-if-needed.patch b/SOURCES/1269-timer-rebase-last_trigger-timestamp-if-needed.patch new file mode 100644 index 0000000..89b6218 --- /dev/null +++ b/SOURCES/1269-timer-rebase-last_trigger-timestamp-if-needed.patch @@ -0,0 +1,143 @@ +From 6c05a35ce4d03cf25220de5e950970ef23417415 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Wed, 19 Nov 2025 14:44:13 +0100 +Subject: [PATCH] timer: rebase last_trigger timestamp if needed + +After bdb8e584f4509de0daebbe2357d23156160c3a90 we stopped rebasing the +next elapse timestamp unconditionally and the only case where we'd do +that was when both last trigger and last inactive timestamps were empty. +This covered timer units during boot just fine, since they would have +neither of those timestamps set. However, persistent timers +(Persistent=yes) store their last trigger timestamp on a persistent +storage and load it back after reboot, so the rebasing was skipped in +this case. + +To mitigate this, check the last_trigger timestamp is older than the +current machine boot - if so, that means that it came from a stamp file +of a persistent timer unit and we need to rebase it to make +RandomizedDelaySec= work properly. + +Follow-up for bdb8e584f4509de0daebbe2357d23156160c3a90. + +(cherry picked from commit 3605b3ba87833a9919bfde05952a7d9de10499a2) + +Related: RHEL-127022 +--- + src/core/timer.c | 15 +++-- + ...tsuite-53.RandomizedDelaySec-persistent.sh | 67 +++++++++++++++++++ + 2 files changed, 78 insertions(+), 4 deletions(-) + create mode 100755 test/units/testsuite-53.RandomizedDelaySec-persistent.sh + +diff --git a/src/core/timer.c b/src/core/timer.c +index 4b0266bc68..8fb79bc0cb 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -394,15 +394,23 @@ static void timer_enter_waiting(Timer *t, bool time_change) { + if (v->base == TIMER_CALENDAR) { + bool rebase_after_boot_time = false; + usec_t b; ++ usec_t boot_monotonic = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic; + + /* If we know the last time this was + * triggered, schedule the job based relative + * to that. If we don't, just start from + * the activation time. */ + +- if (dual_timestamp_is_set(&t->last_trigger)) ++ if (dual_timestamp_is_set(&t->last_trigger)) { + b = t->last_trigger.realtime; +- else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp)) ++ ++ /* Check if the last_trigger timestamp is older than the current machine ++ * boot. If so, this means the timestamp came from a stamp file of a ++ * persistent timer and we need to rebase it to make RandomizedDelaySec= ++ * work (see below). */ ++ if (t->last_trigger.monotonic < boot_monotonic) ++ rebase_after_boot_time = true; ++ } else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp)) + b = UNIT(t)->inactive_exit_timestamp.realtime; + else { + b = ts.realtime; +@@ -418,8 +426,7 @@ static void timer_enter_waiting(Timer *t, bool time_change) { + * time has already passed, set the time when systemd first started as the scheduled + * time. Note that we base this on the monotonic timestamp of the boot, not the + * realtime one, since the wallclock might have been off during boot. */ +- usec_t rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic, +- CLOCK_MONOTONIC, CLOCK_REALTIME); ++ usec_t rebased = map_clock_usec(boot_monotonic, CLOCK_MONOTONIC, CLOCK_REALTIME); + if (v->next_elapse < rebased) + v->next_elapse = rebased; + } +diff --git a/test/units/testsuite-53.RandomizedDelaySec-persistent.sh b/test/units/testsuite-53.RandomizedDelaySec-persistent.sh +new file mode 100755 +index 0000000000..af22daecc7 +--- /dev/null ++++ b/test/units/testsuite-53.RandomizedDelaySec-persistent.sh +@@ -0,0 +1,67 @@ ++#!/usr/bin/env bash ++# SPDX-License-Identifier: LGPL-2.1-or-later ++# ++# Persistent timers (i.e. timers with Persitent=yes) save their last trigger timestamp to a persistent ++# storage (a stamp file), which is loaded during subsequent boots. As mentioned in the man page, such timers ++# should be still affected by RandomizedDelaySec= during boot even if they already elapsed and would be then ++# triggered immediately. ++# ++# This behavior was, however, broken by [0], which stopped rebasing the to-be next elapse timestamps ++# unconditionally and left that only for timers that have neither last trigger nor inactive exit timestamps ++# set, since rebasing is needed only during boot. This holds for regular timers during boot, but not for ++# persistent ones, since the last trigger timestamp is loaded from a persistent storage. ++# ++# Provides coverage for: ++# - https://github.com/systemd/systemd/issues/39739 ++# ++# [0] bdb8e584f4509de0daebbe2357d23156160c3a90 ++# ++set -eux ++set -o pipefail ++ ++# shellcheck source=test/units/test-control.sh ++. "$(dirname "$0")"/util.sh ++ ++UNIT_NAME="timer-RandomizedDelaySec-persistent-$RANDOM" ++STAMP_FILE="/var/lib/systemd/timers/stamp-$UNIT_NAME.timer" ++ ++# Setup ++cat >"/run/systemd/system/$UNIT_NAME.timer" <"/run/systemd/system/$UNIT_NAME.service" <<\EOF ++[Service] ++ExecStart=echo "Service ran at $(date)" ++EOF ++ ++systemctl daemon-reload ++ ++# Create timer's state file with an old-enough timestamp (~2 days ago), so it'd definitely elapse if the next ++# elapse timestamp wouldn't get rebased ++mkdir -p "$(dirname "$STAMP_FILE")" ++touch -d "2 days ago" "$STAMP_FILE" ++stat "$STAMP_FILE" ++SAVED_LAST_TRIGGER_S="$(stat --format="%Y" "$STAMP_FILE")" ++ ++# Start the timer and verify that its last trigger timestamp didn't change ++# ++# The last trigger timestamp should get rebased before it gets used as a base for the next elapse timestamp ++# (since it pre-dates the machine boot time). This should then add a RandomizedDelaySec= to the rebased ++# timestamp and the timer unit should not get triggered immediately after starting. ++systemctl start "$UNIT_NAME.timer" ++systemctl status "$UNIT_NAME.timer" ++ ++TIMER_LAST_TRIGGER="$(systemctl show --property=LastTriggerUSec --value "$UNIT_NAME.timer")" ++TIMER_LAST_TRIGGER_S="$(date --date="$TIMER_LAST_TRIGGER" "+%s")" ++: "The timer should not be triggered immediately, hence the last trigger timestamp should not change" ++assert_eq "$SAVED_LAST_TRIGGER_S" "$TIMER_LAST_TRIGGER_S" ++ ++# Cleanup ++systemctl stop "$UNIT_NAME".{timer,service} ++systemctl clean --what=state "$UNIT_NAME.timer" ++rm -f "/run/systemd/system/$UNIT_NAME".{timer,service} ++systemctl daemon-reload diff --git a/SOURCES/1270-core-fix-array-size-in-unit_log_resources.patch b/SOURCES/1270-core-fix-array-size-in-unit_log_resources.patch new file mode 100644 index 0000000..f563377 --- /dev/null +++ b/SOURCES/1270-core-fix-array-size-in-unit_log_resources.patch @@ -0,0 +1,36 @@ +From ca32ed0b2451453eaff579d08f9e188f9c79ab0c Mon Sep 17 00:00:00 2001 +From: Florian Schmaus +Date: Thu, 9 Nov 2023 08:59:59 +0100 +Subject: [PATCH] core: fix array size in unit_log_resources() + +In 0531bded79dc ("core: include peak memory in unit_log_resources()") new log +messages where added, however the size of the according arrays to hold the +messages was not adjusted. + +Fixes: 0531bded79dc ("core: include peak memory in unit_log_resources()") +(cherry picked from commit 893028523469b3ec459388428ddc466942cdaf4d) + +Resolves: RHEL-132120 +--- + src/core/unit.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 9e349402ff..3e04b12951 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -2233,12 +2233,12 @@ static int raise_level(int log_level, bool condition_info, bool condition_notice + } + + static int unit_log_resources(Unit *u) { +- struct iovec iovec[1 + _CGROUP_IP_ACCOUNTING_METRIC_MAX + _CGROUP_IO_ACCOUNTING_METRIC_MAX + 4]; ++ struct iovec iovec[1 + 1 + _CGROUP_IP_ACCOUNTING_METRIC_MAX + _CGROUP_IO_ACCOUNTING_METRIC_MAX + 4]; + bool any_traffic = false, have_ip_accounting = false, any_io = false, have_io_accounting = false; + _cleanup_free_ char *igress = NULL, *egress = NULL, *rr = NULL, *wr = NULL; + int log_level = LOG_DEBUG; /* May be raised if resources consumed over a threshold */ + size_t n_message_parts = 0, n_iovec = 0; +- char* message_parts[1 + 2 + 2 + 1], *t; ++ char* message_parts[1 + 1 + 2 + 2 + 1], *t; + nsec_t nsec = NSEC_INFINITY; + uint64_t memory_peak = UINT64_MAX; + int r; diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index c480e69..f7ff293 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -21,7 +21,7 @@ Name: systemd Url: https://systemd.io Version: 252 -Release: 55%{?dist}.2 +Release: 55%{?dist}.7 # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -1333,6 +1333,26 @@ Patch1247: 1247-time-util-drop-unnecessary-assignment-of-timezone-na.patch Patch1248: 1248-time-util-make-parse_timestamp-use-the-RFC-822-ISO-8.patch Patch1249: 1249-time-util-fix-typo.patch Patch1250: 1250-ci-bump-the-tools-tree-to-F42.patch +Patch1251: 1251-cryptsetup-Add-optional-support-for-linking-volume-k.patch +Patch1252: 1252-cryptsetup-fix-typo.patch +Patch1253: 1253-cryptsetup-HAVE_CRYPT_SET_KEYRING_TO_LINK-is-always-.patch +Patch1254: 1254-basic-add-PIDFS-magic-31709.patch +Patch1255: 1255-time-util-make-USEC_TIMESTAMP_FORMATTABLE_MAX-for-32.patch +Patch1256: 1256-coredump-make-check-that-all-argv-meta-data-fields-a.patch +Patch1257: 1257-coredump-restore-compatibility-with-older-patterns.patch +Patch1258: 1258-coredump-use-d-in-kernel-core-pattern.patch +Patch1259: 1259-pidref-add-structure-that-can-reference-a-pid-via-bo.patch +Patch1260: 1260-fd-util-introduce-parse_fd.patch +Patch1261: 1261-coredump-add-support-for-new-F-PIDFD-specifier.patch +Patch1262: 1262-test-rename-TEST-53-ISSUE-16347-to-TEST-53-TIMER.patch +Patch1263: 1263-test-restarting-elapsed-timer-shouldn-t-trigger-the-.patch +Patch1264: 1264-test-check-the-next-elapse-timer-timestamp-after-des.patch +Patch1265: 1265-timer-don-t-run-service-immediately-after-restart-of.patch +Patch1266: 1266-test-store-and-compare-just-the-property-value.patch +Patch1267: 1267-timer-rebase-the-next-elapse-timestamp-only-if-timer.patch +Patch1268: 1268-coredump-handle-ENOBUFS-and-EMSGSIZE-the-same-way.patch +Patch1269: 1269-timer-rebase-last_trigger-timestamp-if-needed.patch +Patch1270: 1270-core-fix-array-size-in-unit_log_resources.patch # Downstream-only patches (9000–9999) @@ -2210,6 +2230,34 @@ systemd-hwdb update &>/dev/null || : %{_prefix}/lib/dracut/modules.d/70rhel-net-naming-sysattrs/* %changelog +* Mon Dec 01 2025 systemd maintenance team - 252-55.7 +- core: fix array size in unit_log_resources() (RHEL-132120) + +* Mon Nov 24 2025 systemd maintenance team - 252-55.6 +- timer: rebase last_trigger timestamp if needed (RHEL-127022) + +* Tue Nov 18 2025 systemd maintenance team - 252-55.5 +- test: rename TEST-53-ISSUE-16347 to TEST-53-TIMER (RHEL-127022) +- test: restarting elapsed timer shouldn't trigger the corresponding service (RHEL-127022) +- test: check the next elapse timer timestamp after deserialization (RHEL-127022) +- timer: don't run service immediately after restart of a timer (RHEL-127022) +- test: store and compare just the property value (RHEL-127022) +- timer: rebase the next elapse timestamp only if timer didn't already run (RHEL-127022) +- coredump: handle ENOBUFS and EMSGSIZE the same way (RHEL-126114) + +* Thu Nov 06 2025 systemd maintenance team - 252-55.4 +- cryptsetup: Add optional support for linking volume key in keyring. (RHEL-118294) +- cryptsetup: fix typo (RHEL-118294) +- cryptsetup: HAVE_CRYPT_SET_KEYRING_TO_LINK is always defined (RHEL-118294) +- basic: add PIDFS magic (#31709) (RHEL-118294) +- time-util: make USEC_TIMESTAMP_FORMATTABLE_MAX for 32bit system off by one day (RHEL-118294) +- coredump: make check that all argv[] meta data fields are passed strict (RHEL-104138) +- coredump: restore compatibility with older patterns (RHEL-104138) +- coredump: use %d in kernel core pattern (RHEL-104138) +- pidref: add structure that can reference a pid via both pidfd and pid_t (RHEL-104138) +- fd-util: introduce parse_fd() (RHEL-104138) +- coredump: add support for new %F PIDFD specifier (RHEL-104138) + * Fri Sep 12 2025 systemd maintenance team - 252-55.2 - Revert "test-time-util: disable failing tests" (RHEL-110954) - test: use get_timezones() to iterate all known timezones (RHEL-110954)