From a62784f9f6415a89d5cf518c906aea6ecd2516cf Mon Sep 17 00:00:00 2001 From: Yangyang Shen Date: Mon, 11 May 2020 22:10:57 +0800 Subject: [PATCH 01/38] solve the build failure caused by the upgrade of libseccomp --- ...prehensive-protection-against-libsec.patch | 145 ++++++++++++++++++ systemd.spec | 9 +- 2 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 seccomp-more-comprehensive-protection-against-libsec.patch diff --git a/seccomp-more-comprehensive-protection-against-libsec.patch b/seccomp-more-comprehensive-protection-against-libsec.patch new file mode 100644 index 0000000..8e28c85 --- /dev/null +++ b/seccomp-more-comprehensive-protection-against-libsec.patch @@ -0,0 +1,145 @@ +From 4df8fe8415eaf4abd5b93c3447452547c6ea9e5f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 14 Nov 2019 17:51:30 +0100 +Subject: [PATCH] seccomp: more comprehensive protection against libseccomp's + __NR_xyz namespace invasion + +A follow-up for 59b657296a2fe104f112b91bbf9301724067cc81, adding the +same conditioning for all cases of our __NR_xyz use. + +Fixes: #14031 +--- + src/basic/missing_syscall.h | 10 +++++----- + src/test/test-seccomp.c | 19 ++++++++++--------- + 2 files changed, 15 insertions(+), 14 deletions(-) + +diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h +index 6d9b125..1255d8b 100644 +--- a/src/basic/missing_syscall.h ++++ b/src/basic/missing_syscall.h +@@ -274,7 +274,7 @@ static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, c + + #if !HAVE_KCMP + static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) { +-# ifdef __NR_kcmp ++# if defined __NR_kcmp && __NR_kcmp > 0 + return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); + # else + errno = ENOSYS; +@@ -289,7 +289,7 @@ static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long i + + #if !HAVE_KEYCTL + static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { +-# ifdef __NR_keyctl ++# if defined __NR_keyctl && __NR_keyctl > 0 + return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); + # else + errno = ENOSYS; +@@ -300,7 +300,7 @@ static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg + } + + static inline key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) { +-# ifdef __NR_add_key ++# if defined __NR_add_key && __NR_add_key > 0 + return syscall(__NR_add_key, type, description, payload, plen, ringid); + # else + errno = ENOSYS; +@@ -311,7 +311,7 @@ static inline key_serial_t missing_add_key(const char *type, const char *descrip + } + + static inline key_serial_t missing_request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) { +-# ifdef __NR_request_key ++# if defined __NR_request_key && __NR_request_key > 0 + return syscall(__NR_request_key, type, description, callout_info, destringid); + # else + errno = ENOSYS; +@@ -496,7 +496,7 @@ enum { + static inline long missing_set_mempolicy(int mode, const unsigned long *nodemask, + unsigned long maxnode) { + long i; +-# ifdef __NR_set_mempolicy ++# if defined __NR_set_mempolicy && __NR_set_mempolicy > 0 + i = syscall(__NR_set_mempolicy, mode, nodemask, maxnode); + # else + errno = ENOSYS; +diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c +index 018c20f..c669204 100644 +--- a/src/test/test-seccomp.c ++++ b/src/test/test-seccomp.c +@@ -28,7 +28,8 @@ + #include "tmpfile-util.h" + #include "virt.h" + +-#if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) ++/* __NR_socket may be invalid due to libseccomp */ ++#if !defined(__NR_socket) || __NR_socket <= 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) + /* On these archs, socket() is implemented via the socketcall() syscall multiplexer, + * and we can't restrict it hence via seccomp. */ + # define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1 +@@ -304,14 +305,14 @@ static void test_protect_sysctl(void) { + assert_se(pid >= 0); + + if (pid == 0) { +-#if __NR__sysctl > 0 ++#if defined __NR__sysctl && __NR__sysctl > 0 + assert_se(syscall(__NR__sysctl, NULL) < 0); + assert_se(errno == EFAULT); + #endif + + assert_se(seccomp_protect_sysctl() >= 0); + +-#if __NR__sysctl > 0 ++#if defined __NR__sysctl && __NR__sysctl > 0 + assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0); + assert_se(errno == EPERM); + #endif +@@ -640,7 +641,7 @@ static void test_load_syscall_filter_set_raw(void) { + assert_se(poll(NULL, 0, 0) == 0); + + assert_se(s = hashmap_new(NULL)); +-#if SCMP_SYS(access) >= 0 ++#if defined __NR_access && __NR_access > 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(-1)) >= 0); + #else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0); +@@ -656,7 +657,7 @@ static void test_load_syscall_filter_set_raw(void) { + s = hashmap_free(s); + + assert_se(s = hashmap_new(NULL)); +-#if SCMP_SYS(access) >= 0 ++#if defined __NR_access && __NR_access > 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(EILSEQ)) >= 0); + #else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0); +@@ -672,7 +673,7 @@ static void test_load_syscall_filter_set_raw(void) { + s = hashmap_free(s); + + assert_se(s = hashmap_new(NULL)); +-#if SCMP_SYS(poll) >= 0 ++#if defined __NR_poll && __NR_poll > 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(-1)) >= 0); + #else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0); +@@ -689,7 +690,7 @@ static void test_load_syscall_filter_set_raw(void) { + s = hashmap_free(s); + + assert_se(s = hashmap_new(NULL)); +-#if SCMP_SYS(poll) >= 0 ++#if defined __NR_poll && __NR_poll > 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(EILSEQ)) >= 0); + #else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0); +@@ -767,8 +768,8 @@ static int real_open(const char *path, int flags, mode_t mode) { + * testing purposes that calls the real syscall, on architectures where SYS_open is defined. On + * other architectures, let's just fall back to the glibc call. */ + +-#ifdef SYS_open +- return (int) syscall(SYS_open, path, flags, mode); ++#if defined __NR_open && __NR_open > 0 ++ return (int) syscall(__NR_open, path, flags, mode); + #else + return open(path, flags, mode); + #endif +-- +1.8.3.1 + diff --git a/systemd.spec b/systemd.spec index 931a944..f2e9435 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 21 +Release: 22 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -85,6 +85,7 @@ Patch0036: revert-pid1-use-a-cache-for-all-unit-aliases.patch Patch0037: revert-shared-unit-file-add-a-function-to-validate-u.patch Patch0038: systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch +Patch0039: seccomp-more-comprehensive-protection-against-libsec.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1490,6 +1491,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon May 11 2020 openEuler Buildteam - 243-22 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:solve the build failure caused by the upgrade of libseccomp + * Mon Apr 27 2020 openEuler Buildteam - 243-21 - Type:enhancement - ID:NA -- Gitee From 163783835d1db1b98990acbe5e1aa375b1d80640 Mon Sep 17 00:00:00 2001 From: Yangyang Shen Date: Thu, 28 May 2020 11:27:23 +0800 Subject: [PATCH 02/38] add requirement of systemd to libs --- systemd.spec | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/systemd.spec b/systemd.spec index f2e9435..8d7c993 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 22 +Release: 23 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -114,6 +114,7 @@ BuildRequires: python3-devel, python3-lxml, firewalld-filesystem, libseccomp-de BuildRequires: gnu-efi gnu-efi-devel BuildRequires: valgrind-devel, util-linux +Requires: %{name}-libs = %{version}-%{release} Requires(post): coreutils Requires(post): sed Requires(post): acl @@ -134,22 +135,8 @@ Obsoletes: systemd-sysv < 206 Obsoletes: %{name} < 229-5 Provides: systemd-sysv = 206 Conflicts: initscripts < 9.56.1 -Conflicts: fedora-release < 23-0.12 Recommends: %{name}-help -#libs -Obsoletes: libudev < 183 -Obsoletes: systemd < 185-4 -Conflicts: systemd < 185-4 -Obsoletes: systemd-compat-libs < 230 -Obsoletes: nss-myhostname < 0.4 -Provides: nss-myhostname = 0.4 -Provides: nss-myhostname%{_isa} = 0.4 -Requires(post): coreutils -Requires(post): sed -Requires(post): grep -Requires(post): /usr/bin/getent - Provides: %{name}-pam Provides: %{name}-rpm-config Obsoletes: %{name}-pam @@ -1491,6 +1478,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Thu May 28 2020 openEuler Buildteam - 243-23 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:add requirement of systemd to libs + * Mon May 11 2020 openEuler Buildteam - 243-22 - Type:enhancement - ID:NA -- Gitee From 2400efa839dfa7b7616773faa176a90180928d7c Mon Sep 17 00:00:00 2001 From: Yangyang Shen Date: Thu, 4 Jun 2020 21:29:56 +0800 Subject: [PATCH 03/38] fix double free in macsec_receive_channel_free() and fix crash in network L2TP --- network-L2TP-fix-crash.patch | 59 +++++++++++++++++++ ...le-free-in-macsec_receive_channel_fr.patch | 45 ++++++++++++++ systemd.spec | 11 +++- 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 network-L2TP-fix-crash.patch create mode 100644 network-fix-double-free-in-macsec_receive_channel_fr.patch diff --git a/network-L2TP-fix-crash.patch b/network-L2TP-fix-crash.patch new file mode 100644 index 0000000..d3cd0e9 --- /dev/null +++ b/network-L2TP-fix-crash.patch @@ -0,0 +1,59 @@ +From a1422af564e3b1128fc7754596b4c2f8b36a4620 Mon Sep 17 00:00:00 2001 +From: Susant Sahani +Date: Sat, 30 May 2020 06:35:28 +0200 +Subject: [PATCH] network: L2TP fix crash + +``` +=220358== Invalid read of size 8 +==220358== at 0x452F05: l2tp_session_free (l2tp-tunnel.c:46) +==220358== by 0x456926: l2tp_tunnel_done (l2tp-tunnel.c:725) +==220358== by 0x43CF4D: netdev_free (netdev.c:205) +==220358== by 0x43D045: netdev_unref (netdev.c:210) +==220358== by 0x4198B7: manager_free (networkd-manager.c:1877) +==220358== by 0x40D0B3: manager_freep (networkd-manager.h:105) +==220358== by 0x40DE1C: run (networkd.c:21) +==220358== by 0x40DE75: main (networkd.c:130) +==220358== Address 0x5c035d0 is 0 bytes inside a block of size 40 free'd +==220358== at 0x483A9F5: free (vg_replace_malloc.c:538) +==220358== by 0x452F87: l2tp_session_free (l2tp-tunnel.c:57) +==220358== by 0x456857: netdev_l2tp_tunnel_verify (l2tp-tunnel.c:710) +==220358== by 0x440947: netdev_load_one (netdev.c:738) +==220358== by 0x441222: netdev_load (netdev.c:851) +==220358== by 0x419C50: manager_load_config (networkd-manager.c:1934) +==220358== by 0x40D7BE: run (networkd.c:87) +==220358== by 0x40DE75: main (networkd.c:130) +==220358== Block was alloc'd at +==220358== at 0x4839809: malloc (vg_replace_malloc.c:307) +==220358== by 0x452A76: malloc_multiply (alloc-util.h:96) +==220358== by 0x4531E6: l2tp_session_new_static (l2tp-tunnel.c:82) +==220358== by 0x455C01: config_parse_l2tp_session_id (l2tp-tunnel.c:535) +==220358== by 0x48E6D72: next_assignment (conf-parser.c:133) +==220358== by 0x48E77A3: parse_line (conf-parser.c:271) +==220358== by 0x48E7E4F: config_parse (conf-parser.c:396) +==220358== by 0x48E80E5: config_parse_many_files (conf-parser.c:453) +==220358== by 0x48E8490: config_parse_many (conf-parser.c:512) +==220358== by 0x44089C: netdev_load_one (netdev.c:729) +==220358== by 0x441222: netdev_load (netdev.c:851) +==220358== by 0x419C50: manager_load_config (networkd-manager.c:1934) + +``` +--- + src/network/netdev/l2tp-tunnel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c +index 19683c0a00..91788c3681 100644 +--- a/src/network/netdev/l2tp-tunnel.c ++++ b/src/network/netdev/l2tp-tunnel.c +@@ -44,7 +44,7 @@ static void l2tp_session_free(L2tpSession *s) { + return; + + if (s->tunnel && s->section) +- ordered_hashmap_remove(s->tunnel->sessions_by_section, s); ++ ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section); + + network_config_section_free(s->section); + +-- +2.23.0 + diff --git a/network-fix-double-free-in-macsec_receive_channel_fr.patch b/network-fix-double-free-in-macsec_receive_channel_fr.patch new file mode 100644 index 0000000..4b266b6 --- /dev/null +++ b/network-fix-double-free-in-macsec_receive_channel_fr.patch @@ -0,0 +1,45 @@ +From 0e77fc66bceb9832da82a56a4c1040fe49f8d805 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 29 May 2020 16:56:09 +0900 +Subject: [PATCH] network: fix double free in macsec_receive_channel_free() + +Fixes #15941. +Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22547 +--- + src/network/netdev/macsec.c | 2 +- + test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 | 10 ++++++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 + +diff --git a/src/network/netdev/macsec.c b/src/network/netdev/macsec.c +index 3542f9652a..8f7559e9ae 100644 +--- a/src/network/netdev/macsec.c ++++ b/src/network/netdev/macsec.c +@@ -102,7 +102,7 @@ static void macsec_receive_channel_free(ReceiveChannel *c) { + + if (c->macsec) { + if (c->sci.as_uint64 > 0) +- ordered_hashmap_remove(c->macsec->receive_channels, &c->sci.as_uint64); ++ ordered_hashmap_remove_value(c->macsec->receive_channels, &c->sci.as_uint64, c); + + if (c->section) + ordered_hashmap_remove(c->macsec->receive_channels_by_section, c->section); +diff --git a/test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 b/test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 +new file mode 100644 +index 0000000000..ca55a33ae9 +--- /dev/null ++++ b/test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 +@@ -0,0 +1,10 @@ ++[NetDev] ++Name=o ++Kind=macsec ++ ++[MACsecReceiveChannel] ++MACAddress=12.0.4 ++Port=913 ++[MACsecReceiveChannel] ++MACAddress=12.0.4 ++Port=913 +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index 8d7c993..e7bc021 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 23 +Release: 24 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -86,6 +86,8 @@ Patch0037: revert-shared-unit-file-add-a-function-to-validate-u.patch Patch0038: systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch Patch0039: seccomp-more-comprehensive-protection-against-libsec.patch +Patch0040: network-fix-double-free-in-macsec_receive_channel_fr.patch +Patch0041: network-L2TP-fix-crash.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1478,6 +1480,13 @@ fi %exclude /usr/share/man/man3/* %changelog +* Thu May 28 2020 openEuler Buildteam - 243-24 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:fix double free in macsec_receive_channel_free() and + fix crash in network L2TP + * Thu May 28 2020 openEuler Buildteam - 243-23 - Type:enhancement - ID:NA -- Gitee From 44102a945c2840480f2bce16002fdef4e7903b03 Mon Sep 17 00:00:00 2001 From: licunlong Date: Thu, 18 Jun 2020 11:04:22 +0800 Subject: [PATCH 04/38] dbus commissioning enhancement --- analyze-fix-minor-memleak.patch | 25 + ...ble-avoid-crash-when-table-is-sparse.patch | 27 + ...-priority-value-via-dbus-only-if-it-.patch | 42 ++ ...ix-re-realization-of-cgroup-siblings.patch | 59 ++ ...priority_set-when-parsing-swap-unit-.patch | 99 +++ ...initialize-swap-structure-fields-if-.patch | 35 + core-set-error-value-correctly.patch | 28 + core-swap-priority-can-be-negative.patch | 115 +++ ...pParseFlags-between-dbus-execute-and.patch | 54 ++ ...sed-logging-instead-of-generic-loggi.patch | 47 ++ ...t-systemctl-with-dependencies-switch.patch | 39 + ...k-Add-support-to-advertie-ipv6-route.patch | 711 ++++++++++++++++++ ...k-add-one-more-section-validty-check.patch | 28 + network-fix-invalid-cleanup-function.patch | 34 + ...ork-fix-memleak-in-route_prefix_free.patch | 33 + network-fix-memleak.patch | 34 + network-use-fix-invalid-free-function.patch | 26 + ...spection-bug-in-signal-parameter-nam.patch | 25 + ...validate-connection-when-Hello-fails.patch | 66 ++ sd-radv-fix-memleak.patch | 30 + ...-bus-util-Don-t-replace-exsting-strv.patch | 33 + systemctl-Add-with-dependencies-flag.patch | 330 ++++++++ ...memleak-caused-by-wrong-cleanup-func.patch | 25 + systemd.spec | 33 +- ...we-forgot-to-destroy-some-bus-errors.patch | 39 + 25 files changed, 2016 insertions(+), 1 deletion(-) create mode 100644 analyze-fix-minor-memleak.patch create mode 100644 basic-string-table-avoid-crash-when-table-is-sparse.patch create mode 100644 core-expose-swap-priority-value-via-dbus-only-if-it-.patch create mode 100644 core-fix-re-realization-of-cgroup-siblings.patch create mode 100644 core-initialize-priority_set-when-parsing-swap-unit-.patch create mode 100644 core-no-need-to-initialize-swap-structure-fields-if-.patch create mode 100644 core-set-error-value-correctly.patch create mode 100644 core-swap-priority-can-be-negative.patch create mode 100644 core-sync-SeccompParseFlags-between-dbus-execute-and.patch create mode 100644 core-use-unit-based-logging-instead-of-generic-loggi.patch create mode 100644 man-Document-systemctl-with-dependencies-switch.patch create mode 100644 network-Add-support-to-advertie-ipv6-route.patch create mode 100644 network-add-one-more-section-validty-check.patch create mode 100644 network-fix-invalid-cleanup-function.patch create mode 100644 network-fix-memleak-in-route_prefix_free.patch create mode 100644 network-fix-memleak.patch create mode 100644 network-use-fix-invalid-free-function.patch create mode 100644 sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch create mode 100644 sd-bus-invalidate-connection-when-Hello-fails.patch create mode 100644 sd-radv-fix-memleak.patch create mode 100644 shared-bus-util-Don-t-replace-exsting-strv.patch create mode 100644 systemctl-Add-with-dependencies-flag.patch create mode 100644 systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch create mode 100644 tree-wide-we-forgot-to-destroy-some-bus-errors.patch diff --git a/analyze-fix-minor-memleak.patch b/analyze-fix-minor-memleak.patch new file mode 100644 index 0000000..8e62c2c --- /dev/null +++ b/analyze-fix-minor-memleak.patch @@ -0,0 +1,25 @@ +From 81610e9609c966a33dcff15a4f3b173aa8f07e4b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 25 Oct 2019 16:05:11 +0200 +Subject: [PATCH] analyze: fix minor memleak + +--- + src/analyze/analyze.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c +index 1871a4363e..2d541fe701 100644 +--- a/src/analyze/analyze.c ++++ b/src/analyze/analyze.c +@@ -1713,7 +1713,7 @@ static void kernel_syscalls_remove(Set *s, const SyscallFilterSet *set) { + if (syscall[0] == '@') + continue; + +- (void) set_remove(s, syscall); ++ free(set_remove(s, syscall)); + } + } + +-- +2.23.0 + diff --git a/basic-string-table-avoid-crash-when-table-is-sparse.patch b/basic-string-table-avoid-crash-when-table-is-sparse.patch new file mode 100644 index 0000000..a41e066 --- /dev/null +++ b/basic-string-table-avoid-crash-when-table-is-sparse.patch @@ -0,0 +1,27 @@ +From aa73f181e92ce991cff4e6890822764698befc90 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 27 Feb 2020 21:28:54 +0100 +Subject: [PATCH] basic/string-table: avoid crash when table is sparse + +Generated _from_string() would crash when invoked on a table with some +holes. +--- + src/basic/string-table.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/basic/string-table.h b/src/basic/string-table.h +index 2d3cf81435..96924778f5 100644 +--- a/src/basic/string-table.h ++++ b/src/basic/string-table.h +@@ -44,7 +44,7 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k + char *s; \ + if (i < 0 || i > max) \ + return -ERANGE; \ +- if (i < (type) ELEMENTSOF(name##_table)) { \ ++ if (i < (type) ELEMENTSOF(name##_table) && name##_table[i]) { \ + s = strdup(name##_table[i]); \ + if (!s) \ + return -ENOMEM; \ +-- +2.23.0 + diff --git a/core-expose-swap-priority-value-via-dbus-only-if-it-.patch b/core-expose-swap-priority-value-via-dbus-only-if-it-.patch new file mode 100644 index 0000000..4baab93 --- /dev/null +++ b/core-expose-swap-priority-value-via-dbus-only-if-it-.patch @@ -0,0 +1,42 @@ +From 6d9e0ca400133aeffa4a53c707db43b3e6c98c7b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:01:14 +0100 +Subject: [PATCH] core: expose swap priority value via dbus only if it is set + +--- + src/core/dbus-swap.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c +index 353fa20132..57c8c42091 100644 +--- a/src/core/dbus-swap.c ++++ b/src/core/dbus-swap.c +@@ -12,16 +12,23 @@ + #include "unit.h" + + static int swap_get_priority(Swap *s) { +- if (s->from_proc_swaps) ++ assert(s); ++ ++ if (s->from_proc_swaps && s->parameters_proc_swaps.priority_set) + return s->parameters_proc_swaps.priority; +- if (s->from_fragment) ++ ++ if (s->from_fragment && s->parameters_fragment.priority_set) + return s->parameters_fragment.priority; ++ + return -1; + } + + static const char *swap_get_options(Swap *s) { ++ assert(s); ++ + if (s->from_fragment) + return s->parameters_fragment.options; ++ + return NULL; + } + +-- +2.23.0 + diff --git a/core-fix-re-realization-of-cgroup-siblings.patch b/core-fix-re-realization-of-cgroup-siblings.patch new file mode 100644 index 0000000..8e5af6f --- /dev/null +++ b/core-fix-re-realization-of-cgroup-siblings.patch @@ -0,0 +1,59 @@ +From 65f6b6bdcb500c576674b5838e4cc4c35e18bfde Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:30:31 +0100 +Subject: [PATCH] core: fix re-realization of cgroup siblings + +This is a fix-up for eef85c4a3f8054d29383a176f6cebd1ef3a15b9a which +broke this. + +Tracked down by @w-simon + +Fixes: #14453 +--- + src/core/cgroup.c | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index abcd057d6a..af2efd46fa 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -2334,29 +2334,25 @@ unsigned manager_dispatch_cgroup_realize_queue(Manager *m) { + static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) { + Unit *slice; + +- /* This adds the siblings of the specified unit and the +- * siblings of all parent units to the cgroup queue. (But +- * neither the specified unit itself nor the parents.) */ ++ /* This adds the siblings of the specified unit and the siblings of all parent units to the cgroup ++ * queue. (But neither the specified unit itself nor the parents.) */ + + while ((slice = UNIT_DEREF(u->slice))) { + Iterator i; + Unit *m; + void *v; + +- HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE], i) { +- /* Skip units that have a dependency on the slice +- * but aren't actually in it. */ ++ HASHMAP_FOREACH_KEY(v, m, slice->dependencies[UNIT_BEFORE], i) { ++ /* Skip units that have a dependency on the slice but aren't actually in it. */ + if (UNIT_DEREF(m->slice) != slice) + continue; + +- /* No point in doing cgroup application for units +- * without active processes. */ ++ /* No point in doing cgroup application for units without active processes. */ + if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m))) + continue; + +- /* If the unit doesn't need any new controllers +- * and has current ones realized, it doesn't need +- * any changes. */ ++ /* If the unit doesn't need any new controllers and has current ones realized, it ++ * doesn't need any changes. */ + if (unit_has_mask_realized(m, + unit_get_target_mask(m), + unit_get_enable_mask(m))) +-- +2.23.0 + diff --git a/core-initialize-priority_set-when-parsing-swap-unit-.patch b/core-initialize-priority_set-when-parsing-swap-unit-.patch new file mode 100644 index 0000000..134470a --- /dev/null +++ b/core-initialize-priority_set-when-parsing-swap-unit-.patch @@ -0,0 +1,99 @@ +From eb34a981d67165ec346c69aba53168facc556b64 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:02:56 +0100 +Subject: [PATCH] core: initialize priority_set when parsing swap unit files + +Fixes: #14524 +--- + src/core/load-fragment-gperf.gperf.m4 | 2 +- + src/core/load-fragment.c | 48 +++++++++++++++++++++++++++ + src/core/load-fragment.h | 1 + + 3 files changed, 50 insertions(+), 1 deletion(-) + +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index de08f7d067..c1f8ac7bb2 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -435,7 +435,7 @@ Automount.DirectoryMode, config_parse_mode, 0, + Automount.TimeoutIdleSec, config_parse_sec_fix_0, 0, offsetof(Automount, timeout_idle_usec) + m4_dnl + Swap.What, config_parse_unit_path_printf, 0, offsetof(Swap, parameters_fragment.what) +-Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority) ++Swap.Priority, config_parse_swap_priority, 0, 0 + Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options) + Swap.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Swap, timeout_usec) + EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 1679e047dd..8f9a2f64db 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -5129,6 +5129,54 @@ int config_parse_crash_chvt( + return 0; + } + ++int config_parse_swap_priority( ++ const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ ++ Swap *s = userdata; ++ int r, priority; ++ ++ assert(s); ++ assert(filename); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ ++ if (isempty(rvalue)) { ++ s->parameters_fragment.priority = -1; ++ s->parameters_fragment.priority_set = false; ++ return 0; ++ } ++ ++ r = safe_atoi(rvalue, &priority); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap pririty '%s', ignoring.", rvalue); ++ return 0; ++ } ++ ++ if (priority < -1) { ++ log_syntax(unit, LOG_ERR, filename, line, 0, "Sorry, swap priorities smaller than -1 may only be assigned by the kernel itself, ignoring: %s", rvalue); ++ return 0; ++ } ++ ++ if (priority > 32767) { ++ log_syntax(unit, LOG_ERR, filename, line, 0, "Swap priority out of range, ignoring: %s", rvalue); ++ return 0; ++ } ++ ++ s->parameters_fragment.priority = priority; ++ s->parameters_fragment.priority_set = true; ++ return 0; ++} ++ + int config_parse_timeout_abort( + const char* unit, + const char *filename, +diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h +index b81887d510..28613ef5b3 100644 +--- a/src/core/load-fragment.h ++++ b/src/core/load-fragment.h +@@ -121,6 +121,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_status_unit_format); + CONFIG_PARSER_PROTOTYPE(config_parse_output_restricted); + CONFIG_PARSER_PROTOTYPE(config_parse_crash_chvt); + CONFIG_PARSER_PROTOTYPE(config_parse_timeout_abort); ++CONFIG_PARSER_PROTOTYPE(config_parse_swap_priority); + + /* gperf prototypes */ + const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length); +-- +2.23.0 + diff --git a/core-no-need-to-initialize-swap-structure-fields-if-.patch b/core-no-need-to-initialize-swap-structure-fields-if-.patch new file mode 100644 index 0000000..cdfab1a --- /dev/null +++ b/core-no-need-to-initialize-swap-structure-fields-if-.patch @@ -0,0 +1,35 @@ +From 6afc31615e63b7db941684be84da82a06373a778 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:01:46 +0100 +Subject: [PATCH] core: no need to initialize swap structure fields if all + zeroes anyway + +--- + src/core/swap.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index 03f443daec..6caf20ea66 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -63,7 +63,6 @@ static void swap_unset_proc_swaps(Swap *s) { + return; + + s->parameters_proc_swaps.what = mfree(s->parameters_proc_swaps.what); +- + s->from_proc_swaps = false; + } + +@@ -117,9 +116,6 @@ static void swap_init(Unit *u) { + s->exec_context.std_output = u->manager->default_std_output; + s->exec_context.std_error = u->manager->default_std_error; + +- s->parameters_proc_swaps.priority = s->parameters_fragment.priority = 0; +- s->parameters_fragment.priority_set = false; +- + s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; + + u->ignore_on_isolate = true; +-- +2.23.0 + diff --git a/core-set-error-value-correctly.patch b/core-set-error-value-correctly.patch new file mode 100644 index 0000000..9a07379 --- /dev/null +++ b/core-set-error-value-correctly.patch @@ -0,0 +1,28 @@ +From 6fca66a7f125607864850ac9a4d6cc56a27594dd Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:04:25 +0100 +Subject: [PATCH] core: set error value correctly + +--- + src/core/swap.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index d4f6db6ddc..225488282e 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -777,8 +777,10 @@ static void swap_enter_activating(Swap *s) { + r = asprintf(&opts, "%s,pri=%i", s->parameters_fragment.options, s->parameters_fragment.priority); + else + r = asprintf(&opts, "pri=%i", s->parameters_fragment.priority); +- if (r < 0) ++ if (r < 0) { ++ r = -ENOMEM; + goto fail; ++ } + } + } + +-- +2.23.0 + diff --git a/core-swap-priority-can-be-negative.patch b/core-swap-priority-can-be-negative.patch new file mode 100644 index 0000000..b7f7089 --- /dev/null +++ b/core-swap-priority-can-be-negative.patch @@ -0,0 +1,115 @@ +From 7477451b691d288dad67b4c8ce9e519e9b75770d Mon Sep 17 00:00:00 2001 +From: Topi Miettinen +Date: Tue, 3 Dec 2019 20:36:37 +0200 +Subject: [PATCH] core: swap priority can be negative + +Negative priorities are useful for swap targets which should be only used as +last resort. +--- + src/core/swap.c | 10 ++++++---- + src/core/swap.h | 1 + + src/shared/fstab-util.c | 10 +++------- + src/test/test-fstab-util.c | 3 +++ + 4 files changed, 13 insertions(+), 11 deletions(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index e4b018616d..03f443daec 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -117,7 +117,8 @@ static void swap_init(Unit *u) { + s->exec_context.std_output = u->manager->default_std_output; + s->exec_context.std_error = u->manager->default_std_error; + +- s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1; ++ s->parameters_proc_swaps.priority = s->parameters_fragment.priority = 0; ++ s->parameters_fragment.priority_set = false; + + s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; + +@@ -433,6 +434,7 @@ static int swap_setup_unit( + SWAP(u)->from_proc_swaps = true; + + p->priority = priority; ++ p->priority_set = true; + + unit_add_to_dbus_queue(u); + return 0; +@@ -766,15 +768,15 @@ static void swap_enter_activating(Swap *s) { + s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE; + + if (s->from_fragment) { +- int priority = -1; ++ int priority = 0; + + r = fstab_find_pri(s->parameters_fragment.options, &priority); + if (r < 0) + log_warning_errno(r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options); +- else if (r == 1 && s->parameters_fragment.priority >= 0) ++ else if (r == 1 && s->parameters_fragment.priority_set) + log_warning("Duplicate swap priority configuration by Priority and Options fields."); + +- if (r <= 0 && s->parameters_fragment.priority >= 0) { ++ if (r <= 0 && s->parameters_fragment.priority_set) { + if (s->parameters_fragment.options) + r = asprintf(&opts, "%s,pri=%i", s->parameters_fragment.options, s->parameters_fragment.priority); + else +diff --git a/src/core/swap.h b/src/core/swap.h +index 389faf584d..cb24cec7aa 100644 +--- a/src/core/swap.h ++++ b/src/core/swap.h +@@ -33,6 +33,7 @@ typedef struct SwapParameters { + char *what; + char *options; + int priority; ++ bool priority_set; + } SwapParameters; + + struct Swap { +diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c +index f90501eb92..86a57e6b2c 100644 +--- a/src/shared/fstab-util.c ++++ b/src/shared/fstab-util.c +@@ -186,8 +186,7 @@ int fstab_extract_values(const char *opts, const char *name, char ***values) { + + int fstab_find_pri(const char *options, int *ret) { + _cleanup_free_ char *opt = NULL; +- int r; +- unsigned pri; ++ int r, pri; + + assert(ret); + +@@ -197,14 +196,11 @@ int fstab_find_pri(const char *options, int *ret) { + if (r == 0 || !opt) + return 0; + +- r = safe_atou(opt, &pri); ++ r = safe_atoi(opt, &pri); + if (r < 0) + return r; + +- if ((int) pri < 0) +- return -ERANGE; +- +- *ret = (int) pri; ++ *ret = pri; + return 1; + } + +diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c +index 4cd504e45c..c1c7ec9114 100644 +--- a/src/test/test-fstab-util.c ++++ b/src/test/test-fstab-util.c +@@ -100,6 +100,9 @@ static void test_fstab_find_pri(void) { + assert_se(fstab_find_pri("pri=11", &pri) == 1); + assert_se(pri == 11); + ++ assert_se(fstab_find_pri("pri=-2", &pri) == 1); ++ assert_se(pri == -2); ++ + assert_se(fstab_find_pri("opt,pri=12,opt", &pri) == 1); + assert_se(pri == 12); + +-- +2.23.0 + diff --git a/core-sync-SeccompParseFlags-between-dbus-execute-and.patch b/core-sync-SeccompParseFlags-between-dbus-execute-and.patch new file mode 100644 index 0000000..3b6e1b5 --- /dev/null +++ b/core-sync-SeccompParseFlags-between-dbus-execute-and.patch @@ -0,0 +1,54 @@ +From 72545ae05745f99e194eb83e3fa865f276601378 Mon Sep 17 00:00:00 2001 +From: Anita Zhang +Date: Thu, 6 Feb 2020 15:34:17 -0800 +Subject: [PATCH] core: sync SeccompParseFlags between dbus-execute and + load-fragment + +9e486265716963439fb0fd7f2a97abf109f24f75 added some new syscalls to the +filter lists. However, on systems that do not yet support the new calls, +running systemd-run with the filter set results in error: + +``` +$ sudo systemd-run -t -r -p "SystemCallFilter=~@mount" /bin/true +Failed to start transient service unit: Invalid argument +``` + +Having the same properties in a unit file will start the service +without issue. This is because the load-fragment code will parse the +syscall filters in permissive mode: +https://github.com/systemd/systemd/blob/master/src/core/load-fragment.c#L2909 +whereas the dbus-execute equivalent of the code does not. + +Since the permissive mode appears to be the right setting to support +older kernels/libseccomp, this will update the dbus-execute parsing +to also be permissive. +--- + src/core/dbus-execute.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 9ff3f157f5..d8ba3e5d92 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -1587,6 +1587,7 @@ int bus_exec_context_set_transient_property( + r = seccomp_parse_syscall_filter("@default", + -1, + c->syscall_filter, ++ SECCOMP_PARSE_PERMISSIVE | + SECCOMP_PARSE_WHITELIST | invert_flag, + u->id, + NULL, 0); +@@ -1606,7 +1607,9 @@ int bus_exec_context_set_transient_property( + r = seccomp_parse_syscall_filter(n, + e, + c->syscall_filter, +- (c->syscall_whitelist ? SECCOMP_PARSE_WHITELIST : 0) | invert_flag, ++ SECCOMP_PARSE_LOG | SECCOMP_PARSE_PERMISSIVE | ++ invert_flag | ++ (c->syscall_whitelist ? SECCOMP_PARSE_WHITELIST : 0), + u->id, + NULL, 0); + if (r < 0) +-- +2.23.0 + diff --git a/core-use-unit-based-logging-instead-of-generic-loggi.patch b/core-use-unit-based-logging-instead-of-generic-loggi.patch new file mode 100644 index 0000000..045d60b --- /dev/null +++ b/core-use-unit-based-logging-instead-of-generic-loggi.patch @@ -0,0 +1,47 @@ +From af4454cb17da6727e490522afb7d4bddf8dae7fd Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:03:57 +0100 +Subject: [PATCH] core: use unit-based logging instead of generic logging where + appropriate + +--- + src/core/swap.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index 6caf20ea66..d4f6db6ddc 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -768,9 +768,9 @@ static void swap_enter_activating(Swap *s) { + + r = fstab_find_pri(s->parameters_fragment.options, &priority); + if (r < 0) +- log_warning_errno(r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options); +- else if (r == 1 && s->parameters_fragment.priority_set) +- log_warning("Duplicate swap priority configuration by Priority and Options fields."); ++ log_unit_warning_errno(UNIT(s), r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options); ++ else if (r > 0 && s->parameters_fragment.priority_set) ++ log_unit_warning(UNIT(s), "Duplicate swap priority configuration by Priority= and Options= fields."); + + if (r <= 0 && s->parameters_fragment.priority_set) { + if (s->parameters_fragment.options) +@@ -788,7 +788,7 @@ static void swap_enter_activating(Swap *s) { + + if (s->parameters_fragment.options || opts) { + r = exec_command_append(s->control_command, "-o", +- opts ? : s->parameters_fragment.options, NULL); ++ opts ?: s->parameters_fragment.options, NULL); + if (r < 0) + goto fail; + } +@@ -804,7 +804,6 @@ static void swap_enter_activating(Swap *s) { + goto fail; + + swap_set_state(s, SWAP_ACTIVATING); +- + return; + + fail: +-- +2.23.0 + diff --git a/man-Document-systemctl-with-dependencies-switch.patch b/man-Document-systemctl-with-dependencies-switch.patch new file mode 100644 index 0000000..46d3314 --- /dev/null +++ b/man-Document-systemctl-with-dependencies-switch.patch @@ -0,0 +1,39 @@ +From a602a0b44b9eb9af0027d054dd24e405a658e375 Mon Sep 17 00:00:00 2001 +From: Kevin Kuehler +Date: Mon, 9 Dec 2019 01:40:47 -0800 +Subject: [PATCH] man: Document systemctl --with-dependencies switch + +--- + man/systemctl.xml | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/man/systemctl.xml b/man/systemctl.xml +index 3d86f7dffa..5828477e8d 100644 +--- a/man/systemctl.xml ++++ b/man/systemctl.xml +@@ -1592,6 +1592,22 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err + + + ++ ++ ++ ++ ++ When used with status, ++ cat, list-units, and ++ list-unit-files, those commands print all ++ specified units and the dependencies of those units. ++ ++ Options , ++ , ++ may be used to change what types of dependencies ++ are shown. ++ ++ ++ + + + +-- +2.23.0 + diff --git a/network-Add-support-to-advertie-ipv6-route.patch b/network-Add-support-to-advertie-ipv6-route.patch new file mode 100644 index 0000000..4c3e404 --- /dev/null +++ b/network-Add-support-to-advertie-ipv6-route.patch @@ -0,0 +1,711 @@ +From 203d4df5732b1fdcf50db498ddeb74a934b21f87 Mon Sep 17 00:00:00 2001 +From: Susant Sahani +Date: Sat, 14 Sep 2019 16:44:22 +0530 +Subject: [PATCH] network: Add support to advertie ipv6 route + +Implements https://tools.ietf.org/html/rfc4191 + +cat veth99.network +``` +[Match] +Name=veth99 + +[Network] +DHCP=no +IPv6PrefixDelegation=yes +Address=2001:db8:0:1::1/64 + +[IPv6Prefix] +Prefix=2001:db8:0:1::4/64 + +[IPv6RoutePrefix] +Route=2001:db0:fff::/48 + +``` +Wireshark + +``` +Frame 481: 142 bytes on wire (1136 bits), 142 bytes captured (1136 bits) on interface 0 +Ethernet II, Src: 1e:04:f8:b8:2f:d4 (1e:04:f8:b8:2f:d4), Dst: IPv6mcast_01 (33:33:00:00:00:01) +Internet Protocol Version 6, Src: fe80::1c04:f8ff:feb8:2fd4, Dst: ff02::1 +Internet Control Message Protocol v6 + Type: Router Advertisement (134) + Code: 0 + Checksum: 0xec77 [correct] + [Checksum Status: Good] + Cur hop limit: 0 + Flags: 0x00, Prf (Default Router Preference): Medium + Router lifetime (s): 0 + Reachable time (ms): 0 + Retrans timer (ms): 0 + ICMPv6 Option (Source link-layer address : 1e:04:f8:b8:2f:d4) + Type: Source link-layer address (1) + Length: 1 (8 bytes) + Link-layer address: 1e:04:f8:b8:2f:d4 (1e:04:f8:b8:2f:d4) + ICMPv6 Option (MTU : 1500) + Type: MTU (5) + Length: 1 (8 bytes) + Reserved + MTU: 1500 + ICMPv6 Option (Prefix information : 2001:db8:0:1::4/64) + Type: Prefix information (3) + Length: 4 (32 bytes) + Prefix Length: 64 + Flag: 0xc0, On-link flag(L), Autonomous address-configuration flag(A) + Valid Lifetime: 2592000 + Preferred Lifetime: 604800 + Reserved + Prefix: 2001:db8:0:1::4 + ICMPv6 Option (Route Information : Medium 2001:db0:fff::/48) + Type: Route Information (24) + Length: 3 (24 bytes) + Prefix Length: 48 + Flag: 0x00, Route Preference: Medium + ...0 0... = Route Preference: Medium (0) + 000. .000 = Reserved: 0 + Route Lifetime: 604800 + Prefix: 2001:db0:fff:: +``` +--- + man/systemd.network.xml | 33 ++- + src/libsystemd-network/radv-internal.h | 26 +++ + src/libsystemd-network/sd-radv.c | 130 +++++++++++- + src/network/networkd-network-gperf.gperf | 2 + + src/network/networkd-network.c | 1 + + src/network/networkd-network.h | 3 + + src/network/networkd-radv.c | 195 +++++++++++++++++- + src/network/networkd-radv.h | 9 + + src/systemd/sd-radv.h | 10 + + .../fuzz-network-parser/directives.network | 3 + + 10 files changed, 400 insertions(+), 12 deletions(-) + +diff --git a/man/systemd.network.xml b/man/systemd.network.xml +index 155c0868b2..8ecc39ce5e 100644 +--- a/man/systemd.network.xml ++++ b/man/systemd.network.xml +@@ -1886,7 +1886,7 @@ + + + +- ++ + [IPv6Prefix] Section Options + One or more [IPv6Prefix] sections contain the IPv6 + prefixes that are announced via Router Advertisements. See +@@ -1931,6 +1931,37 @@ + + + ++ ++ [IPv6RoutePrefix] Section Options ++ One or more [IPv6RoutePrefix] sections contain the IPv6 ++ prefix routes that are announced via Router Advertisements. See ++ RFC 4191 ++ for further details. ++ ++ ++ ++ ++ Route= ++ ++ The IPv6 route that is to be distributed to hosts. ++ Similarly to configuring static IPv6 routes, the setting is ++ configured as an IPv6 prefix routes and its prefix route length, ++ separated by a/ character. Use multiple ++ [IPv6PrefixRoutes] sections to configure multiple IPv6 ++ prefix routes. ++ ++ ++ ++ LifetimeSec= ++ ++ Lifetime for the route prefix measured in ++ seconds. LifetimeSec= defaults to 604800 seconds (one week). ++ ++ ++ ++ ++ ++ + + [Bridge] Section Options + The [Bridge] section accepts the +diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h +index 7b09c7a66c..fb6617bedd 100644 +--- a/src/libsystemd-network/radv-internal.h ++++ b/src/libsystemd-network/radv-internal.h +@@ -19,6 +19,7 @@ assert_cc(SD_RADV_DEFAULT_MIN_TIMEOUT_USEC <= SD_RADV_DEFAULT_MAX_TIMEOUT_USEC); + #define SD_RADV_MIN_DELAY_BETWEEN_RAS 3 + #define SD_RADV_MAX_RA_DELAY_TIME_USEC (500*USEC_PER_MSEC) + ++#define SD_RADV_OPT_ROUTE_INFORMATION 24 + #define SD_RADV_OPT_RDNSS 25 + #define SD_RADV_OPT_DNSSL 31 + +@@ -58,6 +59,9 @@ struct sd_radv { + unsigned n_prefixes; + LIST_HEAD(sd_radv_prefix, prefixes); + ++ unsigned n_route_prefixes; ++ LIST_HEAD(sd_radv_route_prefix, route_prefixes); ++ + size_t n_rdnss; + struct sd_radv_opt_dns *rdnss; + struct sd_radv_opt_dns *dnssl; +@@ -98,6 +102,28 @@ struct sd_radv_prefix { + usec_t preferred_until; + }; + ++#define radv_route_prefix_opt__contents { \ ++ uint8_t type; \ ++ uint8_t length; \ ++ uint8_t prefixlen; \ ++ uint8_t flags_reserved; \ ++ be32_t lifetime; \ ++ struct in6_addr in6_addr; \ ++} ++ ++struct radv_route_prefix_opt radv_route_prefix_opt__contents; ++ ++struct radv_route_prefix_opt__packed radv_route_prefix_opt__contents _packed_; ++assert_cc(sizeof(struct radv_route_prefix_opt) == sizeof(struct radv_route_prefix_opt__packed)); ++ ++struct sd_radv_route_prefix { ++ unsigned n_ref; ++ ++ struct radv_route_prefix_opt opt; ++ ++ LIST_FIELDS(struct sd_radv_route_prefix, prefix); ++}; ++ + #define log_radv_full(level, error, fmt, ...) log_internal(level, error, PROJECT_FILE, __LINE__, __func__, "RADV: " fmt, ##__VA_ARGS__) + #define log_radv_errno(error, fmt, ...) log_radv_full(LOG_DEBUG, error, fmt, ##__VA_ARGS__) + #define log_radv(fmt, ...) log_radv_errno(0, fmt, ##__VA_ARGS__) +diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c +index 185b55e1c5..d531f52326 100644 +--- a/src/libsystemd-network/sd-radv.c ++++ b/src/libsystemd-network/sd-radv.c +@@ -116,6 +116,7 @@ static sd_radv *radv_free(sd_radv *ra) { + DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv, sd_radv, radv_free); + + static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_lifetime) { ++ sd_radv_route_prefix *rt; + sd_radv_prefix *p; + struct sockaddr_in6 dst_addr = { + .sin6_family = AF_INET6, +@@ -136,9 +137,9 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_li + .nd_opt_mtu_type = ND_OPT_MTU, + .nd_opt_mtu_len = 1, + }; +- /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, RDNSS ++ /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, N routes, RDNSS + and DNSSL */ +- struct iovec iov[5 + ra->n_prefixes]; ++ struct iovec iov[5 + ra->n_prefixes + ra->n_route_prefixes]; + struct msghdr msg = { + .msg_name = &dst_addr, + .msg_namelen = sizeof(dst_addr), +@@ -190,6 +191,9 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_li + iov[msg.msg_iovlen++] = IOVEC_MAKE(&p->opt, sizeof(p->opt)); + } + ++ LIST_FOREACH(prefix, rt, ra->route_prefixes) ++ iov[msg.msg_iovlen++] = IOVEC_MAKE(&rt->opt, sizeof(rt->opt)); ++ + if (ra->rdnss) + iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->rdnss, ra->rdnss->length * 8); + +@@ -606,6 +610,77 @@ _public_ sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, + return cur; + } + ++_public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int dynamic) { ++ char time_string_valid[FORMAT_TIMESPAN_MAX]; ++ usec_t time_now, valid, valid_until; ++ _cleanup_free_ char *pretty = NULL; ++ sd_radv_route_prefix *cur; ++ int r; ++ ++ assert_return(ra, -EINVAL); ++ ++ if (!p) ++ return -EINVAL; ++ ++ (void) in_addr_to_string(AF_INET6, ++ (union in_addr_union*) &p->opt.in6_addr, ++ &pretty); ++ ++ LIST_FOREACH(prefix, cur, ra->route_prefixes) { ++ _cleanup_free_ char *addr = NULL; ++ ++ r = in_addr_prefix_intersect(AF_INET6, ++ (union in_addr_union*) &cur->opt.in6_addr, ++ cur->opt.prefixlen, ++ (union in_addr_union*) &p->opt.in6_addr, ++ p->opt.prefixlen); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ continue; ++ ++ if (dynamic && cur->opt.prefixlen == p->opt.prefixlen) ++ goto update; ++ ++ (void) in_addr_to_string(AF_INET6, ++ (union in_addr_union*) &cur->opt.in6_addr, ++ &addr); ++ log_radv("IPv6 route prefix %s/%u already configured, ignoring %s/%u", ++ strempty(addr), cur->opt.prefixlen, ++ strempty(pretty), p->opt.prefixlen); ++ ++ return -EEXIST; ++ } ++ ++ p = sd_radv_route_prefix_ref(p); ++ ++ LIST_APPEND(prefix, ra->route_prefixes, p); ++ ra->n_route_prefixes++; ++ ++ cur = p; ++ if (!dynamic) { ++ log_radv("Added prefix %s/%u", strempty(pretty), p->opt.prefixlen); ++ return 0; ++ } ++ ++ update: ++ r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now); ++ if (r < 0) ++ return r; ++ ++ valid = be32toh(p->opt.lifetime) * USEC_PER_SEC; ++ valid_until = usec_add(valid, time_now); ++ if (valid_until == USEC_INFINITY) ++ return -EOVERFLOW; ++ ++ log_radv("%s route prefix %s/%u valid %s", ++ cur? "Updated": "Added", ++ strempty(pretty), p->opt.prefixlen, ++ format_timespan(time_string_valid, FORMAT_TIMESPAN_MAX, valid, USEC_PER_SEC)); ++ ++ return 0; ++} ++ + _public_ int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime, + const struct in6_addr *dns, size_t n_dns) { + _cleanup_free_ struct sd_radv_opt_dns *opt_rdnss = NULL; +@@ -770,3 +845,54 @@ _public_ int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p, + + return 0; + } ++ ++_public_ int sd_radv_route_prefix_new(sd_radv_route_prefix **ret) { ++ sd_radv_route_prefix *p; ++ ++ assert_return(ret, -EINVAL); ++ ++ p = new(sd_radv_route_prefix, 1); ++ if (!p) ++ return -ENOMEM; ++ ++ *p = (sd_radv_route_prefix) { ++ .n_ref = 1, ++ ++ .opt.type = SD_RADV_OPT_ROUTE_INFORMATION, ++ .opt.length = DIV_ROUND_UP(sizeof(p->opt), 8), ++ .opt.prefixlen = 64, ++ ++ .opt.lifetime = htobe32(604800), ++ }; ++ ++ *ret = p; ++ return 0; ++} ++ ++DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_route_prefix, sd_radv_route_prefix, mfree); ++ ++_public_ int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, ++ unsigned char prefixlen) { ++ assert_return(p, -EINVAL); ++ assert_return(in6_addr, -EINVAL); ++ ++ if (prefixlen > 128) ++ return -EINVAL; ++ ++ if (prefixlen > 64) ++ /* unusual but allowed, log it */ ++ log_radv("Unusual prefix length %u greater than 64", prefixlen); ++ ++ p->opt.in6_addr = *in6_addr; ++ p->opt.prefixlen = prefixlen; ++ ++ return 0; ++} ++ ++_public_ int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint32_t valid_lifetime) { ++ assert_return(p, -EINVAL); ++ ++ p->opt.lifetime = htobe32(valid_lifetime); ++ ++ return 0; ++} +diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf +index d4d108ad25..43163a31ec 100644 +--- a/src/network/networkd-network-gperf.gperf ++++ b/src/network/networkd-network-gperf.gperf +@@ -223,6 +223,8 @@ IPv6Prefix.OnLink, config_parse_prefix_flags, + IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0 + IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0 + IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0 ++IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0 ++IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0 + CAN.BitRate, config_parse_si_size, 0, offsetof(Network, can_bitrate) + CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point) + CAN.RestartSec, config_parse_sec, 0, offsetof(Network, can_restart_us) +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 70dbd31f50..0608219429 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -458,6 +458,7 @@ int network_load_one(Manager *manager, const char *filename) { + "BridgeVLAN\0" + "IPv6PrefixDelegation\0" + "IPv6Prefix\0" ++ "IPv6RoutePrefix\0" + "CAN\0", + config_item_perf_lookup, network_network_gperf_lookup, + CONFIG_PARSE_WARN, network); +diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h +index bc760744e5..486b8c31a5 100644 +--- a/src/network/networkd-network.h ++++ b/src/network/networkd-network.h +@@ -221,6 +221,7 @@ struct Network { + LIST_HEAD(Neighbor, neighbors); + LIST_HEAD(AddressLabel, address_labels); + LIST_HEAD(Prefix, static_prefixes); ++ LIST_HEAD(Prefix, static_route_prefixes); + LIST_HEAD(RoutingPolicyRule, rules); + + unsigned n_static_addresses; +@@ -230,6 +231,7 @@ struct Network { + unsigned n_neighbors; + unsigned n_address_labels; + unsigned n_static_prefixes; ++ unsigned n_static_route_prefixes; + unsigned n_rules; + + Hashmap *addresses_by_section; +@@ -238,6 +240,7 @@ struct Network { + Hashmap *neighbors_by_section; + Hashmap *address_labels_by_section; + Hashmap *prefixes_by_section; ++ Hashmap *route_prefixes_by_section; + Hashmap *rules_by_section; + + /* All kinds of DNS configuration */ +diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c +index 25321aefed..8972c661ae 100644 +--- a/src/network/networkd-radv.c ++++ b/src/network/networkd-radv.c +@@ -101,16 +101,100 @@ static int prefix_new_static(Network *network, const char *filename, + return 0; + } + ++int route_prefix_new(Prefix **ret) { ++ _cleanup_(prefix_freep) Prefix *prefix = NULL; ++ ++ prefix = new0(Prefix, 1); ++ if (!prefix) ++ return -ENOMEM; ++ ++ if (sd_radv_route_prefix_new(&prefix->radv_route_prefix) < 0) ++ return -ENOMEM; ++ ++ *ret = TAKE_PTR(prefix); ++ ++ return 0; ++} ++ ++void route_prefix_free(Prefix *prefix) { ++ if (!prefix) ++ return; ++ ++ if (prefix->network) { ++ LIST_REMOVE(prefixes, prefix->network->static_route_prefixes, prefix); ++ assert(prefix->network->n_static_route_prefixes > 0); ++ prefix->network->n_static_route_prefixes--; ++ ++ if (prefix->section) ++ hashmap_remove(prefix->network->route_prefixes_by_section, ++ prefix->section); ++ } ++ ++ network_config_section_free(prefix->section); ++ ++ free(prefix); ++} ++ ++static int route_prefix_new_static(Network *network, const char *filename, ++ unsigned section_line, Prefix **ret) { ++ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; ++ _cleanup_(prefix_freep) Prefix *prefix = NULL; ++ int r; ++ ++ assert(network); ++ assert(ret); ++ assert(!!filename == (section_line > 0)); ++ ++ if (filename) { ++ r = network_config_section_new(filename, section_line, &n); ++ if (r < 0) ++ return r; ++ ++ if (section_line) { ++ prefix = hashmap_get(network->route_prefixes_by_section, n); ++ if (prefix) { ++ *ret = TAKE_PTR(prefix); ++ ++ return 0; ++ } ++ } ++ } ++ ++ r = route_prefix_new(&prefix); ++ if (r < 0) ++ return r; ++ ++ prefix->network = network; ++ LIST_APPEND(prefixes, network->static_route_prefixes, prefix); ++ network->n_static_route_prefixes++; ++ ++ if (filename) { ++ prefix->section = TAKE_PTR(n); ++ ++ r = hashmap_ensure_allocated(&network->route_prefixes_by_section, &network_config_hash_ops); ++ if (r < 0) ++ return r; ++ ++ r = hashmap_put(network->route_prefixes_by_section, prefix->section, prefix); ++ if (r < 0) ++ return r; ++ } ++ ++ *ret = TAKE_PTR(prefix); ++ ++ return 0; ++} ++ + int config_parse_prefix(const char *unit, +- const char *filename, +- unsigned line, +- const char *section, +- unsigned section_line, +- const char *lvalue, +- int ltype, +- const char *rvalue, +- void *data, +- void *userdata) { ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { + + Network *network = userdata; + _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; +@@ -234,6 +318,90 @@ int config_parse_prefix_lifetime(const char *unit, + return 0; + } + ++int config_parse_route_prefix(const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ ++ Network *network = userdata; ++ _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ uint8_t prefixlen = 64; ++ union in_addr_union in6addr; ++ int r; ++ ++ assert(filename); ++ assert(section); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ ++ r = route_prefix_new_static(network, filename, section_line, &p); ++ if (r < 0) ++ return r; ++ ++ r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Route prefix is invalid, ignoring assignment: %s", rvalue); ++ return 0; ++ } ++ ++ if (sd_radv_prefix_set_route_prefix(p->radv_route_prefix, &in6addr.in6, prefixlen) < 0) ++ return -EADDRNOTAVAIL; ++ ++ log_syntax(unit, LOG_INFO, filename, line, r, "Found route prefix %s", rvalue); ++ ++ p = NULL; ++ ++ return 0; ++} ++ ++int config_parse_route_prefix_lifetime(const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ Network *network = userdata; ++ _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ usec_t usec; ++ int r; ++ ++ assert(filename); ++ assert(section); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ ++ r = route_prefix_new_static(network, filename, section_line, &p); ++ if (r < 0) ++ return r; ++ ++ r = parse_sec(rvalue, &usec); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Roure lifetime is invalid, ignoring assignment: %s", rvalue); ++ return 0; ++ } ++ ++ /* a value of 0xffffffff represents infinity */ ++ r = sd_radv_route_prefix_set_lifetime(p->radv_route_prefix, DIV_ROUND_UP(usec, USEC_PER_SEC)); ++ if (r < 0) ++ return r; ++ ++ p = NULL; ++ ++ return 0; ++} ++ + static int radv_get_ip6dns(Network *network, struct in6_addr **dns, + size_t *n_dns) { + _cleanup_free_ struct in6_addr *addresses = NULL; +@@ -438,6 +606,15 @@ int radv_configure(Link *link) { + if (r < 0) + return r; + } ++ ++ LIST_FOREACH(prefixes, p, link->network->static_route_prefixes) { ++ r = sd_radv_add_route_prefix(link->radv, p->radv_route_prefix, false); ++ if (r == -EEXIST) ++ continue; ++ if (r < 0) ++ return r; ++ } ++ + } + + return radv_emit_dns(link); +diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h +index 45be083bfe..2f60b285ae 100644 +--- a/src/network/networkd-radv.h ++++ b/src/network/networkd-radv.h +@@ -26,8 +26,10 @@ struct Prefix { + NetworkConfigSection *section; + + sd_radv_prefix *radv_prefix; ++ sd_radv_route_prefix *radv_route_prefix; + + LIST_FIELDS(Prefix, prefixes); ++ LIST_FIELDS(Prefix, route_prefixes); + }; + + int prefix_new(Prefix **ret); +@@ -35,6 +37,11 @@ void prefix_free(Prefix *prefix); + + DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free); + ++int route_prefix_new(Prefix **ret); ++void route_prefix_free(Prefix *prefix); ++ ++DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, route_prefix_free); ++ + int radv_emit_dns(Link *link); + int radv_configure(Link *link); + +@@ -48,3 +55,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags); + CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime); + CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns); + CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains); ++CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix); ++CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix_lifetime); +diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h +index 93861b9d24..f085231934 100644 +--- a/src/systemd/sd-radv.h ++++ b/src/systemd/sd-radv.h +@@ -37,6 +37,7 @@ _SD_BEGIN_DECLARATIONS; + + typedef struct sd_radv sd_radv; + typedef struct sd_radv_prefix sd_radv_prefix; ++typedef struct sd_radv_route_prefix sd_radv_route_prefix; + + /* Router Advertisement */ + int sd_radv_new(sd_radv **ret); +@@ -59,6 +60,7 @@ int sd_radv_set_managed_information(sd_radv *ra, int managed); + int sd_radv_set_other_information(sd_radv *ra, int other); + int sd_radv_set_preference(sd_radv *ra, unsigned preference); + int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic); ++int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int dynamic); + sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, const struct in6_addr *prefix, + unsigned char prefixlen); + int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime, +@@ -80,8 +82,16 @@ int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p, + int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p, + uint32_t preferred_lifetime); + ++int sd_radv_route_prefix_new(sd_radv_route_prefix **ret); ++sd_radv_route_prefix *sd_radv_route_prefix_ref(sd_radv_route_prefix *ra); ++sd_radv_route_prefix *sd_radv_route_prefix_unref(sd_radv_route_prefix *ra); ++ ++int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen); ++int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint32_t valid_lifetime); ++ + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref); + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_prefix, sd_radv_prefix_unref); ++_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_route_prefix, sd_radv_route_prefix_unref); + + _SD_END_DECLARATIONS; + +diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network +index 848d4bd187..b688d37d08 100644 +--- a/test/fuzz/fuzz-network-parser/directives.network ++++ b/test/fuzz/fuzz-network-parser/directives.network +@@ -174,6 +174,9 @@ OnLink= + PreferredLifetimeSec= + AddressAutoconfiguration= + ValidLifetimeSec= ++[IPv6RoutePrefix] ++Route= ++LifetimeSec= + [BridgeVLAN] + EgressUntagged= + VLAN= +-- +2.23.0 + diff --git a/network-add-one-more-section-validty-check.patch b/network-add-one-more-section-validty-check.patch new file mode 100644 index 0000000..f2107bb --- /dev/null +++ b/network-add-one-more-section-validty-check.patch @@ -0,0 +1,28 @@ +From 714a199e481c294b9986b7d5160a89a65d8b375a Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 19 Sep 2019 15:20:00 +0900 +Subject: [PATCH] network: add one more section validty check + +Follow-up for 203d4df5732b1fdcf50db498ddeb74a934b21f87. +--- + src/network/networkd-network.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index d1c4cddeb1..a2cd7f4c60 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -300,6 +300,10 @@ int network_verify(Network *network) { + if (section_is_invalid(prefix->section)) + prefix_free(prefix); + ++ LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_route_prefixes) ++ if (section_is_invalid(prefix->section)) ++ prefix_free(prefix); ++ + LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules) + if (routing_policy_rule_section_verify(rule) < 0) + routing_policy_rule_free(rule); +-- +2.23.0 + diff --git a/network-fix-invalid-cleanup-function.patch b/network-fix-invalid-cleanup-function.patch new file mode 100644 index 0000000..0b7d423 --- /dev/null +++ b/network-fix-invalid-cleanup-function.patch @@ -0,0 +1,34 @@ +From e7825b2359d484c606bc1ff8ae3e5ab9aaf980c1 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 10:39:15 +0900 +Subject: [PATCH] network: fix invalid cleanup function + +--- + src/network/networkd-radv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c +index 8972c661ae..4e74756d17 100644 +--- a/src/network/networkd-radv.c ++++ b/src/network/networkd-radv.c +@@ -330,7 +330,7 @@ int config_parse_route_prefix(const char *unit, + void *userdata) { + + Network *network = userdata; +- _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ _cleanup_(route_prefix_free_or_set_invalidp) Prefix *p = NULL; + uint8_t prefixlen = 64; + union in_addr_union in6addr; + int r; +@@ -372,7 +372,7 @@ int config_parse_route_prefix_lifetime(const char *unit, + void *data, + void *userdata) { + Network *network = userdata; +- _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ _cleanup_(route_prefix_free_or_set_invalidp) Prefix *p = NULL; + usec_t usec; + int r; + +-- +2.23.0 + diff --git a/network-fix-memleak-in-route_prefix_free.patch b/network-fix-memleak-in-route_prefix_free.patch new file mode 100644 index 0000000..a63765e --- /dev/null +++ b/network-fix-memleak-in-route_prefix_free.patch @@ -0,0 +1,33 @@ +From 471e126b254dccac66cb2987be3a5f58592d8932 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 10:46:44 +0900 +Subject: [PATCH] network: fix memleak in route_prefix_free() + +--- + src/network/networkd-radv.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c +index 8d933f1901..87db34d6cc 100644 +--- a/src/network/networkd-radv.c ++++ b/src/network/networkd-radv.c +@@ -31,7 +31,7 @@ void prefix_free(Prefix *prefix) { + } + + network_config_section_free(prefix->section); +- prefix->radv_prefix = sd_radv_prefix_unref(prefix->radv_prefix); ++ sd_radv_prefix_unref(prefix->radv_prefix); + + free(prefix); + } +@@ -131,6 +131,7 @@ void route_prefix_free(Prefix *prefix) { + } + + network_config_section_free(prefix->section); ++ sd_radv_route_prefix_unref(prefix->radv_route_prefix); + + free(prefix); + } +-- +2.23.0 + diff --git a/network-fix-memleak.patch b/network-fix-memleak.patch new file mode 100644 index 0000000..5aef90c --- /dev/null +++ b/network-fix-memleak.patch @@ -0,0 +1,34 @@ +From 9be6ae775fb303deb49ee8e4c5013ce98dc48b93 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 09:39:44 +0900 +Subject: [PATCH] network: fix memleak + +--- + src/network/networkd-network.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 5e82b3c5e0..f6d02fb274 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -586,6 +586,9 @@ static Network *network_free(Network *network) { + while ((prefix = network->static_prefixes)) + prefix_free(prefix); + ++ while ((prefix = network->static_route_prefixes)) ++ route_prefix_free(prefix); ++ + while ((rule = network->rules)) + routing_policy_rule_free(rule); + +@@ -596,6 +599,7 @@ static Network *network_free(Network *network) { + hashmap_free(network->neighbors_by_section); + hashmap_free(network->address_labels_by_section); + hashmap_free(network->prefixes_by_section); ++ hashmap_free(network->route_prefixes_by_section); + hashmap_free(network->rules_by_section); + + if (network->manager) { +-- +2.23.0 + diff --git a/network-use-fix-invalid-free-function.patch b/network-use-fix-invalid-free-function.patch new file mode 100644 index 0000000..e811470 --- /dev/null +++ b/network-use-fix-invalid-free-function.patch @@ -0,0 +1,26 @@ +From acb71754e12f98ebd01963869a297ea262494740 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 09:36:39 +0900 +Subject: [PATCH] network: use fix invalid free function + +Fixes #13938. +--- + src/network/networkd-network.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 90d86f35a9..5e82b3c5e0 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -306,7 +306,7 @@ int network_verify(Network *network) { + + LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_route_prefixes) + if (section_is_invalid(prefix->section)) +- prefix_free(prefix); ++ route_prefix_free(prefix); + + LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules) + if (routing_policy_rule_section_verify(rule) < 0) +-- +2.23.0 + diff --git a/sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch b/sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch new file mode 100644 index 0000000..d937f86 --- /dev/null +++ b/sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch @@ -0,0 +1,25 @@ +From 58abbbcc6bcedc4eebd1f5c7733cd41518e1f2e3 Mon Sep 17 00:00:00 2001 +From: sangelovic +Date: Mon, 27 Jan 2020 21:40:37 +0100 +Subject: [PATCH] sd-bus: fix introspection bug in signal parameter names + +--- + src/libsystemd/sd-bus/bus-introspect.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c +index beab80687d..e8934489b5 100644 +--- a/src/libsystemd/sd-bus/bus-introspect.c ++++ b/src/libsystemd/sd-bus/bus-introspect.c +@@ -160,7 +160,7 @@ int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) { + case _SD_BUS_VTABLE_SIGNAL: + fprintf(i->f, " \n", v->x.signal.member); + if (bus_vtable_has_names(vtable)) +- names = strempty(v->x.method.names); ++ names = strempty(v->x.signal.names); + introspect_write_arguments(i, strempty(v->x.signal.signature), &names, NULL); + introspect_write_flags(i, v->type, v->flags); + fputs(" \n", i->f); +-- +2.23.0 + diff --git a/sd-bus-invalidate-connection-when-Hello-fails.patch b/sd-bus-invalidate-connection-when-Hello-fails.patch new file mode 100644 index 0000000..2b09b25 --- /dev/null +++ b/sd-bus-invalidate-connection-when-Hello-fails.patch @@ -0,0 +1,66 @@ +From 19fa17c7c4ac228924bd9b7499653a6018abf0b5 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 15 Nov 2019 14:23:53 +0100 +Subject: [PATCH] sd-bus: invalidate connection when Hello() fails + +Fixes: #13969 +--- + src/libsystemd/sd-bus/sd-bus.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index ebbfc588ca..058492a83e 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -537,29 +537,41 @@ static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *e + assert(IN_SET(bus->state, BUS_HELLO, BUS_CLOSING)); + + r = sd_bus_message_get_errno(reply); +- if (r > 0) +- return -r; ++ if (r > 0) { ++ r = -r; ++ goto fail; ++ } + + r = sd_bus_message_read(reply, "s", &s); + if (r < 0) +- return r; ++ goto fail; + +- if (!service_name_is_valid(s) || s[0] != ':') +- return -EBADMSG; ++ if (!service_name_is_valid(s) || s[0] != ':') { ++ r = -EBADMSG; ++ goto fail; ++ } + + r = free_and_strdup(&bus->unique_name, s); + if (r < 0) +- return r; ++ goto fail; + + if (bus->state == BUS_HELLO) { + bus_set_state(bus, BUS_RUNNING); + + r = synthesize_connected_signal(bus); + if (r < 0) +- return r; ++ goto fail; + } + + return 1; ++ ++fail: ++ /* When Hello() failed, let's propagate this in two ways: first we return the error immediately here, ++ * which is the propagated up towards the event loop. Let's also invalidate the connection, so that ++ * if the user then calls back into us again we won't wait any longer. */ ++ ++ bus_set_state(bus, BUS_CLOSING); ++ return r; + } + + static int bus_send_hello(sd_bus *bus) { +-- +2.23.0 + diff --git a/sd-radv-fix-memleak.patch b/sd-radv-fix-memleak.patch new file mode 100644 index 0000000..78b1310 --- /dev/null +++ b/sd-radv-fix-memleak.patch @@ -0,0 +1,30 @@ +From 69d7eba1880095f4a9bf9350de777fe7d370c188 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 13:30:00 +0900 +Subject: [PATCH] sd-radv: fix memleak + +--- + src/libsystemd-network/sd-radv.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c +index 5c7f727faa..873a2f40f8 100644 +--- a/src/libsystemd-network/sd-radv.c ++++ b/src/libsystemd-network/sd-radv.c +@@ -99,6 +99,13 @@ static sd_radv *radv_free(sd_radv *ra) { + sd_radv_prefix_unref(p); + } + ++ while (ra->route_prefixes) { ++ sd_radv_route_prefix *p = ra->route_prefixes; ++ ++ LIST_REMOVE(prefix, ra->route_prefixes, p); ++ sd_radv_route_prefix_unref(p); ++ } ++ + free(ra->rdnss); + free(ra->dnssl); + +-- +2.23.0 + diff --git a/shared-bus-util-Don-t-replace-exsting-strv.patch b/shared-bus-util-Don-t-replace-exsting-strv.patch new file mode 100644 index 0000000..6b6ae8a --- /dev/null +++ b/shared-bus-util-Don-t-replace-exsting-strv.patch @@ -0,0 +1,33 @@ +From 411975ce63b28194b21b964268efaa04b19cbb37 Mon Sep 17 00:00:00 2001 +From: Kevin Kuehler +Date: Tue, 10 Dec 2019 01:58:01 -0800 +Subject: [PATCH] shared/bus-util: Don't replace exsting strv + +Change the behavior of string arrays in a bus property map. Previously, +passing the same strv pointer to more than one map entry would result in +the old strv being freed and overwritten. With this change, an existing +strv pointer is appended to. + +This is important if we want to create one strv comprised of multiple +dependencies. This makes it so callers don't have to create one strv per +dependency and subsequently merge them into one strv. +--- + src/shared/bus-util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index aea46d3119..10c05eba18 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -1127,7 +1127,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigne + if (r < 0) + return r; + +- return strv_free_and_replace(*p, l); ++ return strv_extend_strv(p, l, false); + } + + case SD_BUS_TYPE_BOOLEAN: { +-- +2.23.0 + diff --git a/systemctl-Add-with-dependencies-flag.patch b/systemctl-Add-with-dependencies-flag.patch new file mode 100644 index 0000000..8fc4800 --- /dev/null +++ b/systemctl-Add-with-dependencies-flag.patch @@ -0,0 +1,330 @@ +From e9c387c8293c57d1c773fc80d23239350eb3b370 Mon Sep 17 00:00:00 2001 +From: Kevin Kuehler +Date: Sun, 8 Dec 2019 15:23:27 -0800 +Subject: [PATCH] systemctl: Add --with-dependencies flag + +Will print a unit and all of its dependencies. Works with cat, status, +list-units, and list-unit-files. This flag can also be used in conjunction +with --reverse, --before, and --after. + +We also vastly simplify the list_dependencies_get_dependencies logic. +Instead of using 5 strvs and merging them into one, use one strv and +have the bus append all the map values to it. + +Fixes #9273 +--- + src/systemctl/systemctl.c | 227 +++++++++++++++++++++++++------------- + 1 file changed, 148 insertions(+), 79 deletions(-) + +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 6a0e59a4d7..0873045173 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -117,6 +117,7 @@ static bool arg_dry_run = false; + static bool arg_quiet = false; + static bool arg_full = false; + static bool arg_recursive = false; ++static bool arg_with_dependencies = false; + static bool arg_show_transaction = false; + static int arg_force = 0; + static bool arg_ask_password = false; +@@ -799,6 +800,107 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r + return c; + } + ++static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***ret) { ++ _cleanup_strv_free_ char **deps = NULL; ++ ++ static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = { ++ [DEPENDENCY_FORWARD] = { ++ { "Requires", "as", NULL, 0 }, ++ { "Requisite", "as", NULL, 0 }, ++ { "Wants", "as", NULL, 0 }, ++ { "ConsistsOf", "as", NULL, 0 }, ++ { "BindsTo", "as", NULL, 0 }, ++ {} ++ }, ++ [DEPENDENCY_REVERSE] = { ++ { "RequiredBy", "as", NULL, 0 }, ++ { "RequisiteOf", "as", NULL, 0 }, ++ { "WantedBy", "as", NULL, 0 }, ++ { "PartOf", "as", NULL, 0 }, ++ { "BoundBy", "as", NULL, 0 }, ++ {} ++ }, ++ [DEPENDENCY_AFTER] = { ++ { "After", "as", NULL, 0 }, ++ {} ++ }, ++ [DEPENDENCY_BEFORE] = { ++ { "Before", "as", NULL, 0 }, ++ {} ++ }, ++ }; ++ ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_free_ char *dbus_path = NULL; ++ int r; ++ ++ assert(bus); ++ assert(name); ++ assert(ret); ++ ++ dbus_path = unit_dbus_path_from_name(name); ++ if (!dbus_path) ++ return log_oom(); ++ ++ r = bus_map_all_properties(bus, ++ "org.freedesktop.systemd1", ++ dbus_path, ++ map[arg_dependency], ++ BUS_MAP_STRDUP, ++ &error, ++ NULL, ++ &deps); ++ if (r < 0) ++ return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r)); ++ ++ *ret = TAKE_PTR(deps); ++ ++ return 0; ++} ++ ++static int append_unit_dependencies(sd_bus *bus, char **names, char ***ret) { ++ _cleanup_strv_free_ char **with_deps = NULL; ++ char **name; ++ ++ assert(bus); ++ assert(ret); ++ ++ STRV_FOREACH(name, names) { ++ _cleanup_strv_free_ char **deps = NULL; ++ ++ if (strv_extend(&with_deps, *name) < 0) ++ return log_oom(); ++ ++ (void) list_dependencies_get_dependencies(bus, *name, &deps); ++ ++ if (strv_extend_strv(&with_deps, deps, true) < 0) ++ return log_oom(); ++ } ++ ++ *ret = TAKE_PTR(with_deps); ++ ++ return 0; ++} ++ ++static int maybe_extend_with_unit_dependencies(sd_bus *bus, char ***list) { ++ assert(bus); ++ assert(list); ++ ++ if (arg_with_dependencies) { ++ int r; ++ _cleanup_strv_free_ char **list_with_deps = NULL; ++ ++ r = append_unit_dependencies(bus, *list, &list_with_deps); ++ if (r < 0) ++ return log_error_errno(r, "Failed to append unit dependencies: %m"); ++ ++ strv_free(*list); ++ *list = TAKE_PTR(list_with_deps); ++ } ++ ++ return 0; ++} ++ + static int list_units(int argc, char *argv[], void *userdata) { + _cleanup_free_ UnitInfo *unit_infos = NULL; + _cleanup_(message_set_freep) Set *replies = NULL; +@@ -812,9 +914,21 @@ static int list_units(int argc, char *argv[], void *userdata) { + + (void) pager_open(arg_pager_flags); + +- r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); +- if (r < 0) +- return r; ++ if (arg_with_dependencies) { ++ _cleanup_strv_free_ char **names = NULL; ++ ++ r = append_unit_dependencies(bus, strv_skip(argv, 1), &names); ++ if (r < 0) ++ return r; ++ ++ r = get_unit_list_recursive(bus, names, &unit_infos, &replies, &machines); ++ if (r < 0) ++ return r; ++ } else { ++ r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); ++ if (r < 0) ++ return r; ++ } + + typesafe_qsort(unit_infos, r, compare_unit_info); + return output_units_list(unit_infos, r); +@@ -1571,9 +1685,21 @@ static int list_unit_files(int argc, char *argv[], void *userdata) { + if (r < 0) + return bus_log_create_error(r); + +- r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); +- if (r < 0) +- return bus_log_create_error(r); ++ if (arg_with_dependencies) { ++ _cleanup_strv_free_ char **names_with_deps = NULL; ++ ++ r = append_unit_dependencies(bus, strv_skip(argv, 1), &names_with_deps); ++ if (r < 0) ++ return log_error_errno(r, "Failed to append unit dependencies: %m"); ++ ++ r = sd_bus_message_append_strv(m, names_with_deps); ++ if (r < 0) ++ return bus_log_create_error(r); ++ } else { ++ r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); ++ if (r < 0) ++ return bus_log_create_error(r); ++ } + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) { +@@ -1677,79 +1803,6 @@ static int list_dependencies_print(const char *name, int level, unsigned branche + return 0; + } + +-static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) { +- struct DependencyStatusInfo { +- char **dep[5]; +- } info = {}; +- +- static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = { +- [DEPENDENCY_FORWARD] = { +- { "Requires", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- { "Requisite", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) }, +- { "Wants", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) }, +- { "ConsistsOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) }, +- { "BindsTo", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) }, +- {} +- }, +- [DEPENDENCY_REVERSE] = { +- { "RequiredBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- { "RequisiteOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) }, +- { "WantedBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) }, +- { "PartOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) }, +- { "BoundBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) }, +- {} +- }, +- [DEPENDENCY_AFTER] = { +- { "After", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- {} +- }, +- [DEPENDENCY_BEFORE] = { +- { "Before", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- {} +- }, +- }; +- +- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; +- _cleanup_strv_free_ char **ret = NULL; +- _cleanup_free_ char *dbus_path = NULL; +- int i, r; +- +- assert(bus); +- assert(name); +- assert(deps); +- +- dbus_path = unit_dbus_path_from_name(name); +- if (!dbus_path) +- return log_oom(); +- +- r = bus_map_all_properties(bus, +- "org.freedesktop.systemd1", +- dbus_path, +- map[arg_dependency], +- BUS_MAP_STRDUP, +- &error, +- NULL, +- &info); +- if (r < 0) +- return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r)); +- +- if (IN_SET(arg_dependency, DEPENDENCY_AFTER, DEPENDENCY_BEFORE)) { +- *deps = info.dep[0]; +- return 0; +- } +- +- for (i = 0; i < 5; i++) { +- r = strv_extend_strv(&ret, info.dep[i], true); +- if (r < 0) +- return log_oom(); +- info.dep[i] = strv_free(info.dep[i]); +- } +- +- *deps = TAKE_PTR(ret); +- +- return 0; +-} +- + static int list_dependencies_compare(char * const *a, char * const *b) { + if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET) + return 1; +@@ -5909,6 +5962,10 @@ static int show(int argc, char *argv[], void *userdata) { + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + ++ r = maybe_extend_with_unit_dependencies(bus, &names); ++ if (r < 0) ++ return r; ++ + STRV_FOREACH(name, names) { + _cleanup_free_ char *path; + +@@ -5959,6 +6016,10 @@ static int cat(int argc, char *argv[], void *userdata) { + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + ++ r = maybe_extend_with_unit_dependencies(bus, &names); ++ if (r < 0) ++ return r; ++ + (void) pager_open(arg_pager_flags); + + STRV_FOREACH(name, names) { +@@ -7945,6 +8006,9 @@ static int systemctl_help(void) { + " -l --full Don't ellipsize unit names on output\n" + " -r --recursive Show unit list of host and local containers\n" + " --reverse Show reverse dependencies with 'list-dependencies'\n" ++ " --with-dependencies\n" ++ " Show unit dependencies with 'status', 'cat',\n" ++ " 'list-units', and 'list-unit-files'.\n" + " --job-mode=MODE Specify how to deal with already queued jobs, when\n" + " queueing a new job\n" + " -T --show-transaction\n" +@@ -8235,6 +8298,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { + ARG_BOOT_LOADER_ENTRY, + ARG_NOW, + ARG_MESSAGE, ++ ARG_WITH_DEPENDENCIES, + ARG_WAIT, + ARG_WHAT, + }; +@@ -8281,6 +8345,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { + { "plain", no_argument, NULL, ARG_PLAIN }, + { "state", required_argument, NULL, ARG_STATE }, + { "recursive", no_argument, NULL, 'r' }, ++ { "with-dependencies", no_argument, NULL, ARG_WITH_DEPENDENCIES }, + { "preset-mode", required_argument, NULL, ARG_PRESET_MODE }, + { "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP }, + { "boot-loader-menu", required_argument, NULL, ARG_BOOT_LOADER_MENU }, +@@ -8641,6 +8706,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { + arg_show_transaction = true; + break; + ++ case ARG_WITH_DEPENDENCIES: ++ arg_with_dependencies = true; ++ break; ++ + case ARG_WHAT: { + const char *p; + +-- +2.23.0 + diff --git a/systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch b/systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch new file mode 100644 index 0000000..20d450f --- /dev/null +++ b/systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch @@ -0,0 +1,25 @@ +From 13f697b7b1f3837d144ba6f60188bc7dc4d1fbaa Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 13 Oct 2019 00:54:34 +0900 +Subject: [PATCH] systemctl: fix memleak caused by wrong cleanup func + +--- + src/systemctl/systemctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 98a71c4460..738b9af536 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -7977,7 +7977,7 @@ static void help_states(void) { + + static int help_boot_loader_entry(void) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; +- _cleanup_free_ char **l = NULL; ++ _cleanup_strv_free_ char **l = NULL; + sd_bus *bus; + char **i; + int r; +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index e7bc021..baf372a 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 24 +Release: 25 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -89,6 +89,31 @@ Patch0039: seccomp-more-comprehensive-protection-against-libsec.patch Patch0040: network-fix-double-free-in-macsec_receive_channel_fr.patch Patch0041: network-L2TP-fix-crash.patch +Patch0042: systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch +Patch0043: analyze-fix-minor-memleak.patch +Patch0044: network-add-one-more-section-validty-check.patch +Patch0045: network-use-fix-invalid-free-function.patch +Patch0046: network-fix-memleak.patch +Patch0047: network-Add-support-to-advertie-ipv6-route.patch +Patch0048: network-fix-invalid-cleanup-function.patch +Patch0049: network-fix-memleak-in-route_prefix_free.patch +Patch0050: sd-radv-fix-memleak.patch +Patch0051: sd-bus-invalidate-connection-when-Hello-fails.patch +Patch0052: shared-bus-util-Don-t-replace-exsting-strv.patch +Patch0053: systemctl-Add-with-dependencies-flag.patch +Patch0054: man-Document-systemctl-with-dependencies-switch.patch +Patch0055: core-expose-swap-priority-value-via-dbus-only-if-it-.patch +Patch0056: tree-wide-we-forgot-to-destroy-some-bus-errors.patch +Patch0057: sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch +Patch0058: core-sync-SeccompParseFlags-between-dbus-execute-and.patch +Patch0059: core-swap-priority-can-be-negative.patch +Patch0060: core-no-need-to-initialize-swap-structure-fields-if-.patch +Patch0061: core-initialize-priority_set-when-parsing-swap-unit-.patch +Patch0062: core-use-unit-based-logging-instead-of-generic-loggi.patch +Patch0063: core-set-error-value-correctly.patch +Patch0064: core-fix-re-realization-of-cgroup-siblings.patch +Patch0065: basic-string-table-avoid-crash-when-table-is-sparse.patch + #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch Patch9003: 1602-activation-service-must-be-restarted-when-reactivated.patch @@ -1480,6 +1505,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Thu Jun 18 2020 openEuler Buildteam - 243-25 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:dbus commissioning enhancement + * Thu May 28 2020 openEuler Buildteam - 243-24 - Type:enhancement - ID:NA diff --git a/tree-wide-we-forgot-to-destroy-some-bus-errors.patch b/tree-wide-we-forgot-to-destroy-some-bus-errors.patch new file mode 100644 index 0000000..92beba2 --- /dev/null +++ b/tree-wide-we-forgot-to-destroy-some-bus-errors.patch @@ -0,0 +1,39 @@ +From 7e284b054ec599012f0dad6a745f6b52eba87853 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 17 Jan 2020 15:37:56 +0100 +Subject: [PATCH] tree-wide: we forgot to destroy some bus errors + +--- + src/libsystemd/sd-bus/test-bus-server.c | 2 +- + src/locale/localed.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c +index e38bcdcc76..82eb35e5b1 100644 +--- a/src/libsystemd/sd-bus/test-bus-server.c ++++ b/src/libsystemd/sd-bus/test-bus-server.c +@@ -108,7 +108,7 @@ fail: + static int client(struct context *c) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; +- sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert_se(sd_bus_new(&bus) >= 0); +diff --git a/src/locale/localed.c b/src/locale/localed.c +index baf0bd102b..2031cd25ce 100644 +--- a/src/locale/localed.c ++++ b/src/locale/localed.c +@@ -33,7 +33,7 @@ static int locale_update_system_manager(Context *c, sd_bus *bus) { + _cleanup_free_ char **l_unset = NULL; + _cleanup_strv_free_ char **l_set = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; +- sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + size_t c_set, c_unset; + LocaleVariable p; + int r; +-- +2.23.0 + -- Gitee From 657ad8be9ad33e8e1550d18c31050f94c530c5e9 Mon Sep 17 00:00:00 2001 From: fayeinseu <15651793630@163.com> Date: Tue, 7 Jul 2020 16:30:00 +0800 Subject: [PATCH 05/38] fix buffer overrun when urlifying. --- ...al-fix-buffer-overrun-when-urlifying.patch | 49 +++++++++++++++++++ systemd.spec | 9 +++- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 journal-fix-buffer-overrun-when-urlifying.patch diff --git a/journal-fix-buffer-overrun-when-urlifying.patch b/journal-fix-buffer-overrun-when-urlifying.patch new file mode 100644 index 0000000..d46e191 --- /dev/null +++ b/journal-fix-buffer-overrun-when-urlifying.patch @@ -0,0 +1,49 @@ +From 85fbebe61a1aec2f86e36fb464283b6b55d3d76d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 23 Jun 2020 20:51:13 +0200 +Subject: [PATCH] journal: fix buffer overrun when urlifying + +Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21122. + +message is only valid until message_len, and we need to make sure we're not +reading pass that. Bug introduced in 2108b56749ebb8d17f06d08b6ada2f79ae4f0. +--- + src/shared/logs-show.c | 9 ++++++--- + test/fuzz/fuzz-journal-remote/oss-fuzz-21122 | Bin 0 -> 35798 bytes + 2 files changed, 6 insertions(+), 3 deletions(-) + create mode 100644 test/fuzz/fuzz-journal-remote/oss-fuzz-21122 + +diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c +index 570377dc76..fee6ccdf2a 100644 +--- a/src/shared/logs-show.c ++++ b/src/shared/logs-show.c +@@ -573,19 +573,22 @@ static int output_short( + if (config_file && + message_len >= config_file_len && + memcmp(message, config_file, config_file_len) == 0 && +- IN_SET(message[config_file_len], ':', ' ', '\0') && ++ (message_len == config_file_len || IN_SET(message[config_file_len], ':', ' ')) && + (!highlight || highlight_shifted[0] == 0 || highlight_shifted[0] > config_file_len)) { + + _cleanup_free_ char *t = NULL, *urlified = NULL; + + t = strndup(config_file, config_file_len); + if (t && terminal_urlify_path(t, NULL, &urlified) >= 0) { +- size_t shift = strlen(urlified) - config_file_len; ++ size_t urlified_len = strlen(urlified); ++ size_t shift = urlified_len - config_file_len; + char *joined; + +- joined = strjoin(urlified, message + config_file_len); ++ joined = realloc(urlified, message_len + shift); + if (joined) { ++ memcpy(joined + urlified_len, message + config_file_len, message_len - config_file_len); + free_and_replace(message, joined); ++ TAKE_PTR(urlified); + message_len += shift; + if (highlight) { + highlight_shifted[0] += shift; + +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index baf372a..6a90b19 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 25 +Release: 26 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -113,6 +113,7 @@ Patch0062: core-use-unit-based-logging-instead-of-generic-loggi.patch Patch0063: core-set-error-value-correctly.patch Patch0064: core-fix-re-realization-of-cgroup-siblings.patch Patch0065: basic-string-table-avoid-crash-when-table-is-sparse.patch +Patch0066: journal-fix-buffer-overrun-when-urlifying.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1505,6 +1506,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Jul 7 2020 openEuler Buildteam - 243-26 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:fix buffer overrun when urlifying + * Thu Jun 18 2020 openEuler Buildteam - 243-25 - Type:enhancement - ID:NA -- Gitee From 33904a01d7e1740b798c0d05e1dc56bdcd8ee7ca Mon Sep 17 00:00:00 2001 From: Yangyang Shen Date: Mon, 23 Nov 2020 16:26:49 +0800 Subject: [PATCH 06/38] add elevator= kernel command line parameter and don't enable bfq by default --- ...dev-use-bfq-as-the-default-scheduler.patch | 40 ------------------- ...le-that-adds-elevator-kernel-command.patch | 6 +-- systemd.spec | 11 +++-- 3 files changed, 11 insertions(+), 46 deletions(-) delete mode 100644 0001-udev-use-bfq-as-the-default-scheduler.patch diff --git a/0001-udev-use-bfq-as-the-default-scheduler.patch b/0001-udev-use-bfq-as-the-default-scheduler.patch deleted file mode 100644 index bbb294b..0000000 --- a/0001-udev-use-bfq-as-the-default-scheduler.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 5ab4d083dbe0a1ae095875c4af6ac26749b67211 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Wed, 14 Aug 2019 15:57:42 +0200 -Subject: [PATCH] udev: use bfq as the default scheduler - -As requested in https://bugzilla.redhat.com/show_bug.cgi?id=1738828. -Test results are that bfq seems to behave better and more consistently on -typical hardware. The kernel does not have a configuration option to set -the default scheduler, and it currently needs to be set by userspace. - -See the bug for more discussion and links. ---- - rules/60-block-scheduler.rules | 5 +++++ - rules/meson.build | 1 + - 2 files changed, 6 insertions(+) - create mode 100644 rules/60-block-scheduler.rules - -diff --git a/rules/60-block-scheduler.rules b/rules/60-block-scheduler.rules -new file mode 100644 -index 00000000000..480b941761f ---- /dev/null -+++ b/rules/60-block-scheduler.rules -@@ -0,0 +1,5 @@ -+# do not edit this file, it will be overwritten on update -+ -+ACTION=="add", SUBSYSTEM=="block", \ -+ KERNEL=="mmcblk*[0-9]|msblk*[0-9]|mspblk*[0-9]|sd*[!0-9]|sr*", \ -+ ATTR{queue/scheduler}="bfq" -diff --git a/rules/meson.build b/rules/meson.build -index b6a32ba77e2..1da958b4d46 100644 ---- a/rules/meson.build -+++ b/rules/meson.build -@@ -2,6 +2,7 @@ - - rules = files(''' - 60-block.rules -+ 60-block-scheduler.rules - 60-cdrom_id.rules - 60-drm.rules - 60-evdev.rules diff --git a/rules-add-the-rule-that-adds-elevator-kernel-command.patch b/rules-add-the-rule-that-adds-elevator-kernel-command.patch index dd20b73..2e5faab 100644 --- a/rules-add-the-rule-that-adds-elevator-kernel-command.patch +++ b/rules-add-the-rule-that-adds-elevator-kernel-command.patch @@ -11,7 +11,7 @@ Resolves: #1670126 1 file changed, 1 insertion(+) diff --git a/rules/meson.build b/rules/meson.build -index 1da958b..043313a 100644 +index 0fb5c6a..a2dbf2b 100644 --- a/rules/meson.build +++ b/rules/meson.build @@ -1,6 +1,7 @@ @@ -20,8 +20,8 @@ index 1da958b..043313a 100644 rules = files(''' + 40-elevator.rules 60-block.rules - 60-block-scheduler.rules 60-cdrom_id.rules + 60-drm.rules -- -2.19.1 +2.23.0 diff --git a/systemd.spec b/systemd.spec index 6a90b19..28e6d50 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 26 +Release: 27 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -44,7 +44,6 @@ Source105: rule_generator.functions Source106: write_net_rules Source107: detect_virt -Patch0001: 0001-udev-use-bfq-as-the-default-scheduler.patch Patch0002: 0001-udev-ignore-error-caused-by-device-disconnection.patch Patch0003: 0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch Patch0004: 0001-core-dont-check-potentially-NULL-error.patch @@ -1409,7 +1408,6 @@ fi %{_udevrulesdir}/60-persistent-v4l.rules %{_udevrulesdir}/70-joystick.rules %{_udevrulesdir}/70-power-switch.rules -%{_udevrulesdir}/60-block-scheduler.rules %{_udevrulesdir}/60-persistent-storage.rules %{_udevrulesdir}/80-net-setup-link.rules %{_udevrulesdir}/60-evdev.rules @@ -1506,6 +1504,13 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon Nov 23 2020 openEuler Buildteam - 243-27 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:add elevator= kernel command line parameter and don't enable bfq + by default + * Tue Jul 7 2020 openEuler Buildteam - 243-26 - Type:enhancement - ID:NA -- Gitee From 6aa75ab3773d8a7a9eb0aa3c115b4ffa2400b4c0 Mon Sep 17 00:00:00 2001 From: Yangyang Shen Date: Wed, 25 Nov 2020 10:59:27 +0800 Subject: [PATCH 07/38] don't enable systemd-journald-audit.socket by default --- ...able-systemd-journald-audit.socket-b.patch | 19 +++++++++++++++++-- systemd.spec | 9 +++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/journal-don-t-enable-systemd-journald-audit.socket-b.patch b/journal-don-t-enable-systemd-journald-audit.socket-b.patch index bdb9129..1c4f54a 100644 --- a/journal-don-t-enable-systemd-journald-audit.socket-b.patch +++ b/journal-don-t-enable-systemd-journald-audit.socket-b.patch @@ -7,9 +7,24 @@ Subject: [PATCH] journal: don't enable systemd-journald-audit.socket Resolves: #1699287 --- + units/meson.build | 3 +-- units/systemd-journald.service.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) + 2 files changed, 2 insertions(+), 3 deletions(-) +diff --git a/units/meson.build b/units/meson.build +index e105ade..48c621d 100644 +--- a/units/meson.build ++++ b/units/meson.build +@@ -88,8 +88,7 @@ units = [ + 'sockets.target.wants/'], + ['systemd-journal-gatewayd.socket', 'ENABLE_REMOTE HAVE_MICROHTTPD'], + ['systemd-journal-remote.socket', 'ENABLE_REMOTE HAVE_MICROHTTPD'], +- ['systemd-journald-audit.socket', '', +- 'sockets.target.wants/'], ++ ['systemd-journald-audit.socket', ''], + ['systemd-journald-dev-log.socket', '', + 'sockets.target.wants/'], + ['systemd-journald.socket', '', diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in index 089bc38..7436619 100644 --- a/units/systemd-journald.service.in @@ -24,5 +39,5 @@ index 089bc38..7436619 100644 SystemCallArchitectures=native SystemCallErrorNumber=EPERM -- -2.19.1 +2.23.0 diff --git a/systemd.spec b/systemd.spec index 28e6d50..e4bbaba 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 27 +Release: 28 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -1139,7 +1139,6 @@ fi %{_unitdir}/multi-user.target.wants/systemd-update-utmp-runlevel.service %{_unitdir}/systemd-hostnamed.service.d/disable-privatedevices.conf %{_unitdir}/sockets.target.wants/systemd-coredump.socket -%{_unitdir}/sockets.target.wants/systemd-journald-audit.socket %{_unitdir}/sockets.target.wants/systemd-journald-dev-log.socket %{_unitdir}/sockets.target.wants/systemd-journald.socket %{_unitdir}/sockets.target.wants/systemd-initctl.socket @@ -1504,6 +1503,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Wed Nov 25 2020 shenyangyang - 243-28 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:don't enable systemd-journald-audit.socket by default + * Mon Nov 23 2020 openEuler Buildteam - 243-27 - Type:enhancement - ID:NA -- Gitee From ccd97e8e83936269351d019ec84bcf512b4334da Mon Sep 17 00:00:00 2001 From: Yangyang Shen Date: Mon, 14 Dec 2020 14:10:47 +0800 Subject: [PATCH 08/38] revert don't enable systemd-journald-audit.socket by default --- ...able-systemd-journald-audit.socket-b.patch | 19 ++----------------- systemd.spec | 11 ++++++++++- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/journal-don-t-enable-systemd-journald-audit.socket-b.patch b/journal-don-t-enable-systemd-journald-audit.socket-b.patch index 1c4f54a..bdb9129 100644 --- a/journal-don-t-enable-systemd-journald-audit.socket-b.patch +++ b/journal-don-t-enable-systemd-journald-audit.socket-b.patch @@ -7,24 +7,9 @@ Subject: [PATCH] journal: don't enable systemd-journald-audit.socket Resolves: #1699287 --- - units/meson.build | 3 +-- units/systemd-journald.service.in | 2 +- - 2 files changed, 2 insertions(+), 3 deletions(-) + 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/units/meson.build b/units/meson.build -index e105ade..48c621d 100644 ---- a/units/meson.build -+++ b/units/meson.build -@@ -88,8 +88,7 @@ units = [ - 'sockets.target.wants/'], - ['systemd-journal-gatewayd.socket', 'ENABLE_REMOTE HAVE_MICROHTTPD'], - ['systemd-journal-remote.socket', 'ENABLE_REMOTE HAVE_MICROHTTPD'], -- ['systemd-journald-audit.socket', '', -- 'sockets.target.wants/'], -+ ['systemd-journald-audit.socket', ''], - ['systemd-journald-dev-log.socket', '', - 'sockets.target.wants/'], - ['systemd-journald.socket', '', diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in index 089bc38..7436619 100644 --- a/units/systemd-journald.service.in @@ -39,5 +24,5 @@ index 089bc38..7436619 100644 SystemCallArchitectures=native SystemCallErrorNumber=EPERM -- -2.23.0 +2.19.1 diff --git a/systemd.spec b/systemd.spec index e4bbaba..82ab381 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 28 +Release: 29 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -1139,6 +1139,7 @@ fi %{_unitdir}/multi-user.target.wants/systemd-update-utmp-runlevel.service %{_unitdir}/systemd-hostnamed.service.d/disable-privatedevices.conf %{_unitdir}/sockets.target.wants/systemd-coredump.socket +%{_unitdir}/sockets.target.wants/systemd-journald-audit.socket %{_unitdir}/sockets.target.wants/systemd-journald-dev-log.socket %{_unitdir}/sockets.target.wants/systemd-journald.socket %{_unitdir}/sockets.target.wants/systemd-initctl.socket @@ -1503,6 +1504,14 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon Dec 14 2020 shenyangyang - 243-29 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:revert don't enable systemd-journald-audit.socket by default + that may cause reboot problem if update systemd with out dracut -f + from LTS-20.03 + * Wed Nov 25 2020 shenyangyang - 243-28 - Type:enhancement - ID:NA -- Gitee From 5f8e8fb7c9d8baf533a4ec032d444f9ae4b23b9d Mon Sep 17 00:00:00 2001 From: Yangyang Shen Date: Wed, 16 Dec 2020 11:17:28 +0800 Subject: [PATCH 09/38] do not create /var/log/journal on initial installation --- systemd.spec | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/systemd.spec b/systemd.spec index 82ab381..08882f6 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 29 +Release: 30 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -576,12 +576,6 @@ systemctl daemon-reexec &>/dev/null || : journalctl --update-catalog &>/dev/null || : systemd-tmpfiles --create &>/dev/null || : -# create /var/log/journal only on initial installation, -# and only if it's writable (it won't be in rpm-ostree). -if [ $1 -eq 1 ] && [ -w %{_localstatedir} ]; then - mkdir -p %{_localstatedir}/log/journal -fi - # Make sure new journal files will be owned by the "systemd-journal" group machine_id=$(cat /etc/machine-id 2>/dev/null) chgrp systemd-journal /{run,var}/log/journal/{,${machine_id}} &>/dev/null || : @@ -1504,6 +1498,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Wed Dec 16 2020 shenyangyang - 243-30 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:do not create /var/log/journal on initial installation + * Mon Dec 14 2020 shenyangyang - 243-29 - Type:enhancement - ID:NA @@ -1953,7 +1953,7 @@ fi - Type:bugfix - ID:NA - SUG:restart -- DESC:do not create /var/log/journal on initial installation refer to redhat8 +- DESC:do not create /var/log/journal on initial installation * Sat Feb 02 2019 Yi Cang - 239-3.h3 - Type:enhance -- Gitee From f5e09308d150e55317accad6759435099bd0b617 Mon Sep 17 00:00:00 2001 From: Hexiaowen Date: Fri, 18 Dec 2020 10:13:11 +0800 Subject: [PATCH 10/38] Fix bug of memory offline udev rules in 40-openEuler.rules --- systemd.spec | 8 +++++++- udev-40-openEuler.rules | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/systemd.spec b/systemd.spec index 08882f6..26cab8d 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 30 +Release: 31 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -1498,6 +1498,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Fri Dec 18 2020 overweight - 243-31 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: fix 40-openEuler.rules for memory offline + * Wed Dec 16 2020 shenyangyang - 243-30 - Type:enhancement - ID:NA diff --git a/udev-40-openEuler.rules b/udev-40-openEuler.rules index ed85acb..dcf0ef0 100644 --- a/udev-40-openEuler.rules +++ b/udev-40-openEuler.rules @@ -4,7 +4,8 @@ SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1" # Memory hotadd request -SUBSYSTEM!="memory", ACTION!="add", GOTO="memory_hotplug_end" +SUBSYSTEM!="memory", GOTO="memory_hotplug_end" +ACTION!="add", GOTO="memory_hotplug_end" PROGRAM="/bin/uname -p", RESULT=="s390*", GOTO="memory_hotplug_end" ENV{.state}="online" -- Gitee From c967b63bf3d6eb5ab23c6867ee6fe19ab89c7db2 Mon Sep 17 00:00:00 2001 From: fangxiuning Date: Wed, 7 Apr 2021 11:18:40 +0800 Subject: [PATCH 11/38] modify --- ...rdata-pointer-inheritance-from-varli.patch | 84 +++++++++++++++++++ systemd.spec | 9 +- 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 backport-varlink-make-userdata-pointer-inheritance-from-varli.patch diff --git a/backport-varlink-make-userdata-pointer-inheritance-from-varli.patch b/backport-varlink-make-userdata-pointer-inheritance-from-varli.patch new file mode 100644 index 0000000..fd3e27c --- /dev/null +++ b/backport-varlink-make-userdata-pointer-inheritance-from-varli.patch @@ -0,0 +1,84 @@ +From 9807fdc1da8e037ddedfa4e2c6d2728b6e60051e Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 20 Jan 2021 19:15:55 +0100 +Subject: [PATCH] varlink: make 'userdata' pointer inheritance from varlink + server to connection optional + +@keszybz's right on +https://github.com/systemd/systemd/pull/18248#issuecomment-760798473: +swapping out the userdata pointer of a live varlink connection is iffy. + +Let's fix this by making the userdata inheritance from VarlinkServer +object to the Varlink connection object optional: we want it for most +cases, but not all, i.e. all those cases where the calls implemented as +varlink methods are stateless and can be answered synchronously. For the +other cases (i.e. where we want per-connection objects that wrap the +asynchronous operation as it goes on) let's not do such inheritance but +initialize the userdata pointer only once we have it. THis means the +original manager object must be manually retrieved from the +VarlinkServer object, which in turn needs to be requested from the +Varlink connection object. + +The userdata inheritance is now controlled by the +VARLINK_INHERIT_USERDATA flag passed at VarlinkServer construction. + +Alternative-to: #18248 + +--- + src/journal/journald-server.c | 2 +- + src/shared/varlink.c | 4 +++- + src/shared/varlink.h | 9 +++++---- + 3 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index a0c2dcd..7f3c7a9 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -1968,7 +1968,7 @@ static int server_open_varlink(Server *s) { + + assert(s); + +- r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY); ++ r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_INHERIT_USERDATA); + if (r < 0) + return r; + +diff --git a/src/shared/varlink.c b/src/shared/varlink.c +index 9934316..06fb0ab 100644 +--- a/src/shared/varlink.c ++++ b/src/shared/varlink.c +@@ -2035,7 +2035,9 @@ int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret) + return r; + + v->fd = fd; +- v->userdata = server->userdata; ++ if (server->flags & VARLINK_SERVER_INHERIT_USERDATA) ++ v->userdata = server->userdata; ++ + if (ucred_acquired) { + v->ucred = ucred; + v->ucred_acquired = true; +diff --git a/src/shared/varlink.h b/src/shared/varlink.h +index d96fa93..1284bc8 100644 +--- a/src/shared/varlink.h ++++ b/src/shared/varlink.h +@@ -41,11 +41,12 @@ typedef enum VarlinkMethodFlags { + } VarlinkMethodFlags; + + typedef enum VarlinkServerFlags { +- VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */ +- VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */ +- VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */ ++ VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */ ++ VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */ ++ VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */ ++ VARLINK_SERVER_INHERIT_USERDATA = 1 << 3, /* Initialize Varlink connection userdata from VarlinkServer userdata */ + +- _VARLINK_SERVER_FLAGS_ALL = (1 << 3) - 1, ++ _VARLINK_SERVER_FLAGS_ALL = (1 << 4) - 1, + } VarlinkServerFlags; + + typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata); +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index 26cab8d..c9308a4 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 31 +Release: 32 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -113,6 +113,7 @@ Patch0063: core-set-error-value-correctly.patch Patch0064: core-fix-re-realization-of-cgroup-siblings.patch Patch0065: basic-string-table-avoid-crash-when-table-is-sparse.patch Patch0066: journal-fix-buffer-overrun-when-urlifying.patch +Patch0067: backport-varlink-make-userdata-pointer-inheritance-from-varli.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1498,6 +1499,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Wed Apr 07 2021 fangxiuning - 243-32 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: fix userdate double free + * Fri Dec 18 2020 overweight - 243-31 - Type:bugfix - ID:NA -- Gitee From 432b764073995773bc88c396a8309a123da4bc96 Mon Sep 17 00:00:00 2001 From: fangxiuning Date: Fri, 21 May 2021 18:05:18 +0800 Subject: [PATCH 12/38] modify --- ...cached-credentials-of-stdout-streams.patch | 148 +++++++++++ ...-longer-line-length-limit-during-set.patch | 104 ++++++++ ...end-of-line-marker-handling-to-use-a.patch | 77 ++++++ ...-journald-rework-pid-change-handling.patch | 230 ++++++++++++++++++ systemd.spec | 12 +- 5 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 backport-journal-refresh-cached-credentials-of-stdout-streams.patch create mode 100644 backport-journald-enforce-longer-line-length-limit-during-set.patch create mode 100644 backport-journald-rework-end-of-line-marker-handling-to-use-a.patch create mode 100644 backport-journald-rework-pid-change-handling.patch diff --git a/backport-journal-refresh-cached-credentials-of-stdout-streams.patch b/backport-journal-refresh-cached-credentials-of-stdout-streams.patch new file mode 100644 index 0000000..195dda4 --- /dev/null +++ b/backport-journal-refresh-cached-credentials-of-stdout-streams.patch @@ -0,0 +1,148 @@ +From 09d0b46ab61bebafe5bdc1be95ee153dfb13d6bc Mon Sep 17 00:00:00 2001 +From: Lorenz Bauer +Date: Mon, 4 Nov 2019 16:35:46 +0000 +Subject: [PATCH] journal: refresh cached credentials of stdout streams + +journald assumes that getsockopt(SO_PEERCRED) correctly identifies the +process on the remote end of the socket. However, this is incorrect +according to man 7 socket: + +The returned credentials are those that were in effect at the + time of the call to connect(2) or socketpair(2). + +This becomes a problem when a new process inherits the stdout stream +from a parent. First, log messages from the child process will +be attributed to the parent. Second, the struct ucred used by journald +becomes invalid as soon as the parent exits. Further sendmsg calls then +fail with ENOENT. Logs for the child process then vanish from the journal. + +Fix this by using recvmsg on the stdout stream, and refreshing the cached +struct ucred if SCM_CREDENTIALS indicate a new process. + +Fixes #13708 +--- + src/journal/journald-stream.c | 49 ++++++++++++++++++++++++++++++++++-- + test/TEST-04-JOURNAL/test-journal.sh | 16 ++++++++++++ + 2 files changed, 63 insertions(+), 2 deletions(-) + +diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c +index afebade..22a70ce 100644 +--- a/src/journal/journald-stream.c ++++ b/src/journal/journald-stream.c +@@ -487,11 +487,22 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) { + } + + static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { ++ uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; + StdoutStream *s = userdata; ++ struct ucred *ucred = NULL; ++ struct cmsghdr *cmsg; ++ struct iovec iovec; + size_t limit; + ssize_t l; + int r; + ++ struct msghdr msghdr = { ++ .msg_iov = &iovec, ++ .msg_iovlen = 1, ++ .msg_control = buf, ++ .msg_controllen = sizeof(buf), ++ }; ++ + assert(s); + + if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) { +@@ -511,20 +522,50 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + * always leave room for a terminating NUL we might need to add. */ + limit = MIN(s->allocated - 1, s->server->line_max); + +- l = read(s->fd, s->buffer + s->length, limit - s->length); ++ iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length); ++ ++ l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (l < 0) { +- if (errno == EAGAIN) ++ if (IN_SET(errno, EINTR, EAGAIN)) + return 0; + + log_warning_errno(errno, "Failed to read from stream: %m"); + goto terminate; + } ++ cmsg_close_all(&msghdr); + + if (l == 0) { + stdout_stream_scan(s, true); + goto terminate; + } + ++ CMSG_FOREACH(cmsg, &msghdr) ++ if (cmsg->cmsg_level == SOL_SOCKET && ++ cmsg->cmsg_type == SCM_CREDENTIALS && ++ cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { ++ ucred = (struct ucred *)CMSG_DATA(cmsg); ++ break; ++ } ++ ++ /* Invalidate the context if the pid of the sender changed. ++ * This happens when a forked process inherits stdout / stderr ++ * from a parent. In this case getpeercred returns the ucred ++ * of the parent, which can be invalid if the parent has exited ++ * in the meantime. ++ */ ++ if (ucred && ucred->pid != s->ucred.pid) { ++ /* force out any previously half-written lines from a ++ * different process, before we switch to the new ucred ++ * structure for everything we just added */ ++ r = stdout_stream_scan(s, true); ++ if (r < 0) ++ goto terminate; ++ ++ s->ucred = *ucred; ++ client_context_release(s->server, s->context); ++ s->context = NULL; ++ } ++ + s->length += l; + r = stdout_stream_scan(s, false); + if (r < 0) +@@ -562,6 +603,10 @@ int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { + if (r < 0) + return log_error_errno(r, "Failed to determine peer credentials: %m"); + ++ r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true); ++ if (r < 0) ++ return log_error_errno(r, "SO_PASSCRED failed: %m"); ++ + if (mac_selinux_use()) { + r = getpeersec(fd, &stream->label); + if (r < 0 && r != -EOPNOTSUPP) +diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh +index 4e539aa..de27eb0 100755 +--- a/test/TEST-04-JOURNAL/test-journal.sh ++++ b/test/TEST-04-JOURNAL/test-journal.sh +@@ -74,6 +74,22 @@ cmp /expected /output + { journalctl -ball -b -m 2>&1 || :; } | head -1 > /output + cmp /expected /output + ++# https://github.com/systemd/systemd/issues/13708 ++ID=$(systemd-id128 new) ++systemd-cat -t "$ID" bash -c 'echo parent; (echo child) & wait' & ++PID=$! ++wait %% ++journalctl --sync ++# We can drop this grep when https://github.com/systemd/systemd/issues/13937 ++# has a fix. ++journalctl -b -o export -t "$ID" --output-fields=_PID | grep '^_PID=' >/output ++[[ `grep -c . /output` -eq 2 ]] ++grep -q "^_PID=$PID" /output ++grep -vq "^_PID=$PID" /output ++ ++# Add new tests before here, the journald restarts below ++# may make tests flappy. ++ + # Don't lose streams on restart + systemctl start forever-print-hola + sleep 3 +-- +1.8.3.1 + diff --git a/backport-journald-enforce-longer-line-length-limit-during-set.patch b/backport-journald-enforce-longer-line-length-limit-during-set.patch new file mode 100644 index 0000000..71aeae5 --- /dev/null +++ b/backport-journald-enforce-longer-line-length-limit-during-set.patch @@ -0,0 +1,104 @@ +From 4e071b5240a29842bc8acd0d7eb0b797f2812b8b Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Fri, 21 May 2021 17:55:38 +0800 +Subject: [PATCH] change + +--- + src/journal/journald-stream.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c +index 3219b14..fda75fb 100644 +--- a/src/journal/journald-stream.c ++++ b/src/journal/journald-stream.c +@@ -38,6 +38,12 @@ + + #define STDOUT_STREAMS_MAX 4096 + ++/* During the "setup" protocol phase of the stream logic let's define a different maximum line length than ++ * during the actual operational phase. We want to allow users to specify very short line lengths after all, ++ * but the unit name we embed in the setup protocol might be longer than that. Hence, during the setup phase ++ * let's enforce a line length matching the maximum unit name length (255) */ ++#define STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX (UNIT_NAME_MAX-1U) ++ + typedef enum StdoutStreamState { + STDOUT_STREAM_IDENTIFIER, + STDOUT_STREAM_UNIT_ID, +@@ -46,7 +52,7 @@ typedef enum StdoutStreamState { + STDOUT_STREAM_FORWARD_TO_SYSLOG, + STDOUT_STREAM_FORWARD_TO_KMSG, + STDOUT_STREAM_FORWARD_TO_CONSOLE, +- STDOUT_STREAM_RUNNING ++ STDOUT_STREAM_RUNNING, + } StdoutStreamState; + + /* The different types of log record terminators: a real \n was read, a NUL character was read, the maximum line length +@@ -457,6 +463,18 @@ static int stdout_stream_found( + return r; + } + ++static size_t stdout_stream_line_max(StdoutStream *s) { ++ assert(s); ++ ++ /* During the "setup" phase of our protocol, let's ensure we use a line length where a full unit name ++ * can fit in */ ++ if (s->state != STDOUT_STREAM_RUNNING) ++ return STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX; ++ ++ /* After the protocol's "setup" phase is complete, let's use whatever the user configured */ ++ return s->server->line_max; ++} ++ + static int stdout_stream_scan( + StdoutStream *s, + char *p, +@@ -464,19 +482,22 @@ static int stdout_stream_scan( + LineBreak force_flush, + size_t *ret_consumed) { + +- size_t consumed = 0; ++ size_t consumed = 0, line_max; + int r; + + assert(s); + assert(p); + ++ line_max = stdout_stream_line_max(s); ++ + for (;;) { + LineBreak line_break; + size_t skip, found; + char *end1, *end2; ++ size_t tmp_remaining = MIN(remaining, line_max); + +- end1 = memchr(p, '\n', remaining); +- end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : remaining); ++ end1 = memchr(p, '\n', tmp_remaining); ++ end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : tmp_remaining); + + if (end2) { + /* We found a NUL terminator */ +@@ -488,9 +509,9 @@ static int stdout_stream_scan( + found = end1 - p; + skip = found + 1; + line_break = LINE_BREAK_NEWLINE; +- } else if (remaining >= s->server->line_max) { ++ } else if (remaining >= line_max) { + /* Force a line break after the maximum line length */ +- found = skip = s->server->line_max; ++ found = skip = line_max; + line_break = LINE_BREAK_LINE_MAX; + } else + break; +@@ -553,7 +574,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + + /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, + * always leave room for a terminating NUL we might need to add. */ +- limit = MIN(s->allocated - 1, s->server->line_max); ++ limit = MIN(s->allocated - 1, MAX(s->server->line_max, STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX)); + assert(s->length <= limit); + iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length); + +-- +1.8.3.1 + diff --git a/backport-journald-rework-end-of-line-marker-handling-to-use-a.patch b/backport-journald-rework-end-of-line-marker-handling-to-use-a.patch new file mode 100644 index 0000000..c365959 --- /dev/null +++ b/backport-journald-rework-end-of-line-marker-handling-to-use-a.patch @@ -0,0 +1,77 @@ +From 549b7379ba404c33fd448d2bca46a57f6529b00b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 12 May 2020 18:53:35 +0200 +Subject: [PATCH] journald: rework end of line marker handling to use a field + table + +--- + src/journal/journald-stream.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c +index 22a70ce..b86ed78 100644 +--- a/src/journal/journald-stream.c ++++ b/src/journal/journald-stream.c +@@ -57,6 +57,8 @@ typedef enum LineBreak { + LINE_BREAK_NUL, + LINE_BREAK_LINE_MAX, + LINE_BREAK_EOF, ++ _LINE_BREAK_MAX, ++ _LINE_BREAK_INVALID = -1, + } LineBreak; + + struct StdoutStream { +@@ -236,7 +238,11 @@ fail: + return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file); + } + +-static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_break) { ++static int stdout_stream_log( ++ StdoutStream *s, ++ const char *p, ++ LineBreak line_break) { ++ + struct iovec *iovec; + int priority; + char syslog_priority[] = "PRIORITY=\0"; +@@ -248,6 +254,9 @@ static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_brea + assert(s); + assert(p); + ++ assert(line_break >= 0); ++ assert(line_break < _LINE_BREAK_MAX); ++ + if (s->context) + (void) client_context_maybe_refresh(s->server, s->context, NULL, NULL, 0, NULL, USEC_INFINITY); + else if (pid_is_valid(s->ucred.pid)) { +@@ -299,17 +308,19 @@ static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_brea + iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier); + } + +- if (line_break != LINE_BREAK_NEWLINE) { +- const char *c; ++ static const char * const line_break_field_table[_LINE_BREAK_MAX] = { ++ [LINE_BREAK_NEWLINE] = NULL, /* Do not add field if traditional newline */ ++ [LINE_BREAK_NUL] = "_LINE_BREAK=nul", ++ [LINE_BREAK_LINE_MAX] = "_LINE_BREAK=line-max", ++ [LINE_BREAK_EOF] = "_LINE_BREAK=eof", ++ }; + +- /* If this log message was generated due to an uncommon line break then mention this in the log +- * entry */ ++ const char *c = line_break_field_table[line_break]; + +- c = line_break == LINE_BREAK_NUL ? "_LINE_BREAK=nul" : +- line_break == LINE_BREAK_LINE_MAX ? "_LINE_BREAK=line-max" : +- "_LINE_BREAK=eof"; ++ /* If this log message was generated due to an uncommon line break then mention this in the log ++ * entry */ ++ if (c) + iovec[n++] = IOVEC_MAKE_STRING(c); +- } + + message = strjoin("MESSAGE=", p); + if (message) +-- +1.8.3.1 + diff --git a/backport-journald-rework-pid-change-handling.patch b/backport-journald-rework-pid-change-handling.patch new file mode 100644 index 0000000..b8edce4 --- /dev/null +++ b/backport-journald-rework-pid-change-handling.patch @@ -0,0 +1,230 @@ +From 45ba1ea5e9264d385fa565328fe957ef1d78caa1 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 12 May 2020 18:56:34 +0200 +Subject: [PATCH] journald: rework pid change handling + +Let's introduce an explicit line ending marker for line endings due to +pid change. + +Let's also make sure we don't get confused with buffer management. + +Fixes: #15654 +--- + src/journal/journald-stream.c | 108 +++++++++++++++++++++++++++--------------- + 1 file changed, 69 insertions(+), 39 deletions(-) + +diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c +index b86ed78..3219b14 100644 +--- a/src/journal/journald-stream.c ++++ b/src/journal/journald-stream.c +@@ -57,6 +57,7 @@ typedef enum LineBreak { + LINE_BREAK_NUL, + LINE_BREAK_LINE_MAX, + LINE_BREAK_EOF, ++ LINE_BREAK_PID_CHANGE, + _LINE_BREAK_MAX, + _LINE_BREAK_INVALID = -1, + } LineBreak; +@@ -313,6 +314,7 @@ static int stdout_stream_log( + [LINE_BREAK_NUL] = "_LINE_BREAK=nul", + [LINE_BREAK_LINE_MAX] = "_LINE_BREAK=line-max", + [LINE_BREAK_EOF] = "_LINE_BREAK=eof", ++ [LINE_BREAK_PID_CHANGE] = "_LINE_BREAK=pid-change", + }; + + const char *c = line_break_field_table[line_break]; +@@ -434,21 +436,43 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { + assert_not_reached("Unknown stream state"); + } + +-static int stdout_stream_scan(StdoutStream *s, bool force_flush) { +- char *p; +- size_t remaining; ++static int stdout_stream_found( ++ StdoutStream *s, ++ char *p, ++ size_t l, ++ LineBreak line_break) { ++ ++ char saved; + int r; + + assert(s); ++ assert(p); ++ ++ /* Let's NUL terminate the specified buffer for this call, and revert back afterwards */ ++ saved = p[l]; ++ p[l] = 0; ++ r = stdout_stream_line(s, p, line_break); ++ p[l] = saved; + +- p = s->buffer; +- remaining = s->length; ++ return r; ++} ++ ++static int stdout_stream_scan( ++ StdoutStream *s, ++ char *p, ++ size_t remaining, ++ LineBreak force_flush, ++ size_t *ret_consumed) { + +- /* XXX: This function does nothing if (s->length == 0) */ ++ size_t consumed = 0; ++ int r; ++ ++ assert(s); ++ assert(p); + + for (;;) { + LineBreak line_break; +- size_t skip; ++ size_t skip, found; + char *end1, *end2; + + end1 = memchr(p, '\n', remaining); +@@ -456,43 +480,40 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) { + + if (end2) { + /* We found a NUL terminator */ +- skip = end2 - p + 1; ++ found = end2 - p; ++ skip = found + 1; + line_break = LINE_BREAK_NUL; + } else if (end1) { + /* We found a \n terminator */ +- *end1 = 0; +- skip = end1 - p + 1; ++ found = end1 - p; ++ skip = found + 1; + line_break = LINE_BREAK_NEWLINE; + } else if (remaining >= s->server->line_max) { + /* Force a line break after the maximum line length */ +- *(p + s->server->line_max) = 0; +- skip = remaining; ++ found = skip = s->server->line_max; + line_break = LINE_BREAK_LINE_MAX; + } else + break; + +- r = stdout_stream_line(s, p, line_break); ++ r = stdout_stream_found(s, p, found, line_break); + if (r < 0) + return r; + +- remaining -= skip; + p += skip; ++ consumed += skip; ++ remaining -= skip; + } + +- if (force_flush && remaining > 0) { +- p[remaining] = 0; +- r = stdout_stream_line(s, p, LINE_BREAK_EOF); ++ if (force_flush >= 0 && remaining > 0) { ++ r = stdout_stream_found(s, p, remaining, force_flush); + if (r < 0) + return r; + +- p += remaining; +- remaining = 0; ++ consumed += remaining; + } + +- if (p > s->buffer) { +- memmove(s->buffer, p, remaining); +- s->length = remaining; +- } ++ if (ret_consumed) ++ *ret_consumed = consumed; + + return 0; + } +@@ -500,11 +521,12 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) { + static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; + StdoutStream *s = userdata; ++ size_t limit, consumed; + struct ucred *ucred = NULL; + struct cmsghdr *cmsg; + struct iovec iovec; +- size_t limit; + ssize_t l; ++ char *p; + int r; + + struct msghdr msghdr = { +@@ -532,7 +554,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, + * always leave room for a terminating NUL we might need to add. */ + limit = MIN(s->allocated - 1, s->server->line_max); +- ++ assert(s->length <= limit); + iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length); + + l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); +@@ -546,7 +568,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + cmsg_close_all(&msghdr); + + if (l == 0) { +- stdout_stream_scan(s, true); ++ (void) stdout_stream_scan(s, s->buffer, s->length, /* force_flush = */ LINE_BREAK_EOF, NULL); + goto terminate; + } + +@@ -558,30 +580,38 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + break; + } + +- /* Invalidate the context if the pid of the sender changed. +- * This happens when a forked process inherits stdout / stderr +- * from a parent. In this case getpeercred returns the ucred +- * of the parent, which can be invalid if the parent has exited +- * in the meantime. +- */ ++ /* Invalidate the context if the PID of the sender changed. This happens when a forked process ++ * inherits stdout/stderr from a parent. In this case getpeercred() returns the ucred of the parent, ++ * which can be invalid if the parent has exited in the meantime. */ + if (ucred && ucred->pid != s->ucred.pid) { +- /* force out any previously half-written lines from a ++ /* Force out any previously half-written lines from a + * different process, before we switch to the new ucred + * structure for everything we just added */ +- r = stdout_stream_scan(s, true); ++ r = stdout_stream_scan(s, s->buffer, s->length, /* force_flush = */ LINE_BREAK_PID_CHANGE, NULL); + if (r < 0) + goto terminate; + +- s->ucred = *ucred; +- client_context_release(s->server, s->context); +- s->context = NULL; ++ s->context = client_context_release(s->server, s->context); ++ ++ p = s->buffer + s->length; ++ } else { ++ p = s->buffer; ++ l += s->length; + } + +- s->length += l; +- r = stdout_stream_scan(s, false); ++ /* Always copy in the new credentials */ ++ if (ucred) ++ s->ucred = *ucred; ++ ++ r = stdout_stream_scan(s, p, l, _LINE_BREAK_INVALID, &consumed); + if (r < 0) + goto terminate; + ++ /* Move what wasn't consumed to the front of the buffer */ ++ assert(consumed <= (size_t) l); ++ s->length = l - consumed; ++ memmove(s->buffer, p + consumed, s->length); ++ + return 1; + + terminate: +-- +1.8.3.1 + diff --git a/systemd.spec b/systemd.spec index c9308a4..99f5582 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 32 +Release: 33 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -114,6 +114,10 @@ Patch0064: core-fix-re-realization-of-cgroup-siblings.patch Patch0065: basic-string-table-avoid-crash-when-table-is-sparse.patch Patch0066: journal-fix-buffer-overrun-when-urlifying.patch Patch0067: backport-varlink-make-userdata-pointer-inheritance-from-varli.patch +Patch0068: backport-journal-refresh-cached-credentials-of-stdout-streams.patch +Patch0069: backport-journald-rework-end-of-line-marker-handling-to-use-a.patch +Patch0070: backport-journald-rework-pid-change-handling.patch +Patch0071: backport-journald-enforce-longer-line-length-limit-during-set.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1499,6 +1503,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Fri May 21 2021 fangxiuning - 243-33 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: journald: enforce longer line length limit during "setup" phase of stream protocol + * Wed Apr 07 2021 fangxiuning - 243-32 - Type:bugfix - ID:NA -- Gitee From e4ffca3f362ecbe5e969dfe2e40808c772ab2c85 Mon Sep 17 00:00:00 2001 From: overweight Date: Mon, 31 May 2021 02:23:16 -0400 Subject: [PATCH 13/38] fix patches name and patches num --- ...error-caused-by-device-disconnection.patch | 0 ...-parameter-of-get_name_owner_handler.patch | 0 ...re-dont-check-potentially-NULL-error.patch | 0 ...=> 0005-0001-core-shorten-code-a-bit.patch | 0 ...06-0001-core-no-need-to-eat-up-error.patch | 0 ...-unit-bus-name-slots-always-together.patch | 0 ...initial-ListNames-bus-call-from-PID1.patch | 0 ...-rtc-with-system-clock-when-shutdown.patch | 0 ...dd-actions-while-rename-netif-failed.patch | 0 ...1712-1.patch => 0011-CVE-2020-1712-1.patch | 0 ...1712-2.patch => 0012-CVE-2020-1712-2.patch | 0 ...1712-3.patch => 0013-CVE-2020-1712-3.patch | 0 ...1712-4.patch => 0014-CVE-2020-1712-4.patch | 0 ...1712-5.patch => 0015-CVE-2020-1712-5.patch | 0 ...-journal-files-that-were-deleted-by-.patch | 0 ...tTasksMax-to-80-of-the-kernel-pid.ma.patch | 0 ...rtual-machines-have-same-mac-address.patch | 0 ...nd-set-RemoveIPC-to-false-by-default.patch | 0 ...or-naming-Dell-iDRAC-USB-Virtual-NIC.patch | 0 ...nit-don-t-add-Requires-for-tmp.mount.patch | 0 ...switch-net.ipv4.conf.all.rp_filter-f.patch | 0 ...evator-kernel-command-line-parameter.patch | 0 ...le-that-adds-elevator-kernel-command.patch | 0 ...its-add-Install-section-to-tmp.mount.patch | 0 ...vd.service-start-after-systemd-remou.patch | 0 ...patch => 0027-udev-virsh-shutdown-vm.patch | 0 ...8-fix-fd-leak-in-no-memory-condition.patch | 0 ...0029-dbus-execute-avoid-extra-strdup.patch | 0 ...mounted-as-tmpfs-without-the-user-s-.patch | 0 ...d-bus-properly-initialize-containers.patch | 0 ...step-back-again-for-nspawn-we-actual.patch | 0 ...able-systemd-journald-audit.socket-b.patch | 0 ...drop-unit-caches-only-based-on-mtime.patch | 0 ...dd-unit-files-to-dump-the-unit-fragm.patch | 0 ...id1-use-a-cache-for-all-unit-aliases.patch | 0 ...it-file-add-a-function-to-validate-u.patch | 0 ...tl-crash-on-aarch64-when-setting-out.patch | 0 ...prehensive-protection-against-libsec.patch | 0 ...le-free-in-macsec_receive_channel_fr.patch | 0 ...patch => 0041-network-L2TP-fix-crash.patch | 0 ...memleak-caused-by-wrong-cleanup-func.patch | 0 ...ch => 0043-analyze-fix-minor-memleak.patch | 0 ...k-add-one-more-section-validty-check.patch | 0 ...etwork-use-fix-invalid-free-function.patch | 0 ...ak.patch => 0046-network-fix-memleak.patch | 0 ...k-Add-support-to-advertie-ipv6-route.patch | 0 ...network-fix-invalid-cleanup-function.patch | 0 ...ork-fix-memleak-in-route_prefix_free.patch | 0 ...ak.patch => 0050-sd-radv-fix-memleak.patch | 0 ...validate-connection-when-Hello-fails.patch | 0 ...-bus-util-Don-t-replace-exsting-strv.patch | 0 ...systemctl-Add-with-dependencies-flag.patch | 0 ...t-systemctl-with-dependencies-switch.patch | 0 ...-priority-value-via-dbus-only-if-it-.patch | 0 ...we-forgot-to-destroy-some-bus-errors.patch | 0 ...spection-bug-in-signal-parameter-nam.patch | 0 ...pParseFlags-between-dbus-execute-and.patch | 0 ...9-core-swap-priority-can-be-negative.patch | 0 ...initialize-swap-structure-fields-if-.patch | 0 ...priority_set-when-parsing-swap-unit-.patch | 0 ...sed-logging-instead-of-generic-loggi.patch | 0 ... 0063-core-set-error-value-correctly.patch | 0 ...ix-re-realization-of-cgroup-siblings.patch | 0 ...ble-avoid-crash-when-table-is-sparse.patch | 0 ...al-fix-buffer-overrun-when-urlifying.patch | 0 ...rdata-pointer-inheritance-from-varli.patch | 0 ...cached-credentials-of-stdout-streams.patch | 0 ...end-of-line-marker-handling-to-use-a.patch | 0 ...-journald-rework-pid-change-handling.patch | 0 ...-longer-line-length-limit-during-set.patch | 0 systemd.spec | 151 +++++++++--------- 71 files changed, 77 insertions(+), 74 deletions(-) rename 0001-udev-ignore-error-caused-by-device-disconnection.patch => 0002-0001-udev-ignore-error-caused-by-device-disconnection.patch (100%) rename 0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch => 0003-0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch (100%) rename 0001-core-dont-check-potentially-NULL-error.patch => 0004-0001-core-dont-check-potentially-NULL-error.patch (100%) rename 0001-core-shorten-code-a-bit.patch => 0005-0001-core-shorten-code-a-bit.patch (100%) rename 0001-core-no-need-to-eat-up-error.patch => 0006-0001-core-no-need-to-eat-up-error.patch (100%) rename 0001-core-create-or-remove-unit-bus-name-slots-always-together.patch => 0007-0001-core-create-or-remove-unit-bus-name-slots-always-together.patch (100%) rename 0001-core-drop-initial-ListNames-bus-call-from-PID1.patch => 0008-0001-core-drop-initial-ListNames-bus-call-from-PID1.patch (100%) rename 1605-update-rtc-with-system-clock-when-shutdown.patch => 0009-1605-update-rtc-with-system-clock-when-shutdown.patch (100%) rename 1603-udev-add-actions-while-rename-netif-failed.patch => 0010-1603-udev-add-actions-while-rename-netif-failed.patch (100%) rename CVE-2020-1712-1.patch => 0011-CVE-2020-1712-1.patch (100%) rename CVE-2020-1712-2.patch => 0012-CVE-2020-1712-2.patch (100%) rename CVE-2020-1712-3.patch => 0013-CVE-2020-1712-3.patch (100%) rename CVE-2020-1712-4.patch => 0014-CVE-2020-1712-4.patch (100%) rename CVE-2020-1712-5.patch => 0015-CVE-2020-1712-5.patch (100%) rename sd-journal-close-journal-files-that-were-deleted-by-.patch => 0016-sd-journal-close-journal-files-that-were-deleted-by-.patch (100%) rename pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch => 0017-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch (100%) rename fix-two-VF-virtual-machines-have-same-mac-address.patch => 0018-fix-two-VF-virtual-machines-have-same-mac-address.patch (100%) rename logind-set-RemoveIPC-to-false-by-default.patch => 0019-logind-set-RemoveIPC-to-false-by-default.patch (100%) rename rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch => 0020-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch (100%) rename unit-don-t-add-Requires-for-tmp.mount.patch => 0021-unit-don-t-add-Requires-for-tmp.mount.patch (100%) rename Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch => 0022-Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch (100%) rename rules-add-elevator-kernel-command-line-parameter.patch => 0023-rules-add-elevator-kernel-command-line-parameter.patch (100%) rename rules-add-the-rule-that-adds-elevator-kernel-command.patch => 0024-rules-add-the-rule-that-adds-elevator-kernel-command.patch (100%) rename units-add-Install-section-to-tmp.mount.patch => 0025-units-add-Install-section-to-tmp.mount.patch (100%) rename Make-systemd-udevd.service-start-after-systemd-remou.patch => 0026-Make-systemd-udevd.service-start-after-systemd-remou.patch (100%) rename udev-virsh-shutdown-vm.patch => 0027-udev-virsh-shutdown-vm.patch (100%) rename fix-fd-leak-in-no-memory-condition.patch => 0028-fix-fd-leak-in-no-memory-condition.patch (100%) rename dbus-execute-avoid-extra-strdup.patch => 0029-dbus-execute-avoid-extra-strdup.patch (100%) rename Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch => 0030-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch (100%) rename sd-bus-properly-initialize-containers.patch => 0031-sd-bus-properly-initialize-containers.patch (100%) rename Revert-core-one-step-back-again-for-nspawn-we-actual.patch => 0032-Revert-core-one-step-back-again-for-nspawn-we-actual.patch (100%) rename journal-don-t-enable-systemd-journald-audit.socket-b.patch => 0033-journal-don-t-enable-systemd-journald-audit.socket-b.patch (100%) rename revert-pid1-drop-unit-caches-only-based-on-mtime.patch => 0034-revert-pid1-drop-unit-caches-only-based-on-mtime.patch (100%) rename revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch => 0035-revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch (100%) rename revert-pid1-use-a-cache-for-all-unit-aliases.patch => 0036-revert-pid1-use-a-cache-for-all-unit-aliases.patch (100%) rename revert-shared-unit-file-add-a-function-to-validate-u.patch => 0037-revert-shared-unit-file-add-a-function-to-validate-u.patch (100%) rename systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch => 0038-systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch (100%) rename seccomp-more-comprehensive-protection-against-libsec.patch => 0039-seccomp-more-comprehensive-protection-against-libsec.patch (100%) rename network-fix-double-free-in-macsec_receive_channel_fr.patch => 0040-network-fix-double-free-in-macsec_receive_channel_fr.patch (100%) rename network-L2TP-fix-crash.patch => 0041-network-L2TP-fix-crash.patch (100%) rename systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch => 0042-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch (100%) rename analyze-fix-minor-memleak.patch => 0043-analyze-fix-minor-memleak.patch (100%) rename network-add-one-more-section-validty-check.patch => 0044-network-add-one-more-section-validty-check.patch (100%) rename network-use-fix-invalid-free-function.patch => 0045-network-use-fix-invalid-free-function.patch (100%) rename network-fix-memleak.patch => 0046-network-fix-memleak.patch (100%) rename network-Add-support-to-advertie-ipv6-route.patch => 0047-network-Add-support-to-advertie-ipv6-route.patch (100%) rename network-fix-invalid-cleanup-function.patch => 0048-network-fix-invalid-cleanup-function.patch (100%) rename network-fix-memleak-in-route_prefix_free.patch => 0049-network-fix-memleak-in-route_prefix_free.patch (100%) rename sd-radv-fix-memleak.patch => 0050-sd-radv-fix-memleak.patch (100%) rename sd-bus-invalidate-connection-when-Hello-fails.patch => 0051-sd-bus-invalidate-connection-when-Hello-fails.patch (100%) rename shared-bus-util-Don-t-replace-exsting-strv.patch => 0052-shared-bus-util-Don-t-replace-exsting-strv.patch (100%) rename systemctl-Add-with-dependencies-flag.patch => 0053-systemctl-Add-with-dependencies-flag.patch (100%) rename man-Document-systemctl-with-dependencies-switch.patch => 0054-man-Document-systemctl-with-dependencies-switch.patch (100%) rename core-expose-swap-priority-value-via-dbus-only-if-it-.patch => 0055-core-expose-swap-priority-value-via-dbus-only-if-it-.patch (100%) rename tree-wide-we-forgot-to-destroy-some-bus-errors.patch => 0056-tree-wide-we-forgot-to-destroy-some-bus-errors.patch (100%) rename sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch => 0057-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch (100%) rename core-sync-SeccompParseFlags-between-dbus-execute-and.patch => 0058-core-sync-SeccompParseFlags-between-dbus-execute-and.patch (100%) rename core-swap-priority-can-be-negative.patch => 0059-core-swap-priority-can-be-negative.patch (100%) rename core-no-need-to-initialize-swap-structure-fields-if-.patch => 0060-core-no-need-to-initialize-swap-structure-fields-if-.patch (100%) rename core-initialize-priority_set-when-parsing-swap-unit-.patch => 0061-core-initialize-priority_set-when-parsing-swap-unit-.patch (100%) rename core-use-unit-based-logging-instead-of-generic-loggi.patch => 0062-core-use-unit-based-logging-instead-of-generic-loggi.patch (100%) rename core-set-error-value-correctly.patch => 0063-core-set-error-value-correctly.patch (100%) rename core-fix-re-realization-of-cgroup-siblings.patch => 0064-core-fix-re-realization-of-cgroup-siblings.patch (100%) rename basic-string-table-avoid-crash-when-table-is-sparse.patch => 0065-basic-string-table-avoid-crash-when-table-is-sparse.patch (100%) rename journal-fix-buffer-overrun-when-urlifying.patch => 0066-journal-fix-buffer-overrun-when-urlifying.patch (100%) rename backport-varlink-make-userdata-pointer-inheritance-from-varli.patch => 0067-backport-varlink-make-userdata-pointer-inheritance-from-varli.patch (100%) rename backport-journal-refresh-cached-credentials-of-stdout-streams.patch => 0068-backport-journal-refresh-cached-credentials-of-stdout-streams.patch (100%) rename backport-journald-rework-end-of-line-marker-handling-to-use-a.patch => 0069-backport-journald-rework-end-of-line-marker-handling-to-use-a.patch (100%) rename backport-journald-rework-pid-change-handling.patch => 0070-backport-journald-rework-pid-change-handling.patch (100%) rename backport-journald-enforce-longer-line-length-limit-during-set.patch => 0071-backport-journald-enforce-longer-line-length-limit-during-set.patch (100%) diff --git a/0001-udev-ignore-error-caused-by-device-disconnection.patch b/0002-0001-udev-ignore-error-caused-by-device-disconnection.patch similarity index 100% rename from 0001-udev-ignore-error-caused-by-device-disconnection.patch rename to 0002-0001-udev-ignore-error-caused-by-device-disconnection.patch diff --git a/0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch b/0003-0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch similarity index 100% rename from 0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch rename to 0003-0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch diff --git a/0001-core-dont-check-potentially-NULL-error.patch b/0004-0001-core-dont-check-potentially-NULL-error.patch similarity index 100% rename from 0001-core-dont-check-potentially-NULL-error.patch rename to 0004-0001-core-dont-check-potentially-NULL-error.patch diff --git a/0001-core-shorten-code-a-bit.patch b/0005-0001-core-shorten-code-a-bit.patch similarity index 100% rename from 0001-core-shorten-code-a-bit.patch rename to 0005-0001-core-shorten-code-a-bit.patch diff --git a/0001-core-no-need-to-eat-up-error.patch b/0006-0001-core-no-need-to-eat-up-error.patch similarity index 100% rename from 0001-core-no-need-to-eat-up-error.patch rename to 0006-0001-core-no-need-to-eat-up-error.patch diff --git a/0001-core-create-or-remove-unit-bus-name-slots-always-together.patch b/0007-0001-core-create-or-remove-unit-bus-name-slots-always-together.patch similarity index 100% rename from 0001-core-create-or-remove-unit-bus-name-slots-always-together.patch rename to 0007-0001-core-create-or-remove-unit-bus-name-slots-always-together.patch diff --git a/0001-core-drop-initial-ListNames-bus-call-from-PID1.patch b/0008-0001-core-drop-initial-ListNames-bus-call-from-PID1.patch similarity index 100% rename from 0001-core-drop-initial-ListNames-bus-call-from-PID1.patch rename to 0008-0001-core-drop-initial-ListNames-bus-call-from-PID1.patch diff --git a/1605-update-rtc-with-system-clock-when-shutdown.patch b/0009-1605-update-rtc-with-system-clock-when-shutdown.patch similarity index 100% rename from 1605-update-rtc-with-system-clock-when-shutdown.patch rename to 0009-1605-update-rtc-with-system-clock-when-shutdown.patch diff --git a/1603-udev-add-actions-while-rename-netif-failed.patch b/0010-1603-udev-add-actions-while-rename-netif-failed.patch similarity index 100% rename from 1603-udev-add-actions-while-rename-netif-failed.patch rename to 0010-1603-udev-add-actions-while-rename-netif-failed.patch diff --git a/CVE-2020-1712-1.patch b/0011-CVE-2020-1712-1.patch similarity index 100% rename from CVE-2020-1712-1.patch rename to 0011-CVE-2020-1712-1.patch diff --git a/CVE-2020-1712-2.patch b/0012-CVE-2020-1712-2.patch similarity index 100% rename from CVE-2020-1712-2.patch rename to 0012-CVE-2020-1712-2.patch diff --git a/CVE-2020-1712-3.patch b/0013-CVE-2020-1712-3.patch similarity index 100% rename from CVE-2020-1712-3.patch rename to 0013-CVE-2020-1712-3.patch diff --git a/CVE-2020-1712-4.patch b/0014-CVE-2020-1712-4.patch similarity index 100% rename from CVE-2020-1712-4.patch rename to 0014-CVE-2020-1712-4.patch diff --git a/CVE-2020-1712-5.patch b/0015-CVE-2020-1712-5.patch similarity index 100% rename from CVE-2020-1712-5.patch rename to 0015-CVE-2020-1712-5.patch diff --git a/sd-journal-close-journal-files-that-were-deleted-by-.patch b/0016-sd-journal-close-journal-files-that-were-deleted-by-.patch similarity index 100% rename from sd-journal-close-journal-files-that-were-deleted-by-.patch rename to 0016-sd-journal-close-journal-files-that-were-deleted-by-.patch diff --git a/pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch b/0017-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch similarity index 100% rename from pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch rename to 0017-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch diff --git a/fix-two-VF-virtual-machines-have-same-mac-address.patch b/0018-fix-two-VF-virtual-machines-have-same-mac-address.patch similarity index 100% rename from fix-two-VF-virtual-machines-have-same-mac-address.patch rename to 0018-fix-two-VF-virtual-machines-have-same-mac-address.patch diff --git a/logind-set-RemoveIPC-to-false-by-default.patch b/0019-logind-set-RemoveIPC-to-false-by-default.patch similarity index 100% rename from logind-set-RemoveIPC-to-false-by-default.patch rename to 0019-logind-set-RemoveIPC-to-false-by-default.patch diff --git a/rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch b/0020-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch similarity index 100% rename from rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch rename to 0020-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch diff --git a/unit-don-t-add-Requires-for-tmp.mount.patch b/0021-unit-don-t-add-Requires-for-tmp.mount.patch similarity index 100% rename from unit-don-t-add-Requires-for-tmp.mount.patch rename to 0021-unit-don-t-add-Requires-for-tmp.mount.patch diff --git a/Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch b/0022-Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch similarity index 100% rename from Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch rename to 0022-Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch diff --git a/rules-add-elevator-kernel-command-line-parameter.patch b/0023-rules-add-elevator-kernel-command-line-parameter.patch similarity index 100% rename from rules-add-elevator-kernel-command-line-parameter.patch rename to 0023-rules-add-elevator-kernel-command-line-parameter.patch diff --git a/rules-add-the-rule-that-adds-elevator-kernel-command.patch b/0024-rules-add-the-rule-that-adds-elevator-kernel-command.patch similarity index 100% rename from rules-add-the-rule-that-adds-elevator-kernel-command.patch rename to 0024-rules-add-the-rule-that-adds-elevator-kernel-command.patch diff --git a/units-add-Install-section-to-tmp.mount.patch b/0025-units-add-Install-section-to-tmp.mount.patch similarity index 100% rename from units-add-Install-section-to-tmp.mount.patch rename to 0025-units-add-Install-section-to-tmp.mount.patch diff --git a/Make-systemd-udevd.service-start-after-systemd-remou.patch b/0026-Make-systemd-udevd.service-start-after-systemd-remou.patch similarity index 100% rename from Make-systemd-udevd.service-start-after-systemd-remou.patch rename to 0026-Make-systemd-udevd.service-start-after-systemd-remou.patch diff --git a/udev-virsh-shutdown-vm.patch b/0027-udev-virsh-shutdown-vm.patch similarity index 100% rename from udev-virsh-shutdown-vm.patch rename to 0027-udev-virsh-shutdown-vm.patch diff --git a/fix-fd-leak-in-no-memory-condition.patch b/0028-fix-fd-leak-in-no-memory-condition.patch similarity index 100% rename from fix-fd-leak-in-no-memory-condition.patch rename to 0028-fix-fd-leak-in-no-memory-condition.patch diff --git a/dbus-execute-avoid-extra-strdup.patch b/0029-dbus-execute-avoid-extra-strdup.patch similarity index 100% rename from dbus-execute-avoid-extra-strdup.patch rename to 0029-dbus-execute-avoid-extra-strdup.patch diff --git a/Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch b/0030-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch similarity index 100% rename from Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch rename to 0030-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch diff --git a/sd-bus-properly-initialize-containers.patch b/0031-sd-bus-properly-initialize-containers.patch similarity index 100% rename from sd-bus-properly-initialize-containers.patch rename to 0031-sd-bus-properly-initialize-containers.patch diff --git a/Revert-core-one-step-back-again-for-nspawn-we-actual.patch b/0032-Revert-core-one-step-back-again-for-nspawn-we-actual.patch similarity index 100% rename from Revert-core-one-step-back-again-for-nspawn-we-actual.patch rename to 0032-Revert-core-one-step-back-again-for-nspawn-we-actual.patch diff --git a/journal-don-t-enable-systemd-journald-audit.socket-b.patch b/0033-journal-don-t-enable-systemd-journald-audit.socket-b.patch similarity index 100% rename from journal-don-t-enable-systemd-journald-audit.socket-b.patch rename to 0033-journal-don-t-enable-systemd-journald-audit.socket-b.patch diff --git a/revert-pid1-drop-unit-caches-only-based-on-mtime.patch b/0034-revert-pid1-drop-unit-caches-only-based-on-mtime.patch similarity index 100% rename from revert-pid1-drop-unit-caches-only-based-on-mtime.patch rename to 0034-revert-pid1-drop-unit-caches-only-based-on-mtime.patch diff --git a/revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch b/0035-revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch similarity index 100% rename from revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch rename to 0035-revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch diff --git a/revert-pid1-use-a-cache-for-all-unit-aliases.patch b/0036-revert-pid1-use-a-cache-for-all-unit-aliases.patch similarity index 100% rename from revert-pid1-use-a-cache-for-all-unit-aliases.patch rename to 0036-revert-pid1-use-a-cache-for-all-unit-aliases.patch diff --git a/revert-shared-unit-file-add-a-function-to-validate-u.patch b/0037-revert-shared-unit-file-add-a-function-to-validate-u.patch similarity index 100% rename from revert-shared-unit-file-add-a-function-to-validate-u.patch rename to 0037-revert-shared-unit-file-add-a-function-to-validate-u.patch diff --git a/systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch b/0038-systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch similarity index 100% rename from systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch rename to 0038-systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch diff --git a/seccomp-more-comprehensive-protection-against-libsec.patch b/0039-seccomp-more-comprehensive-protection-against-libsec.patch similarity index 100% rename from seccomp-more-comprehensive-protection-against-libsec.patch rename to 0039-seccomp-more-comprehensive-protection-against-libsec.patch diff --git a/network-fix-double-free-in-macsec_receive_channel_fr.patch b/0040-network-fix-double-free-in-macsec_receive_channel_fr.patch similarity index 100% rename from network-fix-double-free-in-macsec_receive_channel_fr.patch rename to 0040-network-fix-double-free-in-macsec_receive_channel_fr.patch diff --git a/network-L2TP-fix-crash.patch b/0041-network-L2TP-fix-crash.patch similarity index 100% rename from network-L2TP-fix-crash.patch rename to 0041-network-L2TP-fix-crash.patch diff --git a/systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch b/0042-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch similarity index 100% rename from systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch rename to 0042-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch diff --git a/analyze-fix-minor-memleak.patch b/0043-analyze-fix-minor-memleak.patch similarity index 100% rename from analyze-fix-minor-memleak.patch rename to 0043-analyze-fix-minor-memleak.patch diff --git a/network-add-one-more-section-validty-check.patch b/0044-network-add-one-more-section-validty-check.patch similarity index 100% rename from network-add-one-more-section-validty-check.patch rename to 0044-network-add-one-more-section-validty-check.patch diff --git a/network-use-fix-invalid-free-function.patch b/0045-network-use-fix-invalid-free-function.patch similarity index 100% rename from network-use-fix-invalid-free-function.patch rename to 0045-network-use-fix-invalid-free-function.patch diff --git a/network-fix-memleak.patch b/0046-network-fix-memleak.patch similarity index 100% rename from network-fix-memleak.patch rename to 0046-network-fix-memleak.patch diff --git a/network-Add-support-to-advertie-ipv6-route.patch b/0047-network-Add-support-to-advertie-ipv6-route.patch similarity index 100% rename from network-Add-support-to-advertie-ipv6-route.patch rename to 0047-network-Add-support-to-advertie-ipv6-route.patch diff --git a/network-fix-invalid-cleanup-function.patch b/0048-network-fix-invalid-cleanup-function.patch similarity index 100% rename from network-fix-invalid-cleanup-function.patch rename to 0048-network-fix-invalid-cleanup-function.patch diff --git a/network-fix-memleak-in-route_prefix_free.patch b/0049-network-fix-memleak-in-route_prefix_free.patch similarity index 100% rename from network-fix-memleak-in-route_prefix_free.patch rename to 0049-network-fix-memleak-in-route_prefix_free.patch diff --git a/sd-radv-fix-memleak.patch b/0050-sd-radv-fix-memleak.patch similarity index 100% rename from sd-radv-fix-memleak.patch rename to 0050-sd-radv-fix-memleak.patch diff --git a/sd-bus-invalidate-connection-when-Hello-fails.patch b/0051-sd-bus-invalidate-connection-when-Hello-fails.patch similarity index 100% rename from sd-bus-invalidate-connection-when-Hello-fails.patch rename to 0051-sd-bus-invalidate-connection-when-Hello-fails.patch diff --git a/shared-bus-util-Don-t-replace-exsting-strv.patch b/0052-shared-bus-util-Don-t-replace-exsting-strv.patch similarity index 100% rename from shared-bus-util-Don-t-replace-exsting-strv.patch rename to 0052-shared-bus-util-Don-t-replace-exsting-strv.patch diff --git a/systemctl-Add-with-dependencies-flag.patch b/0053-systemctl-Add-with-dependencies-flag.patch similarity index 100% rename from systemctl-Add-with-dependencies-flag.patch rename to 0053-systemctl-Add-with-dependencies-flag.patch diff --git a/man-Document-systemctl-with-dependencies-switch.patch b/0054-man-Document-systemctl-with-dependencies-switch.patch similarity index 100% rename from man-Document-systemctl-with-dependencies-switch.patch rename to 0054-man-Document-systemctl-with-dependencies-switch.patch diff --git a/core-expose-swap-priority-value-via-dbus-only-if-it-.patch b/0055-core-expose-swap-priority-value-via-dbus-only-if-it-.patch similarity index 100% rename from core-expose-swap-priority-value-via-dbus-only-if-it-.patch rename to 0055-core-expose-swap-priority-value-via-dbus-only-if-it-.patch diff --git a/tree-wide-we-forgot-to-destroy-some-bus-errors.patch b/0056-tree-wide-we-forgot-to-destroy-some-bus-errors.patch similarity index 100% rename from tree-wide-we-forgot-to-destroy-some-bus-errors.patch rename to 0056-tree-wide-we-forgot-to-destroy-some-bus-errors.patch diff --git a/sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch b/0057-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch similarity index 100% rename from sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch rename to 0057-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch diff --git a/core-sync-SeccompParseFlags-between-dbus-execute-and.patch b/0058-core-sync-SeccompParseFlags-between-dbus-execute-and.patch similarity index 100% rename from core-sync-SeccompParseFlags-between-dbus-execute-and.patch rename to 0058-core-sync-SeccompParseFlags-between-dbus-execute-and.patch diff --git a/core-swap-priority-can-be-negative.patch b/0059-core-swap-priority-can-be-negative.patch similarity index 100% rename from core-swap-priority-can-be-negative.patch rename to 0059-core-swap-priority-can-be-negative.patch diff --git a/core-no-need-to-initialize-swap-structure-fields-if-.patch b/0060-core-no-need-to-initialize-swap-structure-fields-if-.patch similarity index 100% rename from core-no-need-to-initialize-swap-structure-fields-if-.patch rename to 0060-core-no-need-to-initialize-swap-structure-fields-if-.patch diff --git a/core-initialize-priority_set-when-parsing-swap-unit-.patch b/0061-core-initialize-priority_set-when-parsing-swap-unit-.patch similarity index 100% rename from core-initialize-priority_set-when-parsing-swap-unit-.patch rename to 0061-core-initialize-priority_set-when-parsing-swap-unit-.patch diff --git a/core-use-unit-based-logging-instead-of-generic-loggi.patch b/0062-core-use-unit-based-logging-instead-of-generic-loggi.patch similarity index 100% rename from core-use-unit-based-logging-instead-of-generic-loggi.patch rename to 0062-core-use-unit-based-logging-instead-of-generic-loggi.patch diff --git a/core-set-error-value-correctly.patch b/0063-core-set-error-value-correctly.patch similarity index 100% rename from core-set-error-value-correctly.patch rename to 0063-core-set-error-value-correctly.patch diff --git a/core-fix-re-realization-of-cgroup-siblings.patch b/0064-core-fix-re-realization-of-cgroup-siblings.patch similarity index 100% rename from core-fix-re-realization-of-cgroup-siblings.patch rename to 0064-core-fix-re-realization-of-cgroup-siblings.patch diff --git a/basic-string-table-avoid-crash-when-table-is-sparse.patch b/0065-basic-string-table-avoid-crash-when-table-is-sparse.patch similarity index 100% rename from basic-string-table-avoid-crash-when-table-is-sparse.patch rename to 0065-basic-string-table-avoid-crash-when-table-is-sparse.patch diff --git a/journal-fix-buffer-overrun-when-urlifying.patch b/0066-journal-fix-buffer-overrun-when-urlifying.patch similarity index 100% rename from journal-fix-buffer-overrun-when-urlifying.patch rename to 0066-journal-fix-buffer-overrun-when-urlifying.patch diff --git a/backport-varlink-make-userdata-pointer-inheritance-from-varli.patch b/0067-backport-varlink-make-userdata-pointer-inheritance-from-varli.patch similarity index 100% rename from backport-varlink-make-userdata-pointer-inheritance-from-varli.patch rename to 0067-backport-varlink-make-userdata-pointer-inheritance-from-varli.patch diff --git a/backport-journal-refresh-cached-credentials-of-stdout-streams.patch b/0068-backport-journal-refresh-cached-credentials-of-stdout-streams.patch similarity index 100% rename from backport-journal-refresh-cached-credentials-of-stdout-streams.patch rename to 0068-backport-journal-refresh-cached-credentials-of-stdout-streams.patch diff --git a/backport-journald-rework-end-of-line-marker-handling-to-use-a.patch b/0069-backport-journald-rework-end-of-line-marker-handling-to-use-a.patch similarity index 100% rename from backport-journald-rework-end-of-line-marker-handling-to-use-a.patch rename to 0069-backport-journald-rework-end-of-line-marker-handling-to-use-a.patch diff --git a/backport-journald-rework-pid-change-handling.patch b/0070-backport-journald-rework-pid-change-handling.patch similarity index 100% rename from backport-journald-rework-pid-change-handling.patch rename to 0070-backport-journald-rework-pid-change-handling.patch diff --git a/backport-journald-enforce-longer-line-length-limit-during-set.patch b/0071-backport-journald-enforce-longer-line-length-limit-during-set.patch similarity index 100% rename from backport-journald-enforce-longer-line-length-limit-during-set.patch rename to 0071-backport-journald-enforce-longer-line-length-limit-during-set.patch diff --git a/systemd.spec b/systemd.spec index 99f5582..7104ec2 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 33 +Release: 34 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -44,80 +44,80 @@ Source105: rule_generator.functions Source106: write_net_rules Source107: detect_virt -Patch0002: 0001-udev-ignore-error-caused-by-device-disconnection.patch -Patch0003: 0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch -Patch0004: 0001-core-dont-check-potentially-NULL-error.patch -Patch0005: 0001-core-shorten-code-a-bit.patch -Patch0006: 0001-core-no-need-to-eat-up-error.patch -Patch0007: 0001-core-create-or-remove-unit-bus-name-slots-always-together.patch -Patch0008: 0001-core-drop-initial-ListNames-bus-call-from-PID1.patch -Patch0009: 1605-update-rtc-with-system-clock-when-shutdown.patch -Patch0010: 1603-udev-add-actions-while-rename-netif-failed.patch -Patch0011: CVE-2020-1712-1.patch -Patch0012: CVE-2020-1712-2.patch -Patch0013: CVE-2020-1712-3.patch -Patch0014: CVE-2020-1712-4.patch -Patch0015: CVE-2020-1712-5.patch -Patch0016: sd-journal-close-journal-files-that-were-deleted-by-.patch -Patch0017: pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch -Patch0018: fix-two-VF-virtual-machines-have-same-mac-address.patch -Patch0019: logind-set-RemoveIPC-to-false-by-default.patch -Patch0020: rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch -Patch0021: unit-don-t-add-Requires-for-tmp.mount.patch -Patch0022: Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch -Patch2023: rules-add-elevator-kernel-command-line-parameter.patch -Patch2024: rules-add-the-rule-that-adds-elevator-kernel-command.patch -Patch2025: units-add-Install-section-to-tmp.mount.patch -Patch0026: Make-systemd-udevd.service-start-after-systemd-remou.patch -Patch0027: udev-virsh-shutdown-vm.patch -Patch0028: fix-fd-leak-in-no-memory-condition.patch -Patch0029: dbus-execute-avoid-extra-strdup.patch -Patch0030: Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch -Patch0031: sd-bus-properly-initialize-containers.patch -Patch0032: Revert-core-one-step-back-again-for-nspawn-we-actual.patch -Patch0033: journal-don-t-enable-systemd-journald-audit.socket-b.patch +Patch0002: 0002-0001-udev-ignore-error-caused-by-device-disconnection.patch +Patch0003: 0003-0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch +Patch0004: 0004-0001-core-dont-check-potentially-NULL-error.patch +Patch0005: 0005-0001-core-shorten-code-a-bit.patch +Patch0006: 0006-0001-core-no-need-to-eat-up-error.patch +Patch0007: 0007-0001-core-create-or-remove-unit-bus-name-slots-always-together.patch +Patch0008: 0008-0001-core-drop-initial-ListNames-bus-call-from-PID1.patch +Patch0009: 0009-1605-update-rtc-with-system-clock-when-shutdown.patch +Patch0010: 0010-1603-udev-add-actions-while-rename-netif-failed.patch +Patch0011: 0011-CVE-2020-1712-1.patch +Patch0012: 0012-CVE-2020-1712-2.patch +Patch0013: 0013-CVE-2020-1712-3.patch +Patch0014: 0014-CVE-2020-1712-4.patch +Patch0015: 0015-CVE-2020-1712-5.patch +Patch0016: 0016-sd-journal-close-journal-files-that-were-deleted-by-.patch +Patch0017: 0017-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch +Patch0018: 0018-fix-two-VF-virtual-machines-have-same-mac-address.patch +Patch0019: 0019-logind-set-RemoveIPC-to-false-by-default.patch +Patch0020: 0020-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch +Patch0021: 0021-unit-don-t-add-Requires-for-tmp.mount.patch +Patch0022: 0022-Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch +Patch0023: 0023-rules-add-elevator-kernel-command-line-parameter.patch +Patch0024: 0024-rules-add-the-rule-that-adds-elevator-kernel-command.patch +Patch0025: 0025-units-add-Install-section-to-tmp.mount.patch +Patch0026: 0026-Make-systemd-udevd.service-start-after-systemd-remou.patch +Patch0027: 0027-udev-virsh-shutdown-vm.patch +Patch0028: 0028-fix-fd-leak-in-no-memory-condition.patch +Patch0029: 0029-dbus-execute-avoid-extra-strdup.patch +Patch0030: 0030-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch +Patch0031: 0031-sd-bus-properly-initialize-containers.patch +Patch0032: 0032-Revert-core-one-step-back-again-for-nspawn-we-actual.patch +Patch0033: 0033-journal-don-t-enable-systemd-journald-audit.socket-b.patch # The patch of 0026~0029 resolve the pid1 memory leaks -Patch0034: revert-pid1-drop-unit-caches-only-based-on-mtime.patch -Patch0035: revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch -Patch0036: revert-pid1-use-a-cache-for-all-unit-aliases.patch -Patch0037: revert-shared-unit-file-add-a-function-to-validate-u.patch - -Patch0038: systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch -Patch0039: seccomp-more-comprehensive-protection-against-libsec.patch -Patch0040: network-fix-double-free-in-macsec_receive_channel_fr.patch -Patch0041: network-L2TP-fix-crash.patch - -Patch0042: systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch -Patch0043: analyze-fix-minor-memleak.patch -Patch0044: network-add-one-more-section-validty-check.patch -Patch0045: network-use-fix-invalid-free-function.patch -Patch0046: network-fix-memleak.patch -Patch0047: network-Add-support-to-advertie-ipv6-route.patch -Patch0048: network-fix-invalid-cleanup-function.patch -Patch0049: network-fix-memleak-in-route_prefix_free.patch -Patch0050: sd-radv-fix-memleak.patch -Patch0051: sd-bus-invalidate-connection-when-Hello-fails.patch -Patch0052: shared-bus-util-Don-t-replace-exsting-strv.patch -Patch0053: systemctl-Add-with-dependencies-flag.patch -Patch0054: man-Document-systemctl-with-dependencies-switch.patch -Patch0055: core-expose-swap-priority-value-via-dbus-only-if-it-.patch -Patch0056: tree-wide-we-forgot-to-destroy-some-bus-errors.patch -Patch0057: sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch -Patch0058: core-sync-SeccompParseFlags-between-dbus-execute-and.patch -Patch0059: core-swap-priority-can-be-negative.patch -Patch0060: core-no-need-to-initialize-swap-structure-fields-if-.patch -Patch0061: core-initialize-priority_set-when-parsing-swap-unit-.patch -Patch0062: core-use-unit-based-logging-instead-of-generic-loggi.patch -Patch0063: core-set-error-value-correctly.patch -Patch0064: core-fix-re-realization-of-cgroup-siblings.patch -Patch0065: basic-string-table-avoid-crash-when-table-is-sparse.patch -Patch0066: journal-fix-buffer-overrun-when-urlifying.patch -Patch0067: backport-varlink-make-userdata-pointer-inheritance-from-varli.patch -Patch0068: backport-journal-refresh-cached-credentials-of-stdout-streams.patch -Patch0069: backport-journald-rework-end-of-line-marker-handling-to-use-a.patch -Patch0070: backport-journald-rework-pid-change-handling.patch -Patch0071: backport-journald-enforce-longer-line-length-limit-during-set.patch +Patch0034: 0034-revert-pid1-drop-unit-caches-only-based-on-mtime.patch +Patch0035: 0035-revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch +Patch0036: 0036-revert-pid1-use-a-cache-for-all-unit-aliases.patch +Patch0037: 0037-revert-shared-unit-file-add-a-function-to-validate-u.patch + +Patch0038: 0038-systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch +Patch0039: 0039-seccomp-more-comprehensive-protection-against-libsec.patch +Patch0040: 0040-network-fix-double-free-in-macsec_receive_channel_fr.patch +Patch0041: 0041-network-L2TP-fix-crash.patch + +Patch0042: 0042-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch +Patch0043: 0043-analyze-fix-minor-memleak.patch +Patch0044: 0044-network-add-one-more-section-validty-check.patch +Patch0045: 0045-network-use-fix-invalid-free-function.patch +Patch0046: 0046-network-fix-memleak.patch +Patch0047: 0047-network-Add-support-to-advertie-ipv6-route.patch +Patch0048: 0048-network-fix-invalid-cleanup-function.patch +Patch0049: 0049-network-fix-memleak-in-route_prefix_free.patch +Patch0050: 0050-sd-radv-fix-memleak.patch +Patch0051: 0051-sd-bus-invalidate-connection-when-Hello-fails.patch +Patch0052: 0052-shared-bus-util-Don-t-replace-exsting-strv.patch +Patch0053: 0053-systemctl-Add-with-dependencies-flag.patch +Patch0054: 0054-man-Document-systemctl-with-dependencies-switch.patch +Patch0055: 0055-core-expose-swap-priority-value-via-dbus-only-if-it-.patch +Patch0056: 0056-tree-wide-we-forgot-to-destroy-some-bus-errors.patch +Patch0057: 0057-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch +Patch0058: 0058-core-sync-SeccompParseFlags-between-dbus-execute-and.patch +Patch0059: 0059-core-swap-priority-can-be-negative.patch +Patch0060: 0060-core-no-need-to-initialize-swap-structure-fields-if-.patch +Patch0061: 0061-core-initialize-priority_set-when-parsing-swap-unit-.patch +Patch0062: 0062-core-use-unit-based-logging-instead-of-generic-loggi.patch +Patch0063: 0063-core-set-error-value-correctly.patch +Patch0064: 0064-core-fix-re-realization-of-cgroup-siblings.patch +Patch0065: 0065-basic-string-table-avoid-crash-when-table-is-sparse.patch +Patch0066: 0066-journal-fix-buffer-overrun-when-urlifying.patch +Patch0067: 0067-backport-varlink-make-userdata-pointer-inheritance-from-varli.patch +Patch0068: 0068-backport-journal-refresh-cached-credentials-of-stdout-streams.patch +Patch0069: 0069-backport-journald-rework-end-of-line-marker-handling-to-use-a.patch +Patch0070: 0070-backport-journald-rework-pid-change-handling.patch +Patch0071: 0071-backport-journald-enforce-longer-line-length-limit-during-set.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1503,6 +1503,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon May 31 2021 overweight - 243-34 +- fix patchname and patchnum + * Fri May 21 2021 fangxiuning - 243-33 - Type:bugfix - ID:NA @@ -1614,7 +1617,7 @@ fi - Type:enhancement - ID:NA - SUG:NA -- DESC:add 1603-udev-add-actions-while-rename-netif-failed.patch +- DESC:add 0010-1603-udev-add-actions-while-rename-netif-failed.patch * Sat Feb 29 2020 openEuler Buildteam - 243-15 - Type:enhancement -- Gitee From 80d9a32e06399498abc4782c0504f26002359a64 Mon Sep 17 00:00:00 2001 From: Yangyang Shen Date: Thu, 3 Jun 2021 00:30:31 +0800 Subject: [PATCH 14/38] change requires to openssl-libs as post scripts systemctl requires libssl.so.1.1 --- systemd.spec | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/systemd.spec b/systemd.spec index 7104ec2..978d33d 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 34 +Release: 35 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -151,7 +151,7 @@ Requires(post): coreutils Requires(post): sed Requires(post): acl Requires(post): grep -Requires(post): openssl +Requires(post): openssl-libs Requires(pre): coreutils Requires(pre): /usr/bin/getent Requires(pre): /usr/sbin/groupadd @@ -1503,6 +1503,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Thu Jun 03 2021 shenyangyang - 243-35 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:change requires to openssl-libs as post scripts systemctl requires libssl.so.1.1 + * Mon May 31 2021 overweight - 243-34 - fix patchname and patchnum -- Gitee From f71e3dd3e66e6014602986e7667461cc34aa53d7 Mon Sep 17 00:00:00 2001 From: ExtinctFire Date: Thu, 3 Jun 2021 20:46:21 +0800 Subject: [PATCH 15/38] Fix migration from DynamicUser=yes to no. Signed-off-by: ExtinctFire --- ...migration-from-DynamicUser-yes-to-no.patch | 52 +++++++++++++++++++ systemd.spec | 9 +++- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch diff --git a/backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch b/backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch new file mode 100644 index 0000000..ac60fbc --- /dev/null +++ b/backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch @@ -0,0 +1,52 @@ +From 578dc69f2a60d6282acc2d06ce8a3bf8a9d8ada0 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 6 Mar 2020 15:56:28 +0900 +Subject: [PATCH 0007/6858] execute: Fix migration from DynamicUser=yes to no + +Closes #12131. +Reference: https://github.com/systemd/systemd/pull/15033/commits/578dc69f2a60d6282acc2d06ce8a3bf8a9d8ada0 +Conflict: remove the last arguement "NULL" of function "chase_symlinks" +--- + src/core/execute.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index 4595bb12dc..46b5c99ada 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -2247,7 +2247,7 @@ static int setup_exec_directory( + + if (type != EXEC_DIRECTORY_CONFIGURATION && + readlink_and_make_absolute(p, &target) >= 0) { +- _cleanup_free_ char *q = NULL; ++ _cleanup_free_ char *q = NULL, *q_resolved = NULL, *target_resolved = NULL; + + /* This already exists and is a symlink? Interesting. Maybe it's one created + * by DynamicUser=1 (see above)? +@@ -2256,13 +2256,22 @@ static int setup_exec_directory( + * since they all support the private/ symlink logic at least in some + * configurations, see above. */ + ++ r = chase_symlinks(target, NULL, 0, &target_resolved); ++ if (r < 0) ++ goto fail; ++ + q = path_join(params->prefix[type], "private", *rt); + if (!q) { + r = -ENOMEM; + goto fail; + } + +- if (path_equal(q, target)) { ++ /* /var/lib or friends may be symlinks. So, let's chase them also. */ ++ r = chase_symlinks(q, NULL, CHASE_NONEXISTENT, &q_resolved); ++ if (r < 0) ++ goto fail; ++ ++ if (path_equal(q_resolved, target_resolved)) { + + /* Hmm, apparently DynamicUser= was once turned on for this service, + * but is no longer. Let's move the directory back up. */ +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index 978d33d..0f19bb1 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 35 +Release: 36 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -118,6 +118,7 @@ Patch0068: 0068-backport-journal-refresh-cached-credentials-of-stdout-strea Patch0069: 0069-backport-journald-rework-end-of-line-marker-handling-to-use-a.patch Patch0070: 0070-backport-journald-rework-pid-change-handling.patch Patch0071: 0071-backport-journald-enforce-longer-line-length-limit-during-set.patch +Patch0072: backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1503,6 +1504,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Thu Jun 03 2021 ExtinctFire - 243-36 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:Fix migration from DynamicUser=yes to no. + * Thu Jun 03 2021 shenyangyang - 243-35 - Type:bugfix - ID:NA -- Gitee From b418a7f91f2be0554691ba36c129727ded19e181 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Wed, 21 Jul 2021 17:10:34 +0800 Subject: [PATCH 16/38] fix CVE-2021-33910 --- 0073-fix-CVE-2021-33910.patch | 72 +++++++++++++++++++++++++++++++++++ systemd.spec | 9 ++++- 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 0073-fix-CVE-2021-33910.patch diff --git a/0073-fix-CVE-2021-33910.patch b/0073-fix-CVE-2021-33910.patch new file mode 100644 index 0000000..d4b7ed3 --- /dev/null +++ b/0073-fix-CVE-2021-33910.patch @@ -0,0 +1,72 @@ +From 441e0115646d54f080e5c3bb0ba477c892861ab9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 23 Jun 2021 11:46:41 +0200 +Subject: [PATCH] basic/unit-name: do not use strdupa() on a path + +The path may have unbounded length, for example through a fuse mount. + +CVE-2021-33910: attacked controlled alloca() leads to crash in systemd +and +ultimately a kernel panic. Systemd parses the content of +/proc/self/mountinfo +and each mountpoint is passed to mount_setup_unit(), which calls +unit_name_path_escape() underneath. A local attacker who is able to +mount a +filesystem with a very long path can crash systemd and the whole system. + +https://bugzilla.redhat.com/show_bug.cgi?id=1970887 + +The resulting string length is bounded by UNIT_NAME_MAX, which is 256. +But we +can't easily check the length after simplification before doing the +simplification, which in turns uses a copy of the string we can write +to. +So we can't reject paths that are too long before doing the duplication. +Hence the most obvious solution is to switch back to strdup(), as before +7410616cd9dbbec97cf98d75324da5cda2b2f7a2. + +https://github.com/systemd/systemd/pull/20256/commits/441e0115646d54f080e5c3bb0ba477c892861ab9 + +--- + src/basic/unit-name.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c +index 4226f30..1b01af6 100644 +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -370,12 +370,13 @@ int unit_name_unescape(const char *f, char **ret) { + } + + int unit_name_path_escape(const char *f, char **ret) { +- char *p, *s; ++ _cleanup_free_ char *p = NULL; ++ char *s; + + assert(f); + assert(ret); + +- p = strdupa(f); ++ p = strdup(f); + if (!p) + return -ENOMEM; + +@@ -387,13 +388,9 @@ int unit_name_path_escape(const char *f, char **ret) { + if (!path_is_normalized(p)) + return -EINVAL; + +- /* Truncate trailing slashes */ ++ /* Truncate trailing slashes and skip leading slashes */ + delete_trailing_chars(p, "/"); +- +- /* Truncate leading slashes */ +- p = skip_leading_chars(p, "/"); +- +- s = unit_name_escape(p); ++ s = unit_name_escape(skip_leading_chars(p, "/")); + } + if (!s) + return -ENOMEM; +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index 0f19bb1..e79480e 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 36 +Release: 37 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -119,6 +119,7 @@ Patch0069: 0069-backport-journald-rework-end-of-line-marker-handling-to-use Patch0070: 0070-backport-journald-rework-pid-change-handling.patch Patch0071: 0071-backport-journald-enforce-longer-line-length-limit-during-set.patch Patch0072: backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch +Patch0073: 0073-fix-CVE-2021-33910.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1504,6 +1505,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Wed Jul 21 2021 yangmingtai - 243-37 +- Type:cve +- ID:CVE-2021-33910 +- SUG:NA +- DESC:Fix CVE-2021-33910 + * Thu Jun 03 2021 ExtinctFire - 243-36 - Type:bugfix - ID:NA -- Gitee From 64f4384ceadf27f28dae1aea18ff66054eeaed9b Mon Sep 17 00:00:00 2001 From: ExtinctFire Date: Tue, 27 Jul 2021 19:01:57 +0800 Subject: [PATCH 17/38] restore RemainAfterExit=yes in systemd-vconsole-setup.service Signed-off-by: ExtinctFire --- ...mainAfterExit-yes-in-systemd-vconsol.patch | 30 +++++++++++++++++++ systemd.spec | 9 +++++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch diff --git a/backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch b/backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch new file mode 100644 index 0000000..72db99f --- /dev/null +++ b/backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch @@ -0,0 +1,30 @@ +From 9fd32ff7d363945fbf8fdae0128702b995127558 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 5 Mar 2020 07:11:09 +0100 +Subject: [PATCH] units: restore RemainAfterExit=yes in + systemd-vconsole-setup.service + +This reverts the second part of 8125e8d38e3aa099c7dce8b0161997b8842aebdc. +The first part was reverted in 750e550eba362096d56a35104c6a32631aa67b8e. +The problem starts when s-v-s.s is pulled in by something that is then pulled +in by sysinit.target. Every time a unit is started, systemd recursively checks +all dependencies, and since sysinit.target is pull in by almost anything, we'll +start s-v-s.s over and over. In particular, plymouth-start.service currently +has Wants=s-v-s.s and After=s-v-s.s. +--- + units/systemd-vconsole-setup.service.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in +index f4178f495a..9042521c9d 100644 +--- a/units/systemd-vconsole-setup.service.in ++++ b/units/systemd-vconsole-setup.service.in +@@ -16,4 +16,5 @@ ConditionPathExists=/dev/tty0 + + [Service] + Type=oneshot ++RemainAfterExit=yes + ExecStart=@rootlibexecdir@/systemd-vconsole-setup +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index e79480e..94df65b 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 37 +Release: 38 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -120,6 +120,7 @@ Patch0070: 0070-backport-journald-rework-pid-change-handling.patch Patch0071: 0071-backport-journald-enforce-longer-line-length-limit-during-set.patch Patch0072: backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch Patch0073: 0073-fix-CVE-2021-33910.patch +Patch0074: backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1505,6 +1506,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Jul 27 2021 extinctfire - 243-38 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:restore RemainAfterExit=yes in systemd-vconsole-setup.service + * Wed Jul 21 2021 yangmingtai - 243-37 - Type:cve - ID:CVE-2021-33910 -- Gitee From 12af30bc27e16e690d410a76007aed5448b0701f Mon Sep 17 00:00:00 2001 From: fangxiuning Date: Tue, 27 Jul 2021 19:50:59 +0800 Subject: [PATCH 18/38] modify --- ...-worker-in-manager_kill_workers-when.patch | 104 ++++++++++++++++++ systemd.spec | 9 +- 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch diff --git a/backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch b/backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch new file mode 100644 index 0000000..518e870 --- /dev/null +++ b/backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch @@ -0,0 +1,104 @@ +From f257a8fc13b2a617d845132eb61aefde47921198 Mon Sep 17 00:00:00 2001 +From: gaoyi +Date: Fri, 19 Mar 2021 15:16:56 +0800 +Subject: [PATCH] udevd: don't kill worker in manager_kill_workers when it's + running + +If worker is running, kill worker may lead uevent unprocessed. +--- + src/udev/udevd.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +diff --git a/src/udev/udevd.c b/src/udev/udevd.c +index cb51230..215f020 100644 +--- a/src/udev/udevd.c ++++ b/src/udev/udevd.c +@@ -134,6 +134,7 @@ enum worker_state { + WORKER_RUNNING, + WORKER_IDLE, + WORKER_KILLED, ++ WORKER_KILLING, + }; + + struct worker { +@@ -654,7 +655,7 @@ static int event_queue_insert(Manager *manager, sd_device *dev) { + return 0; + } + +-static void manager_kill_workers(Manager *manager) { ++static void manager_kill_workers(Manager *manager, bool force) { + struct worker *worker; + Iterator i; + +@@ -664,6 +665,11 @@ static void manager_kill_workers(Manager *manager) { + if (worker->state == WORKER_KILLED) + continue; + ++ if (worker->state == WORKER_RUNNING && !force) { ++ worker->state = WORKER_KILLING; ++ continue; ++ } ++ + worker->state = WORKER_KILLED; + (void) kill(worker->pid, SIGTERM); + } +@@ -810,7 +816,7 @@ static void manager_exit(Manager *manager) { + + /* discard queued events and kill workers */ + event_queue_cleanup(manager, EVENT_QUEUED); +- manager_kill_workers(manager); ++ manager_kill_workers(manager, true); + + assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0); + +@@ -829,7 +835,7 @@ static void manager_reload(Manager *manager) { + "RELOADING=1\n" + "STATUS=Flushing configuration..."); + +- manager_kill_workers(manager); ++ manager_kill_workers(manager, false); + manager->rules = udev_rules_free(manager->rules); + udev_builtin_exit(); + +@@ -844,7 +850,7 @@ static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userda + assert(manager); + + log_debug("Cleanup idle workers"); +- manager_kill_workers(manager); ++ manager_kill_workers(manager, false); + + return 1; + } +@@ -966,7 +972,10 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat + continue; + } + +- if (worker->state != WORKER_KILLED) ++ if (worker->state == WORKER_KILLING) { ++ worker->state = WORKER_KILLED; ++ (void) kill(worker->pid, SIGTERM); ++ } else if (worker->state != WORKER_KILLED) + worker->state = WORKER_IDLE; + + /* worker returned */ +@@ -1012,7 +1021,7 @@ static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, co + log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", value->intval); + log_set_max_level_realm(LOG_REALM_UDEV, value->intval); + log_set_max_level_realm(LOG_REALM_SYSTEMD, value->intval); +- manager_kill_workers(manager); ++ manager_kill_workers(manager, false); + break; + case UDEV_CTRL_STOP_EXEC_QUEUE: + log_debug("Received udev control message (STOP_EXEC_QUEUE)"); +@@ -1077,7 +1086,7 @@ static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, co + } + + key = val = NULL; +- manager_kill_workers(manager); ++ manager_kill_workers(manager, false); + break; + } + case UDEV_CTRL_SET_CHILDREN_MAX: +-- +1.8.3.1 + diff --git a/systemd.spec b/systemd.spec index 94df65b..52ddc9f 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 38 +Release: 39 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -121,6 +121,7 @@ Patch0071: 0071-backport-journald-enforce-longer-line-length-limit-during-s Patch0072: backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch Patch0073: 0073-fix-CVE-2021-33910.patch Patch0074: backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch +Patch0075: backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1506,6 +1507,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Jul 27 2021 fangxiuning - 243-39 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:udevd: don't kill worker in manager_kill_worker when it's running + * Tue Jul 27 2021 extinctfire - 243-38 - Type:bugfix - ID:NA -- Gitee From c280878580839352f31cd0a01d6d8605ccafd944 Mon Sep 17 00:00:00 2001 From: jiazhenyuan Date: Mon, 2 Aug 2021 10:08:30 +0800 Subject: [PATCH 19/38] set kernel.core_pipe_limit=16 --- set-kernel-core_pipe_limit-to-16.patch | 33 ++++++++++++++++++++++++++ systemd.spec | 9 ++++++- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 set-kernel-core_pipe_limit-to-16.patch diff --git a/set-kernel-core_pipe_limit-to-16.patch b/set-kernel-core_pipe_limit-to-16.patch new file mode 100644 index 0000000..e241504 --- /dev/null +++ b/set-kernel-core_pipe_limit-to-16.patch @@ -0,0 +1,33 @@ +From 283ff70372cddb8b06ca3b2c5e7b8287f81207a9 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Fri, 30 Jul 2021 12:38:27 +0800 +Subject: [PATCH] set kernel.core_pipe_limit=16 + +https://github.com/poettering/systemd/commit/8444f245b56d085cdcfa788e9b9c7799fc58a46b + +--- + sysctl.d/50-coredump.conf.in | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in +index 47bf847..327863d 100644 +--- a/sysctl.d/50-coredump.conf.in ++++ b/sysctl.d/50-coredump.conf.in +@@ -10,3 +10,14 @@ + # setting below. + + kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %c %h ++ ++# Allow that 16 coredumps are dispatched in parallel by the kernel. We want to ++# be able to collect process metadata from /proc/%P/ while processing ++# coredumps, and thus need to make sure the crashed processes are not reaped ++# until we finished collecting what we need. The kernel default for this sysctl ++# is "0" which means the kernel doesn't wait for userspace processes to finish ++# processing before reaping the crashed processes — by setting this higher the ++# kernel will delay reaping until we are done, but only for the specified ++# number of crashes in parallel. The value of 16 is chosen to match ++# systemd-coredump.socket's MaxConnections= value. ++kernel.core_pipe_limit=16 +-- +2.27.0 + diff --git a/systemd.spec b/systemd.spec index 52ddc9f..416bae8 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 39 +Release: 40 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -136,6 +136,7 @@ Patch9008: 1620-nop_job-of-a-unit-must-also-be-coldpluged-after-deserizatio Patch9009: systemd-change-time-log-level.patch Patch9010: fix-capsh-drop-but-ping-success.patch Patch9011: 0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch +Patch9012: set-kernel-core_pipe_limit-to-16.patch BuildRequires: gcc, gcc-c++ BuildRequires: libcap-devel, libmount-devel, pam-devel, libselinux-devel @@ -1507,6 +1508,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon Aug 02 2021 jiazhenyuan - 243-40 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:set kernel.core_pipe_limit=16 + * Tue Jul 27 2021 fangxiuning - 243-39 - Type:bugfix - ID:NA -- Gitee From 8cadff94d6d9ae40486647df083b8c19cdc00e84 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Tue, 3 Aug 2021 09:46:46 +0800 Subject: [PATCH 20/38] fix broken symbolic links when same link for different devices --- ...make-mtime-check-stricter-and-use-en.patch | 34 ++++ ...at_inode_unmodified-helper-that-chec.patch | 53 ++++++ ...thm-that-selects-highest-priority-de.patch | 174 ++++++++++++++++++ systemd.spec | 11 +- 4 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch create mode 100644 backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch create mode 100644 backport-udev-make-algorithm-that-selects-highest-priority-de.patch diff --git a/backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch b/backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch new file mode 100644 index 0000000..b61423c --- /dev/null +++ b/backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch @@ -0,0 +1,34 @@ +From a59b0a9f768f6e27b25f4f1bab6de08842e78d74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Thu, 5 Nov 2020 17:55:25 +0100 +Subject: [PATCH] basic/stat-util: make mtime check stricter and use entire + timestamp + +Note that st_mtime member of struct stat is defined as follows, + + #define st_mtime st_mtim.tv_sec + +Hence we omitted checking nanosecond part of the timestamp (struct +timespec) and possibly would miss modifications that happened within the +same second. +--- + src/basic/stat-util.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c +index 4595ba7..b44d75c 100644 +--- a/src/basic/stat-util.c ++++ b/src/basic/stat-util.c +@@ -394,7 +394,8 @@ bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { + return a && b && + (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */ + ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */ +- a->st_mtime == b->st_mtime && ++ a->st_mtim.tv_sec == b->st_mtim.tv_sec && ++ a->st_mtim.tv_nsec == b->st_mtim.tv_nsec && + (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */ + a->st_dev == b->st_dev && + a->st_ino == b->st_ino && +-- +2.23.0 + diff --git a/backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch b/backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch new file mode 100644 index 0000000..c901844 --- /dev/null +++ b/backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch @@ -0,0 +1,53 @@ +From fee5c52ac260d021466c1062499f0ebd5241db5f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 28 Apr 2020 18:16:25 +0200 +Subject: [PATCH] stat-util: add stat_inode_unmodified() helper that checks if + an inode was modified + +--- + src/basic/stat-util.c | 21 +++++++++++++++++++++ + src/basic/stat-util.h | 2 ++ + 2 files changed, 23 insertions(+) + +diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c +index 2cd722c..4595ba7 100644 +--- a/src/basic/stat-util.c ++++ b/src/basic/stat-util.c +@@ -379,3 +379,24 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret + + return 0; + } ++ ++bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { ++ ++ /* Returns if the specified stat structures reference the same, unmodified inode. This check tries to ++ * be reasonably careful when detecting changes: we check both inode and mtime, to cater for file ++ * systems where mtimes are fixed to 0 (think: ostree/nixos type installations). We also check file ++ * size, backing device, inode type and if this refers to a device not the major/minor. ++ * ++ * Note that we don't care if file attributes such as ownership or access mode change, this here is ++ * about contents of the file. The purpose here is to detect file contents changes, and nothing ++ * else. */ ++ ++ return a && b && ++ (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */ ++ ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */ ++ a->st_mtime == b->st_mtime && ++ (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */ ++ a->st_dev == b->st_dev && ++ a->st_ino == b->st_ino && ++ (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */ ++} +diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h +index 7824af3..3665059 100644 +--- a/src/basic/stat-util.h ++++ b/src/basic/stat-util.h +@@ -87,3 +87,5 @@ int fd_verify_directory(int fd); + int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret); + int device_path_make_canonical(mode_t mode, dev_t devno, char **ret); + int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno); ++ ++bool stat_inode_unmodified(const struct stat *a, const struct stat *b); +-- +2.23.0 + diff --git a/backport-udev-make-algorithm-that-selects-highest-priority-de.patch b/backport-udev-make-algorithm-that-selects-highest-priority-de.patch new file mode 100644 index 0000000..139d3e3 --- /dev/null +++ b/backport-udev-make-algorithm-that-selects-highest-priority-de.patch @@ -0,0 +1,174 @@ +From 30f6dce62cb3a738b20253f2192270607c31b55b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Fri, 23 Oct 2020 16:30:23 +0200 +Subject: [PATCH] udev: make algorithm that selects highest priority devlink + less susceptible to race conditions + +Previously it was very likely, when multiple contenders for the symlink +appear in parallel, that algorithm would select wrong symlink (i.e. one +with lower-priority). + +Now the algorithm is much more defensive and when we detect change in +set of contenders for the symlink we reevaluate the selection. Same +happens when new symlink replaces already existing symlink that points +to different device node. +--- + src/udev/udev-event.c | 7 ++++ + src/udev/udev-node.c | 75 ++++++++++++++++++++++++++++++++++--------- + 2 files changed, 67 insertions(+), 15 deletions(-) + +diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c +index ae78aef..1a8becb 100644 +--- a/src/udev/udev-event.c ++++ b/src/udev/udev-event.c +@@ -1017,6 +1017,13 @@ int udev_event_execute_rules(UdevEvent *event, + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m"); + ++ /* Yes, we run update_devnode() twice, because in the first invocation, that is before update of udev database, ++ * it could happen that two contenders are replacing each other's symlink. Hence we run it again to make sure ++ * symlinks point to devices that claim them with the highest priority. */ ++ r = update_devnode(event); ++ if (r < 0) ++ return r; ++ + device_set_is_initialized(dev); + + event->dev_db_clone = sd_device_unref(event->dev_db_clone); +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c +index ce95e20..2694185 100644 +--- a/src/udev/udev-node.c ++++ b/src/udev/udev-node.c +@@ -22,12 +22,15 @@ + #include "path-util.h" + #include "selinux-util.h" + #include "smack-util.h" ++#include "stat-util.h" + #include "stdio-util.h" + #include "string-util.h" + #include "strxcpyx.h" + #include "udev-node.h" + #include "user-util.h" + ++#define LINK_UPDATE_MAX_RETRIES 128 ++ + static int node_symlink(sd_device *dev, const char *node, const char *slink) { + _cleanup_free_ char *slink_dirname = NULL, *target = NULL; + const char *id_filename, *slink_tmp; +@@ -101,7 +104,9 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) { + if (rename(slink_tmp, slink) < 0) { + r = log_device_error_errno(dev, errno, "Failed to rename '%s' to '%s': %m", slink_tmp, slink); + (void) unlink(slink_tmp); +- } ++ } else ++ /* Tell caller that we replaced already existing symlink. */ ++ r = 1; + + return r; + } +@@ -194,7 +199,7 @@ static int link_update(sd_device *dev, const char *slink, bool add) { + _cleanup_free_ char *target = NULL, *filename = NULL, *dirname = NULL; + char name_enc[PATH_MAX]; + const char *id_filename; +- int r; ++ int i, r, retries; + + assert(dev); + assert(slink); +@@ -214,14 +219,6 @@ static int link_update(sd_device *dev, const char *slink, bool add) { + if (!add && unlink(filename) == 0) + (void) rmdir(dirname); + +- r = link_find_prioritized(dev, add, dirname, &target); +- if (r < 0) { +- log_device_debug(dev, "No reference left, removing '%s'", slink); +- if (unlink(slink) == 0) +- (void) rmdir_parents(slink, "/"); +- } else +- (void) node_symlink(dev, target, slink); +- + if (add) + do { + _cleanup_close_ int fd = -1; +@@ -234,7 +231,49 @@ static int link_update(sd_device *dev, const char *slink, bool add) { + r = -errno; + } while (r == -ENOENT); + +- return r; ++ /* If the database entry is not written yet we will just do one iteration and possibly wrong symlink ++ * will be fixed in the second invocation. */ ++ retries = sd_device_get_is_initialized(dev) > 0 ? LINK_UPDATE_MAX_RETRIES : 1; ++ ++ for (i = 0; i < retries; i++) { ++ struct stat st1 = {}, st2 = {}; ++ ++ r = stat(dirname, &st1); ++ if (r < 0 && errno != ENOENT) ++ return -errno; ++ ++ r = link_find_prioritized(dev, add, dirname, &target); ++ if (r == -ENOENT) { ++ log_device_debug(dev, "No reference left, removing '%s'", slink); ++ if (unlink(slink) == 0) ++ (void) rmdir_parents(slink, "/"); ++ ++ break; ++ } else if (r < 0) ++ return log_device_error_errno(dev, r, "Failed to determine highest priority symlink: %m"); ++ ++ r = node_symlink(dev, target, slink); ++ if (r < 0) { ++ (void) unlink(filename); ++ break; ++ } else if (r == 1) ++ /* We have replaced already existing symlink, possibly there is some other device trying ++ * to claim the same symlink. Let's do one more iteration to give us a chance to fix ++ * the error if other device actually claims the symlink with higher priority. */ ++ continue; ++ ++ /* Skip the second stat() if the first failed, stat_inode_unmodified() would return false regardless. */ ++ if ((st1.st_mode & S_IFMT) != 0) { ++ r = stat(dirname, &st2); ++ if (r < 0 && errno != ENOENT) ++ return -errno; ++ ++ if (stat_inode_unmodified(&st1, &st2)) ++ break; ++ } ++ } ++ ++ return i < LINK_UPDATE_MAX_RETRIES ? 0 : -ELOOP; + } + + int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) { +@@ -442,8 +481,11 @@ int udev_node_add(sd_device *dev, bool apply, + (void) node_symlink(dev, devnode, filename); + + /* create/update symlinks, add symlinks to name index */ +- FOREACH_DEVICE_DEVLINK(dev, devlink) +- (void) link_update(dev, devlink, true); ++ FOREACH_DEVICE_DEVLINK(dev, devlink) { ++ r = link_update(dev, devlink, true); ++ if (r < 0) ++ log_device_info_errno(dev, r, "Failed to update device symlinks: %m"); ++ } + + return 0; + } +@@ -456,8 +498,11 @@ int udev_node_remove(sd_device *dev) { + assert(dev); + + /* remove/update symlinks, remove symlinks from name index */ +- FOREACH_DEVICE_DEVLINK(dev, devlink) +- (void) link_update(dev, devlink, false); ++ FOREACH_DEVICE_DEVLINK(dev, devlink) { ++ r = link_update(dev, devlink, false); ++ if (r < 0) ++ log_device_info_errno(dev, r, "Failed to update device symlinks: %m"); ++ } + + r = xsprintf_dev_num_path_from_sd_device(dev, &filename); + if (r < 0) +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index 416bae8..12c2175 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 40 +Release: 41 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -122,6 +122,9 @@ Patch0072: backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch Patch0073: 0073-fix-CVE-2021-33910.patch Patch0074: backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch Patch0075: backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch +Patch0076: backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch +Patch0077: backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch +Patch0078: backport-udev-make-algorithm-that-selects-highest-priority-de.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1508,6 +1511,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Aug 03 2021 yangmingtai - 243-41 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:udevd: fix broken symbolic links when same link for different devices + * Mon Aug 02 2021 jiazhenyuan - 243-40 - Type:bugfix - ID:NA -- Gitee From bae6e6fdcf55cbad4e3ed61254210ff879146cc6 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Tue, 10 Aug 2021 13:26:35 +0000 Subject: [PATCH 21/38] udevd: exec daemon-reload after installation --- systemd.spec | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/systemd.spec b/systemd.spec index 12c2175..7830901 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 41 +Release: 42 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -701,6 +701,7 @@ grep -q -E '^KEYMAP="?fi-latin[19]"?' /etc/vconsole.conf 2>/dev/null && if [ -f "/usr/lib/udev/rules.d/50-udev-default.rules" ]; then sed -i 's/KERNEL=="kvm", GROUP="kvm", MODE="0666"/KERNEL=="kvm", GROUP="kvm", MODE="0660"/g' /usr/lib/udev/rules.d/50-udev-default.rules fi +%{_bindir}/systemctl daemon-reload &>/dev/null || : %preun udev %systemd_preun %udev_services @@ -1511,6 +1512,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Aug 10 2021 yangmingtai - 243-42 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:udevd: exec daemon-reload after installation + * Tue Aug 03 2021 yangmingtai - 243-41 - Type:bugfix - ID:NA -- Gitee From 67c0320118c3838cb7933ae4f83974bd38a9d957 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Mon, 16 Aug 2021 16:48:43 +0800 Subject: [PATCH 22/38] fix CVE-2020-13529 --- ...entatively-ignore-FORCERENEW-command.patch | 38 +++++++++++++++++++ systemd.spec | 9 ++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 backport-tentatively-ignore-FORCERENEW-command.patch diff --git a/backport-tentatively-ignore-FORCERENEW-command.patch b/backport-tentatively-ignore-FORCERENEW-command.patch new file mode 100644 index 0000000..2623fa2 --- /dev/null +++ b/backport-tentatively-ignore-FORCERENEW-command.patch @@ -0,0 +1,38 @@ +From 38e980a6a5a3442c2f48b1f827284388096d8ca5 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 24 Jun 2021 01:22:07 +0900 +Subject: [PATCH] sd-dhcp-client: tentatively ignore FORCERENEW command + +This makes DHCP client ignore FORCERENEW requests, as unauthenticated +FORCERENEW requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). + +Let's re-enable this after RFC3118 (Authentication for DHCP Messages) +and/or RFC6704 (Forcerenew Nonce Authentication) are implemented. + +Fixes #16774. +--- + src/libsystemd-network/sd-dhcp-client.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c +index 67a5a03eba6a..dc8ff19d1a24 100644 +--- a/src/libsystemd-network/sd-dhcp-client.c ++++ b/src/libsystemd-network/sd-dhcp-client.c +@@ -1380,9 +1380,17 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, + if (r != DHCP_FORCERENEW) + return -ENOMSG; + ++#if 0 + log_dhcp_client(client, "FORCERENEW"); + + return 0; ++#else ++ /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP ++ * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW ++ * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */ ++ log_dhcp_client(client, "Received FORCERENEW, ignoring."); ++ return -ENOMSG; ++#endif + } + + static bool lease_equal(const sd_dhcp_lease *a, const sd_dhcp_lease *b) { diff --git a/systemd.spec b/systemd.spec index 7830901..92ff160 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 42 +Release: 43 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -125,6 +125,7 @@ Patch0075: backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.pa Patch0076: backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch Patch0077: backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch Patch0078: backport-udev-make-algorithm-that-selects-highest-priority-de.patch +Patch0079: backport-tentatively-ignore-FORCERENEW-command.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1512,6 +1513,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon Aug 16 2021 yangmingtai - 243-43 +- Type:CVE +- ID:CVE-2020-13529 +- SUG:NA +- DESC:fix CVE-2020-13529 + * Tue Aug 10 2021 yangmingtai - 243-42 - Type:bugfix - ID:NA -- Gitee From 8049294aa76988bbc79bd51101abe0ad059b656b Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Thu, 9 Sep 2021 21:04:04 +0800 Subject: [PATCH 23/38] network:add missing link->network checks --- ...work-add-missing-link-network-checks.patch | 41 +++++++++++++++++++ systemd.spec | 6 ++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 backport-network-add-missing-link-network-checks.patch diff --git a/backport-network-add-missing-link-network-checks.patch b/backport-network-add-missing-link-network-checks.patch new file mode 100644 index 0000000..186596b --- /dev/null +++ b/backport-network-add-missing-link-network-checks.patch @@ -0,0 +1,41 @@ +From b1b0b42e48303134731e017a108c6c334ef5f4c8 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 17 Sep 2019 21:29:23 +0900 +Subject: [PATCH] network: add missing link->network checks + +When the function is called, no network file may be assigned to the +link. +--- + src/network/networkd-link.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index f1aeb7287e34..46d55f64dc5b 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -2393,9 +2393,9 @@ static int link_drop_foreign_config(Link *link) { + continue; + + if (link_address_is_dynamic(link, address)) { +- if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) ++ if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; +- } else if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) ++ } else if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + + if (link_is_static_address_configured(link, address)) { +@@ -2435,11 +2435,11 @@ static int link_drop_foreign_config(Link *link) { + in_addr_equal(AF_INET6, &route->dst, &(union in_addr_union) { .in6 = {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}} })) + continue; + +- if (route->protocol == RTPROT_STATIC && ++ if (route->protocol == RTPROT_STATIC && link->network && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + +- if (route->protocol == RTPROT_DHCP && ++ if (route->protocol == RTPROT_DHCP && link->network && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + diff --git a/systemd.spec b/systemd.spec index 92ff160..4ad658f 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 43 +Release: 44 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -126,6 +126,7 @@ Patch0076: backport-stat-util-add-stat_inode_unmodified-helper-that-chec.pa Patch0077: backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch Patch0078: backport-udev-make-algorithm-that-selects-highest-priority-de.patch Patch0079: backport-tentatively-ignore-FORCERENEW-command.patch +Patch0080: backport-network-add-missing-link-network-checks.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1513,6 +1514,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Thu Sep 9 2021 yangmingtai - 243-44 +- fix network coredump after install cloud-init + * Mon Aug 16 2021 yangmingtai - 243-43 - Type:CVE - ID:CVE-2020-13529 -- Gitee From f19b136a09cf18334d472a3ea4124a752ad9f431 Mon Sep 17 00:00:00 2001 From: fangxiuning Date: Tue, 14 Sep 2021 15:49:14 +0800 Subject: [PATCH 24/38] modify --- ...k-new-epoll-events-when-a-child-even.patch | 317 ++++++++++++++++++ systemd.spec | 9 +- 2 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch diff --git a/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch b/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch new file mode 100644 index 0000000..61d935c --- /dev/null +++ b/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch @@ -0,0 +1,317 @@ +From efd3be9de1dc07ec743912f3c166bbf17dbb20f5 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 8 Mar 2021 15:39:53 +0900 +Subject: [PATCH] sd-event: re-check new epoll events when a child event is + queued + +Previously, when a process outputs something and exit just after +epoll_wait() but before process_child(), then the IO event is ignored +even if the IO event has higher priority. See #18190. + +This can be solved by checking epoll event again after process_child(). + +However, there exists a possibility that another process outputs and +exits just after process_child() but before the second epoll_wait(). +When the IO event has lower priority than the child event, still IO +event is processed. + +So, this makes new epoll events and child events are checked in a loop +until no new event is detected. To prevent an infinite loop, the number +of maximum trial is set to 10. + +Fixes #18190. +--- + src/libsystemd/sd-event/sd-event.c | 150 +++++++++++++++++++++++++++---------- + 1 file changed, 110 insertions(+), 40 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 5d0e057..65db799 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -850,7 +850,7 @@ static int source_set_pending(sd_event_source *s, bool b) { + } + } + +- return 0; ++ return 1; + } + + static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) { +@@ -2502,12 +2502,20 @@ static int process_timer( + return 0; + } + +-static int process_child(sd_event *e) { ++static int process_child(sd_event *e, int64_t threshold, int64_t *ret_min_priority) { ++ int64_t min_priority = threshold; ++ bool something_new = false; + sd_event_source *s; + Iterator i; + int r; + + assert(e); ++ assert(ret_min_priority); ++ ++ if (!e->need_process_child) { ++ *ret_min_priority = min_priority; ++ return 0; ++ } + + e->need_process_child = false; + +@@ -2532,6 +2540,9 @@ static int process_child(sd_event *e) { + HASHMAP_FOREACH(s, e->child_sources, i) { + assert(s->type == SOURCE_CHILD); + ++ if (s->priority > threshold) ++ continue; ++ + if (s->pending) + continue; + +@@ -2560,19 +2571,24 @@ static int process_child(sd_event *e) { + r = source_set_pending(s, true); + if (r < 0) + return r; ++ if (r > 0) { ++ something_new = true; ++ min_priority = MIN(min_priority, s->priority); ++ } + } + } + +- return 0; ++ *ret_min_priority = min_priority; ++ return something_new; + } + +-static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { +- bool read_one = false; ++static int process_signal(sd_event *e, struct signal_data *d, uint32_t events, int64_t *min_priority) { + int r; + + assert(e); + assert(d); + assert_return(events == EPOLLIN, -EIO); ++ assert(min_priority); + + /* If there's a signal queued on this priority and SIGCHLD is + on this priority too, then make sure to recheck the +@@ -2598,7 +2614,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { + n = read(d->fd, &si, sizeof(si)); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) +- return read_one; ++ return 0; + + return -errno; + } +@@ -2608,8 +2624,6 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { + + assert(SIGNAL_VALID(si.ssi_signo)); + +- read_one = true; +- + if (e->signal_sources) + s = e->signal_sources[si.ssi_signo]; + if (!s) +@@ -2623,12 +2637,16 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { + r = source_set_pending(s, true); + if (r < 0) + return r; ++ if (r > 0 && *min_priority >= s->priority) { ++ *min_priority = s->priority; ++ return 1; /* an event source with smaller priority is queued. */ ++ } + +- return 1; ++ return 0; + } + } + +-static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents) { ++static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents, int64_t threshold) { + ssize_t n; + + assert(e); +@@ -2644,6 +2662,9 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t + if (d->buffer_filled > 0) + return 0; + ++ if (d->priority > threshold) ++ return 0; ++ + n = read(d->fd, &d->buffer, sizeof(d->buffer)); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) +@@ -3101,21 +3122,15 @@ pending: + return r; + } + +-_public_ int sd_event_wait(sd_event *e, uint64_t timeout) { ++static int process_epoll(sd_event *e, usec_t timeout, int64_t threshold, int64_t *ret_min_priority) { ++ int64_t min_priority = threshold; ++ bool something_new = false; + struct epoll_event *ev_queue; + unsigned ev_queue_max; + int r, m, i; + +- assert_return(e, -EINVAL); +- assert_return(e = event_resolve(e), -ENOPKG); +- assert_return(!event_pid_changed(e), -ECHILD); +- assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); +- assert_return(e->state == SD_EVENT_ARMED, -EBUSY); +- +- if (e->exit_requested) { +- e->state = SD_EVENT_PENDING; +- return 1; +- } ++ assert(e); ++ assert(ret_min_priority); + + ev_queue_max = MAX(e->n_sources, 1u); + ev_queue = newa(struct epoll_event, ev_queue_max); +@@ -3127,16 +3142,12 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max, + timeout == (uint64_t) -1 ? -1 : (int) DIV_ROUND_UP(timeout, USEC_PER_MSEC)); + if (m < 0) { +- if (errno == EINTR) { +- e->state = SD_EVENT_PENDING; +- return 1; +- } +- +- r = -errno; +- goto finish; ++ return -errno; + } + +- triple_timestamp_get(&e->timestamp); ++ /* Set timestamp only when this is called first time. */ ++ if (threshold == INT64_MAX) ++ triple_timestamp_get(&e->timestamp); + + for (i = 0; i < m; i++) { + +@@ -3147,9 +3158,18 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + + switch (*t) { + +- case WAKEUP_EVENT_SOURCE: +- r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events); ++ case WAKEUP_EVENT_SOURCE: { ++ sd_event_source *s = ev_queue[i].data.ptr; ++ ++ if (s->priority > threshold) ++ continue; ++ ++ min_priority = MIN(min_priority, s->priority); ++ ++ r = process_io(e, s, ev_queue[i].events); ++ + break; ++ } + + case WAKEUP_CLOCK_DATA: { + struct clock_data *d = ev_queue[i].data.ptr; +@@ -3158,11 +3178,12 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + } + + case WAKEUP_SIGNAL_DATA: +- r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events); ++ r = process_signal(e, e->event_queue[i].data.ptr, e->event_queue[i].events, &min_priority); + break; + + case WAKEUP_INOTIFY_DATA: +- r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events); ++ r = event_inotify_data_read(e, e->event_queue[i].data.ptr, e->event_queue[i].events, thresh ++old); + break; + + default: +@@ -3170,7 +3191,63 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + } + } + if (r < 0) ++ return r; ++ if (r > 0) ++ something_new = true; ++ } ++ ++ *ret_min_priority = min_priority; ++ return something_new; ++} ++ ++_public_ int sd_event_wait(sd_event *e, uint64_t timeout) { ++ int r; ++ ++ assert_return(e, -EINVAL); ++ assert_return(e = event_resolve(e), -ENOPKG); ++ assert_return(!event_pid_changed(e), -ECHILD); ++ assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); ++ assert_return(e->state == SD_EVENT_ARMED, -EBUSY); ++ ++ if (e->exit_requested) { ++ e->state = SD_EVENT_PENDING; ++ return 1; ++ } ++ ++ for (int64_t threshold = INT64_MAX; ; threshold--) { ++ int64_t epoll_min_priority, child_min_priority; ++ ++ /* There may be a possibility that new epoll (especially IO) and child events are ++ * triggered just after process_epoll() call but before process_child(), and the new IO ++ * events may have higher priority than the child events. To salvage these events, ++ * let's call epoll_wait() again, but accepts only events with higher priority than the ++ * previous. See issue https://github.com/systemd/systemd/issues/18190 and comments ++ * https://github.com/systemd/systemd/pull/18750#issuecomment-785801085 ++ * https://github.com/systemd/systemd/pull/18922#issuecomment-792825226 */ ++ ++ r = process_epoll(e, timeout, threshold, &epoll_min_priority); ++ if (r == -EINTR) { ++ e->state = SD_EVENT_PENDING; ++ return 1; ++ } ++ if (r < 0) + goto finish; ++ if (r == 0 && threshold < INT64_MAX) ++ /* No new epoll event. */ ++ break; ++ ++ r = process_child(e, threshold, &child_min_priority); ++ if (r < 0) ++ goto finish; ++ if (r == 0) ++ /* No new child event. */ ++ break; ++ ++ threshold = MIN(epoll_min_priority, child_min_priority); ++ if (threshold == INT64_MIN) ++ break; ++ ++ timeout = 0; + } + + r = process_watchdog(e); +@@ -3197,19 +3274,12 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + if (r < 0) + goto finish; + +- if (e->need_process_child) { +- r = process_child(e); +- if (r < 0) +- goto finish; +- } +- + r = process_inotify(e); + if (r < 0) + goto finish; + + if (event_next_pending(e)) { + e->state = SD_EVENT_PENDING; +- + return 1; + } + +-- +1.8.3.1 + diff --git a/systemd.spec b/systemd.spec index 4ad658f..8fd912d 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 44 +Release: 45 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -127,6 +127,7 @@ Patch0077: backport-basic-stat-util-make-mtime-check-stricter-and-use-en.pa Patch0078: backport-udev-make-algorithm-that-selects-highest-priority-de.patch Patch0079: backport-tentatively-ignore-FORCERENEW-command.patch Patch0080: backport-network-add-missing-link-network-checks.patch +Patch0081: backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1514,6 +1515,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Sep 14 2021 fangxiuning - 243-45 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:sd-event: re-check new epoll events when a child event is queued + * Thu Sep 9 2021 yangmingtai - 243-44 - fix network coredump after install cloud-init -- Gitee From 0db1e85d0e2d6ab710885e5a9e733a4b59653b4a Mon Sep 17 00:00:00 2001 From: fangxiuning Date: Tue, 14 Sep 2021 20:16:58 +0800 Subject: [PATCH 25/38] modify --- ...vent-re-check-new-epoll-events-when-a-child-even.patch | 6 +++--- systemd.spec | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch b/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch index 61d935c..17d4325 100644 --- a/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch +++ b/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch @@ -218,13 +218,13 @@ index 5d0e057..65db799 100644 case WAKEUP_SIGNAL_DATA: - r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events); -+ r = process_signal(e, e->event_queue[i].data.ptr, e->event_queue[i].events, &min_priority); ++ r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events, &min_priority); break; case WAKEUP_INOTIFY_DATA: - r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events); -+ r = event_inotify_data_read(e, e->event_queue[i].data.ptr, e->event_queue[i].events, thresh -+old); ++ r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events, threshold); ++ break; default: diff --git a/systemd.spec b/systemd.spec index 8fd912d..5e5f0c6 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 45 +Release: 46 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -1515,6 +1515,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Sep 14 2021 fangxiuning - 243-46 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:sd-event: fix typo erro + * Tue Sep 14 2021 fangxiuning - 243-45 - Type:bugfix - ID:NA -- Gitee From 28d54f66820e2b8b576a751d551d865e4165fc7c Mon Sep 17 00:00:00 2001 From: ExtinctFire Date: Thu, 16 Sep 2021 17:32:00 +0800 Subject: [PATCH 26/38] core: fix free undefined pointer when strdup failed in the first loop Signed-off-by: ExtinctFire --- ...defined-pointer-when-strdup-failed-i.patch | 33 +++++++++++++++++++ systemd.spec | 9 ++++- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 backport-core-fix-free-undefined-pointer-when-strdup-failed-i.patch diff --git a/backport-core-fix-free-undefined-pointer-when-strdup-failed-i.patch b/backport-core-fix-free-undefined-pointer-when-strdup-failed-i.patch new file mode 100644 index 0000000..17e0d0b --- /dev/null +++ b/backport-core-fix-free-undefined-pointer-when-strdup-failed-i.patch @@ -0,0 +1,33 @@ +From 1509274359979079e3e61899ce12fc8b0f0958d9 Mon Sep 17 00:00:00 2001 +From: xujing <17826839720@163.com> +Date: Wed, 8 Sep 2021 14:26:20 +0800 +Subject: [PATCH] core: fix free undefined pointer when strdup failed in the + first loop + +--- + src/core/load-fragment.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 92815b1dbaea..1c8159a23550 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -800,7 +800,7 @@ int config_parse_exec( + if (!separate_argv0) { + char *w = NULL; + +- if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) ++ if (!GREEDY_REALLOC0(n, nbufsize, nlen + 2)) + return log_oom(); + + w = strdup(path); +@@ -832,7 +832,7 @@ int config_parse_exec( + p += 2; + p += strspn(p, WHITESPACE); + +- if (!GREEDY_REALLOC(n, nbufsize, nlen + 2)) ++ if (!GREEDY_REALLOC0(n, nbufsize, nlen + 2)) + return log_oom(); + + w = strdup(";"); + diff --git a/systemd.spec b/systemd.spec index 5e5f0c6..ced946c 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 46 +Release: 47 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -128,6 +128,7 @@ Patch0078: backport-udev-make-algorithm-that-selects-highest-priority-de.pa Patch0079: backport-tentatively-ignore-FORCERENEW-command.patch Patch0080: backport-network-add-missing-link-network-checks.patch Patch0081: backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch +Patch0082: backport-core-fix-free-undefined-pointer-when-strdup-failed-i.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1515,6 +1516,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Thu Sep 16 2021 ExtinctFire - 243-47 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:core: fix free undefined pointer when strdup failed in the first loop + * Tue Sep 14 2021 fangxiuning - 243-46 - Type:bugfix - ID:NA -- Gitee From 51019f0a671d850e6a8c84d12838dad6c0dfa84c Mon Sep 17 00:00:00 2001 From: ExtinctFire Date: Wed, 27 Oct 2021 16:06:58 +0800 Subject: [PATCH 27/38] adapt to the new capsh format for test Signed-off-by: ExtinctFire --- ...t-test-adapt-to-the-new-capsh-format.patch | 107 ++++++++++++++++++ systemd.spec | 9 +- 2 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 backport-test-adapt-to-the-new-capsh-format.patch diff --git a/backport-test-adapt-to-the-new-capsh-format.patch b/backport-test-adapt-to-the-new-capsh-format.patch new file mode 100644 index 0000000..d2726c0 --- /dev/null +++ b/backport-test-adapt-to-the-new-capsh-format.patch @@ -0,0 +1,107 @@ +From 9569e385036c05c0bf9fbccdbf3d131161398e2e Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 4 Feb 2020 13:49:01 +0100 +Subject: [PATCH] test: adapt to the new capsh format + +Since libcap v2.29 the format of cap_to_text() has been changed which +makes certain `test-execute` subtest fail. Let's remove the offending +part of the output (dropped capabilities) to make it compatible with +both the old and the new libcap. +--- + test/test-execute/exec-capabilityboundingset-invert.service | 3 ++- + .../exec-privatedevices-no-capability-mknod.service | 3 ++- + .../exec-privatedevices-no-capability-sys-rawio.service | 3 ++- + .../exec-privatedevices-yes-capability-mknod.service | 3 ++- + .../exec-privatedevices-yes-capability-sys-rawio.service | 3 ++- + .../exec-protectkernelmodules-no-capabilities.service | 3 ++- + .../exec-protectkernelmodules-yes-capabilities.service | 3 ++- + 9 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/test/test-execute/exec-capabilityboundingset-invert.service b/test/test-execute/exec-capabilityboundingset-invert.service +index 1abe390601..5f37427603 100644 +--- a/test/test-execute/exec-capabilityboundingset-invert.service ++++ b/test/test-execute/exec-capabilityboundingset-invert.service +@@ -2,6 +2,7 @@ + Description=Test for CapabilityBoundingSet + + [Service] +-ExecStart=/bin/sh -x -c '! capsh --print | grep "^Bounding set .*cap_chown"' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep "^Bounding set .*cap_chown"' + Type=oneshot + CapabilityBoundingSet=~CAP_CHOWN +diff --git a/test/test-execute/exec-privatedevices-no-capability-mknod.service b/test/test-execute/exec-privatedevices-no-capability-mknod.service +index 6d39469da8..4d61d9ffaa 100644 +--- a/test/test-execute/exec-privatedevices-no-capability-mknod.service ++++ b/test/test-execute/exec-privatedevices-no-capability-mknod.service +@@ -3,5 +3,6 @@ Description=Test CAP_MKNOD capability for PrivateDevices=no + + [Service] + PrivateDevices=no +-ExecStart=/bin/sh -x -c 'capsh --print | grep cap_mknod' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_mknod' + Type=oneshot +diff --git a/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service +index e7f529c44c..f7f7a16736 100644 +--- a/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service ++++ b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service +@@ -3,5 +3,6 @@ Description=Test CAP_SYS_RAWIO capability for PrivateDevices=no + + [Service] + PrivateDevices=no +-ExecStart=/bin/sh -x -c 'capsh --print | grep cap_sys_rawio' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_rawio' + Type=oneshot +diff --git a/test/test-execute/exec-privatedevices-yes-capability-mknod.service b/test/test-execute/exec-privatedevices-yes-capability-mknod.service +index fb1fc2875a..5bcace0845 100644 +--- a/test/test-execute/exec-privatedevices-yes-capability-mknod.service ++++ b/test/test-execute/exec-privatedevices-yes-capability-mknod.service +@@ -3,5 +3,6 @@ Description=Test CAP_MKNOD capability for PrivateDevices=yes + + [Service] + PrivateDevices=yes +-ExecStart=/bin/sh -x -c '! capsh --print | grep cap_mknod' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_mknod' + Type=oneshot +diff --git a/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service +index cebc493a7a..a246f950c1 100644 +--- a/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service ++++ b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service +@@ -3,5 +3,6 @@ Description=Test CAP_SYS_RAWIO capability for PrivateDevices=yes + + [Service] + PrivateDevices=yes +-ExecStart=/bin/sh -x -c '! capsh --print | grep cap_sys_rawio' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_rawio' + Type=oneshot +diff --git a/test/test-execute/exec-protectkernelmodules-no-capabilities.service b/test/test-execute/exec-protectkernelmodules-no-capabilities.service +index b2f2cd6b8a..8d7e2b52d4 100644 +--- a/test/test-execute/exec-protectkernelmodules-no-capabilities.service ++++ b/test/test-execute/exec-protectkernelmodules-no-capabilities.service +@@ -3,5 +3,6 @@ Description=Test CAP_SYS_MODULE ProtectKernelModules=no + + [Service] + ProtectKernelModules=no +-ExecStart=/bin/sh -x -c 'capsh --print | grep cap_sys_module' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_module' + Type=oneshot +diff --git a/test/test-execute/exec-protectkernelmodules-yes-capabilities.service b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service +index 84bf39be56..fe2ae208dd 100644 +--- a/test/test-execute/exec-protectkernelmodules-yes-capabilities.service ++++ b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service +@@ -3,5 +3,6 @@ Description=Test CAP_SYS_MODULE for ProtectKernelModules=yes + + [Service] + ProtectKernelModules=yes +-ExecStart=/bin/sh -x -c '! capsh --print | grep cap_sys_module' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_module' + Type=oneshot +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index ced946c..8abb121 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 47 +Release: 48 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -129,6 +129,7 @@ Patch0079: backport-tentatively-ignore-FORCERENEW-command.patch Patch0080: backport-network-add-missing-link-network-checks.patch Patch0081: backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch Patch0082: backport-core-fix-free-undefined-pointer-when-strdup-failed-i.patch +Patch0083: backport-test-adapt-to-the-new-capsh-format.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1516,6 +1517,12 @@ fi %exclude /usr/share/man/man3/* %changelog +* Wed Oct 27 2021 ExtinctFire - 243-48 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:adapt to the new capsh format for test + * Thu Sep 16 2021 ExtinctFire - 243-47 - Type:bugfix - ID:NA -- Gitee From 202162fff3c525c6f3bf21cf0426dbe1daf2cf30 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Tue, 18 Jan 2022 17:19:43 +0800 Subject: [PATCH 28/38] fix CVE-2021-3997 --- ...3997-rm-rf-add-new-flag-REMOVE_CHMOD.patch | 206 +++++++++++ ...elper-that-abstracts-might-be-btrfs-.patch | 113 ++++++ ...ght-fail-if-containing-dir-has-limit.patch | 135 ++++++++ ...m_rf_children-split-out-body-of-dire.patch | 326 ++++++++++++++++++ ...-fsync-after-removing-directory-tree.patch | 45 +++ ...-st-may-have-been-used-uninitialized.patch | 33 ++ ...actor-rm_rf_children_inner-to-shorte.patch | 73 ++++ ...refactor-rm_rf-to-shorten-code-a-bit.patch | 105 ++++++ ...p-over-nested-directories-instead-of.patch | 270 +++++++++++++++ systemd.spec | 14 +- 10 files changed, 1319 insertions(+), 1 deletion(-) create mode 100644 backport-0001-CVE-2021-3997-rm-rf-add-new-flag-REMOVE_CHMOD.patch create mode 100644 backport-0002-CVE-2021-3997-btrfs-util-add-helper-that-abstracts-might-be-btrfs-.patch create mode 100644 backport-0003-CVE-2021-3997-rm-rf-fstatat-might-fail-if-containing-dir-has-limit.patch create mode 100644 backport-0004-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch create mode 100644 backport-0005-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch create mode 100644 backport-0006-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch create mode 100644 backport-0007-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch create mode 100644 backport-0008-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch create mode 100644 backport-0009-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch diff --git a/backport-0001-CVE-2021-3997-rm-rf-add-new-flag-REMOVE_CHMOD.patch b/backport-0001-CVE-2021-3997-rm-rf-add-new-flag-REMOVE_CHMOD.patch new file mode 100644 index 0000000..2dabe2e --- /dev/null +++ b/backport-0001-CVE-2021-3997-rm-rf-add-new-flag-REMOVE_CHMOD.patch @@ -0,0 +1,206 @@ +From 4d16bbb4de8cbcea2476bd8433be42c9d080e1f6 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 23 Jul 2020 15:24:54 +0200 +Subject: [PATCH 1/9] rm-rf: add new flag REMOVE_CHMOD + +Conflict:NA +Reference:https://github.com/systemd/systemd/commit/2899fb024f066f1cb14989fb470e188de7d6dc88 + +When removing a directory tree as unprivileged user we might encounter +files owned by us but not deletable since the containing directory might +have the "r" bit missing in its access mode. Let's try to deal with +this: optionally if we get EACCES try to set the bit and see if it works +then. +--- + src/basic/rm-rf.c | 54 ++++++++++++++++++++++++++----- + src/basic/rm-rf.h | 1 + + src/test/meson.build | 4 +++ + src/test/test-rm-rf.c | 74 +++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 125 insertions(+), 8 deletions(-) + create mode 100644 src/test/test-rm-rf.c + +diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c +index 796eb93..03b41f3 100644 +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -25,6 +25,46 @@ static bool is_physical_fs(const struct statfs *sfs) { + return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs); + } + ++static int unlinkat_harder( ++ int dfd, ++ const char *filename, ++ int unlink_flags, ++ RemoveFlags remove_flags) { ++ ++ struct stat st; ++ int r; ++ ++ /* Like unlinkat(), but tries harder: if we get EACCESS we'll try to set the r/w/x bits on the ++ * directory. This is useful if we run unprivileged and have some files where the w bit is ++ * missing. */ ++ ++ if (unlinkat(dfd, filename, unlink_flags) >= 0) ++ return 0; ++ if (errno != EACCES || !FLAGS_SET(remove_flags, REMOVE_CHMOD)) ++ return -errno; ++ ++ if (fstat(dfd, &st) < 0) ++ return -errno; ++ if (!S_ISDIR(st.st_mode)) ++ return -ENOTDIR; ++ if ((st.st_mode & 0700) == 0700) /* Already set? */ ++ return -EACCES; /* original error */ ++ if (st.st_uid != geteuid()) /* this only works if the UID matches ours */ ++ return -EACCES; ++ ++ if (fchmod(dfd, (st.st_mode | 0700) & 07777) < 0) ++ return -errno; ++ ++ if (unlinkat(dfd, filename, unlink_flags) < 0) { ++ r = -errno; ++ /* Try to restore the original access mode if this didn't work */ ++ (void) fchmod(dfd, st.st_mode & 07777); ++ return r; ++ } ++ ++ return 0; ++} ++ + int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { + _cleanup_closedir_ DIR *d = NULL; + struct dirent *de; +@@ -134,17 +174,15 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { + if (r < 0 && ret == 0) + ret = r; + +- if (unlinkat(fd, de->d_name, AT_REMOVEDIR) < 0) { +- if (ret == 0 && errno != ENOENT) +- ret = -errno; +- } ++ r = unlinkat_harder(fd, de->d_name, AT_REMOVEDIR, flags); ++ if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; + + } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { + +- if (unlinkat(fd, de->d_name, 0) < 0) { +- if (ret == 0 && errno != ENOENT) +- ret = -errno; +- } ++ r = unlinkat_harder(fd, de->d_name, 0, flags); ++ if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; + } + } + return ret; +diff --git a/src/basic/rm-rf.h b/src/basic/rm-rf.h +index 40cbff2..0edf01e 100644 +--- a/src/basic/rm-rf.h ++++ b/src/basic/rm-rf.h +@@ -11,6 +11,7 @@ typedef enum RemoveFlags { + REMOVE_PHYSICAL = 1 << 2, /* If not set, only removes files on tmpfs, never physical file systems */ + REMOVE_SUBVOLUME = 1 << 3, /* Drop btrfs subvolumes in the tree too */ + REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */ ++ REMOVE_CHMOD = 1 << 5, /* chmod() for write access if we cannot delete something */ + } RemoveFlags; + + int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev); +diff --git a/src/test/meson.build b/src/test/meson.build +index 3fcfa9f..255b00b 100644 +--- a/src/test/meson.build ++++ b/src/test/meson.build +@@ -631,6 +631,10 @@ tests += [ + [], + []], + ++ [['src/test/test-rm-rf.c'], ++ [], ++ []], ++ + [['src/test/test-chase-symlinks.c'], + [], + [], +diff --git a/src/test/test-rm-rf.c b/src/test/test-rm-rf.c +new file mode 100644 +index 0000000..d6e426c +--- /dev/null ++++ b/src/test/test-rm-rf.c +@@ -0,0 +1,74 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include ++ ++#include "alloc-util.h" ++#include "process-util.h" ++#include "rm-rf.h" ++#include "string-util.h" ++#include "tests.h" ++#include "tmpfile-util.h" ++ ++static void test_rm_rf_chmod_inner(void) { ++ _cleanup_free_ char *d = NULL; ++ const char *x, *y; ++ ++ assert_se(getuid() != 0); ++ ++ assert_se(mkdtemp_malloc(NULL, &d) >= 0); ++ ++ x = strjoina(d, "/d"); ++ assert_se(mkdir(x, 0700) >= 0); ++ y = strjoina(x, "/f"); ++ assert_se(mknod(y, S_IFREG | 0600, 0) >= 0); ++ ++ assert_se(chmod(y, 0400) >= 0); ++ assert_se(chmod(x, 0500) >= 0); ++ assert_se(chmod(d, 0500) >= 0); ++ ++ assert_se(rm_rf(d, REMOVE_PHYSICAL|REMOVE_ROOT) == -EACCES); ++ ++ assert_se(access(d, F_OK) >= 0); ++ assert_se(access(x, F_OK) >= 0); ++ assert_se(access(y, F_OK) >= 0); ++ ++ assert_se(rm_rf(d, REMOVE_PHYSICAL|REMOVE_ROOT|REMOVE_CHMOD) >= 0); ++ ++ errno = 0; ++ assert_se(access(d, F_OK) < 0 && errno == ENOENT); ++} ++ ++static void test_rm_rf_chmod(void) { ++ int r; ++ ++ log_info("/* %s */", __func__); ++ ++ if (getuid() == 0) { ++ /* This test only works unpriv (as only then the access mask for the owning user matters), ++ * hence drop privs here */ ++ ++ r = safe_fork("(setresuid)", FORK_DEATHSIG|FORK_WAIT, NULL); ++ assert_se(r >= 0); ++ ++ if (r == 0) { ++ /* child */ ++ ++ assert_se(setresuid(1, 1, 1) >= 0); ++ ++ test_rm_rf_chmod_inner(); ++ _exit(EXIT_SUCCESS); ++ } ++ ++ return; ++ } ++ ++ test_rm_rf_chmod_inner(); ++} ++ ++int main(int argc, char **argv) { ++ test_setup_logging(LOG_DEBUG); ++ ++ test_rm_rf_chmod(); ++ ++ return 0; ++} +-- +2.23.0 + diff --git a/backport-0002-CVE-2021-3997-btrfs-util-add-helper-that-abstracts-might-be-btrfs-.patch b/backport-0002-CVE-2021-3997-btrfs-util-add-helper-that-abstracts-might-be-btrfs-.patch new file mode 100644 index 0000000..d8c87ac --- /dev/null +++ b/backport-0002-CVE-2021-3997-btrfs-util-add-helper-that-abstracts-might-be-btrfs-.patch @@ -0,0 +1,113 @@ +From 318ea885ca5a8466842b4808ac631473229bd970 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 26 Feb 2021 17:39:55 +0100 +Subject: [PATCH 2/9] btrfs-util: add helper that abstracts "might be btrfs + subvol?" check + +Conflict:adapt context +Reference:https://github.com/systemd/systemd/commit/674b04ff1b6deab17f5d36c036c0275ba94e1ebc + +Let#s not hardcode inode nr 256 everywhere, but abstract this check +slightly. + +(cherry picked from commit 674b04ff1b6deab17f5d36c036c0275ba94e1ebc) +--- + src/basic/btrfs-util.c | 6 +++--- + src/basic/btrfs-util.h | 10 ++++++++++ + src/basic/rm-rf.c | 2 +- + src/import/export-tar.c | 2 +- + src/shared/machine-image.c | 3 +-- + 5 files changed, 16 insertions(+), 7 deletions(-) + +diff --git a/src/basic/btrfs-util.c b/src/basic/btrfs-util.c +index 540a199..e55378e 100644 +--- a/src/basic/btrfs-util.c ++++ b/src/basic/btrfs-util.c +@@ -94,7 +94,7 @@ int btrfs_is_subvol_fd(int fd) { + if (fstat(fd, &st) < 0) + return -errno; + +- if (!S_ISDIR(st.st_mode) || st.st_ino != 256) ++ if (!btrfs_might_be_subvol(&st)) + return 0; + + return btrfs_is_filesystem(fd); +@@ -172,7 +172,7 @@ int btrfs_subvol_set_read_only_fd(int fd, bool b) { + if (fstat(fd, &st) < 0) + return -errno; + +- if (!S_ISDIR(st.st_mode) || st.st_ino != 256) ++ if (!btrfs_might_be_subvol(&st)) + return -EINVAL; + + if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0) +@@ -211,7 +211,7 @@ int btrfs_subvol_get_read_only_fd(int fd) { + if (fstat(fd, &st) < 0) + return -errno; + +- if (!S_ISDIR(st.st_mode) || st.st_ino != 256) ++ if (!btrfs_might_be_subvol(&st)) + return -EINVAL; + + if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0) +diff --git a/src/basic/btrfs-util.h b/src/basic/btrfs-util.h +index b15667b..0acd125 100644 +--- a/src/basic/btrfs-util.h ++++ b/src/basic/btrfs-util.h +@@ -119,3 +119,13 @@ int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret); + + int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *quota); + int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *quota); ++ ++static inline bool btrfs_might_be_subvol(const struct stat *st) { ++ if (!st) ++ return false; ++ ++ /* Returns true if this 'struct stat' looks like it could refer to a btrfs subvolume. To make a final ++ * decision, needs to be combined with an fstatfs() check to see if this is actually btrfs. */ ++ ++ return S_ISDIR(st->st_mode) && st->st_ino == 256; ++} +diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c +index 03b41f3..26b943e 100644 +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -149,7 +149,7 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { + if (r > 0) + continue; + +- if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) { ++ if ((flags & REMOVE_SUBVOLUME) && btrfs_might_be_subvol(&st)) { + + /* This could be a subvolume, try to remove it */ + +diff --git a/src/import/export-tar.c b/src/import/export-tar.c +index ed54676..aa5c717 100644 +--- a/src/import/export-tar.c ++++ b/src/import/export-tar.c +@@ -284,7 +284,7 @@ int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType + + e->quota_referenced = (uint64_t) -1; + +- if (e->st.st_ino == 256) { /* might be a btrfs subvolume? */ ++ if (btrfs_might_be_subvol(&e->st)) { + BtrfsQuotaInfo q; + + r = btrfs_subvol_get_subtree_quota_fd(sfd, 0, &q); +diff --git a/src/shared/machine-image.c b/src/shared/machine-image.c +index 7007374..07bb80c 100644 +--- a/src/shared/machine-image.c ++++ b/src/shared/machine-image.c +@@ -249,8 +249,7 @@ static int image_make( + if (fd < 0) + return -errno; + +- /* btrfs subvolumes have inode 256 */ +- if (st->st_ino == 256) { ++ if (btrfs_might_be_subvol(st)) { + + r = btrfs_is_filesystem(fd); + if (r < 0) +-- +2.23.0 + diff --git a/backport-0003-CVE-2021-3997-rm-rf-fstatat-might-fail-if-containing-dir-has-limit.patch b/backport-0003-CVE-2021-3997-rm-rf-fstatat-might-fail-if-containing-dir-has-limit.patch new file mode 100644 index 0000000..def3782 --- /dev/null +++ b/backport-0003-CVE-2021-3997-rm-rf-fstatat-might-fail-if-containing-dir-has-limit.patch @@ -0,0 +1,135 @@ +From 3e4d0a7c37021bc5f75fa429991f597428d1b63a Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 26 Jan 2021 16:47:07 +0100 +Subject: [PATCH 3/9] rm-rf: fstatat() might fail if containing dir has limited + access mode, patch that too + +Conflict:according 1d6cc5d0e5658848ac8cce5da22626d17f15b1ec, use FLAGS_SET +instead of "==" +Reference:https://github.com/systemd/systemd/commit/1b55621dabf741dd963f59ac706ea62cd6e3e95c + +(cherry picked from commit 1b55621dabf741dd963f59ac706ea62cd6e3e95c) +--- + src/basic/rm-rf.c | 82 ++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 66 insertions(+), 16 deletions(-) + +diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c +index 26b943e..602266d 100644 +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -25,13 +25,38 @@ static bool is_physical_fs(const struct statfs *sfs) { + return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs); + } + ++static int patch_dirfd_mode( ++ int dfd, ++ mode_t *ret_old_mode) { ++ ++ struct stat st; ++ ++ assert(dfd >= 0); ++ assert(ret_old_mode); ++ ++ if (fstat(dfd, &st) < 0) ++ return -errno; ++ if (!S_ISDIR(st.st_mode)) ++ return -ENOTDIR; ++ if (FLAGS_SET(st.st_mode, 0700)) /* Already set? */ ++ return -EACCES; /* original error */ ++ if (st.st_uid != geteuid()) /* this only works if the UID matches ours */ ++ return -EACCES; ++ ++ if (fchmod(dfd, (st.st_mode | 0700) & 07777) < 0) ++ return -errno; ++ ++ *ret_old_mode = st.st_mode; ++ return 0; ++} ++ + static int unlinkat_harder( + int dfd, + const char *filename, + int unlink_flags, + RemoveFlags remove_flags) { + +- struct stat st; ++ mode_t old_mode; + int r; + + /* Like unlinkat(), but tries harder: if we get EACCESS we'll try to set the r/w/x bits on the +@@ -43,22 +68,46 @@ static int unlinkat_harder( + if (errno != EACCES || !FLAGS_SET(remove_flags, REMOVE_CHMOD)) + return -errno; + +- if (fstat(dfd, &st) < 0) +- return -errno; +- if (!S_ISDIR(st.st_mode)) +- return -ENOTDIR; +- if ((st.st_mode & 0700) == 0700) /* Already set? */ +- return -EACCES; /* original error */ +- if (st.st_uid != geteuid()) /* this only works if the UID matches ours */ +- return -EACCES; +- +- if (fchmod(dfd, (st.st_mode | 0700) & 07777) < 0) +- return -errno; ++ r = patch_dirfd_mode(dfd, &old_mode); ++ if (r < 0) ++ return r; + + if (unlinkat(dfd, filename, unlink_flags) < 0) { + r = -errno; + /* Try to restore the original access mode if this didn't work */ +- (void) fchmod(dfd, st.st_mode & 07777); ++ (void) fchmod(dfd, old_mode); ++ return r; ++ } ++ ++ /* If this worked, we won't reset the old mode, since we'll need it for other entries too, and we ++ * should destroy the whole thing */ ++ return 0; ++} ++ ++static int fstatat_harder( ++ int dfd, ++ const char *filename, ++ struct stat *ret, ++ int fstatat_flags, ++ RemoveFlags remove_flags) { ++ ++ mode_t old_mode; ++ int r; ++ ++ /* Like unlink_harder() but does the same for fstatat() */ ++ ++ if (fstatat(dfd, filename, ret, fstatat_flags) >= 0) ++ return 0; ++ if (errno != EACCES || !FLAGS_SET(remove_flags, REMOVE_CHMOD)) ++ return -errno; ++ ++ r = patch_dirfd_mode(dfd, &old_mode); ++ if (r < 0) ++ return r; ++ ++ if (fstatat(dfd, filename, ret, fstatat_flags) < 0) { ++ r = -errno; ++ (void) fchmod(dfd, old_mode); + return r; + } + +@@ -114,9 +163,10 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { + + if (de->d_type == DT_UNKNOWN || + (de->d_type == DT_DIR && (root_dev || (flags & REMOVE_SUBVOLUME)))) { +- if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { +- if (ret == 0 && errno != ENOENT) +- ret = -errno; ++ r = fstatat_harder(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW, flags); ++ if (r < 0) { ++ if (ret == 0 && r != -ENOENT) ++ ret = r; + continue; + } + +-- +2.23.0 + diff --git a/backport-0004-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch b/backport-0004-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch new file mode 100644 index 0000000..1ba94f4 --- /dev/null +++ b/backport-0004-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch @@ -0,0 +1,326 @@ +From 6e1da1342eed3bcd1cd7dfb7f78d26a29d2a8b12 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 26 Jan 2021 16:30:06 +0100 +Subject: [PATCH 4/9] rm-rf: refactor rm_rf_children(), split out body of + directory iteration loop + +Conflict:modify files in basic instead of shared +Reference:https://github.com/systemd/systemd/commit/1f0fb7d544711248cba34615e43c5a76bc902d74 + +This splits out rm_rf_children_inner() as body of the loop. We can use +that to implement rm_rf_child() for deleting one specific entry in a +directory. + +(cherry picked from commit 1f0fb7d544711248cba34615e43c5a76bc902d74) +(cherry picked from commit ca4a0e7d41f0b2a1fe2f99dbc3763187c16cf7ab) +(cherry picked from commit 85ccac3393e78d4bf2776ffb8c3a1d8a2a909a2a) +--- + src/basic/rm-rf.c | 223 +++++++++++++++++++++++++++------------------- + src/basic/rm-rf.h | 3 +- + 2 files changed, 131 insertions(+), 95 deletions(-) + +diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c +index 602266d..8e3eb59 100644 +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -21,6 +21,9 @@ + #include "stat-util.h" + #include "string-util.h" + ++/* We treat tmpfs/ramfs + cgroupfs as non-physical file sytems. cgroupfs is similar to tmpfs in a way after ++ * all: we can create arbitrary directory hierarchies in it, and hence can also use rm_rf() on it to remove ++ * those again. */ + static bool is_physical_fs(const struct statfs *sfs) { + return !is_temporary_fs(sfs) && !is_cgroup_fs(sfs); + } +@@ -114,133 +117,145 @@ static int fstatat_harder( + return 0; + } + +-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) { +- _cleanup_closedir_ DIR *d = NULL; +- struct dirent *de; +- int ret = 0, r; +- struct statfs sfs; ++static int rm_rf_children_inner( ++ int fd, ++ const char *fname, ++ int is_dir, ++ RemoveFlags flags, ++ const struct stat *root_dev) { + +- assert(fd >= 0); ++ struct stat st; ++ int r; + +- /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed +- * fd, in all cases, including on failure.. */ ++ assert(fd >= 0); ++ assert(fname); + +- if (!(flags & REMOVE_PHYSICAL)) { ++ if (is_dir < 0 || (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) { + +- r = fstatfs(fd, &sfs); +- if (r < 0) { +- safe_close(fd); +- return -errno; +- } ++ r = fstatat_harder(fd, fname, &st, AT_SYMLINK_NOFOLLOW, flags); ++ if (r < 0) ++ return r; + +- if (is_physical_fs(&sfs)) { +- /* We refuse to clean physical file systems with this call, +- * unless explicitly requested. This is extra paranoia just +- * to be sure we never ever remove non-state data. */ +- _cleanup_free_ char *path = NULL; ++ is_dir = S_ISDIR(st.st_mode); ++ } + +- (void) fd_get_path(fd, &path); +- log_error("Attempted to remove disk file system under \"%s\", and we can't allow that.", +- strna(path)); ++ if (is_dir) { ++ _cleanup_close_ int subdir_fd = -1; ++ int q; + +- safe_close(fd); +- return -EPERM; +- } +- } ++ /* if root_dev is set, remove subdirectories only if device is same */ ++ if (root_dev && st.st_dev != root_dev->st_dev) ++ return 0; + +- d = fdopendir(fd); +- if (!d) { +- safe_close(fd); +- return errno == ENOENT ? 0 : -errno; +- } ++ /* Stop at mount points */ ++ r = fd_is_mount_point(fd, fname, 0); ++ if (r < 0) ++ return r; ++ if (r > 0) ++ return 0; + +- FOREACH_DIRENT_ALL(de, d, return -errno) { +- bool is_dir; +- struct stat st; ++ if ((flags & REMOVE_SUBVOLUME) && btrfs_might_be_subvol(&st)) { + +- if (dot_or_dot_dot(de->d_name)) +- continue; ++ /* This could be a subvolume, try to remove it */ + +- if (de->d_type == DT_UNKNOWN || +- (de->d_type == DT_DIR && (root_dev || (flags & REMOVE_SUBVOLUME)))) { +- r = fstatat_harder(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW, flags); ++ r = btrfs_subvol_remove_fd(fd, fname, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); + if (r < 0) { +- if (ret == 0 && r != -ENOENT) +- ret = r; +- continue; +- } ++ if (!IN_SET(r, -ENOTTY, -EINVAL)) ++ return r; + +- is_dir = S_ISDIR(st.st_mode); +- } else +- is_dir = de->d_type == DT_DIR; ++ /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */ ++ } else ++ /* It was a subvolume, done. */ ++ return 1; ++ } + +- if (is_dir) { +- _cleanup_close_ int subdir_fd = -1; ++ subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); ++ if (subdir_fd < 0) ++ return -errno; + +- /* if root_dev is set, remove subdirectories only if device is same */ +- if (root_dev && st.st_dev != root_dev->st_dev) +- continue; ++ /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file system type ++ * again for each directory */ ++ q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); + +- subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); +- if (subdir_fd < 0) { +- if (ret == 0 && errno != ENOENT) +- ret = -errno; +- continue; +- } ++ r = unlinkat_harder(fd, fname, AT_REMOVEDIR, flags); ++ if (r < 0) ++ return r; ++ if (q < 0) ++ return q; + +- /* Stop at mount points */ +- r = fd_is_mount_point(fd, de->d_name, 0); +- if (r < 0) { +- if (ret == 0 && r != -ENOENT) +- ret = r; ++ return 1; + +- continue; +- } +- if (r > 0) +- continue; ++ } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { ++ r = unlinkat_harder(fd, fname, 0, flags); ++ if (r < 0) ++ return r; + +- if ((flags & REMOVE_SUBVOLUME) && btrfs_might_be_subvol(&st)) { ++ return 1; ++ } + +- /* This could be a subvolume, try to remove it */ ++ return 0; ++} + +- r = btrfs_subvol_remove_fd(fd, de->d_name, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); +- if (r < 0) { +- if (!IN_SET(r, -ENOTTY, -EINVAL)) { +- if (ret == 0) +- ret = r; ++int rm_rf_children( ++ int fd, ++ RemoveFlags flags, ++ const struct stat *root_dev) { + +- continue; +- } ++ _cleanup_closedir_ DIR *d = NULL; ++ struct dirent *de; ++ int ret = 0, r; + +- /* ENOTTY, then it wasn't a btrfs subvolume, continue below. */ +- } else +- /* It was a subvolume, continue. */ +- continue; +- } ++ assert(fd >= 0); ++ ++ /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed ++ * fd, in all cases, including on failure. */ ++ ++ d = fdopendir(fd); ++ if (!d) { ++ safe_close(fd); ++ return -errno; ++ } + +- /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file +- * system type again for each directory */ +- r = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); +- if (r < 0 && ret == 0) +- ret = r; ++ if (!(flags & REMOVE_PHYSICAL)) { ++ struct statfs sfs; + +- r = unlinkat_harder(fd, de->d_name, AT_REMOVEDIR, flags); +- if (r < 0 && r != -ENOENT && ret == 0) +- ret = r; ++ if (fstatfs(dirfd(d), &sfs) < 0) ++ return -errno; ++ ++ if (is_physical_fs(&sfs)) { ++ /* We refuse to clean physical file systems with this call, unless explicitly ++ * requested. This is extra paranoia just to be sure we never ever remove non-state ++ * data. */ + +- } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { ++ _cleanup_free_ char *path = NULL; + +- r = unlinkat_harder(fd, de->d_name, 0, flags); +- if (r < 0 && r != -ENOENT && ret == 0) +- ret = r; ++ (void) fd_get_path(fd, &path); ++ return log_error_errno(SYNTHETIC_ERRNO(EPERM), ++ "Attempted to remove disk file system under \"%s\", and we can't allow that.", ++ strna(path)); + } + } ++ ++ FOREACH_DIRENT_ALL(de, d, return -errno) { ++ int is_dir; ++ ++ if (dot_or_dot_dot(de->d_name)) ++ continue; ++ ++ is_dir = ++ de->d_type == DT_UNKNOWN ? -1 : ++ de->d_type == DT_DIR; ++ ++ r = rm_rf_children_inner(dirfd(d), de->d_name, is_dir, flags, root_dev); ++ if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; ++ } ++ + return ret; + } + + int rm_rf(const char *path, RemoveFlags flags) { + int fd, r; +- struct statfs s; + + assert(path); + +@@ -285,9 +300,10 @@ int rm_rf(const char *path, RemoveFlags flags) { + if (FLAGS_SET(flags, REMOVE_ROOT)) { + + if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { ++ struct statfs s; ++ + if (statfs(path, &s) < 0) + return -errno; +- + if (is_physical_fs(&s)) + return log_error_errno(SYNTHETIC_ERRNO(EPERM), + "Attempted to remove files from a disk file system under \"%s\", refusing.", +@@ -315,3 +331,22 @@ int rm_rf(const char *path, RemoveFlags flags) { + + return r; + } ++ ++int rm_rf_child(int fd, const char *name, RemoveFlags flags) { ++ ++ /* Removes one specific child of the specified directory */ ++ ++ if (fd < 0) ++ return -EBADF; ++ ++ if (!filename_is_valid(name)) ++ return -EINVAL; ++ ++ if ((flags & (REMOVE_ROOT|REMOVE_MISSING_OK)) != 0) /* Doesn't really make sense here, we are not supposed to remove 'fd' anyway */ ++ return -EINVAL; ++ ++ if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME)) ++ return -EINVAL; ++ ++ return rm_rf_children_inner(fd, name, -1, flags, NULL); ++} +diff --git a/src/basic/rm-rf.h b/src/basic/rm-rf.h +index 0edf01e..15f7a87 100644 +--- a/src/basic/rm-rf.h ++++ b/src/basic/rm-rf.h +@@ -14,7 +14,8 @@ typedef enum RemoveFlags { + REMOVE_CHMOD = 1 << 5, /* chmod() for write access if we cannot delete something */ + } RemoveFlags; + +-int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev); ++int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev); ++int rm_rf_child(int fd, const char *name, RemoveFlags flags); + int rm_rf(const char *path, RemoveFlags flags); + + /* Useful for usage with _cleanup_(), destroys a directory and frees the pointer */ +-- +2.23.0 + diff --git a/backport-0005-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch b/backport-0005-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch new file mode 100644 index 0000000..a9646a9 --- /dev/null +++ b/backport-0005-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch @@ -0,0 +1,45 @@ +From 1a1d36c2e421f496b52f5e607c1d5bcfa61df2e5 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 5 Oct 2021 10:32:56 +0200 +Subject: [PATCH 5/9] rm-rf: optionally fsync() after removing directory tree + +Conflict:modify files in basic instead of shared +Reference:https://github.com/systemd/systemd/commit/bdfe7ada0d4d66e6d6e65f2822acbb1ec230f9c2 + +(cherry picked from commit bdfe7ada0d4d66e6d6e65f2822acbb1ec230f9c2) +(cherry picked from commit 2426beacca09d84091759be45b25c88116302184) +(cherry picked from commit 0e180f8e9c25c707b0465ad1b9447a4360f785f1) +--- + src/basic/rm-rf.c | 3 +++ + src/basic/rm-rf.h | 1 + + 2 files changed, 4 insertions(+) + +diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c +index 8e3eb59..4e46654 100644 +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -251,6 +251,9 @@ int rm_rf_children( + ret = r; + } + ++ if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(dirfd(d)) < 0 && ret >= 0) ++ ret = -errno; ++ + return ret; + } + +diff --git a/src/basic/rm-rf.h b/src/basic/rm-rf.h +index 15f7a87..1ecd552 100644 +--- a/src/basic/rm-rf.h ++++ b/src/basic/rm-rf.h +@@ -12,6 +12,7 @@ typedef enum RemoveFlags { + REMOVE_SUBVOLUME = 1 << 3, /* Drop btrfs subvolumes in the tree too */ + REMOVE_MISSING_OK = 1 << 4, /* If the top-level directory is missing, ignore the ENOENT for it */ + REMOVE_CHMOD = 1 << 5, /* chmod() for write access if we cannot delete something */ ++ REMOVE_SYNCFS = 1 << 6, /* syncfs() the root of the specified directory after removing everything in it */ + } RemoveFlags; + + int rm_rf_children(int fd, RemoveFlags flags, const struct stat *root_dev); +-- +2.23.0 + diff --git a/backport-0006-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch b/backport-0006-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch new file mode 100644 index 0000000..dba23ad --- /dev/null +++ b/backport-0006-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch @@ -0,0 +1,33 @@ +From c8de3762ec6de66884be0c5313d3872f869c4ee0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 23 Nov 2021 15:05:58 +0100 +Subject: [PATCH 6/9] tmpfiles: 'st' may have been used uninitialized + +Conflict:modify file in basic instead of shared +Reference:https://github.com/systemd/systemd/commit/160dadc0350c77d612aa9d5569f57d9bc84c3dca + +(cherry picked from commit 160dadc0350c77d612aa9d5569f57d9bc84c3dca) +(cherry picked from commit 7563de501246dccf5a9ea229933481aa1e7bd5c9) +(cherry picked from commit f54b97b1d05052bfee824ecc03ae9f07f6c37be8) +--- + src/basic/rm-rf.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c +index 4e46654..ad1f286 100644 +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -130,7 +130,9 @@ static int rm_rf_children_inner( + assert(fd >= 0); + assert(fname); + +- if (is_dir < 0 || (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) { ++ if (is_dir < 0 || ++ root_dev || ++ (is_dir > 0 && (root_dev || (flags & REMOVE_SUBVOLUME)))) { + + r = fstatat_harder(fd, fname, &st, AT_SYMLINK_NOFOLLOW, flags); + if (r < 0) +-- +2.23.0 + diff --git a/backport-0007-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch b/backport-0007-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch new file mode 100644 index 0000000..dfdc7e0 --- /dev/null +++ b/backport-0007-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch @@ -0,0 +1,73 @@ +From c5e7d1c9cf03542896d4fd994bee1d7b05ad6f2c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 23 Nov 2021 15:55:45 +0100 +Subject: [PATCH 7/9] shared/rm_rf: refactor rm_rf_children_inner() to shorten + code a bit + +Conflict:modify file in basic instead of shared +Reference:https://github.com/systemd/systemd/commit/3bac86abfa1b1720180840ffb9d06b3d54841c11 + +(cherry picked from commit 3bac86abfa1b1720180840ffb9d06b3d54841c11) +(cherry picked from commit 47741ff9eae6311a03e4d3d837128191826a4a3a) +(cherry picked from commit 89395b63f04f1acc0db533c32637ea20379f97c0) +(cherry picked from commit 3976f244990aa1210ebe018647f32ab060e1c3d3) +--- + src/basic/rm-rf.c | 27 +++++++++------------------ + 1 file changed, 9 insertions(+), 18 deletions(-) + +diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c +index ad1f286..c1c7bd1 100644 +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -125,7 +125,7 @@ static int rm_rf_children_inner( + const struct stat *root_dev) { + + struct stat st; +- int r; ++ int r, q = 0; + + assert(fd >= 0); + assert(fname); +@@ -143,7 +143,6 @@ static int rm_rf_children_inner( + + if (is_dir) { + _cleanup_close_ int subdir_fd = -1; +- int q; + + /* if root_dev is set, remove subdirectories only if device is same */ + if (root_dev && st.st_dev != root_dev->st_dev) +@@ -179,23 +178,15 @@ static int rm_rf_children_inner( + * again for each directory */ + q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); + +- r = unlinkat_harder(fd, fname, AT_REMOVEDIR, flags); +- if (r < 0) +- return r; +- if (q < 0) +- return q; +- +- return 1; +- +- } else if (!(flags & REMOVE_ONLY_DIRECTORIES)) { +- r = unlinkat_harder(fd, fname, 0, flags); +- if (r < 0) +- return r; +- +- return 1; +- } ++ } else if (flags & REMOVE_ONLY_DIRECTORIES) ++ return 0; + +- return 0; ++ r = unlinkat_harder(fd, fname, is_dir ? AT_REMOVEDIR : 0, flags); ++ if (r < 0) ++ return r; ++ if (q < 0) ++ return q; ++ return 1; + } + + int rm_rf_children( +-- +2.23.0 + diff --git a/backport-0008-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch b/backport-0008-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch new file mode 100644 index 0000000..12c3c10 --- /dev/null +++ b/backport-0008-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch @@ -0,0 +1,105 @@ +From 1ee928ffda0d202ded617d8e25ba92e62306c1cd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 23 Nov 2021 16:56:42 +0100 +Subject: [PATCH 8/9] shared/rm_rf: refactor rm_rf() to shorten code a bit + +Conflict:modify file in basic instead of shared +Reference:https://github.com/systemd/systemd/commit/84ced330020c0bae57bd4628f1f44eec91304e69 + +(cherry picked from commit 84ced330020c0bae57bd4628f1f44eec91304e69) +(cherry picked from commit 664529efa9431edc043126013ea54e6c399ae2d3) +(cherry picked from commit 811b137d6137cc3e8932599e6ef9254ba43ff5eb) +(cherry picked from commit 39a53d4f1445a8981efd0adcc1734dfad46647c5) +--- + src/basic/rm-rf.c | 54 +++++++++++++++++++++-------------------------- + 1 file changed, 24 insertions(+), 30 deletions(-) + +diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c +index c1c7bd1..3b1a920 100644 +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -251,7 +251,7 @@ int rm_rf_children( + } + + int rm_rf(const char *path, RemoveFlags flags) { +- int fd, r; ++ int fd, r, q = 0; + + assert(path); + +@@ -283,49 +283,43 @@ int rm_rf(const char *path, RemoveFlags flags) { + } + + fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); +- if (fd < 0) { ++ if (fd >= 0) { ++ /* We have a dir */ ++ r = rm_rf_children(fd, flags, NULL); ++ ++ if (FLAGS_SET(flags, REMOVE_ROOT) && rmdir(path) < 0) ++ q = -errno; ++ } else { + if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT) + return 0; + + if (!IN_SET(errno, ENOTDIR, ELOOP)) + return -errno; + +- if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES)) ++ if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES) || !FLAGS_SET(flags, REMOVE_ROOT)) + return 0; + +- if (FLAGS_SET(flags, REMOVE_ROOT)) { +- +- if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { +- struct statfs s; +- +- if (statfs(path, &s) < 0) +- return -errno; +- if (is_physical_fs(&s)) +- return log_error_errno(SYNTHETIC_ERRNO(EPERM), +- "Attempted to remove files from a disk file system under \"%s\", refusing.", +- path); +- } +- +- if (unlink(path) < 0) { +- if (FLAGS_SET(flags, REMOVE_MISSING_OK) && errno == ENOENT) +- return 0; ++ if (!FLAGS_SET(flags, REMOVE_PHYSICAL)) { ++ struct statfs s; + ++ if (statfs(path, &s) < 0) + return -errno; +- } ++ if (is_physical_fs(&s)) ++ return log_error_errno(SYNTHETIC_ERRNO(EPERM), ++ "Attempted to remove files from a disk file system under \"%s\", refusing.", ++ path); + } + +- return 0; ++ r = 0; ++ if (unlink(path) < 0) ++ q = -errno; + } + +- r = rm_rf_children(fd, flags, NULL); +- +- if (FLAGS_SET(flags, REMOVE_ROOT) && +- rmdir(path) < 0 && +- r >= 0 && +- (!FLAGS_SET(flags, REMOVE_MISSING_OK) || errno != ENOENT)) +- r = -errno; +- +- return r; ++ if (r < 0) ++ return r; ++ if (q < 0 && (q != -ENOENT || !FLAGS_SET(flags, REMOVE_MISSING_OK))) ++ return q; ++ return 0; + } + + int rm_rf_child(int fd, const char *name, RemoveFlags flags) { +-- +2.23.0 + diff --git a/backport-0009-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch b/backport-0009-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch new file mode 100644 index 0000000..f42af39 --- /dev/null +++ b/backport-0009-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch @@ -0,0 +1,270 @@ +From fd956e3df0c64035a2de244bb39ff9345d7c9423 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 30 Nov 2021 22:29:05 +0100 +Subject: [PATCH 9/9] shared/rm-rf: loop over nested directories instead of + instead of recursing + +Conflict:modify file in basic instead of shared +Reference:https://github.com/systemd/systemd/commit/5b1cf7a9be37e20133c0208005274ce4a5b5c6a1 + +To remove directory structures, we need to remove the innermost items first, +and then recursively remove higher-level directories. We would recursively +descend into directories and invoke rm_rf_children and rm_rm_children_inner. +This is problematic when too many directories are nested. + +Instead, let's create a "TODO" queue. In the the queue, for each level we +hold the DIR* object we were working on, and the name of the directory. This +allows us to leave a partially-processed directory, and restart the removal +loop one level down. When done with the inner directory, we use the name to +unlinkat() it from the parent, and proceed with the removal of other items. + +Because the nesting is increased by one level, it is best to view this patch +with -b/--ignore-space-change. + +This fixes CVE-2021-3997, https://bugzilla.redhat.com/show_bug.cgi?id=2024639. +The issue was reported and patches reviewed by Qualys Team. +Mauro Matteo Cascella and Riccardo Schirone from Red Hat handled the disclosure. + +(cherry picked from commit 5b1cf7a9be37e20133c0208005274ce4a5b5c6a1) +(cherry picked from commit 911516e1614e435755814ada5fc6064fa107a105) +(cherry picked from commit 6a28f8b55904c818b25e4db2e1511faac79fd471) +(cherry picked from commit c752f27b7647c99b4a17477c99d84fd8c950ddf0) +--- + src/basic/rm-rf.c | 160 ++++++++++++++++++++++++++++++++-------------- + 1 file changed, 113 insertions(+), 47 deletions(-) + +diff --git a/src/basic/rm-rf.c b/src/basic/rm-rf.c +index 3b1a920..b7ecb27 100644 +--- a/src/basic/rm-rf.c ++++ b/src/basic/rm-rf.c +@@ -117,12 +117,13 @@ static int fstatat_harder( + return 0; + } + +-static int rm_rf_children_inner( ++static int rm_rf_inner_child( + int fd, + const char *fname, + int is_dir, + RemoveFlags flags, +- const struct stat *root_dev) { ++ const struct stat *root_dev, ++ bool allow_recursion) { + + struct stat st; + int r, q = 0; +@@ -142,9 +143,7 @@ static int rm_rf_children_inner( + } + + if (is_dir) { +- _cleanup_close_ int subdir_fd = -1; +- +- /* if root_dev is set, remove subdirectories only if device is same */ ++ /* If root_dev is set, remove subdirectories only if device is same */ + if (root_dev && st.st_dev != root_dev->st_dev) + return 0; + +@@ -156,7 +155,6 @@ static int rm_rf_children_inner( + return 0; + + if ((flags & REMOVE_SUBVOLUME) && btrfs_might_be_subvol(&st)) { +- + /* This could be a subvolume, try to remove it */ + + r = btrfs_subvol_remove_fd(fd, fname, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA); +@@ -170,13 +168,16 @@ static int rm_rf_children_inner( + return 1; + } + +- subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); ++ if (!allow_recursion) ++ return -EISDIR; ++ ++ int subdir_fd = openat(fd, fname, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + if (subdir_fd < 0) + return -errno; + + /* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file system type + * again for each directory */ +- q = rm_rf_children(TAKE_FD(subdir_fd), flags | REMOVE_PHYSICAL, root_dev); ++ q = rm_rf_children(subdir_fd, flags | REMOVE_PHYSICAL, root_dev); + + } else if (flags & REMOVE_ONLY_DIRECTORIES) + return 0; +@@ -189,63 +190,128 @@ static int rm_rf_children_inner( + return 1; + } + ++typedef struct TodoEntry { ++ DIR *dir; /* A directory that we were operating on. */ ++ char *dirname; /* The filename of that directory itself. */ ++} TodoEntry; ++ ++static void free_todo_entries(TodoEntry **todos) { ++ for (TodoEntry *x = *todos; x && x->dir; x++) { ++ closedir(x->dir); ++ free(x->dirname); ++ } ++ ++ freep(todos); ++} ++ + int rm_rf_children( + int fd, + RemoveFlags flags, + const struct stat *root_dev) { + +- _cleanup_closedir_ DIR *d = NULL; +- struct dirent *de; ++ _cleanup_(free_todo_entries) TodoEntry *todos = NULL; ++ size_t n_todo = 0, n_todo_alloc = 0; ++ _cleanup_free_ char *dirname = NULL; /* Set when we are recursing and want to delete ourselves */ + int ret = 0, r; + +- assert(fd >= 0); ++ /* Return the first error we run into, but nevertheless try to go on. ++ * The passed fd is closed in all cases, including on failure. */ ++ ++ for (;;) { /* This loop corresponds to the directory nesting level. */ ++ _cleanup_closedir_ DIR *d = NULL; ++ ++ if (n_todo > 0) { ++ /* We know that we are in recursion here, because n_todo is set. ++ * We need to remove the inner directory we were operating on. */ ++ assert(dirname); ++ r = unlinkat_harder(dirfd(todos[n_todo-1].dir), dirname, AT_REMOVEDIR, flags); ++ if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; ++ dirname = mfree(dirname); ++ ++ /* And now let's back out one level up */ ++ n_todo --; ++ d = TAKE_PTR(todos[n_todo].dir); ++ dirname = TAKE_PTR(todos[n_todo].dirname); ++ ++ assert(d); ++ fd = dirfd(d); /* Retrieve the file descriptor from the DIR object */ ++ assert(fd >= 0); ++ } else { ++ next_fd: ++ assert(fd >= 0); ++ d = fdopendir(fd); ++ if (!d) { ++ safe_close(fd); ++ return -errno; ++ } ++ fd = dirfd(d); /* We donated the fd to fdopendir(). Let's make sure we sure we have ++ * the right descriptor even if it were to internally invalidate the ++ * one we passed. */ ++ ++ if (!(flags & REMOVE_PHYSICAL)) { ++ struct statfs sfs; ++ ++ if (fstatfs(fd, &sfs) < 0) ++ return -errno; ++ ++ if (is_physical_fs(&sfs)) { ++ /* We refuse to clean physical file systems with this call, unless ++ * explicitly requested. This is extra paranoia just to be sure we ++ * never ever remove non-state data. */ ++ ++ _cleanup_free_ char *path = NULL; ++ ++ (void) fd_get_path(fd, &path); ++ return log_error_errno(SYNTHETIC_ERRNO(EPERM), ++ "Attempted to remove disk file system under \"%s\", and we can't allow that.", ++ strna(path)); ++ } ++ } ++ } + +- /* This returns the first error we run into, but nevertheless tries to go on. This closes the passed +- * fd, in all cases, including on failure. */ ++ struct dirent *de; ++ FOREACH_DIRENT_ALL(de, d, return -errno) { ++ int is_dir; + +- d = fdopendir(fd); +- if (!d) { +- safe_close(fd); +- return -errno; +- } ++ if (dot_or_dot_dot(de->d_name)) ++ continue; + +- if (!(flags & REMOVE_PHYSICAL)) { +- struct statfs sfs; ++ is_dir = de->d_type == DT_UNKNOWN ? -1 : de->d_type == DT_DIR; + +- if (fstatfs(dirfd(d), &sfs) < 0) +- return -errno; ++ r = rm_rf_inner_child(fd, de->d_name, is_dir, flags, root_dev, false); ++ if (r == -EISDIR) { ++ /* Push the current working state onto the todo list */ + +- if (is_physical_fs(&sfs)) { +- /* We refuse to clean physical file systems with this call, unless explicitly +- * requested. This is extra paranoia just to be sure we never ever remove non-state +- * data. */ ++ if (!GREEDY_REALLOC0(todos, n_todo_alloc, n_todo + 2)) ++ return log_oom(); + +- _cleanup_free_ char *path = NULL; ++ _cleanup_free_ char *newdirname = strdup(de->d_name); ++ if (!newdirname) ++ return log_oom(); + +- (void) fd_get_path(fd, &path); +- return log_error_errno(SYNTHETIC_ERRNO(EPERM), +- "Attempted to remove disk file system under \"%s\", and we can't allow that.", +- strna(path)); +- } +- } ++ int newfd = openat(fd, de->d_name, ++ O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); ++ if (newfd >= 0) { ++ todos[n_todo++] = (TodoEntry) { TAKE_PTR(d), TAKE_PTR(dirname) }; ++ fd = newfd; ++ dirname = TAKE_PTR(newdirname); + +- FOREACH_DIRENT_ALL(de, d, return -errno) { +- int is_dir; ++ goto next_fd; + +- if (dot_or_dot_dot(de->d_name)) +- continue; ++ } else if (errno != -ENOENT && ret == 0) ++ ret = -errno; + +- is_dir = +- de->d_type == DT_UNKNOWN ? -1 : +- de->d_type == DT_DIR; ++ } else if (r < 0 && r != -ENOENT && ret == 0) ++ ret = r; ++ } + +- r = rm_rf_children_inner(dirfd(d), de->d_name, is_dir, flags, root_dev); +- if (r < 0 && r != -ENOENT && ret == 0) +- ret = r; +- } ++ if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(fd) < 0 && ret >= 0) ++ ret = -errno; + +- if (FLAGS_SET(flags, REMOVE_SYNCFS) && syncfs(dirfd(d)) < 0 && ret >= 0) +- ret = -errno; ++ if (n_todo == 0) ++ break; ++ } + + return ret; + } +@@ -338,5 +404,5 @@ int rm_rf_child(int fd, const char *name, RemoveFlags flags) { + if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME)) + return -EINVAL; + +- return rm_rf_children_inner(fd, name, -1, flags, NULL); ++ return rm_rf_inner_child(fd, name, -1, flags, NULL, true); + } +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index 8abb121..b24b20b 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 48 +Release: 49 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -130,6 +130,15 @@ Patch0080: backport-network-add-missing-link-network-checks.patch Patch0081: backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch Patch0082: backport-core-fix-free-undefined-pointer-when-strdup-failed-i.patch Patch0083: backport-test-adapt-to-the-new-capsh-format.patch +Patch0084: backport-0001-CVE-2021-3997-rm-rf-add-new-flag-REMOVE_CHMOD.patch +Patch0085: backport-0002-CVE-2021-3997-btrfs-util-add-helper-that-abstracts-might-be-btrfs-.patch +Patch0086: backport-0003-CVE-2021-3997-rm-rf-fstatat-might-fail-if-containing-dir-has-limit.patch +Patch0087: backport-0004-CVE-2021-3997-rm-rf-refactor-rm_rf_children-split-out-body-of-dire.patch +Patch0088: backport-0005-CVE-2021-3997-rm-rf-optionally-fsync-after-removing-directory-tree.patch +Patch0089: backport-0006-CVE-2021-3997-tmpfiles-st-may-have-been-used-uninitialized.patch +Patch0090: backport-0007-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch +Patch0091: backport-0008-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch +Patch0092: backport-0009-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1517,6 +1526,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Jan 18 2021 yangmingtai - 243-49 +- CVE:fix CVE-2021-3997 + * Wed Oct 27 2021 ExtinctFire - 243-48 - Type:bugfix - ID:NA -- Gitee From fdea3b8b4a8acae8c0cbc9c8eb04e12f2df48d3c Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Wed, 16 Feb 2022 11:53:41 +0800 Subject: [PATCH 29/38] fix CVE-2020-13776 --- ...il-Allow-names-starting-with-a-digit.patch | 105 +++ ...-order-of-checks-in-valid_user_group.patch | 39 + ...il-rework-how-we-validate-user-names.patch | 793 ++++++++++++++++++ ...r-document-explaining-our-rules-on-u.patch | 191 +++++ ...e-new-USER_NAMES-document-everywhere.patch | 58 ++ ...ntry-for-SD_MESSAGE_UNSAFE_USER_NAME.patch | 45 + ...always-use-base-10-for-user-group-nu.patch | 73 ++ ...imes-it-is-useful-to-check-if-a-stri.patch | 151 ++++ ...76-basic-parse-util-add-safe_atoux64.patch | 132 +++ ...allow-tweaking-how-to-parse-integers.patch | 155 ++++ ...il-allow-0-as-alternative-to-0-and-0.patch | 61 ++ ...return-parameter-optional-in-safe_at.patch | 32 + ...te-parse_mode-on-top-of-safe_atou_fu.patch | 60 ++ ...6-user-util-be-stricter-in-parse_uid.patch | 79 ++ ...parse-integers-prefixed-with-0b-and-.patch | 165 ++++ systemd.spec | 20 +- 16 files changed, 2158 insertions(+), 1 deletion(-) create mode 100644 backport-0001-CVE-2020-13776-user-util-Allow-names-starting-with-a-digit.patch create mode 100644 backport-0002-CVE-2020-13776-user-util-switch-order-of-checks-in-valid_user_group.patch create mode 100644 backport-0003-CVE-2020-13776-user-util-rework-how-we-validate-user-names.patch create mode 100644 backport-0004-CVE-2020-13776-docs-add-a-longer-document-explaining-our-rules-on-u.patch create mode 100644 backport-0005-CVE-2020-13776-docs-hook-up-the-new-USER_NAMES-document-everywhere.patch create mode 100644 backport-0006-CVE-2020-13776-catalog-add-entry-for-SD_MESSAGE_UNSAFE_USER_NAME.patch create mode 100644 backport-0007-CVE-2020-13776-basic-user-util-always-use-base-10-for-user-group-nu.patch create mode 100644 backport-0008-CVE-2020-13776-parse-util-sometimes-it-is-useful-to-check-if-a-stri.patch create mode 100644 backport-0009-CVE-2020-13776-basic-parse-util-add-safe_atoux64.patch create mode 100644 backport-0010-CVE-2020-13776-parse-util-allow-tweaking-how-to-parse-integers.patch create mode 100644 backport-0011-CVE-2020-13776-parse-util-allow-0-as-alternative-to-0-and-0.patch create mode 100644 backport-0012-CVE-2020-13776-parse-util-make-return-parameter-optional-in-safe_at.patch create mode 100644 backport-0013-CVE-2020-13776-parse-util-rewrite-parse_mode-on-top-of-safe_atou_fu.patch create mode 100644 backport-0014-CVE-2020-13776-user-util-be-stricter-in-parse_uid.patch create mode 100644 backport-0015-CVE-2020-13776-parse-util-also-parse-integers-prefixed-with-0b-and-.patch diff --git a/backport-0001-CVE-2020-13776-user-util-Allow-names-starting-with-a-digit.patch b/backport-0001-CVE-2020-13776-user-util-Allow-names-starting-with-a-digit.patch new file mode 100644 index 0000000..9350477 --- /dev/null +++ b/backport-0001-CVE-2020-13776-user-util-Allow-names-starting-with-a-digit.patch @@ -0,0 +1,105 @@ +From 93c23c9297e48e594785e0bb9c51504aae5fbe3e Mon Sep 17 00:00:00 2001 +From: Balint Reczey +Date: Wed, 18 Mar 2020 18:29:02 +0100 +Subject: [PATCH] user-util: Allow names starting with a digit + +In 1a29610f5fa1bcb2eeb37d2c6b79d8d1a6dbb865 the change inadvertedly +disabled names with digit as the first character. This follow-up change +allows a digit as the first character in compat mode. + +Fixes: #15141 +Reference: https://github.com/systemd/systemd/commit/93c23c9297e48e594785e0bb9c51504aae5fbe3e +Conflict: NA +--- + src/basic/user-util.c | 20 +++++++++++++++++--- + src/test/test-user-util.c | 4 ++-- + 2 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/src/basic/user-util.c b/src/basic/user-util.c +index a491f5505e..e998a46e72 100644 +--- a/src/basic/user-util.c ++++ b/src/basic/user-util.c +@@ -701,16 +701,18 @@ int take_etc_passwd_lock(const char *root) { + bool valid_user_group_name_full(const char *u, bool strict) { + const char *i; + long sz; ++ bool warned = false; + + /* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, + * 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules: + * + * - We require that names fit into the appropriate utmp field + * - We don't allow empty user names +- * - No dots or digits in the first character ++ * - No dots in the first character + * + * If strict==true, additionally: + * - We don't allow any dots (this conflicts with chown syntax which permits dots as user/group name separator) ++ * - We don't allow a digit as the first character + * + * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters. + */ +@@ -720,17 +722,26 @@ bool valid_user_group_name_full(const char *u, bool strict) { + + if (!(u[0] >= 'a' && u[0] <= 'z') && + !(u[0] >= 'A' && u[0] <= 'Z') && ++ !(u[0] >= '0' && u[0] <= '9' && !strict) && + u[0] != '_') + return false; + +- bool warned = false; ++ bool only_digits_seen = u[0] >= '0' && u[0] <= '9'; ++ ++ if (only_digits_seen) { ++ log_warning("User or group name \"%s\" starts with a digit, accepting for compatibility.", u); ++ warned = true; ++ } + + for (i = u+1; *i; i++) { + if (((*i >= 'a' && *i <= 'z') || + (*i >= 'A' && *i <= 'Z') || + (*i >= '0' && *i <= '9') || +- IN_SET(*i, '_', '-'))) ++ IN_SET(*i, '_', '-'))) { ++ if (!(*i >= '0' && *i <= '9')) ++ only_digits_seen = false; + continue; ++ } + + if (*i == '.' && !strict) { + if (!warned) { +@@ -744,6 +755,9 @@ bool valid_user_group_name_full(const char *u, bool strict) { + return false; + } + ++ if (only_digits_seen) ++ return false; ++ + sz = sysconf(_SC_LOGIN_NAME_MAX); + assert_se(sz > 0); + +diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c +index 084a584876..11c01e5189 100644 +--- a/src/test/test-user-util.c ++++ b/src/test/test-user-util.c +@@ -96,7 +96,7 @@ static void test_valid_user_group_name_compat(void) { + assert_se(valid_user_group_name_compat("eff.")); + + assert_se(valid_user_group_name_compat("some5")); +- assert_se(!valid_user_group_name_compat("5some")); ++ assert_se(valid_user_group_name_compat("5some")); + assert_se(valid_user_group_name_compat("INNER5NUMBER")); + } + +@@ -166,7 +166,7 @@ static void test_valid_user_group_name_or_id_compat(void) { + assert_se(valid_user_group_name_or_id_compat("kk-k")); + + assert_se(valid_user_group_name_or_id_compat("some5")); +- assert_se(!valid_user_group_name_or_id_compat("5some")); ++ assert_se(valid_user_group_name_or_id_compat("5some")); + assert_se(valid_user_group_name_or_id_compat("INNER5NUMBER")); + } + +-- +2.23.0 + diff --git a/backport-0002-CVE-2020-13776-user-util-switch-order-of-checks-in-valid_user_group.patch b/backport-0002-CVE-2020-13776-user-util-switch-order-of-checks-in-valid_user_group.patch new file mode 100644 index 0000000..e1c041a --- /dev/null +++ b/backport-0002-CVE-2020-13776-user-util-switch-order-of-checks-in-valid_user_group.patch @@ -0,0 +1,39 @@ +From a85daa0dfb3eb03be9845760e90e54b9af8fb00e Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 30 Mar 2020 21:46:01 +0200 +Subject: [PATCH] user-util: switch order of checks in + valid_user_group_name_or_id_full() + +When we are supposed to accept numeric UIDs formatted as string, then +let's check that first, before passing things on to +valid_user_group_name_full(), since that might log about, and not the +other way round. + +See: #15201 +Follow-up for: 93c23c9297e48e594785e0bb9c51504aae5fbe3e +Reference: https://github.com/systemd/systemd/commit/a85daa0dfb3eb03be9845760e90e54b9af8fb00e +Conflict: NA +--- + src/basic/user-util.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/basic/user-util.c b/src/basic/user-util.c +index e998a46e72..1510fc96ef 100644 +--- a/src/basic/user-util.c ++++ b/src/basic/user-util.c +@@ -778,10 +778,10 @@ bool valid_user_group_name_or_id_full(const char *u, bool strict) { + if (isempty(u)) + return false; + +- if (valid_user_group_name_full(u, strict)) ++ if (parse_uid(u, NULL) >= 0) + return true; + +- return parse_uid(u, NULL) >= 0; ++ return valid_user_group_name_full(u, strict); + } + + bool valid_gecos(const char *d) { +-- +2.23.0 + diff --git a/backport-0003-CVE-2020-13776-user-util-rework-how-we-validate-user-names.patch b/backport-0003-CVE-2020-13776-user-util-rework-how-we-validate-user-names.patch new file mode 100644 index 0000000..56f70c1 --- /dev/null +++ b/backport-0003-CVE-2020-13776-user-util-rework-how-we-validate-user-names.patch @@ -0,0 +1,793 @@ +From 7a8867abfab10e5bbca10590ec2aa40c5b27d8fb Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Sat, 4 Apr 2020 12:23:02 +0200 +Subject: [PATCH] user-util: rework how we validate user names +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This reworks the user validation infrastructure. There are now two +modes. In regular mode we are strict and test against a strict set of +valid chars. And in "relaxed" mode we just filter out some really +obvious, dangerous stuff. i.e. strict is whitelisting what is OK, but +"relaxed" is blacklisting what is really not OK. + +The idea is that we use strict mode whenver we allocate a new user +(i.e. in sysusers.d or homed), while "relaxed" mode is when we process +users registered elsewhere, (i.e. userdb, logind, …) + +The requirements on user name validity vary wildly. SSSD thinks its fine +to embedd "@" for example, while the suggested NAME_REGEX field on +Debian does not even allow uppercase chars… + +This effectively liberaralizes a lot what we expect from usernames. + +The code that warns about questionnable user names is now optional and +only used at places such as unit file parsing, so that it doesn't show +up on every userdb query, but only when processing configuration files +that know better. + +Fixes: #15149 #15090 +Reference: https://github.com/systemd/systemd/commit/7a8867abfab10e5bbca10590ec2aa40c5b27d8fb +Conflict: Remove unneeded file and change the context. +--- + src/basic/user-util.c | 185 +++++++++++++---------- + src/basic/user-util.h | 21 +-- + src/core/dbus-execute.c | 6 +- + src/core/dbus-manager.c | 2 +- + src/core/dbus-socket.c | 4 +- + src/core/dbus-util.c | 7 +- + src/core/dbus-util.h | 2 +- + src/core/dynamic-user.c | 2 +- + src/core/load-fragment.c | 4 +- + src/core/unit.c | 2 +- + src/nss-systemd/nss-systemd.c | 6 +- + src/systemd/sd-messages.h | 3 + + src/sysusers/sysusers.c | 4 +- + src/test/test-user-util.c | 271 ++++++++++++++++++---------------- + 14 files changed, 287 insertions(+), 232 deletions(-) + +diff --git a/src/basic/user-util.c b/src/basic/user-util.c +index 1510fc96ef..2e3580017d 100644 +--- a/src/basic/user-util.c ++++ b/src/basic/user-util.c +@@ -10,6 +10,8 @@ + #include + #include + ++#include "sd-messages.h" ++ + #include "alloc-util.h" + #include "errno-util.h" + #include "fd-util.h" +@@ -698,90 +701,123 @@ int take_etc_passwd_lock(const char *root) { + return fd; + } + +-bool valid_user_group_name_full(const char *u, bool strict) { ++bool valid_user_group_name(const char *u, ValidUserFlags flags) { + const char *i; +- long sz; +- bool warned = false; + +- /* Checks if the specified name is a valid user/group name. Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, +- * 3.437. We are a bit stricter here however. Specifically we deviate from POSIX rules: +- * +- * - We require that names fit into the appropriate utmp field +- * - We don't allow empty user names +- * - No dots in the first character +- * +- * If strict==true, additionally: +- * - We don't allow any dots (this conflicts with chown syntax which permits dots as user/group name separator) +- * - We don't allow a digit as the first character ++ /* Checks if the specified name is a valid user/group name. There are two flavours of this call: ++ * strict mode is the default which is POSIX plus some extra rules; and relaxed mode where we accept ++ * pretty much everything except the really worst offending names. + * +- * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters. +- */ ++ * Whenever we synthesize users ourselves we should use the strict mode. But when we process users ++ * created by other stuff, let's be more liberal. */ + +- if (isempty(u)) ++ if (isempty(u)) /* An empty user name is never valid */ + return false; + +- if (!(u[0] >= 'a' && u[0] <= 'z') && +- !(u[0] >= 'A' && u[0] <= 'Z') && +- !(u[0] >= '0' && u[0] <= '9' && !strict) && +- u[0] != '_') +- return false; +- +- bool only_digits_seen = u[0] >= '0' && u[0] <= '9'; ++ if (parse_uid(u, NULL) >= 0) /* Something that parses as numeric UID string is valid exactly when the ++ * flag for it is set */ ++ return FLAGS_SET(flags, VALID_USER_ALLOW_NUMERIC); ++ ++ if (FLAGS_SET(flags, VALID_USER_RELAX)) { ++ ++ /* In relaxed mode we just check very superficially. Apparently SSSD and other stuff is ++ * extremely liberal (way too liberal if you ask me, even inserting "@" in user names, which ++ * is bound to cause problems for example when used with an MTA), hence only filter the most ++ * obvious cases, or where things would result in an invalid entry if such a user name would ++ * show up in /etc/passwd (or equivalent getent output). ++ * ++ * Note that we stepped far out of POSIX territory here. It's not our fault though, but ++ * SSSD's, Samba's and everybody else who ignored POSIX on this. (I mean, I am happy to step ++ * outside of POSIX' bounds any day, but I must say in this case I probably wouldn't ++ * have...) */ ++ ++ if (startswith(u, " ") || endswith(u, " ")) /* At least expect whitespace padding is removed ++ * at front and back (accept in the middle, since ++ * that's apparently a thing on Windows). Note ++ * that this also blocks usernames consisting of ++ * whitespace only. */ ++ return false; + +- if (only_digits_seen) { +- log_warning("User or group name \"%s\" starts with a digit, accepting for compatibility.", u); +- warned = true; +- } ++ if (!utf8_is_valid(u)) /* We want to synthesize JSON from this, hence insist on UTF-8 */ ++ return false; + +- for (i = u+1; *i; i++) { +- if (((*i >= 'a' && *i <= 'z') || +- (*i >= 'A' && *i <= 'Z') || +- (*i >= '0' && *i <= '9') || +- IN_SET(*i, '_', '-'))) { +- if (!(*i >= '0' && *i <= '9')) +- only_digits_seen = false; +- continue; +- } +- +- if (*i == '.' && !strict) { +- if (!warned) { +- log_warning("Bad user or group name \"%s\", accepting for compatibility.", u); +- warned = true; +- } +- +- continue; +- } ++ if (string_has_cc(u, NULL)) /* CC characters are just dangerous (and \n in particular is the ++ * record separator in /etc/passwd), so we can't allow that. */ ++ return false; + +- return false; +- } ++ if (strpbrk(u, ":/")) /* Colons are the field separator in /etc/passwd, we can't allow ++ * that. Slashes are special to file systems paths and user names ++ * typically show up in the file system as home directories, hence ++ * don't allow slashes. */ ++ return false; + +- if (only_digits_seen) +- return false; ++ if (in_charset(u, "0123456789")) /* Don't allow fully numeric strings, they might be confused ++ * with with UIDs (note that this test is more broad than ++ * the parse_uid() test above, as it will cover more than ++ * the 32bit range, and it will detect 65535 (which is in ++ * invalid UID, even though in the unsigned 32 bit range) */ ++ return false; + +- sz = sysconf(_SC_LOGIN_NAME_MAX); +- assert_se(sz > 0); ++ if (u[0] == '-' && in_charset(u + 1, "0123456789")) /* Don't allow negative fully numeric ++ * strings either. After all some people ++ * write 65535 as -1 (even though that's ++ * not even true on 32bit uid_t ++ * anyway) */ ++ return false; + +- if ((size_t) (i-u) > (size_t) sz) +- return false; ++ if (dot_or_dot_dot(u)) /* User names typically become home directory names, and these two are ++ * special in that context, don't allow that. */ ++ return false; + +- if ((size_t) (i-u) > UT_NAMESIZE - 1) +- return false; ++ /* Compare with strict result and warn if result doesn't match */ ++ if (FLAGS_SET(flags, VALID_USER_WARN) && !valid_user_group_name(u, 0)) ++ log_struct(LOG_NOTICE, ++ "MESSAGE=Accepting user/group name '%s', which does not match strict user/group name rules.", u, ++ "USER_GROUP_NAME=%s", u, ++ "MESSAGE_ID=" SD_MESSAGE_UNSAFE_USER_NAME_STR); + +- return true; +-} ++ /* Note that we make no restrictions on the length in relaxed mode! */ ++ } else { ++ long sz; ++ size_t l; ++ ++ /* Also see POSIX IEEE Std 1003.1-2008, 2016 Edition, 3.437. We are a bit stricter here ++ * however. Specifically we deviate from POSIX rules: ++ * ++ * - We don't allow empty user names (see above) ++ * - We require that names fit into the appropriate utmp field ++ * - We don't allow any dots (this conflicts with chown syntax which permits dots as user/group name separator) ++ * - We don't allow dashes or digit as the first character ++ * ++ * Note that other systems are even more restrictive, and don't permit underscores or uppercase characters. ++ */ ++ ++ if (!(u[0] >= 'a' && u[0] <= 'z') && ++ !(u[0] >= 'A' && u[0] <= 'Z') && ++ u[0] != '_') ++ return false; + +-bool valid_user_group_name_or_id_full(const char *u, bool strict) { ++ for (i = u+1; *i; i++) ++ if (!(*i >= 'a' && *i <= 'z') && ++ !(*i >= 'A' && *i <= 'Z') && ++ !(*i >= '0' && *i <= '9') && ++ !IN_SET(*i, '_', '-')) ++ return false; + +- /* Similar as above, but is also fine with numeric UID/GID specifications, as long as they are in the +- * right range, and not the invalid user ids. */ ++ l = i - u; + +- if (isempty(u)) +- return false; ++ sz = sysconf(_SC_LOGIN_NAME_MAX); ++ assert_se(sz > 0); + +- if (parse_uid(u, NULL) >= 0) +- return true; ++ if (l > (size_t) sz) ++ return false; ++ if (l > FILENAME_MAX) ++ return false; ++ if (l > UT_NAMESIZE - 1) ++ return false; ++ } + +- return valid_user_group_name_full(u, strict); ++ return true; + } + + bool valid_gecos(const char *d) { +diff --git a/src/basic/user-util.h b/src/basic/user-util.h +index 6796ac42c1..1f267d21a3 100644 +--- a/src/basic/user-util.h ++++ b/src/basic/user-util.h +@@ -97,20 +97,13 @@ static inline bool userns_supported(void) { + return access("/proc/self/uid_map", F_OK) >= 0; + } + +-bool valid_user_group_name_full(const char *u, bool strict); +-bool valid_user_group_name_or_id_full(const char *u, bool strict); +-static inline bool valid_user_group_name(const char *u) { +- return valid_user_group_name_full(u, true); +-} +-static inline bool valid_user_group_name_or_id(const char *u) { +- return valid_user_group_name_or_id_full(u, true); +-} +-static inline bool valid_user_group_name_compat(const char *u) { +- return valid_user_group_name_full(u, false); +-} +-static inline bool valid_user_group_name_or_id_compat(const char *u) { +- return valid_user_group_name_or_id_full(u, false); +-} ++typedef enum ValidUserFlags { ++ VALID_USER_RELAX = 1 << 0, ++ VALID_USER_WARN = 1 << 1, ++ VALID_USER_ALLOW_NUMERIC = 1 << 2, ++} ValidUserFlags; ++ ++bool valid_user_group_name(const char *u, ValidUserFlags flags); + bool valid_gecos(const char *d); + bool valid_home(const char *p); + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 5696a60ba8..93857436b4 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -1204,10 +1204,10 @@ int bus_exec_context_set_transient_property( + flags |= UNIT_PRIVATE; + + if (streq(name, "User")) +- return bus_set_transient_user_compat(u, name, &c->user, message, flags, error); ++ return bus_set_transient_user_relaxed(u, name, &c->user, message, flags, error); + + if (streq(name, "Group")) +- return bus_set_transient_user_compat(u, name, &c->group, message, flags, error); ++ return bus_set_transient_user_relaxed(u, name, &c->group, message, flags, error); + + if (streq(name, "TTYPath")) + return bus_set_transient_path(u, name, &c->tty_path, message, flags, error); +@@ -1392,7 +1392,7 @@ int bus_exec_context_set_transient_property( + return r; + + STRV_FOREACH(p, l) +- if (!isempty(*p) && !valid_user_group_name_or_id_compat(*p)) ++ if (!isempty(*p) && !valid_user_group_name(*p, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, + "Invalid supplementary group names"); + +diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c +index 60f55aef5f..ef4bb316cc 100644 +--- a/src/core/dbus-manager.c ++++ b/src/core/dbus-manager.c +@@ -1643,7 +1643,7 @@ static int method_lookup_dynamic_user_by_name(sd_bus_message *message, void *use + + if (!MANAGER_IS_SYSTEM(m)) + return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Dynamic users are only supported in the system instance."); +- if (!valid_user_group_name(name)) ++ if (!valid_user_group_name(name, VALID_USER_RELAX)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "User name invalid: %s", name); + + r = dynamic_user_lookup_name(m, name, &uid); +diff --git a/src/core/dbus-socket.c b/src/core/dbus-socket.c +index c8253c7940..ad7b41a95b 100644 +--- a/src/core/dbus-socket.c ++++ b/src/core/dbus-socket.c +@@ -278,10 +278,10 @@ static int bus_socket_set_transient_property( + return bus_set_transient_fdname(u, name, &s->fdname, message, flags, error); + + if (streq(name, "SocketUser")) +- return bus_set_transient_user_compat(u, name, &s->user, message, flags, error); ++ return bus_set_transient_user_relaxed(u, name, &s->user, message, flags, error); + + if (streq(name, "SocketGroup")) +- return bus_set_transient_user_compat(u, name, &s->group, message, flags, error); ++ return bus_set_transient_user_relaxed(u, name, &s->group, message, flags, error); + + if (streq(name, "BindIPv6Only")) + return bus_set_transient_bind_ipv6_only(u, name, &s->bind_ipv6_only, message, flags, error); +diff --git a/src/core/dbus-util.c b/src/core/dbus-util.c +index 7862beaacb..951450e53d 100644 +--- a/src/core/dbus-util.c ++++ b/src/core/dbus-util.c +@@ -30,7 +30,12 @@ int bus_property_get_triggered_unit( + + BUS_DEFINE_SET_TRANSIENT(mode_t, "u", uint32_t, mode_t, "%040o"); + BUS_DEFINE_SET_TRANSIENT(unsigned, "u", uint32_t, unsigned, "%" PRIu32); +-BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user_compat, valid_user_group_name_or_id_compat); ++ ++static inline bool valid_user_group_name_or_id_relaxed(const char *u) { ++ return valid_user_group_name(u, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX); ++} ++ ++BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(user_relaxed, valid_user_group_name_or_id_relaxed); + BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(path, path_is_absolute); + + int bus_set_transient_string( +diff --git a/src/core/dbus-util.h b/src/core/dbus-util.h +index ec8c245fff..654ceb5279 100644 +--- a/src/core/dbus-util.h ++++ b/src/core/dbus-util.h +@@ -236,7 +236,7 @@ int bus_property_get_triggered_unit(sd_bus *bus, const char *path, const char *i + + int bus_set_transient_mode_t(Unit *u, const char *name, mode_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); + int bus_set_transient_unsigned(Unit *u, const char *name, unsigned *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +-int bus_set_transient_user_compat(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); ++int bus_set_transient_user_relaxed(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); + int bus_set_transient_path(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); + int bus_set_transient_string(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); + int bus_set_transient_bool(Unit *u, const char *name, bool *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +diff --git a/src/core/dynamic-user.c b/src/core/dynamic-user.c +index f1819b36bc..58b37925bf 100644 +--- a/src/core/dynamic-user.c ++++ b/src/core/dynamic-user.c +@@ -116,7 +116,7 @@ static int dynamic_user_acquire(Manager *m, const char *name, DynamicUser** ret) + return 0; + } + +- if (!valid_user_group_name_or_id(name)) ++ if (!valid_user_group_name(name, VALID_USER_ALLOW_NUMERIC)) + return -EINVAL; + + if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, storage_socket) < 0) +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 646364eb89..f3fe73535e 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -2068,7 +2068,7 @@ int config_parse_user_group_compat( + return -ENOEXEC; + } + +- if (!valid_user_group_name_or_id_compat(k)) { ++ if (!valid_user_group_name(k, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k); + return -ENOEXEC; + } +@@ -2122,7 +2122,7 @@ int config_parse_user_group_strv_compat( + return -ENOEXEC; + } + +- if (!valid_user_group_name_or_id_compat(k)) { ++ if (!valid_user_group_name(k, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN)) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid user/group name or numeric ID: %s", k); + return -ENOEXEC; + } +diff --git a/src/core/unit.c b/src/core/unit.c +index 96e1a6c320..95d574d8d4 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -4287,7 +4287,7 @@ static int user_from_unit_name(Unit *u, char **ret) { + if (r < 0) + return r; + +- if (valid_user_group_name(n)) { ++ if (valid_user_group_name(n, 0)) { + *ret = TAKE_PTR(n); + return 0; + } +diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c +index 8ef1cd5..25d034a 100644 +--- a/src/nss-systemd/nss-systemd.c ++++ b/src/nss-systemd/nss-systemd.c +@@ -124,7 +124,7 @@ static int direct_lookup_uid(uid_t uid, char **ret) { + r = readlink_malloc(path, &s); + if (r < 0) + return r; +- if (!valid_user_group_name(s)) { /* extra safety check */ ++ if (!valid_user_group_name(s, VALID_USER_RELAX)) { /* extra safety check */ + free(s); + return -EINVAL; + } +@@ -154,7 +154,7 @@ enum nss_status _nss_systemd_getpwnam_r( + + /* If the username is not valid, then we don't know it. Ideally libc would filter these for us anyway. We don't + * generate EINVAL here, because it isn't really out business to complain about invalid user names. */ +- if (!valid_user_group_name(name)) ++ if (!valid_user_group_name(name, VALID_USER_RELAX)) + return NSS_STATUS_NOTFOUND; + + /* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */ +@@ -357,7 +357,7 @@ enum nss_status _nss_systemd_getgrnam_r( + assert(name); + assert(gr); + +- if (!valid_user_group_name(name)) ++ if (!valid_user_group_name(name, VALID_USER_RELAX)) + return NSS_STATUS_NOTFOUND; + + /* Synthesize records for root and nobody, in case they are missing form /etc/group */ +diff --git a/src/systemd/sd-messages.h b/src/systemd/sd-messages.h +index e8d26ab71b..162b650e64 100644 +--- a/src/systemd/sd-messages.h ++++ b/src/systemd/sd-messages.h +@@ -158,6 +158,9 @@ _SD_BEGIN_DECLARATIONS; + #define SD_MESSAGE_DNSSEC_DOWNGRADE SD_ID128_MAKE(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57) + #define SD_MESSAGE_DNSSEC_DOWNGRADE_STR SD_ID128_MAKE_STR(36,db,2d,fa,5a,90,45,e1,bd,4a,f5,f9,3e,1c,f0,57) + ++#define SD_MESSAGE_UNSAFE_USER_NAME SD_ID128_MAKE(b6,1f,da,c6,12,e9,4b,91,82,28,5b,99,88,43,06,1f) ++#define SD_MESSAGE_UNSAFE_USER_NAME_STR SD_ID128_MAKE_STR(b6,1f,da,c6,12,e9,4b,91,82,28,5b,99,88,43,06,1f) ++ + _SD_END_DECLARATIONS; + + #endif +diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c +index 08a2df7..3e3da47 100644 +--- a/src/sysusers/sysusers.c ++++ b/src/sysusers/sysusers.c +@@ -1417,7 +1417,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { + if (r < 0) + log_error_errno(r, "[%s:%u] Failed to replace specifiers: %s", fname, line, name); + +- if (!valid_user_group_name(resolved_name)) ++ if (!valid_user_group_name(resolved_name, 0)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] '%s' is not a valid user or group name.", + fname, line, resolved_name); +@@ -1520,7 +1520,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { + "[%s:%u] Lines of type 'm' require a group name in the third field.", + fname, line); + +- if (!valid_user_group_name(resolved_id)) ++ if (!valid_user_group_name(resolved_id, 0)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "[%s:%u] '%s' is not a valid user or group name.", + fname, line, resolved_id); +diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c +index 11c01e5189..a0e1495186 100644 +--- a/src/test/test-user-util.c ++++ b/src/test/test-user-util.c +@@ -63,144 +63,163 @@ static void test_uid_ptr(void) { + assert_se(PTR_TO_UID(UID_TO_PTR(1000)) == 1000); + } + +-static void test_valid_user_group_name_compat(void) { ++static void test_valid_user_group_name_relaxed(void) { + log_info("/* %s */", __func__); + +- assert_se(!valid_user_group_name_compat(NULL)); +- assert_se(!valid_user_group_name_compat("")); +- assert_se(!valid_user_group_name_compat("1")); +- assert_se(!valid_user_group_name_compat("65535")); +- assert_se(!valid_user_group_name_compat("-1")); +- assert_se(!valid_user_group_name_compat("-kkk")); +- assert_se(!valid_user_group_name_compat("rööt")); +- assert_se(!valid_user_group_name_compat(".")); +- assert_se(!valid_user_group_name_compat(".eff")); +- assert_se(!valid_user_group_name_compat("foo\nbar")); +- assert_se(!valid_user_group_name_compat("0123456789012345678901234567890123456789")); +- assert_se(!valid_user_group_name_or_id_compat("aaa:bbb")); +- assert_se(!valid_user_group_name_compat(".")); +- assert_se(!valid_user_group_name_compat(".1")); +- assert_se(!valid_user_group_name_compat(".65535")); +- assert_se(!valid_user_group_name_compat(".-1")); +- assert_se(!valid_user_group_name_compat(".-kkk")); +- assert_se(!valid_user_group_name_compat(".rööt")); +- assert_se(!valid_user_group_name_or_id_compat(".aaa:bbb")); +- +- assert_se(valid_user_group_name_compat("root")); +- assert_se(valid_user_group_name_compat("lennart")); +- assert_se(valid_user_group_name_compat("LENNART")); +- assert_se(valid_user_group_name_compat("_kkk")); +- assert_se(valid_user_group_name_compat("kkk-")); +- assert_se(valid_user_group_name_compat("kk-k")); +- assert_se(valid_user_group_name_compat("eff.eff")); +- assert_se(valid_user_group_name_compat("eff.")); +- +- assert_se(valid_user_group_name_compat("some5")); +- assert_se(valid_user_group_name_compat("5some")); +- assert_se(valid_user_group_name_compat("INNER5NUMBER")); ++ assert_se(!valid_user_group_name(NULL, VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("", VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("1", VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("65535", VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("-1", VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("foo\nbar", VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_RELAX|VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name(".aaa:bbb", VALID_USER_RELAX|VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name(".", VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("..", VALID_USER_RELAX)); ++ ++ assert_se(valid_user_group_name("root", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("lennart", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("LENNART", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("_kkk", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("kkk-", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("kk-k", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("eff.eff", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("eff.", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("-kkk", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("rööt", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name(".eff", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name(".1", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name(".65535", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name(".-1", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name(".-kkk", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name(".rööt", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("...", VALID_USER_RELAX)); ++ ++ assert_se(valid_user_group_name("some5", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("5some", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("INNER5NUMBER", VALID_USER_RELAX)); ++ ++ assert_se(valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("Dāvis", VALID_USER_RELAX)); + } + + static void test_valid_user_group_name(void) { + log_info("/* %s */", __func__); + +- assert_se(!valid_user_group_name(NULL)); +- assert_se(!valid_user_group_name("")); +- assert_se(!valid_user_group_name("1")); +- assert_se(!valid_user_group_name("65535")); +- assert_se(!valid_user_group_name("-1")); +- assert_se(!valid_user_group_name("-kkk")); +- assert_se(!valid_user_group_name("rööt")); +- assert_se(!valid_user_group_name(".")); +- assert_se(!valid_user_group_name(".eff")); +- assert_se(!valid_user_group_name("foo\nbar")); +- assert_se(!valid_user_group_name("0123456789012345678901234567890123456789")); +- assert_se(!valid_user_group_name_or_id("aaa:bbb")); +- assert_se(!valid_user_group_name(".")); +- assert_se(!valid_user_group_name(".1")); +- assert_se(!valid_user_group_name(".65535")); +- assert_se(!valid_user_group_name(".-1")); +- assert_se(!valid_user_group_name(".-kkk")); +- assert_se(!valid_user_group_name(".rööt")); +- assert_se(!valid_user_group_name_or_id(".aaa:bbb")); +- +- assert_se(valid_user_group_name("root")); +- assert_se(valid_user_group_name("lennart")); +- assert_se(valid_user_group_name("LENNART")); +- assert_se(valid_user_group_name("_kkk")); +- assert_se(valid_user_group_name("kkk-")); +- assert_se(valid_user_group_name("kk-k")); +- assert_se(!valid_user_group_name("eff.eff")); +- assert_se(!valid_user_group_name("eff.")); +- +- assert_se(valid_user_group_name("some5")); +- assert_se(!valid_user_group_name("5some")); +- assert_se(valid_user_group_name("INNER5NUMBER")); ++ assert_se(!valid_user_group_name(NULL, 0)); ++ assert_se(!valid_user_group_name("", 0)); ++ assert_se(!valid_user_group_name("1", 0)); ++ assert_se(!valid_user_group_name("65535", 0)); ++ assert_se(!valid_user_group_name("-1", 0)); ++ assert_se(!valid_user_group_name("-kkk", 0)); ++ assert_se(!valid_user_group_name("rööt", 0)); ++ assert_se(!valid_user_group_name(".", 0)); ++ assert_se(!valid_user_group_name(".eff", 0)); ++ assert_se(!valid_user_group_name("foo\nbar", 0)); ++ assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", 0)); ++ assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name(".", 0)); ++ assert_se(!valid_user_group_name("..", 0)); ++ assert_se(!valid_user_group_name("...", 0)); ++ assert_se(!valid_user_group_name(".1", 0)); ++ assert_se(!valid_user_group_name(".65535", 0)); ++ assert_se(!valid_user_group_name(".-1", 0)); ++ assert_se(!valid_user_group_name(".-kkk", 0)); ++ assert_se(!valid_user_group_name(".rööt", 0)); ++ assert_se(!valid_user_group_name(".aaa:bbb", VALID_USER_ALLOW_NUMERIC)); ++ ++ assert_se(valid_user_group_name("root", 0)); ++ assert_se(valid_user_group_name("lennart", 0)); ++ assert_se(valid_user_group_name("LENNART", 0)); ++ assert_se(valid_user_group_name("_kkk", 0)); ++ assert_se(valid_user_group_name("kkk-", 0)); ++ assert_se(valid_user_group_name("kk-k", 0)); ++ assert_se(!valid_user_group_name("eff.eff", 0)); ++ assert_se(!valid_user_group_name("eff.", 0)); ++ ++ assert_se(valid_user_group_name("some5", 0)); ++ assert_se(!valid_user_group_name("5some", 0)); ++ assert_se(valid_user_group_name("INNER5NUMBER", 0)); ++ ++ assert_se(!valid_user_group_name("piff.paff@ad.domain.example", 0)); ++ assert_se(!valid_user_group_name("Dāvis", 0)); + } + +-static void test_valid_user_group_name_or_id_compat(void) { ++static void test_valid_user_group_name_or_numeric_relaxed(void) { + log_info("/* %s */", __func__); + +- assert_se(!valid_user_group_name_or_id_compat(NULL)); +- assert_se(!valid_user_group_name_or_id_compat("")); +- assert_se(valid_user_group_name_or_id_compat("0")); +- assert_se(valid_user_group_name_or_id_compat("1")); +- assert_se(valid_user_group_name_or_id_compat("65534")); +- assert_se(!valid_user_group_name_or_id_compat("65535")); +- assert_se(valid_user_group_name_or_id_compat("65536")); +- assert_se(!valid_user_group_name_or_id_compat("-1")); +- assert_se(!valid_user_group_name_or_id_compat("-kkk")); +- assert_se(!valid_user_group_name_or_id_compat("rööt")); +- assert_se(!valid_user_group_name_or_id_compat(".")); +- assert_se(!valid_user_group_name_or_id_compat(".eff")); +- assert_se(valid_user_group_name_or_id_compat("eff.eff")); +- assert_se(valid_user_group_name_or_id_compat("eff.")); +- assert_se(!valid_user_group_name_or_id_compat("foo\nbar")); +- assert_se(!valid_user_group_name_or_id_compat("0123456789012345678901234567890123456789")); +- assert_se(!valid_user_group_name_or_id_compat("aaa:bbb")); +- +- assert_se(valid_user_group_name_or_id_compat("root")); +- assert_se(valid_user_group_name_or_id_compat("lennart")); +- assert_se(valid_user_group_name_or_id_compat("LENNART")); +- assert_se(valid_user_group_name_or_id_compat("_kkk")); +- assert_se(valid_user_group_name_or_id_compat("kkk-")); +- assert_se(valid_user_group_name_or_id_compat("kk-k")); +- +- assert_se(valid_user_group_name_or_id_compat("some5")); +- assert_se(valid_user_group_name_or_id_compat("5some")); +- assert_se(valid_user_group_name_or_id_compat("INNER5NUMBER")); ++ assert_se(!valid_user_group_name(NULL, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("0", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("1", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("65534", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("65535", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("65536", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("-1", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("foo\nbar", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name(".", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(!valid_user_group_name("..", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ ++ assert_se(valid_user_group_name("root", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("lennart", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("LENNART", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("_kkk", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("kkk-", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("kk-k", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("-kkk", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("rööt", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name(".eff", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("eff.eff", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("eff.", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("...", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ ++ assert_se(valid_user_group_name("some5", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("5some", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("INNER5NUMBER", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ ++ assert_se(valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); ++ assert_se(valid_user_group_name("Dāvis", VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX)); + } + +-static void test_valid_user_group_name_or_id(void) { ++static void test_valid_user_group_name_or_numeric(void) { + log_info("/* %s */", __func__); + +- assert_se(!valid_user_group_name_or_id(NULL)); +- assert_se(!valid_user_group_name_or_id("")); +- assert_se(valid_user_group_name_or_id("0")); +- assert_se(valid_user_group_name_or_id("1")); +- assert_se(valid_user_group_name_or_id("65534")); +- assert_se(!valid_user_group_name_or_id("65535")); +- assert_se(valid_user_group_name_or_id("65536")); +- assert_se(!valid_user_group_name_or_id("-1")); +- assert_se(!valid_user_group_name_or_id("-kkk")); +- assert_se(!valid_user_group_name_or_id("rööt")); +- assert_se(!valid_user_group_name_or_id(".")); +- assert_se(!valid_user_group_name_or_id(".eff")); +- assert_se(!valid_user_group_name_or_id("eff.eff")); +- assert_se(!valid_user_group_name_or_id("eff.")); +- assert_se(!valid_user_group_name_or_id("foo\nbar")); +- assert_se(!valid_user_group_name_or_id("0123456789012345678901234567890123456789")); +- assert_se(!valid_user_group_name_or_id("aaa:bbb")); +- +- assert_se(valid_user_group_name_or_id("root")); +- assert_se(valid_user_group_name_or_id("lennart")); +- assert_se(valid_user_group_name_or_id("LENNART")); +- assert_se(valid_user_group_name_or_id("_kkk")); +- assert_se(valid_user_group_name_or_id("kkk-")); +- assert_se(valid_user_group_name_or_id("kk-k")); +- +- assert_se(valid_user_group_name_or_id("some5")); +- assert_se(!valid_user_group_name_or_id("5some")); +- assert_se(valid_user_group_name_or_id("INNER5NUMBER")); ++ assert_se(!valid_user_group_name(NULL, VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("0", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("1", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("65534", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("65535", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("65536", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("-1", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("-kkk", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("rööt", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name(".", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("..", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("...", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name(".eff", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("eff.eff", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("eff.", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("foo\nbar", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("0123456789012345678901234567890123456789", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("aaa:bbb", VALID_USER_ALLOW_NUMERIC)); ++ ++ assert_se(valid_user_group_name("root", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("lennart", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("LENNART", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("_kkk", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("kkk-", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("kk-k", VALID_USER_ALLOW_NUMERIC)); ++ ++ assert_se(valid_user_group_name("some5", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("5some", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(valid_user_group_name("INNER5NUMBER", VALID_USER_ALLOW_NUMERIC)); ++ ++ assert_se(!valid_user_group_name("piff.paff@ad.domain.example", VALID_USER_ALLOW_NUMERIC)); ++ assert_se(!valid_user_group_name("Dāvis", VALID_USER_ALLOW_NUMERIC)); + } + + static void test_valid_gecos(void) { +@@ -355,10 +374,10 @@ int main(int argc, char *argv[]) { + test_parse_uid(); + test_uid_ptr(); + +- test_valid_user_group_name_compat(); ++ test_valid_user_group_name_relaxed(); + test_valid_user_group_name(); +- test_valid_user_group_name_or_id_compat(); +- test_valid_user_group_name_or_id(); ++ test_valid_user_group_name_or_numeric_relaxed(); ++ test_valid_user_group_name_or_numeric(); + test_valid_gecos(); + test_valid_home(); + +-- +2.23.0 + diff --git a/backport-0004-CVE-2020-13776-docs-add-a-longer-document-explaining-our-rules-on-u.patch b/backport-0004-CVE-2020-13776-docs-add-a-longer-document-explaining-our-rules-on-u.patch new file mode 100644 index 0000000..340cac1 --- /dev/null +++ b/backport-0004-CVE-2020-13776-docs-add-a-longer-document-explaining-our-rules-on-u.patch @@ -0,0 +1,191 @@ +From cafed7b32cdac13024c4093b7942a49ee8602dcf Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 7 Apr 2020 10:38:39 +0200 +Subject: [PATCH] docs: add a longer document explaining our rules on + user/group names + +Reference: https://github.com/systemd/systemd/commit/cafed7b32cdac13024c4093b7942a49ee8602dcf +Conflict: NA +--- + docs/USER_NAMES.md | 169 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 169 insertions(+) + create mode 100644 docs/USER_NAMES.md + +diff --git a/docs/USER_NAMES.md b/docs/USER_NAMES.md +new file mode 100644 +index 0000000000..ccbb0a360d +--- /dev/null ++++ b/docs/USER_NAMES.md +@@ -0,0 +1,169 @@ ++-- ++title: User/Group Name Syntax ++category: Concepts ++layout: default ++--- ++ ++# User/Group Name Syntax ++ ++The precise set of allowed user and group names on Linux systems is weakly ++defined. Depending on the distribution a different set of requirements and ++restrictions on the syntax of user/group names are enforced — on some ++distributions the accepted syntax is even configurable by the administrator. In ++the interest of interoperability systemd enforces different rules when ++processing users/group defined by other subsystems and when defining users/groups ++itself, following the principle of "Be conservative in what you send, be ++liberal in what you accept". Also in the interest of interoperability systemd ++will enforce the same rules everywhere and not make them configurable or ++distribution dependent. The precise rules are described below. ++ ++Generally, the same rules apply for user as for group names. ++ ++## Other Systems ++ ++* On POSIX the set of [valid user ++ names](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_437) ++ is defined as [lower and upper case ASCII letters, digits, period, ++ underscore, and ++ hyphen](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_282), ++ with the restriction that hyphen is now allowed as first character of the ++ user name. Interestingly no size limit is declared, i.e. in neither ++ direction, meaning that strictly speaking according to POSIX both the empty ++ string is a valid user name as well as a string of gigabytes in length. ++ ++* Debian/Ubuntu based systems enforce the regular expression ++ `^[a-z][-a-z0-9]*$`, i.e. only lower case ASCII letters, digits and ++ hyphens. As first character only lowercase ASCII letters are allowed. This ++ regular expression is configurable by the administrator at runtime ++ though. This rule enforces a minimum length of one character but no maximum ++ length. ++ ++* Upstream shadow-utils enforces the regular expression ++ `^[a-z_][a-z0-9_-]*[$]$`, i.e. is similar to the Debian/Ubuntu rule, but ++ allows underscores and hyphens, but the latter not as first character. Also, ++ an optional trailing dollar character is permitted. ++ ++* Fedora/Red Hat based systems enforce the regular expression of ++ `^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,30}[a-zA-Z0-9_.$-]?$`, i.e. a size limit of ++ 32 characters, with upper and lower case letters, digits, underscores, ++ hyphens and periods. No hyphen as first character though, and the last ++ character may be a dollar character. On top of that, `.` and `..` are not ++ allowed as user/group names. ++ ++* sssd is known to generate user names with embedded `@` and white-space ++ characters, as well as non-ASCII (i.e. UTF-8) user/group names. ++ ++* winbindd is known to generate user/group names with embedded `\` and ++ white-space characters, as well as non-ASCII (i.e. UTF-8) user/group names. ++ ++Other operating systems enforce different rules; in this documentation we'll ++focus on Linux systems only however, hence those are out of scope. That said, ++software like Samba is frequently deployed on Linux for providing compatibility ++with Windows systems; on such systems it might be wise to stick to user/group ++names also valid according to Windows rules. ++ ++## Rules systemd enforces ++ ++Distilled from the above, below are the rules systemd enforces on user/group ++names. An additional, common rule between both modes listed below is that empty ++strings are not valid user/group names. ++ ++Philosophically, the strict mode described below enforces a white-list of what's ++allowed and prohibits everything else, while the relaxed mode described below ++implements a blacklist of what's not allowed and permits everything else. ++ ++### Strict mode ++ ++Strict user/group name syntax is enforced whenever a systemd component is used ++to register a user or group in the system, for example a system user/group ++using ++[`systemd-sysusers.service`](https://www.freedesktop.org/software/systemd/man/systemd-sysusers.html) ++or a regular user with ++[`systemd-homed.service`](https://www.freedesktop.org/software/systemd/man/systemd-homed.html). ++ ++In strict mode, only uppercase and lowercase characters are allowed, as well as ++digits, underscores and hyphens. The first character may not be a digit or ++hyphen. A size limit is enforced: the minimum of `sysconf(_SC_LOGIN_NAME_MAX)` ++(typically 256 on Linux; rationale: this is how POSIX suggests to detect the ++limit), `UT_NAMESIZE-1` (typically 31 on Linux; rationale: names longer than ++this cannot correctly appear in `utmp`/`wtmp` and create ambiguity with login ++accounting) and `FILENAME_MAX` (4096 on Linux; rationale: user names typically ++appear in directory names, i.e. the home directory), thus MIN(256, 31, 4096) = ++31. ++ ++Note that these rules are both more strict and more relaxed than all of the ++rules enforced by other systems listed above. A user/group name conforming to ++systemd's strict rules will not necessarily pass a test by the rules enforced ++by these other subsystems. ++ ++Written as regular expression the above is: `^[a-zA-Z_][a-zA-Z0-9_-]{0,30}$` ++ ++### Relaxed mode ++ ++Relaxed user/group name syntax is enforced whenever a systemd component accepts ++and makes use of user/group names registered by other (non-systemd) ++components of the system, for example in ++[`systemd-logind.service`](https://www.freedesktop.org/software/systemd/man/systemd-logind.html). ++ ++Relaxed syntax is also enforced by the `User=` setting in service unit files, ++i.e. for system services used for running services. Since these users may be ++registered by a variety of tools relaxed mode is used, but since the primary ++purpose of these users is to run a system service and thus a job for systemd a ++warning is shown if the specified user name does not qualify by the strict ++rules above. ++ ++* No embedded NUL bytes (rationale: handling in C must be possible and ++ straight-forward) ++ ++* No names consisting fully of digits (rationale: avoid confusion with numeric ++ UID/GID specifications) ++ ++* Similar, no names consisting of an initial hyphen and otherwise entirely made ++ up of digits (rationale: avoid confusion with negative, numeric UID/GID ++ specifications, e.g. `-1`) ++ ++* No strings that do not qualify as valid UTF-8 (rationale: we want to be able ++ to embed these strings in JSON, with permits only valid UTF-8 in its strings; ++ user names using other character sets, such as JIS/Shift-JIS will cause ++ validation errors) ++ ++* No control characters (i.e. characters in ASCII range 1…31; rationale: they ++ tend to have special meaning when output on a terminal in other contexts, ++ moreover the newline character — as a specific control character — is used as ++ record separator in `/etc/passwd`, and hence it's crucial to avoid ++ ambiguities here) ++ ++* No colon characters (rationale: it is used as field separator in `/etc/passwd`) ++ ++* The two strings `.` and `..` are not permitted, as these have special meaning ++ in file system paths, and user names are frequently included in file system ++ paths, in particular for the purpose of home directories. ++ ++* Similar, no slashes, as these have special meaning in file system paths ++ ++* No leading or trailing white-space is permitted; and hence no user/group names ++ consisting of white-space only either (rationale: this typically indicates ++ parsing errors, and creates confusion since not visible on screen) ++ ++Note that these relaxed rules are implied by the strict rules above, i.e. all ++user/group names accepted by the strict rules are also accepted by the relaxed ++rules, but not vice versa. ++ ++Note that this relaxed mode does not refuse a couple of very questionable ++syntaxes. For example it permits a leading or embedded period. A leading period ++is problematic because the matching home directory would typically be hidden ++from the user's/administrator's view. An embedded period is problematic since ++it creates ambiguity in traditional `chown` syntax (which is still accepted ++today) that uses it to separate user and group names in the command's ++parameter: without consulting the user/group databases it is not possible to ++determine if a `chown` invocation would change just the owning user or both the ++owning user and group. It also allows embeddeding `@` (which is confusing to ++MTAs). ++ ++## Common Core ++ ++Combining all rules listed above, user/group names that shall be considered ++valid in all systemd contexts and on all Linux systems should match the ++following regular expression (at least according to our understanding): ++ ++`^[a-z][a-z0-9-]{0,30}$` +-- +2.23.0 + diff --git a/backport-0005-CVE-2020-13776-docs-hook-up-the-new-USER_NAMES-document-everywhere.patch b/backport-0005-CVE-2020-13776-docs-hook-up-the-new-USER_NAMES-document-everywhere.patch new file mode 100644 index 0000000..bc14f5f --- /dev/null +++ b/backport-0005-CVE-2020-13776-docs-hook-up-the-new-USER_NAMES-document-everywhere.patch @@ -0,0 +1,58 @@ +From 887a8fa341d9b24a7c9cd3f1fce328f8e43a1b4f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 7 Apr 2020 11:04:59 +0200 +Subject: [PATCH] docs: hook up the new USER_NAMES document everywhere + +(Also correct the set of names we accept in User=, which was forgotten +to be updated in ae480f0b09aec815b64579bb1828ea935d8ee236. + +Reference: https://github.com/systemd/systemd/commit/887a8fa341d9b24a7c9cd3f1fce328f8e43a1b4f +Conflict: Remove unneeded file changes. +--- + man/systemd.exec.xml | 15 +++++++++------ + man/sysusers.d.xml | 3 +++ + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml +index a52d8fa..bf9b030 100644 +--- a/man/systemd.exec.xml ++++ b/man/systemd.exec.xml +@@ -186,12 +186,15 @@ + is set, the default group of the user is used. This setting does not affect commands whose command line is + prefixed with +. + +- Note that restrictions on the user/group name syntax are enforced: the specified name must consist only +- of the characters a-z, A-Z, 0-9, _ and -, except for the first character +- which must be one of a-z, A-Z or _ (i.e. numbers and - are not permitted +- as first character). The user/group name must have at least one character, and at most 31. These restrictions +- are enforced in order to avoid ambiguities and to ensure user/group names and unit files remain portable among +- Linux systems. ++ Note that this enforces only weak restrictions on the user/group name syntax, but will generate ++ warnings in many cases where user/group names do not adhere to the following rules: the specified ++ name should consist only of the characters a-z, A-Z, 0-9, _ and ++ -, except for the first character which must be one of a-z, A-Z and ++ _ (i.e. digits and - are not permitted as first character). The ++ user/group name must have at least one character, and at most 31. These restrictions are made in ++ order to avoid ambiguities and to ensure user/group names and unit files remain portable among Linux ++ systems. For further details on the names accepted and the names warned about see User/Group Name Syntax. + + When used in conjunction with DynamicUser= the user/group name specified is + dynamically allocated at the time the service is started, and released at the time the service is stopped — +diff --git a/man/sysusers.d.xml b/man/sysusers.d.xml +index e47d36c..840da44 100644 +--- a/man/sysusers.d.xml ++++ b/man/sysusers.d.xml +@@ -143,6 +143,9 @@ u root 0 "Superuser" /root /bin/zsh_ (i.e. numbers and - are not permitted as first character). The + user/group name must have at least one character, and at most 31. + ++ For further details about the syntax of user/group names, see User/Group Name Syntax. ++ + It is strongly recommended to pick user and group names that are unlikely to clash with normal users + created by the administrator. A good scheme to guarantee this is by prefixing all system and group names with the + underscore, and avoiding too generic names. +-- +2.23.0 + diff --git a/backport-0006-CVE-2020-13776-catalog-add-entry-for-SD_MESSAGE_UNSAFE_USER_NAME.patch b/backport-0006-CVE-2020-13776-catalog-add-entry-for-SD_MESSAGE_UNSAFE_USER_NAME.patch new file mode 100644 index 0000000..af047c9 --- /dev/null +++ b/backport-0006-CVE-2020-13776-catalog-add-entry-for-SD_MESSAGE_UNSAFE_USER_NAME.patch @@ -0,0 +1,45 @@ +From ad313ec33bb367624c25c9264994d6e43b8a7e2e Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 7 Apr 2020 11:15:49 +0200 +Subject: [PATCH] catalog: add entry for SD_MESSAGE_UNSAFE_USER_NAME + +Reference: https://github.com/systemd/systemd/commit/ad313ec33bb367624c25c9264994d6e43b8a7e2e +Conflict: NA +--- + catalog/systemd.catalog.in | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/catalog/systemd.catalog.in b/catalog/systemd.catalog.in +index db275d7c50..3342d59422 100644 +--- a/catalog/systemd.catalog.in ++++ b/catalog/systemd.catalog.in +@@ -412,3 +412,26 @@ as the best process to terminate and has been forcibly terminated by the + kernel. + + Note that the memory pressure might or might not have been caused by @UNIT@. ++ ++-- b61fdac612e94b9182285b998843061f ++Subject: Accepting user/group name @USER_GROUP_NAME@, which does not match strict user/group name rules. ++Defined-By: systemd ++Support: %SUPPORT_URL% ++ ++The user/group name @USER_GROUP_NAME@ has been specified, which is accepted ++according the relaxed user/group name rules, but does not qualify under the ++strict rules. ++ ++The strict user/group name rules written as regular expression are: ++ ++^[a-zA-Z_][a-zA-Z0-9_-]{0,30}$ ++ ++The relaxed user/group name rules accept all names, except for the empty ++string; names containing NUL bytes, control characters, colon or slash ++characters; names not valid UTF-8; names with leading or trailing whitespace; ++the strings "." or ".."; fully numeric strings, or strings beginning in a ++hyphen and otherwise fully numeric. ++ ++For further details on strict and relaxed user/group name rules, see: ++ ++https://systemd.io/USER_NAMES +-- +2.23.0 + diff --git a/backport-0007-CVE-2020-13776-basic-user-util-always-use-base-10-for-user-group-nu.patch b/backport-0007-CVE-2020-13776-basic-user-util-always-use-base-10-for-user-group-nu.patch new file mode 100644 index 0000000..0e2bce2 --- /dev/null +++ b/backport-0007-CVE-2020-13776-basic-user-util-always-use-base-10-for-user-group-nu.patch @@ -0,0 +1,73 @@ +From 156a5fd297b61bce31630d7a52c15614bf784843 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 31 May 2020 18:21:09 +0200 +Subject: [PATCH] basic/user-util: always use base 10 for user/group numbers + +We would parse numbers with base prefixes as user identifiers. For example, +"0x2b3bfa0" would be interpreted as UID==45334432 and "01750" would be +interpreted as UID==1000. This parsing was used also in cases where either a +user/group name or number may be specified. This means that names like +0x2b3bfa0 would be ambiguous: they are a valid user name according to our +documented relaxed rules, but they would also be parsed as numeric uids. + +This behaviour is definitely not expected by users, since tools generally only +accept decimal numbers (e.g. id, getent passwd), while other tools only accept +user names and thus will interpret such strings as user names without even +attempting to convert them to numbers (su, ssh). So let's follow suit and only +accept numbers in decimal notation. Effectively this means that we will reject +such strings as a username/uid/groupname/gid where strict mode is used, and try +to look up a user/group with such a name in relaxed mode. + +Since the function changed is fairly low-level and fairly widely used, this +affects multiple tools: loginctl show-user/enable-linger/disable-linger foo', +the third argument in sysusers.d, fourth and fifth arguments in tmpfiles.d, +etc. + +Fixes #15985. +Reference: https://github.com/systemd/systemd/commit/156a5fd297b61bce31630d7a52c15614bf784843 +Conflict: NA +--- + src/basic/user-util.c | 2 +- + src/test/test-user-util.c | 10 ++++++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + +diff --git a/src/basic/user-util.c b/src/basic/user-util.c +index 2e3580017d..2db8ef6abf 100644 +--- a/src/basic/user-util.c ++++ b/src/basic/user-util.c +@@ -49,7 +49,7 @@ int parse_uid(const char *s, uid_t *ret) { + assert(s); + + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); +- r = safe_atou32(s, &uid); ++ r = safe_atou32_full(s, 10, &uid); + if (r < 0) + return r; + +diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c +index a0e1495186..3165232fef 100644 +--- a/src/test/test-user-util.c ++++ b/src/test/test-user-util.c +@@ -48,9 +48,19 @@ static void test_parse_uid(void) { + + r = parse_uid("65535", &uid); + assert_se(r == -ENXIO); ++ assert_se(uid == 100); ++ ++ r = parse_uid("0x1234", &uid); ++ assert_se(r == -EINVAL); ++ assert_se(uid == 100); ++ ++ r = parse_uid("01234", &uid); ++ assert_se(r == 0); ++ assert_se(uid == 1234); + + r = parse_uid("asdsdas", &uid); + assert_se(r == -EINVAL); ++ assert_se(uid == 1234); + } + + static void test_uid_ptr(void) { +-- +2.23.0 + diff --git a/backport-0008-CVE-2020-13776-parse-util-sometimes-it-is-useful-to-check-if-a-stri.patch b/backport-0008-CVE-2020-13776-parse-util-sometimes-it-is-useful-to-check-if-a-stri.patch new file mode 100644 index 0000000..cceb3cf --- /dev/null +++ b/backport-0008-CVE-2020-13776-parse-util-sometimes-it-is-useful-to-check-if-a-stri.patch @@ -0,0 +1,151 @@ +From 22810041c2200fe72b0e0c985d0e404f8b80f9e2 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 14 Nov 2019 14:49:40 +0100 +Subject: [PATCH] parse-util: sometimes it is useful to check if a string is a + valid integer, but not actually parse it + +Reference: https://github.com/systemd/systemd/commit/22810041c2200fe72b0e0c985d0e404f8b80f9e2 +Conflict: NA +--- + src/basic/parse-util.c | 34 ++++++++++++++++++++-------------- + 1 file changed, 20 insertions(+), 14 deletions(-) + +diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c +index aec6099c9c..b81db04989 100644 +--- a/src/basic/parse-util.c ++++ b/src/basic/parse-util.c +@@ -365,7 +365,6 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { + unsigned long l; + + assert(s); +- assert(ret_u); + assert(base <= 16); + + /* strtoul() is happy to parse negative values, and silently +@@ -389,7 +388,9 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { + if ((unsigned long) (unsigned) l != l) + return -ERANGE; + +- *ret_u = (unsigned) l; ++ if (ret_u) ++ *ret_u = (unsigned) l; ++ + return 0; + } + +@@ -398,7 +399,6 @@ int safe_atoi(const char *s, int *ret_i) { + long l; + + assert(s); +- assert(ret_i); + + errno = 0; + l = strtol(s, &x, 0); +@@ -409,7 +409,9 @@ int safe_atoi(const char *s, int *ret_i) { + if ((long) (int) l != l) + return -ERANGE; + +- *ret_i = (int) l; ++ if (ret_i) ++ *ret_i = (int) l; ++ + return 0; + } + +@@ -418,7 +420,6 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) { + unsigned long long l; + + assert(s); +- assert(ret_llu); + + s += strspn(s, WHITESPACE); + +@@ -431,7 +432,9 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) { + if (*s == '-') + return -ERANGE; + +- *ret_llu = l; ++ if (ret_llu) ++ *ret_llu = l; ++ + return 0; + } + +@@ -440,7 +443,6 @@ int safe_atolli(const char *s, long long int *ret_lli) { + long long l; + + assert(s); +- assert(ret_lli); + + errno = 0; + l = strtoll(s, &x, 0); +@@ -449,7 +451,9 @@ int safe_atolli(const char *s, long long int *ret_lli) { + if (!x || x == s || *x != 0) + return -EINVAL; + +- *ret_lli = l; ++ if (ret_lli) ++ *ret_lli = l; ++ + return 0; + } + +@@ -458,7 +462,6 @@ int safe_atou8(const char *s, uint8_t *ret) { + unsigned long l; + + assert(s); +- assert(ret); + + s += strspn(s, WHITESPACE); + +@@ -473,7 +476,8 @@ int safe_atou8(const char *s, uint8_t *ret) { + if ((unsigned long) (uint8_t) l != l) + return -ERANGE; + +- *ret = (uint8_t) l; ++ if (ret) ++ *ret = (uint8_t) l; + return 0; + } + +@@ -507,7 +511,6 @@ int safe_atoi16(const char *s, int16_t *ret) { + long l; + + assert(s); +- assert(ret); + + errno = 0; + l = strtol(s, &x, 0); +@@ -518,7 +521,9 @@ int safe_atoi16(const char *s, int16_t *ret) { + if ((long) (int16_t) l != l) + return -ERANGE; + +- *ret = (int16_t) l; ++ if (ret) ++ *ret = (int16_t) l; ++ + return 0; + } + +@@ -528,7 +533,6 @@ int safe_atod(const char *s, double *ret_d) { + double d = 0; + + assert(s); +- assert(ret_d); + + loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0); + if (loc == (locale_t) 0) +@@ -541,7 +545,9 @@ int safe_atod(const char *s, double *ret_d) { + if (!x || x == s || *x != 0) + return -EINVAL; + +- *ret_d = (double) d; ++ if (ret_d) ++ *ret_d = (double) d; ++ + return 0; + } + +-- +2.23.0 + diff --git a/backport-0009-CVE-2020-13776-basic-parse-util-add-safe_atoux64.patch b/backport-0009-CVE-2020-13776-basic-parse-util-add-safe_atoux64.patch new file mode 100644 index 0000000..5dc0591 --- /dev/null +++ b/backport-0009-CVE-2020-13776-basic-parse-util-add-safe_atoux64.patch @@ -0,0 +1,132 @@ +From ce51632a357d347737bf40d3817df331cd8874cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 9 Apr 2020 11:18:26 +0200 +Subject: [PATCH] basic/parse-util: add safe_atoux64() + +Reference: https://github.com/systemd/systemd/commit/ce51632a357d347737bf40d3817df331cd8874cb +Conflict: NA +--- + src/basic/parse-util.c | 4 ++-- + src/basic/parse-util.h | 12 +++++++++++- + src/test/test-parse-util.c | 39 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 52 insertions(+), 3 deletions(-) + +diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c +index e0094b0f37..8de5cd5c56 100644 +--- a/src/basic/parse-util.c ++++ b/src/basic/parse-util.c +@@ -395,7 +395,7 @@ int safe_atoi(const char *s, int *ret_i) { + return 0; + } + +-int safe_atollu(const char *s, long long unsigned *ret_llu) { ++int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu) { + char *x = NULL; + unsigned long long l; + +@@ -404,7 +404,7 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) { + s += strspn(s, WHITESPACE); + + errno = 0; +- l = strtoull(s, &x, 0); ++ l = strtoull(s, &x, base); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) +diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h +index 36d76ba576..970bdefbf0 100644 +--- a/src/basic/parse-util.h ++++ b/src/basic/parse-util.h +@@ -28,7 +28,6 @@ static inline int safe_atou(const char *s, unsigned *ret_u) { + } + + int safe_atoi(const char *s, int *ret_i); +-int safe_atollu(const char *s, unsigned long long *ret_u); + int safe_atolli(const char *s, long long int *ret_i); + + int safe_atou8(const char *s, uint8_t *ret); +@@ -59,6 +58,12 @@ static inline int safe_atoi32(const char *s, int32_t *ret_i) { + return safe_atoi(s, (int*) ret_i); + } + ++int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu); ++ ++static inline int safe_atollu(const char *s, long long unsigned *ret_llu) { ++ return safe_atollu_full(s, 0, ret_llu); ++} ++ + static inline int safe_atou64(const char *s, uint64_t *ret_u) { + assert_cc(sizeof(uint64_t) == sizeof(unsigned long long)); + return safe_atollu(s, (unsigned long long*) ret_u); +@@ -69,6 +74,11 @@ static inline int safe_atoi64(const char *s, int64_t *ret_i) { + return safe_atolli(s, (long long int*) ret_i); + } + ++static inline int safe_atoux64(const char *s, uint64_t *ret) { ++ assert_cc(sizeof(int64_t) == sizeof(long long unsigned)); ++ return safe_atollu_full(s, 16, (long long unsigned*) ret); ++} ++ + #if LONG_MAX == INT_MAX + static inline int safe_atolu(const char *s, unsigned long *ret_u) { + assert_cc(sizeof(unsigned long) == sizeof(unsigned)); +diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c +index d732f402f0..1627bc747d 100644 +--- a/src/test/test-parse-util.c ++++ b/src/test/test-parse-util.c +@@ -561,6 +561,44 @@ static void test_safe_atoi64(void) { + assert_se(r == -EINVAL); + } + ++static void test_safe_atoux64(void) { ++ int r; ++ uint64_t l; ++ ++ r = safe_atoux64("12345", &l); ++ assert_se(r == 0); ++ assert_se(l == 0x12345); ++ ++ r = safe_atoux64(" 12345", &l); ++ assert_se(r == 0); ++ assert_se(l == 0x12345); ++ ++ r = safe_atoux64("0x12345", &l); ++ assert_se(r == 0); ++ assert_se(l == 0x12345); ++ ++ r = safe_atoux64("18446744073709551617", &l); ++ assert_se(r == -ERANGE); ++ ++ r = safe_atoux64("-1", &l); ++ assert_se(r == -ERANGE); ++ ++ r = safe_atoux64(" -1", &l); ++ assert_se(r == -ERANGE); ++ ++ r = safe_atoux64("junk", &l); ++ assert_se(r == -EINVAL); ++ ++ r = safe_atoux64("123x", &l); ++ assert_se(r == -EINVAL); ++ ++ r = safe_atoux64("12.3", &l); ++ assert_se(r == -EINVAL); ++ ++ r = safe_atoux64("", &l); ++ assert_se(r == -EINVAL); ++} ++ + static void test_safe_atod(void) { + int r; + double d; +@@ -838,6 +876,7 @@ int main(int argc, char *argv[]) { + test_safe_atoux16(); + test_safe_atou64(); + test_safe_atoi64(); ++ test_safe_atoux64(); + test_safe_atod(); + test_parse_percent(); + test_parse_percent_unbounded(); +-- +2.23.0 + diff --git a/backport-0010-CVE-2020-13776-parse-util-allow-tweaking-how-to-parse-integers.patch b/backport-0010-CVE-2020-13776-parse-util-allow-tweaking-how-to-parse-integers.patch new file mode 100644 index 0000000..ae3b68a --- /dev/null +++ b/backport-0010-CVE-2020-13776-parse-util-allow-tweaking-how-to-parse-integers.patch @@ -0,0 +1,155 @@ +From 707e93aff8f358f8a62117e54b857530d6594e4b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 1 Jun 2020 17:06:19 +0200 +Subject: [PATCH] parse-util: allow tweaking how to parse integers + +This allows disabling a few alternative ways to decode integers +formatted as strings, for safety reasons. + +See: #15991 +Reference: https://github.com/systemd/systemd/commit/707e93aff8f358f8a62117e54b857530d6594e4b +Conflict: Add inline function safe_atou32_full. +--- + src/basic/parse-util.c | 65 +++++++++++++++++++++++++++++++++--------- + src/basic/parse-util.h | 13 ++++++++- + 2 files changed, 64 insertions(+), 14 deletions(-) + +diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c +index 59f8a31cec..15818958e4 100644 +--- a/src/basic/parse-util.c ++++ b/src/basic/parse-util.c +@@ -359,20 +359,35 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { + unsigned long l; + + assert(s); +- assert(base <= 16); ++ assert(SAFE_ATO_MASK_FLAGS(base) <= 16); + +- /* strtoul() is happy to parse negative values, and silently +- * converts them to unsigned values without generating an +- * error. We want a clean error, hence let's look for the "-" +- * prefix on our own, and generate an error. But let's do so +- * only after strtoul() validated that the string is clean +- * otherwise, so that we return EINVAL preferably over +- * ERANGE. */ ++ /* strtoul() is happy to parse negative values, and silently converts them to unsigned values without ++ * generating an error. We want a clean error, hence let's look for the "-" prefix on our own, and ++ * generate an error. But let's do so only after strtoul() validated that the string is clean ++ * otherwise, so that we return EINVAL preferably over ERANGE. */ ++ ++ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) && ++ strchr(WHITESPACE, s[0])) ++ return -EINVAL; + + s += strspn(s, WHITESPACE); + ++ if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) && ++ IN_SET(s[0], '+', '-')) ++ return -EINVAL; /* Note that we check the "-" prefix again a second time below, but return a ++ * different error. I.e. if the SAFE_ATO_REFUSE_PLUS_MINUS flag is set we ++ * blanket refuse +/- prefixed integers, while if it is missing we'll just ++ * return ERANGE, because the string actually parses correctly, but doesn't ++ * fit in the return type. */ ++ ++ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) && ++ s[0] == '0' && !streq(s, "0")) ++ return -EINVAL; /* This is particularly useful to avoid ambiguities between C's octal ++ * notation and assumed-to-be-decimal integers with a leading zero. */ ++ + errno = 0; +- l = strtoul(s, &x, base); ++ l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base) /* Let's mask off the flags bits so that only the actual ++ * base is left */); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) +@@ -414,11 +429,24 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu) + unsigned long long l; + + assert(s); ++ assert(SAFE_ATO_MASK_FLAGS(base) <= 16); ++ ++ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) && ++ strchr(WHITESPACE, s[0])) ++ return -EINVAL; + + s += strspn(s, WHITESPACE); + ++ if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) && ++ IN_SET(s[0], '+', '-')) ++ return -EINVAL; ++ ++ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) && ++ s[0] == '0' && s[1] != 0) ++ return -EINVAL; ++ + errno = 0; +- l = strtoull(s, &x, base); ++ l = strtoull(s, &x, SAFE_ATO_MASK_FLAGS(base)); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) +@@ -480,13 +508,24 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) { + unsigned long l; + + assert(s); +- assert(ret); +- assert(base <= 16); ++ assert(SAFE_ATO_MASK_FLAGS(base) <= 16); ++ ++ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_WHITESPACE) && ++ strchr(WHITESPACE, s[0])) ++ return -EINVAL; + + s += strspn(s, WHITESPACE); + ++ if (FLAGS_SET(base, SAFE_ATO_REFUSE_PLUS_MINUS) && ++ IN_SET(s[0], '+', '-')) ++ return -EINVAL; ++ ++ if (FLAGS_SET(base, SAFE_ATO_REFUSE_LEADING_ZERO) && ++ s[0] == '0' && s[1] != 0) ++ return -EINVAL; ++ + errno = 0; +- l = strtoul(s, &x, base); ++ l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base)); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) +diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h +index 84a2c8a..ae7fca7 100644 +--- a/src/basic/parse-util.h ++++ b/src/basic/parse-util.h +@@ -22,6 +22,12 @@ int parse_range(const char *t, unsigned *lower, unsigned *upper); + int parse_errno(const char *t); + int parse_syscall_and_errno(const char *in, char **name, int *error); + ++#define SAFE_ATO_REFUSE_PLUS_MINUS (1U << 30) ++#define SAFE_ATO_REFUSE_LEADING_ZERO (1U << 29) ++#define SAFE_ATO_REFUSE_LEADING_WHITESPACE (1U << 28) ++#define SAFE_ATO_ALL_FLAGS (SAFE_ATO_REFUSE_PLUS_MINUS|SAFE_ATO_REFUSE_LEADING_ZERO|SAFE_ATO_REFUSE_LEADING_WHITESPACE) ++#define SAFE_ATO_MASK_FLAGS(base) ((base) & ~SAFE_ATO_ALL_FLAGS) ++ + int safe_atou_full(const char *s, unsigned base, unsigned *ret_u); + + static inline int safe_atou(const char *s, unsigned *ret_u) { +@@ -45,9 +51,14 @@ static inline int safe_atoux16(const char *s, uint16_t *ret) { + + int safe_atoi16(const char *s, int16_t *ret); + ++static inline int safe_atou32_full(const char *s, unsigned base, uint32_t *ret_u) { ++ assert_cc(sizeof(uint32_t) == sizeof(unsigned)); ++ return safe_atou_full(s, base, (unsigned*) ret_u); ++} ++ + static inline int safe_atou32(const char *s, uint32_t *ret_u) { + assert_cc(sizeof(uint32_t) == sizeof(unsigned)); +- return safe_atou(s, (unsigned*) ret_u); ++ return safe_atou32_full(s, 0, (unsigned*) ret_u); + } + + static inline int safe_atoi32(const char *s, int32_t *ret_i) { +-- +2.23.0 + diff --git a/backport-0011-CVE-2020-13776-parse-util-allow-0-as-alternative-to-0-and-0.patch b/backport-0011-CVE-2020-13776-parse-util-allow-0-as-alternative-to-0-and-0.patch new file mode 100644 index 0000000..e314d2f --- /dev/null +++ b/backport-0011-CVE-2020-13776-parse-util-allow-0-as-alternative-to-0-and-0.patch @@ -0,0 +1,61 @@ +From c78eefc13562a8fc0c22c00a6d3001af89860258 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 1 Jun 2020 17:08:38 +0200 +Subject: [PATCH] parse-util: allow '-0' as alternative to '0' and '+0' + +Let's allow "-0" as alternative to "+0" and "0" when parsing integers, +unless the new SAFE_ATO_REFUSE_PLUS_MINUS flag is specified. + +In cases where allowing the +/- syntax shall not be allowed +SAFE_ATO_REFUSE_PLUS_MINUS is the right flag to use, but this also means +that -0 as only negative integer that fits into an unsigned value should +be acceptable if the flag is not specified. +Reference: https://github.com/systemd/systemd/commit/c78eefc13562a8fc0c22c00a6d3001af89860258 +Conflict: NA +--- + src/basic/parse-util.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c +index 15818958e4..7344dc4311 100644 +--- a/src/basic/parse-util.c ++++ b/src/basic/parse-util.c +@@ -392,7 +392,7 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; +- if (s[0] == '-') ++ if (l != 0 && s[0] == '-') + return -ERANGE; + if ((unsigned long) (unsigned) l != l) + return -ERANGE; +@@ -451,7 +451,7 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu) + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; +- if (*s == '-') ++ if (l != 0 && s[0] == '-') + return -ERANGE; + + if (ret_llu) +@@ -493,7 +493,7 @@ int safe_atou8(const char *s, uint8_t *ret) { + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; +- if (s[0] == '-') ++ if (l != 0 && s[0] == '-') + return -ERANGE; + if ((unsigned long) (uint8_t) l != l) + return -ERANGE; +@@ -530,7 +530,7 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) { + return -errno; + if (!x || x == s || *x != 0) + return -EINVAL; +- if (s[0] == '-') ++ if (l != 0 && s[0] == '-') + return -ERANGE; + if ((unsigned long) (uint16_t) l != l) + return -ERANGE; +-- +2.23.0 + diff --git a/backport-0012-CVE-2020-13776-parse-util-make-return-parameter-optional-in-safe_at.patch b/backport-0012-CVE-2020-13776-parse-util-make-return-parameter-optional-in-safe_at.patch new file mode 100644 index 0000000..95b5179 --- /dev/null +++ b/backport-0012-CVE-2020-13776-parse-util-make-return-parameter-optional-in-safe_at.patch @@ -0,0 +1,32 @@ +From aa85e4d3cef8ca8436e480bce9fa4ce72876b636 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 1 Jun 2020 17:10:27 +0200 +Subject: [PATCH] parse-util: make return parameter optional in + safe_atou16_full() + +All other safe_atoXYZ_full() functions have the parameter optional, +let's make it optoinal here, too. +Reference: https://github.com/systemd/systemd/commit/aa85e4d3cef8ca8436e480bce9fa4ce72876b636 +Conflict: NA +--- + src/basic/parse-util.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c +index 7344dc4311..c58f2cdda1 100644 +--- a/src/basic/parse-util.c ++++ b/src/basic/parse-util.c +@@ -535,7 +535,9 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) { + if ((unsigned long) (uint16_t) l != l) + return -ERANGE; + +- *ret = (uint16_t) l; ++ if (ret) ++ *ret = (uint16_t) l; ++ + return 0; + } + +-- +2.23.0 + diff --git a/backport-0013-CVE-2020-13776-parse-util-rewrite-parse_mode-on-top-of-safe_atou_fu.patch b/backport-0013-CVE-2020-13776-parse-util-rewrite-parse_mode-on-top-of-safe_atou_fu.patch new file mode 100644 index 0000000..69a2df1 --- /dev/null +++ b/backport-0013-CVE-2020-13776-parse-util-rewrite-parse_mode-on-top-of-safe_atou_fu.patch @@ -0,0 +1,60 @@ +From c44702a8bd8cc8b7f2f1df21db9308d9af7dda5b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 1 Jun 2020 17:16:04 +0200 +Subject: [PATCH] parse-util: rewrite parse_mode() on top of safe_atou_full() + +Parsing is hard, hence let's use our own careful wrappers wherever +possible. +Reference: https://github.com/systemd/systemd/commit/c44702a8bd8cc8b7f2f1df21db9308d9af7dda5b +Conflict: NA +--- + src/basic/parse-util.c | 28 +++++++++++++--------------- + 1 file changed, 13 insertions(+), 15 deletions(-) + +diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c +index c58f2cdda1..0f6d24f590 100644 +--- a/src/basic/parse-util.c ++++ b/src/basic/parse-util.c +@@ -70,26 +70,24 @@ int parse_pid(const char *s, pid_t* ret_pid) { + } + + int parse_mode(const char *s, mode_t *ret) { +- char *x; +- long l; ++ unsigned m; ++ int r; + + assert(s); +- assert(ret); + +- s += strspn(s, WHITESPACE); +- if (s[0] == '-') +- return -ERANGE; +- +- errno = 0; +- l = strtol(s, &x, 8); +- if (errno > 0) +- return -errno; +- if (!x || x == s || *x != 0) +- return -EINVAL; +- if (l < 0 || l > 07777) ++ r = safe_atou_full(s, 8 | ++ SAFE_ATO_REFUSE_PLUS_MINUS, /* Leading '+' or even '-' char? that's just weird, ++ * refuse. User might have wanted to add mode flags or ++ * so, but this parser doesn't allow that, so let's ++ * better be safe. */ ++ &m); ++ if (r < 0) ++ return r; ++ if (m > 07777) + return -ERANGE; + +- *ret = (mode_t) l; ++ if (ret) ++ *ret = m; + return 0; + } + +-- +2.23.0 + diff --git a/backport-0014-CVE-2020-13776-user-util-be-stricter-in-parse_uid.patch b/backport-0014-CVE-2020-13776-user-util-be-stricter-in-parse_uid.patch new file mode 100644 index 0000000..4101808 --- /dev/null +++ b/backport-0014-CVE-2020-13776-user-util-be-stricter-in-parse_uid.patch @@ -0,0 +1,79 @@ +From f5979b63cc305ba217dfd174b1bf0583bcf75a73 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 1 Jun 2020 17:16:46 +0200 +Subject: [PATCH] user-util: be stricter in parse_uid() + +Let's refuse "+" and "-" prefixed UIDs. Let's refuse whitespace-prefixed +UIDS, Let's refuse zero-prefixed UIDs. Let's be safe than sorry. +Reference: https://github.com/systemd/systemd/commit/f5979b63cc305ba217dfd174b1bf0583bcf75a73 +Conflict: NA +--- + src/basic/user-util.c | 10 +++++++++- + src/test/test-user-util.c | 26 +++++++++++++++++++++++--- + 2 files changed, 32 insertions(+), 4 deletions(-) + +diff --git a/src/basic/user-util.c b/src/basic/user-util.c +index 2db8ef6abf..4d087b1d3e 100644 +--- a/src/basic/user-util.c ++++ b/src/basic/user-util.c +@@ -49,7 +49,15 @@ int parse_uid(const char *s, uid_t *ret) { + assert(s); + + assert_cc(sizeof(uid_t) == sizeof(uint32_t)); +- r = safe_atou32_full(s, 10, &uid); ++ ++ /* We are very strict when parsing UIDs, and prohibit +/- as prefix, leading zero as prefix, and ++ * whitespace. We do this, since this call is often used in a context where we parse things as UID ++ * first, and if that doesn't work we fall back to NSS. Thus we really want to make sure that UIDs ++ * are parsed as UIDs only if they really really look like UIDs. */ ++ r = safe_atou32_full(s, 10 ++ | SAFE_ATO_REFUSE_PLUS_MINUS ++ | SAFE_ATO_REFUSE_LEADING_ZERO ++ | SAFE_ATO_REFUSE_LEADING_WHITESPACE, &uid); + if (r < 0) + return r; + +diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c +index 3165232fef..7d2efc8c59 100644 +--- a/src/test/test-user-util.c ++++ b/src/test/test-user-util.c +@@ -54,13 +54,33 @@ static void test_parse_uid(void) { + assert_se(r == -EINVAL); + assert_se(uid == 100); + ++ r = parse_uid("+1234", &uid); ++ assert_se(r == -EINVAL); ++ assert_se(uid == 100); ++ ++ r = parse_uid("-1234", &uid); ++ assert_se(r == -EINVAL); ++ assert_se(uid == 100); ++ ++ r = parse_uid(" 1234", &uid); ++ assert_se(r == -EINVAL); ++ assert_se(uid == 100); ++ + r = parse_uid("01234", &uid); +- assert_se(r == 0); +- assert_se(uid == 1234); ++ assert_se(r == -EINVAL); ++ assert_se(uid == 100); ++ ++ r = parse_uid("-0", &uid); ++ assert_se(r == -EINVAL); ++ assert_se(uid == 100); ++ ++ r = parse_uid("+0", &uid); ++ assert_se(r == -EINVAL); ++ assert_se(uid == 100); + + r = parse_uid("asdsdas", &uid); + assert_se(r == -EINVAL); +- assert_se(uid == 1234); ++ assert_se(uid == 100); + } + + static void test_uid_ptr(void) { +-- +2.23.0 + diff --git a/backport-0015-CVE-2020-13776-parse-util-also-parse-integers-prefixed-with-0b-and-.patch b/backport-0015-CVE-2020-13776-parse-util-also-parse-integers-prefixed-with-0b-and-.patch new file mode 100644 index 0000000..9ded598 --- /dev/null +++ b/backport-0015-CVE-2020-13776-parse-util-also-parse-integers-prefixed-with-0b-and-.patch @@ -0,0 +1,165 @@ +From fc80cabcf584a8b486bdff5be0c074fec4059cdc Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 1 Jun 2020 17:31:51 +0200 +Subject: [PATCH] parse-util: also parse integers prefixed with 0b and 0o + +Let's adopt Python 3 style 0b and 0x syntaxes, because it makes a ton of +sense, in particular in bitmask settings. +Reference: https://github.com/systemd/systemd/commit/fc80cabcf584a8b486bdff5be0c074fec4059cdc +Conflict: Also include strv.h. +--- + src/basic/parse-util.c | 57 ++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 52 insertions(+), 5 deletions(-) + +diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c +index b4c7f0d..bf56410 100644 +--- a/src/basic/parse-util.c ++++ b/src/basic/parse-util.c +@@ -20,6 +20,7 @@ + #include "process-util.h" + #include "stat-util.h" + #include "string-util.h" ++#include "strv.h" + + int parse_boolean(const char *v) { + if (!v) +@@ -360,6 +361,32 @@ int parse_syscall_and_errno(const char *in, char **name, int *error) { + return 0; + } + ++static const char *mangle_base(const char *s, unsigned *base) { ++ const char *k; ++ ++ assert(s); ++ assert(base); ++ ++ /* Base already explicitly specified, then don't do anything. */ ++ if (SAFE_ATO_MASK_FLAGS(*base) != 0) ++ return s; ++ ++ /* Support Python 3 style "0b" and 0x" prefixes, because they truly make sense, much more than C's "0" prefix for octal. */ ++ k = STARTSWITH_SET(s, "0b", "0B"); ++ if (k) { ++ *base = 2 | (*base & SAFE_ATO_ALL_FLAGS); ++ return k; ++ } ++ ++ k = STARTSWITH_SET(s, "0o", "0O"); ++ if (k) { ++ *base = 8 | (*base & SAFE_ATO_ALL_FLAGS); ++ return k; ++ } ++ ++ return s; ++} ++ + int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { + char *x = NULL; + unsigned long l; +@@ -391,6 +418,8 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { + return -EINVAL; /* This is particularly useful to avoid ambiguities between C's octal + * notation and assumed-to-be-decimal integers with a leading zero. */ + ++ s = mangle_base(s, &base); ++ + errno = 0; + l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base) /* Let's mask off the flags bits so that only the actual + * base is left */); +@@ -410,13 +439,17 @@ int safe_atou_full(const char *s, unsigned base, unsigned *ret_u) { + } + + int safe_atoi(const char *s, int *ret_i) { ++ unsigned base = 0; + char *x = NULL; + long l; + + assert(s); + ++ s += strspn(s, WHITESPACE); ++ s = mangle_base(s, &base); ++ + errno = 0; +- l = strtol(s, &x, 0); ++ l = strtol(s, &x, base); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) +@@ -451,6 +484,8 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu) + s[0] == '0' && s[1] != 0) + return -EINVAL; + ++ s = mangle_base(s, &base); ++ + errno = 0; + l = strtoull(s, &x, SAFE_ATO_MASK_FLAGS(base)); + if (errno > 0) +@@ -467,13 +502,17 @@ int safe_atollu_full(const char *s, unsigned base, long long unsigned *ret_llu) + } + + int safe_atolli(const char *s, long long int *ret_lli) { ++ unsigned base = 0; + char *x = NULL; + long long l; + + assert(s); + ++ s += strspn(s, WHITESPACE); ++ s = mangle_base(s, &base); ++ + errno = 0; +- l = strtoll(s, &x, 0); ++ l = strtoll(s, &x, base); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) +@@ -486,15 +525,17 @@ int safe_atolli(const char *s, long long int *ret_lli) { + } + + int safe_atou8(const char *s, uint8_t *ret) { +- char *x = NULL; ++ unsigned base = 0; + unsigned long l; ++ char *x = NULL; + + assert(s); + + s += strspn(s, WHITESPACE); ++ s = mangle_base(s, &base); + + errno = 0; +- l = strtoul(s, &x, 0); ++ l = strtoul(s, &x, base); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) +@@ -530,6 +571,8 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) { + s[0] == '0' && s[1] != 0) + return -EINVAL; + ++ s = mangle_base(s, &base); ++ + errno = 0; + l = strtoul(s, &x, SAFE_ATO_MASK_FLAGS(base)); + if (errno > 0) +@@ -548,13 +591,17 @@ int safe_atou16_full(const char *s, unsigned base, uint16_t *ret) { + } + + int safe_atoi16(const char *s, int16_t *ret) { ++ unsigned base = 0; + char *x = NULL; + long l; + + assert(s); + ++ s += strspn(s, WHITESPACE); ++ s = mangle_base(s, &base); ++ + errno = 0; +- l = strtol(s, &x, 0); ++ l = strtol(s, &x, base); + if (errno > 0) + return -errno; + if (!x || x == s || *x != 0) +-- +2.23.0 + diff --git a/systemd.spec b/systemd.spec index b24b20b..bf1f1d4 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 49 +Release: 50 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -139,6 +139,21 @@ Patch0089: backport-0006-CVE-2021-3997-tmpfiles-st-may-have-been-used-unini Patch0090: backport-0007-CVE-2021-3997-shared-rm_rf-refactor-rm_rf_children_inner-to-shorte.patch Patch0091: backport-0008-CVE-2021-3997-shared-rm_rf-refactor-rm_rf-to-shorten-code-a-bit.patch Patch0092: backport-0009-CVE-2021-3997-shared-rm-rf-loop-over-nested-directories-instead-of.patch +Patch0093: backport-0001-CVE-2020-13776-user-util-Allow-names-starting-with-a-digit.patch +Patch0094: backport-0002-CVE-2020-13776-user-util-switch-order-of-checks-in-valid_user_group.patch +Patch0095: backport-0003-CVE-2020-13776-user-util-rework-how-we-validate-user-names.patch +Patch0096: backport-0004-CVE-2020-13776-docs-add-a-longer-document-explaining-our-rules-on-u.patch +Patch0097: backport-0005-CVE-2020-13776-docs-hook-up-the-new-USER_NAMES-document-everywhere.patch +Patch0098: backport-0006-CVE-2020-13776-catalog-add-entry-for-SD_MESSAGE_UNSAFE_USER_NAME.patch +Patch0099: backport-0007-CVE-2020-13776-basic-user-util-always-use-base-10-for-user-group-nu.patch +Patch0100: backport-0008-CVE-2020-13776-parse-util-sometimes-it-is-useful-to-check-if-a-stri.patch +Patch0101: backport-0009-CVE-2020-13776-basic-parse-util-add-safe_atoux64.patch +Patch0102: backport-0010-CVE-2020-13776-parse-util-allow-tweaking-how-to-parse-integers.patch +Patch0103: backport-0011-CVE-2020-13776-parse-util-allow-0-as-alternative-to-0-and-0.patch +Patch0104: backport-0012-CVE-2020-13776-parse-util-make-return-parameter-optional-in-safe_at.patch +Patch0105: backport-0013-CVE-2020-13776-parse-util-rewrite-parse_mode-on-top-of-safe_atou_fu.patch +Patch0106: backport-0014-CVE-2020-13776-user-util-be-stricter-in-parse_uid.patch +Patch0107: backport-0015-CVE-2020-13776-parse-util-also-parse-integers-prefixed-with-0b-and-.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1526,6 +1541,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Wed Feb 16 2021 yangmingtai - 243-50 +- fix CVE-2020-13776 + * Tue Jan 18 2021 yangmingtai - 243-49 - CVE:fix CVE-2021-3997 -- Gitee From 355acaa8b9dc56254039f04609672d1b57f51254 Mon Sep 17 00:00:00 2001 From: ship_harbour Date: Sat, 26 Feb 2022 17:36:37 +0800 Subject: [PATCH 30/38] add backport-udev-rename-the-persistent-link-for-ATA-devices.patch for the name of ATA devices --- ...-the-persistent-link-for-ATA-devices.patch | 267 ++++++++++++++++++ systemd.spec | 11 +- 2 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 backport-udev-rename-the-persistent-link-for-ATA-devices.patch diff --git a/backport-udev-rename-the-persistent-link-for-ATA-devices.patch b/backport-udev-rename-the-persistent-link-for-ATA-devices.patch new file mode 100644 index 0000000..74cb44e --- /dev/null +++ b/backport-udev-rename-the-persistent-link-for-ATA-devices.patch @@ -0,0 +1,267 @@ +From 9b3278d90704416bfe51a05d5681caf99445fb2f Mon Sep 17 00:00:00 2001 +From: Lidong Zhong +Date: Wed, 15 Apr 2020 00:54:57 +0800 +Subject: [PATCH] udev: rename the persistent link for ATA devices + +ATA devices should use the ATA ids like port number and (possibly) +master/slave or multiplier id, not the generic SCSI ID. +Currently only port number is included in the link. With this patch +the link would be able to support more cases, which are a) when the +device is behind a port multiplexer b) the distinction between master +and slave (distinguished by target id). + +I tried to verify scenario a) with this patch, but I failed to find a +machine with PMP SATA devices attached. But the link below +https://github.com/systemd/systemd/issues/3943 +could show what's the difference. Here is my test for scenario b) + +Current version: +linux-ql21:~ # ll /sys/class/block/sd[ab] +lrwxrwxrwx 1 root root 0 May 8 20:46 /sys/class/block/sda -> +../../devices/pci0000:00/0000:00:01.1/ata4/host3/target3:0:0/3:0:0:0/block/sda +lrwxrwxrwx 1 root root 0 May 8 20:46 /sys/class/block/sdb -> +../../devices/pci0000:00/0000:00:01.1/ata4/host3/target3:0:1/3:0:1:0/block/sdb +linux-ql21:~ # ll /dev/disk/by-path/pci-0000\:00\:01.1-ata-1 +lrwxrwxrwx 1 root root 9 May 8 20:44 +/dev/disk/by-path/pci-0000:00:01.1-ata-1 -> ../../sdb +linux-ql21:~ # udevadm info /sys/class/block/sda |grep by-path +S: disk/by-path/pci-0000:00:01.1-ata-1 +E: DEVLINKS=/dev/disk/by-id/ata-VBOX_HARDDISK_VB3649e885-3e0cdd64 +/dev/disk/by-id/scsi-0ATA_VBOX_HARDDISK_VB3649e885-3e0cdd64 +/dev/disk/by-id/scsi-1ATA_VBOX_HARDDISK_VB3649e885-3e0cdd64 +/dev/disk/by-path/pci-0000:00:01.1-ata-1 +/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VB3649e885-3e0cdd64 +linux-ql21:~ # udevadm info /sys/class/block/sdb |grep by-path +S: disk/by-path/pci-0000:00:01.1-ata-1 +E: DEVLINKS=/dev/disk/by-id/ata-VBOX_HARDDISK_VBc53b2498-d84ae8de +/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBc53b2498-d84ae8de +/dev/disk/by-id/scsi-1ATA_VBOX_HARDDISK_VBc53b2498-d84ae8de +/dev/disk/by-id/scsi-0ATA_VBOX_HARDDISK_VBc53b2498-d84ae8de +/dev/disk/by-path/pci-0000:00:01.1-ata-1 + +After patch applied: +linux-ql21:~ # ll /sys/class/block/sd[ab] +lrwxrwxrwx 1 root root 0 May 8 21:07 /sys/class/block/sda -> +../../devices/pci0000:00/0000:00:01.1/ata4/host3/target3:0:0/3:0:0:0/block/sda +lrwxrwxrwx 1 root root 0 May 8 21:07 /sys/class/block/sdb -> +../../devices/pci0000:00/0000:00:01.1/ata4/host3/target3:0:1/3:0:1:0/block/sdb +linux-ql21:~ # ll /dev/disk/by-path/pci-0000\:00\:01.1-ata-* +lrwxrwxrwx 1 root root 9 May 8 21:07 +/dev/disk/by-path/pci-0000:00:01.1-ata-1.0 -> ../../sda +lrwxrwxrwx 1 root root 9 May 8 21:07 +/dev/disk/by-path/pci-0000:00:01.1-ata-1.1 -> ../../sdb +linux-ql21:~ # udevadm info /sys/class/block/sda |grep by-path +S: disk/by-path/pci-0000:00:01.1-ata-1.0 +E: DEVLINKS=/dev/disk/by-id/scsi-1ATA_VBOX_HARDDISK_VB3649e885-3e0cdd64 +/dev/disk/by-id/scsi-0ATA_VBOX_HARDDISK_VB3649e885-3e0cdd64 +/dev/disk/by-id/ata-VBOX_HARDDISK_VB3649e885-3e0cdd64 +/dev/disk/by-path/pci-0000:00:01.1-ata-1.0 +/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VB3649e885-3e0cdd64 +linux-ql21:~ # udevadm info /sys/class/block/sdb |grep by-path +S: disk/by-path/pci-0000:00:01.1-ata-1.1 +E: DEVLINKS=/dev/disk/by-id/scsi-0ATA_VBOX_HARDDISK_VBc53b2498-d84ae8de +/dev/disk/by-id/ata-VBOX_HARDDISK_VBc53b2498-d84ae8de +/dev/disk/by-id/scsi-1ATA_VBOX_HARDDISK_VBc53b2498-d84ae8de +/dev/disk/by-id/scsi-SATA_VBOX_HARDDISK_VBc53b2498-d84ae8de +/dev/disk/by-path/pci-0000:00:01.1-ata-1.1 + +Changelog: +v5: add another parameter compat_link in handle_scsi() +v4: comment for ID_PATH_ATA_COMPAT + get string length with pointer difference + (suggested by Franck Bui) +v3: creating compatible link from env + variables type change +v2: remove udev rules modification for compatible link + setup a test scenario of master/slave ATA devices +v1: initial patch + +Conflict:NA +Reference:https://github.com/systemd/systemd/commit/9b3278d90704416bfe51a05d5681caf99445fb2f +--- + rules/60-persistent-storage.rules | 3 ++ + src/udev/udev-builtin-path_id.c | 55 +++++++++++++++++++++++++---- + 2 files changed, 52 insertions(+), 6 deletions(-) + +diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules +index 01586690bd..821e9db86f 100644 +--- a/rules/60-persistent-storage.rules ++++ b/rules/60-persistent-storage.rules +@@ -93,6 +93,9 @@ ENV{DEVTYPE}=="disk", DEVPATH!="*/virtual/*", IMPORT{builtin}="path_id" + KERNEL=="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-boot%n" + KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}" + ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n" ++# compatible links for ATA devices ++KERNEL!="mmcblk[0-9]boot[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_PATH_ATA_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_ATA_COMPAT}" ++ENV{DEVTYPE}=="partition", ENV{ID_PATH_ATA_COMPAT}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH_ATA_COMPAT}-part%n" + + # legacy virtio-pci by-path links (deprecated) + KERNEL=="vd*[!0-9]", ENV{ID_PATH}=="pci-*", SYMLINK+="disk/by-path/virtio-$env{ID_PATH}" +diff --git a/src/udev/udev-builtin-path_id.c b/src/udev/udev-builtin-path_id.c +index ca38f56087..48e9500548 100644 +--- a/src/udev/udev-builtin-path_id.c ++++ b/src/udev/udev-builtin-path_id.c +@@ -253,14 +253,20 @@ static sd_device *handle_scsi_iscsi(sd_device *parent, char **path) { + return parent; + } + +-static sd_device *handle_scsi_ata(sd_device *parent, char **path) { ++static sd_device *handle_scsi_ata(sd_device *parent, char **path, char **compat_path) { + sd_device *targetdev, *target_parent; + _cleanup_(sd_device_unrefp) sd_device *atadev = NULL; +- const char *port_no, *sysname; ++ const char *port_no, *sysname, *name; ++ unsigned host, bus, target, lun; + + assert(parent); + assert(path); + ++ if (sd_device_get_sysname(parent, &name) < 0) ++ return NULL; ++ if (sscanf(name, "%u:%u:%u:%u", &host, &bus, &target, &lun) != 4) ++ return NULL; ++ + if (sd_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host", &targetdev) < 0) + return NULL; + +@@ -275,7 +281,17 @@ static sd_device *handle_scsi_ata(sd_device *parent, char **path) { + if (sd_device_get_sysattr_value(atadev, "port_no", &port_no) < 0) + return NULL; + +- path_prepend(path, "ata-%s", port_no); ++ if (bus != 0) ++ /* Devices behind port multiplier have a bus != 0*/ ++ path_prepend(path, "ata-%s.%u.0", port_no, bus); ++ else ++ /* Master/slave are distinguished by target id */ ++ path_prepend(path, "ata-%s.%u", port_no, target); ++ ++ /* old compatible persistent link for ATA devices */ ++ if (compat_path) ++ path_prepend(compat_path, "ata-%s", port_no); ++ + return parent; + } + +@@ -392,7 +408,7 @@ static sd_device *handle_scsi_hyperv(sd_device *parent, char **path, size_t guid + return parent; + } + +-static sd_device *handle_scsi(sd_device *parent, char **path, bool *supported_parent) { ++static sd_device *handle_scsi(sd_device *parent, char **path, char **compat_path, bool *supported_parent) { + const char *devtype, *id, *name; + + if (sd_device_get_devtype(parent, &devtype) < 0 || +@@ -426,7 +442,7 @@ static sd_device *handle_scsi(sd_device *parent, char **path, bool *supported_pa + } + + if (strstr(name, "/ata")) +- return handle_scsi_ata(parent, path); ++ return handle_scsi_ata(parent, path, compat_path); + + if (strstr(name, "/vmbus_")) + return handle_scsi_hyperv(parent, path, 37); +@@ -520,6 +536,7 @@ static sd_device *handle_ap(sd_device *parent, char **path) { + static int builtin_path_id(sd_device *dev, int argc, char *argv[], bool test) { + sd_device *parent; + _cleanup_free_ char *path = NULL; ++ _cleanup_free_ char *compat_path = NULL; + bool supported_transport = false; + bool supported_parent = false; + const char *subsystem; +@@ -537,7 +554,7 @@ static int builtin_path_id(sd_device *dev, int argc, char *argv[], bool test) { + } else if (streq(subsys, "scsi_tape")) { + handle_scsi_tape(parent, &path); + } else if (streq(subsys, "scsi")) { +- parent = handle_scsi(parent, &path, &supported_parent); ++ parent = handle_scsi(parent, &path, &compat_path, &supported_parent); + supported_transport = true; + } else if (streq(subsys, "cciss")) { + parent = handle_cciss(parent, &path); +@@ -557,19 +574,27 @@ static int builtin_path_id(sd_device *dev, int argc, char *argv[], bool test) { + } + } else if (streq(subsys, "pci")) { + path_prepend(&path, "pci-%s", sysname); ++ if (compat_path) ++ path_prepend(&compat_path, "pci-%s", sysname); + parent = skip_subsystem(parent, "pci"); + supported_parent = true; + } else if (streq(subsys, "platform")) { + path_prepend(&path, "platform-%s", sysname); ++ if (compat_path) ++ path_prepend(&compat_path, "platform-%s", sysname); + parent = skip_subsystem(parent, "platform"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "acpi")) { + path_prepend(&path, "acpi-%s", sysname); ++ if (compat_path) ++ path_prepend(&compat_path, "acpi-%s", sysname); + parent = skip_subsystem(parent, "acpi"); + supported_parent = true; + } else if (streq(subsys, "xen")) { + path_prepend(&path, "xen-%s", sysname); ++ if (compat_path) ++ path_prepend(&compat_path, "xen-%s", sysname); + parent = skip_subsystem(parent, "xen"); + supported_parent = true; + } else if (streq(subsys, "virtio")) { +@@ -577,16 +602,22 @@ static int builtin_path_id(sd_device *dev, int argc, char *argv[], bool test) { + supported_transport = true; + } else if (streq(subsys, "scm")) { + path_prepend(&path, "scm-%s", sysname); ++ if (compat_path) ++ path_prepend(&compat_path, "scm-%s", sysname); + parent = skip_subsystem(parent, "scm"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "ccw")) { + path_prepend(&path, "ccw-%s", sysname); ++ if (compat_path) ++ path_prepend(&compat_path, "ccw-%s", sysname); + parent = skip_subsystem(parent, "ccw"); + supported_transport = true; + supported_parent = true; + } else if (streq(subsys, "ccwgroup")) { + path_prepend(&path, "ccwgroup-%s", sysname); ++ if (compat_path) ++ path_prepend(&compat_path, "ccwgroup-%s", sysname); + parent = skip_subsystem(parent, "ccwgroup"); + supported_transport = true; + supported_parent = true; +@@ -596,6 +627,8 @@ static int builtin_path_id(sd_device *dev, int argc, char *argv[], bool test) { + supported_parent = true; + } else if (streq(subsys, "iucv")) { + path_prepend(&path, "iucv-%s", sysname); ++ if (compat_path) ++ path_prepend(&compat_path, "iucv-%s", sysname); + parent = skip_subsystem(parent, "iucv"); + supported_transport = true; + supported_parent = true; +@@ -604,6 +637,8 @@ static int builtin_path_id(sd_device *dev, int argc, char *argv[], bool test) { + + if (sd_device_get_sysattr_value(dev, "nsid", &nsid) >= 0) { + path_prepend(&path, "nvme-%s", nsid); ++ if (compat_path) ++ path_prepend(&compat_path, "nvme-%s", nsid); + parent = skip_subsystem(parent, "nvme"); + supported_parent = true; + supported_transport = true; +@@ -671,6 +706,14 @@ static int builtin_path_id(sd_device *dev, int argc, char *argv[], bool test) { + udev_builtin_add_property(dev, test, "ID_PATH_TAG", tag); + } + ++ /* ++ * Compatible link generation for ATA devices ++ * we assign compat_link to the env variable ++ * ID_PATH_ATA_COMPAT ++ */ ++ if (compat_path) ++ udev_builtin_add_property(dev, test, "ID_PATH_ATA_COMPAT", compat_path); ++ + return 0; + } + +-- +2.27.0 + diff --git a/systemd.spec b/systemd.spec index bf1f1d4..d1dd8cf 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 50 +Release: 51 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -154,6 +154,7 @@ Patch0104: backport-0012-CVE-2020-13776-parse-util-make-return-parameter-op Patch0105: backport-0013-CVE-2020-13776-parse-util-rewrite-parse_mode-on-top-of-safe_atou_fu.patch Patch0106: backport-0014-CVE-2020-13776-user-util-be-stricter-in-parse_uid.patch Patch0107: backport-0015-CVE-2020-13776-parse-util-also-parse-integers-prefixed-with-0b-and-.patch +Patch0108: backport-udev-rename-the-persistent-link-for-ATA-devices.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1541,10 +1542,14 @@ fi %exclude /usr/share/man/man3/* %changelog -* Wed Feb 16 2021 yangmingtai - 243-50 +* Fri Feb 26 2022 jiangchuangang - 243-51 +- add backport-udev-rename-the-persistent-link-for-ATA-devices.patch + for the link of ATA devices + +* Wed Feb 16 2022 yangmingtai - 243-50 - fix CVE-2020-13776 -* Tue Jan 18 2021 yangmingtai - 243-49 +* Tue Jan 18 2022 yangmingtai - 243-49 - CVE:fix CVE-2021-3997 * Wed Oct 27 2021 ExtinctFire - 243-48 -- Gitee From 03fc2ce07f58aef9a12c51ee41601a4b0399bc1c Mon Sep 17 00:00:00 2001 From: Yangyang Shen Date: Wed, 27 Apr 2022 21:59:44 +0800 Subject: [PATCH 31/38] fix ConditionDirectoryNotEmpty,ConditionPathIsReadWrite and DirectoryNotEmpty --- ...ectoryNotEmpty-when-it-comes-to-a-No.patch | 26 +++++++++++++++ ...hIsReadWrite-when-path-does-not-exis.patch | 33 +++++++++++++++++++ ...Empty-when-it-comes-to-a-Non-directo.patch | 25 ++++++++++++++ systemd.spec | 8 ++++- 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 backport-fix-ConditionDirectoryNotEmpty-when-it-comes-to-a-No.patch create mode 100644 backport-fix-ConditionPathIsReadWrite-when-path-does-not-exis.patch create mode 100644 backport-fix-DirectoryNotEmpty-when-it-comes-to-a-Non-directo.patch diff --git a/backport-fix-ConditionDirectoryNotEmpty-when-it-comes-to-a-No.patch b/backport-fix-ConditionDirectoryNotEmpty-when-it-comes-to-a-No.patch new file mode 100644 index 0000000..ca67b7d --- /dev/null +++ b/backport-fix-ConditionDirectoryNotEmpty-when-it-comes-to-a-No.patch @@ -0,0 +1,26 @@ +rom 193105f2d0408e2d96265935174b3cf0f100ef2e Mon Sep 17 00:00:00 2001 +From: jiangchuangang +Date: Mon, 29 Nov 2021 22:30:37 +0800 +Subject: [PATCH] fix ConditionDirectoryNotEmpty when it comes to a + Non-directory file + +--- + src/shared/condition.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/condition.c b/src/shared/condition.c +index e5e6c6c..bbe137a 100644 +--- a/src/shared/condition.c ++++ b/src/shared/condition.c +@@ -682,7 +682,7 @@ static int condition_test_directory_not_empty(Condition *c) { + assert(c->type == CONDITION_DIRECTORY_NOT_EMPTY); + + r = dir_is_empty(c->parameter); +- return r <= 0 && r != -ENOENT; ++ return r <= 0 && !IN_SET(r, -ENOENT, -ENOTDIR); + } + + static int condition_test_file_not_empty(Condition *c) { +-- +2.27.0 + diff --git a/backport-fix-ConditionPathIsReadWrite-when-path-does-not-exis.patch b/backport-fix-ConditionPathIsReadWrite-when-path-does-not-exis.patch new file mode 100644 index 0000000..0e9b4f4 --- /dev/null +++ b/backport-fix-ConditionPathIsReadWrite-when-path-does-not-exis.patch @@ -0,0 +1,33 @@ +From 7c4c9948d02ceda903ed4e4deea0d0084612625a Mon Sep 17 00:00:00 2001 +From: jiangchuangang +Date: Tue, 30 Nov 2021 15:25:27 +0800 +Subject: [PATCH] fix ConditionPathIsReadWrite when path does not exist. + +--- + src/shared/condition.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/shared/condition.c b/src/shared/condition.c +index bbe137a..8d460f9 100644 +--- a/src/shared/condition.c ++++ b/src/shared/condition.c +@@ -667,11 +667,15 @@ static int condition_test_path_is_mount_point(Condition *c) { + } + + static int condition_test_path_is_read_write(Condition *c) { ++ int r; ++ + assert(c); + assert(c->parameter); + assert(c->type == CONDITION_PATH_IS_READ_WRITE); + +- return path_is_read_only_fs(c->parameter) <= 0; ++ r = path_is_read_only_fs(c->parameter); ++ ++ return r <= 0 && r != -ENOENT; + } + + static int condition_test_directory_not_empty(Condition *c) { +-- +2.27.0 + diff --git a/backport-fix-DirectoryNotEmpty-when-it-comes-to-a-Non-directo.patch b/backport-fix-DirectoryNotEmpty-when-it-comes-to-a-Non-directo.patch new file mode 100644 index 0000000..3234d28 --- /dev/null +++ b/backport-fix-DirectoryNotEmpty-when-it-comes-to-a-Non-directo.patch @@ -0,0 +1,25 @@ +From 5896a9ebdbe4d38c01390d0a5e82f9fcb4971059 Mon Sep 17 00:00:00 2001 +From: yangmingtai <961612727@qq.com> +Date: Mon, 6 Dec 2021 17:06:13 +0800 +Subject: [PATCH] fix DirectoryNotEmpty when it comes to a Non-directory file + +--- + src/core/path.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/path.c b/src/core/path.c +index 29ec66fd4d..bcd922901b 100644 +--- a/src/core/path.c ++++ b/src/core/path.c +@@ -215,7 +215,7 @@ static bool path_spec_check_good(PathSpec *s, bool initial, bool from_trigger_no + int k; + + k = dir_is_empty(s->path); +- good = !(k == -ENOENT || k > 0); ++ good = !(IN_SET(k, -ENOENT, -ENOTDIR) || k > 0); + break; + } + +-- +2.27.0 + diff --git a/systemd.spec b/systemd.spec index d1dd8cf..bc918ff 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 51 +Release: 52 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -155,6 +155,9 @@ Patch0105: backport-0013-CVE-2020-13776-parse-util-rewrite-parse_mode-on-to Patch0106: backport-0014-CVE-2020-13776-user-util-be-stricter-in-parse_uid.patch Patch0107: backport-0015-CVE-2020-13776-parse-util-also-parse-integers-prefixed-with-0b-and-.patch Patch0108: backport-udev-rename-the-persistent-link-for-ATA-devices.patch +Patch0109: backport-fix-ConditionDirectoryNotEmpty-when-it-comes-to-a-No.patch +Patch0110: backport-fix-ConditionPathIsReadWrite-when-path-does-not-exis.patch +Patch0111: backport-fix-DirectoryNotEmpty-when-it-comes-to-a-Non-directo.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1542,6 +1545,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Wed Apr 27 2022 shenyangyang - 243-52 +- fix ConditionDirectoryNotEmpty,ConditionPathIsReadWrite and DirectoryNotEmpty + * Fri Feb 26 2022 jiangchuangang - 243-51 - add backport-udev-rename-the-persistent-link-for-ATA-devices.patch for the link of ATA devices -- Gitee From 459f31e71b56a142c386427f7f04f7a58229f08e Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Wed, 18 May 2022 17:06:55 +0800 Subject: [PATCH 32/38] remove old device on move event --- ...rt-the-full-db-on-MOVE-events-for-de.patch | 56 ++++ ...ve-.device-unit-corresponding-to-DEV.patch | 59 ++++ ...-reload-events-from-devices-on-every.patch | 68 +++++ ...test-for-device-renaming-issue-16967.patch | 72 +++++ ...tch-OriginalName-with-renamed-interf.patch | 64 +++++ ...o-not-update-return-value-on-failure.patch | 25 ++ backport-udev-drop-unnecessary-checks.patch | 53 ++++ ...D_NET_DRIVER-ID_NET_LINK_FILE-ID_NET.patch | 93 +++++++ ...-link_config_apply-into-small-pieces.patch | 256 ++++++++++++++++++ systemd.spec | 14 +- 10 files changed, 759 insertions(+), 1 deletion(-) create mode 100644 backport-Revert-udev-import-the-full-db-on-MOVE-events-for-de.patch create mode 100644 backport-core-device-remove-.device-unit-corresponding-to-DEV.patch create mode 100644 backport-device-propagate-reload-events-from-devices-on-every.patch create mode 100644 backport-test-add-test-for-device-renaming-issue-16967.patch create mode 100644 backport-udev-allow-to-match-OriginalName-with-renamed-interf.patch create mode 100644 backport-udev-do-not-update-return-value-on-failure.patch create mode 100644 backport-udev-drop-unnecessary-checks.patch create mode 100644 backport-udev-re-assign-ID_NET_DRIVER-ID_NET_LINK_FILE-ID_NET.patch create mode 100644 backport-udev-split-link_config_apply-into-small-pieces.patch diff --git a/backport-Revert-udev-import-the-full-db-on-MOVE-events-for-de.patch b/backport-Revert-udev-import-the-full-db-on-MOVE-events-for-de.patch new file mode 100644 index 0000000..9d8d692 --- /dev/null +++ b/backport-Revert-udev-import-the-full-db-on-MOVE-events-for-de.patch @@ -0,0 +1,56 @@ +From 51d9aec0ff333ff554079da4babf6dbfa9837096 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 14 Sep 2020 15:20:04 +0900 +Subject: [PATCH] Revert "udev: import the full db on MOVE events for devices + without dev_t" + +This reverts commit b081b27e1433cdc7ac72b25ae8b4db887d79187f. + +If a network interface get a 'move' event, then previously SYSTEMD_ALIAS= +property still contains an old alias, and the old alias .device unit +will not be removed. + +This makes all properties cleared on 'move' event, and then old alias +.device unit will be removed by pid1. + +Fixes #16967. + +Reference:https://github.com/systemd/systemd/commit/51d9aec0ff333ff554079da4babf6dbfa9837096 +Conflict:context adaptation +--- + src/udev/udev-event.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c +index 7c78b4c680..ede8e3aef7 100644 +--- a/src/udev/udev-event.c ++++ b/src/udev/udev-event.c +@@ -940,16 +940,9 @@ static void event_execute_rules_on_remove( + (void) udev_node_remove(dev); + } + +-static int udev_event_on_move(UdevEvent *event) { +- sd_device *dev = event->dev; ++static int udev_event_on_move(sd_device *dev) { + int r; + +- if (sd_device_get_devnum(dev, NULL) < 0) { +- r = device_copy_properties(dev, event->dev_db_clone); +- if (r < 0) +- log_device_debug_errno(dev, r, "Failed to copy properties from cloned sd_device object, ignoring: %m"); +- } +- + /* Drop previously added property */ + r = device_add_property(dev, "ID_RENAMING", NULL); + if (r < 0) +@@ -1017,7 +1010,7 @@ int udev_event_execute_rules(UdevEvent *event, + (void) udev_watch_end(event->dev_db_clone); + + if (action == DEVICE_ACTION_MOVE) { +- r = udev_event_on_move(event); ++ r = udev_event_on_move(event->dev); + if (r < 0) + return r; + } +-- +2.27.0 diff --git a/backport-core-device-remove-.device-unit-corresponding-to-DEV.patch b/backport-core-device-remove-.device-unit-corresponding-to-DEV.patch new file mode 100644 index 0000000..7dd53b3 --- /dev/null +++ b/backport-core-device-remove-.device-unit-corresponding-to-DEV.patch @@ -0,0 +1,59 @@ +From 87bc687a8cbadbc9eb3c77fba41a6caf3219cf7c Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 7 Sep 2020 13:43:56 +0900 +Subject: [PATCH] core/device: remove .device unit corresponding to DEVPATH_OLD + +Partially fixes #16967. + +Reference:https://github.com/systemd/systemd/commit/87bc687a8cbadbc9eb3c77fba41a6caf3219cf7c +Conflict:context adaptation +--- + src/core/device.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/src/core/device.c b/src/core/device.c +index 31aa3341c2..d242d15e36 100644 +--- a/src/core/device.c ++++ b/src/core/device.c +@@ -897,6 +897,29 @@ static void device_propagate_reload_by_sysfs(Manager *m, const char *sysfs) { + } + } + ++static int device_remove_old(Manager *m, sd_device *dev) { ++ _cleanup_free_ char *syspath_old = NULL, *e = NULL; ++ const char *devpath_old; ++ int r; ++ ++ r = sd_device_get_property_value(dev, "DEVPATH_OLD", &devpath_old); ++ if (r < 0) { ++ log_device_debug_errno(dev, r, "Failed to get DEVPATH_OLD= property on 'move' uevent, ignoring: %m"); ++ return 0; ++ } ++ ++ syspath_old = path_join("/sys", devpath_old); ++ if (!syspath_old) ++ return log_oom(); ++ ++ r = unit_name_from_path(syspath_old, ".device", &e); ++ if (r < 0) ++ return log_device_error_errno(dev, r, "Failed to generate unit name from old device path: %m"); ++ ++ device_update_found_by_sysfs(m, syspath_old, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP); ++ return 0; ++} ++ + static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void *userdata) { + Manager *m = userdata; + DeviceAction action; +@@ -921,6 +944,9 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void * + if (!IN_SET(action, DEVICE_ACTION_ADD, DEVICE_ACTION_REMOVE, DEVICE_ACTION_MOVE)) + device_propagate_reload_by_sysfs(m, sysfs); + ++ if (action == DEVICE_ACTION_MOVE) ++ (void) device_remove_old(m, dev); ++ + /* A change event can signal that a device is becoming ready, in particular if the device is using + * the SYSTEMD_READY logic in udev so we need to reach the else block of the following if, even for + * change events */ +-- +2.27.0 diff --git a/backport-device-propagate-reload-events-from-devices-on-every.patch b/backport-device-propagate-reload-events-from-devices-on-every.patch new file mode 100644 index 0000000..0fbcbfe --- /dev/null +++ b/backport-device-propagate-reload-events-from-devices-on-every.patch @@ -0,0 +1,68 @@ +From ae6ad21e0b9a179e3408c12297783870cf13a00a Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 12 Dec 2018 21:31:12 +0100 +Subject: [PATCH] device: propagate reload events from devices on everything + but "add", and "remove" + +Any uevent other then the initial and the last uevent we see for a +device (which is "add" and "remove") should result in a reload being +triggered, including "bind" and "unbind". Hence, let's fix up the check. + +("move" is kinda a combined "remove" + "add", hence cover that too) + +Reference:https://github.com/systemd/systemd/commit/ae6ad21e0b9a179e3408c12297783870cf13a00a +Conflict: NA +--- + src/core/device.c | 22 +++++++++------------- + 1 file changed, 9 insertions(+), 13 deletions(-) + +diff --git a/src/core/device.c b/src/core/device.c +index 50d55289fa..5b8134159a 100644 +--- a/src/core/device.c ++++ b/src/core/device.c +@@ -915,20 +915,19 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void * + return 0; + } + +- if (action == DEVICE_ACTION_CHANGE) ++ if (!IN_SET(action, DEVICE_ACTION_ADD, DEVICE_ACTION_REMOVE, DEVICE_ACTION_MOVE)) + device_propagate_reload_by_sysfs(m, sysfs); + +- /* A change event can signal that a device is becoming ready, in particular if +- * the device is using the SYSTEMD_READY logic in udev +- * so we need to reach the else block of the following if, even for change events */ ++ /* A change event can signal that a device is becoming ready, in particular if the device is using ++ * the SYSTEMD_READY logic in udev so we need to reach the else block of the following if, even for ++ * change events */ + if (action == DEVICE_ACTION_REMOVE) { + r = swap_process_device_remove(m, dev); + if (r < 0) + log_device_warning_errno(dev, r, "Failed to process swap device remove event, ignoring: %m"); + +- /* If we get notified that a device was removed by +- * udev, then it's completely gone, hence unset all +- * found bits */ ++ /* If we get notified that a device was removed by udev, then it's completely gone, hence ++ * unset all found bits */ + device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV|DEVICE_FOUND_MOUNT|DEVICE_FOUND_SWAP); + + } else if (device_is_ready(dev)) { +@@ -944,13 +943,10 @@ static int device_dispatch_io(sd_device_monitor *monitor, sd_device *dev, void * + /* The device is found now, set the udev found bit */ + device_update_found_by_sysfs(m, sysfs, DEVICE_FOUND_UDEV, DEVICE_FOUND_UDEV); + +- } else { +- /* The device is nominally around, but not ready for +- * us. Hence unset the udev bit, but leave the rest +- * around. */ +- ++ } else ++ /* The device is nominally around, but not ready for us. Hence unset the udev bit, but leave ++ * the rest around. */ + device_update_found_by_sysfs(m, sysfs, 0, DEVICE_FOUND_UDEV); +- } + + return 0; + } +-- +2.27.0 diff --git a/backport-test-add-test-for-device-renaming-issue-16967.patch b/backport-test-add-test-for-device-renaming-issue-16967.patch new file mode 100644 index 0000000..5171270 --- /dev/null +++ b/backport-test-add-test-for-device-renaming-issue-16967.patch @@ -0,0 +1,72 @@ +From efdaeb88f02aeb406068d45ae7687abf1bd4a8a3 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 14 Sep 2020 15:44:30 +0900 +Subject: [PATCH] test: add test for device renaming issue #16967 + +Reference:https://github.com/systemd/systemd/commit/efdaeb88f02aeb406068d45ae7687abf1bd4a8a3 +Conflict:context adaptation +--- + test/TEST-29-UDEV-ID_RENAMING/test.sh | 15 +++++++++++++++ + test/units/testsuite-29.sh | 16 ++++++++++++++++ + 2 files changed, 31 insertions(+) + +diff --git a/test/TEST-29-UDEV-ID_RENAMING/test.sh b/test/TEST-29-UDEV-ID_RENAMING/test.sh +index 4feafc04d7..ddf6db9735 100755 +--- a/test/TEST-29-UDEV-ID_RENAMING/test.sh ++++ b/test/TEST-29-UDEV-ID_RENAMING/test.sh +@@ -1,11 +1,26 @@ + #!/bin/bash + set -e + TEST_DESCRIPTION="UDEV ID_RENAMING property" ++IMAGE_NAME="udev-id-renaming" + TEST_NO_NSPAWN=1 + + . $TEST_BASE_DIR/test-functions + QEMU_TIMEOUT=300 + ++test_create_image() { ++ create_empty_image_rootdir ++ ++ # Create what will eventually be our root filesystem onto an overlay ++ ( ++ LOG_LEVEL=5 ++ setup_basic_environment ++ mask_supporting_services ++ ++ instmods dummy ++ generate_module_dependencies ++ ) ++} ++ + test_setup() { + create_empty_image_rootdir + +diff --git a/test/TEST-29-UDEV-ID_RENAMING/testsuite.sh b/test/TEST-29-UDEV-ID_RENAMING/testsuite.sh +index eb9b2ff..b477d16 100755 +--- a/test/TEST-29-UDEV-ID_RENAMING/testsuite.sh ++++ b/test/TEST-29-UDEV-ID_RENAMING/testsuite.sh +@@ -38,6 +38,22 @@ STATE=$(systemctl show --property=ActiveState --value sys-devices-virtual-net-lo + rm -f /run/udev/rules.d/50-testsuite.rules + udevadm control --reload --timeout=600 + ++# test for issue #16967 ++ ++ip link add hoge type dummy ++udevadm info --wait-for-initialization=10s /sys/devices/virtual/net/hoge ++sleep 1 ++if ! systemctl status sys-devices-virtual-net-hoge.device; then exit 1; fi ++if ! systemctl status sys-subsystem-net-devices-hoge.device; then exit 1; fi ++ ++ip link set hoge name foobar ++udevadm info --wait-for-initialization=10s /sys/devices/virtual/net/foobar ++sleep 1 ++if systemctl status sys-devices-virtual-net-hoge.device; then exit 1; fi ++if systemctl status sys-subsystem-net-devices-hoge.device; then exit 1; fi ++if ! systemctl status sys-devices-virtual-net-foobar.device; then exit 1; fi ++if ! systemctl status sys-subsystem-net-devices-foobar.device; then exit 1; fi ++ + echo OK > /testok + + exit 0 +-- +2.23.0 diff --git a/backport-udev-allow-to-match-OriginalName-with-renamed-interf.patch b/backport-udev-allow-to-match-OriginalName-with-renamed-interf.patch new file mode 100644 index 0000000..3108e0f --- /dev/null +++ b/backport-udev-allow-to-match-OriginalName-with-renamed-interf.patch @@ -0,0 +1,64 @@ +From f57673025680fdca0c200e7ca7a37fed943d2b49 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 14 Sep 2020 18:28:29 +0900 +Subject: [PATCH] udev: allow to match OriginalName= with renamed interface + name + +Reference:https://github.com/systemd/systemd/commit/f57673025680fdca0c200e7ca7a37fed943d2b49 +Conflict:context adaptation +--- + src/udev/net/link-config.c | 27 ++++++++------------------- + 1 file changed, 8 insertions(+), 19 deletions(-) + +diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c +index 5c871b6717..cb1db3b52b 100644 +--- a/src/udev/net/link-config.c ++++ b/src/udev/net/link-config.c +@@ -232,6 +232,7 @@ bool link_config_should_reload(link_config_ctx *ctx) { + } + + int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) { ++ unsigned name_assign_type = NET_NAME_UNKNOWN; + link_config *link; + + assert(ctx); +@@ -238,30 +238,17 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) + assert(device); + assert(ret); + ++ (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type); ++ + LIST_FOREACH(links, link, ctx->links) { + if (net_match_config(link->match_mac, link->match_path, link->match_driver, + link->match_type, link->match_name, link->match_property, + device, NULL, NULL)) { +- if (link->match_name && !strv_contains(link->match_name, "*")) { +- unsigned name_assign_type = NET_NAME_UNKNOWN; +- +- (void) link_unsigned_attribute(device, "name_assign_type", &name_assign_type); +- +- if (name_assign_type == NET_NAME_ENUM) { +- log_device_warning(device, "Config file %s applies to device based on potentially unpredictable interface name", +- link->filename); +- *ret = link; +- +- return 0; +- } else if (name_assign_type == NET_NAME_RENAMED) { +- log_device_warning(device, "Config file %s matches device based on renamed interface name, ignoring", +- link->filename); +- +- continue; +- } +- } +- +- log_device_debug(device, "Config file %s is applied", link->filename); ++ if (link->match_name && !strv_contains(link->match_name, "*") && name_assign_type == NET_NAME_ENUM) ++ log_device_warning(device, "Config file %s is applied to device based on potentially unpredictable interface name.", ++ link->filename); ++ else ++ log_device_debug(device, "Config file %s is applied", link->filename); + + *ret = link; + return 0; +-- +2.23.0 diff --git a/backport-udev-do-not-update-return-value-on-failure.patch b/backport-udev-do-not-update-return-value-on-failure.patch new file mode 100644 index 0000000..5e6a897 --- /dev/null +++ b/backport-udev-do-not-update-return-value-on-failure.patch @@ -0,0 +1,25 @@ +From 7f67b01e3f81029a64c2bb46e2fb57fae6c9d505 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 14 Sep 2020 18:30:58 +0900 +Subject: [PATCH] udev: do not update return value on failure + +Reference:https://github.com/systemd/systemd/pull/16968/commits/7f67b01e3f81029a64c2bb46e2fb57fae6c9d505 +Conflict:NA +--- + src/udev/net/link-config.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c +index cb1db3b52b..c23c2bdd20 100644 +--- a/src/udev/net/link-config.c ++++ b/src/udev/net/link-config.c +@@ -287,7 +287,6 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) + } + } + +- *ret = NULL; + return -ENOENT; + } + +-- +2.27.0 diff --git a/backport-udev-drop-unnecessary-checks.patch b/backport-udev-drop-unnecessary-checks.patch new file mode 100644 index 0000000..ac5ffe9 --- /dev/null +++ b/backport-udev-drop-unnecessary-checks.patch @@ -0,0 +1,53 @@ +From 28266c446a64597c55f68e33c086da7465541a21 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 21 Jul 2020 11:39:44 +0900 +Subject: [PATCH] udev: drop unnecessary checks + +Also, drop one unnecessary sd_device_unref(), as dev_db_clone will be +unref()ed in udev_event_free(). +--- + src/udev/udev-event.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c +index 2ae76eb51a43..e1c2baf7f212 100644 +--- a/src/udev/udev-event.c ++++ b/src/udev/udev-event.c +@@ -881,8 +881,7 @@ static int update_devnode(UdevEvent *event) { + return log_device_error_errno(dev, r, "Failed to get devnum: %m"); + + /* remove/update possible left-over symlinks from old database entry */ +- if (event->dev_db_clone) +- (void) udev_node_update_old_links(dev, event->dev_db_clone); ++ (void) udev_node_update_old_links(dev, event->dev_db_clone); + + if (!uid_is_valid(event->uid)) { + r = device_get_devnode_uid(dev, &event->uid); +@@ -945,8 +944,7 @@ static int udev_event_on_move(UdevEvent *event) { + sd_device *dev = event->dev; + int r; + +- if (event->dev_db_clone && +- sd_device_get_devnum(dev, NULL) < 0) { ++ if (sd_device_get_devnum(dev, NULL) < 0) { + r = device_copy_properties(dev, event->dev_db_clone); + if (r < 0) + log_device_debug_errno(dev, r, "Failed to copy properties from cloned sd_device object, ignoring: %m"); +@@ -992,7 +990,7 @@ int udev_event_execute_rules(UdevEvent *event, + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to clone sd_device object: %m"); + +- if (event->dev_db_clone && sd_device_get_devnum(dev, NULL) >= 0) ++ if (sd_device_get_devnum(dev, NULL) >= 0) + /* Disable watch during event processing. */ + (void) udev_watch_end(event->dev_db_clone); + +@@ -1030,8 +1028,6 @@ int udev_event_execute_rules(UdevEvent *event, + + device_set_is_initialized(dev); + +- event->dev_db_clone = sd_device_unref(event->dev_db_clone); +- + return 0; + } + diff --git a/backport-udev-re-assign-ID_NET_DRIVER-ID_NET_LINK_FILE-ID_NET.patch b/backport-udev-re-assign-ID_NET_DRIVER-ID_NET_LINK_FILE-ID_NET.patch new file mode 100644 index 0000000..d54ccab --- /dev/null +++ b/backport-udev-re-assign-ID_NET_DRIVER-ID_NET_LINK_FILE-ID_NET.patch @@ -0,0 +1,93 @@ +From e0e789c1e97e2cdf1cafe0c6b7d7e43fa054f151 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 14 Sep 2020 15:21:04 +0900 +Subject: [PATCH] udev: re-assign ID_NET_DRIVER=, ID_NET_LINK_FILE=, + ID_NET_NAME= properties on non-'add' uevent + +Previous commit makes drop ID_NET_DRIVER=, ID_NET_LINK_FILE=, and +ID_NET_NAME= properties for network interfaces on 'move' uevent. +ID_NET_DRIVER= and ID_NET_LINK_FILE= properties are used by networkctl. +ID_NET_NAME= may be used by end-user rules or programs. So, let's +re-assign them on 'move' uevent. (Note that strictly speaking, this +makes them re-assigned on all but 'remove' uevent.) + +Reference:https://github.com/systemd/systemd/commit/e0e789c1e97e2cdf1cafe0c6b7d7e43fa054f151 +Conflict:context adaptation +--- +diff --git a/rules/80-net-setup-link.rules b/rules/80-net-setup-link.rules +index 6e411a9..bafc3fb 100644 +--- a/rules/80-net-setup-link.rules ++++ b/rules/80-net-setup-link.rules +@@ -4,7 +4,7 @@ SUBSYSTEM!="net", GOTO="net_setup_link_end" + + IMPORT{builtin}="path_id" + +-ACTION!="add", GOTO="net_setup_link_end" ++ACTION=="remove", GOTO="net_setup_link_end" + + IMPORT{builtin}="net_setup_link" + +diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c +index 5fa439b..9c13906 100644 +--- a/src/udev/net/link-config.c ++++ b/src/udev/net/link-config.c +@@ -10,6 +10,7 @@ + #include "conf-files.h" + #include "conf-parser.h" + #include "def.h" ++#include "device-private.h" + #include "device-util.h" + #include "ethtool-util.h" + #include "fd-util.h" +@@ -480,6 +481,7 @@ no_rename: + + int link_config_apply(link_config_ctx *ctx, const link_config *config, sd_device *device, const char **ret_name) { + const char *new_name; ++ DeviceAction a; + int r; + + assert(ctx); +@@ -487,6 +489,20 @@ int link_config_apply(link_config_ctx *ctx, const link_config *config, sd_device + assert(device); + assert(ret_name); + ++ r = device_get_action(device, &a); ++ if (r < 0) ++ return log_device_error_errno(device, r, "Failed to get ACTION= property: %m"); ++ ++ if (!IN_SET(a, DEVICE_ACTION_ADD, DEVICE_ACTION_BIND, DEVICE_ACTION_MOVE)) { ++ log_device_debug(device, "Skipping to apply .link settings on '%s' uevent.", device_action_to_string(a)); ++ ++ r = sd_device_get_sysname(device, ret_name); ++ if (r < 0) ++ return log_device_error_errno(device, r, "Failed to get sysname: %m"); ++ ++ return 0; ++ } ++ + r = link_config_apply_ethtool_settings(&ctx->ethtool_fd, config, device); + if (r < 0) + return r; +@@ -495,9 +511,17 @@ int link_config_apply(link_config_ctx *ctx, const link_config *config, sd_device + if (r < 0) + return r; + +- r = link_config_generate_new_name(ctx, config, device, &new_name); +- if (r < 0) +- return r; ++ if (a == DEVICE_ACTION_MOVE) { ++ log_device_debug(device, "Skipping to apply Name= and NamePolicy= on '%s' uevent.", device_action_to_string(a)); ++ ++ r = sd_device_get_sysname(device, &new_name); ++ if (r < 0) ++ return log_device_error_errno(device, r, "Failed to get sysname: %m"); ++ } else { ++ r = link_config_generate_new_name(ctx, config, device, &new_name); ++ if (r < 0) ++ return r; ++ } + + *ret_name = new_name; + +-- +2.27.0 diff --git a/backport-udev-split-link_config_apply-into-small-pieces.patch b/backport-udev-split-link_config_apply-into-small-pieces.patch new file mode 100644 index 0000000..fa44793 --- /dev/null +++ b/backport-udev-split-link_config_apply-into-small-pieces.patch @@ -0,0 +1,256 @@ +From 2e17fed5f3000175f3ea67ece47fb7fd6ca41efa Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 15 Sep 2020 10:41:38 +0900 +Subject: [PATCH] udev: split link_config_apply() into small pieces + +Reference:https://github.com/systemd/systemd/commit/2e17fed5f3000175f3ea67ece47fb7fd6ca41efa +Conflict:context adaptation +--- + src/udev/net/link-config.c | 154 ++++++++++++++++++++++++------------- + src/udev/net/link-config.h | 4 +- + 2 files changed, 104 insertions(+), 54 deletions(-) + +diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c +index 6a414db..8453785 100644 +--- a/src/udev/net/link-config.c ++++ b/src/udev/net/link-config.c +@@ -320,67 +320,94 @@ static int get_mac(sd_device *device, MACAddressPolicy policy, struct ether_addr + return 1; + } + +-int link_config_apply(link_config_ctx *ctx, link_config *config, +- sd_device *device, const char **name) { +- struct ether_addr generated_mac; +- struct ether_addr *mac = NULL; +- const char *new_name = NULL; +- const char *old_name; +- unsigned speed, name_type = NET_NAME_UNKNOWN; +- NamePolicy policy; +- int r, ifindex; +- +- assert(ctx); ++static int link_config_apply_ethtool_settings(int *ethtool_fd, const link_config *config, sd_device *device) { ++ const char *name; ++ int r; ++ ++ assert(ethtool_fd); + assert(config); + assert(device); +- assert(name); + +- r = sd_device_get_sysname(device, &old_name); ++ r = sd_device_get_sysname(device, &name); + if (r < 0) +- return r; ++ return log_device_error_errno(device, r, "Failed to get sysname: %m"); + +- r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, ++ r = ethtool_set_glinksettings(ethtool_fd, name, + config->autonegotiation, config->advertise, + config->speed, config->duplex, config->port); +- if (r < 0) { + ++ if (r < 0) { + if (config->port != _NET_DEV_PORT_INVALID) +- log_warning_errno(r, "Could not set port (%s) of %s: %m", port_to_string(config->port), old_name); ++ log_device_warning_errno(device, r, "Could not set port '%s', ignoring: %m", port_to_string(config->port)); + + if (!eqzero(config->advertise)) +- log_warning_errno(r, "Could not set advertise mode: %m"); /* TODO: include modes in the log message. */ ++ log_device_warning_errno(device, r, "Could not set advertise mode, ignoring: %m"); /* TODO: include modes in the log message. */ + + if (config->speed) { +- speed = DIV_ROUND_UP(config->speed, 1000000); ++ unsigned speed = DIV_ROUND_UP(config->speed, 1000000); + if (r == -EOPNOTSUPP) { +- r = ethtool_set_speed(&ctx->ethtool_fd, old_name, speed, config->duplex); ++ r = ethtool_set_speed(ethtool_fd, name, speed, config->duplex); + if (r < 0) +- log_warning_errno(r, "Could not set speed of %s to %u Mbps: %m", old_name, speed); ++ log_device_warning_errno(device, r, "Could not set speed to %uMbps, ignoring: %m", speed); + } + } + +- if (config->duplex !=_DUP_INVALID) +- log_warning_errno(r, "Could not set duplex of %s to (%s): %m", old_name, duplex_to_string(config->duplex)); ++ if (config->duplex != _DUP_INVALID) ++ log_device_warning_errno(device, r, "Could not set duplex to %s, ignoring: %m", duplex_to_string(config->duplex)); + } + +- r = ethtool_set_wol(&ctx->ethtool_fd, old_name, config->wol); ++ r = ethtool_set_wol(ethtool_fd, name, config->wol); + if (r < 0) +- log_warning_errno(r, "Could not set WakeOnLan of %s to %s: %m", +- old_name, wol_to_string(config->wol)); ++ log_device_warning_errno(device, r, "Could not set WakeOnLan to %s, ignoring: %m", wol_to_string(config->wol)); + +- r = ethtool_set_features(&ctx->ethtool_fd, old_name, config->features); ++ r = ethtool_set_features(ethtool_fd, name, config->features); + if (r < 0) +- log_warning_errno(r, "Could not set offload features of %s: %m", old_name); ++ log_device_warning_errno(device, r, "Could not set offload features, ignoring: %m"); + + if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) { +- r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels); ++ r = ethtool_set_channels(ethtool_fd, name, &config->channels); + if (r < 0) +- log_warning_errno(r, "Could not set channels of %s: %m", old_name); ++ log_device_warning_errno(device, r, "Could not set channels, ignoring: %m"); + } + ++ return 0; ++} ++ ++static int link_config_apply_rtnl_settings(sd_netlink **rtnl, const link_config *config, sd_device *device) { ++ struct ether_addr generated_mac, *mac = NULL; ++ int ifindex, r; ++ ++ assert(rtnl); ++ assert(config); ++ assert(device); ++ + r = sd_device_get_ifindex(device, &ifindex); + if (r < 0) +- return log_device_warning_errno(device, r, "Could not find ifindex: %m"); ++ return log_device_error_errno(device, r, "Could not find ifindex: %m"); ++ ++ if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM)) { ++ if (get_mac(device, config->mac_address_policy, &generated_mac) > 0) ++ mac = &generated_mac; ++ } else ++ mac = config->mac; ++ ++ r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, config->mtu); ++ if (r < 0) ++ log_device_warning_errno(device, r, "Could not set Alias=, MACAddress= or MTU=, ignoring: %m"); ++ ++ return 0; ++} ++ ++static int link_config_generate_new_name(const link_config_ctx *ctx, const link_config *config, sd_device *device, const char **ret_name) { ++ unsigned name_type = NET_NAME_UNKNOWN; ++ const char *new_name = NULL; ++ NamePolicy policy; ++ int r; ++ ++ assert(ctx); ++ assert(config); ++ assert(device); ++ assert(ret_name); + + (void) link_unsigned_attribute(device, "name_assign_type", &name_type); + +@@ -390,15 +417,13 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, + goto no_rename; + } + +- if (ctx->enable_name_policy && config->name_policy) +- for (NamePolicy *p = config->name_policy; !new_name && *p != _NAMEPOLICY_INVALID; p++) { ++ if (ctx->enable_name_policy && config->name_policy) ++ for (NamePolicy *p = config->name_policy; *p != _NAMEPOLICY_INVALID; p++) { + policy = *p; +- + switch (policy) { + case NAMEPOLICY_KERNEL: + if (name_type != NET_NAME_PREDICTABLE) + continue; +- + /* The kernel claims to have given a predictable name, keep it. */ + log_device_debug(device, "Policy *%s*: keeping predictable kernel name", + name_policy_to_string(policy)); +@@ -406,7 +431,6 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, + case NAMEPOLICY_KEEP: + if (!IN_SET(name_type, NET_NAME_USER, NET_NAME_RENAMED)) + continue; +- + log_device_debug(device, "Policy *%s*: keeping existing userspace name", + name_policy_to_string(policy)); + goto no_rename; +@@ -428,28 +452,54 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, + default: + assert_not_reached("invalid policy"); + } +- } ++ if (ifname_valid(new_name)) ++ break; ++ } + +- if (new_name) ++ if (new_name) { + log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name); +- else if (config->name) { +- new_name = config->name; +- log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", new_name); +- } else +- log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming."); +- no_rename: ++ *ret_name = new_name; ++ return 0; ++ } + +- if (IN_SET(config->mac_address_policy, MAC_ADDRESS_POLICY_PERSISTENT, MAC_ADDRESS_POLICY_RANDOM)) { +- if (get_mac(device, config->mac_address_policy, &generated_mac) > 0) +- mac = &generated_mac; +- } else +- mac = config->mac; ++ if (config->name) { ++ log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", config->name); ++ *ret_name = config->name; ++ return 0; ++ } ++ ++ log_device_debug(device, "Policies didn't yield a name and Name= is not given, not renaming."); + +- r = rtnl_set_link_properties(&ctx->rtnl, ifindex, config->alias, mac, config->mtu); ++no_rename: ++ r = sd_device_get_sysname(device, ret_name); ++ if (r < 0) ++ return log_device_error_errno(device, r, "Failed to get sysname: %m"); ++ ++ return 0; ++} ++ ++int link_config_apply(link_config_ctx *ctx, const link_config *config, sd_device *device, const char **ret_name) { ++ const char *new_name; ++ int r; ++ ++ assert(ctx); ++ assert(config); ++ assert(device); ++ assert(ret_name); ++ ++ r = link_config_apply_ethtool_settings(&ctx->ethtool_fd, config, device); ++ if (r < 0) ++ return r; ++ ++ r = link_config_apply_rtnl_settings(&ctx->rtnl, config, device); + if (r < 0) +- return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name); ++ return r; ++ ++ r = link_config_generate_new_name(ctx, config, device, &new_name); ++ if (r < 0) ++ return r; + +- *name = new_name; ++ *ret_name = new_name; + + return 0; + } +diff --git a/src/udev/net/link-config.h b/src/udev/net/link-config.h +index 26666ad..4922be6 100644 +--- a/src/udev/net/link-config.h ++++ b/src/udev/net/link-config.h +@@ -70,8 +70,8 @@ int link_load_one(link_config_ctx *ctx, const char *filename); + int link_config_load(link_config_ctx *ctx); + bool link_config_should_reload(link_config_ctx *ctx); + +-int link_config_get(link_config_ctx *ctx, sd_device *device, struct link_config **ret); +-int link_config_apply(link_config_ctx *ctx, struct link_config *config, sd_device *device, const char **name); ++int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret); ++int link_config_apply(link_config_ctx *ctx, const link_config *config, sd_device *device, const char **ret_name); + int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret); + + const char *name_policy_to_string(NamePolicy p) _const_; +-- +2.27.0 diff --git a/systemd.spec b/systemd.spec index bc918ff..fee5964 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 52 +Release: 53 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -158,6 +158,15 @@ Patch0108: backport-udev-rename-the-persistent-link-for-ATA-devices.patch Patch0109: backport-fix-ConditionDirectoryNotEmpty-when-it-comes-to-a-No.patch Patch0110: backport-fix-ConditionPathIsReadWrite-when-path-does-not-exis.patch Patch0111: backport-fix-DirectoryNotEmpty-when-it-comes-to-a-Non-directo.patch +Patch0112: backport-udev-drop-unnecessary-checks.patch +Patch0113: backport-device-propagate-reload-events-from-devices-on-every.patch +Patch0114: backport-core-device-remove-.device-unit-corresponding-to-DEV.patch +Patch0115: backport-udev-split-link_config_apply-into-small-pieces.patch +Patch0116: backport-Revert-udev-import-the-full-db-on-MOVE-events-for-de.patch +Patch0117: backport-udev-re-assign-ID_NET_DRIVER-ID_NET_LINK_FILE-ID_NET.patch +Patch0118: backport-udev-allow-to-match-OriginalName-with-renamed-interf.patch +Patch0119: backport-udev-do-not-update-return-value-on-failure.patch +Patch0120: backport-test-add-test-for-device-renaming-issue-16967.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1545,6 +1554,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Thu May 26 2022 yangmingtai - 243-53 +- remove old device on move event + * Wed Apr 27 2022 shenyangyang - 243-52 - fix ConditionDirectoryNotEmpty,ConditionPathIsReadWrite and DirectoryNotEmpty -- Gitee From 982657a516cd3e8de5254930229143417c9de53d Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Wed, 31 Aug 2022 19:40:20 +0800 Subject: [PATCH 33/38] divided some feature into subpackage --- systemd.spec | 228 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 167 insertions(+), 61 deletions(-) diff --git a/systemd.spec b/systemd.spec index fee5964..441857e 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 53 +Release: 54 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -197,6 +197,10 @@ BuildRequires: gnu-efi gnu-efi-devel BuildRequires: valgrind-devel, util-linux Requires: %{name}-libs = %{version}-%{release} +Requires: %{name}-networkd = %{version}-%{release} +Requires: %{name}-timesyncd = %{version}-%{release} +Requires: %{name}-pam = %{version}-%{release} +Requires: %{name}-resolved = %{version}-%{release} Requires(post): coreutils Requires(post): sed Requires(post): acl @@ -219,9 +223,7 @@ Provides: systemd-sysv = 206 Conflicts: initscripts < 9.56.1 Recommends: %{name}-help -Provides: %{name}-pam Provides: %{name}-rpm-config -Obsoletes: %{name}-pam Obsoletes: %{name}-rpm-config %description @@ -286,6 +288,7 @@ machines and in virtual machines, but not in containers. %package container Summary: Tools for containers and VMs Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: %{name}-nspawn = %{version}-%{release} Obsoletes: %{name} < 229-5 License: LGPLv2+ @@ -324,6 +327,69 @@ systemd-udev-compat is a set of udev rules which conflict with NetworkManager. If users choose to use the network-scripts to manager the network, the package can be used to do somethings when down or up nics or disk. +%package resolved +Summary: Network Name Resolution manager +License: LGPLv2+ +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires(post): systemd +Requires(preun):systemd +Requires(postun):systemd +Requires(pre): /usr/bin/getent + +%description resolved +systemd-resolve is a system service that provides network name resolution to +local applications. It implements a caching and validating DNS/DNSSEC stub +resolver, as well as an LLMNR and MulticastDNS resolver and responder. + +%package nspawn +Summary: Spawn a command or OS in a light-weight container +License: LGPLv2+ +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description nspawn +systemd-nspawn may be used to run a command or OS in a light-weight namespace +container. In many ways it is similar to chroot, but more powerful since it +fully virtualizes the file system hierarchy, as well as the process tree, the +various IPC subsystems and the host and domain name. + +%package networkd +Summary: System daemon that manages network configurations +Requires: %{name}%{?_isa} = %{version}-%{release} +License: LGPLv2+ +Requires(pre): /usr/bin/getent +Requires(post): systemd +Requires(preun):systemd +Requires(postun):systemd + +%description networkd +systemd-networkd is a system service that manages networks. It detects +and configures network devices as they appear, as well as creating virtual +network devices. + +%package timesyncd +Summary: Network Time Synchronization +License: LGPLv2+ +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires(post): systemd +Requires(preun):systemd +Requires(postun):systemd +Requires(pre): /usr/bin/getent + +%description timesyncd +systemd-timesyncd is a system service that may be used to synchronize +the local system clock with a remote Network Time Protocol (NTP) server. +It also saves the local time to disk every time the clock has been +synchronized and uses this to possibly advance the system realtime clock +on subsequent reboots to ensure it (roughly) monotonically advances even +if the system lacks a battery-buffered RTC chip. + +%package pam +Summary: systemd PAM module +Requires: %{name} = %{version}-%{release} + +%description pam +Systemd PAM module registers the session with systemd-logind. + %package_help %prep @@ -619,13 +685,16 @@ getent group systemd-journal &>/dev/null || groupadd -r -g 190 systemd-journal 2 getent group systemd-coredump &>/dev/null || groupadd -r systemd-coredump 2>&1 || : getent passwd systemd-coredump &>/dev/null || useradd -r -l -g systemd-coredump -d / -s /sbin/nologin -c "systemd Core Dumper" systemd-coredump &>/dev/null || : -getent group systemd-network &>/dev/null || groupadd -r -g 192 systemd-network 2>&1 || : -getent passwd systemd-network &>/dev/null || useradd -r -u 192 -l -g systemd-network -d / -s /sbin/nologin -c "systemd Network Management" systemd-network &>/dev/null || : - +%pre resolved getent group systemd-resolve &>/dev/null || groupadd -r -g 193 systemd-resolve 2>&1 || : getent passwd systemd-resolve &>/dev/null || useradd -r -u 193 -l -g systemd-resolve -d / -s /sbin/nologin -c "systemd Resolver" systemd-resolve &>/dev/null || : +%pre networkd +getent group systemd-network &>/dev/null || groupadd -r -g 192 systemd-network 2>&1 || : +getent passwd systemd-network &>/dev/null || useradd -r -u 192 -l -g systemd-network -d / -s /sbin/nologin -c "systemd Network Management" systemd-network &>/dev/null || : + %post +/sbin/ldconfig systemd-machine-id-setup &>/dev/null || : systemctl daemon-reexec &>/dev/null || : journalctl --update-catalog &>/dev/null || : @@ -648,6 +717,9 @@ if [ $1 -eq 1 ] ; then systemctl preset-all &>/dev/null || : fi +%postun +/sbin/ldconfig + %post libs %{?ldconfig} @@ -698,7 +770,7 @@ fi %{?ldconfig:%postun -p %ldconfig} -%global udev_services systemd-udev{d,-settle,-trigger}.service systemd-udevd-{control,kernel}.socket systemd-timesyncd.service +%global udev_services systemd-udev{d,-settle,-trigger}.service systemd-udevd-{control,kernel}.socket %preun if [ $1 -eq 0 ] ; then @@ -708,20 +780,29 @@ if [ $1 -eq 0 ] ; then serial-getty@.service \ console-getty.service \ debug-shell.service \ + >/dev/null || : +fi + +%preun resolved +if [ $1 -eq 0 ] ; then + systemctl disable --quiet \ + systemd-resolved.service \ + >/dev/null || : +fi + +%preun networkd +if [ $1 -eq 0 ] ; then + systemctl disable --quiet \ systemd-networkd.service \ systemd-networkd-wait-online.service \ - systemd-resolved.service \ >/dev/null || : fi -%pre udev +%pre timesyncd getent group systemd-timesync &>/dev/null || groupadd -r systemd-timesync 2>&1 || : getent passwd systemd-timesync &>/dev/null || useradd -r -l -g systemd-timesync -d / -s /sbin/nologin -c "systemd Time Synchronization" systemd-timesync &>/dev/null || : -%post udev -# Move old stuff around in /var/lib -mv %{_localstatedir}/lib/random-seed %{_localstatedir}/lib/systemd/random-seed &>/dev/null -mv %{_localstatedir}/lib/backlight %{_localstatedir}/lib/systemd/backlight &>/dev/null +%post timesyncd if [ -L %{_localstatedir}/lib/systemd/timesync ]; then rm %{_localstatedir}/lib/systemd/timesync mv %{_localstatedir}/lib/private/systemd/timesync %{_localstatedir}/lib/systemd/timesync @@ -730,7 +811,13 @@ if [ -f %{_localstatedir}/lib/systemd/clock ] ; then mkdir -p %{_localstatedir}/lib/systemd/timesync mv %{_localstatedir}/lib/systemd/clock %{_localstatedir}/lib/systemd/timesync/. fi +# devided from post and preun stage of udev that included in macro udev_services +%systemd_post systemd-timesyncd.service +%post udev +# Move old stuff around in /var/lib +mv %{_localstatedir}/lib/random-seed %{_localstatedir}/lib/systemd/random-seed &>/dev/null +mv %{_localstatedir}/lib/backlight %{_localstatedir}/lib/systemd/backlight &>/dev/null udevadm hwdb --update &>/dev/null %systemd_post %udev_services %{_systemddir}/systemd-random-seed save 2>&1 @@ -745,6 +832,10 @@ if [ -f "/usr/lib/udev/rules.d/50-udev-default.rules" ]; then fi %{_bindir}/systemctl daemon-reload &>/dev/null || : +# devided from post and preun stage of udev that included in macro udev_services +%preun timesyncd +%systemd_preun systemd-timesyncd.service + %preun udev %systemd_preun %udev_services @@ -801,7 +892,6 @@ fi %ghost %dir %attr(0755,-,-) /etc/systemd/system/system-update.target.wants %ghost %dir %attr(0755,-,-) /etc/systemd/system/timers.target.wants %ghost %dir %attr(0755,-,-) /var/lib/rpm-state/systemd - %ghost %dir /var/log/journal %ghost %attr(0664,root,utmp) /var/log/wtmp /var/log/README @@ -819,7 +909,6 @@ fi /usr/sbin/reboot /usr/sbin/halt /usr/sbin/telinit -/usr/sbin/resolvconf /usr/sbin/init /usr/sbin/runlevel /usr/sbin/poweroff @@ -839,12 +928,9 @@ fi /usr/share/bash-completion/completions/portablectl /usr/share/bash-completion/completions/systemd-run /usr/share/bash-completion/completions/systemd-cat -/usr/share/bash-completion/completions/resolvectl /usr/share/bash-completion/completions/coredumpctl /usr/share/bash-completion/completions/systemd-delta /usr/share/bash-completion/completions/systemd-cgls -/usr/share/bash-completion/completions/systemd-resolve -/usr/share/bash-completion/completions/networkctl /usr/share/bash-completion/completions/systemd-detect-virt /usr/share/bash-completion/completions/hostnamectl /usr/share/bash-completion/completions/systemd-cgtop @@ -859,14 +945,12 @@ fi /usr/share/zsh/site-functions/_journalctl /usr/share/zsh/site-functions/_systemd-delta /usr/share/zsh/site-functions/_systemd-tmpfiles -/usr/share/zsh/site-functions/_resolvectl /usr/share/zsh/site-functions/_systemctl /usr/share/zsh/site-functions/_systemd-run /usr/share/zsh/site-functions/_sd_outputmodes /usr/share/zsh/site-functions/_sd_unit_files /usr/share/zsh/site-functions/_sd_machines /usr/share/zsh/site-functions/_coredumpctl -/usr/share/zsh/site-functions/_networkctl /usr/share/zsh/site-functions/_timedatectl /usr/share/zsh/site-functions/_busctl /usr/share/zsh/site-functions/_systemd @@ -877,29 +961,22 @@ fi /usr/share/dbus-1/system-services/org.freedesktop.portable1.service /usr/share/dbus-1/system-services/org.freedesktop.login1.service /usr/share/dbus-1/system-services/org.freedesktop.locale1.service -/usr/share/dbus-1/system-services/org.freedesktop.resolve1.service /usr/share/dbus-1/system-services/org.freedesktop.hostname1.service -/usr/share/dbus-1/system-services/org.freedesktop.network1.service /usr/share/dbus-1/system-services/org.freedesktop.timedate1.service -/usr/share/dbus-1/system.d/org.freedesktop.resolve1.conf /usr/share/dbus-1/system.d/org.freedesktop.timedate1.conf /usr/share/dbus-1/system.d/org.freedesktop.hostname1.conf /usr/share/dbus-1/system.d/org.freedesktop.login1.conf /usr/share/dbus-1/system.d/org.freedesktop.systemd1.conf /usr/share/dbus-1/system.d/org.freedesktop.locale1.conf /usr/share/dbus-1/system.d/org.freedesktop.portable1.conf -/usr/share/dbus-1/system.d/org.freedesktop.network1.conf /usr/share/pkgconfig/systemd.pc /usr/share/pkgconfig/udev.pc /usr/share/polkit-1/actions/org.freedesktop.hostname1.policy /usr/share/polkit-1/actions/org.freedesktop.portable1.policy /usr/share/polkit-1/actions/org.freedesktop.timedate1.policy -/usr/share/polkit-1/actions/org.freedesktop.resolve1.policy /usr/share/polkit-1/actions/org.freedesktop.systemd1.policy /usr/share/polkit-1/actions/org.freedesktop.login1.policy -/usr/share/polkit-1/actions/org.freedesktop.network1.policy /usr/share/polkit-1/actions/org.freedesktop.locale1.policy -/usr/share/polkit-1/rules.d/systemd-networkd.rules /usr/bin/systemd-machine-id-setup /usr/bin/localectl /usr/bin/systemd-path @@ -911,13 +988,10 @@ fi /usr/bin/systemd-cat /usr/bin/systemd-inhibit /usr/bin/systemd-ask-password -/usr/bin/resolvectl /usr/bin/systemd-notify /usr/bin/coredumpctl /usr/bin/systemd-delta /usr/bin/systemd-cgls -/usr/bin/systemd-resolve -/usr/bin/networkctl /usr/bin/systemd-stdio-bridge /usr/bin/systemd-detect-virt /usr/bin/systemd-socket-activate @@ -954,10 +1028,8 @@ fi %{_systemddir}/systemd-cgroups-agent %{_systemddir}/systemd-sulogin-shell %{_systemddir}/systemd-boot-check-no-failures -%dir %{_systemddir}/ntp-units.d %{_systemddir}/systemd-user-sessions %{_systemddir}/systemd-sysctl -%{_systemddir}/systemd-networkd-wait-online %{_systemddir}/systemd-socket-proxyd %{_systemddir}/systemd-ac-power %{_systemddir}/systemd-hostnamed @@ -968,7 +1040,6 @@ fi %{_systemddir}/systemd-journald %{_systemddir}/systemd-user-runtime-dir %{_systemddir}/systemd-logind -%{_systemddir}/systemd-networkd %dir %{_systemddir}/system-preset %dir %{_systemddir}/user-environment-generators %{_systemddir}/systemd-shutdown @@ -985,13 +1056,10 @@ fi %{_systemddir}/systemd %dir %{_systemddir}/user-preset %{_systemddir}/systemd-coredump -%{_systemddir}/resolv.conf %{_systemddir}/systemd-dissect %{_systemddir}/systemd-veritysetup %{_systemddir}/systemd-network-generator -%{_systemddir}/systemd-time-wait-sync %{_systemddir}/systemd-pstore -%{_systemddir}/systemd-resolved %{_systemddir}/systemd-binfmt %{_systemddir}/user-preset/90-systemd.preset %dir %{_systemddir}/portable/profile @@ -1003,14 +1071,12 @@ fi %{_systemddir}/portable/profile/trusted/service.conf %{_systemddir}/portable/profile/nonetwork/service.conf %{_systemddir}/portable/profile/strict/service.conf -%{_unitdir}/systemd-networkd.socket %{_unitdir}/systemd-binfmt.service %{_unitdir}/systemd-machine-id-commit.service %dir %{_unitdir}/basic.target.wants %{_unitdir}/systemd-coredump.socket %{_unitdir}/ctrl-alt-del.target %{_unitdir}/systemd-tmpfiles-setup.service -%{_unitdir}/systemd-time-wait-sync.service %{_unitdir}/rpcbind.target %{_unitdir}/systemd-update-done.service %{_unitdir}/dev-hugepages.mount @@ -1074,7 +1140,6 @@ fi %{_unitdir}/systemd-update-utmp.service %dir %{_unitdir}/rescue.target.wants %{_unitdir}/bluetooth.target -%{_unitdir}/systemd-networkd-wait-online.service %{_unitdir}/systemd-ask-password-wall.path %{_unitdir}/emergency.service %{_unitdir}/network-pre.target @@ -1127,13 +1192,11 @@ fi %{_unitdir}/runlevel1.target %dir %{_unitdir}/remote-fs.target.wants %{_unitdir}/dbus-org.freedesktop.hostname1.service -%{_unitdir}/systemd-networkd.service %{_unitdir}/runlevel0.target %{_unitdir}/user.slice %{_unitdir}/systemd-journal-catalog-update.service %{_unitdir}/local-fs-pre.target %{_unitdir}/systemd-halt.service -%{_unitdir}/systemd-resolved.service %{_unitdir}/container-getty@.service %{_unitdir}/slices.target %{_unitdir}/systemd-network-generator.service @@ -1221,7 +1284,6 @@ fi %{_userunitdir}/systemd-tmpfiles-clean.timer %{_userunitdir}/sockets.target %{_userunitdir}/smartcard.target -%{_systemddir}/network/80-container-host0.network %{_systemddir}/catalog/systemd.fr.catalog %{_systemddir}/catalog/systemd.be.catalog %{_systemddir}/catalog/systemd.bg.catalog @@ -1263,13 +1325,10 @@ fi %ghost %config(noreplace) /etc/machine-info %ghost %config(noreplace) /etc/machine-id %ghost %config(noreplace) /etc/hostname -%dir /etc/systemd/network %config(noreplace) /etc/systemd/user.conf %config(noreplace) /etc/systemd/coredump.conf %dir /etc/systemd/user %config(noreplace) /etc/systemd/logind.conf -%config(noreplace) /etc/systemd/networkd.conf -%config(noreplace) /etc/systemd/resolved.conf %config(noreplace) /etc/systemd/journald.conf %config(noreplace) /etc/systemd/pstore.conf %dir /etc/systemd/system @@ -1285,7 +1344,6 @@ fi %config(noreplace) /etc/rc.d/init.d/README %dir /etc/xdg/systemd %config(noreplace) /etc/xdg/systemd/user - /usr/lib64/security/pam_systemd.so /usr/lib/rpm/macros.d/macros.systemd @@ -1321,10 +1379,8 @@ fi %files udev %ghost %dir /var/lib/systemd/backlight -%ghost %dir /var/lib/systemd/timesync %ghost %dir /var/lib/systemd/rfkill %ghost /var/lib/systemd/random-seed -%ghost /var/lib/systemd/timesync/clock /usr/sbin/udevadm /usr/share/bash-completion/completions/udevadm /usr/share/bash-completion/completions/bootctl @@ -1332,8 +1388,6 @@ fi /usr/share/zsh/site-functions/_bootctl /usr/share/zsh/site-functions/_udevadm /usr/share/zsh/site-functions/_kernel-install -/usr/share/dbus-1/system-services/org.freedesktop.timesync1.service -/usr/share/dbus-1/system.d/org.freedesktop.timesync1.conf /usr/bin/systemd-hwdb /usr/bin/udevadm /usr/bin/bootctl @@ -1343,7 +1397,6 @@ fi %dir /usr/lib/kernel %dir /usr/lib/modules-load.d %dir %{_systemddir}/boot -%{_systemddir}/systemd-timesyncd %{_systemddir}/systemd-growfs %{_systemddir}/systemd-modules-load %dir %{_systemddir}/system-sleep @@ -1371,7 +1424,6 @@ fi %dir %{_unitdir}/systemd-udev-trigger.service.d %{_unitdir}/systemd-random-seed.service %{_unitdir}/systemd-quotacheck.service -%{_unitdir}/systemd-timesyncd.service %{_unitdir}/systemd-udevd-control.socket %{_unitdir}/hibernate.target %{_unitdir}/systemd-remount-fs.service @@ -1405,7 +1457,7 @@ fi %{_systemddir}/system-generators/systemd-cryptsetup-generator %{_systemddir}/system-generators/systemd-hibernate-resume-generator %{_systemddir}/system-generators/systemd-gpt-auto-generator -%{_systemddir}/ntp-units.d/80-systemd-timesync.list + %dir %{_systemddir}/boot/efi %{_systemddir}/boot/efi/systemd-boot%{efi_arch}.efi %{_systemddir}/boot/efi/linux%{efi_arch}.efi.stub @@ -1476,7 +1528,7 @@ fi %dir /etc/udev %dir /etc/kernel %dir /etc/modules-load.d -%config(noreplace) /etc/systemd/timesyncd.conf + %config(noreplace) /etc/systemd/sleep.conf %dir /etc/kernel/install.d %ghost /etc/udev/hwdb.bin @@ -1486,9 +1538,7 @@ fi %files container /usr/share/bash-completion/completions/machinectl -/usr/share/bash-completion/completions/systemd-nspawn /usr/share/zsh/site-functions/_machinectl -/usr/share/zsh/site-functions/_systemd-nspawn /usr/share/dbus-1/system-services/org.freedesktop.import1.service /usr/share/dbus-1/system-services/org.freedesktop.machine1.service /usr/share/dbus-1/system.d/org.freedesktop.import1.conf @@ -1497,7 +1547,6 @@ fi /usr/share/polkit-1/actions/org.freedesktop.machine1.policy /usr/lib64/libnss_mymachines.so.2 /usr/bin/machinectl -/usr/bin/systemd-nspawn %{_systemddir}/systemd-import %{_systemddir}/systemd-machined %{_systemddir}/systemd-importd @@ -1512,12 +1561,8 @@ fi %{_unitdir}/machine.slice %{_unitdir}/machines.target %dir %{_unitdir}/machines.target.wants -%{_unitdir}/systemd-nspawn@.service %{_unitdir}/machines.target.wants/var-lib-machines.mount %{_unitdir}/remote-fs.target.wants/var-lib-machines.mount -%{_systemddir}/network/80-container-vz.network -%{_systemddir}/network/80-container-ve.network -/usr/lib/tmpfiles.d/systemd-nspawn.conf %files journal-remote %ghost %dir /var/log/journal/remote @@ -1549,11 +1594,72 @@ fi /usr/lib/udev/net-set-sriov-names /usr/lib/udev/detect_virt +%files resolved +/usr/sbin/resolvconf +/usr/bin/resolvectl +/usr/share/bash-completion/completions/resolvectl +/usr/share/zsh/site-functions/_resolvectl +/usr/share/bash-completion/completions/systemd-resolve +/usr/share/dbus-1/system-services/org.freedesktop.resolve1.service +/usr/share/dbus-1/system.d/org.freedesktop.resolve1.conf +/usr/share/polkit-1/actions/org.freedesktop.resolve1.policy +/usr/bin/systemd-resolve +%{_systemddir}/resolv.conf +%{_systemddir}/systemd-resolved +%config(noreplace) /etc/systemd/resolved.conf +%{_libdir}/libnss_resolve.so.2 +%{_unitdir}/systemd-resolved.service + +%files nspawn +/usr/share/bash-completion/completions/systemd-nspawn +/usr/share/zsh/site-functions/_systemd-nspawn +/usr/bin/systemd-nspawn +%{_unitdir}/systemd-nspawn@.service +/usr/lib/tmpfiles.d/systemd-nspawn.conf + +%files networkd +/usr/share/bash-completion/completions/networkctl +/usr/share/zsh/site-functions/_networkctl +/usr/share/dbus-1/system-services/org.freedesktop.network1.service +/usr/share/dbus-1/system.d/org.freedesktop.network1.conf +/usr/share/polkit-1/actions/org.freedesktop.network1.policy +/usr/share/polkit-1/rules.d/systemd-networkd.rules +/usr/bin/networkctl +%{_systemddir}/systemd-networkd-wait-online +%{_systemddir}/systemd-networkd +%{_unitdir}/systemd-networkd.socket +%{_unitdir}/systemd-networkd-wait-online.service +%{_unitdir}/systemd-networkd.service +%{_systemddir}/network/80-container-host0.network +%dir /etc/systemd/network +%config(noreplace) /etc/systemd/networkd.conf +%{_systemddir}/network/80-container-vz.network +%{_systemddir}/network/80-container-ve.network + +%files timesyncd +%dir %{_systemddir}/ntp-units.d +%{_systemddir}/systemd-time-wait-sync +%{_unitdir}/systemd-time-wait-sync.service +%ghost %dir /var/lib/systemd/timesync +%ghost /var/lib/systemd/timesync/clock +/usr/share/dbus-1/system-services/org.freedesktop.timesync1.service +/usr/share/dbus-1/system.d/org.freedesktop.timesync1.conf +%{_systemddir}/systemd-timesyncd +%{_unitdir}/systemd-timesyncd.service +%{_systemddir}/ntp-units.d/80-systemd-timesync.list +%config(noreplace) /etc/systemd/timesyncd.conf + +%files pam +%{_libdir}/security/pam_systemd.so + %files help /usr/share/man/*/* %exclude /usr/share/man/man3/* %changelog +* Wed Aug 31 2022 yangmingtai - 243-54 +- divided some feature into subpackage + * Thu May 26 2022 yangmingtai - 243-53 - remove old device on move event -- Gitee From d7c79af9d35f333593090160a671ad86dfe4aff5 Mon Sep 17 00:00:00 2001 From: Mingtai Date: Mon, 5 Sep 2022 07:04:14 +0000 Subject: [PATCH 34/38] delete rpath Signed-off-by: Mingtai --- systemd.spec | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/systemd.spec b/systemd.spec index 441857e..2f1539e 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 54 +Release: 55 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -556,6 +556,20 @@ install -m 0755 %{SOURCE105} %{buildroot}/usr/lib/udev install -m 0755 %{SOURCE106} %{buildroot}/usr/lib/udev install -m 0755 %{SOURCE107} %{buildroot}/usr/lib/udev +# remove rpath info +for file in $(find %{buildroot}/ -executable -type f -exec file {} ';' | grep "\" | awk -F ':' '{print $1}') +do + if [ ! -u "$file" ]; then + if [ -w "$file" ]; then + chrpath -d $file + fi + fi +done + +# add rpath path /usr/lib/systemd in ld.so.conf.d +mkdir -p %{buildroot}%{_sysconfdir}/ld.so.conf.d +echo "/usr/lib/systemd" > %{buildroot}%{_sysconfdir}/ld.so.conf.d/%{name}-%{_arch}.conf + %check %ninja_test -C %{_vpath_builddir} @@ -1346,6 +1360,7 @@ fi %config(noreplace) /etc/xdg/systemd/user /usr/lib64/security/pam_systemd.so /usr/lib/rpm/macros.d/macros.systemd +%{_sysconfdir}/ld.so.conf.d/%{name}-%{_arch}.conf %files libs /usr/lib64/libnss_systemd.so.2 @@ -1657,6 +1672,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon Sep 5 2022 yangmingtai - 243-55 +- delete rpath + * Wed Aug 31 2022 yangmingtai - 243-54 - divided some feature into subpackage -- Gitee From ae569885e492fab0df82147fedc9926006cc4acd Mon Sep 17 00:00:00 2001 From: hanjinpeng Date: Fri, 2 Sep 2022 12:38:44 +0800 Subject: [PATCH 35/38] Prevent excessive proc 1 mountinfo reparsing (rhbz #1819868) --- ...excessive-proc-1-mountinfo-reparsing.patch | 1463 +++++++++++++++++ systemd.spec | 8 +- 2 files changed, 1470 insertions(+), 1 deletion(-) create mode 100644 0001-Prevent-excessive-proc-1-mountinfo-reparsing.patch diff --git a/0001-Prevent-excessive-proc-1-mountinfo-reparsing.patch b/0001-Prevent-excessive-proc-1-mountinfo-reparsing.patch new file mode 100644 index 0000000..4adb522 --- /dev/null +++ b/0001-Prevent-excessive-proc-1-mountinfo-reparsing.patch @@ -0,0 +1,1463 @@ +From 9b7bf4ac5545e66c838257145167224ef02d3fb3 Mon Sep 17 00:00:00 2001 +From: hanjinpeng +Date: Thu, 18 Aug 2022 15:31:39 +0800 +Subject: [PATCH] Prevent excessive proc 1 mountinfo reparsing (rhbz #1819868) + +--- + src/basic/ratelimit.h | 8 + + src/core/mount.c | 6 + + src/libsystemd/libsystemd.sym | 7 + + src/libsystemd/sd-event/event-source.h | 9 + + src/libsystemd/sd-event/sd-event.c | 795 +++++++++++++++++-------- + src/libsystemd/sd-event/test-event.c | 96 +++ + src/systemd/sd-event.h | 4 + + 7 files changed, 689 insertions(+), 236 deletions(-) + +diff --git a/src/basic/ratelimit.h b/src/basic/ratelimit.h +index de91def..0012b49 100644 +--- a/src/basic/ratelimit.h ++++ b/src/basic/ratelimit.h +@@ -38,3 +38,11 @@ typedef struct RateLimit { + } while (false) + + bool ratelimit_below(RateLimit *r); ++ ++static inline void ratelimit_reset(RateLimit *rl) { ++ rl->num = rl->begin = 0; ++} ++ ++static inline bool ratelimit_configured(RateLimit *rl) { ++ return rl->interval > 0 && rl->burst > 0; ++} +diff --git a/src/core/mount.c b/src/core/mount.c +index 959b8fb..1b64011 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1756,6 +1756,12 @@ static void mount_enumerate(Manager *m) { + goto fail; + } + ++ r = sd_event_source_set_ratelimit(m->mount_event_source, 1 * USEC_PER_SEC, 5); ++ if (r < 0) { ++ log_error_errno(r, "Failed to enable rate limit for mount events: %m"); ++ goto fail; ++ } ++ + (void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch"); + } + +diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym +index 5ec42e0..23dd19a 100644 +--- a/src/libsystemd/libsystemd.sym ++++ b/src/libsystemd/libsystemd.sym +@@ -682,3 +682,10 @@ global: + sd_bus_object_vtable_format; + sd_event_source_disable_unref; + } LIBSYSTEMD_241; ++ ++LIBSYSTEMD_248 { ++global: ++ sd_event_source_set_ratelimit; ++ sd_event_source_get_ratelimit; ++ sd_event_source_is_ratelimited; ++} LIBSYSTEMD_243; +diff --git a/src/libsystemd/sd-event/event-source.h b/src/libsystemd/sd-event/event-source.h +index 99ab8fc..817739d 100644 +--- a/src/libsystemd/sd-event/event-source.h ++++ b/src/libsystemd/sd-event/event-source.h +@@ -11,6 +11,7 @@ + #include "hashmap.h" + #include "list.h" + #include "prioq.h" ++#include "ratelimit.h" + + typedef enum EventSourceType { + SOURCE_IO, +@@ -60,6 +61,7 @@ struct sd_event_source { + bool pending:1; + bool dispatching:1; + bool floating:1; ++ bool ratelimited:1; + + int64_t priority; + unsigned pending_index; +@@ -71,6 +73,13 @@ struct sd_event_source { + + LIST_FIELDS(sd_event_source, sources); + ++ RateLimit rate_limit; ++ ++ /* These are primarily fields relevant for time event sources, but since any event source can ++ * effectively become one when rate-limited, this is part of the common fields. */ ++ unsigned earliest_index; ++ unsigned latest_index; ++ + union { + struct { + sd_event_io_handler_t callback; +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 5d0e057..b1e6a9a 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -28,6 +28,7 @@ + + #define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC) + ++ + static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = { + [SOURCE_IO] = "io", + [SOURCE_TIME_REALTIME] = "realtime", +@@ -46,7 +47,25 @@ static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] + + DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int); + +-#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM) ++#define EVENT_SOURCE_IS_TIME(t) \ ++ IN_SET((t), \ ++ SOURCE_TIME_REALTIME, \ ++ SOURCE_TIME_BOOTTIME, \ ++ SOURCE_TIME_MONOTONIC, \ ++ SOURCE_TIME_REALTIME_ALARM, \ ++ SOURCE_TIME_BOOTTIME_ALARM) ++ ++#define EVENT_SOURCE_CAN_RATE_LIMIT(t) \ ++ IN_SET((t), \ ++ SOURCE_IO, \ ++ SOURCE_TIME_REALTIME, \ ++ SOURCE_TIME_BOOTTIME, \ ++ SOURCE_TIME_MONOTONIC, \ ++ SOURCE_TIME_REALTIME_ALARM, \ ++ SOURCE_TIME_BOOTTIME_ALARM, \ ++ SOURCE_SIGNAL, \ ++ SOURCE_DEFER, \ ++ SOURCE_INOTIFY) + + struct sd_event { + unsigned n_ref; +@@ -72,7 +91,7 @@ struct sd_event { + Hashmap *signal_data; /* indexed by priority */ + + Hashmap *child_sources; +- unsigned n_enabled_child_sources; ++ unsigned n_online_child_sources; + + Set *post_sources; + +@@ -108,7 +127,7 @@ struct sd_event { + + LIST_HEAD(sd_event_source, sources); + +- usec_t last_run, last_log; ++ usec_t last_run_usec, last_log_usec; + unsigned delays[sizeof(usec_t) * 8]; + }; + +@@ -117,6 +136,16 @@ static thread_local sd_event *default_event = NULL; + static void source_disconnect(sd_event_source *s); + static void event_gc_inode_data(sd_event *e, struct inode_data *d); + ++static bool event_source_is_online(sd_event_source *s) { ++ assert(s); ++ return s->enabled != SD_EVENT_OFF && !s->ratelimited; ++} ++ ++static bool event_source_is_offline(sd_event_source *s) { ++ assert(s); ++ return s->enabled == SD_EVENT_OFF || s->ratelimited; ++} ++ + static sd_event *event_resolve(sd_event *e) { + return e == SD_EVENT_DEFAULT ? default_event : e; + } +@@ -134,6 +163,11 @@ static int pending_prioq_compare(const void *a, const void *b) { + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + ++ /* Non rate-limited ones first. */ ++ r = CMP(!!x->ratelimited, !!y->ratelimited); ++ if (r != 0) ++ return r; ++ + /* Lower priority values first */ + r = CMP(x->priority, y->priority); + if (r != 0) +@@ -156,6 +190,11 @@ static int prepare_prioq_compare(const void *a, const void *b) { + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + ++ /* Non rate-limited ones first. */ ++ r = CMP(!!x->ratelimited, !!y->ratelimited); ++ if (r != 0) ++ return r; ++ + /* Move most recently prepared ones last, so that we can stop + * preparing as soon as we hit one that has already been + * prepared in the current iteration */ +@@ -167,12 +206,30 @@ static int prepare_prioq_compare(const void *a, const void *b) { + return CMP(x->priority, y->priority); + } + ++static usec_t time_event_source_next(const sd_event_source *s) { ++ assert(s); ++ ++ /* We have two kinds of event sources that have elapsation times associated with them: the actual ++ * time based ones and the ones for which a ratelimit can be in effect (where we want to be notified ++ * once the ratelimit time window ends). Let's return the next elapsing time depending on what we are ++ * looking at here. */ ++ ++ if (s->ratelimited) { /* If rate-limited the next elapsation is when the ratelimit time window ends */ ++ assert(s->rate_limit.begin != 0); ++ assert(s->rate_limit.interval != 0); ++ return usec_add(s->rate_limit.begin, s->rate_limit.interval); ++ } ++ ++ /* Otherwise this must be a time event source, if not ratelimited */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ return s->time.next; ++ ++ return USEC_INFINITY; ++} ++ + static int earliest_time_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + +- assert(EVENT_SOURCE_IS_TIME(x->type)); +- assert(x->type == y->type); +- + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; +@@ -186,19 +243,30 @@ static int earliest_time_prioq_compare(const void *a, const void *b) { + return 1; + + /* Order by time */ +- return CMP(x->time.next, y->time.next); ++ return CMP(time_event_source_next(x), time_event_source_next(y)); + } + + static usec_t time_event_source_latest(const sd_event_source *s) { +- return usec_add(s->time.next, s->time.accuracy); ++ assert(s); ++ ++ if (s->ratelimited) { /* For ratelimited stuff the earliest and the latest time shall actually be the ++ * same, as we should avoid adding additional inaccuracy on an inaccuracy time ++ * window */ ++ assert(s->rate_limit.begin != 0); ++ assert(s->rate_limit.interval != 0); ++ return usec_add(s->rate_limit.begin, s->rate_limit.interval); ++ } ++ ++ /* Must be a time event source, if not ratelimited */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ return usec_add(s->time.next, s->time.accuracy); ++ ++ return USEC_INFINITY; + } + + static int latest_time_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; + +- assert(EVENT_SOURCE_IS_TIME(x->type)); +- assert(x->type == y->type); +- + /* Enabled ones first */ + if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) + return -1; +@@ -356,8 +424,6 @@ static bool event_pid_changed(sd_event *e) { + } + + static void source_io_unregister(sd_event_source *s) { +- int r; +- + assert(s); + assert(s->type == SOURCE_IO); + +@@ -367,9 +433,8 @@ static void source_io_unregister(sd_event_source *s) { + if (!s->io.registered) + return; + +- r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL); +- if (r < 0) +- log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll: %m", ++ if (epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL) < 0) ++ log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll, ignoring: %m", + strna(s->description), event_source_type_to_string(s->type)); + + s->io.registered = false; +@@ -619,12 +684,12 @@ static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) + * the signalfd for it. */ + + if (sig == SIGCHLD && +- e->n_enabled_child_sources > 0) ++ e->n_online_child_sources > 0) + return; + + if (e->signal_sources && + e->signal_sources[sig] && +- e->signal_sources[sig]->enabled != SD_EVENT_OFF) ++ event_source_is_online(e->signal_sources[sig])) + return; + + /* +@@ -654,6 +719,52 @@ static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) + event_unmask_signal_data(e, d, sig); + } + ++static void event_source_pp_prioq_reshuffle(sd_event_source *s) { ++ assert(s); ++ ++ /* Reshuffles the pending + prepare prioqs. Called whenever the dispatch order changes, i.e. when ++ * they are enabled/disabled or marked pending and such. */ ++ ++ if (s->pending) ++ prioq_reshuffle(s->event->pending, s, &s->pending_index); ++ ++ if (s->prepare) ++ prioq_reshuffle(s->event->prepare, s, &s->prepare_index); ++} ++ ++static void event_source_time_prioq_reshuffle(sd_event_source *s) { ++ struct clock_data *d; ++ ++ assert(s); ++ ++ /* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy, ++ * pending, enable state. Makes sure the two prioq's are ordered properly again. */ ++ ++ if (s->ratelimited) ++ d = &s->event->monotonic; ++ else { ++ assert(EVENT_SOURCE_IS_TIME(s->type)); ++ assert_se(d = event_get_clock_data(s->event, s->type)); ++ } ++ ++ prioq_reshuffle(d->earliest, s, &s->earliest_index); ++ prioq_reshuffle(d->latest, s, &s->latest_index); ++ d->needs_rearm = true; ++} ++ ++static void event_source_time_prioq_remove( ++ sd_event_source *s, ++ struct clock_data *d) { ++ ++ assert(s); ++ assert(d); ++ ++ prioq_remove(d->earliest, s, &s->earliest_index); ++ prioq_remove(d->latest, s, &s->latest_index); ++ s->earliest_index = s->latest_index = PRIOQ_IDX_NULL; ++ d->needs_rearm = true; ++} ++ + static void source_disconnect(sd_event_source *s) { + sd_event *event; + +@@ -676,17 +787,18 @@ static void source_disconnect(sd_event_source *s) { + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: +- case SOURCE_TIME_BOOTTIME_ALARM: { +- struct clock_data *d; ++ case SOURCE_TIME_BOOTTIME_ALARM: ++ /* Only remove this event source from the time event source here if it is not ratelimited. If ++ * it is ratelimited, we'll remove it below, separately. Why? Because the clock used might ++ * differ: ratelimiting always uses CLOCK_MONOTONIC, but timer events might use any clock */ + +- d = event_get_clock_data(s->event, s->type); +- assert(d); ++ if (!s->ratelimited) { ++ struct clock_data *d; ++ assert_se(d = event_get_clock_data(s->event, s->type)); ++ event_source_time_prioq_remove(s, d); ++ } + +- prioq_remove(d->earliest, s, &s->time.earliest_index); +- prioq_remove(d->latest, s, &s->time.latest_index); +- d->needs_rearm = true; + break; +- } + + case SOURCE_SIGNAL: + if (s->signal.sig > 0) { +@@ -701,9 +813,9 @@ static void source_disconnect(sd_event_source *s) { + + case SOURCE_CHILD: + if (s->child.pid > 0) { +- if (s->enabled != SD_EVENT_OFF) { +- assert(s->event->n_enabled_child_sources > 0); +- s->event->n_enabled_child_sources--; ++ if (event_source_is_online(s)) { ++ assert(s->event->n_online_child_sources > 0); ++ s->event->n_online_child_sources--; + } + + (void) hashmap_remove(s->event->child_sources, PID_TO_PTR(s->child.pid)); +@@ -769,6 +881,9 @@ static void source_disconnect(sd_event_source *s) { + if (s->prepare) + prioq_remove(s->event->prepare, s, &s->prepare_index); + ++ if (s->ratelimited) ++ event_source_time_prioq_remove(s, &s->event->monotonic); ++ + event = s->event; + + s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID; +@@ -818,16 +933,8 @@ static int source_set_pending(sd_event_source *s, bool b) { + } else + assert_se(prioq_remove(s->event->pending, s, &s->pending_index)); + +- if (EVENT_SOURCE_IS_TIME(s->type)) { +- struct clock_data *d; +- +- d = event_get_clock_data(s->event, s->type); +- assert(d); +- +- prioq_reshuffle(d->earliest, s, &s->time.earliest_index); +- prioq_reshuffle(d->latest, s, &s->time.latest_index); +- d->needs_rearm = true; +- } ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ event_source_time_prioq_reshuffle(s); + + if (s->type == SOURCE_SIGNAL && !b) { + struct signal_data *d; +@@ -983,6 +1090,52 @@ static int time_exit_callback(sd_event_source *s, uint64_t usec, void *userdata) + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); + } + ++static int setup_clock_data(sd_event *e, struct clock_data *d, clockid_t clock) { ++ int r; ++ ++ assert(d); ++ ++ if (d->fd < 0) { ++ r = event_setup_timer_fd(e, d, clock); ++ if (r < 0) ++ return r; ++ } ++ ++ r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); ++ if (r < 0) ++ return r; ++ ++ r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); ++ if (r < 0) ++ return r; ++ ++ return 0; ++} ++ ++static int event_source_time_prioq_put( ++ sd_event_source *s, ++ struct clock_data *d) { ++ ++ int r; ++ ++ assert(s); ++ assert(d); ++ ++ r = prioq_put(d->earliest, s, &s->earliest_index); ++ if (r < 0) ++ return r; ++ ++ r = prioq_put(d->latest, s, &s->latest_index); ++ if (r < 0) { ++ assert_se(prioq_remove(d->earliest, s, &s->earliest_index) > 0); ++ s->earliest_index = PRIOQ_IDX_NULL; ++ return r; ++ } ++ ++ d->needs_rearm = true; ++ return 0; ++} ++ + _public_ int sd_event_add_time( + sd_event *e, + sd_event_source **ret, +@@ -1013,23 +1166,12 @@ _public_ int sd_event_add_time( + if (!callback) + callback = time_exit_callback; + +- d = event_get_clock_data(e, type); +- assert(d); ++ assert_se(d = event_get_clock_data(e, type)); + +- r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); ++ r = setup_clock_data(e, d, clock); + if (r < 0) + return r; + +- r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); +- if (r < 0) +- return r; +- +- if (d->fd < 0) { +- r = event_setup_timer_fd(e, d, clock); +- if (r < 0) +- return r; +- } +- + s = source_new(e, !ret, type); + if (!s) + return -ENOMEM; +@@ -1037,17 +1179,12 @@ _public_ int sd_event_add_time( + s->time.next = usec; + s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy; + s->time.callback = callback; +- s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL; ++ s->earliest_index = s->latest_index = PRIOQ_IDX_NULL; + s->userdata = userdata; + s->enabled = SD_EVENT_ONESHOT; + +- d->needs_rearm = true; + +- r = prioq_put(d->earliest, s, &s->time.earliest_index); +- if (r < 0) +- return r; +- +- r = prioq_put(d->latest, s, &s->time.latest_index); ++ r = event_source_time_prioq_put(s, d); + if (r < 0) + return r; + +@@ -1165,11 +1302,12 @@ _public_ int sd_event_add_child( + if (r < 0) + return r; + +- e->n_enabled_child_sources++; ++ e->n_online_child_sources++; + + r = event_make_signal_data(e, SIGCHLD, NULL); + if (r < 0) { +- e->n_enabled_child_sources--; ++ e->n_online_child_sources--; ++ source_free(s); + return r; + } + +@@ -1746,7 +1884,7 @@ _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { + if (s->io.fd == fd) + return 0; + +- if (s->enabled == SD_EVENT_OFF) { ++ if (event_source_is_offline(s)) { + s->io.fd = fd; + s->io.registered = false; + } else { +@@ -1813,7 +1951,7 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) + if (r < 0) + return r; + +- if (s->enabled != SD_EVENT_OFF) { ++ if (event_source_is_online(s)) { + r = source_io_register(s, s->enabled, events); + if (r < 0) + return r; +@@ -1916,7 +2054,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) + + event_gc_inode_data(s->event, old_inode_data); + +- } else if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) { ++ } else if (s->type == SOURCE_SIGNAL && event_source_is_online(s)) { + struct signal_data *old, *d; + + /* Move us from the signalfd belonging to the old +@@ -1936,11 +2074,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) + } else + s->priority = priority; + +- if (s->pending) +- prioq_reshuffle(s->event->pending, s, &s->pending_index); +- +- if (s->prepare) +- prioq_reshuffle(s->event->prepare, s, &s->prepare_index); ++ event_source_pp_prioq_reshuffle(s); + + if (s->type == SOURCE_EXIT) + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); +@@ -1966,172 +2100,201 @@ _public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) { + return s->enabled != SD_EVENT_OFF; + } + +-_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { +- int r; +- +- assert_return(s, -EINVAL); +- assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL); +- assert_return(!event_pid_changed(s->event), -ECHILD); ++static int event_source_offline( ++ sd_event_source *s, ++ int enabled, ++ bool ratelimited) { + +- /* If we are dead anyway, we are fine with turning off +- * sources, but everything else needs to fail. */ +- if (s->event->state == SD_EVENT_FINISHED) +- return m == SD_EVENT_OFF ? 0 : -ESTALE; ++ bool was_offline; ++ int r; + +- if (s->enabled == m) +- return 0; ++ assert(s); ++ assert(enabled == SD_EVENT_OFF || ratelimited); + +- if (m == SD_EVENT_OFF) { ++ /* Unset the pending flag when this event source is disabled */ ++ if (s->enabled != SD_EVENT_OFF && ++ enabled == SD_EVENT_OFF && ++ !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { ++ r = source_set_pending(s, false); ++ if (r < 0) ++ return r; ++ } + +- /* Unset the pending flag when this event source is disabled */ +- if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { +- r = source_set_pending(s, false); +- if (r < 0) +- return r; +- } ++ was_offline = event_source_is_offline(s); ++ s->enabled = enabled; ++ s->ratelimited = ratelimited; + +- switch (s->type) { ++ switch (s->type) { + +- case SOURCE_IO: +- source_io_unregister(s); +- s->enabled = m; +- break; ++ case SOURCE_IO: ++ source_io_unregister(s); ++ break; + +- case SOURCE_TIME_REALTIME: +- case SOURCE_TIME_BOOTTIME: +- case SOURCE_TIME_MONOTONIC: +- case SOURCE_TIME_REALTIME_ALARM: +- case SOURCE_TIME_BOOTTIME_ALARM: { +- struct clock_data *d; ++ case SOURCE_TIME_REALTIME: ++ case SOURCE_TIME_BOOTTIME: ++ case SOURCE_TIME_MONOTONIC: ++ case SOURCE_TIME_REALTIME_ALARM: ++ case SOURCE_TIME_BOOTTIME_ALARM: ++ event_source_time_prioq_reshuffle(s); ++ break; + +- s->enabled = m; +- d = event_get_clock_data(s->event, s->type); +- assert(d); ++ case SOURCE_SIGNAL: ++ event_gc_signal_data(s->event, &s->priority, s->signal.sig); ++ break; + +- prioq_reshuffle(d->earliest, s, &s->time.earliest_index); +- prioq_reshuffle(d->latest, s, &s->time.latest_index); +- d->needs_rearm = true; +- break; ++ case SOURCE_CHILD: ++ if (!was_offline) { ++ assert(s->event->n_online_child_sources > 0); ++ s->event->n_online_child_sources--; + } + +- case SOURCE_SIGNAL: +- s->enabled = m; +- +- event_gc_signal_data(s->event, &s->priority, s->signal.sig); +- break; ++ event_gc_signal_data(s->event, &s->priority, SIGCHLD); ++ break; + +- case SOURCE_CHILD: +- s->enabled = m; ++ case SOURCE_EXIT: ++ prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); ++ break; + +- assert(s->event->n_enabled_child_sources > 0); +- s->event->n_enabled_child_sources--; ++ case SOURCE_DEFER: ++ case SOURCE_POST: ++ case SOURCE_INOTIFY: ++ break; + +- event_gc_signal_data(s->event, &s->priority, SIGCHLD); +- break; ++ default: ++ assert_not_reached("Wut? I shouldn't exist."); ++ } + +- case SOURCE_EXIT: +- s->enabled = m; +- prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); +- break; ++ return 1; ++} + +- case SOURCE_DEFER: +- case SOURCE_POST: +- case SOURCE_INOTIFY: +- s->enabled = m; +- break; ++static int event_source_online( ++ sd_event_source *s, ++ int enabled, ++ bool ratelimited) { + +- default: +- assert_not_reached("Wut? I shouldn't exist."); +- } ++ bool was_online; ++ int r; + +- } else { ++ assert(s); ++ assert(enabled != SD_EVENT_OFF || !ratelimited); + +- /* Unset the pending flag when this event source is enabled */ +- if (s->enabled == SD_EVENT_OFF && !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { +- r = source_set_pending(s, false); +- if (r < 0) +- return r; +- } ++ /* Unset the pending flag when this event source is enabled */ ++ if (s->enabled == SD_EVENT_OFF && ++ enabled != SD_EVENT_OFF && ++ !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { ++ r = source_set_pending(s, false); ++ if (r < 0) ++ return r; ++ } + +- switch (s->type) { ++ /* Are we really ready for onlining? */ ++ if (enabled == SD_EVENT_OFF || ratelimited) { ++ /* Nope, we are not ready for onlining, then just update the precise state and exit */ ++ s->enabled = enabled; ++ s->ratelimited = ratelimited; ++ return 0; ++ } + +- case SOURCE_IO: +- r = source_io_register(s, m, s->io.events); +- if (r < 0) +- return r; ++ was_online = event_source_is_online(s); + +- s->enabled = m; +- break; ++ switch (s->type) { ++ case SOURCE_IO: ++ r = source_io_register(s, enabled, s->io.events); ++ if (r < 0) ++ return r; ++ break; + +- case SOURCE_TIME_REALTIME: +- case SOURCE_TIME_BOOTTIME: +- case SOURCE_TIME_MONOTONIC: +- case SOURCE_TIME_REALTIME_ALARM: +- case SOURCE_TIME_BOOTTIME_ALARM: { +- struct clock_data *d; ++ case SOURCE_SIGNAL: ++ r = event_make_signal_data(s->event, s->signal.sig, NULL); ++ if (r < 0) { ++ event_gc_signal_data(s->event, &s->priority, s->signal.sig); ++ return r; ++ } + +- s->enabled = m; +- d = event_get_clock_data(s->event, s->type); +- assert(d); ++ break; + +- prioq_reshuffle(d->earliest, s, &s->time.earliest_index); +- prioq_reshuffle(d->latest, s, &s->time.latest_index); +- d->needs_rearm = true; +- break; ++ case SOURCE_CHILD: ++ r = event_make_signal_data(s->event, SIGCHLD, NULL); ++ if (r < 0) { ++ s->enabled = SD_EVENT_OFF; ++ s->event->n_online_child_sources--; ++ event_gc_signal_data(s->event, &s->priority, SIGCHLD); ++ return r; + } + +- case SOURCE_SIGNAL: ++ if (!was_online) ++ s->event->n_online_child_sources++; ++ break; + +- s->enabled = m; ++ case SOURCE_TIME_REALTIME: ++ case SOURCE_TIME_BOOTTIME: ++ case SOURCE_TIME_MONOTONIC: ++ case SOURCE_TIME_REALTIME_ALARM: ++ case SOURCE_TIME_BOOTTIME_ALARM: ++ case SOURCE_EXIT: ++ case SOURCE_DEFER: ++ case SOURCE_POST: ++ case SOURCE_INOTIFY: ++ break; + +- r = event_make_signal_data(s->event, s->signal.sig, NULL); +- if (r < 0) { +- s->enabled = SD_EVENT_OFF; +- event_gc_signal_data(s->event, &s->priority, s->signal.sig); +- return r; +- } ++ default: ++ assert_not_reached("Wut? I shouldn't exist."); ++ } + +- break; ++ s->enabled = enabled; ++ s->ratelimited = ratelimited; + +- case SOURCE_CHILD: ++ /* Non-failing operations below */ ++ switch (s->type) { ++ case SOURCE_TIME_REALTIME: ++ case SOURCE_TIME_BOOTTIME: ++ case SOURCE_TIME_MONOTONIC: ++ case SOURCE_TIME_REALTIME_ALARM: ++ case SOURCE_TIME_BOOTTIME_ALARM: ++ event_source_time_prioq_reshuffle(s); ++ break; + +- if (s->enabled == SD_EVENT_OFF) +- s->event->n_enabled_child_sources++; ++ case SOURCE_EXIT: ++ prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); ++ break; + +- s->enabled = m; ++ default: ++ break; ++ } + +- r = event_make_signal_data(s->event, SIGCHLD, NULL); +- if (r < 0) { +- s->enabled = SD_EVENT_OFF; +- s->event->n_enabled_child_sources--; +- event_gc_signal_data(s->event, &s->priority, SIGCHLD); +- return r; +- } ++ return 1; ++} + +- break; ++_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { ++ int r; + +- case SOURCE_EXIT: +- s->enabled = m; +- prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); +- break; ++ assert_return(s, -EINVAL); ++ assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL); ++ assert_return(!event_pid_changed(s->event), -ECHILD); + +- case SOURCE_DEFER: +- case SOURCE_POST: +- case SOURCE_INOTIFY: +- s->enabled = m; +- break; ++ /* If we are dead anyway, we are fine with turning off sources, but everything else needs to fail. */ ++ if (s->event->state == SD_EVENT_FINISHED) ++ return m == SD_EVENT_OFF ? 0 : -ESTALE; + +- default: +- assert_not_reached("Wut? I shouldn't exist."); +- } +- } ++ if (s->enabled == m) /* No change? */ ++ return 0; + +- if (s->pending) +- prioq_reshuffle(s->event->pending, s, &s->pending_index); ++ if (m == SD_EVENT_OFF) ++ r = event_source_offline(s, m, s->ratelimited); ++ else { ++ if (s->enabled != SD_EVENT_OFF) { ++ /* Switching from "on" to "oneshot" or back? If that's the case, we can take a shortcut, the ++ * event source is already enabled after all. */ ++ s->enabled = m; ++ return 0; ++ } + +- if (s->prepare) +- prioq_reshuffle(s->event->prepare, s, &s->prepare_index); ++ r = event_source_online(s, m, s->ratelimited); ++ } ++ if (r < 0) ++ return r; + ++ event_source_pp_prioq_reshuffle(s); + return 0; + } + +@@ -2146,7 +2309,6 @@ _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) { + } + + _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { +- struct clock_data *d; + int r; + + assert_return(s, -EINVAL); +@@ -2160,13 +2322,7 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { + + s->time.next = usec; + +- d = event_get_clock_data(s->event, s->type); +- assert(d); +- +- prioq_reshuffle(d->earliest, s, &s->time.earliest_index); +- prioq_reshuffle(d->latest, s, &s->time.latest_index); +- d->needs_rearm = true; +- ++ event_source_time_prioq_reshuffle(s); + return 0; + } + +@@ -2181,7 +2337,6 @@ _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *use + } + + _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) { +- struct clock_data *d; + int r; + + assert_return(s, -EINVAL); +@@ -2199,12 +2354,7 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec + + s->time.accuracy = usec; + +- d = event_get_clock_data(s->event, s->type); +- assert(d); +- +- prioq_reshuffle(d->latest, s, &s->time.latest_index); +- d->needs_rearm = true; +- ++ event_source_time_prioq_reshuffle(s); + return 0; + } + +@@ -2287,6 +2437,96 @@ _public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata) + return ret; + } + ++static int event_source_enter_ratelimited(sd_event_source *s) { ++ int r; ++ ++ assert(s); ++ ++ /* When an event source becomes ratelimited, we place it in the CLOCK_MONOTONIC priority queue, with ++ * the end of the rate limit time window, much as if it was a timer event source. */ ++ ++ if (s->ratelimited) ++ return 0; /* Already ratelimited, this is a NOP hence */ ++ ++ /* Make sure we can install a CLOCK_MONOTONIC event further down. */ ++ r = setup_clock_data(s->event, &s->event->monotonic, CLOCK_MONOTONIC); ++ if (r < 0) ++ return r; ++ ++ /* Timer event sources are already using the earliest/latest queues for the timer scheduling. Let's ++ * first remove them from the prioq appropriate for their own clock, so that we can use the prioq ++ * fields of the event source then for adding it to the CLOCK_MONOTONIC prioq instead. */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ event_source_time_prioq_remove(s, event_get_clock_data(s->event, s->type)); ++ ++ /* Now, let's add the event source to the monotonic clock instead */ ++ r = event_source_time_prioq_put(s, &s->event->monotonic); ++ if (r < 0) ++ goto fail; ++ ++ /* And let's take the event source officially offline */ ++ r = event_source_offline(s, s->enabled, /* ratelimited= */ true); ++ if (r < 0) { ++ event_source_time_prioq_remove(s, &s->event->monotonic); ++ goto fail; ++ } ++ ++ event_source_pp_prioq_reshuffle(s); ++ ++ log_debug("Event source %p (%s) entered rate limit state.", s, strna(s->description)); ++ return 0; ++ ++fail: ++ /* Reinstall time event sources in the priority queue as before. This shouldn't fail, since the queue ++ * space for it should already be allocated. */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ assert_se(event_source_time_prioq_put(s, event_get_clock_data(s->event, s->type)) >= 0); ++ ++ return r; ++} ++ ++static int event_source_leave_ratelimit(sd_event_source *s) { ++ int r; ++ ++ assert(s); ++ ++ if (!s->ratelimited) ++ return 0; ++ ++ /* Let's take the event source out of the monotonic prioq first. */ ++ event_source_time_prioq_remove(s, &s->event->monotonic); ++ ++ /* Let's then add the event source to its native clock prioq again — if this is a timer event source */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) { ++ r = event_source_time_prioq_put(s, event_get_clock_data(s->event, s->type)); ++ if (r < 0) ++ goto fail; ++ } ++ ++ /* Let's try to take it online again. */ ++ r = event_source_online(s, s->enabled, /* ratelimited= */ false); ++ if (r < 0) { ++ /* Do something roughly sensible when this failed: undo the two prioq ops above */ ++ if (EVENT_SOURCE_IS_TIME(s->type)) ++ event_source_time_prioq_remove(s, event_get_clock_data(s->event, s->type)); ++ ++ goto fail; ++ } ++ ++ event_source_pp_prioq_reshuffle(s); ++ ratelimit_reset(&s->rate_limit); ++ ++ log_debug("Event source %p (%s) left rate limit state.", s, strna(s->description)); ++ return 0; ++ ++fail: ++ /* Do something somewhat reasonable when we cannot move an event sources out of ratelimited mode: ++ * simply put it back in it, maybe we can then process it more successfully next iteration. */ ++ assert_se(event_source_time_prioq_put(s, &s->event->monotonic) >= 0); ++ ++ return r; ++} ++ + static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) { + usec_t c; + assert(e); +@@ -2385,7 +2625,7 @@ static int event_arm_timer( + d->needs_rearm = false; + + a = prioq_peek(d->earliest); +- if (!a || a->enabled == SD_EVENT_OFF || a->time.next == USEC_INFINITY) { ++ if (!a || a->enabled == SD_EVENT_OFF || time_event_source_next(a) == USEC_INFINITY) { + + if (d->fd < 0) + return 0; +@@ -2405,7 +2645,7 @@ static int event_arm_timer( + b = prioq_peek(d->latest); + assert_se(b && b->enabled != SD_EVENT_OFF); + +- t = sleep_between(e, a->time.next, time_event_source_latest(b)); ++ t = sleep_between(e, time_event_source_next(a), time_event_source_latest(b)); + if (d->next == t) + return 0; + +@@ -2484,19 +2724,29 @@ static int process_timer( + + for (;;) { + s = prioq_peek(d->earliest); +- if (!s || +- s->time.next > n || +- s->enabled == SD_EVENT_OFF || +- s->pending) ++ if (!s || time_event_source_next(s) > n) ++ break; ++ ++ if (s->ratelimited) { ++ /* This is an event sources whose ratelimit window has ended. Let's turn it on ++ * again. */ ++ assert(s->ratelimited); ++ ++ r = event_source_leave_ratelimit(s); ++ if (r < 0) ++ return r; ++ ++ continue; ++ } ++ ++ if (s->enabled == SD_EVENT_OFF || s->pending) + break; + + r = source_set_pending(s, true); + if (r < 0) + return r; + +- prioq_reshuffle(d->earliest, s, &s->time.earliest_index); +- prioq_reshuffle(d->latest, s, &s->time.latest_index); +- d->needs_rearm = true; ++ event_source_time_prioq_reshuffle(s); + } + + return 0; +@@ -2535,7 +2785,7 @@ static int process_child(sd_event *e) { + if (s->pending) + continue; + +- if (s->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(s)) + continue; + + zero(s->child.siginfo); +@@ -2708,7 +2958,7 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { + + LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { + +- if (s->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(s)) + continue; + + r = source_set_pending(s, true); +@@ -2744,7 +2994,7 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { + * sources if IN_IGNORED or IN_UNMOUNT is set. */ + LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { + +- if (s->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(s)) + continue; + + if ((d->buffer.ev.mask & (IN_IGNORED|IN_UNMOUNT)) == 0 && +@@ -2783,6 +3033,7 @@ static int process_inotify(sd_event *e) { + } + + static int source_dispatch(sd_event_source *s) { ++ _cleanup_(sd_event_unrefp) sd_event *saved_event = NULL; + EventSourceType saved_type; + int r = 0; + +@@ -2793,6 +3044,20 @@ static int source_dispatch(sd_event_source *s) { + * the event. */ + saved_type = s->type; + ++ /* Similar, store a reference to the event loop object, so that we can still access it after the ++ * callback might have invalidated/disconnected the event source. */ ++ saved_event = sd_event_ref(s->event); ++ ++ /* Check if we hit the ratelimit for this event source, if so, let's disable it. */ ++ assert(!s->ratelimited); ++ if (!ratelimit_below(&s->rate_limit)) { ++ r = event_source_enter_ratelimited(s); ++ if (r < 0) ++ return r; ++ ++ return 1; ++ } ++ + if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { + r = source_set_pending(s, false); + if (r < 0) +@@ -2919,7 +3184,7 @@ static int event_prepare(sd_event *e) { + sd_event_source *s; + + s = prioq_peek(e->prepare); +- if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF) ++ if (!s || s->prepare_iteration == e->iteration || event_source_is_offline(s)) + break; + + s->prepare_iteration = e->iteration; +@@ -2948,18 +3213,17 @@ static int event_prepare(sd_event *e) { + + static int dispatch_exit(sd_event *e) { + sd_event_source *p; +- _cleanup_(sd_event_unrefp) sd_event *ref = NULL; + int r; + + assert(e); + + p = prioq_peek(e->exit); +- if (!p || p->enabled == SD_EVENT_OFF) { ++ if (!p || event_source_is_offline(p)) { + e->state = SD_EVENT_FINISHED; + return 0; + } + +- ref = sd_event_ref(e); ++ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); + e->iteration++; + e->state = SD_EVENT_EXITING; + r = source_dispatch(p); +@@ -2976,7 +3240,7 @@ static sd_event_source* event_next_pending(sd_event *e) { + if (!p) + return NULL; + +- if (p->enabled == SD_EVENT_OFF) ++ if (event_source_is_offline(p)) + return NULL; + + return p; +@@ -3052,6 +3316,14 @@ _public_ int sd_event_prepare(sd_event *e) { + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); + ++ /* Let's check that if we are a default event loop we are executed in the correct thread. We only do ++ * this check here once, since gettid() is typically not cached, and thus want to minimize ++ * syscalls */ ++ assert_return(!e->default_event_ptr || e->tid == gettid(), -EREMOTEIO); ++ ++ /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */ ++ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); ++ + if (e->exit_requested) + goto pending; + +@@ -3236,9 +3508,8 @@ _public_ int sd_event_dispatch(sd_event *e) { + + p = event_next_pending(e); + if (p) { +- _cleanup_(sd_event_unrefp) sd_event *ref = NULL; ++ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); + +- ref = sd_event_ref(e); + e->state = SD_EVENT_RUNNING; + r = source_dispatch(p); + e->state = SD_EVENT_INITIAL; +@@ -3272,29 +3543,32 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) { + assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); + assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); + +- if (e->profile_delays && e->last_run) { ++ if (e->profile_delays && e->last_run_usec != 0) { + usec_t this_run; + unsigned l; + + this_run = now(CLOCK_MONOTONIC); + +- l = u64log2(this_run - e->last_run); +- assert(l < sizeof(e->delays)); ++ l = u64log2(this_run - e->last_run_usec); ++ assert(l < ELEMENTSOF(e->delays)); + e->delays[l]++; + +- if (this_run - e->last_log >= 5*USEC_PER_SEC) { ++ if (this_run - e->last_log_usec >= 5*USEC_PER_SEC) { + event_log_delays(e); +- e->last_log = this_run; ++ e->last_log_usec = this_run; + } + } + ++ /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */ ++ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); ++ + r = sd_event_prepare(e); + if (r == 0) + /* There was nothing? Then wait... */ + r = sd_event_wait(e, timeout); + + if (e->profile_delays) +- e->last_run = now(CLOCK_MONOTONIC); ++ e->last_run_usec = now(CLOCK_MONOTONIC); + + if (r > 0) { + /* There's something now, then let's dispatch it */ +@@ -3309,7 +3583,6 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) { + } + + _public_ int sd_event_loop(sd_event *e) { +- _cleanup_(sd_event_unrefp) sd_event *ref = NULL; + int r; + + assert_return(e, -EINVAL); +@@ -3317,7 +3590,7 @@ _public_ int sd_event_loop(sd_event *e) { + assert_return(!event_pid_changed(e), -ECHILD); + assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); + +- ref = sd_event_ref(e); ++ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = NULL; + + while (e->state != SD_EVENT_FINISHED) { + r = sd_event_run(e, (uint64_t) -1); +@@ -3549,3 +3822,53 @@ _public_ int sd_event_source_set_floating(sd_event_source *s, int b) { + + return 1; + } ++ ++_public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval, unsigned burst) { ++ int r; ++ ++ assert_return(s, -EINVAL); ++ ++ /* Turning on ratelimiting on event source types that don't support it, is a loggable offense. Doing ++ * so is a programming error. */ ++ assert_return(EVENT_SOURCE_CAN_RATE_LIMIT(s->type), -EDOM); ++ ++ /* When ratelimiting is configured we'll always reset the rate limit state first and start fresh, ++ * non-ratelimited. */ ++ r = event_source_leave_ratelimit(s); ++ if (r < 0) ++ return r; ++ ++ RATELIMIT_INIT(s->rate_limit, interval, burst); ++ return 0; ++} ++ ++_public_ int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval, unsigned *ret_burst) { ++ assert_return(s, -EINVAL); ++ ++ /* Querying whether an event source has ratelimiting configured is not a loggable offsense, hence ++ * don't use assert_return(). Unlike turning on ratelimiting it's not really a programming error */ ++ if (!EVENT_SOURCE_CAN_RATE_LIMIT(s->type)) ++ return -EDOM; ++ ++ if (!ratelimit_configured(&s->rate_limit)) ++ return -ENOEXEC; ++ ++ if (ret_interval) ++ *ret_interval = s->rate_limit.interval; ++ if (ret_burst) ++ *ret_burst = s->rate_limit.burst; ++ ++ return 0; ++} ++ ++_public_ int sd_event_source_is_ratelimited(sd_event_source *s) { ++ assert_return(s, -EINVAL); ++ ++ if (!EVENT_SOURCE_CAN_RATE_LIMIT(s->type)) ++ return false; ++ ++ if (!ratelimit_configured(&s->rate_limit)) ++ return false; ++ ++ return s->ratelimited; ++} +diff --git a/src/libsystemd/sd-event/test-event.c b/src/libsystemd/sd-event/test-event.c +index 954b93a..bc82c61 100644 +--- a/src/libsystemd/sd-event/test-event.c ++++ b/src/libsystemd/sd-event/test-event.c +@@ -482,6 +482,100 @@ static void test_inotify(unsigned n_create_events) { + sd_event_unref(e); + } + ++ ++static int ratelimit_io_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { ++ unsigned *c = (unsigned*) userdata; ++ *c += 1; ++ return 0; ++} ++ ++static int ratelimit_time_handler(sd_event_source *s, uint64_t usec, void *userdata) { ++ int r; ++ ++ r = sd_event_source_set_enabled(s, SD_EVENT_ON); ++ if (r < 0) ++ log_warning_errno(r, "Failed to turn on notify event source: %m"); ++ ++ r = sd_event_source_set_time(s, usec + 1000); ++ if (r < 0) ++ log_error_errno(r, "Failed to restart watchdog event source: %m"); ++ ++ unsigned *c = (unsigned*) userdata; ++ *c += 1; ++ ++ return 0; ++} ++ ++static void test_ratelimit(void) { ++ _cleanup_close_pair_ int p[2] = {-1, -1}; ++ _cleanup_(sd_event_unrefp) sd_event *e = NULL; ++ _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL; ++ uint64_t interval; ++ unsigned count, burst; ++ ++ assert_se(sd_event_default(&e) >= 0); ++ assert_se(pipe2(p, O_CLOEXEC|O_NONBLOCK) >= 0); ++ ++ assert_se(sd_event_add_io(e, &s, p[0], EPOLLIN, ratelimit_io_handler, &count) >= 0); ++ assert_se(sd_event_source_set_description(s, "test-ratelimit-io") >= 0); ++ assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0); ++ assert_se(sd_event_source_get_ratelimit(s, &interval, &burst) >= 0); ++ assert_se(interval == 1 * USEC_PER_SEC && burst == 5); ++ ++ assert_se(write(p[1], "1", 1) == 1); ++ ++ count = 0; ++ for (unsigned i = 0; i < 10; i++) { ++ log_debug("slow loop iteration %u", i); ++ assert_se(sd_event_run(e, UINT64_MAX) >= 0); ++ assert_se(usleep(250 * USEC_PER_MSEC) >= 0); ++ } ++ ++ assert_se(sd_event_source_is_ratelimited(s) == 0); ++ assert_se(count == 10); ++ log_info("ratelimit_io_handler: called %d times, event source not ratelimited", count); ++ ++ assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0); ++ assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 5) >= 0); ++ ++ count = 0; ++ for (unsigned i = 0; i < 10; i++) { ++ log_debug("fast event loop iteration %u", i); ++ assert_se(sd_event_run(e, UINT64_MAX) >= 0); ++ assert_se(usleep(10) >= 0); ++ } ++ log_info("ratelimit_io_handler: called %d times, event source got ratelimited", count); ++ assert_se(count < 10); ++ ++ s = sd_event_source_unref(s); ++ safe_close_pair(p); ++ ++ count = 0; ++ ++ assert_se(sd_event_add_time(e, &s, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 1000, 0, ratelimit_time_handler, &count) >= 0); ++ assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) == 0); ++ ++ do { ++ assert_se(sd_event_run(e, UINT64_MAX) >= 0); ++ } while (!sd_event_source_is_ratelimited(s)); ++ ++ log_info("ratelimit_time_handler: called %d times, event source got ratelimited", count); ++ assert_se(count == 10); ++ ++ /* In order to get rid of active rate limit client needs to disable it explicitely */ ++ assert_se(sd_event_source_set_ratelimit(s, 0, 0) >= 0); ++ assert_se(!sd_event_source_is_ratelimited(s)); ++ ++ assert_se(sd_event_source_set_ratelimit(s, 1 * USEC_PER_SEC, 10) >= 0); ++ ++ do { ++ assert_se(sd_event_run(e, UINT64_MAX) >= 0); ++ } while (!sd_event_source_is_ratelimited(s)); ++ ++ log_info("ratelimit_time_handler: called 10 more times, event source got ratelimited"); ++ assert_se(count == 20); ++} ++ + int main(int argc, char *argv[]) { + test_setup_logging(LOG_INFO); + +@@ -492,5 +586,7 @@ int main(int argc, char *argv[]) { + test_inotify(100); /* should work without overflow */ + test_inotify(33000); /* should trigger a q overflow */ + ++ test_ratelimit(); ++ + return 0; + } +diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h +index b14c926..121b721 100644 +--- a/src/systemd/sd-event.h ++++ b/src/systemd/sd-event.h +@@ -147,6 +147,10 @@ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t + int sd_event_source_get_floating(sd_event_source *s); + int sd_event_source_set_floating(sd_event_source *s, int b); + ++int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval_usec, unsigned burst); ++int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval_usec, unsigned *ret_burst); ++int sd_event_source_is_ratelimited(sd_event_source *s); ++ + /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */ + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref); + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref); +-- +2.27.0 + diff --git a/systemd.spec b/systemd.spec index 441857e..974e075 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 54 +Release: 55 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -183,6 +183,9 @@ Patch9010: fix-capsh-drop-but-ping-success.patch Patch9011: 0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch Patch9012: set-kernel-core_pipe_limit-to-16.patch +#rhbz 1819868 +Patch9013: 0001-Prevent-excessive-proc-1-mountinfo-reparsing.patch + BuildRequires: gcc, gcc-c++ BuildRequires: libcap-devel, libmount-devel, pam-devel, libselinux-devel BuildRequires: audit-libs-devel, cryptsetup-devel, dbus-devel, libacl-devel @@ -1657,6 +1660,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Thu Sep 1 2022 Han Jinpeng - 243-55 +- fix create pod container fail and systemd timeout (rhbz #1819868) + * Wed Aug 31 2022 yangmingtai - 243-54 - divided some feature into subpackage -- Gitee From d72cc1a0d84a7a2c207cdb5a63538b8166607d04 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Tue, 18 Oct 2022 21:13:25 +0800 Subject: [PATCH 36/38] sync community patches --- backport-Use-correct-poll.h-include.patch | 43 ++++++ ...alize-mounts-and-automounts-for-swit.patch | 136 ++++++++++++++++++ ...l-add-some-careful-overflow-checking.patch | 57 ++++++++ backport-network-fix-an-infinite-loop.patch | 35 +++++ ...-use-right-type-for-usec_initialized.patch | 29 ++++ systemd.spec | 10 +- 6 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 backport-Use-correct-poll.h-include.patch create mode 100644 backport-core-do-not-serialize-mounts-and-automounts-for-swit.patch create mode 100644 backport-journal-add-some-careful-overflow-checking.patch create mode 100644 backport-network-fix-an-infinite-loop.patch create mode 100644 backport-sd-device-use-right-type-for-usec_initialized.patch diff --git a/backport-Use-correct-poll.h-include.patch b/backport-Use-correct-poll.h-include.patch new file mode 100644 index 0000000..c93cc63 --- /dev/null +++ b/backport-Use-correct-poll.h-include.patch @@ -0,0 +1,43 @@ +From 99236971acc52455df51226996fbe71ecedc2f6f Mon Sep 17 00:00:00 2001 +From: David Seifert +Date: Mon, 2 Aug 2021 16:09:10 +0200 +Subject: [PATCH] Use correct `` include + +* `` is not specified in POSIX + +(cherry picked from commit 2b6c0bb2a341c95223ce672249e43c743b03d78c) +(cherry picked from commit fba9fd963bb3b5fafdb123788b3fabe6ed0830c9) + +Reference: https://github.com/systemd/systemd-stable/commit/99236971acc52455df51226996fbe71ecedc2f6f +Conflict: adapt context +--- + src/shared/nscd-flush.c | 2 +- + src/shared/varlink.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/shared/nscd-flush.c b/src/shared/nscd-flush.c +index dfc47c4234..19e16d9345 100644 +--- a/src/shared/nscd-flush.c ++++ b/src/shared/nscd-flush.c +@@ -1,5 +1,5 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ +-#include ++#include + + #include "fd-util.h" + #include "io-util.h" +diff --git a/src/shared/varlink.c b/src/shared/varlink.c +index b9da917310..b887cb1ba4 100644 +--- a/src/shared/varlink.c ++++ b/src/shared/varlink.c +@@ -1,6 +1,6 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + +-#include ++#include + + #include "alloc-util.h" + #include "errno-util.h" +-- +2.27.0 + diff --git a/backport-core-do-not-serialize-mounts-and-automounts-for-swit.patch b/backport-core-do-not-serialize-mounts-and-automounts-for-swit.patch new file mode 100644 index 0000000..511123c --- /dev/null +++ b/backport-core-do-not-serialize-mounts-and-automounts-for-swit.patch @@ -0,0 +1,136 @@ +From 0dc4f1b0910d7b96ea9743493db7fd2d841164da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 3 Jun 2021 19:40:01 +0200 +Subject: [PATCH] core: do not serialize mounts and automounts for switch-root + +When e.g. tmp.mount is present in the initrd, and we serialize it, switch root, +and deserialize, the new systemd is confused because it thinks /tmp is mounted. +In general, it doesn't make sense to serialize anything that refers to paths in +the old root file system. + +This fixes two errors for me: + +1. tmp.mount was not mounted properly before local-fs.target. It would be +mounted as some point (I guess when we re-read /proc/self/mountinfo for some +other reason). In effect systemd-tmpfiles-setup.service would see one fs, and +some other units started later a different one. In particular gdm.service would +fail because the pre-created /tmp/.X11-unix with proper permissions would not +exist at time it was started. + +2. # systemd[1]: proc-sys-fs-binfmt_misc.automount: Got hangup/error on autofs pipe from kernel. Likely our automount point has been unmounted by someone or something else? + # systemd[1]: proc-sys-fs-binfmt_misc.automount: Failed with result 'unmounted'. + # systemd[1]: Mounting proc-sys-fs-binfmt_misc.mount... + # systemd[1]: Mounted proc-sys-fs-binfmt_misc.mount. + # systemd[1]: Starting systemd-binfmt.service... + # systemd[1]: Finished systemd-binfmt.service. + # systemd[1]: proc-sys-fs-binfmt_misc.automount: Path /proc/sys/fs/binfmt_misc is already a mount point, refusing start. + # systemd[1]: Failed to set up automount proc-sys-fs-binfmt_misc.automount. + # systemd[1]: proc-sys-fs-binfmt_misc.automount: Path /proc/sys/fs/binfmt_misc is already a mount point, refusing start. + # systemd[1]: Failed to set up automount proc-sys-fs-binfmt_misc.automount. + # systemd[1]: proc-sys-fs-binfmt_misc.automount: Path /proc/sys/fs/binfmt_misc is already a mount point, refusing start. + # systemd[1]: Failed to set up automount proc-sys-fs-binfmt_misc.automount. + # systemd[1]: Stopping systemd-binfmt.service... + # systemd[1]: systemd-binfmt.service: Deactivated successfully. + # systemd[1]: Stopped systemd-binfmt.service. + +I couldn't understand the error here, but in retrospect the first line is entirely +correct: "someone or something else" was the old systemd unmounting the old root. + +(cherry picked from commit 755021d43448011ef169f20ec3a08d4e92c824af) + +Reference: https://github.com/systemd/systemd-stable/commit/0dc4f1b0910d7b96ea9743493db7fd2d841164da +Conflict: adapt context +--- + src/core/manager.c | 6 +----- + src/core/mount.c | 1 + + src/core/unit.c | 16 ++++++++++++++-- + src/core/unit.h | 3 +++ + 4 files changed, 19 insertions(+), 7 deletions(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index cfeaca6..722e4e6 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -3255,11 +3255,7 @@ int manager_serialize( + if (u->id != t) + continue; + +- /* Start marker */ +- fputs(u->id, f); +- fputc('\n', f); +- +- r = unit_serialize(u, f, fds, !switching_root); ++ r = unit_serialize(u, f, fds, switching_root); + if (r < 0) + return r; + } +diff --git a/src/core/mount.c b/src/core/mount.c +index 1b64011..3a6c220 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1981,6 +1981,7 @@ const UnitVTable mount_vtable = { + "Mount\0" + "Install\0", + .private_section = "Mount", ++ .exclude_from_switch_root_serialization = true, + + .init = mount_init, + .load = mount_load, +diff --git a/src/core/unit.c b/src/core/unit.c +index c8cf9ee..fa8489c 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3376,7 +3376,7 @@ static const char *const io_accounting_metric_field_last[_CGROUP_IO_ACCOUNTING_M + [CGROUP_IO_WRITE_OPERATIONS] = "io-accounting-write-operations-last", + }; + +-int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { ++int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool switching_root) { + CGroupIPAccountingMetric m; + int r; + +@@ -3384,6 +3384,18 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { + assert(f); + assert(fds); + ++ if (switching_root && UNIT_VTABLE(u)->exclude_from_switch_root_serialization) { ++ /* In the new root, paths for mounts and automounts will be different, so it doesn't make ++ * much sense to serialize things. API file systems will be moved to the new root, but we ++ * don't have mount units for those. */ ++ log_unit_debug(u, "not serializing before switch-root"); ++ return 0; ++ } ++ ++ /* Start marker */ ++ fputs(u->id, f); ++ fputc('\n', f); ++ + if (unit_can_serialize(u)) { + r = UNIT_VTABLE(u)->serialize(u, f, fds); + if (r < 0) +@@ -3455,7 +3467,7 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { + (void) serialize_item_format(f, ip_accounting_metric_field[m], "%" PRIu64, v); + } + +- if (serialize_jobs) { ++ if (!switching_root) { + if (u->job) { + fputs("job\n", f); + job_serialize(u->job, f); +diff --git a/src/core/unit.h b/src/core/unit.h +index bb5e782..cb70325 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -602,6 +602,9 @@ typedef struct UnitVTable { + /* True if units of this type shall be startable only once and then never again */ + bool once_only:1; + ++ /* Do not serialize this unit when preparing for root switch */ ++ bool exclude_from_switch_root_serialization; ++ + /* True if queued jobs of this type should be GC'ed if no other job needs them anymore */ + bool gc_jobs:1; + } UnitVTable; +-- +2.27.0 + diff --git a/backport-journal-add-some-careful-overflow-checking.patch b/backport-journal-add-some-careful-overflow-checking.patch new file mode 100644 index 0000000..2b7d27e --- /dev/null +++ b/backport-journal-add-some-careful-overflow-checking.patch @@ -0,0 +1,57 @@ +From 84e1819ec104a168f7904134b6212669133c955f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 8 Jun 2021 22:14:40 +0200 +Subject: [PATCH] journal: add some careful overflow checking + +(cherry picked from commit d8671b1c6f036ce270b9631973314e7de24e74b1) + +Reference: https://github.com/systemd/systemd-stable/commit/84e1819ec104a168f7904134b6212669133c955f +Conflict: adapt context +--- + src/journal/sd-journal.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c +index 02ac260..244ea91 100644 +--- a/src/journal/sd-journal.c ++++ b/src/journal/sd-journal.c +@@ -2761,25 +2761,33 @@ void journal_print_header(sd_journal *j) { + } + } + +-_public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) { ++_public_ int sd_journal_get_usage(sd_journal *j, uint64_t *ret) { + Iterator i; + JournalFile *f; + uint64_t sum = 0; + + assert_return(j, -EINVAL); + assert_return(!journal_pid_changed(j), -ECHILD); +- assert_return(bytes, -EINVAL); ++ assert_return(ret, -EINVAL); + + ORDERED_HASHMAP_FOREACH(f, j->files, i) { + struct stat st; ++ uint64_t b; + + if (fstat(f->fd, &st) < 0) + return -errno; + +- sum += (uint64_t) st.st_blocks * 512ULL; ++ b = (uint64_t) st.st_blocks; ++ if (b > UINT64_MAX / 512) ++ return -EOVERFLOW; ++ b *= 512; ++ ++ if (sum > UINT64_MAX - b) ++ return -EOVERFLOW; ++ sum += b; + } + +- *bytes = sum; ++ *ret = sum; + return 0; + } + +-- +2.27.0 diff --git a/backport-network-fix-an-infinite-loop.patch b/backport-network-fix-an-infinite-loop.patch new file mode 100644 index 0000000..01841b8 --- /dev/null +++ b/backport-network-fix-an-infinite-loop.patch @@ -0,0 +1,35 @@ +From b234ee7859de556c272c36fc691cee4cb08f7230 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 20 May 2021 16:14:17 +0900 +Subject: [PATCH] network: fix an infinite loop + +Fixes #19467. + +(cherry picked from commit e8f99f4e249916e12c09ee5cc9a108cba6a2b5c0) + +Reference: https://github.com/systemd/systemd-stable/commit/b234ee7859de556c272c36fc691cee4cb08f7230 +Conflict: adapt context +--- + src/network/networkd-link.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index 8219d95b0d..c781dd58d7 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -157,6 +157,12 @@ static void link_update_master_operstate(Link *link, NetDev *netdev) { + if (!netdev) + return; + ++ /* If an interface is self-mentioned in Bridge= or friends, then it introduces an infinite loop. ++ * FIXME: there still exits a possibility of an infinite loop when two or more interfaces ++ * mention each other in Bridge= or so. We need to detect such a loop. */ ++ if (link->ifindex == netdev->ifindex) ++ return; ++ + if (link_get(link->manager, netdev->ifindex, &master) < 0) + return; + +-- +2.27.0 + diff --git a/backport-sd-device-use-right-type-for-usec_initialized.patch b/backport-sd-device-use-right-type-for-usec_initialized.patch new file mode 100644 index 0000000..d182492 --- /dev/null +++ b/backport-sd-device-use-right-type-for-usec_initialized.patch @@ -0,0 +1,29 @@ +From d6b0efcdd83a937363267ed751fd9a1085505394 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 20 Apr 2021 17:06:21 +0200 +Subject: [PATCH] sd-device: use right type for usec_initialized + +(cherry picked from commit a156eb89c827206ee5b51d53016ba63be0c90449) + +Reference: https://github.com/systemd/systemd-stable/commit/d6b0efcdd83a937363267ed751fd9a1085505394 +Conflict: NA +--- + src/libsystemd/sd-device/device-internal.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-device/device-internal.h b/src/libsystemd/sd-device/device-internal.h +index c1a81e3b41..c7f9b59087 100644 +--- a/src/libsystemd/sd-device/device-internal.h ++++ b/src/libsystemd/sd-device/device-internal.h +@@ -69,7 +69,7 @@ struct sd_device { + + char *id_filename; + +- uint64_t usec_initialized; ++ usec_t usec_initialized; + + mode_t devmode; + uid_t devuid; +-- +2.27.0 + diff --git a/systemd.spec b/systemd.spec index db630b3..f5ebd25 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 56 +Release: 57 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -168,6 +168,11 @@ Patch0118: backport-udev-allow-to-match-OriginalName-with-renamed-interf.pa Patch0119: backport-udev-do-not-update-return-value-on-failure.patch Patch0120: backport-test-add-test-for-device-renaming-issue-16967.patch Patch0121: backport-Prevent-excessive-proc-1-mountinfo-reparsing.patch +Patch0122: backport-Use-correct-poll.h-include.patch +Patch0123: backport-core-do-not-serialize-mounts-and-automounts-for-swit.patch +Patch0124: backport-journal-add-some-careful-overflow-checking.patch +Patch0125: backport-network-fix-an-infinite-loop.patch +Patch0126: backport-sd-device-use-right-type-for-usec_initialized.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1673,6 +1678,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Oct 18 2022 yangmingtai - 243-57 +- DESC:sync community patches + * Tue Sep 6 2022 Han Jinpeng - 243-56 - fix create pod container fail and systemd timeout (rhbz #1819868) -- Gitee From 1cbfde447da33f06aeec742cc59ad7a6e38455a5 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Mon, 7 Nov 2022 17:25:21 +0800 Subject: [PATCH 37/38] fix CVE-2022-3821 and backport patch to fix ci failed --- ...ap-list-parse-numerical-capabilities.patch | 94 +++++++++++++ backport-fix-CVE-2022-3821.patch | 46 +++++++ ...t-use-cap_last_cap-for-max-supported.patch | 128 ++++++++++++++++++ systemd.spec | 8 +- 4 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 backport-cap-list-parse-numerical-capabilities.patch create mode 100644 backport-fix-CVE-2022-3821.patch create mode 100644 backport-test-use-cap_last_cap-for-max-supported.patch diff --git a/backport-cap-list-parse-numerical-capabilities.patch b/backport-cap-list-parse-numerical-capabilities.patch new file mode 100644 index 0000000..da558de --- /dev/null +++ b/backport-cap-list-parse-numerical-capabilities.patch @@ -0,0 +1,94 @@ +From 417770f3033c426ca848b158d0bf057cd8ad1329 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 9 Jul 2020 23:15:47 +0200 +Subject: [PATCH] basic/cap-list: parse/print numerical capabilities + +We would refuse to print capabilities which were didn't have a name +for. The kernel adds new capabilities from time to time, most recently +cap_bpf. 'systmectl show -p CapabilityBoundingSet ...' would fail with +"Failed to parse bus message: Invalid argument" because +capability_set_to_string_alloc() would fail with -EINVAL. So let's +print such capabilities in hexadecimal: + +CapabilityBoundingSet=cap_chown cap_dac_override cap_dac_read_search + cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap + cap_linux_immutable cap_net_bind_service cap_net_broadcast +cap_net_admin + cap_net_raw cap_ipc_lock cap_ipc_owner 0x10 0x11 0x12 0x13 0x14 0x15 +0x16 + 0x17 0x18 0x19 0x1a ... + +For symmetry, also allow capabilities that we don't know to be +specified. + +Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1853736. +Reference:https://github.com/systemd/systemd/pull/16424/commits/417770f3033c426ca848b158d0bf057cd8ad1329 +Conflict:adapt context +--- + src/basic/cap-list.c | 10 +++++++--- + src/test/test-cap-list.c | 4 +++- + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c +index 79d6a40..a975574 100644 +--- a/src/basic/cap-list.c ++++ b/src/basic/cap-list.c +@@ -10,6 +10,7 @@ + #include "macro.h" + #include "missing.h" + #include "parse-util.h" ++#include "stdio-util.h" + #include "util.h" + + static const struct capability_name* lookup_capability(register const char *str, register GPERF_LEN_TYPE len); +@@ -37,7 +38,7 @@ int capability_from_name(const char *name) { + /* Try to parse numeric capability */ + r = safe_atoi(name, &i); + if (r >= 0) { +- if (i >= 0 && (size_t) i < ELEMENTSOF(capability_names)) ++ if (i >= 0 && i < 64) + return i; + else + return -EINVAL; +@@ -65,11 +66,14 @@ int capability_set_to_string_alloc(uint64_t set, char **s) { + for (i = 0; i <= cap_last_cap(); i++) + if (set & (UINT64_C(1) << i)) { + const char *p; ++ char buf[2 + 16 + 1]; + size_t add; + + p = capability_to_name(i); +- if (!p) +- return -EINVAL; ++ if (!p) { ++ xsprintf(buf, "0x%lx", i); ++ p = buf; ++ } + + add = strlen(p); + +diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c +index 563b996..33dd246 100644 +--- a/src/test/test-cap-list.c ++++ b/src/test/test-cap-list.c +@@ -31,6 +31,8 @@ static void test_cap_list(void) { + assert_se(capability_from_name("cAp_aUdIt_rEAd") == CAP_AUDIT_READ); + assert_se(capability_from_name("0") == 0); + assert_se(capability_from_name("15") == 15); ++ assert_se(capability_from_name("63") == 63); ++ assert_se(capability_from_name("64") == -EINVAL); + assert_se(capability_from_name("-1") == -EINVAL); + + for (i = 0; i < capability_list_length(); i++) { +@@ -65,7 +67,7 @@ static void test_capability_set_one(uint64_t c, const char *t) { + + free(t1); + assert_se(t1 = strjoin("'cap_chown cap_dac_override' \"cap_setgid cap_setuid\"", t, +- " hogehoge foobar 12345 3.14 -3 ", t)); ++ " hogehoge foobar 18446744073709551616 3.14 -3 ", t)); + assert_se(capability_set_from_string(t1, &c1) == 0); + assert_se(c1 == c_masked); + } +-- +2.27.0 + diff --git a/backport-fix-CVE-2022-3821.patch b/backport-fix-CVE-2022-3821.patch new file mode 100644 index 0000000..6bce6f6 --- /dev/null +++ b/backport-fix-CVE-2022-3821.patch @@ -0,0 +1,46 @@ +From 8d2d0895229cfbe39c1c5c16e61e426812a72e8b Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 7 Jul 2022 18:27:02 +0900 +Subject: [PATCH] time-util: fix buffer-over-run + +Fixes #23928. +Conflict:adapt test context +Reference:https://github.com/systemd/systemd/pull/23933/commits/8d2d0895229cfbe39c1c5c16e61e426812a72e8b + +--- + src/basic/time-util.c | 2 +- + src/test/test-time-util.c | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/basic/time-util.c b/src/basic/time-util.c +index a9cf9c4..a0eec99 100644 +--- a/src/basic/time-util.c ++++ b/src/basic/time-util.c +@@ -516,7 +516,7 @@ char *format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) { + t = b; + } + +- n = MIN((size_t) k, l); ++ n = MIN((size_t) k, l-1); + + l -= n; + p += n; +diff --git a/src/test/test-time-util.c b/src/test/test-time-util.c +index d05bb61..0761653 100644 +--- a/src/test/test-time-util.c ++++ b/src/test/test-time-util.c +@@ -241,6 +241,11 @@ static void test_format_timespan(usec_t accuracy) { + test_format_timespan_one(500 * USEC_PER_MSEC, accuracy); + test_format_timespan_one(9*USEC_PER_YEAR/5 - 23, accuracy); + test_format_timespan_one(USEC_INFINITY, accuracy); ++ ++ /* See issue #23928. */ ++ _cleanup_free_ char *buf; ++ assert_se(buf = new(char, 5)); ++ assert_se(buf == format_timespan(buf, 5, 100005, 1000)); + } + + static void test_timezone_is_valid(void) { +-- +2.27.0 + diff --git a/backport-test-use-cap_last_cap-for-max-supported.patch b/backport-test-use-cap_last_cap-for-max-supported.patch new file mode 100644 index 0000000..02f9f53 --- /dev/null +++ b/backport-test-use-cap_last_cap-for-max-supported.patch @@ -0,0 +1,128 @@ +From ebc815cd1c647faa934a446ceea91ff4bc9dffa4 Mon Sep 17 00:00:00 2001 +From: Dan Streetman +Date: Wed, 25 Nov 2020 15:22:24 -0500 +Subject: [PATCH] test: use cap_last_cap() for max supported cap number, not + capability_list_length() + +This test assumes capability_list_length() is an invalid cap number, +but that isn't true if the running kernel supports more caps than we were +compiled with, which results in the test failing. + +Instead use cap_last_cap() + 1. + +If cap_last_cap() is 63, there are no more 'invalid' cap numbers to test with, +so the invalid cap number test part is skipped. + +Reference:https://github.com/systemd/systemd/commit/ebc815cd1c647faa934a446ceea91ff4bc9dffa4 +Conflict:NA +--- + src/basic/cap-list.c | 3 ++ + src/test/test-cap-list.c | 62 +++++++++++++++++++++------------------- + 2 files changed, 36 insertions(+), 29 deletions(-) + +diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c +index 1e783a6f29dd..d295a635ca9b 100644 +--- a/src/basic/cap-list.c ++++ b/src/basic/cap-list.c +@@ -50,6 +50,9 @@ int capability_from_name(const char *name) { + return sc->id; + } + ++/* This is the number of capability names we are *compiled* with. ++ * For the max capability number of the currently-running kernel, ++ * use cap_last_cap(). */ + int capability_list_length(void) { + return (int) ELEMENTSOF(capability_names); + } +diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c +index c5f429d05272..c4b40f34faca 100644 +--- a/src/test/test-cap-list.c ++++ b/src/test/test-cap-list.c +@@ -55,7 +55,7 @@ static void test_cap_list(void) { + + static void test_capability_set_one(uint64_t c, const char *t) { + _cleanup_free_ char *t1 = NULL; +- uint64_t c1, c_masked = c & ((UINT64_C(1) << capability_list_length()) - 1); ++ uint64_t c1, c_masked = c & all_capabilities(); + + assert_se(capability_set_to_string_alloc(c, &t1) == 0); + assert_se(streq(t1, t)); +@@ -70,7 +70,7 @@ static void test_capability_set_one(uint64_t c, const char *t) { + assert_se(c1 == c_masked); + } + +-static void test_capability_set(void) { ++static void test_capability_set_from_string(void) { + uint64_t c; + + assert_se(capability_set_from_string(NULL, &c) == 0); +@@ -87,38 +87,42 @@ static void test_capability_set(void) { + + assert_se(capability_set_from_string("0 1 2 3", &c) == 0); + assert_se(c == (UINT64_C(1) << 4) - 1); ++} ++ ++static void test_capability_set_to_string(uint64_t invalid_cap_set) { ++ uint64_t c; + +- test_capability_set_one(0, ""); +- test_capability_set_one( +- UINT64_C(1) << CAP_DAC_OVERRIDE, +- "cap_dac_override"); +- test_capability_set_one( +- UINT64_C(1) << CAP_DAC_OVERRIDE | +- UINT64_C(1) << capability_list_length(), +- "cap_dac_override"); +- test_capability_set_one( +- UINT64_C(1) << capability_list_length(), ""); +- test_capability_set_one( +- UINT64_C(1) << CAP_CHOWN | +- UINT64_C(1) << CAP_DAC_OVERRIDE | +- UINT64_C(1) << CAP_DAC_READ_SEARCH | +- UINT64_C(1) << CAP_FOWNER | +- UINT64_C(1) << CAP_SETGID | +- UINT64_C(1) << CAP_SETUID | +- UINT64_C(1) << CAP_SYS_PTRACE | +- UINT64_C(1) << CAP_SYS_ADMIN | +- UINT64_C(1) << CAP_AUDIT_CONTROL | +- UINT64_C(1) << CAP_MAC_OVERRIDE | +- UINT64_C(1) << CAP_SYSLOG | +- UINT64_C(1) << (capability_list_length() + 1), +- "cap_chown cap_dac_override cap_dac_read_search cap_fowner " +- "cap_setgid cap_setuid cap_sys_ptrace cap_sys_admin " +- "cap_audit_control cap_mac_override cap_syslog"); ++ test_capability_set_one(invalid_cap_set, ""); ++ ++ c = (UINT64_C(1) << CAP_DAC_OVERRIDE | invalid_cap_set); ++ test_capability_set_one(c, "cap_dac_override"); ++ ++ c = (UINT64_C(1) << CAP_CHOWN | ++ UINT64_C(1) << CAP_DAC_OVERRIDE | ++ UINT64_C(1) << CAP_DAC_READ_SEARCH | ++ UINT64_C(1) << CAP_FOWNER | ++ UINT64_C(1) << CAP_SETGID | ++ UINT64_C(1) << CAP_SETUID | ++ UINT64_C(1) << CAP_SYS_PTRACE | ++ UINT64_C(1) << CAP_SYS_ADMIN | ++ UINT64_C(1) << CAP_AUDIT_CONTROL | ++ UINT64_C(1) << CAP_MAC_OVERRIDE | ++ UINT64_C(1) << CAP_SYSLOG | ++ invalid_cap_set); ++ test_capability_set_one(c, ("cap_chown cap_dac_override cap_dac_read_search cap_fowner " ++ "cap_setgid cap_setuid cap_sys_ptrace cap_sys_admin " ++ "cap_audit_control cap_mac_override cap_syslog")); + } + + int main(int argc, char *argv[]) { + test_cap_list(); +- test_capability_set(); ++ test_capability_set_from_string(); ++ test_capability_set_to_string(0); ++ ++ /* once the kernel supports 63 caps, there are no 'invalid' numbers ++ * for us to test with */ ++ if (cap_last_cap() < 63) ++ test_capability_set_to_string(all_capabilities() + 1); + + return 0; + } diff --git a/systemd.spec b/systemd.spec index f5ebd25..09257ae 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 57 +Release: 58 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -173,6 +173,9 @@ Patch0123: backport-core-do-not-serialize-mounts-and-automounts-for-swit.pa Patch0124: backport-journal-add-some-careful-overflow-checking.patch Patch0125: backport-network-fix-an-infinite-loop.patch Patch0126: backport-sd-device-use-right-type-for-usec_initialized.patch +Patch0127: backport-fix-CVE-2022-3821.patch +Patch0128: backport-cap-list-parse-numerical-capabilities.patch +Patch0129: backport-test-use-cap_last_cap-for-max-supported.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1678,6 +1681,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Mon Nov 7 2022 yangmingtai - 243-58 +- fix CVE-2022-3821 and backport patch to fix ci failed + * Tue Oct 18 2022 yangmingtai - 243-57 - DESC:sync community patches -- Gitee From f13e9d98b33cb2175f29d7c0e08b63f40eca776d Mon Sep 17 00:00:00 2001 From: h30032433 Date: Tue, 14 Mar 2023 12:01:18 +0800 Subject: [PATCH 38/38] fix CVE-2023-26604 --- ...nt-all-pager-variables-for-systemctl.patch | 47 ++++ ...-share-description-of-SYSTEMD_COLORS.patch | 79 ++++++ ...er-secure-when-under-euid-is-changed.patch | 180 ++++++++++++ ...LESSSECURE-whenver-we-invoke-a-pager.patch | 113 ++++++++ ...gin-always-test-sd_pid_get_owner_uid.patch | 263 ++++++++++++++++++ systemd.spec | 10 +- 6 files changed, 691 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2023-26604-man-document-all-pager-variables-for-systemctl.patch create mode 100644 backport-CVE-2023-26604-man-share-description-of-SYSTEMD_COLORS.patch create mode 100644 backport-CVE-2023-26604-pager-make-pager-secure-when-under-euid-is-changed.patch create mode 100644 backport-CVE-2023-26604-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch create mode 100644 backport-CVE-2023-26604-test-login-always-test-sd_pid_get_owner_uid.patch diff --git a/backport-CVE-2023-26604-man-document-all-pager-variables-for-systemctl.patch b/backport-CVE-2023-26604-man-document-all-pager-variables-for-systemctl.patch new file mode 100644 index 0000000..5acfc5c --- /dev/null +++ b/backport-CVE-2023-26604-man-document-all-pager-variables-for-systemctl.patch @@ -0,0 +1,47 @@ +From 3d58bfc01c9283eded77736990ea09b0ee4f6e23 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 24 Nov 2019 13:59:32 +0100 +Subject: [PATCH] man: document all pager variables for systemctl and systemd + +In those two pages, we need to include individual entries with xi:include to +merge the list less-variables.xml with the other entries, which is obviously +error prone. All variables are supported in both tools so add them. +--- + man/systemctl.xml | 2 ++ + man/systemd.xml | 7 +++++-- + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/man/systemctl.xml b/man/systemctl.xml +index fb0ca46620..3d86f7dffa 100644 +--- a/man/systemctl.xml ++++ b/man/systemctl.xml +@@ -2161,6 +2161,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err + + + ++ ++ + + + +diff --git a/man/systemd.xml b/man/systemd.xml +index 9b2d5ac280..bde79d56fd 100644 +--- a/man/systemd.xml ++++ b/man/systemd.xml +@@ -669,8 +669,11 @@ + script runlevel link farms. + + +- +- ++ ++ ++ ++ ++ + + + $LISTEN_PID +-- +2.33.0 + diff --git a/backport-CVE-2023-26604-man-share-description-of-SYSTEMD_COLORS.patch b/backport-CVE-2023-26604-man-share-description-of-SYSTEMD_COLORS.patch new file mode 100644 index 0000000..0749873 --- /dev/null +++ b/backport-CVE-2023-26604-man-share-description-of-SYSTEMD_COLORS.patch @@ -0,0 +1,79 @@ +From 339bf2076b3294e5f7b59e84c59ba8c55ded3c25 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 15 Nov 2019 11:59:34 +0100 +Subject: [PATCH] man: share description of $SYSTEMD_COLORS in other tools + +It was only described in systemd(1), making it hard to discover. +Fixes #13561. + +The same for $SYSTEMD_URLIFY. + +I think all the tools whose man pages include less-variables.xml support +those variables. +--- + man/less-variables.xml | 20 +++++++++++++++++++- + man/systemd.xml | 19 ++----------------- + 2 files changed, 21 insertions(+), 18 deletions(-) + +diff --git a/man/less-variables.xml b/man/less-variables.xml +index 38cb18be2e..8a701277b6 100644 +--- a/man/less-variables.xml ++++ b/man/less-variables.xml +@@ -64,5 +64,23 @@ + the invoking terminal is determined to be UTF-8 compatible). + + +- ++ ++ $SYSTEMD_COLORS ++ ++ The value must be a boolean. Controls whether colorized output should be ++ generated. This can be specified to override the decision that systemd makes based ++ on $TERM and what the console is connected to. ++ ++ ++ ++ ++ $SYSTEMD_URLIFY ++ ++ The value must be a boolean. Controls whether clickable links should be generated in ++ the output for terminal emulators supporting this. This can be specified to override the decision that ++ systemd makes based on $TERM and other conditions. ++ ++ ++ ++ + +diff --git a/man/systemd.xml b/man/systemd.xml +index 957d37dcd9..5caf54b330 100644 +--- a/man/systemd.xml ++++ b/man/systemd.xml +@@ -870,23 +870,8 @@ + script runlevel link farms. + + +- +- $SYSTEMD_COLORS +- +- The value must be a boolean. Controls whether colorized output should be +- generated. This can be specified to override the decision that systemd +- makes based on $TERM and what the console is connected to. +- +- +- +- +- $SYSTEMD_URLIFY +- +- The value must be a boolean. Controls whether clickable links should be generated in the output +- for terminal emulators supporting this. This can be specified to override the decision that +- systemd makes based on $TERM and other conditions. +- +- ++ ++ + + + $LISTEN_PID +-- +2.33.0 + diff --git a/backport-CVE-2023-26604-pager-make-pager-secure-when-under-euid-is-changed.patch b/backport-CVE-2023-26604-pager-make-pager-secure-when-under-euid-is-changed.patch new file mode 100644 index 0000000..20defa6 --- /dev/null +++ b/backport-CVE-2023-26604-pager-make-pager-secure-when-under-euid-is-changed.patch @@ -0,0 +1,180 @@ +From 0a42426d797406b4b01a0d9c13bb759c2629d108 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 7 Oct 2020 11:15:05 +0200 +Subject: [PATCH 3/3] pager: make pager secure when under euid is changed or + explicitly requested + +The variable is renamed to SYSTEMD_PAGERSECURE (because it's not just about +less now), and we automatically enable secure mode in certain cases, but not +otherwise. + +This approach is more nuanced, but should provide a better experience for +users: + +- Previusly we would set LESSSECURE=1 and trust the pager to make use of + it. But this has an effect only on less. We need to not start pagers which + are insecure when in secure mode. In particular more is like that and is a + very popular pager. + +- We don't enable secure mode always, which means that those other pagers can + reasonably used. + +- We do the right thing by default, but the user has ultimate control by + setting SYSTEMD_PAGERSECURE. + +Fixes #5666. + +v2: +- also check $PKEXEC_UID + +v3: +- use 'sd_pid_get_owner_uid() != geteuid()' as the condition +--- + man/less-variables.xml | 30 ++++++++++++++++---- + src/shared/pager.c | 63 ++++++++++++++++++++++++++++-------------- + 2 files changed, 66 insertions(+), 27 deletions(-) + +diff --git a/man/less-variables.xml b/man/less-variables.xml +index c52511ca8e..049e9f75d7 100644 +--- a/man/less-variables.xml ++++ b/man/less-variables.xml +@@ -65,12 +65,30 @@ + + + +- $SYSTEMD_LESSSECURE +- +- Takes a boolean argument. Overrides the $LESSSECURE environment +- variable when invoking the pager, which controls the "secure" mode of less (which disables commands +- such as | which allow to easily shell out to external command lines). By default +- less secure mode is enabled, with this setting it may be disabled. ++ $SYSTEMD_PAGERSECURE ++ ++ Takes a boolean argument. When true, the "secure" mode of the pager is enabled; if ++ false, disabled. If $SYSTEMD_PAGERSECURE is not set at all, secure mode is enabled ++ if the effective UID is not the same as the owner of the login session, see geteuid2 and ++ sd_pid_get_owner_uid3. ++ In secure mode, will be set when invoking the pager, and the pager shall ++ disable commands that open or create new files or start new subprocesses. When ++ $SYSTEMD_PAGERSECURE is not set at all, pagers which are not known to implement ++ secure mode will not be used. (Currently only ++ less1 implements ++ secure mode.) ++ ++ Note: when commands are invoked with elevated privileges, for example under sudo8 or ++ pkexec1, care ++ must be taken to ensure that unintended interactive features are not enabled. "Secure" mode for the ++ pager may be enabled automatically as describe above. Setting SYSTEMD_PAGERSECURE=0 ++ or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note ++ that if the $SYSTEMD_PAGER or $PAGER variables are to be ++ honoured, $SYSTEMD_PAGERSECURE must be set too. It might be reasonable to completly ++ disable the pager using instead. + + + +diff --git a/src/shared/pager.c b/src/shared/pager.c +index 9c21881241..9a14d44d69 100644 +--- a/src/shared/pager.c ++++ b/src/shared/pager.c +@@ -8,6 +8,8 @@ + #include + #include + ++#include "sd-login.h" ++ + #include "copy.h" + #include "env-util.h" + #include "fd-util.h" +@@ -165,25 +167,42 @@ int pager_open(PagerFlags flags) { + } + + /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out +- * privileged stuff. */ +- r = getenv_bool("SYSTEMD_LESSSECURE"); +- if (r == 0) { /* Remove env var if off */ +- if (unsetenv("LESSSECURE") < 0) { +- log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m"); +- _exit(EXIT_FAILURE); +- } +- } else { +- /* Set env var otherwise */ ++ * privileged stuff. If the user set $SYSTEMD_PAGERSECURE, trust their configuration of the ++ * pager. If they didn't, use secure mode when under euid is changed. If $SYSTEMD_PAGERSECURE ++ * wasn't explicitly set, and we autodetect the need for secure mode, only use the pager we ++ * know to be good. */ ++ int use_secure_mode = getenv_bool("SYSTEMD_PAGERSECURE"); ++ bool trust_pager = use_secure_mode >= 0; ++ if (use_secure_mode == -ENXIO) { ++ uid_t uid; ++ ++ r = sd_pid_get_owner_uid(0, &uid); + if (r < 0) +- log_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m"); ++ log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m"); + +- if (setenv("LESSSECURE", "1", 1) < 0) { +- log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m"); +- _exit(EXIT_FAILURE); +- } ++ use_secure_mode = r < 0 || uid != geteuid(); ++ ++ } else if (use_secure_mode < 0) { ++ log_warning_errno(use_secure_mode, "Unable to parse $SYSTEMD_PAGERSECURE, assuming true: %m"); ++ use_secure_mode = true; + } + +- if (pager_args) { ++ /* We generally always set variables used by less, even if we end up using a different pager. ++ * They shouldn't hurt in any case, and ideally other pagers would look at them too. */ ++ if (use_secure_mode) ++ r = setenv("LESSSECURE", "1", 1); ++ else ++ r = unsetenv("LESSSECURE"); ++ if (r < 0) { ++ log_error_errno(errno, "Failed to adjust environment variable LESSSECURE: %m"); ++ _exit(EXIT_FAILURE); ++ } ++ ++ if (trust_pager && pager_args) { /* The pager config might be set globally, and we cannot ++ * know if the user adjusted it to be appropriate for the ++ * secure mode. Thus, start the pager specified through ++ * envvars only when $SYSTEMD_PAGERSECURE was explicitly set ++ * as well. */ + r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false); + if (r < 0) { + log_error_errno(r, "Failed to write pager name to socket: %m"); +@@ -195,13 +214,14 @@ int pager_open(PagerFlags flags) { + "Failed to execute '%s', using fallback pagers: %m", pager_args[0]); + } + +- /* Debian's alternatives command for pagers is +- * called 'pager'. Note that we do not call +- * sensible-pagers here, since that is just a +- * shell script that implements a logic that +- * is similar to this one anyway, but is +- * Debian-specific. */ ++ /* Debian's alternatives command for pagers is called 'pager'. Note that we do not call ++ * sensible-pagers here, since that is just a shell script that implements a logic that is ++ * similar to this one anyway, but is Debian-specific. */ + FOREACH_STRING(exe, "pager", "less", "more") { ++ /* Only less implements secure mode right now. */ ++ if (use_secure_mode && !streq(exe, "less")) ++ continue; ++ + r = loop_write(exe_name_pipe[1], exe, strlen(exe) + 1, false); + if (r < 0) { + log_error_errno(r, "Failed to write pager name to socket: %m"); +@@ -212,6 +232,7 @@ int pager_open(PagerFlags flags) { + "Failed to execute '%s', using next fallback pager: %m", exe); + } + ++ /* Our builtin is also very secure. */ + r = loop_write(exe_name_pipe[1], "(built-in)", strlen("(built-in)") + 1, false); + if (r < 0) { + log_error_errno(r, "Failed to write pager name to socket: %m"); +-- +2.33.0 + diff --git a/backport-CVE-2023-26604-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch b/backport-CVE-2023-26604-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch new file mode 100644 index 0000000..e2c5978 --- /dev/null +++ b/backport-CVE-2023-26604-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch @@ -0,0 +1,113 @@ +From 612ebf6c913dd0e4197c44909cb3157f5c51a2f0 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 31 Aug 2020 19:37:13 +0200 +Subject: [PATCH 1/3] pager: set $LESSSECURE whenver we invoke a pager + +Some extra safety when invoked via "sudo". With this we address a +genuine design flaw of sudo, and we shouldn't need to deal with this. +But it's still a good idea to disable this surface given how exotic it +is. + +Prompted by #5666 +--- + man/less-variables.xml | 9 +++++++++ + man/systemctl.xml | 1 + + man/systemd.xml | 1 + + src/shared/pager.c | 23 +++++++++++++++++++++-- + 4 files changed, 32 insertions(+), 2 deletions(-) + +diff --git a/man/less-variables.xml b/man/less-variables.xml +index 08e513c99f..c52511ca8e 100644 +--- a/man/less-variables.xml ++++ b/man/less-variables.xml +@@ -64,6 +64,15 @@ + the invoking terminal is determined to be UTF-8 compatible). + + ++ ++ $SYSTEMD_LESSSECURE ++ ++ Takes a boolean argument. Overrides the $LESSSECURE environment ++ variable when invoking the pager, which controls the "secure" mode of less (which disables commands ++ such as | which allow to easily shell out to external command lines). By default ++ less secure mode is enabled, with this setting it may be disabled. ++ ++ + + $SYSTEMD_COLORS + +diff --git a/man/systemctl.xml b/man/systemctl.xml +index 1c55028837..a3f0c3041a 100644 +--- a/man/systemctl.xml ++++ b/man/systemctl.xml +@@ -2240,6 +2240,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err + + + ++ + + + +diff --git a/man/systemd.xml b/man/systemd.xml +index a9040545c2..c92cfef776 100644 +--- a/man/systemd.xml ++++ b/man/systemd.xml +@@ -692,6 +692,7 @@ + + + ++ + + + +diff --git a/src/shared/pager.c b/src/shared/pager.c +index e03be6d23b..9c21881241 100644 +--- a/src/shared/pager.c ++++ b/src/shared/pager.c +@@ -9,6 +9,7 @@ + #include + + #include "copy.h" ++#include "env-util.h" + #include "fd-util.h" + #include "fileio.h" + #include "io-util.h" +@@ -152,8 +153,7 @@ int pager_open(PagerFlags flags) { + _exit(EXIT_FAILURE); + } + +- /* Initialize a good charset for less. This is +- * particularly important if we output UTF-8 ++ /* Initialize a good charset for less. This is particularly important if we output UTF-8 + * characters. */ + less_charset = getenv("SYSTEMD_LESSCHARSET"); + if (!less_charset && is_locale_utf8()) +@@ -164,6 +164,25 @@ int pager_open(PagerFlags flags) { + _exit(EXIT_FAILURE); + } + ++ /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out ++ * privileged stuff. */ ++ r = getenv_bool("SYSTEMD_LESSSECURE"); ++ if (r == 0) { /* Remove env var if off */ ++ if (unsetenv("LESSSECURE") < 0) { ++ log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m"); ++ _exit(EXIT_FAILURE); ++ } ++ } else { ++ /* Set env var otherwise */ ++ if (r < 0) ++ log_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m"); ++ ++ if (setenv("LESSSECURE", "1", 1) < 0) { ++ log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m"); ++ _exit(EXIT_FAILURE); ++ } ++ } ++ + if (pager_args) { + r = loop_write(exe_name_pipe[1], pager_args[0], strlen(pager_args[0]) + 1, false); + if (r < 0) { +-- +2.33.0 + diff --git a/backport-CVE-2023-26604-test-login-always-test-sd_pid_get_owner_uid.patch b/backport-CVE-2023-26604-test-login-always-test-sd_pid_get_owner_uid.patch new file mode 100644 index 0000000..685d257 --- /dev/null +++ b/backport-CVE-2023-26604-test-login-always-test-sd_pid_get_owner_uid.patch @@ -0,0 +1,263 @@ +From 1b5b507cd2d1d7a2b053151abb548475ad9c5c3b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 12 Oct 2020 18:57:32 +0200 +Subject: [PATCH 2/3] test-login: always test sd_pid_get_owner_uid(), modernize + +A long time some function only worked when in a session, and the test +didn't execute them when sd_pid_get_session() failed. Let's always call +them to increase coverage. + +While at it, let's test for ==0 not >=0 where we don't expect the function +to return anything except 0 or error. +--- + src/libsystemd/sd-login/test-login.c | 131 ++++++++++++++------------- + 1 file changed, 70 insertions(+), 61 deletions(-) + +diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c +index c0c77e0471..0494fc77ba 100644 +--- a/src/libsystemd/sd-login/test-login.c ++++ b/src/libsystemd/sd-login/test-login.c +@@ -5,21 +5,22 @@ + #include "sd-login.h" + + #include "alloc-util.h" ++#include "errno-list.h" + #include "fd-util.h" + #include "format-util.h" + #include "log.h" + #include "string-util.h" + #include "strv.h" + #include "time-util.h" +-#include "util.h" ++#include "user-util.h" + + static char* format_uids(char **buf, uid_t* uids, int count) { +- int pos = 0, k, inc; ++ int pos = 0, inc; + size_t size = (DECIMAL_STR_MAX(uid_t) + 1) * count + 1; + + assert_se(*buf = malloc(size)); + +- for (k = 0; k < count; k++) { ++ for (int k = 0; k < count; k++) { + sprintf(*buf + pos, "%s"UID_FMT"%n", k > 0 ? " " : "", uids[k], &inc); + pos += inc; + } +@@ -30,6 +31,10 @@ static char* format_uids(char **buf, uid_t* uids, int count) { + return *buf; + } + ++static const char *e(int r) { ++ return r == 0 ? "OK" : errno_to_name(r); ++} ++ + static void test_login(void) { + _cleanup_close_pair_ int pair[2] = { -1, -1 }; + _cleanup_free_ char *pp = NULL, *qq = NULL, +@@ -39,65 +44,71 @@ static void test_login(void) { + *seat = NULL, *session = NULL, + *unit = NULL, *user_unit = NULL, *slice = NULL; + int r; +- uid_t u, u2; +- char *t, **seats, **sessions; ++ uid_t u, u2 = UID_INVALID; ++ char *t, **seats = NULL, **sessions = NULL; + + r = sd_pid_get_unit(0, &unit); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_pid_get_unit(0, …) → \"%s\"", strna(unit)); ++ log_info("sd_pid_get_unit(0, …) → %s / \"%s\"", e(r), strnull(unit)); ++ assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pid_get_user_unit(0, &user_unit); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_pid_get_user_unit(0, …) → \"%s\"", strna(user_unit)); ++ log_info("sd_pid_get_user_unit(0, …) → %s / \"%s\"", e(r), strnull(user_unit)); ++ assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pid_get_slice(0, &slice); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_pid_get_slice(0, …) → \"%s\"", strna(slice)); ++ log_info("sd_pid_get_slice(0, …) → %s / \"%s\"", e(r), strnull(slice)); ++ assert_se(IN_SET(r, 0, -ENODATA)); ++ ++ r = sd_pid_get_owner_uid(0, &u2); ++ log_info("sd_pid_get_owner_uid(0, …) → %s / "UID_FMT, e(r), u2); ++ assert_se(IN_SET(r, 0, -ENODATA)); + + r = sd_pid_get_session(0, &session); +- if (r < 0) { +- log_warning_errno(r, "sd_pid_get_session(0, …): %m"); +- if (r == -ENODATA) +- log_info("Seems we are not running in a session, skipping some tests."); +- } else { +- log_info("sd_pid_get_session(0, …) → \"%s\"", session); +- +- assert_se(sd_pid_get_owner_uid(0, &u2) == 0); +- log_info("sd_pid_get_owner_uid(0, …) → "UID_FMT, u2); +- +- assert_se(sd_pid_get_cgroup(0, &cgroup) == 0); +- log_info("sd_pid_get_cgroup(0, …) → \"%s\"", cgroup); +- +- r = sd_uid_get_display(u2, &display_session); +- assert_se(r >= 0 || r == -ENODATA); +- log_info("sd_uid_get_display("UID_FMT", …) → \"%s\"", +- u2, strnull(display_session)); +- +- assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0); +- sd_peer_get_session(pair[0], &pp); +- sd_peer_get_session(pair[1], &qq); +- assert_se(streq_ptr(pp, qq)); +- +- r = sd_uid_get_sessions(u2, false, &sessions); ++ log_info("sd_pid_get_session(0, …) → %s / \"%s\"", e(r), strnull(session)); ++ ++ r = sd_pid_get_cgroup(0, &cgroup); ++ log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup)); ++ assert_se(r == 0); ++ ++ r = sd_uid_get_display(u2, &display_session); ++ log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session)); ++ if (u2 == UID_INVALID) ++ assert_se(r == -EINVAL); ++ else ++ assert_se(IN_SET(r, 0, -ENODATA)); ++ ++ assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0); ++ sd_peer_get_session(pair[0], &pp); ++ sd_peer_get_session(pair[1], &qq); ++ assert_se(streq_ptr(pp, qq)); ++ ++ r = sd_uid_get_sessions(u2, false, &sessions); ++ assert_se(t = strv_join(sessions, " ")); ++ log_info("sd_uid_get_sessions("UID_FMT", …) → %s \"%s\"", u2, e(r), t); ++ if (u2 == UID_INVALID) ++ assert_se(r == -EINVAL); ++ else { + assert_se(r >= 0); + assert_se(r == (int) strv_length(sessions)); +- assert_se(t = strv_join(sessions, " ")); +- strv_free(sessions); +- log_info("sd_uid_get_sessions("UID_FMT", …) → [%i] \"%s\"", u2, r, t); +- free(t); ++ } ++ sessions = strv_free(sessions); ++ free(t); + +- assert_se(r == sd_uid_get_sessions(u2, false, NULL)); ++ assert_se(r == sd_uid_get_sessions(u2, false, NULL)); + +- r = sd_uid_get_seats(u2, false, &seats); ++ r = sd_uid_get_seats(u2, false, &seats); ++ assert_se(t = strv_join(seats, " ")); ++ log_info("sd_uid_get_seats("UID_FMT", …) → %s \"%s\"", u2, e(r), t); ++ if (u2 == UID_INVALID) ++ assert_se(r == -EINVAL); ++ else { + assert_se(r >= 0); + assert_se(r == (int) strv_length(seats)); +- assert_se(t = strv_join(seats, " ")); +- strv_free(seats); +- log_info("sd_uid_get_seats("UID_FMT", …) → [%i] \"%s\"", u2, r, t); +- free(t); +- +- assert_se(r == sd_uid_get_seats(u2, false, NULL)); + } ++ seats = strv_free(seats); ++ free(t); ++ ++ assert_se(r == sd_uid_get_seats(u2, false, NULL)); + + if (session) { + r = sd_session_is_active(session); +@@ -109,7 +120,7 @@ static void test_login(void) { + log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r)); + + r = sd_session_get_state(session, &state); +- assert_se(r >= 0); ++ assert_se(r == 0); + log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state); + + assert_se(sd_session_get_uid(session, &u) >= 0); +@@ -123,16 +134,16 @@ static void test_login(void) { + log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class); + + r = sd_session_get_display(session, &display); +- assert_se(r >= 0 || r == -ENODATA); ++ assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display)); + + r = sd_session_get_remote_user(session, &remote_user); +- assert_se(r >= 0 || r == -ENODATA); ++ assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_session_get_remote_user(\"%s\") → \"%s\"", + session, strna(remote_user)); + + r = sd_session_get_remote_host(session, &remote_host); +- assert_se(r >= 0 || r == -ENODATA); ++ assert_se(IN_SET(r, 0, -ENODATA)); + log_info("sd_session_get_remote_host(\"%s\") → \"%s\"", + session, strna(remote_host)); + +@@ -161,7 +172,7 @@ static void test_login(void) { + assert_se(r == -ENODATA); + } + +- assert_se(sd_uid_get_state(u, &state2) >= 0); ++ assert_se(sd_uid_get_state(u, &state2) == 0); + log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2); + } + +@@ -173,11 +184,11 @@ static void test_login(void) { + assert_se(sd_uid_is_on_seat(u, 0, seat) > 0); + + r = sd_seat_get_active(seat, &session2, &u2); +- assert_se(r >= 0); ++ assert_se(r == 0); + log_info("sd_seat_get_active(\"%s\", …) → \"%s\", "UID_FMT, seat, session2, u2); + + r = sd_uid_is_on_seat(u, 1, seat); +- assert_se(r >= 0); ++ assert_se(IN_SET(r, 0, 1)); + assert_se(!!r == streq(session, session2)); + + r = sd_seat_get_sessions(seat, &sessions, &uids, &n); +@@ -185,8 +196,8 @@ static void test_login(void) { + assert_se(r == (int) strv_length(sessions)); + assert_se(t = strv_join(sessions, " ")); + strv_free(sessions); +- log_info("sd_seat_get_sessions(\"%s\", …) → %i, \"%s\", [%i] {%s}", +- seat, r, t, n, format_uids(&buf, uids, n)); ++ log_info("sd_seat_get_sessions(\"%s\", …) → %s, \"%s\", [%u] {%s}", ++ seat, e(r), t, n, format_uids(&buf, uids, n)); + free(t); + + assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r); +@@ -204,7 +215,7 @@ static void test_login(void) { + + r = sd_seat_get_active(NULL, &t, NULL); + assert_se(IN_SET(r, 0, -ENODATA)); +- log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s", strnull(t)); ++ log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s / \"%s\"", e(r), strnull(t)); + free(t); + + r = sd_get_sessions(&sessions); +@@ -244,13 +255,11 @@ static void test_login(void) { + + static void test_monitor(void) { + sd_login_monitor *m = NULL; +- unsigned n; + int r; + +- r = sd_login_monitor_new("session", &m); +- assert_se(r >= 0); ++ assert_se(sd_login_monitor_new("session", &m) == 0); + +- for (n = 0; n < 5; n++) { ++ for (unsigned n = 0; n < 5; n++) { + struct pollfd pollfd = {}; + usec_t timeout, nw; + +-- +2.33.0 + diff --git a/systemd.spec b/systemd.spec index 09257ae..edc97cf 100644 --- a/systemd.spec +++ b/systemd.spec @@ -16,7 +16,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 243 -Release: 58 +Release: 59 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -176,6 +176,11 @@ Patch0126: backport-sd-device-use-right-type-for-usec_initialized.patch Patch0127: backport-fix-CVE-2022-3821.patch Patch0128: backport-cap-list-parse-numerical-capabilities.patch Patch0129: backport-test-use-cap_last_cap-for-max-supported.patch +Patch0130: backport-CVE-2023-26604-man-share-description-of-SYSTEMD_COLORS.patch +Patch0131: backport-CVE-2023-26604-man-document-all-pager-variables-for-systemctl.patch +Patch0132: backport-CVE-2023-26604-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch +Patch0133: backport-CVE-2023-26604-test-login-always-test-sd_pid_get_owner_uid.patch +Patch0134: backport-CVE-2023-26604-pager-make-pager-secure-when-under-euid-is-changed.patch #openEuler Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch @@ -1681,6 +1686,9 @@ fi %exclude /usr/share/man/man3/* %changelog +* Tue Mar 14 2023 huyubiao - 243-59 +- fix CVE-2023-26604 + * Mon Nov 7 2022 yangmingtai - 243-58 - fix CVE-2022-3821 and backport patch to fix ci failed -- Gitee