From fe8745ee78838ac261a4ae434fc73953c63366f0 Mon Sep 17 00:00:00 2001 From: Jan Macku Date: Mon, 11 Mar 2024 14:25:35 +0100 Subject: [PATCH] systemd-252-30 Resolves: RHEL-26133,RHEL-26643 --- ...he-number-of-signature-validations-i.patch | 184 ++++++++++++++++++ ...-the-maximum-nsec3-iterations-to-100.patch | 34 ++++ ...-the-PE-file-has-to-be-at-least-512-.patch | 28 +++ ...ert-to-condition-to-skip-running-in-.patch | 101 ++++++++++ ...figuration-for-regression-sniffer-GA.patch | 20 ++ systemd.spec | 14 +- 6 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 0704-resolved-limit-the-number-of-signature-validations-i.patch create mode 100644 0705-resolved-reduce-the-maximum-nsec3-iterations-to-100.patch create mode 100644 0706-efi-alignment-of-the-PE-file-has-to-be-at-least-512-.patch create mode 100644 0707-units-change-assert-to-condition-to-skip-running-in-.patch create mode 100644 0708-ci-add-configuration-for-regression-sniffer-GA.patch diff --git a/0704-resolved-limit-the-number-of-signature-validations-i.patch b/0704-resolved-limit-the-number-of-signature-validations-i.patch new file mode 100644 index 0000000..037879e --- /dev/null +++ b/0704-resolved-limit-the-number-of-signature-validations-i.patch @@ -0,0 +1,184 @@ +From bcb4e65f7ab49fd94b002ff9e1bba24237082726 Mon Sep 17 00:00:00 2001 +From: Jacek Migacz +Date: Mon, 26 Feb 2024 14:05:37 +0100 +Subject: [PATCH] resolved: limit the number of signature validations in a + transaction + +It has been demonstrated that tolerating an unbounded number of dnssec +signature validations is a bad idea. It is easy for a maliciously +crafted DNS reply to contain as many keytag collisions as desired, +causing us to iterate every dnskey and signature combination in vain. + +The solution is to impose a maximum number of validations we will +tolerate. While collisions are not hard to craft, I still expect they +are unlikely in the wild so it should be safe to pick fairly small +values. + +Here two limits are imposed: one on the maximum number of invalid +signatures encountered per rrset, and another on the total number of +validations performed per transaction. + +(cherry picked from commit 67d0ce8843d612a2245d0966197d4f528b911b66) + +Resolves: RHEL-26643 +--- + src/resolve/resolved-dns-dnssec.c | 16 ++++++++++++++-- + src/resolve/resolved-dns-dnssec.h | 9 ++++++++- + src/resolve/resolved-dns-transaction.c | 19 ++++++++++++++++--- + 3 files changed, 38 insertions(+), 6 deletions(-) + +diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c +index 426ea945ca..de2660e317 100644 +--- a/src/resolve/resolved-dns-dnssec.c ++++ b/src/resolve/resolved-dns-dnssec.c +@@ -1176,6 +1176,7 @@ int dnssec_verify_rrset_search( + DnsResourceRecord **ret_rrsig) { + + bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false; ++ unsigned nvalidations = 0; + DnsResourceRecord *rrsig; + int r; + +@@ -1221,6 +1222,14 @@ int dnssec_verify_rrset_search( + if (realtime == USEC_INFINITY) + realtime = now(CLOCK_REALTIME); + ++ /* Have we seen an unreasonable number of invalid signaures? */ ++ if (nvalidations > DNSSEC_INVALID_MAX) { ++ if (ret_rrsig) ++ *ret_rrsig = NULL; ++ *result = DNSSEC_TOO_MANY_VALIDATIONS; ++ return (int) nvalidations; ++ } ++ + /* Yay, we found a matching RRSIG with a matching + * DNSKEY, awesome. Now let's verify all entries of + * the RRSet against the RRSIG and DNSKEY +@@ -1230,6 +1239,8 @@ int dnssec_verify_rrset_search( + if (r < 0) + return r; + ++ nvalidations++; ++ + switch (one_result) { + + case DNSSEC_VALIDATED: +@@ -1240,7 +1251,7 @@ int dnssec_verify_rrset_search( + *ret_rrsig = rrsig; + + *result = one_result; +- return 0; ++ return (int) nvalidations; + + case DNSSEC_INVALID: + /* If the signature is invalid, let's try another +@@ -1287,7 +1298,7 @@ int dnssec_verify_rrset_search( + if (ret_rrsig) + *ret_rrsig = NULL; + +- return 0; ++ return (int) nvalidations; + } + + int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) { +@@ -2571,6 +2582,7 @@ static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = { + [DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary", + [DNSSEC_NSEC_MISMATCH] = "nsec-mismatch", + [DNSSEC_INCOMPATIBLE_SERVER] = "incompatible-server", ++ [DNSSEC_TOO_MANY_VALIDATIONS] = "too-many-validations", + }; + DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult); + +diff --git a/src/resolve/resolved-dns-dnssec.h b/src/resolve/resolved-dns-dnssec.h +index 954bb3ef9d..29b90130a3 100644 +--- a/src/resolve/resolved-dns-dnssec.h ++++ b/src/resolve/resolved-dns-dnssec.h +@@ -9,12 +9,13 @@ typedef enum DnssecVerdict DnssecVerdict; + #include "resolved-dns-rr.h" + + enum DnssecResult { +- /* These five are returned by dnssec_verify_rrset() */ ++ /* These six are returned by dnssec_verify_rrset() */ + DNSSEC_VALIDATED, + DNSSEC_VALIDATED_WILDCARD, /* Validated via a wildcard RRSIG, further NSEC/NSEC3 checks necessary */ + DNSSEC_INVALID, + DNSSEC_SIGNATURE_EXPIRED, + DNSSEC_UNSUPPORTED_ALGORITHM, ++ DNSSEC_TOO_MANY_VALIDATIONS, + + /* These two are added by dnssec_verify_rrset_search() */ + DNSSEC_NO_SIGNATURE, +@@ -45,6 +46,12 @@ enum DnssecVerdict { + /* The longest digest we'll ever generate, of all digest algorithms we support */ + #define DNSSEC_HASH_SIZE_MAX (MAX(20, 32)) + ++/* The most invalid signatures we will tolerate for a single rrset */ ++#define DNSSEC_INVALID_MAX 5 ++ ++/* The total number of signature validations we will tolerate for a single transaction */ ++#define DNSSEC_VALIDATION_MAX 64 ++ + int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok); + int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig); + +diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c +index 0306af84a2..ccca49d399 100644 +--- a/src/resolve/resolved-dns-transaction.c ++++ b/src/resolve/resolved-dns-transaction.c +@@ -3140,11 +3140,14 @@ static int dnssec_validate_records( + DnsTransaction *t, + Phase phase, + bool *have_nsec, ++ unsigned *nvalidations, + DnsAnswer **validated) { + + DnsResourceRecord *rr; + int r; + ++ assert(nvalidations); ++ + /* Returns negative on error, 0 if validation failed, 1 to restart validation, 2 when finished. */ + + DNS_ANSWER_FOREACH(rr, t->answer) { +@@ -3186,6 +3189,7 @@ static int dnssec_validate_records( + &rrsig); + if (r < 0) + return r; ++ *nvalidations += r; + + log_debug("Looking at %s: %s", strna(dns_resource_record_to_string(rr)), dnssec_result_to_string(result)); + +@@ -3383,7 +3387,8 @@ static int dnssec_validate_records( + DNSSEC_SIGNATURE_EXPIRED, + DNSSEC_NO_SIGNATURE)) + manager_dnssec_verdict(t->scope->manager, DNSSEC_BOGUS, rr->key); +- else /* DNSSEC_MISSING_KEY or DNSSEC_UNSUPPORTED_ALGORITHM */ ++ else /* DNSSEC_MISSING_KEY, DNSSEC_UNSUPPORTED_ALGORITHM, ++ or DNSSEC_TOO_MANY_VALIDATIONS */ + manager_dnssec_verdict(t->scope->manager, DNSSEC_INDETERMINATE, rr->key); + + /* This is a primary response to our question, and it failed validation. +@@ -3476,13 +3481,21 @@ int dns_transaction_validate_dnssec(DnsTransaction *t) { + return r; + + phase = DNSSEC_PHASE_DNSKEY; +- for (;;) { ++ for (unsigned nvalidations = 0;;) { + bool have_nsec = false; + +- r = dnssec_validate_records(t, phase, &have_nsec, &validated); ++ r = dnssec_validate_records(t, phase, &have_nsec, &nvalidations, &validated); + if (r <= 0) + return r; + ++ if (nvalidations > DNSSEC_VALIDATION_MAX) { ++ /* This reply requires an onerous number of signature validations to verify. Let's ++ * not waste our time trying, as this shouldn't happen for well-behaved domains ++ * anyway. */ ++ t->answer_dnssec_result = DNSSEC_TOO_MANY_VALIDATIONS; ++ return 0; ++ } ++ + /* Try again as long as we managed to achieve something */ + if (r == 1) + continue; diff --git a/0705-resolved-reduce-the-maximum-nsec3-iterations-to-100.patch b/0705-resolved-reduce-the-maximum-nsec3-iterations-to-100.patch new file mode 100644 index 0000000..28c6122 --- /dev/null +++ b/0705-resolved-reduce-the-maximum-nsec3-iterations-to-100.patch @@ -0,0 +1,34 @@ +From f7b027e1a0dcdd2c92a5f3b1bcd488912389dca4 Mon Sep 17 00:00:00 2001 +From: Jacek Migacz +Date: Mon, 26 Feb 2024 14:07:37 +0100 +Subject: [PATCH] resolved: reduce the maximum nsec3 iterations to 100 + +According to RFC9267, the 2500 value is not helpful, and in fact it can +be harmful to permit a large number of iterations. Combined with limits +on the number of signature validations, I expect this will mitigate the +impact of maliciously crafted domains designed to cause excessive +cryptographic work. + +(cherry picked from commit eba291124bc11f03732d1fc468db3bfac069f9cb) + +Related: RHEL-26643 +--- + src/resolve/resolved-dns-dnssec.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/resolve/resolved-dns-dnssec.c b/src/resolve/resolved-dns-dnssec.c +index de2660e317..df25b7f619 100644 +--- a/src/resolve/resolved-dns-dnssec.c ++++ b/src/resolve/resolved-dns-dnssec.c +@@ -27,8 +27,9 @@ DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(EC_KEY*, EC_KEY_free, NULL); + /* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */ + #define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE) + +-/* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value */ +-#define NSEC3_ITERATIONS_MAX 2500 ++/* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value, but ++ * RFC9276 § 3.2 says that we should reduce the acceptable iteration count */ ++#define NSEC3_ITERATIONS_MAX 100 + + /* + * The DNSSEC Chain of trust: diff --git a/0706-efi-alignment-of-the-PE-file-has-to-be-at-least-512-.patch b/0706-efi-alignment-of-the-PE-file-has-to-be-at-least-512-.patch new file mode 100644 index 0000000..f9af744 --- /dev/null +++ b/0706-efi-alignment-of-the-PE-file-has-to-be-at-least-512-.patch @@ -0,0 +1,28 @@ +From 4d3b9819a24f233f66f46a8d153f56e7d73cc809 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 29 Feb 2024 17:51:33 +0100 +Subject: [PATCH] efi: alignment of the PE file has to be at least 512 bytes + +https://learn.microsoft.com/en-us/windows/win32/debug/pe-format?redirectedfrom=MSDN#optional-header-windows-specific-fields-image-only + +Resolves: RHEL-26133 + +RHEL-only + +[msekleta: this is RHEL-only because upstream no longer uses objcopy to create PE files] +--- + src/boot/efi/meson.build | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build +index b84ceb8c9f..c4eb471451 100644 +--- a/src/boot/efi/meson.build ++++ b/src/boot/efi/meson.build +@@ -485,6 +485,7 @@ foreach tuple : [['systemd-boot@0@.@1@', systemd_boot_objects, false, 'systemd-b + '-j', '.sdata', + '-j', '.sdmagic', + '-j', '.text', ++ '--file-alignment=512', + '--section-alignment=512', + efi_format, + '@INPUT@', '@OUTPUT@'], diff --git a/0707-units-change-assert-to-condition-to-skip-running-in-.patch b/0707-units-change-assert-to-condition-to-skip-running-in-.patch new file mode 100644 index 0000000..8184318 --- /dev/null +++ b/0707-units-change-assert-to-condition-to-skip-running-in-.patch @@ -0,0 +1,101 @@ +From 1c4cb49d13264fe1e3de51d64b293b964439fee5 Mon Sep 17 00:00:00 2001 +From: Luca Boccassi +Date: Wed, 8 Feb 2023 23:06:27 +0000 +Subject: [PATCH] units: change assert to condition to skip running in + initrd/os + +These units are also present in the initrd, so instead of an assert, +just use a condition so they are skipped where they need to be skipped. + +Fixes https://github.com/systemd/systemd/issues/26358 + +(cherry picked from commit 7ef09e2099a4f97ad40748d6b7c735b45aa4c990) + +Related: RHEL-16182 +--- + units/systemd-pcrfs-root.service.in | 2 +- + units/systemd-pcrfs@.service.in | 2 +- + units/systemd-pcrmachine.service.in | 2 +- + units/systemd-pcrphase-initrd.service.in | 2 +- + units/systemd-pcrphase-sysinit.service.in | 2 +- + units/systemd-pcrphase.service.in | 2 +- + 6 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/units/systemd-pcrfs-root.service.in b/units/systemd-pcrfs-root.service.in +index b0da413bb4..432eb9fd8c 100644 +--- a/units/systemd-pcrfs-root.service.in ++++ b/units/systemd-pcrfs-root.service.in +@@ -14,7 +14,7 @@ DefaultDependencies=no + Conflicts=shutdown.target + After=systemd-pcrmachine.service + Before=shutdown.target +-AssertPathExists=!/etc/initrd-release ++ConditionPathExists=!/etc/initrd-release + ConditionSecurity=tpm2 + ConditionPathExists=/sys/firmware/efi/efivars/StubPcrKernelImage-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f + +diff --git a/units/systemd-pcrfs@.service.in b/units/systemd-pcrfs@.service.in +index ec1ff118c3..6bbd4b72a5 100644 +--- a/units/systemd-pcrfs@.service.in ++++ b/units/systemd-pcrfs@.service.in +@@ -15,7 +15,7 @@ BindsTo=%i.mount + Conflicts=shutdown.target + After=%i.mount systemd-pcrfs-root.service + Before=shutdown.target +-AssertPathExists=!/etc/initrd-release ++ConditionPathExists=!/etc/initrd-release + ConditionSecurity=tpm2 + ConditionPathExists=/sys/firmware/efi/efivars/StubPcrKernelImage-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f + +diff --git a/units/systemd-pcrmachine.service.in b/units/systemd-pcrmachine.service.in +index e154a7eec1..f1c6ce9f26 100644 +--- a/units/systemd-pcrmachine.service.in ++++ b/units/systemd-pcrmachine.service.in +@@ -13,7 +13,7 @@ Documentation=man:systemd-pcrmachine.service(8) + DefaultDependencies=no + Conflicts=shutdown.target + Before=sysinit.target shutdown.target +-AssertPathExists=!/etc/initrd-release ++ConditionPathExists=!/etc/initrd-release + ConditionSecurity=tpm2 + ConditionPathExists=/sys/firmware/efi/efivars/StubPcrKernelImage-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f + +diff --git a/units/systemd-pcrphase-initrd.service.in b/units/systemd-pcrphase-initrd.service.in +index e437c7e1ce..6320dccf27 100644 +--- a/units/systemd-pcrphase-initrd.service.in ++++ b/units/systemd-pcrphase-initrd.service.in +@@ -13,7 +13,7 @@ Documentation=man:systemd-pcrphase-initrd.service(8) + DefaultDependencies=no + Conflicts=shutdown.target initrd-switch-root.target + Before=sysinit.target cryptsetup-pre.target cryptsetup.target shutdown.target initrd-switch-root.target systemd-sysext.service +-AssertPathExists=/etc/initrd-release ++ConditionPathExists=/etc/initrd-release + ConditionSecurity=tpm2 + ConditionPathExists=/sys/firmware/efi/efivars/StubPcrKernelImage-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f + +diff --git a/units/systemd-pcrphase-sysinit.service.in b/units/systemd-pcrphase-sysinit.service.in +index a22fbbe935..f00ad61257 100644 +--- a/units/systemd-pcrphase-sysinit.service.in ++++ b/units/systemd-pcrphase-sysinit.service.in +@@ -14,7 +14,7 @@ DefaultDependencies=no + Conflicts=shutdown.target + After=sysinit.target + Before=basic.target shutdown.target +-AssertPathExists=!/etc/initrd-release ++ConditionPathExists=!/etc/initrd-release + ConditionSecurity=tpm2 + ConditionPathExists=/sys/firmware/efi/efivars/StubPcrKernelImage-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f + +diff --git a/units/systemd-pcrphase.service.in b/units/systemd-pcrphase.service.in +index 5ba437e5b1..558f268857 100644 +--- a/units/systemd-pcrphase.service.in ++++ b/units/systemd-pcrphase.service.in +@@ -12,7 +12,7 @@ Description=TPM2 PCR Barrier (User) + Documentation=man:systemd-pcrphase.service(8) + After=remote-fs.target remote-cryptsetup.target + Before=systemd-user-sessions.service +-AssertPathExists=!/etc/initrd-release ++ConditionPathExists=!/etc/initrd-release + ConditionSecurity=tpm2 + ConditionPathExists=/sys/firmware/efi/efivars/StubPcrKernelImage-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f + diff --git a/0708-ci-add-configuration-for-regression-sniffer-GA.patch b/0708-ci-add-configuration-for-regression-sniffer-GA.patch new file mode 100644 index 0000000..6bf07ca --- /dev/null +++ b/0708-ci-add-configuration-for-regression-sniffer-GA.patch @@ -0,0 +1,20 @@ +From afb45c747f66526ec015372155c08baf74f4b988 Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Mon, 4 Mar 2024 13:37:41 +0100 +Subject: [PATCH] ci: add configuration for regression sniffer GA + +rhel-only + +Related: RHEL-1086 +--- + .github/regression-sniffer.yml | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 .github/regression-sniffer.yml + +diff --git a/.github/regression-sniffer.yml b/.github/regression-sniffer.yml +new file mode 100644 +index 0000000000..3824028e92 +--- /dev/null ++++ b/.github/regression-sniffer.yml +@@ -0,0 +1 @@ ++upstream: systemd/systemd diff --git a/systemd.spec b/systemd.spec index ac21760..8db4129 100644 --- a/systemd.spec +++ b/systemd.spec @@ -21,7 +21,7 @@ Name: systemd Url: https://systemd.io Version: 252 -Release: 29%{?dist} +Release: 30%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -786,6 +786,11 @@ Patch0700: 0700-stub-allow-loading-and-verifying-cmdline-addons.patch Patch0701: 0701-TODO-remove-fixed-item.patch Patch0702: 0702-fix-do-not-check-verify-slice-units-if-recursive-err.patch Patch0703: 0703-units-fix-typo-in-Condition-in-systemd-boot-system-t.patch +Patch0704: 0704-resolved-limit-the-number-of-signature-validations-i.patch +Patch0705: 0705-resolved-reduce-the-maximum-nsec3-iterations-to-100.patch +Patch0706: 0706-efi-alignment-of-the-PE-file-has-to-be-at-least-512-.patch +Patch0707: 0707-units-change-assert-to-condition-to-skip-running-in-.patch +Patch0708: 0708-ci-add-configuration-for-regression-sniffer-GA.patch # Downstream-only patches (9000–9999) @@ -1651,6 +1656,13 @@ systemd-hwdb update &>/dev/null || : %{_prefix}/lib/dracut/modules.d/70rhel-net-naming-sysattrs/* %changelog +* Mon Mar 11 2024 systemd maintenance team - 252-30 +- resolved: limit the number of signature validations in a transaction (RHEL-26643) +- resolved: reduce the maximum nsec3 iterations to 100 (RHEL-26643) +- efi: alignment of the PE file has to be at least 512 bytes (RHEL-26133) +- units: change assert to condition to skip running in initrd/os (RHEL-16182) +- ci: add configuration for regression sniffer GA (RHEL-1086) + * Mon Feb 26 2024 systemd maintenance team - 252-29 - units: fix typo in Condition in systemd-boot-system-token (RHEL-16952)