diff --git a/1002-core-fix-a-null-reference-case-in-load_from_path.patch b/1002-core-fix-a-null-reference-case-in-load_from_path.patch new file mode 100644 index 0000000000000000000000000000000000000000..9da687ecf5cd557f0b85d1283c93a63807c33073 --- /dev/null +++ b/1002-core-fix-a-null-reference-case-in-load_from_path.patch @@ -0,0 +1,34 @@ +From 3262f6c71165c309605dd87c88c7daf7dd300e6f Mon Sep 17 00:00:00 2001 +From: Wen Yang +Date: Mon, 1 Jun 2020 17:06:53 +0800 +Subject: [PATCH] core: fix a null reference case in load_from_path() + +--- + 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 33fdb82754..be5d3c2816 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -4415,7 +4415,6 @@ static int load_from_path(Unit *u, const char *path) { + r = open_follow(&filename, &f, symlink_names, &id); + if (r >= 0) + break; +- filename = mfree(filename); + + /* ENOENT means that the file is missing or is a dangling symlink. + * ENOTDIR means that one of paths we expect to be is a directory +@@ -4424,7 +4423,8 @@ static int load_from_path(Unit *u, const char *path) { + */ + if (r == -EACCES) + log_debug_errno(r, "Cannot access \"%s\": %m", filename); +- else if (!IN_SET(r, -ENOENT, -ENOTDIR)) ++ filename = mfree(filename); ++ if (!IN_SET(r, -ENOENT, -ENOTDIR)) + return r; + + /* Empty the symlink names for the next run */ +-- +2.18.1 + diff --git a/1003-sysctl-Don-t-pass-null-directive-argument-to-s.patch b/1003-sysctl-Don-t-pass-null-directive-argument-to-s.patch new file mode 100644 index 0000000000000000000000000000000000000000..ebf2592bd7cfa60694b7d6512ee194680c4b7a22 --- /dev/null +++ b/1003-sysctl-Don-t-pass-null-directive-argument-to-s.patch @@ -0,0 +1,30 @@ +From 74dbb8676dcc35c9b1431254142b3cf24ac7e1a4 Mon Sep 17 00:00:00 2001 +From: Khem Raj +Date: Sun, 16 Dec 2018 20:53:38 -0800 +Subject: [PATCH] sysctl: Don't pass null directive argument to '%s' + +value pointer here is always NULL but subsequent use of that pointer +with a %s format will always be NULL, printing p instead would be a +valid string + +Signed-off-by: Khem Raj +--- + src/sysctl/sysctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/sysctl/sysctl.c b/src/sysctl/sysctl.c +index 0151f7dabe..61447bb72e 100644 +--- a/src/sysctl/sysctl.c ++++ b/src/sysctl/sysctl.c +@@ -112,7 +112,7 @@ static int parse_file(OrderedHashmap *sysctl_options, const char *path, bool ign + + value = strchr(p, '='); + if (!value) { +- log_error("Line is not an assignment at '%s:%u': %s", path, c, value); ++ log_error("Line is not an assignment at '%s:%u': %s", path, c, p); + + if (r == 0) + r = -EINVAL; +-- +2.18.1 + diff --git a/1004-test-use-builddir-systemd-runtest.env-to-set-SYSTEMD.patch b/1004-test-use-builddir-systemd-runtest.env-to-set-SYSTEMD.patch new file mode 100644 index 0000000000000000000000000000000000000000..f5edab547b0275f0f68f495c70256d30a26fade4 --- /dev/null +++ b/1004-test-use-builddir-systemd-runtest.env-to-set-SYSTEMD.patch @@ -0,0 +1,171 @@ +From 89bb4cdeae7903e58fe11431fb51f8d995deb0a3 Mon Sep 17 00:00:00 2001 +From: Filipe Brandenburger +Date: Tue, 11 Sep 2018 23:55:02 -0700 +Subject: [PATCH] test: use ${builddir}/systemd-runtest.env to set + $SYSTEMD_TEST_DATA + +This simplifies get_testdata_dir() to simply checking for an environment +variable, with an additional function to locate a systemd-runtest.env file in +the same directory as the test binary and reading environment variable +assignments from that file if it exists. + +This makes it possible to: +- Run `ninja test` from the build dir and have it use ${srcdir}/test for + test unit definitions. +- Run a test directly, such as `build/test-execute` and have it locate + them correctly. +- Run installed tests (from systemd-tests package) and locate the test + units in the installed location (/usr/lib/systemd/tests/testdata), in + which case the absence of the systemd-runtest.env file will have + get_testdata_dir() use the installed location hardcoded into the + binaries. + +Explicit setting of $SYSTEMD_TEST_DATA still overrides the contents of +systemd-runtest.env. + +Signed-off-by: Wen Yang +(cherry picked from commit e2d413707fc68ed033a83e10a055ca638a1e1e18) +--- + meson.build | 10 ++++++- + src/shared/tests.c | 67 ++++++++++++++++++++++------------------------ + 2 files changed, 41 insertions(+), 36 deletions(-) + +diff --git a/meson.build b/meson.build +index 0ba3f924ea..8c4549640b 100644 +--- a/meson.build ++++ b/meson.build +@@ -213,6 +213,7 @@ conf.set_quoted('SYSTEM_SHUTDOWN_PATH', systemshutdowndir) + conf.set_quoted('SYSTEM_SLEEP_PATH', systemsleepdir) + conf.set_quoted('SYSTEMD_KBD_MODEL_MAP', join_paths(pkgdatadir, 'kbd-model-map')) + conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP', join_paths(pkgdatadir, 'language-fallback-map')) ++conf.set_quoted('SYSTEMD_TEST_DATA', join_paths(testsdir, 'testdata')) + conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir) + conf.set_quoted('POLKIT_AGENT_BINARY_PATH', join_paths(bindir, 'pkttyagent')) + conf.set_quoted('LIBDIR', libdir) +@@ -229,7 +230,6 @@ conf.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_ + conf.set_quoted('MEMORY_ACCOUNTING_DEFAULT_YES_NO', memory_accounting_default ? 'yes' : 'no') + + conf.set_quoted('ABS_BUILD_DIR', meson.build_root()) +-conf.set_quoted('ABS_SRC_DIR', meson.source_root()) + + substs.set('prefix', prefixdir) + substs.set('exec_prefix', prefixdir) +@@ -2592,6 +2592,14 @@ executable('systemd-sulogin-shell', + + ############################################################ + ++custom_target( ++ 'systemd-runtest.env', ++ output : 'systemd-runtest.env', ++ command : ['sh', '-c', '{ ' + ++ 'echo SYSTEMD_TEST_DATA=@0@; '.format(join_paths(meson.current_source_dir(), 'test')) + ++ '} >@OUTPUT@'], ++ build_by_default : true) ++ + foreach tuple : tests + sources = tuple[0] + link_with = tuple[1].length() > 0 ? tuple[1] : [libshared] +diff --git a/src/shared/tests.c b/src/shared/tests.c +index 100b62b9b0..102b343fef 100644 +--- a/src/shared/tests.c ++++ b/src/shared/tests.c +@@ -6,8 +6,11 @@ + #include + #include + +-#include "tests.h" ++#include "alloc-util.h" ++#include "fileio.h" + #include "path-util.h" ++#include "strv.h" ++#include "tests.h" + + char* setup_fake_runtime_dir(void) { + char t[] = "/tmp/fake-xdg-runtime-XXXXXX", *p; +@@ -19,55 +22,49 @@ char* setup_fake_runtime_dir(void) { + return p; + } + +-bool test_is_running_from_builddir(char **exedir) { ++static void load_testdata_env(void) { ++ static bool called = false; + _cleanup_free_ char *s = NULL; +- bool r; ++ _cleanup_free_ char *envpath = NULL; ++ _cleanup_strv_free_ char **pairs = NULL; ++ char **k, **v; + +- /* Check if we're running from the builddir. Optionally, this returns +- * the path to the directory where the binary is located. */ ++ if (called) ++ return; ++ called = true; + + assert_se(readlink_and_make_absolute("/proc/self/exe", &s) >= 0); +- r = path_startswith(s, ABS_BUILD_DIR); ++ dirname(s); + +- if (exedir) { +- dirname(s); +- *exedir = TAKE_PTR(s); +- } ++ envpath = path_join(NULL, s, "systemd-runtest.env"); ++ if (load_env_file_pairs(NULL, envpath, NULL, &pairs) < 0) ++ return; + +- return r; ++ STRV_FOREACH_PAIR(k, v, pairs) ++ setenv(*k, *v, 0); ++} ++ ++bool test_is_running_from_builddir(char **exedir) { ++ load_testdata_env(); ++ ++ return !!getenv("SYSTEMD_TEST_DATA"); + } + + const char* get_testdata_dir(void) { + const char *env; +- /* convenience: caller does not need to free result */ +- static char testdir[PATH_MAX]; ++ ++ load_testdata_env(); + + /* if the env var is set, use that */ + env = getenv("SYSTEMD_TEST_DATA"); +- testdir[sizeof(testdir) - 1] = '\0'; +- if (env) { +- if (access(env, F_OK) < 0) { +- fputs("ERROR: $SYSTEMD_TEST_DATA directory does not exist\n", stderr); +- exit(EXIT_FAILURE); +- } +- strncpy(testdir, env, sizeof(testdir) - 1); +- } else { +- _cleanup_free_ char *exedir = NULL; +- +- /* Check if we're running from the builddir. If so, use the compiled in path. */ +- if (test_is_running_from_builddir(&exedir)) +- assert_se(snprintf(testdir, sizeof(testdir), "%s/test", ABS_SRC_DIR) > 0); +- else +- /* Try relative path, according to the install-test layout */ +- assert_se(snprintf(testdir, sizeof(testdir), "%s/testdata", exedir) > 0); +- +- if (access(testdir, F_OK) < 0) { +- fputs("ERROR: Cannot find testdata directory, set $SYSTEMD_TEST_DATA\n", stderr); +- exit(EXIT_FAILURE); +- } ++ if (!env) ++ env = SYSTEMD_TEST_DATA; ++ if (access(env, F_OK) < 0) { ++ fprintf(stderr, "ERROR: $SYSTEMD_TEST_DATA directory [%s] does not exist\n", env); ++ exit(EXIT_FAILURE); + } + +- return testdir; ++ return env; + } + + void test_setup_logging(int level) { +-- +2.18.1 + diff --git a/1005-test-use-builddir-systemd-runtest.env-for-SYSTEMD_CA.patch b/1005-test-use-builddir-systemd-runtest.env-for-SYSTEMD_CA.patch new file mode 100644 index 0000000000000000000000000000000000000000..b74edb73d705a728f0bee37116eab207833bba0e --- /dev/null +++ b/1005-test-use-builddir-systemd-runtest.env-for-SYSTEMD_CA.patch @@ -0,0 +1,139 @@ +From c5e249d9eaabaeebc3ac447462d50adec3245f2f Mon Sep 17 00:00:00 2001 +From: Filipe Brandenburger +Date: Wed, 12 Sep 2018 00:23:40 -0700 +Subject: [PATCH] test: use ${builddir}/systemd-runtest.env for + $SYSTEMD_CATALOG_DIR + +This makes it so that tests no longer need to know the absolute paths to the +source and build dirs, instead using the systemd-runtest.env file to get these +paths when running from the build tree. + +Confirmed that test-catalog works on `ninja test`, when called standalone and +also when the environment file is not present, in which case it will use the +installed location under /usr/lib/systemd/catalog. + +The location can now also be overridden for this test by setting the +$SYSTEMD_CATALOG_DIR environment variable. + +Signed-off-by: Wen Yang +(cherry picked from commit fef716b28be6e866b8afe995805d5ebe2af6bbfa) +--- + meson.build | 4 ++-- + src/journal/test-catalog.c | 6 +----- + src/shared/tests.c | 22 ++++++++++++++++------ + src/shared/tests.h | 2 +- + src/test/meson.build | 3 +-- + 5 files changed, 21 insertions(+), 16 deletions(-) + +diff --git a/meson.build b/meson.build +index 8c4549640b..cf6990a50e 100644 +--- a/meson.build ++++ b/meson.build +@@ -214,6 +214,7 @@ conf.set_quoted('SYSTEM_SLEEP_PATH', systemsleepdir) + conf.set_quoted('SYSTEMD_KBD_MODEL_MAP', join_paths(pkgdatadir, 'kbd-model-map')) + conf.set_quoted('SYSTEMD_LANGUAGE_FALLBACK_MAP', join_paths(pkgdatadir, 'language-fallback-map')) + conf.set_quoted('SYSTEMD_TEST_DATA', join_paths(testsdir, 'testdata')) ++conf.set_quoted('SYSTEMD_CATALOG_DIR', catalogdir) + conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir) + conf.set_quoted('POLKIT_AGENT_BINARY_PATH', join_paths(bindir, 'pkttyagent')) + conf.set_quoted('LIBDIR', libdir) +@@ -229,8 +230,6 @@ conf.set_quoted('DOCUMENT_ROOT', join_paths(pkgdata + conf.set('MEMORY_ACCOUNTING_DEFAULT', memory_accounting_default ? 'true' : 'false') + conf.set_quoted('MEMORY_ACCOUNTING_DEFAULT_YES_NO', memory_accounting_default ? 'yes' : 'no') + +-conf.set_quoted('ABS_BUILD_DIR', meson.build_root()) +- + substs.set('prefix', prefixdir) + substs.set('exec_prefix', prefixdir) + substs.set('libdir', libdir) +@@ -2597,6 +2596,7 @@ custom_target( + output : 'systemd-runtest.env', + command : ['sh', '-c', '{ ' + + 'echo SYSTEMD_TEST_DATA=@0@; '.format(join_paths(meson.current_source_dir(), 'test')) + ++ 'echo SYSTEMD_CATALOG_DIR=@0@; '.format(join_paths(meson.current_build_dir(), 'catalog')) + + '} >@OUTPUT@'], + build_by_default : true) + +diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c +index 0c4da29f31..d9ee557b9c 100644 +--- a/src/journal/test-catalog.c ++++ b/src/journal/test-catalog.c +@@ -212,11 +212,7 @@ int main(int argc, char *argv[]) { + + /* If test-catalog is located at the build directory, then use catalogs in that. + * If it is not, e.g. installed by systemd-tests package, then use installed catalogs. */ +- if (test_is_running_from_builddir(NULL)) { +- assert_se(catalog_dir = path_join(NULL, ABS_BUILD_DIR, "catalog")); +- catalog_dirs = STRV_MAKE(catalog_dir); +- } else +- catalog_dirs = STRV_MAKE(CATALOG_DIR); ++ catalog_dirs = STRV_MAKE(get_catalog_dir()); + + assert_se(access(catalog_dirs[0], F_OK) >= 0); + log_notice("Using catalog directory '%s'", catalog_dirs[0]); +diff --git a/src/shared/tests.c b/src/shared/tests.c +index 102b343fef..7bd6f806b9 100644 +--- a/src/shared/tests.c ++++ b/src/shared/tests.c +@@ -44,12 +44,6 @@ static void load_testdata_env(void) { + setenv(*k, *v, 0); + } + +-bool test_is_running_from_builddir(char **exedir) { +- load_testdata_env(); +- +- return !!getenv("SYSTEMD_TEST_DATA"); +-} +- + const char* get_testdata_dir(void) { + const char *env; + +@@ -72,3 +66,19 @@ void test_setup_logging(int level) { + log_parse_environment(); + log_open(); + } ++ ++const char* get_catalog_dir(void) { ++ const char *env; ++ ++ load_testdata_env(); ++ ++ /* if the env var is set, use that */ ++ env = getenv("SYSTEMD_CATALOG_DIR"); ++ if (!env) ++ env = SYSTEMD_CATALOG_DIR; ++ if (access(env, F_OK) < 0) { ++ fprintf(stderr, "ERROR: $SYSTEMD_CATALOG_DIR directory [%s] does not exist\n", env); ++ exit(EXIT_FAILURE); ++ } ++ return env; ++} +diff --git a/src/shared/tests.h b/src/shared/tests.h +index 3d696d02fd..19a9fa0fee 100644 +--- a/src/shared/tests.h ++++ b/src/shared/tests.h +@@ -2,6 +2,6 @@ + #pragma once + + char* setup_fake_runtime_dir(void); +-bool test_is_running_from_builddir(char **exedir); + const char* get_testdata_dir(void); ++const char* get_catalog_dir(void); + void test_setup_logging(int level); +diff --git a/src/test/meson.build b/src/test/meson.build +index 7b310d4ec7..b4b9e8a60e 100644 +--- a/src/test/meson.build ++++ b/src/test/meson.build +@@ -776,8 +776,7 @@ tests += [ + libshared], + [threads, + libxz, +- liblz4], +- '', '', '-DCATALOG_DIR="@0@"'.format(catalogdir)], ++ liblz4]], + + [['src/journal/test-compress.c'], + [libjournal_core, +-- +2.18.1 + diff --git a/1006-strv-rework-FOREACH_STRING-macro.patch b/1006-strv-rework-FOREACH_STRING-macro.patch new file mode 100644 index 0000000000000000000000000000000000000000..7d8bcf2e5c8193e777292cfa21f82e8196be28fa --- /dev/null +++ b/1006-strv-rework-FOREACH_STRING-macro.patch @@ -0,0 +1,50 @@ +From f3ae2e70053c5145cdd9750b577f5d86077c7271 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 2 Jun 2020 02:48:29 +0000 +Subject: [PATCH] strv: rework FOREACH_STRING() macro + +upstream commit 66a64081f82dfad90f2f9394a477820a2e3e6510 + +So it's apparently problematic that we use STRV_MAKE() (i.e. a compound +initializer) outside of the {} block we use it in (and that includes +outside of the ({}) block, too). Hence, let's rework the macro to not +need that. + +This also makes the macro shorter, which is definitely a good and more +readable. Moreover, it will now complain if the iterator is a "char*" +instead of a "const char*", which is good too. + +Fixes: #11394 +--- + src/basic/strv.h | 15 ++++----------- + 1 file changed, 4 insertions(+), 11 deletions(-) + +diff --git a/src/basic/strv.h b/src/basic/strv.h +index c1e4c97..a09d767 100644 +--- a/src/basic/strv.h ++++ b/src/basic/strv.h +@@ -148,17 +148,10 @@ void strv_print(char **l); + _found; \ + }) + +-#define FOREACH_STRING(x, ...) \ +- for (char **_l = ({ \ +- char **_ll = STRV_MAKE(__VA_ARGS__); \ +- x = _ll ? _ll[0] : NULL; \ +- _ll; \ +- }); \ +- _l && *_l; \ +- x = ({ \ +- _l ++; \ +- _l[0]; \ +- })) ++#define FOREACH_STRING(x, y, ...) \ ++ for (char **_l = STRV_MAKE(({ x = y; }), ##__VA_ARGS__); \ ++ x; \ ++ x = *(++_l)) + + char **strv_reverse(char **l); + char **strv_shell_escape(char **l, const char *bad); +-- +2.18.1 + diff --git a/1007-exit-status-introduce-EXIT_EXCEPTION-mapping-to-255.patch b/1007-exit-status-introduce-EXIT_EXCEPTION-mapping-to-255.patch new file mode 100644 index 0000000000000000000000000000000000000000..eeb47f7ec798ccc06d8631fe699be1e270bc01df --- /dev/null +++ b/1007-exit-status-introduce-EXIT_EXCEPTION-mapping-to-255.patch @@ -0,0 +1,61 @@ +From 7188a29295f3a6f2c8e0a7c5a5ae4914088ee6fc Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 20 Nov 2018 16:55:51 +0100 +Subject: [PATCH] exit-status: introduce EXIT_EXCEPTION mapping to 255 + +cherry-picked from upstream 3584d3ca. + +Conflicts: + src/basic/exit-status.c + src/basic/exit-status.h + +Signed-off-by: Yuanhong Peng +--- + src/basic/exit-status.c | 10 +++++++--- + src/basic/exit-status.h | 2 ++ + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c +index 0a7a53b73d..58ebc3ca4d 100644 +--- a/src/basic/exit-status.c ++++ b/src/basic/exit-status.c +@@ -19,9 +19,10 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) { + * 79…199 │ (Currently unmapped) + * 200…241 │ systemd's private error codes (might be extended to 254 in future development) + * 242…254 │ (Currently unmapped, but see above) +- * 255 │ (We should probably stay away from that one, it's frequently used by applications to indicate an +- * │ exit reason that cannot really be expressed in a single exit status value — such as a propagated +- * │ signal or such) ++ * ++ * 255 │ EXIT_EXCEPTION (We use this to propagate exit-by-signal events. It's frequently used by others apps (like bash) ++ * │ to indicate exit reason that cannot really be expressed in a single exit status value — such as a propagated ++ * │ signal or such, and we follow that logic here.) + */ + + switch (status) { /* We always cover the ISO C ones */ +@@ -158,6 +159,9 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) { + + case EXIT_NUMA_POLICY: + return "NUMA_POLICY"; ++ ++ case EXIT_EXCEPTION: ++ return "EXCEPTION"; + } + } + +diff --git a/src/basic/exit-status.h b/src/basic/exit-status.h +index dc284aacb1..5637e6aa04 100644 +--- a/src/basic/exit-status.h ++++ b/src/basic/exit-status.h +@@ -70,6 +70,8 @@ enum { + EXIT_LOGS_DIRECTORY, /* 240 */ + EXIT_CONFIGURATION_DIRECTORY, + EXIT_NUMA_POLICY, ++ ++ EXIT_EXCEPTION = 255, /* Whenever we want to propagate an abnormal/signal exit, in line with bash */ + }; + + typedef enum ExitStatusLevel { +-- +2.18.1 + diff --git a/1008-main-don-t-freeze-PID-1-in-containers-exit-with-non-.patch b/1008-main-don-t-freeze-PID-1-in-containers-exit-with-non-.patch new file mode 100644 index 0000000000000000000000000000000000000000..94923e1a65f83a2179164b7b9916917601d5aca9 --- /dev/null +++ b/1008-main-don-t-freeze-PID-1-in-containers-exit-with-non-.patch @@ -0,0 +1,59 @@ +From 6c76e460aed00997766a638fa8b40cc1b17a14d5 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 20 Nov 2018 13:16:48 +0100 +Subject: [PATCH] main: don't freeze PID 1 in containers, exit with + non-zero instead + +After all we have a nice way to propagate total failures, hence let's +use it. + +cherry-picked from upstream bb259772 without conflict. + +Signed-off-by: Yuanhong Peng +--- + src/core/main.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/core/main.c b/src/core/main.c +index 25536054b3..1ecdc47446 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -139,7 +139,14 @@ static NUMAPolicy arg_numa_policy; + static int parse_configuration(const struct rlimit *saved_rlimit_nofile, + const struct rlimit *saved_rlimit_memlock); + +-_noreturn_ static void freeze_or_reboot(void) { ++_noreturn_ static void freeze_or_exit_or_reboot(void) { ++ ++ /* If we are running in a contianer, let's prefer exiting, after all we can propagate an exit code to the ++ * container manager, and thus inform it that something went wrong. */ ++ if (detect_container() > 0) { ++ log_emergency("Exiting PID 1..."); ++ exit(EXIT_EXCEPTION); ++ } + + if (arg_crash_reboot) { + log_notice("Rebooting in 10s..."); +@@ -247,7 +254,7 @@ _noreturn_ static void crash(int sig) { + } + } + +- freeze_or_reboot(); ++ freeze_or_exit_or_reboot(); + } + + static void install_crash_handler(void) { +@@ -2664,8 +2671,8 @@ finish: + if (error_message) + manager_status_printf(NULL, STATUS_TYPE_EMERGENCY, + ANSI_HIGHLIGHT_RED "!!!!!!" ANSI_NORMAL, +- "%s, freezing.", error_message); +- freeze_or_reboot(); ++ "%s.", error_message); ++ freeze_or_exit_or_reboot(); + } + + return retval; +-- +2.18.1 + diff --git a/1009-Do-not-go-into-freeze-when-systemd-crashd.patch b/1009-Do-not-go-into-freeze-when-systemd-crashd.patch new file mode 100644 index 0000000000000000000000000000000000000000..2b457bc958f4e11642fec4104353055630679ba3 --- /dev/null +++ b/1009-Do-not-go-into-freeze-when-systemd-crashd.patch @@ -0,0 +1,111 @@ +From d05802b22fda63164a1f12a60ebf726a44fbecb4 Mon Sep 17 00:00:00 2001 +From: Yuanhong Peng +Date: Mon, 14 Dec 2020 17:04:28 +0800 +Subject: [PATCH] Do not go into freeze when systemd crashd + +If something unexpected happens which cause systemd to freeze, the system +cannot resume without a reboot, furthermore, if a service dies or exits, +no one else can recycle all child processes of the service, which will +cause a number of zombie processes remaining in the system. So we +introduce a mechanism, when systemd enters freeze state, you can send +SIGTERM to it to force systemd to re-exec. This may helps to resume the +system if it cannot reboot. + +Signed-off-by: Yuanhong Peng +--- + src/core/main.c | 40 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 39 insertions(+), 1 deletion(-) + +diff --git a/src/core/main.c b/src/core/main.c +index 1ecdc47446..a72c685b20 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -3,6 +3,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -10,6 +11,7 @@ + #include + #include + #include ++#include + #include + #if HAVE_SECCOMP + #include +@@ -135,10 +137,41 @@ static sd_id128_t arg_machine_id; + static EmergencyAction arg_cad_burst_action; + static CPUSet arg_cpu_affinity; + static NUMAPolicy arg_numa_policy; ++static bool reexec_jmp_can = false; ++static bool reexec_jmp_inited = false; ++static sigjmp_buf reexec_jmp_buf; + + static int parse_configuration(const struct rlimit *saved_rlimit_nofile, + const struct rlimit *saved_rlimit_memlock); + ++static void reexec_handler(int sig) { ++ reexec_jmp_can = true; ++} ++ ++_noreturn_ static void freeze_wait_upgrade(void) { ++ struct sigaction sa; ++ sigset_t ss; ++ ++ sigemptyset(&ss); ++ sigaddset(&ss, SIGTERM); ++ sigprocmask(SIG_UNBLOCK, &ss, NULL); ++ ++ sa.sa_handler = reexec_handler; ++ sa.sa_flags = SA_RESTART; ++ sigaction(SIGTERM, &sa, NULL); ++ ++ log_error("freeze_wait_upgrade: %d\n", reexec_jmp_inited); ++ reexec_jmp_can = false; ++ while(1) { ++ usleep(10000); ++ if (reexec_jmp_inited && reexec_jmp_can) { ++ log_error("goto manager_reexecute.\n"); ++ siglongjmp(reexec_jmp_buf, 1); ++ } ++ waitpid(-1, NULL, WNOHANG); ++ } ++} ++ + _noreturn_ static void freeze_or_exit_or_reboot(void) { + + /* If we are running in a contianer, let's prefer exiting, after all we can propagate an exit code to the +@@ -158,7 +191,7 @@ _noreturn_ static void freeze_or_exit_or_reboot(void) { + } + + log_emergency("Freezing execution."); +- freeze(); ++ freeze_wait_upgrade(); + } + + _noreturn_ static void crash(int sig) { +@@ -1668,6 +1701,10 @@ static int invoke_main_loop( + assert(ret_switch_root_init); + assert(ret_error_message); + ++ reexec_jmp_inited = true; ++ if (sigsetjmp(reexec_jmp_buf, 1)) ++ goto manager_reexecute; ++ + for (;;) { + r = manager_loop(m); + if (r < 0) { +@@ -1710,6 +1747,7 @@ static int invoke_main_loop( + + case MANAGER_REEXECUTE: + ++manager_reexecute: + r = prepare_reexecute(m, &arg_serialization, ret_fds, false); + if (r < 0) { + *ret_error_message = "Failed to prepare for reexecution"; +-- +2.18.1 + diff --git a/1010-mount-setup-change-the-system-mount-propagation-to-s.patch b/1010-mount-setup-change-the-system-mount-propagation-to-s.patch new file mode 100644 index 0000000000000000000000000000000000000000..4066dfd94dae0b954d98ee09bab795d7db1521bc --- /dev/null +++ b/1010-mount-setup-change-the-system-mount-propagation-to-s.patch @@ -0,0 +1,77 @@ +From bdd65129e7fbd09c7e0c1fd7fbaffeb9b0b81e1d Mon Sep 17 00:00:00 2001 +From: Wen Yang +Date: Mon, 23 Mar 2020 10:42:46 +0800 +Subject: [PATCH] mount-setup: change the system mount propagation to + shared by default only at bootup + +The commit b3ac5f8cb987 has changed the system mount propagation to +shared by default, and according to the following patch: +https://github.com/opencontainers/runc/pull/208 +When starting the container, the pouch daemon will call runc to execute +make-private. + +However, if the systemctl daemon-reexec is executed after the container +has been started, the system mount propagation will be changed to share +again by default, and the make-private operation above will have no chance +to execute. + +cherry-picked from upstream f74349d8 without conflict. + +Signed-off-by: Yuanhong Peng +--- + src/core/main.c | 2 +- + src/core/mount-setup.c | 4 ++-- + src/core/mount-setup.h | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/core/main.c b/src/core/main.c +index a72c685b20..55c54aecd5 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -2519,7 +2519,7 @@ int main(int argc, char *argv[]) { + if (!skip_setup) + kmod_setup(); + +- r = mount_setup(loaded_policy); ++ r = mount_setup(loaded_policy, skip_setup); + if (r < 0) { + error_message = "Failed to mount API filesystems"; + goto finish; +diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c +index b3cf13af2b..ff7fc18765 100644 +--- a/src/core/mount-setup.c ++++ b/src/core/mount-setup.c +@@ -400,7 +400,7 @@ static int relabel_cgroup_filesystems(void) { + } + #endif + +-int mount_setup(bool loaded_policy) { ++int mount_setup(bool loaded_policy, bool leave_propagation) { + int r = 0; + + r = mount_points_setup(ELEMENTSOF(mount_table), loaded_policy); +@@ -444,7 +444,7 @@ int mount_setup(bool loaded_policy) { + * needed. Note that we set this only when we are invoked directly by the kernel. If we are invoked by a + * container manager we assume the container manager knows what it is doing (for example, because it set up + * some directories with different propagation modes). */ +- if (detect_container() <= 0) ++ if (detect_container() <= 0 && !leave_propagation) + if (mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL) < 0) + log_warning_errno(errno, "Failed to set up the root directory for shared mount propagation: %m"); + +diff --git a/src/core/mount-setup.h b/src/core/mount-setup.h +index 43cd8908de..7a011b25c8 100644 +--- a/src/core/mount-setup.h ++++ b/src/core/mount-setup.h +@@ -4,7 +4,7 @@ + #include + + int mount_setup_early(void); +-int mount_setup(bool loaded_policy); ++int mount_setup(bool loaded_policy, bool leave_propagation); + + int mount_cgroup_controllers(char ***join_controllers); + +-- +2.18.1 + diff --git a/1011-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch b/1011-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch new file mode 100644 index 0000000000000000000000000000000000000000..cbbec36e461fbb2badb177866ac2e615d7c7342a --- /dev/null +++ b/1011-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch @@ -0,0 +1,57 @@ +From 66ccec10af5ac97fa0528a309119f98e4eff44a7 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 28 Nov 2018 12:41:44 +0100 +Subject: [PATCH] mount: don't propagate errors from mount_setup_unit() further + up + +If we can't process a specific line in /proc/self/mountinfo we should +log about it (which we do), but this should not affect other lines, nor +further processing of mount units. Let's keep these failures local. + +Fixes: #10874 + +cherry-picked from upstream ba0d56f5. + +Conflicts: + src/core/mount.c + +Signed-off-by: Yuanhong Peng +--- + src/core/mount.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 7e80a0c..9b1c59b 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1621,12 +1621,10 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { + if (r < 0) + return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m"); + +- r = 0; + for (;;) { + struct libmnt_fs *fs; + const char *device, *path, *options, *fstype; + _cleanup_free_ char *d = NULL, *p = NULL; +- int k; + + r = mnt_table_next_fs(table, iter, &fs); + if (r == 1) +@@ -1650,12 +1648,10 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) { + + device_found_node(m, d, DEVICE_FOUND_MOUNT, DEVICE_FOUND_MOUNT); + +- k = mount_setup_unit(m, d, p, options, fstype, set_flags); +- if (r == 0 && k < 0) +- r = k; ++ (void) mount_setup_unit(m, d, p, options, fstype, set_flags); + } + +- return r; ++ return 0; + } + + static void mount_shutdown(Manager *m) { +-- +2.27.0 + diff --git a/1012-cgroup-util-make-definition-of-CGROUP_CONTROLLER_TO_.patch b/1012-cgroup-util-make-definition-of-CGROUP_CONTROLLER_TO_.patch new file mode 100644 index 0000000000000000000000000000000000000000..7936d1766d423b13a087d03a2847a708d818e3da --- /dev/null +++ b/1012-cgroup-util-make-definition-of-CGROUP_CONTROLLER_TO_.patch @@ -0,0 +1,32 @@ +From 334dddc80cb53561c49f9a7b4e5237a6451a9964 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 26 Oct 2018 15:31:30 +0200 +Subject: [PATCH] cgroup-util: make definition of CGROUP_CONTROLLER_TO_MASK() unsigned + +Otherwise doing comparing a CGroupMask (which is unsigned in effect) +with the result of CGROUP_CONTROLLER_TO_MASK() will result in warnings +about signedness differences. + +cherry-picked from upstream 46f84f95 without conflict. + +Signed-off-by: Yuanhong Peng +--- + src/basic/cgroup-util.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h +index 1210b38a83..76659c3790 100644 +--- a/src/basic/cgroup-util.h ++++ b/src/basic/cgroup-util.h +@@ -31,7 +31,7 @@ typedef enum CGroupController { + _CGROUP_CONTROLLER_INVALID = -1, + } CGroupController; + +-#define CGROUP_CONTROLLER_TO_MASK(c) (1 << (c)) ++#define CGROUP_CONTROLLER_TO_MASK(c) (1U << (c)) + + /* A bit mask of well known cgroup controllers */ + typedef enum CGroupMask { +-- +2.18.1 + diff --git a/1013-cgroup-update-only-siblings-that-got-realized-once.patch b/1013-cgroup-update-only-siblings-that-got-realized-once.patch new file mode 100644 index 0000000000000000000000000000000000000000..cd83cd1f5fbd94c2e1a75ec59d811bc896f5ee45 --- /dev/null +++ b/1013-cgroup-update-only-siblings-that-got-realized-once.patch @@ -0,0 +1,67 @@ +From 18561b46343c94af359d74a48c34974739b46eeb Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 13 Jan 2020 20:06:39 +0100 +Subject: [PATCH] cgroup: update only siblings that got realized once + +Fixes: #14475 +Replaces: #14554 + +cherry-picked from upstream e1e98911 without conflict. + +Signed-off-by: Yuanhong Peng +--- + src/core/cgroup.c | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index e0eb184fd2..00121e3f37 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -1964,7 +1964,15 @@ 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.) */ ++ * queue. (But neither the specified unit itself nor the parents.) ++ * ++ * Propagation of realization "side-ways" (i.e. towards siblings) is in relevant on cgroup-v1 where ++ * scheduling become very weird if two units that own processes reside in the same slice, but one is ++ * realized in the "cpu" hierarchy and once is not (for example because one has CPUWeight= set and ++ * the other does not), because that means processes need to be scheduled against groups. Let's avoid ++ * this asymmetry by always ensuring that units below a slice that are realized at all are hence ++ * always realized in *all* their hierarchies, and it is sufficient for a unit's sibling to be ++ * realized for a unit to be realized too. */ + + while ((slice = UNIT_DEREF(u->slice))) { + Iterator i; +@@ -1972,6 +1980,7 @@ static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) { + void *v; + + 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; +@@ -1980,6 +1989,11 @@ static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) { + if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m))) + continue; + ++ /* We only enqueue siblings if they were realized once at least, in the main ++ * hierarchy. */ ++ if (!m->cgroup_realized) ++ continue; ++ + /* 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, +@@ -2264,6 +2278,7 @@ void unit_add_to_cgroup_empty_queue(Unit *u) { + /* Let's verify that the cgroup is really empty */ + if (!u->cgroup_path) + return; ++ + r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path); + if (r < 0) { + log_unit_debug_errno(u, r, "Failed to determine whether cgroup %s is empty: %m", u->cgroup_path); +-- +2.18.1 + diff --git a/1014-core-add-a-config-item-to-support-setting-the-value-.patch b/1014-core-add-a-config-item-to-support-setting-the-value-.patch new file mode 100644 index 0000000000000000000000000000000000000000..08d87b16a24e3236dd9bc62780b6680f9c6a74bf --- /dev/null +++ b/1014-core-add-a-config-item-to-support-setting-the-value-.patch @@ -0,0 +1,121 @@ +From 729300a386ee380406b6ea92e0924877066b1a3d Mon Sep 17 00:00:00 2001 +From: Yuanhong Peng +Date: Tue, 15 Dec 2020 11:47:49 +0800 +Subject: [PATCH] core: add a config item to support setting the value + of cpuset.clone_children when systemd is starting + +Signed-off-by: Yuanhong Peng +--- + src/core/main.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +diff --git a/src/core/main.c b/src/core/main.c +index 55c54aecd5..f241707842 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -140,6 +140,7 @@ static NUMAPolicy arg_numa_policy; + static bool reexec_jmp_can = false; + static bool reexec_jmp_inited = false; + static sigjmp_buf reexec_jmp_buf; ++static bool arg_default_cpuset_clone_children = false; + + static int parse_configuration(const struct rlimit *saved_rlimit_nofile, + const struct rlimit *saved_rlimit_memlock); +@@ -528,6 +529,14 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat + + parse_path_argument_and_warn(value, false, &arg_watchdog_device); + ++ } else if (proc_cmdline_key_streq(key, "systemd.cpuset_clone_children") && value) { ++ ++ r = parse_boolean(value); ++ if (r < 0) ++ log_warning("Failed to parse cpuset_clone_children switch %s. Ignoring.", value); ++ else ++ arg_default_cpuset_clone_children = r; ++ + } else if (streq(key, "quiet") && !value) { + + if (arg_show_status == _SHOW_STATUS_UNSET) +@@ -756,6 +765,7 @@ static int parse_config_file(void) { + { "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting }, + { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max }, + { "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action }, ++ { "Manager", "DefaultCPUSetCloneChildren",config_parse_bool, 0, &arg_default_cpuset_clone_children }, + {} + }; + +@@ -1872,6 +1882,63 @@ static void log_execution_mode(bool *ret_first_boot) { + } + } + ++static bool is_use_triple_cgroup(void) { ++ const char * path ="/sys/fs/cgroup/cpuset"; ++ _cleanup_strv_free_ char **l = NULL; ++ char buf[128] = {0}; ++ int r; ++ ++ r = is_symlink(path); ++ if (r <= 0) ++ return false; ++ ++ r = readlink(path, buf, sizeof(buf)); ++ if (r < 0 || (unsigned int)r >= sizeof(buf)) ++ return false; ++ ++ buf[r] = '\0'; ++ l = strv_split(buf, ","); ++ if (!l) ++ return false; ++ ++ strv_sort(l); ++ if (strv_length(l) != 3) ++ return false; ++ ++ if (streq(l[0],"cpu") && streq(l[1], "cpuacct") && ++ streq(l[2], "cpuset")) { ++ log_debug(PACKAGE_STRING " use_triple_cgroup: %s", buf); ++ return true; ++ } ++ return false; ++} ++ ++static int ali_handle_cpuset_clone_children(void) ++{ ++ const char *file = "/sys/fs/cgroup/cpuset/cgroup.clone_children"; ++ _cleanup_free_ char *buf = NULL; ++ int r; ++ ++ r = read_one_line_file(file, &buf); ++ if (r < 0) { ++ log_warning_errno(r, "Cannot read %s: %m", file); ++ return r; ++ } ++ ++ if (streq(buf, "1") && arg_default_cpuset_clone_children) ++ return 0; ++ ++ if (streq(buf, "0") && (!arg_default_cpuset_clone_children)) ++ return 0; ++ ++ if (!is_use_triple_cgroup()) ++ return 0; ++ ++ r = write_string_file(file, one_zero(arg_default_cpuset_clone_children), 0); ++ log_info(PACKAGE_STRING " set %s to %s, ret=%d", file, one_zero(arg_default_cpuset_clone_children), r); ++ return r; ++} ++ + static int initialize_runtime( + bool skip_setup, + struct rlimit *saved_rlimit_nofile, +@@ -1906,6 +1973,7 @@ static int initialize_runtime( + return r; + } + ++ ali_handle_cpuset_clone_children(); + status_welcome(); + hostname_setup(); + machine_id_setup(NULL, arg_machine_id, NULL); +-- +2.18.1 + diff --git a/systemd.spec b/systemd.spec index 580ef822e9146c657518f3f293fa0aea07c7e328..a7ecd890a56fbeb56d49426a544a794f98d708d7 100644 --- a/systemd.spec +++ b/systemd.spec @@ -1,3 +1,5 @@ +%define anolis_release .0.1 + #global gitcommit 10e465b5321bd53c1fc59ffab27e724535c6bc0f %{?gitcommit:%global gitcommitshort %(c=%{gitcommit}; echo ${c:0:7})} @@ -13,7 +15,7 @@ Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 239 -Release: 51%{?dist} +Release: 51%{anolis_release}%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -709,6 +711,19 @@ Patch0656: 0656-Fix-LGTM-build.patch Patch0657: 0657-sd-hwdb-allow-empty-properties.patch Patch0658: 0658-Update-hwdb.patch +Patch1002: 1002-core-fix-a-null-reference-case-in-load_from_path.patch +Patch1003: 1003-sysctl-Don-t-pass-null-directive-argument-to-s.patch +Patch1004: 1004-test-use-builddir-systemd-runtest.env-to-set-SYSTEMD.patch +Patch1005: 1005-test-use-builddir-systemd-runtest.env-for-SYSTEMD_CA.patch +Patch1006: 1006-strv-rework-FOREACH_STRING-macro.patch +Patch1007: 1007-exit-status-introduce-EXIT_EXCEPTION-mapping-to-255.patch +Patch1008: 1008-main-don-t-freeze-PID-1-in-containers-exit-with-non-.patch +Patch1009: 1009-Do-not-go-into-freeze-when-systemd-crashd.patch +Patch1010: 1010-mount-setup-change-the-system-mount-propagation-to-s.patch +Patch1011: 1011-mount-don-t-propagate-errors-from-mount_setup_unit-f.patch +Patch1012: 1012-cgroup-util-make-definition-of-CGROUP_CONTROLLER_TO_.patch +Patch1013: 1013-cgroup-update-only-siblings-that-got-realized-once.patch +Patch1014: 1014-core-add-a-config-item-to-support-setting-the-value-.patch %ifarch %{ix86} x86_64 aarch64 %global have_gnu_efi 1 @@ -1335,6 +1350,21 @@ fi %files tests -f .file-list-tests %changelog +* Tue Dec 21 2021 Yuanhong Peng - 239-45.0.2.6 +- core: fix a null reference case in load_from_path() +- sysctl: Don't pass null directive argument to '%s' +- test: use ${builddir}/systemd-runtest.env to set $SYSTEMD_TEST_DATA +- test: use ${builddir}/systemd-runtest.env for $SYSTEMD_CATALOG_DIR +- strv: rework FOREACH_STRING() macro +- exit-status: introduce EXIT_EXCEPTION mapping to 255 +- main: don't freeze PID 1 in containers, exit with non-zero instead +- Do not go into freeze when systemd crashd +- mount-setup: change the system mount propagation to shared by default only at bootup +- mount: don't propagate errors from mount_setup_unit() further up +- cgroup-util: make definition of CGROUP_CONTROLLER_TO_MASK() unsigned +- cgroup: update only siblings that got realized once +- core: add a config item to support setting the value of cpuset.clone_children when systemd is starting + * Thu Sep 23 2021 systemd maintenance team - 239-51 - define newly needed constants (#1850986) - sd-netlink: support IFLA_PROP_LIST and IFLA_ALT_IFNAME attributes (#1850986)