From 984f77e48faa23d1d085735ae8e5911389733641 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Sep 27 2022 20:45:37 +0000 Subject: import systemd-239-67.el8 --- diff --git a/SOURCES/0744-core-disallow-using-.service-as-a-service-name.patch b/SOURCES/0744-core-disallow-using-.service-as-a-service-name.patch new file mode 100644 index 0000000..2e5cf37 --- /dev/null +++ b/SOURCES/0744-core-disallow-using-.service-as-a-service-name.patch @@ -0,0 +1,133 @@ +From a4e9cf5b5c5e4c4a6f05825cd9c159283a425ae2 Mon Sep 17 00:00:00 2001 +From: Anita Zhang +Date: Fri, 4 Oct 2019 16:03:04 -0700 +Subject: [PATCH] core: disallow using '-.service' as a service name + +-.service.d will become a special top level drop in so don't let it be a +usable service name (otherwise the interaction gets complicated). + +(cherry picked from commit e23d911664b4fd86eb2c24b64233cb9f23cffdd1) + +Resolves: #2051520 +--- + src/basic/special.h | 4 ++++ + src/basic/unit-name.c | 25 +++++++++++++++++++++++++ + src/basic/unit-name.h | 2 ++ + src/core/service.c | 5 +++++ + src/test/test-unit-name.c | 19 +++++++++++++++++++ + 5 files changed, 55 insertions(+) + +diff --git a/src/basic/special.h b/src/basic/special.h +index 379a3d7979..2915122929 100644 +--- a/src/basic/special.h ++++ b/src/basic/special.h +@@ -103,3 +103,7 @@ + + /* The root directory. */ + #define SPECIAL_ROOT_MOUNT "-.mount" ++ ++/* Used to apply settings to all services through drop-ins. ++ * Should not exist as an actual service. */ ++#define SPECIAL_ROOT_SERVICE "-.service" +diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c +index 614eb8649b..82a666a481 100644 +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -668,6 +668,31 @@ good: + return 0; + } + ++bool service_unit_name_is_valid(const char *name) { ++ _cleanup_free_ char *prefix = NULL, *s = NULL; ++ const char *e, *service_name = name; ++ ++ if (!unit_name_is_valid(name, UNIT_NAME_ANY)) ++ return false; ++ ++ e = endswith(name, ".service"); ++ if (!e) ++ return false; ++ ++ /* If it's a template or instance, get the prefix as a service name. */ ++ if (unit_name_is_valid(name, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) { ++ assert_se(unit_name_to_prefix(name, &prefix) == 0); ++ assert_se(s = strjoin(prefix, ".service")); ++ service_name = s; ++ } ++ ++ /* Reject reserved service name(s). */ ++ if (streq(service_name, SPECIAL_ROOT_SERVICE)) ++ return false; ++ ++ return true; ++} ++ + int slice_build_parent_slice(const char *slice, char **ret) { + char *s, *dash; + int r; +diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h +index 61abcd585b..21729cba83 100644 +--- a/src/basic/unit-name.h ++++ b/src/basic/unit-name.h +@@ -60,6 +60,8 @@ static inline int unit_name_mangle(const char *name, UnitNameMangle flags, char + return unit_name_mangle_with_suffix(name, flags, ".service", ret); + } + ++bool service_unit_name_is_valid(const char *name); ++ + int slice_build_parent_slice(const char *slice, char **ret); + int slice_build_subslice(const char *slice, const char*name, char **subslice); + bool slice_name_is_valid(const char *name); +diff --git a/src/core/service.c b/src/core/service.c +index e8ae1a5772..b7eb10c044 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -556,6 +556,11 @@ static int service_verify(Service *s) { + } + } + ++ if (!service_unit_name_is_valid(UNIT(s)->id)) { ++ log_unit_error(UNIT(s), "Service name is invalid or reserved. Refusing."); ++ return -ENOEXEC; ++ } ++ + if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP] + && UNIT(s)->success_action == EMERGENCY_ACTION_NONE) { + /* FailureAction= only makes sense if one of the start or stop commands is specified. +diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c +index 2b00ef8cb7..b629df5aea 100644 +--- a/src/test/test-unit-name.c ++++ b/src/test/test-unit-name.c +@@ -347,6 +347,24 @@ static void test_unit_name_build(void) { + free(t); + } + ++static void test_service_unit_name_is_valid(void) { ++ assert_se(service_unit_name_is_valid("foo.service")); ++ assert_se(service_unit_name_is_valid("foo@bar.service")); ++ assert_se(service_unit_name_is_valid("foo@bar@bar.service")); ++ assert_se(service_unit_name_is_valid("--.service")); ++ assert_se(service_unit_name_is_valid(".-.service")); ++ assert_se(service_unit_name_is_valid("-foo-bar.service")); ++ assert_se(service_unit_name_is_valid("-foo-bar-.service")); ++ assert_se(service_unit_name_is_valid("foo-bar-.service")); ++ ++ assert_se(!service_unit_name_is_valid("-.service")); ++ assert_se(!service_unit_name_is_valid("")); ++ assert_se(!service_unit_name_is_valid("foo.slice")); ++ assert_se(!service_unit_name_is_valid("@.service")); ++ assert_se(!service_unit_name_is_valid("@bar.service")); ++ assert_se(!service_unit_name_is_valid("-@.service")); ++} ++ + static void test_slice_name_is_valid(void) { + assert_se( slice_name_is_valid(SPECIAL_ROOT_SLICE)); + assert_se( slice_name_is_valid("foo.slice")); +@@ -833,6 +851,7 @@ int main(int argc, char* argv[]) { + test_unit_prefix_is_valid(); + test_unit_name_change_suffix(); + test_unit_name_build(); ++ test_service_unit_name_is_valid(); + test_slice_name_is_valid(); + test_build_subslice(); + test_build_parent_slice(); diff --git a/SOURCES/0745-shared-dropin-support-.service.d-top-level-drop-in-f.patch b/SOURCES/0745-shared-dropin-support-.service.d-top-level-drop-in-f.patch new file mode 100644 index 0000000..3a25ff5 --- /dev/null +++ b/SOURCES/0745-shared-dropin-support-.service.d-top-level-drop-in-f.patch @@ -0,0 +1,190 @@ +From adc0a99b18153535ef73cf1b6ce2bc64ca501c81 Mon Sep 17 00:00:00 2001 +From: Anita Zhang +Date: Fri, 4 Oct 2019 17:39:34 -0700 +Subject: [PATCH] shared/dropin: support -.service.d/ top level drop-in for + service units + +(cherry picked from commit 272467882c9c3c3d4faca5fd7a1f44c5ef2f064) + +Resolves: #2051520 +--- + man/systemd.service.xml | 13 +++++++++++++ + man/systemd.special.xml | 9 +++++++++ + man/systemd.unit.xml | 4 ++++ + src/basic/unit-name.c | 9 +++++++-- + src/core/service.c | 2 +- + src/shared/dropin.c | 29 ++++++++++++++++++++++++++--- + test/TEST-15-DROPIN/test-dropin.sh | 15 ++++++++++++++- + 7 files changed, 74 insertions(+), 7 deletions(-) + +diff --git a/man/systemd.service.xml b/man/systemd.service.xml +index 1e30a564df..4164402d0e 100644 +--- a/man/systemd.service.xml ++++ b/man/systemd.service.xml +@@ -62,6 +62,19 @@ + about the incompatibilities, see the Incompatibilities + with SysV document. ++ ++ In addition to the various drop-in behaviors described in ++ systemd.unit5, ++ services also support a top-level drop-in with -.service.d/ that allows ++ altering or adding to the settings of all services on the system. ++ The formatting and precedence of applying drop-in configurations follow what is defined in ++ systemd.unit5. ++ However, configurations in -.service.d/ have the lowest precedence compared to settings ++ in the service specific override directories. For example, for foo-bar-baz.service, ++ drop-ins in foo-bar-baz.service.d/ override the ones in ++ foo-bar-.service.d/, which override the ones foo-.service.d/, ++ which override the ones in -.service.d/. ++ + + + +diff --git a/man/systemd.special.xml b/man/systemd.special.xml +index fe6324a4a0..06798cd9e2 100644 +--- a/man/systemd.special.xml ++++ b/man/systemd.special.xml +@@ -117,6 +117,15 @@ + + + ++ ++ -.service ++ ++ This is a reserved unit name used to support top-level drop-ins for services. See ++ systemd.service5 ++ for details. ++ ++ ++ + + basic.target + +diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml +index e80c760dd6..5aa3bd1699 100644 +--- a/man/systemd.unit.xml ++++ b/man/systemd.unit.xml +@@ -190,6 +190,10 @@ + over unit files wherever located. Multiple drop-in files with different names are applied in + lexicographic order, regardless of which of the directories they reside in. + ++ Service units also support a top-level drop-in directory for modifying the settings of all service units. See ++ systemd.service5 ++ for details. ++ + + +diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c +index 82a666a481..078628d6e8 100644 +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -681,8 +681,13 @@ bool service_unit_name_is_valid(const char *name) { + + /* If it's a template or instance, get the prefix as a service name. */ + if (unit_name_is_valid(name, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) { +- assert_se(unit_name_to_prefix(name, &prefix) == 0); +- assert_se(s = strjoin(prefix, ".service")); ++ if (unit_name_to_prefix(name, &prefix) < 0) ++ return false; ++ ++ s = strjoin(prefix, ".service"); ++ if (!s) ++ return false; ++ + service_name = s; + } + +diff --git a/src/core/service.c b/src/core/service.c +index b7eb10c044..b3ef79228f 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -558,7 +558,7 @@ static int service_verify(Service *s) { + + if (!service_unit_name_is_valid(UNIT(s)->id)) { + log_unit_error(UNIT(s), "Service name is invalid or reserved. Refusing."); +- return -ENOEXEC; ++ return -EINVAL; + } + + if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP] +diff --git a/src/shared/dropin.c b/src/shared/dropin.c +index 357c66d800..78ca7f4452 100644 +--- a/src/shared/dropin.c ++++ b/src/shared/dropin.c +@@ -19,6 +19,7 @@ + #include "mkdir.h" + #include "path-util.h" + #include "set.h" ++#include "special.h" + #include "string-util.h" + #include "strv.h" + #include "unit-name.h" +@@ -232,15 +233,37 @@ int unit_file_find_dropin_paths( + char ***ret) { + + _cleanup_strv_free_ char **dirs = NULL; +- char *t, **p; ++ UnitType type = _UNIT_TYPE_INVALID; ++ char *name, **p; + Iterator i; + int r; + + assert(ret); + +- SET_FOREACH(t, names, i) ++ /* All the names in the unit are of the same type so just grab one. */ ++ name = (char*) set_first(names); ++ if (name) { ++ type = unit_name_to_type(name); ++ if (type < 0) ++ return log_error_errno(EINVAL, ++ "Failed to to derive unit type from unit name: %s", ++ name); ++ } ++ ++ /* Special drop in for -.service. Add this first as it's the most generic ++ * and should be able to be overridden by more specific drop-ins. */ ++ if (type == UNIT_SERVICE) ++ STRV_FOREACH(p, lookup_path) ++ (void) unit_file_find_dirs(original_root, ++ unit_path_cache, ++ *p, ++ SPECIAL_ROOT_SERVICE, ++ dir_suffix, ++ &dirs); ++ ++ SET_FOREACH(name, names, i) + STRV_FOREACH(p, lookup_path) +- (void) unit_file_find_dirs(original_root, unit_path_cache, *p, t, dir_suffix, &dirs); ++ (void) unit_file_find_dirs(original_root, unit_path_cache, *p, name, dir_suffix, &dirs); + + if (strv_isempty(dirs)) { + *ret = NULL; +diff --git a/test/TEST-15-DROPIN/test-dropin.sh b/test/TEST-15-DROPIN/test-dropin.sh +index ab0a58caea..def2e03304 100755 +--- a/test/TEST-15-DROPIN/test-dropin.sh ++++ b/test/TEST-15-DROPIN/test-dropin.sh +@@ -102,7 +102,20 @@ test_basic_dropins () { + check_ok b Wants c.service + systemctl stop a c + +- clear_services a b c ++ echo "*** test -.service.d/ top level drop-in" ++ create_services a b ++ check_ko a ExecCondition "/bin/echo a" ++ check_ko b ExecCondition "/bin/echo b" ++ mkdir -p /usr/lib/systemd/system/-.service.d ++ cat >/usr/lib/systemd/system/-.service.d/override.conf < +Date: Mon, 4 Nov 2019 18:29:55 -0800 +Subject: [PATCH] core: change top-level drop-in from -.service.d to service.d + +Discussed in #13743, the -.service semantic conflicts with the +existing root mount and slice names, making this feature not +uniformly extensible to all types. Change the name to be +.d instead. + +Updating to this format also extends the top-level dropin to +unit types. + +(cherry picked from commit 3e1db806b0c18fd6138886ce67fac2655f09caef) + +Resolves: #2051520 +--- + man/systemd.service.xml | 13 ------------- + man/systemd.special.xml | 9 --------- + man/systemd.unit.xml | 11 ++++++++--- + src/basic/special.h | 4 ---- + src/basic/unit-name.c | 30 ------------------------------ + src/basic/unit-name.h | 2 -- + src/core/service.c | 5 ----- + src/shared/dropin.c | 22 ++++++++++++---------- + src/test/test-unit-name.c | 19 ------------------- + test/TEST-15-DROPIN/test-dropin.sh | 8 ++++---- + 10 files changed, 24 insertions(+), 99 deletions(-) + +diff --git a/man/systemd.service.xml b/man/systemd.service.xml +index 4164402d0e..1e30a564df 100644 +--- a/man/systemd.service.xml ++++ b/man/systemd.service.xml +@@ -62,19 +62,6 @@ + about the incompatibilities, see the Incompatibilities + with SysV document. +- +- In addition to the various drop-in behaviors described in +- systemd.unit5, +- services also support a top-level drop-in with -.service.d/ that allows +- altering or adding to the settings of all services on the system. +- The formatting and precedence of applying drop-in configurations follow what is defined in +- systemd.unit5. +- However, configurations in -.service.d/ have the lowest precedence compared to settings +- in the service specific override directories. For example, for foo-bar-baz.service, +- drop-ins in foo-bar-baz.service.d/ override the ones in +- foo-bar-.service.d/, which override the ones foo-.service.d/, +- which override the ones in -.service.d/. +- + + + +diff --git a/man/systemd.special.xml b/man/systemd.special.xml +index 06798cd9e2..fe6324a4a0 100644 +--- a/man/systemd.special.xml ++++ b/man/systemd.special.xml +@@ -117,15 +117,6 @@ + + + +- +- -.service +- +- This is a reserved unit name used to support top-level drop-ins for services. See +- systemd.service5 +- for details. +- +- +- + + basic.target + +diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml +index 5aa3bd1699..6f213ccd56 100644 +--- a/man/systemd.unit.xml ++++ b/man/systemd.unit.xml +@@ -190,9 +190,14 @@ + over unit files wherever located. Multiple drop-in files with different names are applied in + lexicographic order, regardless of which of the directories they reside in. + +- Service units also support a top-level drop-in directory for modifying the settings of all service units. See +- systemd.service5 +- for details. ++ Units also support a top-level drop-in with type.d/, ++ where type may be e.g. service or socket, ++ that allows altering or adding to the settings of all corresponding unit files on the system. ++ The formatting and precedence of applying drop-in configurations follow what is defined above. ++ Configurations in type.d/ have the lowest precedence ++ compared to settings in the name specific override directories. So the contents of ++ foo-.service.d/10-override.conf would override ++ service.d/10-override.conf. + + +diff --git a/src/basic/special.h b/src/basic/special.h +index 2915122929..379a3d7979 100644 +--- a/src/basic/special.h ++++ b/src/basic/special.h +@@ -103,7 +103,3 @@ + + /* The root directory. */ + #define SPECIAL_ROOT_MOUNT "-.mount" +- +-/* Used to apply settings to all services through drop-ins. +- * Should not exist as an actual service. */ +-#define SPECIAL_ROOT_SERVICE "-.service" +diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c +index 078628d6e8..614eb8649b 100644 +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -668,36 +668,6 @@ good: + return 0; + } + +-bool service_unit_name_is_valid(const char *name) { +- _cleanup_free_ char *prefix = NULL, *s = NULL; +- const char *e, *service_name = name; +- +- if (!unit_name_is_valid(name, UNIT_NAME_ANY)) +- return false; +- +- e = endswith(name, ".service"); +- if (!e) +- return false; +- +- /* If it's a template or instance, get the prefix as a service name. */ +- if (unit_name_is_valid(name, UNIT_NAME_INSTANCE|UNIT_NAME_TEMPLATE)) { +- if (unit_name_to_prefix(name, &prefix) < 0) +- return false; +- +- s = strjoin(prefix, ".service"); +- if (!s) +- return false; +- +- service_name = s; +- } +- +- /* Reject reserved service name(s). */ +- if (streq(service_name, SPECIAL_ROOT_SERVICE)) +- return false; +- +- return true; +-} +- + int slice_build_parent_slice(const char *slice, char **ret) { + char *s, *dash; + int r; +diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h +index 21729cba83..61abcd585b 100644 +--- a/src/basic/unit-name.h ++++ b/src/basic/unit-name.h +@@ -60,8 +60,6 @@ static inline int unit_name_mangle(const char *name, UnitNameMangle flags, char + return unit_name_mangle_with_suffix(name, flags, ".service", ret); + } + +-bool service_unit_name_is_valid(const char *name); +- + int slice_build_parent_slice(const char *slice, char **ret); + int slice_build_subslice(const char *slice, const char*name, char **subslice); + bool slice_name_is_valid(const char *name); +diff --git a/src/core/service.c b/src/core/service.c +index b3ef79228f..e8ae1a5772 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -556,11 +556,6 @@ static int service_verify(Service *s) { + } + } + +- if (!service_unit_name_is_valid(UNIT(s)->id)) { +- log_unit_error(UNIT(s), "Service name is invalid or reserved. Refusing."); +- return -EINVAL; +- } +- + if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP] + && UNIT(s)->success_action == EMERGENCY_ACTION_NONE) { + /* FailureAction= only makes sense if one of the start or stop commands is specified. +diff --git a/src/shared/dropin.c b/src/shared/dropin.c +index 78ca7f4452..bd2a3c0feb 100644 +--- a/src/shared/dropin.c ++++ b/src/shared/dropin.c +@@ -19,7 +19,6 @@ + #include "mkdir.h" + #include "path-util.h" + #include "set.h" +-#include "special.h" + #include "string-util.h" + #include "strv.h" + #include "unit-name.h" +@@ -170,6 +169,10 @@ static int unit_file_find_dirs( + return r; + } + ++ /* Return early for top level drop-ins. */ ++ if (unit_type_from_string(name) >= 0) ++ return 0; ++ + /* Let's see if there's a "-" prefix for this unit name. If so, let's invoke ourselves for it. This will then + * recursively do the same for all our prefixes. i.e. this means given "foo-bar-waldo.service" we'll also + * search "foo-bar-.service" and "foo-.service". +@@ -250,16 +253,15 @@ int unit_file_find_dropin_paths( + name); + } + +- /* Special drop in for -.service. Add this first as it's the most generic ++ /* Special top level drop in for ".". Add this first as it's the most generic + * and should be able to be overridden by more specific drop-ins. */ +- if (type == UNIT_SERVICE) +- STRV_FOREACH(p, lookup_path) +- (void) unit_file_find_dirs(original_root, +- unit_path_cache, +- *p, +- SPECIAL_ROOT_SERVICE, +- dir_suffix, +- &dirs); ++ STRV_FOREACH(p, lookup_path) ++ (void) unit_file_find_dirs(original_root, ++ unit_path_cache, ++ *p, ++ unit_type_to_string(type), ++ dir_suffix, ++ &dirs); + + SET_FOREACH(name, names, i) + STRV_FOREACH(p, lookup_path) +diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c +index b629df5aea..2b00ef8cb7 100644 +--- a/src/test/test-unit-name.c ++++ b/src/test/test-unit-name.c +@@ -347,24 +347,6 @@ static void test_unit_name_build(void) { + free(t); + } + +-static void test_service_unit_name_is_valid(void) { +- assert_se(service_unit_name_is_valid("foo.service")); +- assert_se(service_unit_name_is_valid("foo@bar.service")); +- assert_se(service_unit_name_is_valid("foo@bar@bar.service")); +- assert_se(service_unit_name_is_valid("--.service")); +- assert_se(service_unit_name_is_valid(".-.service")); +- assert_se(service_unit_name_is_valid("-foo-bar.service")); +- assert_se(service_unit_name_is_valid("-foo-bar-.service")); +- assert_se(service_unit_name_is_valid("foo-bar-.service")); +- +- assert_se(!service_unit_name_is_valid("-.service")); +- assert_se(!service_unit_name_is_valid("")); +- assert_se(!service_unit_name_is_valid("foo.slice")); +- assert_se(!service_unit_name_is_valid("@.service")); +- assert_se(!service_unit_name_is_valid("@bar.service")); +- assert_se(!service_unit_name_is_valid("-@.service")); +-} +- + static void test_slice_name_is_valid(void) { + assert_se( slice_name_is_valid(SPECIAL_ROOT_SLICE)); + assert_se( slice_name_is_valid("foo.slice")); +@@ -851,7 +833,6 @@ int main(int argc, char* argv[]) { + test_unit_prefix_is_valid(); + test_unit_name_change_suffix(); + test_unit_name_build(); +- test_service_unit_name_is_valid(); + test_slice_name_is_valid(); + test_build_subslice(); + test_build_parent_slice(); +diff --git a/test/TEST-15-DROPIN/test-dropin.sh b/test/TEST-15-DROPIN/test-dropin.sh +index def2e03304..7836c6535d 100755 +--- a/test/TEST-15-DROPIN/test-dropin.sh ++++ b/test/TEST-15-DROPIN/test-dropin.sh +@@ -102,18 +102,18 @@ test_basic_dropins () { + check_ok b Wants c.service + systemctl stop a c + +- echo "*** test -.service.d/ top level drop-in" ++ echo "*** test service.d/ top level drop-in" + create_services a b + check_ko a ExecCondition "/bin/echo a" + check_ko b ExecCondition "/bin/echo b" +- mkdir -p /usr/lib/systemd/system/-.service.d +- cat >/usr/lib/systemd/system/-.service.d/override.conf </usr/lib/systemd/system/service.d/override.conf < +Date: Tue, 17 Dec 2019 15:47:37 +0200 +Subject: [PATCH] shared/dropin: fix assert for invalid drop-in + +Don't try to show top level drop-in for non-existent units or when trying to +instantiate non-instantiated units: + +$ systemctl cat nonexistent@.service +Assertion 'name' failed at src/shared/dropin.c:143, function unit_file_find_dirs(). Aborting. +$ systemctl cat systemd-journald@.service +Assertion 'name' failed at src/shared/dropin.c:143, function unit_file_find_dirs(). Aborting. + +(cherry picked from commit 7a670b1dd981c645064f69faf85b04620aadbafb) + +Resolves: #2051520 +--- + src/shared/dropin.c | 23 ++++++++++++----------- + test/TEST-15-DROPIN/test-dropin.sh | 14 ++++++++++++++ + 2 files changed, 26 insertions(+), 11 deletions(-) + +diff --git a/src/shared/dropin.c b/src/shared/dropin.c +index bd2a3c0feb..11ed4c7184 100644 +--- a/src/shared/dropin.c ++++ b/src/shared/dropin.c +@@ -236,7 +236,6 @@ int unit_file_find_dropin_paths( + char ***ret) { + + _cleanup_strv_free_ char **dirs = NULL; +- UnitType type = _UNIT_TYPE_INVALID; + char *name, **p; + Iterator i; + int r; +@@ -246,22 +245,24 @@ int unit_file_find_dropin_paths( + /* All the names in the unit are of the same type so just grab one. */ + name = (char*) set_first(names); + if (name) { ++ UnitType type = _UNIT_TYPE_INVALID; ++ + type = unit_name_to_type(name); + if (type < 0) + return log_error_errno(EINVAL, + "Failed to to derive unit type from unit name: %s", + name); +- } + +- /* Special top level drop in for ".". Add this first as it's the most generic +- * and should be able to be overridden by more specific drop-ins. */ +- STRV_FOREACH(p, lookup_path) +- (void) unit_file_find_dirs(original_root, +- unit_path_cache, +- *p, +- unit_type_to_string(type), +- dir_suffix, +- &dirs); ++ /* Special top level drop in for ".". Add this first as it's the most generic ++ * and should be able to be overridden by more specific drop-ins. */ ++ STRV_FOREACH(p, lookup_path) ++ (void) unit_file_find_dirs(original_root, ++ unit_path_cache, ++ *p, ++ unit_type_to_string(type), ++ dir_suffix, ++ &dirs); ++ } + + SET_FOREACH(name, names, i) + STRV_FOREACH(p, lookup_path) +diff --git a/test/TEST-15-DROPIN/test-dropin.sh b/test/TEST-15-DROPIN/test-dropin.sh +index 7836c6535d..5419169f7b 100755 +--- a/test/TEST-15-DROPIN/test-dropin.sh ++++ b/test/TEST-15-DROPIN/test-dropin.sh +@@ -289,9 +289,23 @@ EOF + clear_services a b + } + ++test_invalid_dropins () { ++ echo "Testing invalid dropins..." ++ # Assertion failed on earlier versions, command exits unsuccessfully on later versions ++ systemctl cat nonexistent@.service || true ++ create_services a ++ systemctl daemon-reload ++ # Assertion failed on earlier versions, command exits unsuccessfully on later versions ++ systemctl cat a@.service || true ++ systemctl stop a ++ clear_services a ++ return 0 ++} ++ + test_basic_dropins + test_template_dropins + test_alias_dropins + test_masked_dropins ++test_invalid_dropins + + touch /testok diff --git a/SOURCES/0748-udev-fix-slot-based-network-names-on-s390.patch b/SOURCES/0748-udev-fix-slot-based-network-names-on-s390.patch new file mode 100644 index 0000000..338ccc2 --- /dev/null +++ b/SOURCES/0748-udev-fix-slot-based-network-names-on-s390.patch @@ -0,0 +1,132 @@ +From 2e7f41bd0632312d00d472a73a312218a29ce65b Mon Sep 17 00:00:00 2001 +From: Viktor Mihajlovski +Date: Thu, 18 Mar 2021 11:03:34 +0100 +Subject: [PATCH] udev: fix slot based network names on s390 + +The s390 PCI driver assigns the hotplug slot name from the +function_id attribute of the PCI device using a 8 char hexadecimal +format to match the underlying firmware/hypervisor notation. + +Further, there's always a one-to-one mapping between a PCI +function and a hotplug slot, as individual functions can +hot plugged even for multi-function devices. + +As the generic matching code will always try to parse the slot +name in /sys/bus/pci/slots as a positive decimal number, either +a wrong value might be produced for ID_NET_NAME_SLOT if +the slot name consists of decimal numbers only, or none at all +if a character in the range from 'a' to 'f' is encountered. + +Additionally, the generic code assumes that two interfaces +share a hotplug slot, if they differ only in the function part +of the PCI address. E.g., for an interface with the PCI address +dddd:bb:aa.f, it will match the device to the first slot with +an address dddd:bb:aa. As more than one slot may have this address +for the s390 PCI driver, the wrong slot may be selected. + +To resolve this we're adding a new naming schema version with the +flag NAMING_SLOT_FUNCTION_ID, which enables the correct matching +of hotplug slots if the device has an attribute named function_id. +The ID_NET_NAME_SLOT property will only be produced if there's +a file /sys/bus/pci/slots/ where matches +the value of /sys/bus/pci/devices/.../function_id in 8 char +hex notation. + +Fixes #19016 +See also #19078 + +Related: #1939914 + +(cherry picked from commit a496a238e8ee66ce25ad13a3f46549b2e2e979fc) +--- + man/systemd.net-naming-scheme.xml | 10 +++++++++ + src/udev/udev-builtin-net_id.c | 34 +++++++++++++++++++++++++++++++ + 2 files changed, 44 insertions(+) + +diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml +index fe1aa4b654..e42c93eaad 100644 +--- a/man/systemd.net-naming-scheme.xml ++++ b/man/systemd.net-naming-scheme.xml +@@ -313,6 +313,16 @@ + Same as naming scheme rhel-8.4. + + ++ ++ rhel-8.7 ++ ++ PCI hotplug slot names for the s390 PCI driver are a hexadecimal representation ++ of the function_id device attribute. This attribute is now used to build the ++ ID_NET_NAME_SLOT. Before that, all slot names were parsed as decimal ++ numbers, which could either result in an incorrect value of the ID_NET_NAME_SLOT ++ property or none at all. ++ ++ + Note that latest may be used to denote the latest scheme known to this + particular version of systemd. + +diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c +index 386d74ca5e..b57227a09f 100644 +--- a/src/udev/udev-builtin-net_id.c ++++ b/src/udev/udev-builtin-net_id.c +@@ -126,6 +126,7 @@ typedef enum NamingSchemeFlags { + NAMING_SR_IOV_V = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/ + NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */ + NAMING_BRIDGE_NO_SLOT = 1 << 9, /* Don't use PCI hotplug slot information if the corresponding device is a PCI bridge */ ++ NAMING_SLOT_FUNCTION_ID = 1 << 10, /* Use function_id if present to identify PCI hotplug slots */ + + /* And now the masks that combine the features above */ + NAMING_V238 = 0, +@@ -137,6 +138,7 @@ typedef enum NamingSchemeFlags { + NAMING_RHEL_8_4 = NAMING_V239|NAMING_BRIDGE_NO_SLOT, + NAMING_RHEL_8_5 = NAMING_RHEL_8_4, + NAMING_RHEL_8_6 = NAMING_RHEL_8_4, ++ NAMING_RHEL_8_7 = NAMING_RHEL_8_4|NAMING_SLOT_FUNCTION_ID, + + _NAMING_SCHEME_FLAGS_INVALID = -1, + } NamingSchemeFlags; +@@ -156,6 +158,7 @@ static const NamingScheme naming_schemes[] = { + { "rhel-8.4", NAMING_RHEL_8_4 }, + { "rhel-8.5", NAMING_RHEL_8_5 }, + { "rhel-8.6", NAMING_RHEL_8_6 }, ++ { "rhel-8.7", NAMING_RHEL_8_7 }, + /* … add more schemes here, as the logic to name devices is updated … */ + }; + +@@ -477,6 +480,37 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { + + hotplug_slot_dev = names->pcidev; + while (hotplug_slot_dev) { ++ if (!udev_device_get_sysname(hotplug_slot_dev)) ++ continue; ++ ++ /* The /function_id attribute is unique to the s390 PCI driver. ++ If present, we know that the slot's directory name for this device is ++ /sys/bus/pci/XXXXXXXX/ where XXXXXXXX is the fixed length 8 hexadecimal ++ character string representation of function_id. ++ Therefore we can short cut here and just check for the existence of ++ the slot directory. As this directory has to exist, we're emitting a ++ debug message for the unlikely case it's not found. ++ Note that the domain part of doesn't belong to the slot name here ++ because there's a 1-to-1 relationship between PCI function and its hotplug ++ slot. ++ */ ++ if (naming_scheme_has(NAMING_SLOT_FUNCTION_ID)) { ++ attr = udev_device_get_sysattr_value(hotplug_slot_dev, "function_id"); ++ if (attr) { ++ int function_id; ++ _cleanup_free_ char *str; ++ ++ if (safe_atoi(attr, &function_id) >= 0 && ++ asprintf(&str, "%s/%08x/", slots, function_id) >= 0 && ++ access(str, R_OK) == 0) { ++ hotplug_slot = function_id; ++ domain = 0; ++ } else ++ log_debug("No matching slot for function_id (%s).", attr); ++ break; ++ } ++ } ++ + FOREACH_DIRENT_ALL(dent, dir, break) { + int i, r; + char str[PATH_MAX]; diff --git a/SOURCES/0749-udev-add-missing-initialization-to-fix-freeing-inval.patch b/SOURCES/0749-udev-add-missing-initialization-to-fix-freeing-inval.patch new file mode 100644 index 0000000..234cd72 --- /dev/null +++ b/SOURCES/0749-udev-add-missing-initialization-to-fix-freeing-inval.patch @@ -0,0 +1,26 @@ +From e6def2e6be6a1cb87874cf8589ccdcb6ee3eec1e Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 7 Apr 2021 19:09:50 +0900 +Subject: [PATCH] udev: add missing initialization to fix freeing invalid + address + +Releated: #1939914 + +(cherry picked from commit b08c3fbe0e3f310b520d17be92110b4cb96a5f2c) +--- + src/udev/udev-builtin-net_id.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c +index b57227a09f..816661fb93 100644 +--- a/src/udev/udev-builtin-net_id.c ++++ b/src/udev/udev-builtin-net_id.c +@@ -498,7 +498,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { + attr = udev_device_get_sysattr_value(hotplug_slot_dev, "function_id"); + if (attr) { + int function_id; +- _cleanup_free_ char *str; ++ _cleanup_free_ char *str = NULL; + + if (safe_atoi(attr, &function_id) >= 0 && + asprintf(&str, "%s/%08x/", slots, function_id) >= 0 && diff --git a/SOURCES/0750-udev-it-is-not-necessary-that-the-path-is-readable.patch b/SOURCES/0750-udev-it-is-not-necessary-that-the-path-is-readable.patch new file mode 100644 index 0000000..bc6dc29 --- /dev/null +++ b/SOURCES/0750-udev-it-is-not-necessary-that-the-path-is-readable.patch @@ -0,0 +1,25 @@ +From 100324ef0d911913e09db71e030a5ba137ac357e Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 7 Apr 2021 19:19:45 +0900 +Subject: [PATCH] udev: it is not necessary that the path is readable + +Related: #1939914 + +(cherry picked from commit 70c35e4bfd64f24c7cb3536bdf63af537e0f2971) +--- + src/udev/udev-builtin-net_id.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c +index 816661fb93..ba7638fcb8 100644 +--- a/src/udev/udev-builtin-net_id.c ++++ b/src/udev/udev-builtin-net_id.c +@@ -502,7 +502,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { + + if (safe_atoi(attr, &function_id) >= 0 && + asprintf(&str, "%s/%08x/", slots, function_id) >= 0 && +- access(str, R_OK) == 0) { ++ access(str, F_OK) == 0) { + hotplug_slot = function_id; + domain = 0; + } else diff --git a/SOURCES/0751-udev-allow-onboard-index-up-to-65535.patch b/SOURCES/0751-udev-allow-onboard-index-up-to-65535.patch new file mode 100644 index 0000000..61c9d74 --- /dev/null +++ b/SOURCES/0751-udev-allow-onboard-index-up-to-65535.patch @@ -0,0 +1,100 @@ +From 033998c21f01e7b7d91e4aa51a358f8016f3740a Mon Sep 17 00:00:00 2001 +From: Viktor Mihajlovski +Date: Tue, 27 Apr 2021 15:25:16 +0200 +Subject: [PATCH] udev: allow onboard index up to 65535 + +The maximum allowed value of the sysfs device index entry was limited to +16383 (2^14-1) to avoid the generation of unreasonable onboard interface +names. +For s390 the index can assume a value of up to 65535 (2^16-1) which is +now allowed depending on the new naming flag NAMING_16BIT_INDEX. +Larger index values are considered unreasonable and remain to be +ignored. + +Related: #1939914 + +(cherry picked from commit 5a7eb46c0206411d380543021291b4bca0b6f59f) +--- + man/systemd.net-naming-scheme.xml | 7 ++++++- + src/udev/udev-builtin-net_id.c | 22 +++++++++++++++------- + 2 files changed, 21 insertions(+), 8 deletions(-) + +diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml +index e42c93eaad..a567483995 100644 +--- a/man/systemd.net-naming-scheme.xml ++++ b/man/systemd.net-naming-scheme.xml +@@ -320,7 +320,12 @@ + of the function_id device attribute. This attribute is now used to build the + ID_NET_NAME_SLOT. Before that, all slot names were parsed as decimal + numbers, which could either result in an incorrect value of the ID_NET_NAME_SLOT +- property or none at all. ++ property or none at all. ++ ++ Some firmware and hypervisor implementations report unreasonable high numbers for the onboard ++ index. To prevent the generation of bogus onbard interface names, index numbers greater than 16381 ++ (2^14-1) were ignored. For s390 PCI devices index values up to 65535 (2^16-1) are valid. To account ++ for that, the limit is increased to now 65535. + + + Note that latest may be used to denote the latest scheme known to this +diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c +index ba7638fcb8..df84acf27c 100644 +--- a/src/udev/udev-builtin-net_id.c ++++ b/src/udev/udev-builtin-net_id.c +@@ -104,7 +104,8 @@ + #include "udev.h" + #include "udev-util.h" + +-#define ONBOARD_INDEX_MAX (16*1024-1) ++#define ONBOARD_14BIT_INDEX_MAX ((1U << 14) - 1) ++#define ONBOARD_16BIT_INDEX_MAX ((1U << 16) - 1) + + /* So here's the deal: net_id is supposed to be an excercise in providing stable names for network devices. However, we + * also want to keep updating the naming scheme used in future versions of net_id. These two goals of course are +@@ -127,6 +128,7 @@ typedef enum NamingSchemeFlags { + NAMING_NPAR_ARI = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */ + NAMING_BRIDGE_NO_SLOT = 1 << 9, /* Don't use PCI hotplug slot information if the corresponding device is a PCI bridge */ + NAMING_SLOT_FUNCTION_ID = 1 << 10, /* Use function_id if present to identify PCI hotplug slots */ ++ NAMING_16BIT_INDEX = 1 << 11, /* Allow full 16-bit for the onboard index */ + + /* And now the masks that combine the features above */ + NAMING_V238 = 0, +@@ -138,7 +140,7 @@ typedef enum NamingSchemeFlags { + NAMING_RHEL_8_4 = NAMING_V239|NAMING_BRIDGE_NO_SLOT, + NAMING_RHEL_8_5 = NAMING_RHEL_8_4, + NAMING_RHEL_8_6 = NAMING_RHEL_8_4, +- NAMING_RHEL_8_7 = NAMING_RHEL_8_4|NAMING_SLOT_FUNCTION_ID, ++ NAMING_RHEL_8_7 = NAMING_RHEL_8_4|NAMING_SLOT_FUNCTION_ID|NAMING_16BIT_INDEX, + + _NAMING_SCHEME_FLAGS_INVALID = -1, + } NamingSchemeFlags; +@@ -326,6 +328,16 @@ out_unref: + return r; + } + ++static bool is_valid_onboard_index(unsigned long idx) { ++ /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to ++ * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We ++ * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network ++ * interface a system might have. Ideally the kernel would already filter this crap for us, but it ++ * doesn't currently. The initial cut-off value (2^14-1) was too conservative for s390 PCI which ++ * allows for index values up 2^16-1 which is now enabled with the NAMING_16BIT_INDEX naming flag. */ ++ return idx <= (naming_scheme_has(NAMING_16BIT_INDEX) ? ONBOARD_16BIT_INDEX_MAX : ONBOARD_14BIT_INDEX_MAX); ++} ++ + /* retrieve on-board index number and label from firmware */ + static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) { + unsigned dev_port = 0; +@@ -346,11 +358,7 @@ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) { + if (idx <= 0) + return -EINVAL; + +- /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to report for +- * example). Let's define a cut-off where we don't consider the index reliable anymore. We pick some arbitrary +- * cut-off, which is somewhere beyond the realistic number of physical network interface a system might +- * have. Ideally the kernel would already filter his crap for us, but it doesn't currently. */ +- if (idx > ONBOARD_INDEX_MAX) ++ if (!is_valid_onboard_index(idx)) + return -ENOENT; + + /* kernel provided port index for multiple ports on a single PCI function */ diff --git a/SOURCES/0752-Revert-basic-use-comma-as-separator-in-cpuset-cgroup.patch b/SOURCES/0752-Revert-basic-use-comma-as-separator-in-cpuset-cgroup.patch new file mode 100644 index 0000000..e4bfbc1 --- /dev/null +++ b/SOURCES/0752-Revert-basic-use-comma-as-separator-in-cpuset-cgroup.patch @@ -0,0 +1,98 @@ +From 1ad8be47cd41f017faa5a9ca9614cbcbe784d43b Mon Sep 17 00:00:00 2001 +From: Jacek Migacz +Date: Mon, 25 Apr 2022 21:12:40 +0200 +Subject: [PATCH] Revert "basic: use comma as separator in cpuset cgroup cpu + ranges" + +This reverts commit 9fe3b9c7165afeedcf9f31959c436bcec233bb4d. + +RHEL-only + +Resolves: #1858220 +--- + src/basic/cpu-set-util.c | 45 ---------------------------------------- + src/basic/cpu-set-util.h | 1 - + src/core/cgroup.c | 2 +- + 3 files changed, 1 insertion(+), 47 deletions(-) + +diff --git a/src/basic/cpu-set-util.c b/src/basic/cpu-set-util.c +index 1922c95864..db2e1d6c97 100644 +--- a/src/basic/cpu-set-util.c ++++ b/src/basic/cpu-set-util.c +@@ -88,51 +88,6 @@ char *cpu_set_to_range_string(const CPUSet *set) { + return TAKE_PTR(str) ?: strdup(""); + } + +-/* XXX(msekleta): this is the workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1819152, remove in 8.3 */ +-char *cpu_set_to_range_string_kernel(const CPUSet *set) { +- unsigned range_start = 0, range_end; +- _cleanup_free_ char *str = NULL; +- size_t allocated = 0, len = 0; +- bool in_range = false; +- int r; +- +- for (unsigned i = 0; i < set->allocated * 8; i++) +- if (CPU_ISSET_S(i, set->allocated, set->set)) { +- if (in_range) +- range_end++; +- else { +- range_start = range_end = i; +- in_range = true; +- } +- } else if (in_range) { +- in_range = false; +- +- if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(unsigned))) +- return NULL; +- +- if (range_end > range_start) +- r = sprintf(str + len, len > 0 ? ",%d-%d" : "%d-%d", range_start, range_end); +- else +- r = sprintf(str + len, len > 0 ? ",%d" : "%d", range_start); +- assert_se(r > 0); +- len += r; +- } +- +- if (in_range) { +- if (!GREEDY_REALLOC(str, allocated, len + 2 + 2 * DECIMAL_STR_MAX(int))) +- return NULL; +- +- if (range_end > range_start) +- r = sprintf(str + len, len > 0 ? ",%d-%d" : "%d-%d", range_start, range_end); +- else +- r = sprintf(str + len, len > 0 ? ",%d" : "%d", range_start); +- assert_se(r > 0); +- } +- +- return TAKE_PTR(str) ?: strdup(""); +-} +- +- + int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus) { + size_t need; + +diff --git a/src/basic/cpu-set-util.h b/src/basic/cpu-set-util.h +index 795be807af..406b08ee11 100644 +--- a/src/basic/cpu-set-util.h ++++ b/src/basic/cpu-set-util.h +@@ -27,7 +27,6 @@ int cpu_set_add_all(CPUSet *a, const CPUSet *b); + + char* cpu_set_to_string(const CPUSet *a); + char *cpu_set_to_range_string(const CPUSet *a); +-char *cpu_set_to_range_string_kernel(const CPUSet *a); + int cpu_set_realloc(CPUSet *cpu_set, unsigned ncpus); + + int parse_cpu_set_full( +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index f02cc31c6e..f89bce3d61 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -687,7 +687,7 @@ static void cgroup_apply_unified_cpuset(Unit *u, CPUSet cpus, const char *name) + _cleanup_free_ char *buf = NULL; + int r; + +- buf = cpu_set_to_range_string_kernel(&cpus); ++ buf = cpu_set_to_range_string(&cpus); + if (!buf) + return; + diff --git a/SOURCES/0753-acpi-fpdt-mark-structures-as-packed.patch b/SOURCES/0753-acpi-fpdt-mark-structures-as-packed.patch new file mode 100644 index 0000000..075c84e --- /dev/null +++ b/SOURCES/0753-acpi-fpdt-mark-structures-as-packed.patch @@ -0,0 +1,51 @@ +From 45670b65ccc1d41a32b83217ba9a78c9eed5fc02 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 23 Apr 2020 08:49:10 +0200 +Subject: [PATCH] acpi-fpdt: mark structures as packed + +Let's make sure the alignment doesn't matter. + +(cherry picked from commit 49490c1d353bc920cbf73f4c71e9c35d2e3eb8b1) + +Related: #2047373 +--- + src/shared/acpi-fpdt.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/shared/acpi-fpdt.c b/src/shared/acpi-fpdt.c +index d565ebd43e..38c464c912 100644 +--- a/src/shared/acpi-fpdt.c ++++ b/src/shared/acpi-fpdt.c +@@ -23,7 +23,7 @@ struct acpi_table_header { + uint32_t oem_revision; + char asl_compiler_id[4]; + uint32_t asl_compiler_revision; +-}; ++} _packed_; + + enum { + ACPI_FPDT_TYPE_BOOT = 0, +@@ -36,12 +36,12 @@ struct acpi_fpdt_header { + uint8_t revision; + uint8_t reserved[4]; + uint64_t ptr; +-}; ++} _packed_; + + struct acpi_fpdt_boot_header { + char signature[4]; + uint32_t length; +-}; ++} _packed_; + + enum { + ACPI_FPDT_S3PERF_RESUME_REC = 0, +@@ -59,7 +59,7 @@ struct acpi_fpdt_boot { + uint64_t startup_start; + uint64_t exit_services_entry; + uint64_t exit_services_exit; +-}; ++} _packed; + + int acpi_get_boot_usec(usec_t *loader_start, usec_t *loader_exit) { + _cleanup_free_ char *buf = NULL; diff --git a/SOURCES/0754-core-slice-make-slice_freezer_action-return-0-if-fre.patch b/SOURCES/0754-core-slice-make-slice_freezer_action-return-0-if-fre.patch new file mode 100644 index 0000000..15e1d43 --- /dev/null +++ b/SOURCES/0754-core-slice-make-slice_freezer_action-return-0-if-fre.patch @@ -0,0 +1,46 @@ +From 1f4af2e456675c6226857ee0c8127ff4b3d1d18a Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 6 May 2022 14:01:22 +0900 +Subject: [PATCH] core/slice: make slice_freezer_action() return 0 if freezing + state is unchanged + +Fixes #23278. + +(cherry picked from commit d171e72e7afa11b238ba20758384d223b0c76e39) + +Related: #2047373 +--- + src/core/slice.c | 6 +----- + src/core/unit.c | 2 ++ + 2 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/src/core/slice.c b/src/core/slice.c +index c10e830917..34f3c84bf9 100644 +--- a/src/core/slice.c ++++ b/src/core/slice.c +@@ -395,11 +395,7 @@ static int slice_freezer_action(Unit *s, FreezerAction action) { + return r; + } + +- r = unit_cgroup_freezer_action(s, action); +- if (r < 0) +- return r; +- +- return 1; ++ return unit_cgroup_freezer_action(s, action); + } + + static int slice_freeze(Unit *s) { +diff --git a/src/core/unit.c b/src/core/unit.c +index e2c61ce866..bd79578255 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -5622,6 +5622,8 @@ static int unit_freezer_action(Unit *u, FreezerAction action) { + if (r <= 0) + return r; + ++ assert(IN_SET(u->freezer_state, FREEZER_FREEZING, FREEZER_THAWING)); ++ + return 1; + } + diff --git a/SOURCES/0755-core-unit-fix-use-after-free.patch b/SOURCES/0755-core-unit-fix-use-after-free.patch new file mode 100644 index 0000000..fbb9dd7 --- /dev/null +++ b/SOURCES/0755-core-unit-fix-use-after-free.patch @@ -0,0 +1,29 @@ +From f307c633acd12d59800a760b1c45fad8c79b6f49 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 9 May 2022 00:56:05 +0900 +Subject: [PATCH] core/unit: fix use-after-free + +Fixes #23312. + +(cherry picked from commit 734582830b58e000a26e18807ea277c18778573c) + +Related: #2047373 +--- + src/core/unit.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index bd79578255..68affa2c0e 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -580,8 +580,8 @@ void unit_free(Unit *u) { + + unit_dequeue_rewatch_pids(u); + +- sd_bus_slot_unref(u->match_bus_slot); +- sd_bus_track_unref(u->bus_track); ++ u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); ++ u->bus_track = sd_bus_track_unref(u->bus_track); + u->deserialized_refs = strv_free(u->deserialized_refs); + u->pending_freezer_message = sd_bus_message_unref(u->pending_freezer_message); + diff --git a/SOURCES/0756-sd-bus-fix-reference-counter-to-be-incremented.patch b/SOURCES/0756-sd-bus-fix-reference-counter-to-be-incremented.patch new file mode 100644 index 0000000..16390d0 --- /dev/null +++ b/SOURCES/0756-sd-bus-fix-reference-counter-to-be-incremented.patch @@ -0,0 +1,58 @@ +From 39e9bd0412bef0c37d487834b8be3a78e28cb804 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 17 Apr 2022 07:05:07 +0900 +Subject: [PATCH] sd-bus: fix reference counter to be incremented + +Fixes #23097. + +(cherry picked from commit b21f237d996c8c18991a68e1204f060d07dc4745) + +[msekleta: This commit also contains the hunk from c2d7dd35d2 +(in sd_bus_track_remove_name). I've decided to not backport that commit +fully because of conflicts and because its was made largely irrelevant +by 7f40cb7c86] + +Related: #2047373 +--- + src/libsystemd/sd-bus/bus-track.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c +index 16bf615f50..b1ec5ecbbb 100644 +--- a/src/libsystemd/sd-bus/bus-track.c ++++ b/src/libsystemd/sd-bus/bus-track.c +@@ -208,12 +208,12 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { + i = hashmap_get(track->names, name); + if (i) { + if (track->recursive) { +- unsigned k = track->n_ref + 1; ++ unsigned k = i->n_ref + 1; + +- if (k < track->n_ref) /* Check for overflow */ ++ if (k < i->n_ref) /* Check for overflow */ + return -EOVERFLOW; + +- track->n_ref = k; ++ i->n_ref = k; + } + + bus_track_remove_from_queue(track); +@@ -281,14 +281,13 @@ _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) { + i = hashmap_get(track->names, name); + if (!i) + return -EUNATCH; +- if (i->n_ref <= 0) +- return -EUNATCH; +- +- i->n_ref--; + +- if (i->n_ref <= 0) ++ assert(i->n_ref >=1); ++ if (i->n_ref <= 1) + return bus_track_remove_name_fully(track, name); + ++ i->n_ref--; ++ + return 1; + } + diff --git a/SOURCES/0757-sd-bus-do-not-read-unused-value.patch b/SOURCES/0757-sd-bus-do-not-read-unused-value.patch new file mode 100644 index 0000000..18346e1 --- /dev/null +++ b/SOURCES/0757-sd-bus-do-not-read-unused-value.patch @@ -0,0 +1,32 @@ +From 480658d6c79f494e820eb3da59a1818b5b7c3c8b Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 17 Apr 2022 07:25:09 +0900 +Subject: [PATCH] sd-bus: do not read unused value + +(cherry picked from commit 6a7ca27740be4229b4c9f540cd610b205ca5752c) + +Related: #2047373 +--- + src/libsystemd/sd-bus/bus-track.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c +index b1ec5ecbbb..b9965d9d64 100644 +--- a/src/libsystemd/sd-bus/bus-track.c ++++ b/src/libsystemd/sd-bus/bus-track.c +@@ -182,13 +182,13 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) { + + static int on_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { + sd_bus_track *track = userdata; +- const char *name, *old, *new; ++ const char *name; + int r; + + assert(message); + assert(track); + +- r = sd_bus_message_read(message, "sss", &name, &old, &new); ++ r = sd_bus_message_read(message, "sss", &name, NULL, NULL); + if (r < 0) + return 0; + diff --git a/SOURCES/0758-sd-bus-do-not-return-negative-errno-when-unknown-nam.patch b/SOURCES/0758-sd-bus-do-not-return-negative-errno-when-unknown-nam.patch new file mode 100644 index 0000000..9676e25 --- /dev/null +++ b/SOURCES/0758-sd-bus-do-not-return-negative-errno-when-unknown-nam.patch @@ -0,0 +1,35 @@ +From 805e13f7016f37c882069f43b5f0c0972d5fdf95 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 17 Apr 2022 07:29:24 +0900 +Subject: [PATCH] sd-bus: do not return negative errno when unknown name is + specified + +When 'recursive' is false, then sd_bus_track_remove_name() does not +return negative errno when unknown name is specified. Let's follow the +same pattern for the case that 'recursive' is true. + +(cherry picked from commit 55bfacc6c33eaf3475762e71172b2ef504be5af8) + +Related: #2047373 +--- + src/libsystemd/sd-bus/bus-track.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c +index b9965d9d64..8893f190a1 100644 +--- a/src/libsystemd/sd-bus/bus-track.c ++++ b/src/libsystemd/sd-bus/bus-track.c +@@ -275,12 +275,9 @@ _public_ int sd_bus_track_remove_name(sd_bus_track *track, const char *name) { + if (!track) /* Treat a NULL track object as an empty track object */ + return 0; + +- if (!track->recursive) +- return bus_track_remove_name_fully(track, name); +- + i = hashmap_get(track->names, name); + if (!i) +- return -EUNATCH; ++ return 0; + + assert(i->n_ref >=1); + if (i->n_ref <= 1) diff --git a/SOURCES/0759-sd-bus-switch-to-a-manual-overflow-check-in-sd_bus_t.patch b/SOURCES/0759-sd-bus-switch-to-a-manual-overflow-check-in-sd_bus_t.patch new file mode 100644 index 0000000..13a748f --- /dev/null +++ b/SOURCES/0759-sd-bus-switch-to-a-manual-overflow-check-in-sd_bus_t.patch @@ -0,0 +1,48 @@ +From 598eecf5c1c948535ca626833bc5cea59060913f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 20 Apr 2022 22:30:22 +0200 +Subject: [PATCH] sd-bus: switch to a manual overflow check in + sd_bus_track_add_name() + +This is generally used in a directly client controllable way, hence we +should handle ref count overflow gracefully, instead of hitting an +assert(). + +As discussed: + +https://github.com/systemd/systemd/pull/23099#discussion_r854341850 +(cherry picked from commit 7f40cb7c86b0fff3a82096a9499570bad9c19fd2) + +[msekleta: We've never switched to using track_item_ref/unref introduced +in c2d7dd35d2 hence we still had potential undefined behavior related to +overflow check and this commit fixes that.] + +Related: #2047373 +--- + src/libsystemd/sd-bus/bus-track.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c +index 8893f190a1..b818e93bec 100644 +--- a/src/libsystemd/sd-bus/bus-track.c ++++ b/src/libsystemd/sd-bus/bus-track.c +@@ -208,12 +208,16 @@ _public_ int sd_bus_track_add_name(sd_bus_track *track, const char *name) { + i = hashmap_get(track->names, name); + if (i) { + if (track->recursive) { +- unsigned k = i->n_ref + 1; ++ assert(i->n_ref > 0); + +- if (k < i->n_ref) /* Check for overflow */ ++ /* Manual oveflow check (instead of a DEFINE_TRIVIAL_REF_FUNC() helper or so), so ++ * that we can return a proper error, given this is almost always called in a ++ * directly client controllable way, and thus better should never hit an assertion ++ * here. */ ++ if (i->n_ref >= UINT_MAX) + return -EOVERFLOW; + +- i->n_ref = k; ++ i->n_ref++; + } + + bus_track_remove_from_queue(track); diff --git a/SOURCES/0760-resolved-let-s-preferably-route-reverse-lookups-for-.patch b/SOURCES/0760-resolved-let-s-preferably-route-reverse-lookups-for-.patch new file mode 100644 index 0000000..922db9a --- /dev/null +++ b/SOURCES/0760-resolved-let-s-preferably-route-reverse-lookups-for-.patch @@ -0,0 +1,194 @@ +From b9844d3dd9d7fdf81d475b81d06a6e9ec821f91d Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 9 Nov 2020 22:22:56 +0100 +Subject: [PATCH] resolved: let's preferably route reverse lookups for local + subnets to matching interfaces + +Let's preferably route traffic for reverse lookups to LLMNR/mDNS/DNS on +the matching interface if the IP address is in the local subnet. Also, +if looking up an IP address of our own host, let's avoid doing +LLMNR/mDNS at all. + +This is useful if "~." is a routing domain to DNS, as it means, local +reverse lookups still go to LLMNR/mDNS, too. + +(cherry picked from commit 13eb76ef06f5d50bbeb58df1744057e41ef2647e) + +Resolves #1739689 +--- + src/resolve/resolved-dns-scope.c | 85 +++++++++++++++++++++++++++++++- + src/resolve/resolved-link.c | 12 +++-- + src/resolve/resolved-link.h | 1 + + 3 files changed, 92 insertions(+), 6 deletions(-) + +diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c +index 38ea7fea0a..8b65813428 100644 +--- a/src/resolve/resolved-dns-scope.c ++++ b/src/resolve/resolved-dns-scope.c +@@ -417,6 +417,65 @@ int dns_scope_socket_tcp(DnsScope *s, int family, const union in_addr_union *add + return dns_scope_socket(s, SOCK_STREAM, family, address, server, port, ret_socket_address); + } + ++static DnsScopeMatch match_subnet_reverse_lookups( ++ DnsScope *s, ++ const char *domain, ++ bool exclude_own) { ++ ++ union in_addr_union ia; ++ LinkAddress *a; ++ int f, r; ++ ++ assert(s); ++ assert(domain); ++ ++ /* Checks whether the specified domain is a reverse address domain (i.e. in the .in-addr.arpa or ++ * .ip6.arpa area), and if so, whether the address matches any of the local subnets of the link the ++ * scope is associated with. If so, our scope should consider itself relevant for any lookup in the ++ * domain, since it apparently refers to hosts on this link's subnet. ++ * ++ * If 'exclude_own' is true this will return DNS_SCOPE_NO for any IP addresses assigned locally. This ++ * is useful for LLMNR/mDNS as we never want to look up our own hostname on LLMNR/mDNS but always use ++ * the locally synthesized one. */ ++ ++ if (!s->link) ++ return _DNS_SCOPE_INVALID; /* No link, hence no local addresses to check */ ++ ++ r = dns_name_address(domain, &f, &ia); ++ if (r < 0) ++ log_debug_errno(r, "Failed to determine whether '%s' is an address domain: %m", domain); ++ if (r <= 0) ++ return _DNS_SCOPE_INVALID; ++ ++ if (s->family != AF_UNSPEC && f != s->family) ++ return _DNS_SCOPE_INVALID; /* Don't look for IPv4 addresses on LLMNR/mDNS over IPv6 and vice versa */ ++ ++ LIST_FOREACH(addresses, a, s->link->addresses) { ++ ++ if (a->family != f) ++ continue; ++ ++ /* Equals our own address? nah, let's not use this scope. The local synthesizer will pick it up for us. */ ++ if (exclude_own && ++ in_addr_equal(f, &a->in_addr, &ia) > 0) ++ return DNS_SCOPE_NO; ++ ++ if (a->prefixlen == UCHAR_MAX) /* don't know subnet mask */ ++ continue; ++ ++ /* Check if the address is in the local subnet */ ++ r = in_addr_prefix_covers(f, &a->in_addr, a->prefixlen, &ia); ++ if (r < 0) ++ log_debug_errno(r, "Failed to determine whether link address covers lookup address '%s': %m", domain); ++ if (r > 0) ++ /* Note that we only claim zero labels match. This is so that this is at the same ++ * priority a DNS scope with "." as routing domain is. */ ++ return DNS_SCOPE_YES + 0; ++ } ++ ++ return _DNS_SCOPE_INVALID; ++} ++ + DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, const char *domain) { + DnsSearchDomain *d; + +@@ -455,6 +514,7 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co + + case DNS_PROTOCOL_DNS: { + DnsServer *dns_server; ++ DnsScopeMatch m; + + /* Never route things to scopes that lack DNS servers */ + dns_server = dns_scope_get_dns_server(s); +@@ -485,10 +545,23 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co + dns_name_endswith(domain, "local") == 0) + return DNS_SCOPE_MAYBE; + ++ /* If the IP address to look up matches the local subnet, then implicity synthesizes ++ * DNS_SCOPE_YES_BASE + 0 on this interface, i.e. preferably resolve IP addresses via the DNS ++ * server belonging to this interface. */ ++ m = match_subnet_reverse_lookups(s, domain, false); ++ if (m >= 0) ++ return m; ++ + return DNS_SCOPE_NO; + } + +- case DNS_PROTOCOL_MDNS: ++ case DNS_PROTOCOL_MDNS: { ++ DnsScopeMatch m; ++ ++ m = match_subnet_reverse_lookups(s, domain, true); ++ if (m >= 0) ++ return m; ++ + if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) || + (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) || + (dns_name_endswith(domain, "local") > 0 && /* only resolve names ending in .local via mDNS */ +@@ -497,8 +570,15 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co + return DNS_SCOPE_MAYBE; + + return DNS_SCOPE_NO; ++ } ++ ++ case DNS_PROTOCOL_LLMNR: { ++ DnsScopeMatch m; ++ ++ m = match_subnet_reverse_lookups(s, domain, true); ++ if (m >= 0) ++ return m; + +- case DNS_PROTOCOL_LLMNR: + if ((s->family == AF_INET && dns_name_endswith(domain, "in-addr.arpa") > 0) || + (s->family == AF_INET6 && dns_name_endswith(domain, "ip6.arpa") > 0) || + (dns_name_is_single_label(domain) && /* only resolve single label names via LLMNR */ +@@ -507,6 +587,7 @@ DnsScopeMatch dns_scope_good_domain(DnsScope *s, int ifindex, uint64_t flags, co + return DNS_SCOPE_MAYBE; + + return DNS_SCOPE_NO; ++ } + + default: + assert_not_reached("Unknown scope protocol"); +diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c +index ff2be12415..c42fe5b5f4 100644 +--- a/src/resolve/resolved-link.c ++++ b/src/resolve/resolved-link.c +@@ -776,10 +776,13 @@ int link_address_new(Link *l, LinkAddress **ret, int family, const union in_addr + if (!a) + return -ENOMEM; + +- a->family = family; +- a->in_addr = *in_addr; ++ *a = (LinkAddress) { ++ .family = family, ++ .in_addr = *in_addr, ++ .link = l, ++ .prefixlen = UCHAR_MAX, ++ }; + +- a->link = l; + LIST_PREPEND(addresses, l->addresses, a); + l->n_addresses++; + +@@ -1077,7 +1080,8 @@ int link_address_update_rtnl(LinkAddress *a, sd_netlink_message *m) { + if (r < 0) + return r; + +- sd_rtnl_message_addr_get_scope(m, &a->scope); ++ (void) sd_rtnl_message_addr_get_prefixlen(m, &a->prefixlen); ++ (void) sd_rtnl_message_addr_get_scope(m, &a->scope); + + link_allocate_scopes(a->link); + link_add_rrs(a->link, false); +diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h +index 063d3f35c3..8d52b10950 100644 +--- a/src/resolve/resolved-link.h ++++ b/src/resolve/resolved-link.h +@@ -24,6 +24,7 @@ struct LinkAddress { + + int family; + union in_addr_union in_addr; ++ unsigned char prefixlen; + + unsigned char flags, scope; + diff --git a/SOURCES/0761-unit-don-t-emit-PropertiesChanged-signal-if-adding-a.patch b/SOURCES/0761-unit-don-t-emit-PropertiesChanged-signal-if-adding-a.patch new file mode 100644 index 0000000..90565a6 --- /dev/null +++ b/SOURCES/0761-unit-don-t-emit-PropertiesChanged-signal-if-adding-a.patch @@ -0,0 +1,62 @@ +From a46d3732a4f8baacf1be3e5e0ac152119fe26d4c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +Date: Fri, 2 Oct 2020 17:30:35 +0200 +Subject: [PATCH] unit: don't emit PropertiesChanged signal if adding a + dependency to a unit is a no-op + +(cherry picked from commit 5177cb0a9add4ae568cff6e6f7c2b3c77760c343) + +Resolves: #1948480 +--- + src/core/unit.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 68affa2c0e..e3e534ea2e 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -2818,6 +2818,9 @@ int unit_add_dependency( + }; + Unit *original_u = u, *original_other = other; + int r; ++ /* Helper to know whether sending a notification is necessary or not: ++ * if the dependency is already there, no need to notify! */ ++ bool noop = true; + + assert(u); + assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX); +@@ -2842,24 +2845,33 @@ int unit_add_dependency( + r = unit_add_dependency_hashmap(u->dependencies + d, other, mask, 0); + if (r < 0) + return r; ++ else if (r > 0) ++ noop = false; + + if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID && inverse_table[d] != d) { + r = unit_add_dependency_hashmap(other->dependencies + inverse_table[d], u, 0, mask); + if (r < 0) + return r; ++ else if (r > 0) ++ noop = false; + } + + if (add_reference) { + r = unit_add_dependency_hashmap(u->dependencies + UNIT_REFERENCES, other, mask, 0); + if (r < 0) + return r; ++ else if (r > 0) ++ noop = false; + + r = unit_add_dependency_hashmap(other->dependencies + UNIT_REFERENCED_BY, u, 0, mask); + if (r < 0) + return r; ++ else if (r > 0) ++ noop = false; + } + +- unit_add_to_dbus_queue(u); ++ if (!noop) ++ unit_add_to_dbus_queue(u); + return 0; + } + diff --git a/SOURCES/0762-tests-make-inverted-tests-actually-count.patch b/SOURCES/0762-tests-make-inverted-tests-actually-count.patch new file mode 100644 index 0000000..4b7adaa --- /dev/null +++ b/SOURCES/0762-tests-make-inverted-tests-actually-count.patch @@ -0,0 +1,34 @@ +From f784cdd269ccba28e3e14b24ecd33ab9db148403 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 7 Apr 2021 23:24:25 +0200 +Subject: [PATCH] tests: make inverted tests actually count +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +"! test ..." does not cause the script to fail, even with set -e. +IIUC, bash treats this command as part of an expression line, as it +would if 'test ... && ...' was used. Failing expression lines do not +terminate the script. + +This fixes the obvious cases by changing '! test' → 'test !'. +Then the inversion happens internally in test and bash will propagate +the failure. + +(cherry picked from commit ffa328f060f437f3e1f0f0cb13513ee3dd9c3da5) + +Related: #2087152 +--- + test/TEST-22-TMPFILES/test-01.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/TEST-22-TMPFILES/test-01.sh b/test/TEST-22-TMPFILES/test-01.sh +index d233e37fb2..b10b5aaa1a 100755 +--- a/test/TEST-22-TMPFILES/test-01.sh ++++ b/test/TEST-22-TMPFILES/test-01.sh +@@ -10,4 +10,4 @@ rm -fr /tmp/test + + echo "e /tmp/test - root root 1d" | systemd-tmpfiles --create - + +-! test -e /tmp/test ++test ! -e /tmp/test diff --git a/SOURCES/0763-TEST-make-failure-tests-actually-fail-on-failure.patch b/SOURCES/0763-TEST-make-failure-tests-actually-fail-on-failure.patch new file mode 100644 index 0000000..c2e8e26 --- /dev/null +++ b/SOURCES/0763-TEST-make-failure-tests-actually-fail-on-failure.patch @@ -0,0 +1,123 @@ +From d153f9ff573b191076b843118e825f71227dbc01 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 8 Apr 2021 01:27:33 +0200 +Subject: [PATCH] TEST-*: make failure tests actually fail on failure + +Here the intent was actually correct, and the tests still pass when the check +is made effective. + +(cherry picked from commit 4e20fe27950e14e8a082a74515f347546a9371d0) + +Related: #2087152 +--- + test/TEST-03-JOBS/test-jobs.sh | 8 ++++---- + test/TEST-04-JOURNAL/test-journal.sh | 4 ++-- + test/TEST-18-FAILUREACTION/testsuite.sh | 2 +- + test/TEST-20-MAINPIDGAMES/testsuite.sh | 14 ++++++++++++-- + test/TEST-23-TYPE-EXEC/testsuite.sh | 4 ++-- + 5 files changed, 21 insertions(+), 11 deletions(-) + +diff --git a/test/TEST-03-JOBS/test-jobs.sh b/test/TEST-03-JOBS/test-jobs.sh +index 42190cf478..4ff53e0ade 100755 +--- a/test/TEST-03-JOBS/test-jobs.sh ++++ b/test/TEST-03-JOBS/test-jobs.sh +@@ -18,7 +18,7 @@ systemctl start --job-mode=ignore-dependencies hello + END_SEC=$(date -u '+%s') + ELAPSED=$(($END_SEC-$START_SEC)) + +-[ "$ELAPSED" -lt 3 ] ++test "$ELAPSED" -lt 3 + + # sleep should still be running, hello not. + systemctl list-jobs > /root/list-jobs.txt +@@ -27,11 +27,11 @@ grep 'hello\.service' /root/list-jobs.txt && exit 1 + systemctl stop sleep.service hello-after-sleep.target + + # Some basic testing that --show-transaction does something useful +-! systemctl is-active systemd-importd ++systemctl is-active systemd-importd && { echo 'unexpected success'; exit 1; } + systemctl -T start systemd-importd + systemctl is-active systemd-importd + systemctl --show-transaction stop systemd-importd +-! systemctl is-active systemd-importd ++systemctl is-active systemd-importd && { echo 'unexpected success'; exit 1; } + + # Test for a crash when enqueuing a JOB_NOP when other job already exists + systemctl start --no-block hello-after-sleep.target +@@ -79,7 +79,7 @@ ELAPSED=$(($END_SEC-$START_SEC)) + + # wait5fail fails, so systemctl should fail + START_SEC=$(date -u '+%s') +-! systemctl start --wait wait2.service wait5fail.service || exit 1 ++systemctl start --wait wait2.service wait5fail.service && { echo 'unexpected success'; exit 1; } + END_SEC=$(date -u '+%s') + ELAPSED=$(($END_SEC-$START_SEC)) + [[ "$ELAPSED" -ge 5 ]] && [[ "$ELAPSED" -le 7 ]] || exit 1 +diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh +index 52a6ee84d1..a3db1a7472 100755 +--- a/test/TEST-04-JOURNAL/test-journal.sh ++++ b/test/TEST-04-JOURNAL/test-journal.sh +@@ -60,8 +60,8 @@ journalctl -b -o export --output-fields=MESSAGE,FOO --output-fields=PRIORITY,MES + grep -q '^__CURSOR=' /output + grep -q '^MESSAGE=foo$' /output + grep -q '^PRIORITY=6$' /output +-! grep -q '^FOO=' /output +-! grep -q '^SYSLOG_FACILITY=' /output ++grep '^FOO=' /output && { echo 'unexpected success'; exit 1; } ++grep '^SYSLOG_FACILITY=' /output && { echo 'unexpected success'; exit 1; } + + # https://github.com/systemd/systemd/issues/13708 + ID=$(journalctl --new-id128 | sed -n 2p) +diff --git a/test/TEST-18-FAILUREACTION/testsuite.sh b/test/TEST-18-FAILUREACTION/testsuite.sh +index 1867cc3c47..21b055d6ef 100755 +--- a/test/TEST-18-FAILUREACTION/testsuite.sh ++++ b/test/TEST-18-FAILUREACTION/testsuite.sh +@@ -5,7 +5,7 @@ set -ex + set -o pipefail + + systemd-run --wait -p FailureAction=poweroff true +-! systemd-run --wait -p SuccessAction=poweroff false ++systemd-run --wait -p SuccessAction=poweroff false && { echo 'unexpected success'; exit 1; } + + if test -f /firstphase ; then + echo OK > /firstphase +diff --git a/test/TEST-20-MAINPIDGAMES/testsuite.sh b/test/TEST-20-MAINPIDGAMES/testsuite.sh +index 0e1a116b07..d1bfdd7a2d 100755 +--- a/test/TEST-20-MAINPIDGAMES/testsuite.sh ++++ b/test/TEST-20-MAINPIDGAMES/testsuite.sh +@@ -128,8 +128,18 @@ test -f /run/mainpidsh3/pid + EOF + chmod 755 /dev/shm/mainpid3.sh + +-# This has to fail, as we shouldn't accept the dangerous PID file, and then inotify-wait on it to be corrected which we never do +-! systemd-run --unit=mainpidsh3.service -p StandardOutput=tty -p StandardError=tty -p Type=forking -p RuntimeDirectory=mainpidsh3 -p PIDFile=/run/mainpidsh3/pid -p DynamicUser=1 -p TimeoutStartSec=2s /dev/shm/mainpid3.sh ++# This has to fail, as we shouldn't accept the dangerous PID file, and then ++# inotify-wait on it to be corrected which we never do. ++systemd-run --unit=mainpidsh3.service \ ++ -p StandardOutput=tty \ ++ -p StandardError=tty \ ++ -p Type=forking \ ++ -p RuntimeDirectory=mainpidsh3 \ ++ -p PIDFile=/run/mainpidsh3/pid \ ++ -p DynamicUser=1 \ ++ -p TimeoutStartSec=2s \ ++ /dev/shm/mainpid3.sh \ ++ && { echo 'unexpected success'; exit 1; } + + # Test that this failed due to timeout, and not some other error + test `systemctl show -p Result --value mainpidsh3.service` = timeout +diff --git a/test/TEST-23-TYPE-EXEC/testsuite.sh b/test/TEST-23-TYPE-EXEC/testsuite.sh +index e0c34cfd04..beb7fd2e38 100755 +--- a/test/TEST-23-TYPE-EXEC/testsuite.sh ++++ b/test/TEST-23-TYPE-EXEC/testsuite.sh +@@ -18,8 +18,8 @@ systemd-run --unit=three -p Type=simple /tmp/brokenbinary + + # And now, do the same with Type=exec, where the latter two should fail + systemd-run --unit=four -p Type=exec /bin/sleep infinity +-! systemd-run --unit=five -p Type=exec -p User=idontexist /bin/sleep infinity +-! systemd-run --unit=six -p Type=exec /tmp/brokenbinary ++systemd-run --unit=five -p Type=exec -p User=idontexist /bin/sleep infinity && { echo 'unexpected success'; exit 1; } ++systemd-run --unit=six -p Type=exec /tmp/brokenbinary && { echo 'unexpected success'; exit 1; } + + # For issue #20933 + diff --git a/SOURCES/0764-ci-Mergify-configuration-update.patch b/SOURCES/0764-ci-Mergify-configuration-update.patch new file mode 100644 index 0000000..7d0a006 --- /dev/null +++ b/SOURCES/0764-ci-Mergify-configuration-update.patch @@ -0,0 +1,69 @@ +From cd8518b7f4ebfda9955bf0b649cf759c45e729f1 Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Mon, 6 Jun 2022 15:40:20 +0200 +Subject: [PATCH] ci(Mergify): configuration update + +Add rules for needs-ci label management + +RHEL-only + +Related: #2087152 +--- + .mergify.yml | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + create mode 100644 .mergify.yml + +diff --git a/.mergify.yml b/.mergify.yml +new file mode 100644 +index 0000000000..6fa400effd +--- /dev/null ++++ b/.mergify.yml +@@ -0,0 +1,48 @@ ++# doc: https://docs.mergify.com ++--- ++ ++pull_request_rules: ++ - name: Add `needs-ci` label on CI fail ++ conditions: ++ - or: ++ # Unit tests ++ - -check-success=build (stream8, GCC) ++ - -check-success=build (stream8, GCC_ASAN) ++ # CentOS Stream CI ++ - -check-success=CentOS CI (CentOS Stream 8) ++ # LGTM ++ - and: ++ - "-check-success=LGTM analysis: JavaScript" ++ - "-check-neutral=LGTM analysis: JavaScript" ++ - and: ++ - "-check-success=LGTM analysis: Python" ++ - "-check-neutral=LGTM analysis: Python" ++ - and: ++ - "-check-success=LGTM analysis: C/C++" ++ - "-check-neutral=LGTM analysis: C/C++" ++ actions: ++ label: ++ add: ++ - needs-ci ++ ++ - name: Remove `needs-ci` label on CI success ++ conditions: ++ # Unit tests ++ - check-success=build (stream8, GCC) ++ - check-success=build (stream8, GCC_ASAN) ++ # CentOS Stream CI ++ - check-success=CentOS CI (CentOS Stream 8) ++ # LGTM ++ - or: ++ - "check-success=LGTM analysis: JavaScript" ++ - "check-neutral=LGTM analysis: JavaScript" ++ - or: ++ - "check-success=LGTM analysis: Python" ++ - "check-neutral=LGTM analysis: Python" ++ - or: ++ - "check-success=LGTM analysis: C/C++" ++ - "check-neutral=LGTM analysis: C/C++" ++ actions: ++ label: ++ remove: ++ - needs-ci diff --git a/SOURCES/0765-core-propagate-triggered-unit-in-more-load-states.patch b/SOURCES/0765-core-propagate-triggered-unit-in-more-load-states.patch new file mode 100644 index 0000000..5459390 --- /dev/null +++ b/SOURCES/0765-core-propagate-triggered-unit-in-more-load-states.patch @@ -0,0 +1,122 @@ +From e5121fbb839a36055e5fdab1b9d92dc42f495f29 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 11 Sep 2020 19:49:33 +0200 +Subject: [PATCH] core: propagate triggered unit in more load states + +In 4c2ef3276735ad9f7fccf33f5bdcbe7d8751e7ec we enabled propagating +triggered unit state to the triggering unit for service units in more +load states, so that we don't accidentally stop tracking state +correctly. + +Do the same for our other triggering unit states: automounts, paths, and +timers. + +Also, make this an assertion rather than a simple test. After all it +should never happen that we get called for half-loaded units or units of +the wrong type. The load routines should already have made this +impossible. + +(cherry picked from commit 0377cd2936ae5cac0c9d76a4b58889f121c097c4) + +Related: #2065322 +--- + src/core/automount.c | 4 ++-- + src/core/path.c | 7 +++---- + src/core/socket.c | 4 ++-- + src/core/timer.c | 4 ++-- + src/core/transaction.c | 2 +- + src/core/unit.h | 4 ++++ + 6 files changed, 14 insertions(+), 11 deletions(-) + +diff --git a/src/core/automount.c b/src/core/automount.c +index f212620c8f..c1c513d4a5 100644 +--- a/src/core/automount.c ++++ b/src/core/automount.c +@@ -492,8 +492,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) { + assert(other); + + /* Filter out invocations with bogus state */ +- if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT) +- return; ++ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); ++ assert(other->type == UNIT_MOUNT); + + /* Don't propagate state changes from the mount if we are already down */ + if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)) +diff --git a/src/core/path.c b/src/core/path.c +index 58f490589d..a7c2e0b7c1 100644 +--- a/src/core/path.c ++++ b/src/core/path.c +@@ -696,11 +696,10 @@ static void path_trigger_notify(Unit *u, Unit *other) { + assert(u); + assert(other); + +- /* Invoked whenever the unit we trigger changes state or gains +- * or loses a job */ ++ /* Invoked whenever the unit we trigger changes state or gains or loses a job */ + +- if (other->load_state != UNIT_LOADED) +- return; ++ /* Filter out invocations with bogus state */ ++ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); + + if (p->state == PATH_RUNNING && + UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { +diff --git a/src/core/socket.c b/src/core/socket.c +index 3589300e68..74c1cc70cb 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -3190,8 +3190,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) { + assert(other); + + /* Filter out invocations with bogus state */ +- if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE) +- return; ++ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); ++ assert(other->type == UNIT_SERVICE); + + /* Don't propagate state changes from the service if we are already down */ + if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING)) +diff --git a/src/core/timer.c b/src/core/timer.c +index 684180bf99..990f05fee4 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -745,8 +745,8 @@ static void timer_trigger_notify(Unit *u, Unit *other) { + assert(u); + assert(other); + +- if (other->load_state != UNIT_LOADED) +- return; ++ /* Filter out invocations with bogus state */ ++ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); + + /* Reenable all timers that depend on unit state */ + LIST_FOREACH(value, v, t->values) +diff --git a/src/core/transaction.c b/src/core/transaction.c +index ee5b39fef4..8196aba927 100644 +--- a/src/core/transaction.c ++++ b/src/core/transaction.c +@@ -915,7 +915,7 @@ int transaction_add_job_and_dependencies( + + /* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set + * temporarily. */ +- if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED)) ++ if (!UNIT_IS_LOAD_COMPLETE(unit->load_state)) + return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id); + + if (type != JOB_STOP) { +diff --git a/src/core/unit.h b/src/core/unit.h +index 0cd259411f..b8b914711f 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -47,6 +47,10 @@ static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) { + return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED); + } + ++static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) { ++ return t >= 0 && t < _UNIT_LOAD_STATE_MAX && t != UNIT_STUB && t != UNIT_MERGED; ++} ++ + /* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We + * use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be + * created as a result of multiple "reasons", hence the bitmask. */ diff --git a/SOURCES/0766-core-propagate-unit-start-limit-hit-state-to-trigger.patch b/SOURCES/0766-core-propagate-unit-start-limit-hit-state-to-trigger.patch new file mode 100644 index 0000000..1cf791d --- /dev/null +++ b/SOURCES/0766-core-propagate-unit-start-limit-hit-state-to-trigger.patch @@ -0,0 +1,68 @@ +From afb5e76925f7f4992252cc392dac4dda6c4faf69 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 11 Sep 2020 19:57:09 +0200 +Subject: [PATCH] core: propagate unit start limit hit state to triggering path + unit + +We already do this for socket and automount units, do it for path units +too: if the triggered service keeps hitting the start limit, then fail +the triggering unit too, so that we don#t busy loop forever. + +(Note that this leaves only timer units out in the cold for this kind of +protection, but it shouldn't matter there, as they are naturally +protected against busy loops: they are scheduled by time anyway). + +Fixes: #16669 +(cherry picked from commit 47ab8f73e3468b6e5a48218eacdb830e978d2cfd) + +Related: #2065322 +--- + src/core/path.c | 15 +++++++++++++++ + src/core/path.h | 1 + + 2 files changed, 16 insertions(+) + +diff --git a/src/core/path.c b/src/core/path.c +index a7c2e0b7c1..c2facf0b16 100644 +--- a/src/core/path.c ++++ b/src/core/path.c +@@ -701,6 +701,20 @@ static void path_trigger_notify(Unit *u, Unit *other) { + /* Filter out invocations with bogus state */ + assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); + ++ /* Don't propagate state changes from the triggered unit if we are already down */ ++ if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING)) ++ return; ++ ++ /* Propagate start limit hit state */ ++ if (other->start_limit_hit) { ++ path_enter_dead(p, PATH_FAILURE_UNIT_START_LIMIT_HIT); ++ return; ++ } ++ ++ /* Don't propagate anything if there's still a job queued */ ++ if (other->job) ++ return; ++ + if (p->state == PATH_RUNNING && + UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { + log_unit_debug(UNIT(p), "Got notified about unit deactivation."); +@@ -752,6 +766,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = { + [PATH_SUCCESS] = "success", + [PATH_FAILURE_RESOURCES] = "resources", + [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", ++ [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit", + }; + + DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); +diff --git a/src/core/path.h b/src/core/path.h +index 4d4b6236c2..8a69f06c13 100644 +--- a/src/core/path.h ++++ b/src/core/path.h +@@ -45,6 +45,7 @@ typedef enum PathResult { + PATH_SUCCESS, + PATH_FAILURE_RESOURCES, + PATH_FAILURE_START_LIMIT_HIT, ++ PATH_FAILURE_UNIT_START_LIMIT_HIT, + _PATH_RESULT_MAX, + _PATH_RESULT_INVALID = -1 + } PathResult; diff --git a/SOURCES/0767-core-Move-r-variable-declaration-to-start-of-unit_st.patch b/SOURCES/0767-core-Move-r-variable-declaration-to-start-of-unit_st.patch new file mode 100644 index 0000000..1200bd3 --- /dev/null +++ b/SOURCES/0767-core-Move-r-variable-declaration-to-start-of-unit_st.patch @@ -0,0 +1,31 @@ +From 3392b2fb9e4920e9238a09c774252dc0d0183903 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Sat, 30 Oct 2021 22:12:06 +0100 +Subject: [PATCH] core: Move 'r' variable declaration to start of unit_start() + +(cherry picked from commit 5f37c1a955e399756c4137d22f7f0f45a619f425) + +Related: #2065322 +--- + src/core/unit.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index e3e534ea2e..4fd9af87b7 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1725,12 +1725,13 @@ static bool unit_verify_deps(Unit *u) { + int unit_start(Unit *u) { + UnitActiveState state; + Unit *following; ++ int r; + + assert(u); + + /* Check our ability to start early so that failure conditions don't cause us to enter a busy loop. */ + if (UNIT_VTABLE(u)->can_start) { +- int r = UNIT_VTABLE(u)->can_start(u); ++ r = UNIT_VTABLE(u)->can_start(u); + if (r < 0) + return r; + } diff --git a/SOURCES/0768-core-Delay-start-rate-limit-check-when-starting-a-un.patch b/SOURCES/0768-core-Delay-start-rate-limit-check-when-starting-a-un.patch new file mode 100644 index 0000000..243f795 --- /dev/null +++ b/SOURCES/0768-core-Delay-start-rate-limit-check-when-starting-a-un.patch @@ -0,0 +1,49 @@ +From 8c81776212d0aa44f5ae20635079bd6ce76d16ac Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Tue, 19 Oct 2021 10:45:48 +0100 +Subject: [PATCH] core: Delay start rate limit check when starting a unit + +Doing start rate limit checks before doing condition checks made +condition check failures count towards the start rate limit which +broke existing assumptions (see #21025). Run the rate limit checks +after the condition checks again to restore the previous behaviour. + +(cherry picked from commit ce2146f5256659c7fb53a7d5b9dc551252e27e7e) + +Related: #2065322 +--- + src/core/unit.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 4fd9af87b7..b825e2418c 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1729,13 +1729,6 @@ int unit_start(Unit *u) { + + assert(u); + +- /* Check our ability to start early so that failure conditions don't cause us to enter a busy loop. */ +- if (UNIT_VTABLE(u)->can_start) { +- r = UNIT_VTABLE(u)->can_start(u); +- if (r < 0) +- return r; +- } +- + /* If this is already started, then this will succeed. Note that this will even succeed if this unit + * is not startable by the user. This is relied on to detect when we need to wait for units and when + * waiting is finished. */ +@@ -1790,6 +1783,13 @@ int unit_start(Unit *u) { + return unit_start(following); + } + ++ /* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */ ++ if (UNIT_VTABLE(u)->can_start) { ++ r = UNIT_VTABLE(u)->can_start(u); ++ if (r < 0) ++ return r; ++ } ++ + /* If it is stopped, but we cannot start it, then fail */ + if (!UNIT_VTABLE(u)->start) + return -EBADR; diff --git a/SOURCES/0769-core-Propagate-condition-failed-state-to-triggering-.patch b/SOURCES/0769-core-Propagate-condition-failed-state-to-triggering-.patch new file mode 100644 index 0000000..14f13a7 --- /dev/null +++ b/SOURCES/0769-core-Propagate-condition-failed-state-to-triggering-.patch @@ -0,0 +1,258 @@ +From 2820f1706275acd787c72d9a57892200566f0bbe Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Mon, 18 Oct 2021 14:17:02 +0200 +Subject: [PATCH] core: Propagate condition failed state to triggering units. + +Alternative to https://github.com/systemd/systemd/pull/20531. + +Whenever a service triggered by another unit fails condition checks, +stop the triggering unit to prevent systemd busy looping trying to +start the triggered unit. + +(cherry picked from commit 12ab94a1e4961a39c32efb60b71866ab588d3ea2) + +Resolves: #2065322 +--- + src/core/automount.c | 14 ++++++++++---- + src/core/automount.h | 1 + + src/core/path.c | 16 +++++++++++----- + src/core/path.h | 1 + + src/core/socket.c | 28 +++++++++++++++++++--------- + src/core/socket.h | 1 + + src/core/timer.c | 12 +++++++++--- + src/core/timer.h | 1 + + src/core/unit.c | 10 ++++++++++ + src/core/unit.h | 2 ++ + 10 files changed, 65 insertions(+), 21 deletions(-) + +diff --git a/src/core/automount.c b/src/core/automount.c +index c1c513d4a5..bac3b2fab7 100644 +--- a/src/core/automount.c ++++ b/src/core/automount.c +@@ -776,6 +776,11 @@ static void automount_enter_running(Automount *a) { + goto fail; + } + ++ if (unit_has_failed_condition_or_assert(trigger)) { ++ automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED); ++ return; ++ } ++ + r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) { + log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r)); +@@ -1087,10 +1092,11 @@ static int automount_can_start(Unit *u) { + } + + static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = { +- [AUTOMOUNT_SUCCESS] = "success", +- [AUTOMOUNT_FAILURE_RESOURCES] = "resources", +- [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +- [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit", ++ [AUTOMOUNT_SUCCESS] = "success", ++ [AUTOMOUNT_FAILURE_RESOURCES] = "resources", ++ [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit", ++ [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit", ++ [AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED] = "mount-condition-failed", + }; + + DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult); +diff --git a/src/core/automount.h b/src/core/automount.h +index 21dd1c0774..a7417d195c 100644 +--- a/src/core/automount.h ++++ b/src/core/automount.h +@@ -10,6 +10,7 @@ typedef enum AutomountResult { + AUTOMOUNT_FAILURE_RESOURCES, + AUTOMOUNT_FAILURE_START_LIMIT_HIT, + AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT, ++ AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED, + _AUTOMOUNT_RESULT_MAX, + _AUTOMOUNT_RESULT_INVALID = -1 + } AutomountResult; +diff --git a/src/core/path.c b/src/core/path.c +index c2facf0b16..bf7e1bf3c2 100644 +--- a/src/core/path.c ++++ b/src/core/path.c +@@ -453,7 +453,7 @@ static void path_enter_dead(Path *p, PathResult f) { + else + unit_log_failure(UNIT(p), path_result_to_string(p->result)); + +- path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD); ++ path_set_state(p, p->result == PATH_SUCCESS ? PATH_DEAD : PATH_FAILED); + } + + static void path_enter_running(Path *p) { +@@ -711,6 +711,11 @@ static void path_trigger_notify(Unit *u, Unit *other) { + return; + } + ++ if (unit_has_failed_condition_or_assert(other)) { ++ path_enter_dead(p, PATH_FAILURE_UNIT_CONDITION_FAILED); ++ return; ++ } ++ + /* Don't propagate anything if there's still a job queued */ + if (other->job) + return; +@@ -763,10 +768,11 @@ static const char* const path_type_table[_PATH_TYPE_MAX] = { + DEFINE_STRING_TABLE_LOOKUP(path_type, PathType); + + static const char* const path_result_table[_PATH_RESULT_MAX] = { +- [PATH_SUCCESS] = "success", +- [PATH_FAILURE_RESOURCES] = "resources", +- [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +- [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit", ++ [PATH_SUCCESS] = "success", ++ [PATH_FAILURE_RESOURCES] = "resources", ++ [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", ++ [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit", ++ [PATH_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed", + }; + + DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); +diff --git a/src/core/path.h b/src/core/path.h +index 8a69f06c13..0ad6bd12c6 100644 +--- a/src/core/path.h ++++ b/src/core/path.h +@@ -46,6 +46,7 @@ typedef enum PathResult { + PATH_FAILURE_RESOURCES, + PATH_FAILURE_START_LIMIT_HIT, + PATH_FAILURE_UNIT_START_LIMIT_HIT, ++ PATH_FAILURE_UNIT_CONDITION_FAILED, + _PATH_RESULT_MAX, + _PATH_RESULT_INVALID = -1 + } PathResult; +diff --git a/src/core/socket.c b/src/core/socket.c +index 74c1cc70cb..6f9a0f7575 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -2272,6 +2272,15 @@ static void socket_enter_running(Socket *s, int cfd) { + goto refuse; + } + ++ if (UNIT_ISSET(s->service) && cfd < 0) { ++ Unit *service = UNIT_DEREF(s->service); ++ ++ if (unit_has_failed_condition_or_assert(service)) { ++ socket_enter_dead(s, SOCKET_FAILURE_SERVICE_CONDITION_FAILED); ++ return; ++ } ++ } ++ + if (cfd < 0) { + bool pending = false; + Unit *other; +@@ -3287,15 +3296,16 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = { + DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand); + + static const char* const socket_result_table[_SOCKET_RESULT_MAX] = { +- [SOCKET_SUCCESS] = "success", +- [SOCKET_FAILURE_RESOURCES] = "resources", +- [SOCKET_FAILURE_TIMEOUT] = "timeout", +- [SOCKET_FAILURE_EXIT_CODE] = "exit-code", +- [SOCKET_FAILURE_SIGNAL] = "signal", +- [SOCKET_FAILURE_CORE_DUMP] = "core-dump", +- [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +- [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit", +- [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit" ++ [SOCKET_SUCCESS] = "success", ++ [SOCKET_FAILURE_RESOURCES] = "resources", ++ [SOCKET_FAILURE_TIMEOUT] = "timeout", ++ [SOCKET_FAILURE_EXIT_CODE] = "exit-code", ++ [SOCKET_FAILURE_SIGNAL] = "signal", ++ [SOCKET_FAILURE_CORE_DUMP] = "core-dump", ++ [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit", ++ [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit", ++ [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit", ++ [SOCKET_FAILURE_SERVICE_CONDITION_FAILED] = "service-condition-failed", + }; + + DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult); +diff --git a/src/core/socket.h b/src/core/socket.h +index 2409dbf2a0..b171b94316 100644 +--- a/src/core/socket.h ++++ b/src/core/socket.h +@@ -39,6 +39,7 @@ typedef enum SocketResult { + SOCKET_FAILURE_START_LIMIT_HIT, + SOCKET_FAILURE_TRIGGER_LIMIT_HIT, + SOCKET_FAILURE_SERVICE_START_LIMIT_HIT, ++ SOCKET_FAILURE_SERVICE_CONDITION_FAILED, + _SOCKET_RESULT_MAX, + _SOCKET_RESULT_INVALID = -1 + } SocketResult; +diff --git a/src/core/timer.c b/src/core/timer.c +index 990f05fee4..3c8d89771d 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -567,6 +567,11 @@ static void timer_enter_running(Timer *t) { + return; + } + ++ if (unit_has_failed_condition_or_assert(trigger)) { ++ timer_enter_dead(t, TIMER_FAILURE_UNIT_CONDITION_FAILED); ++ return; ++ } ++ + r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) + goto fail; +@@ -850,9 +855,10 @@ static const char* const timer_base_table[_TIMER_BASE_MAX] = { + DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase); + + static const char* const timer_result_table[_TIMER_RESULT_MAX] = { +- [TIMER_SUCCESS] = "success", +- [TIMER_FAILURE_RESOURCES] = "resources", +- [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit", ++ [TIMER_SUCCESS] = "success", ++ [TIMER_FAILURE_RESOURCES] = "resources", ++ [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit", ++ [TIMER_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed", + }; + + DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult); +diff --git a/src/core/timer.h b/src/core/timer.h +index 833aadb0b8..d23e19d622 100644 +--- a/src/core/timer.h ++++ b/src/core/timer.h +@@ -32,6 +32,7 @@ typedef enum TimerResult { + TIMER_SUCCESS, + TIMER_FAILURE_RESOURCES, + TIMER_FAILURE_START_LIMIT_HIT, ++ TIMER_FAILURE_UNIT_CONDITION_FAILED, + _TIMER_RESULT_MAX, + _TIMER_RESULT_INVALID = -1 + } TimerResult; +diff --git a/src/core/unit.c b/src/core/unit.c +index b825e2418c..c00d30e837 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -5657,6 +5657,16 @@ int unit_thaw_vtable_common(Unit *u) { + return unit_cgroup_freezer_action(u, FREEZER_THAW); + } + ++bool unit_has_failed_condition_or_assert(Unit *u) { ++ if (dual_timestamp_is_set(&u->condition_timestamp) && !u->condition_result) ++ return true; ++ ++ if (dual_timestamp_is_set(&u->assert_timestamp) && !u->assert_result) ++ return true; ++ ++ return false; ++} ++ + static const char* const collect_mode_table[_COLLECT_MODE_MAX] = { + [COLLECT_INACTIVE] = "inactive", + [COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed", +diff --git a/src/core/unit.h b/src/core/unit.h +index b8b914711f..a924bd2e83 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -847,6 +847,8 @@ void unit_thawed(Unit *u); + int unit_freeze_vtable_common(Unit *u); + int unit_thaw_vtable_common(Unit *u); + ++bool unit_has_failed_condition_or_assert(Unit *u); ++ + /* Macros which append UNIT= or USER_UNIT= to the message */ + + #define log_unit_full(unit, level, error, ...) \ diff --git a/SOURCES/0770-unit-check-for-mount-rate-limiting-before-checking-a.patch b/SOURCES/0770-unit-check-for-mount-rate-limiting-before-checking-a.patch new file mode 100644 index 0000000..eca0afc --- /dev/null +++ b/SOURCES/0770-unit-check-for-mount-rate-limiting-before-checking-a.patch @@ -0,0 +1,52 @@ +From 4dbe6568d5bcc082b13f3ef4d323d1669f16095c Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 30 May 2022 11:55:41 +0200 +Subject: [PATCH] unit: check for mount rate limiting before checking active + state + +Having this check as part of mount_can_start() is too late because +UNIT(u)->can_start() virtual method is called after checking the active +state of unit in unit_start(). + +We need to hold off running mount start jobs when /p/s/mountinfo monitor +is rate limited even when given mount unit is already active. + +Fixes #20329 + +(cherry picked from commit b161bc394b2cc8b271dda9208e310cc2af0cc29d) + +Resolves: #2095744 +--- + src/core/mount.c | 3 --- + src/core/unit.c | 4 ++++ + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 9547cb9b29..d37b5731f8 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1999,9 +1999,6 @@ static int mount_can_start(Unit *u) { + + assert(m); + +- if (sd_event_source_is_ratelimited(u->manager->mount_event_source)) +- return -EAGAIN; +- + r = unit_test_start_limit(u); + if (r < 0) { + mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT); +diff --git a/src/core/unit.c b/src/core/unit.c +index c00d30e837..0810bf5a58 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1729,6 +1729,10 @@ int unit_start(Unit *u) { + + assert(u); + ++ /* Let's hold off running start jobs for mount units when /proc/self/mountinfo monitor is rate limited. */ ++ if (u->type == UNIT_MOUNT && sd_event_source_is_ratelimited(u->manager->mount_event_source)) ++ return -EAGAIN; ++ + /* If this is already started, then this will succeed. Note that this will even succeed if this unit + * is not startable by the user. This is relied on to detect when we need to wait for units and when + * waiting is finished. */ diff --git a/SOURCES/0771-mkosi-Add-gnutls-package.patch b/SOURCES/0771-mkosi-Add-gnutls-package.patch new file mode 100644 index 0000000..c8e174b --- /dev/null +++ b/SOURCES/0771-mkosi-Add-gnutls-package.patch @@ -0,0 +1,24 @@ +From 3cdbda49a4eca0dc28f1ebc7923c387bc9b69a9f Mon Sep 17 00:00:00 2001 +From: Jacek Migacz +Date: Sun, 26 Jun 2022 22:11:55 +0200 +Subject: [PATCH] mkosi: Add gnutls package + +RHEL-only + +Resolves: #2101227 +--- + .mkosi/mkosi.fedora | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/.mkosi/mkosi.fedora b/.mkosi/mkosi.fedora +index 63027d9fc7..b0451adec2 100644 +--- a/.mkosi/mkosi.fedora ++++ b/.mkosi/mkosi.fedora +@@ -61,6 +61,7 @@ BuildPackages= + + Packages= + libidn2 ++ gnutls + + BuildDirectory=mkosi.builddir + Cache=mkosi.cache diff --git a/SOURCES/0772-unit-name-tighten-checks-for-building-valid-unit-nam.patch b/SOURCES/0772-unit-name-tighten-checks-for-building-valid-unit-nam.patch new file mode 100644 index 0000000..aa8bb9c --- /dev/null +++ b/SOURCES/0772-unit-name-tighten-checks-for-building-valid-unit-nam.patch @@ -0,0 +1,181 @@ +From e3e479fc9c51e0b6f2c21087e2e78e7c6f55169c Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 25 May 2020 00:34:58 +0200 +Subject: [PATCH] unit-name: tighten checks for building valid unit names + +Let's be more thorough that whenever we build a unit name based on +parameters, that the result is actually a valid user name. If it isn't +fail early. + +This should allows us to catch various issues earlier, in particular +when we synthesize mount units from /proc/self/mountinfo: instead of +actually attempting to allocate a mount unit we will fail much earlier +when we build the name to synthesize the unit under. Failing early is a +good thing generally. + +(cherry picked from commit ab19db01ae1826efb3cbdf6dcb6a14412f8844d4) + +Related: #1940973 +--- + src/basic/unit-name.c | 61 ++++++++++++++++++++++++++++++------------- + 1 file changed, 43 insertions(+), 18 deletions(-) + +diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c +index 614eb8649b..f9b3fafd4d 100644 +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -207,8 +207,9 @@ UnitType unit_name_to_type(const char *n) { + } + + int unit_name_change_suffix(const char *n, const char *suffix, char **ret) { +- char *e, *s; ++ _cleanup_free_ char *s = NULL; + size_t a, b; ++ char *e; + + assert(n); + assert(suffix); +@@ -230,8 +231,12 @@ int unit_name_change_suffix(const char *n, const char *suffix, char **ret) { + return -ENOMEM; + + strcpy(mempcpy(s, n, a), suffix); +- *ret = s; + ++ /* Make sure the name is still valid (i.e. didn't grow too large due to longer suffix) */ ++ if (!unit_name_is_valid(s, UNIT_NAME_ANY)) ++ return -EINVAL; ++ ++ *ret = TAKE_PTR(s); + return 0; + } + +@@ -253,8 +258,8 @@ int unit_name_build(const char *prefix, const char *instance, const char *suffix + } + + int unit_name_build_from_type(const char *prefix, const char *instance, UnitType type, char **ret) { ++ _cleanup_free_ char *s = NULL; + const char *ut; +- char *s; + + assert(prefix); + assert(type >= 0); +@@ -264,19 +269,23 @@ int unit_name_build_from_type(const char *prefix, const char *instance, UnitType + if (!unit_prefix_is_valid(prefix)) + return -EINVAL; + +- if (instance && !unit_instance_is_valid(instance)) +- return -EINVAL; +- + ut = unit_type_to_string(type); + +- if (!instance) +- s = strjoin(prefix, ".", ut); +- else ++ if (instance) { ++ if (!unit_instance_is_valid(instance)) ++ return -EINVAL; ++ + s = strjoin(prefix, "@", instance, ".", ut); ++ } else ++ s = strjoin(prefix, ".", ut); + if (!s) + return -ENOMEM; + +- *ret = s; ++ /* Verify that this didn't grow too large (or otherwise is invalid) */ ++ if (!unit_name_is_valid(s, instance ? UNIT_NAME_INSTANCE : UNIT_NAME_PLAIN)) ++ return -EINVAL; ++ ++ *ret = TAKE_PTR(s); + return 0; + } + +@@ -445,8 +454,8 @@ int unit_name_path_unescape(const char *f, char **ret) { + } + + int unit_name_replace_instance(const char *f, const char *i, char **ret) { ++ _cleanup_free_ char *s = NULL; + const char *p, *e; +- char *s; + size_t a, b; + + assert(f); +@@ -470,7 +479,11 @@ int unit_name_replace_instance(const char *f, const char *i, char **ret) { + + strcpy(mempcpy(mempcpy(s, f, a + 1), i, b), e); + +- *ret = s; ++ /* Make sure the resulting name still is valid, i.e. didn't grow too large */ ++ if (!unit_name_is_valid(s, UNIT_NAME_INSTANCE)) ++ return -EINVAL; ++ ++ *ret = TAKE_PTR(s); + return 0; + } + +@@ -501,8 +514,7 @@ int unit_name_template(const char *f, char **ret) { + } + + int unit_name_from_path(const char *path, const char *suffix, char **ret) { +- _cleanup_free_ char *p = NULL; +- char *s = NULL; ++ _cleanup_free_ char *p = NULL, *s = NULL; + int r; + + assert(path); +@@ -520,7 +532,11 @@ int unit_name_from_path(const char *path, const char *suffix, char **ret) { + if (!s) + return -ENOMEM; + +- *ret = s; ++ /* Refuse this if this got too long or for some other reason didn't result in a valid name */ ++ if (!unit_name_is_valid(s, UNIT_NAME_PLAIN)) ++ return -EINVAL; ++ ++ *ret = TAKE_PTR(s); + return 0; + } + +@@ -548,6 +564,10 @@ int unit_name_from_path_instance(const char *prefix, const char *path, const cha + if (!s) + return -ENOMEM; + ++ /* Refuse this if this got too long or for some other reason didn't result in a valid name */ ++ if (!unit_name_is_valid(s, UNIT_NAME_INSTANCE)) ++ return -EINVAL; ++ + *ret = s; + return 0; + } +@@ -601,7 +621,7 @@ static bool do_escape_mangle(const char *f, bool allow_globs, char *t) { + * If @allow_globs, globs characters are preserved. Otherwise, they are escaped. + */ + int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const char *suffix, char **ret) { +- char *s; ++ _cleanup_free_ char *s = NULL; + int r; + bool mangled; + +@@ -656,7 +676,12 @@ int unit_name_mangle_with_suffix(const char *name, UnitNameMangle flags, const c + if ((!(flags & UNIT_NAME_MANGLE_GLOB) || !string_is_glob(s)) && unit_name_to_type(s) < 0) + strcat(s, suffix); + +- *ret = s; ++ /* Make sure mangling didn't grow this too large (but don't do this check if globbing is allowed, ++ * since globs generally do not qualify as valid unit names) */ ++ if (!FLAGS_SET(flags, UNIT_NAME_MANGLE_GLOB) && !unit_name_is_valid(s, UNIT_NAME_ANY)) ++ return -EINVAL; ++ ++ *ret = TAKE_PTR(s); + return 1; + + good: +@@ -664,7 +689,7 @@ good: + if (!s) + return -ENOMEM; + +- *ret = s; ++ *ret = TAKE_PTR(s); + return 0; + } + diff --git a/SOURCES/0773-core-shorten-long-unit-names-that-are-based-on-paths.patch b/SOURCES/0773-core-shorten-long-unit-names-that-are-based-on-paths.patch new file mode 100644 index 0000000..7705a2c --- /dev/null +++ b/SOURCES/0773-core-shorten-long-unit-names-that-are-based-on-paths.patch @@ -0,0 +1,275 @@ +From f62231a54abff6566415ea82aa8773e61f5688d6 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Tue, 15 Mar 2022 19:02:05 +0100 +Subject: [PATCH] core: shorten long unit names that are based on paths and + append path hash at the end + +Fixes #18077 + +(cherry picked from commit 1d0727e76fd5e9a07cc9991ec9a10ea1d78a99c7) + +Resolves: #1940973 +--- + src/basic/string-util.h | 23 +++++----- + src/basic/unit-name.c | 88 ++++++++++++++++++++++++++++++++++++++- + src/basic/unit-name.h | 3 ++ + src/core/mount.c | 3 ++ + src/test/test-unit-name.c | 25 ++++++++++- + 5 files changed, 129 insertions(+), 13 deletions(-) + +diff --git a/src/basic/string-util.h b/src/basic/string-util.h +index 742b566932..0d406ff64a 100644 +--- a/src/basic/string-util.h ++++ b/src/basic/string-util.h +@@ -9,17 +9,18 @@ + #include "macro.h" + + /* What is interpreted as whitespace? */ +-#define WHITESPACE " \t\n\r" +-#define NEWLINE "\n\r" +-#define QUOTES "\"\'" +-#define COMMENTS "#;" +-#define GLOB_CHARS "*?[" +-#define DIGITS "0123456789" +-#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" +-#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +-#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS +-#define ALPHANUMERICAL LETTERS DIGITS +-#define HEXDIGITS DIGITS "abcdefABCDEF" ++#define WHITESPACE " \t\n\r" ++#define NEWLINE "\n\r" ++#define QUOTES "\"\'" ++#define COMMENTS "#;" ++#define GLOB_CHARS "*?[" ++#define DIGITS "0123456789" ++#define LOWERCASE_LETTERS "abcdefghijklmnopqrstuvwxyz" ++#define UPPERCASE_LETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++#define LETTERS LOWERCASE_LETTERS UPPERCASE_LETTERS ++#define ALPHANUMERICAL LETTERS DIGITS ++#define HEXDIGITS DIGITS "abcdefABCDEF" ++#define LOWERCASE_HEXDIGITS DIGITS "abcdef" + + #define streq(a,b) (strcmp((a),(b)) == 0) + #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) +diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c +index f9b3fafd4d..65ed979e39 100644 +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -6,11 +6,17 @@ + #include + #include + ++#include "sd-id128.h" ++ + #include "alloc-util.h" + #include "glob-util.h" + #include "hexdecoct.h" + #include "path-util.h" ++#include "random-util.h" ++#include "siphash24.h" ++#include "sparse-endian.h" + #include "special.h" ++#include "stdio-util.h" + #include "string-util.h" + #include "strv.h" + #include "unit-name.h" +@@ -31,6 +37,9 @@ + VALID_CHARS_WITH_AT \ + "[]!-*?" + ++#define LONG_UNIT_NAME_HASH_KEY SD_ID128_MAKE(ec,f2,37,fb,58,32,4a,32,84,9f,06,9b,0d,21,eb,9a) ++#define UNIT_NAME_HASH_LENGTH_CHARS 16 ++ + bool unit_name_is_valid(const char *n, UnitNameFlags flags) { + const char *e, *i, *at; + +@@ -513,6 +522,68 @@ int unit_name_template(const char *f, char **ret) { + return 0; + } + ++bool unit_name_is_hashed(const char *name) { ++ char *s; ++ ++ if (!unit_name_is_valid(name, UNIT_NAME_PLAIN)) ++ return false; ++ ++ assert_se(s = strrchr(name, '.')); ++ ++ if (s - name < UNIT_NAME_HASH_LENGTH_CHARS + 1) ++ return false; ++ ++ s -= UNIT_NAME_HASH_LENGTH_CHARS; ++ if (s[-1] != '_') ++ return false; ++ ++ for (size_t i = 0; i < UNIT_NAME_HASH_LENGTH_CHARS; i++) ++ if (!strchr(LOWERCASE_HEXDIGITS, s[i])) ++ return false; ++ ++ return true; ++} ++ ++int unit_name_hash_long(const char *name, char **ret) { ++ _cleanup_free_ char *n = NULL, *hash = NULL; ++ char *suffix; ++ le64_t h; ++ size_t len; ++ ++ if (strlen(name) < UNIT_NAME_MAX) ++ return -EMSGSIZE; ++ ++ suffix = strrchr(name, '.'); ++ if (!suffix) ++ return -EINVAL; ++ ++ if (unit_type_from_string(suffix+1) < 0) ++ return -EINVAL; ++ ++ h = htole64(siphash24(name, strlen(name) + 1, LONG_UNIT_NAME_HASH_KEY.bytes)); ++ ++ hash = hexmem(&h, sizeof(h)); ++ if (!hash) ++ return -ENOMEM; ++ ++ assert_se(strlen(hash) == UNIT_NAME_HASH_LENGTH_CHARS); ++ ++ len = UNIT_NAME_MAX - 1 - strlen(suffix+1) - UNIT_NAME_HASH_LENGTH_CHARS - 2; ++ assert(len > 0 && len < UNIT_NAME_MAX); ++ ++ n = strndup(name, len); ++ if (!n) ++ return -ENOMEM; ++ ++ if (!strextend(&n, "_", hash, suffix, NULL)) ++ return -ENOMEM; ++ assert_se(unit_name_is_valid(n, UNIT_NAME_PLAIN)); ++ ++ *ret = TAKE_PTR(n); ++ ++ return 0; ++} ++ + int unit_name_from_path(const char *path, const char *suffix, char **ret) { + _cleanup_free_ char *p = NULL, *s = NULL; + int r; +@@ -532,7 +603,19 @@ int unit_name_from_path(const char *path, const char *suffix, char **ret) { + if (!s) + return -ENOMEM; + +- /* Refuse this if this got too long or for some other reason didn't result in a valid name */ ++ if (strlen(s) >= UNIT_NAME_MAX) { ++ _cleanup_free_ char *n = NULL; ++ ++ log_debug("Unit name \"%s\" too long, falling back to hashed unit name.", s); ++ ++ r = unit_name_hash_long(s, &n); ++ if (r < 0) ++ return r; ++ ++ free_and_replace(s, n); ++ } ++ ++ /* Refuse if this for some other reason didn't result in a valid name */ + if (!unit_name_is_valid(s, UNIT_NAME_PLAIN)) + return -EINVAL; + +@@ -582,6 +665,9 @@ int unit_name_to_path(const char *name, char **ret) { + if (r < 0) + return r; + ++ if (unit_name_is_hashed(name)) ++ return -ENAMETOOLONG; ++ + return unit_name_path_unescape(prefix, ret); + } + +diff --git a/src/basic/unit-name.h b/src/basic/unit-name.h +index 61abcd585b..602295af8f 100644 +--- a/src/basic/unit-name.h ++++ b/src/basic/unit-name.h +@@ -45,6 +45,9 @@ int unit_name_replace_instance(const char *f, const char *i, char **ret); + + int unit_name_template(const char *f, char **ret); + ++int unit_name_hash_long(const char *name, char **ret); ++bool unit_name_is_hashed(const char *name); ++ + int unit_name_from_path(const char *path, const char *suffix, char **ret); + int unit_name_from_path_instance(const char *prefix, const char *path, const char *suffix, char **ret); + int unit_name_to_path(const char *name, char **ret); +diff --git a/src/core/mount.c b/src/core/mount.c +index d37b5731f8..e69ecb7ce3 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -572,6 +572,9 @@ static int mount_add_extras(Mount *m) { + + if (!m->where) { + r = unit_name_to_path(u->id, &m->where); ++ if (r == -ENAMETOOLONG) ++ log_unit_error_errno(u, r, "Failed to derive mount point path from unit name, because unit name is hashed. " ++ "Set \"Where=\" in the unit file explicitly."); + if (r < 0) + return r; + } +diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c +index 2b00ef8cb7..35cfaafd30 100644 +--- a/src/test/test-unit-name.c ++++ b/src/test/test-unit-name.c +@@ -82,6 +82,7 @@ static void test_unit_name_replace_instance(void) { + + static void test_unit_name_from_path_one(const char *path, const char *suffix, const char *expected, int ret) { + _cleanup_free_ char *t = NULL; ++ int r; + + assert_se(unit_name_from_path(path, suffix, &t) == ret); + puts(strna(t)); +@@ -89,12 +90,31 @@ static void test_unit_name_from_path_one(const char *path, const char *suffix, c + + if (t) { + _cleanup_free_ char *k = NULL; +- assert_se(unit_name_to_path(t, &k) == 0); ++ ++ /* We don't support converting hashed unit names back to paths */ ++ r = unit_name_to_path(t, &k); ++ if (r == -ENAMETOOLONG) ++ return; ++ assert(r == 0); ++ + puts(strna(k)); + assert_se(path_equal(k, empty_to_root(path))); + } + } + ++static void test_unit_name_is_hashed(void) { ++ assert_se(!unit_name_is_hashed("")); ++ assert_se(!unit_name_is_hashed("foo@bar.service")); ++ assert_se(!unit_name_is_hashed("foo@.service")); ++ assert_se(unit_name_is_hashed("waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_7736d9ed33c2ec55.mount")); ++ assert_se(!unit_name_is_hashed("waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_7736D9ED33C2EC55.mount")); ++ assert_se(!unit_name_is_hashed("waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!7736d9ed33c2ec55.mount")); ++ assert_se(!unit_name_is_hashed("waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_7736d9gd33c2ec55.mount")); ++ assert_se(!unit_name_is_hashed("waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_.mount")); ++ assert_se(!unit_name_is_hashed("waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_2103e1466b87f7f7@waldo.mount")); ++ assert_se(!unit_name_is_hashed("waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_2103e1466b87f7f7@.mount")); ++} ++ + static void test_unit_name_from_path(void) { + puts("-------------------------------------------------"); + test_unit_name_from_path_one("/waldo", ".mount", "waldo.mount", 0); +@@ -105,6 +125,8 @@ static void test_unit_name_from_path(void) { + test_unit_name_from_path_one("///", ".mount", "-.mount", 0); + test_unit_name_from_path_one("/foo/../bar", ".mount", NULL, -EINVAL); + test_unit_name_from_path_one("/foo/./bar", ".mount", NULL, -EINVAL); ++ test_unit_name_from_path_one("/waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", ".mount", ++ "waldoaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_7736d9ed33c2ec55.mount", 0); + } + + static void test_unit_name_from_path_instance_one(const char *pattern, const char *path, const char *suffix, const char *expected, int ret) { +@@ -824,6 +846,7 @@ int main(int argc, char* argv[]) { + + test_unit_name_is_valid(); + test_unit_name_replace_instance(); ++ test_unit_name_is_hashed(); + test_unit_name_from_path(); + test_unit_name_from_path_instance(); + test_unit_name_mangle(); diff --git a/SOURCES/0774-test-add-extended-test-for-triggering-mount-rate-lim.patch b/SOURCES/0774-test-add-extended-test-for-triggering-mount-rate-lim.patch new file mode 100644 index 0000000..635a2a0 --- /dev/null +++ b/SOURCES/0774-test-add-extended-test-for-triggering-mount-rate-lim.patch @@ -0,0 +1,162 @@ +From 2b390a10d826f060a672d9f01c6ad43714691274 Mon Sep 17 00:00:00 2001 +From: Anita Zhang +Date: Tue, 8 Jun 2021 00:04:35 -0700 +Subject: [PATCH] test: add extended test for triggering mount rate limit + +It's hard to trigger the failure to exit the rate limit state in +isolation as it needs multiple event sources in order to show that it +gets stuck in the queue. Hence why this is an extended test. + +(cherry picked from commit 0c81900965a72b29eb76e0737ed899b925ee75b6) + +Related: #1940973 +--- + test/TEST-60-MOUNT-RATELIMIT/Makefile | 1 + + test/TEST-60-MOUNT-RATELIMIT/test.sh | 48 +++++++++++++++ + test/TEST-60-MOUNT-RATELIMIT/testsuite.sh | 73 +++++++++++++++++++++++ + 3 files changed, 122 insertions(+) + create mode 120000 test/TEST-60-MOUNT-RATELIMIT/Makefile + create mode 100755 test/TEST-60-MOUNT-RATELIMIT/test.sh + create mode 100755 test/TEST-60-MOUNT-RATELIMIT/testsuite.sh + +diff --git a/test/TEST-60-MOUNT-RATELIMIT/Makefile b/test/TEST-60-MOUNT-RATELIMIT/Makefile +new file mode 120000 +index 0000000000..e9f93b1104 +--- /dev/null ++++ b/test/TEST-60-MOUNT-RATELIMIT/Makefile +@@ -0,0 +1 @@ ++../TEST-01-BASIC/Makefile +\ No newline at end of file +diff --git a/test/TEST-60-MOUNT-RATELIMIT/test.sh b/test/TEST-60-MOUNT-RATELIMIT/test.sh +new file mode 100755 +index 0000000000..e3c9288546 +--- /dev/null ++++ b/test/TEST-60-MOUNT-RATELIMIT/test.sh +@@ -0,0 +1,48 @@ ++#!/usr/bin/env bash ++set -e ++TEST_DESCRIPTION="Test that mount/unmount storms can enter/exit rate limit state and will not leak units" ++ ++. $TEST_BASE_DIR/test-functions ++ ++test_setup() { ++ create_empty_image ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ ++ ( ++ LOG_LEVEL=5 ++ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) ++ ++ setup_basic_environment ++ ++ # mask some services that we do not want to run in these tests ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service ++ ++ # setup the testsuite service ++ cat >$initdir/etc/systemd/system/testsuite.service </testok ++ ++exit 0 diff --git a/SOURCES/0775-tests-add-test-case-for-long-unit-names.patch b/SOURCES/0775-tests-add-test-case-for-long-unit-names.patch new file mode 100644 index 0000000..197b19b --- /dev/null +++ b/SOURCES/0775-tests-add-test-case-for-long-unit-names.patch @@ -0,0 +1,42 @@ +From 1c2a0bde1bc3510d9bdc07410ff90429ebed391f Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 23 Mar 2022 13:35:44 +0100 +Subject: [PATCH] tests: add test case for long unit names + +(cherry picked from commit 2ef0101e0b2813e8c99fc8f137dbaa763ca16057) + +Related: #1940973 +--- + test/TEST-60-MOUNT-RATELIMIT/testsuite.sh | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh b/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh +index 8158754667..6211050faf 100755 +--- a/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh ++++ b/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh +@@ -7,6 +7,25 @@ systemd-analyze log-target journal + + NUM_DIRS=20 + ++# make sure we can handle mounts at very long paths such that mount unit name must be hashed to fall within our unit name limit ++LONGPATH="$(printf "/$(printf "x%0.s" {1..255})%0.s" {1..7})" ++LONGMNT="$(systemd-escape --suffix=mount --path "$LONGPATH")" ++TS="$(date '+%H:%M:%S')" ++ ++mkdir -p "$LONGPATH" ++mount -t tmpfs tmpfs "$LONGPATH" ++systemctl daemon-reload ++ ++# check that unit is active(mounted) ++systemctl --no-pager show -p SubState --value "$LONGPATH" | grep -q mounted ++ ++# check that relevant part of journal doesn't contain any errors related to unit ++[ "$(journalctl -b --since="$TS" --priority=err | grep -c "$LONGMNT")" = "0" ] ++ ++# check that we can successfully stop the mount unit ++systemctl stop "$LONGPATH" ++rm -rf "$LONGPATH" ++ + # mount/unmount enough times to trigger the /proc/self/mountinfo parsing rate limiting + + for ((i = 0; i < NUM_DIRS; i++)); do diff --git a/SOURCES/0776-core-unset-HOME-that-the-kernel-gives-us.patch b/SOURCES/0776-core-unset-HOME-that-the-kernel-gives-us.patch new file mode 100644 index 0000000..1753f0c --- /dev/null +++ b/SOURCES/0776-core-unset-HOME-that-the-kernel-gives-us.patch @@ -0,0 +1,33 @@ +From 9ba5d8811630a3d2af90fdc52f4fd6b03ee9e692 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 21 May 2019 19:26:12 +0200 +Subject: [PATCH] core: unset HOME=/ that the kernel gives us + +Partially fixes #12389. + +%h would return "/" in a machine, but "/root" in a container. Let's fix +this by resetting $HOME to the expected value. + +(cherry picked from commit 9d48671c62de133a2b9fe7c31e70c0ff8e68f2db) + +Resolves: #2056527 +--- + src/core/main.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/core/main.c b/src/core/main.c +index d897155644..08a4df3c97 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -1307,6 +1307,11 @@ static int fixup_environment(void) { + if (setenv("TERM", t, 1) < 0) + return -errno; + ++ /* The kernels sets HOME=/ for init. Let's undo this. */ ++ if (path_equal_ptr(getenv("HOME"), "/") && ++ unsetenv("HOME") < 0) ++ log_warning_errno(errno, "Failed to unset $HOME: %m"); ++ + return 0; + } + diff --git a/SOURCES/0777-journal-remote-check-return-value-from-MHD_add_respo.patch b/SOURCES/0777-journal-remote-check-return-value-from-MHD_add_respo.patch new file mode 100644 index 0000000..e4a1e2d --- /dev/null +++ b/SOURCES/0777-journal-remote-check-return-value-from-MHD_add_respo.patch @@ -0,0 +1,94 @@ +From c20e06c1c0319e3759a11bf9051a8041898f79b2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 7 Mar 2021 12:08:06 +0100 +Subject: [PATCH] journal-remote: check return value from + MHD_add_response_header + +Sadly, the API does not allow us to distinguish oom from invalid settings. +If the call fails, let's assume oom happened. + +Coverity CID#1444714. + +(cherry picked from commit 60d9c4f3b972ce70dfadc0a3f1a478a056c2ea7a) + +Resolves: #2051981 +--- + src/journal-remote/journal-gatewayd.c | 22 ++++++++++++++++------ + src/journal-remote/microhttpd-util.c | 3 ++- + 2 files changed, 18 insertions(+), 7 deletions(-) + +diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c +index 3a167ab890..54446ff7b5 100644 +--- a/src/journal-remote/journal-gatewayd.c ++++ b/src/journal-remote/journal-gatewayd.c +@@ -492,7 +492,9 @@ static int request_handler_entries( + if (!response) + return respond_oom(connection); + +- MHD_add_response_header(response, "Content-Type", mime_types[m->mode]); ++ if (MHD_add_response_header(response, "Content-Type", mime_types[m->mode]) == MHD_NO) ++ return respond_oom(connection); ++ + return MHD_queue_response(connection, MHD_HTTP_OK, response); + } + +@@ -627,7 +629,9 @@ static int request_handler_fields( + if (!response) + return respond_oom(connection); + +- MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]); ++ if (MHD_add_response_header(response, "Content-Type", mime_types[m->mode == OUTPUT_JSON ? OUTPUT_JSON : OUTPUT_SHORT]) == MHD_NO) ++ return respond_oom(connection); ++ + return MHD_queue_response(connection, MHD_HTTP_OK, response); + } + +@@ -650,8 +654,10 @@ static int request_handler_redirect( + return respond_oom(connection); + } + +- MHD_add_response_header(response, "Content-Type", "text/html"); +- MHD_add_response_header(response, "Location", target); ++ if (MHD_add_response_header(response, "Content-Type", "text/html") == MHD_NO || ++ MHD_add_response_header(response, "Location", target) == MHD_NO) ++ return respond_oom(connection); ++ + return MHD_queue_response(connection, MHD_HTTP_MOVED_PERMANENTLY, response); + } + +@@ -680,7 +686,9 @@ static int request_handler_file( + return respond_oom(connection); + TAKE_FD(fd); + +- MHD_add_response_header(response, "Content-Type", mime_type); ++ if (MHD_add_response_header(response, "Content-Type", mime_type) == MHD_NO) ++ return respond_oom(connection); ++ + return MHD_queue_response(connection, MHD_HTTP_OK, response); + } + +@@ -781,7 +789,9 @@ static int request_handler_machine( + return respond_oom(connection); + TAKE_PTR(json); + +- MHD_add_response_header(response, "Content-Type", "application/json"); ++ if (MHD_add_response_header(response, "Content-Type", "application/json") == MHD_NO) ++ return respond_oom(connection); ++ + return MHD_queue_response(connection, MHD_HTTP_OK, response); + } + +diff --git a/src/journal-remote/microhttpd-util.c b/src/journal-remote/microhttpd-util.c +index 2ae5172fe9..fdfeaeb2f5 100644 +--- a/src/journal-remote/microhttpd-util.c ++++ b/src/journal-remote/microhttpd-util.c +@@ -40,7 +40,8 @@ static int mhd_respond_internal(struct MHD_Connection *connection, + return MHD_NO; + + log_debug("Queueing response %u: %s", code, buffer); +- MHD_add_response_header(response, "Content-Type", "text/plain"); ++ if (MHD_add_response_header(response, "Content-Type", "text/plain") == MHD_NO) ++ return MHD_NO; + return MHD_queue_response(connection, code, response); + } + diff --git a/SOURCES/0778-journalctl-in-follow-mode-watch-stdout-for-POLLHUP-P.patch b/SOURCES/0778-journalctl-in-follow-mode-watch-stdout-for-POLLHUP-P.patch new file mode 100644 index 0000000..6d0cf4d --- /dev/null +++ b/SOURCES/0778-journalctl-in-follow-mode-watch-stdout-for-POLLHUP-P.patch @@ -0,0 +1,117 @@ +From 67d3aade15bede6b162e8bfe88db60311efb0d1f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 24 Oct 2018 21:49:52 +0200 +Subject: [PATCH] journalctl: in --follow mode watch stdout for POLLHUP/POLLERR + and exit + +Fixes: #9374 +(cherry picked from commit 2a1e0f2228bbdfbc18635e959f47df7da50b62fe) + +Resolves: #2003236 +--- + src/journal/journalctl.c | 65 +++++++++++++++++++++++++++++----------- + 1 file changed, 48 insertions(+), 17 deletions(-) + +diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c +index 56b1be530d..fa83dce562 100644 +--- a/src/journal/journalctl.c ++++ b/src/journal/journalctl.c +@@ -2064,14 +2064,46 @@ static int sync_journal(void) { + return send_signal_and_wait(SIGRTMIN+1, "/run/systemd/journal/synced"); + } + +-int main(int argc, char *argv[]) { ++static int wait_for_change(sd_journal *j, int poll_fd) { ++ struct pollfd pollfds[] = { ++ { .fd = poll_fd, .events = POLLIN }, ++ { .fd = STDOUT_FILENO }, ++ }; ++ ++ struct timespec ts; ++ usec_t timeout; + int r; ++ ++ assert(j); ++ assert(poll_fd >= 0); ++ ++ /* Much like sd_journal_wait() but also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, ++ * i.e. when it is closed. */ ++ ++ r = sd_journal_get_timeout(j, &timeout); ++ if (r < 0) ++ return log_error_errno(r, "Failed to determine journal waiting time: %m"); ++ ++ if (ppoll(pollfds, ELEMENTSOF(pollfds), timeout == USEC_INFINITY ? NULL : timespec_store(&ts, timeout), NULL) < 0) ++ return log_error_errno(errno, "Couldn't wait for journal event: %m"); ++ ++ if (pollfds[1].revents & (POLLHUP|POLLERR)) { /* STDOUT has been closed? */ ++ log_debug("Standard output has been closed."); ++ return -ECANCELED; ++ } ++ ++ r = sd_journal_process(j); ++ if (r < 0) ++ return log_error_errno(r, "Failed to process journal events: %m"); ++ ++ return 0; ++} ++ ++int main(int argc, char *argv[]) { ++ bool previous_boot_id_valid = false, first_line = true, ellipsized = false, need_seek = false; + _cleanup_(sd_journal_closep) sd_journal *j = NULL; +- bool need_seek = false; + sd_id128_t previous_boot_id; +- bool previous_boot_id_valid = false, first_line = true; +- int n_shown = 0; +- bool ellipsized = false; ++ int n_shown = 0, r, poll_fd = -1; + + setlocale(LC_ALL, ""); + log_parse_environment(); +@@ -2391,15 +2423,15 @@ int main(int argc, char *argv[]) { + + /* Opening the fd now means the first sd_journal_wait() will actually wait */ + if (arg_follow) { +- r = sd_journal_get_fd(j); +- if (r == -EMFILE) { +- log_warning("Insufficent watch descriptors available. Reverting to -n."); ++ poll_fd = sd_journal_get_fd(j); ++ if (poll_fd == -EMFILE) { ++ log_warning_errno(poll_fd, "Insufficent watch descriptors available. Reverting to -n."); + arg_follow = false; +- } else if (r == -EMEDIUMTYPE) { +- log_error_errno(r, "The --follow switch is not supported in conjunction with reading from STDIN."); ++ } else if (poll_fd == -EMEDIUMTYPE) { ++ log_error_errno(poll_fd, "The --follow switch is not supported in conjunction with reading from STDIN."); + goto finish; +- } else if (r < 0) { +- log_error_errno(r, "Failed to get journal fd: %m"); ++ } else if (poll_fd < 0) { ++ log_error_errno(poll_fd, "Failed to get journal fd: %m"); + goto finish; + } + } +@@ -2621,7 +2653,7 @@ int main(int argc, char *argv[]) { + need_seek = true; + if (r == -EADDRNOTAVAIL) + break; +- else if (r < 0 || ferror(stdout)) ++ else if (r < 0) + goto finish; + + n_shown++; +@@ -2659,11 +2691,10 @@ int main(int argc, char *argv[]) { + } + + fflush(stdout); +- r = sd_journal_wait(j, (uint64_t) -1); +- if (r < 0) { +- log_error_errno(r, "Couldn't wait for journal event: %m"); ++ ++ r = wait_for_change(j, poll_fd); ++ if (r < 0) + goto finish; +- } + + first_line = false; + } diff --git a/SOURCES/0779-sd-bus-make-BUS_DEFAULT_TIMEOUT-configurable.patch b/SOURCES/0779-sd-bus-make-BUS_DEFAULT_TIMEOUT-configurable.patch new file mode 100644 index 0000000..02d9904 --- /dev/null +++ b/SOURCES/0779-sd-bus-make-BUS_DEFAULT_TIMEOUT-configurable.patch @@ -0,0 +1,182 @@ +From 3022d49ba2276eb5634d84a89a078aa3c357b70a Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 13 Jul 2018 17:38:47 +0900 +Subject: [PATCH] sd-bus: make BUS_DEFAULT_TIMEOUT configurable + +This adds sd_bus_{get,set}_method_call_timeout(). +If the timeout is not set or set to 0, then the timeout value is +parsed from $SYSTEMD_BUS_TIMEOUT= environment variable. If the +environment variable is not set, then built-in timeout is used. + +(cherry picked from commit 385b2eb262a99373f09d01b7f5571dd71a14dc98) + +Resolves: #2039461 +--- + doc/ENVIRONMENT.md | 5 ++++ + src/libsystemd/libsystemd.sym | 7 ++++- + src/libsystemd/sd-bus/bus-internal.h | 9 ++++--- + src/libsystemd/sd-bus/bus-message.c | 7 +++-- + src/libsystemd/sd-bus/sd-bus.c | 40 ++++++++++++++++++++++++++-- + src/systemd/sd-bus.h | 3 +++ + 6 files changed, 62 insertions(+), 9 deletions(-) + +diff --git a/doc/ENVIRONMENT.md b/doc/ENVIRONMENT.md +index 8d7ce6ae2c..d1a79eaa4f 100644 +--- a/doc/ENVIRONMENT.md ++++ b/doc/ENVIRONMENT.md +@@ -50,6 +50,11 @@ All tools: + this only controls use of Unicode emoji glyphs, and has no effect on other + Unicode glyphs. + ++* `$SYSTEMD_BUS_TIMEOUT=SECS` — specifies the maximum time to wait for method call ++ completion. If no time unit is specified, assumes seconds. The usual other units ++ are understood, too (us, ms, s, min, h, d, w, month, y). If it is not set or set ++ to 0, then the built-in default is used. ++ + systemctl: + + * `$SYSTEMCTL_FORCE_BUS=1` — if set, do not connect to PID1's private D-Bus +diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym +index f4a1426248..3b55fc6473 100644 +--- a/src/libsystemd/libsystemd.sym ++++ b/src/libsystemd/libsystemd.sym +@@ -573,12 +573,17 @@ global: + sd_event_source_disable_unref; + } LIBSYSTEMD_238; + ++LIBSYSTEMD_240 { ++ sd_bus_set_method_call_timeout; ++ sd_bus_get_method_call_timeout; ++} LIBSYSTEMD_239; ++ + LIBSYSTEMD_248 { + global: + sd_event_source_set_ratelimit; + sd_event_source_get_ratelimit; + sd_event_source_is_ratelimited; +-} LIBSYSTEMD_239; ++} LIBSYSTEMD_240; + + LIBSYSTEMD_250 { + global: +diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h +index 06bd7862cb..88415ae678 100644 +--- a/src/libsystemd/sd-bus/bus-internal.h ++++ b/src/libsystemd/sd-bus/bus-internal.h +@@ -319,6 +319,9 @@ struct sd_bus { + + int *inotify_watches; + size_t n_inotify_watches; ++ ++ /* zero means use value specified by $SYSTEMD_BUS_TIMEOUT= environment variable or built-in default */ ++ usec_t method_call_timeout; + }; + + /* For method calls we time-out at 25s, like in the D-Bus reference implementation */ +@@ -340,8 +343,7 @@ struct sd_bus { + + #define BUS_CONTAINER_DEPTH 128 + +-/* Defined by the specification as maximum size of an array in +- * bytes */ ++/* Defined by the specification as maximum size of an array in bytes */ + #define BUS_ARRAY_MAX_SIZE 67108864 + + #define BUS_FDS_MAX 1024 +@@ -392,8 +394,7 @@ void bus_close_io_fds(sd_bus *b); + _slash = streq((prefix), "/") ? NULL : strrchr((prefix), '/')) + + /* If we are invoking callbacks of a bus object, ensure unreffing the +- * bus from the callback doesn't destroy the object we are working +- * on */ ++ * bus from the callback doesn't destroy the object we are working on */ + #define BUS_DONT_DESTROY(bus) \ + _cleanup_(sd_bus_unrefp) _unused_ sd_bus *_dont_destroy_##bus = sd_bus_ref(bus) + +diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c +index 7fe8929f82..3ffe559b8d 100644 +--- a/src/libsystemd/sd-bus/bus-message.c ++++ b/src/libsystemd/sd-bus/bus-message.c +@@ -5882,8 +5882,11 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) { + return r; + + timeout = (*m)->timeout; +- if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)) +- timeout = BUS_DEFAULT_TIMEOUT; ++ if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)) { ++ r = sd_bus_get_method_call_timeout(bus, &timeout); ++ if (r < 0) ++ return r; ++ } + + r = sd_bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout); + if (r < 0) +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index c65e24b2d1..803f3f50d6 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -1651,8 +1651,11 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) { + return 0; + } + +- if (timeout == 0) +- timeout = BUS_DEFAULT_TIMEOUT; ++ if (timeout == 0) { ++ r = sd_bus_get_method_call_timeout(b, &timeout); ++ if (r < 0) ++ return r; ++ } + + if (!m->sender && b->patch_sender) { + r = sd_bus_message_set_sender(m, b->patch_sender); +@@ -4141,3 +4144,36 @@ _public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) { + bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus); + return 0; + } ++ ++_public_ int sd_bus_set_method_call_timeout(sd_bus *bus, uint64_t usec) { ++ assert_return(bus, -EINVAL); ++ assert_return(bus = bus_resolve(bus), -ENOPKG); ++ ++ bus->method_call_timeout = usec; ++ return 0; ++} ++ ++_public_ int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret) { ++ const char *e; ++ usec_t usec; ++ ++ assert_return(bus, -EINVAL); ++ assert_return(bus = bus_resolve(bus), -ENOPKG); ++ assert_return(ret, -EINVAL); ++ ++ if (bus->method_call_timeout != 0) { ++ *ret = bus->method_call_timeout; ++ return 0; ++ } ++ ++ e = secure_getenv("SYSTEMD_BUS_TIMEOUT"); ++ if (e && parse_sec(e, &usec) >= 0 && usec != 0) { ++ /* Save the parsed value to avoid multiple parsing. To change the timeout value, ++ * use sd_bus_set_method_call_timeout() instead of setenv(). */ ++ *ret = bus->method_call_timeout = usec; ++ return 0; ++ } ++ ++ *ret = bus->method_call_timeout = BUS_DEFAULT_TIMEOUT; ++ return 0; ++} +diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h +index 9ba757b13d..8b6f70bd68 100644 +--- a/src/systemd/sd-bus.h ++++ b/src/systemd/sd-bus.h +@@ -207,6 +207,9 @@ sd_event *sd_bus_get_event(sd_bus *bus); + int sd_bus_get_n_queued_read(sd_bus *bus, uint64_t *ret); + int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret); + ++int sd_bus_set_method_call_timeout(sd_bus *bus, uint64_t usec); ++int sd_bus_get_method_call_timeout(sd_bus *bus, uint64_t *ret); ++ + int sd_bus_add_filter(sd_bus *bus, sd_bus_slot **slot, sd_bus_message_handler_t callback, void *userdata); + int sd_bus_add_match(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, void *userdata); + int sd_bus_add_match_async(sd_bus *bus, sd_bus_slot **slot, const char *match, sd_bus_message_handler_t callback, sd_bus_message_handler_t install_callback, void *userdata); diff --git a/SOURCES/0780-fstab-generator-fix-debug-log.patch b/SOURCES/0780-fstab-generator-fix-debug-log.patch new file mode 100644 index 0000000..f8318f9 --- /dev/null +++ b/SOURCES/0780-fstab-generator-fix-debug-log.patch @@ -0,0 +1,25 @@ +From bbf71447d5de3b2cb86623a870cad21bbf114390 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 18 Feb 2019 11:29:45 +0900 +Subject: [PATCH] fstab-generator: fix debug log + +(cherry picked from commit 7731c1c20aeba4f1042f6076408db1f107d0706c) + +Resolves: #2101433 +--- + src/fstab-generator/fstab-generator.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c +index 482229b4a5..f24c1d29da 100644 +--- a/src/fstab-generator/fstab-generator.c ++++ b/src/fstab-generator/fstab-generator.c +@@ -561,7 +561,7 @@ static int parse_fstab(bool initrd) { + noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0"); + nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0"); + +- log_debug("Found entry what=%s where=%s type=%s makefs=%s nofail=%s noauto=%s", ++ log_debug("Found entry what=%s where=%s type=%s makefs=%s noauto=%s nofail=%s", + what, where, me->mnt_type, + yes_no(makefs), + yes_no(noauto), yes_no(nofail)); diff --git a/SOURCES/0781-logind-session-dbus-allow-to-set-display-name-via-db.patch b/SOURCES/0781-logind-session-dbus-allow-to-set-display-name-via-db.patch new file mode 100644 index 0000000..c024d91 --- /dev/null +++ b/SOURCES/0781-logind-session-dbus-allow-to-set-display-name-via-db.patch @@ -0,0 +1,123 @@ +From 54a8d932442d02f5a7dbf6038c8f557ce41f468b Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Fri, 10 Jun 2022 15:07:01 +0200 +Subject: [PATCH] logind-session-dbus: allow to set display name via dbus + +Currently, the only way to set display name of a graphical session is to +pass it to CreateSession(). But modern display managers like gdm start +the display server as part of the user session, which means that the +display name isn't known yet when the session is being created. Hence, +let's make it possible to set it later. + +(cherry picked from commit 4885d7490b23e08d8444e5a68927ce9ce8727e5a) + +Resolves: #1857969 +--- + src/login/logind-session-dbus.c | 26 ++++++++++++++++++++++++++ + src/login/logind-session.c | 20 ++++++++++++++++++++ + src/login/logind-session.h | 1 + + src/login/org.freedesktop.login1.conf | 4 ++++ + 4 files changed, 51 insertions(+) + +diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c +index 03585b7f8e..c935959e02 100644 +--- a/src/login/logind-session-dbus.c ++++ b/src/login/logind-session-dbus.c +@@ -381,6 +381,31 @@ static int method_release_control(sd_bus_message *message, void *userdata, sd_bu + return sd_bus_reply_method_return(message, NULL); + } + ++static int method_set_display(sd_bus_message *message, void *userdata, sd_bus_error *error) { ++ Session *s = userdata; ++ const char *display; ++ int r; ++ ++ assert(message); ++ assert(s); ++ ++ r = sd_bus_message_read(message, "s", &display); ++ if (r < 0) ++ return r; ++ ++ if (!session_is_controller(s, sd_bus_message_get_sender(message))) ++ return sd_bus_error_set(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set display"); ++ ++ if (!SESSION_TYPE_IS_GRAPHICAL(s->type)) ++ return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Setting display is only supported for graphical sessions"); ++ ++ r = session_set_display(s, display); ++ if (r < 0) ++ return r; ++ ++ return sd_bus_reply_method_return(message, NULL); ++} ++ + static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Session *s = userdata; + uint32_t major, minor; +@@ -523,6 +548,7 @@ const sd_bus_vtable session_vtable[] = { + SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("SetDisplay", "s", NULL, method_set_display, SD_BUS_VTABLE_UNPRIVILEGED), + + SD_BUS_SIGNAL("PauseDevice", "uus", 0), + SD_BUS_SIGNAL("ResumeDevice", "uuh", 0), +diff --git a/src/login/logind-session.c b/src/login/logind-session.c +index e4c8bb36f6..1143a834a4 100644 +--- a/src/login/logind-session.c ++++ b/src/login/logind-session.c +@@ -953,6 +953,26 @@ void session_set_locked_hint(Session *s, bool b) { + session_send_changed(s, "LockedHint", NULL); + } + ++int session_set_display(Session *s, const char *display) { ++ int r; ++ ++ assert(s); ++ assert(display); ++ ++ if (streq(s->display, display)) ++ return 0; ++ ++ r = free_and_strdup(&s->display, display); ++ if (r < 0) ++ return r; ++ ++ session_save(s); ++ ++ session_send_changed(s, "Display", NULL); ++ ++ return 1; ++} ++ + static int session_dispatch_fifo(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + Session *s = userdata; + +diff --git a/src/login/logind-session.h b/src/login/logind-session.h +index 7d17d9a25f..9bd0c96a03 100644 +--- a/src/login/logind-session.h ++++ b/src/login/logind-session.h +@@ -123,6 +123,7 @@ int session_get_idle_hint(Session *s, dual_timestamp *t); + void session_set_idle_hint(Session *s, bool b); + int session_get_locked_hint(Session *s); + void session_set_locked_hint(Session *s, bool b); ++int session_set_display(Session *s, const char *display); + int session_create_fifo(Session *s); + int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error); + int session_stop(Session *s, bool force); +diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf +index dcde0c22c6..b780ae08cf 100644 +--- a/src/login/org.freedesktop.login1.conf ++++ b/src/login/org.freedesktop.login1.conf +@@ -314,6 +314,10 @@ + send_interface="org.freedesktop.login1.User" + send_member="Kill"/> + ++ ++ + + + diff --git a/SOURCES/0782-Allow-restart-for-oneshot-units.patch b/SOURCES/0782-Allow-restart-for-oneshot-units.patch new file mode 100644 index 0000000..fbf2bed --- /dev/null +++ b/SOURCES/0782-Allow-restart-for-oneshot-units.patch @@ -0,0 +1,160 @@ +From ffc616d9c4d2c64d211c9e63601a321524fe2d31 Mon Sep 17 00:00:00 2001 +From: Claudio Zumbo +Date: Tue, 8 Oct 2019 15:04:29 -0700 +Subject: [PATCH] Allow restart for oneshot units + +Picked up from https://github.com/systemd/systemd/pull/7474 , so +coauthored by @robermorales. + +(cherry picked from commit 10e72727eeeeb1a495303ec406fa8d1e1a83dc6e) + +Resolves: #2042896 +--- + man/systemd.service.xml | 7 ++-- + src/core/service.c | 5 +-- + test/TEST-41-ONESHOT-RESTART/Makefile | 9 +++++ + test/TEST-41-ONESHOT-RESTART/test.sh | 44 +++++++++++++++++++++++ + test/TEST-41-ONESHOT-RESTART/testsuite.sh | 33 +++++++++++++++++ + 5 files changed, 93 insertions(+), 5 deletions(-) + create mode 100644 test/TEST-41-ONESHOT-RESTART/Makefile + create mode 100755 test/TEST-41-ONESHOT-RESTART/test.sh + create mode 100755 test/TEST-41-ONESHOT-RESTART/testsuite.sh + +diff --git a/man/systemd.service.xml b/man/systemd.service.xml +index 1e30a564df..133296d386 100644 +--- a/man/systemd.service.xml ++++ b/man/systemd.service.xml +@@ -1276,9 +1276,10 @@ WantedBy=multi-user.target + + Type= are the + only service units that may have more than one +- ExecStart= specified. They will be executed +- in order until either they are all successful or one of them +- fails. ++ ExecStart= specified. For units with multiple ++ commands (Type=oneshot), all commands will be run again. ++ For Type=oneshot, Restart= ++ and Restart= are not allowed. + + + +diff --git a/src/core/service.c b/src/core/service.c +index e8ae1a5772..e05d0e0514 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -581,8 +581,9 @@ static int service_verify(Service *s) { + return -ENOEXEC; + } + +- if (s->type == SERVICE_ONESHOT && s->restart != SERVICE_RESTART_NO) { +- log_unit_error(UNIT(s), "Service has Restart= setting other than no, which isn't allowed for Type=oneshot services. Refusing."); ++ if (s->type == SERVICE_ONESHOT ++ && !IN_SET(s->restart, SERVICE_RESTART_NO, SERVICE_RESTART_ON_FAILURE, SERVICE_RESTART_ON_ABNORMAL, SERVICE_RESTART_ON_WATCHDOG, SERVICE_RESTART_ON_ABORT)) { ++ log_unit_error(UNIT(s), "Service has Restart= set to either always or on-success, which isn't allowed for Type=oneshot services. Refusing."); + return -ENOEXEC; + } + +diff --git a/test/TEST-41-ONESHOT-RESTART/Makefile b/test/TEST-41-ONESHOT-RESTART/Makefile +new file mode 100644 +index 0000000000..45e9bfc67c +--- /dev/null ++++ b/test/TEST-41-ONESHOT-RESTART/Makefile +@@ -0,0 +1,9 @@ ++BUILD_DIR=$(shell ../../tools/find-build-dir.sh) ++ ++all setup run: ++ @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@ ++ ++clean clean-again: ++ @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --clean ++ ++.PHONY: all setup run clean clean-again +diff --git a/test/TEST-41-ONESHOT-RESTART/test.sh b/test/TEST-41-ONESHOT-RESTART/test.sh +new file mode 100755 +index 0000000000..35de08b1e9 +--- /dev/null ++++ b/test/TEST-41-ONESHOT-RESTART/test.sh +@@ -0,0 +1,44 @@ ++#!/bin/bash ++set -e ++TEST_DESCRIPTION="Test oneshot unit restart on failure" ++. $TEST_BASE_DIR/test-functions ++ ++test_setup() { ++ create_empty_image ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ ++ ( ++ LOG_LEVEL=5 ++ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) ++ ++ setup_basic_environment ++ ++ # mask some services that we do not want to run in these tests ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service ++ ++ # setup the testsuite service ++ cat >$initdir/etc/systemd/system/testsuite.service <> $TMP_FILE\"" /bin/bash -c "exit 1" ++ ++sleep 5 ++ ++if [[ $(cat $TMP_FILE) != "aaa" ]]; then ++ exit 1 ++fi ++ ++systemd-analyze log-level info ++ ++echo OK > /testok ++ ++exit 0 diff --git a/SOURCES/0783-test-correct-TEST-41-StartLimitBurst-test.patch b/SOURCES/0783-test-correct-TEST-41-StartLimitBurst-test.patch new file mode 100644 index 0000000..44eef8b --- /dev/null +++ b/SOURCES/0783-test-correct-TEST-41-StartLimitBurst-test.patch @@ -0,0 +1,76 @@ +From a7375d12da80d633dfa802f2b66d2361c70c62f5 Mon Sep 17 00:00:00 2001 +From: Dan Streetman +Date: Thu, 17 Oct 2019 11:06:18 -0400 +Subject: [PATCH] test: correct TEST-41 StartLimitBurst test + +TEST-41 verifies that the StartLimitBurst property will correctly +limit the number of unit restarts, but the test currently doesn't +adjust the StartLimitIntervalSec which defaults to 10 seconds. + +On Ubuntu CI, running under un-accelerated qemu, it can take more than +10 seconds to perform all 3 restarts, which avoids the burst limit, +and fails the test. + +Instead, specify a long StartLimitIntervalSec in the test, so we can +be sure to correctly test StartLimitBurst even on slow testbeds. + +Fixes #13794. + +(cherry picked from commit dfec314d41159117c28dffc2b980d3bdd67c3dcb) + +Related: #2042896 +--- + test/TEST-41-ONESHOT-RESTART/testsuite.sh | 26 ++++++++++++++++++----- + 1 file changed, 21 insertions(+), 5 deletions(-) + +diff --git a/test/TEST-41-ONESHOT-RESTART/testsuite.sh b/test/TEST-41-ONESHOT-RESTART/testsuite.sh +index f7423dbf9a..4465614ff3 100755 +--- a/test/TEST-41-ONESHOT-RESTART/testsuite.sh ++++ b/test/TEST-41-ONESHOT-RESTART/testsuite.sh +@@ -2,14 +2,19 @@ + set -ex + set -o pipefail + ++# wait this many secs for each test service to succeed in what is being tested ++MAX_SECS=60 ++ + systemd-analyze log-level debug + systemd-analyze log-target console + +-# These three commands should succeed. ++# test one: Restart=on-failure should restart the service + ! systemd-run --unit=one -p Type=oneshot -p Restart=on-failure /bin/bash -c "exit 1" + +-sleep 5 +- ++for ((secs=0; secs<$MAX_SECS; secs++)); do ++ [[ "$(systemctl show one.service -p NRestarts --value)" -le 0 ]] || break ++ sleep 1 ++done + if [[ "$(systemctl show one.service -p NRestarts --value)" -le 0 ]]; then + exit 1 + fi +@@ -18,10 +23,21 @@ TMP_FILE="/test-41-oneshot-restart-test" + + touch $TMP_FILE + +-! systemd-run --unit=two -p StartLimitBurst=3 -p Type=oneshot -p Restart=on-failure -p ExecStart="/bin/bash -c \"printf a >> $TMP_FILE\"" /bin/bash -c "exit 1" ++# test two: make sure StartLimitBurst correctly limits the number of restarts ++# and restarts execution of the unit from the first ExecStart= ++! systemd-run --unit=two -p StartLimitIntervalSec=120 -p StartLimitBurst=3 -p Type=oneshot -p Restart=on-failure -p ExecStart="/bin/bash -c \"printf a >> $TMP_FILE\"" /bin/bash -c "exit 1" + +-sleep 5 ++# wait for at least 3 restarts ++for ((secs=0; secs<$MAX_SECS; secs++)); do ++ [[ $(cat $TMP_FILE) != "aaa" ]] || break ++ sleep 1 ++done ++if [[ $(cat $TMP_FILE) != "aaa" ]]; then ++ exit 1 ++fi + ++# wait for 5 more seconds to make sure there aren't excess restarts ++sleep 5 + if [[ $(cat $TMP_FILE) != "aaa" ]]; then + exit 1 + fi diff --git a/SOURCES/0784-core-fix-assert-about-number-of-built-environment-va.patch b/SOURCES/0784-core-fix-assert-about-number-of-built-environment-va.patch new file mode 100644 index 0000000..20ab06d --- /dev/null +++ b/SOURCES/0784-core-fix-assert-about-number-of-built-environment-va.patch @@ -0,0 +1,29 @@ +From 32ef99e27ca6242cd86e06b7f63ba49562a77335 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 11 Sep 2018 12:56:06 +0900 +Subject: [PATCH] core: fix assert() about number of built environment + variables + +Follow-up for 4b58153dd22172d817055d2a09a0cdf3f4bd9db3 and +fd63e712b2025d235ce4bfbb512fada10e2690b5. + +(cherry picked from commit 76a9460d44b03a86691a8481544f4525bb43610a) + +Related: #2049788 +--- + src/core/execute.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index a104294966..c842b14ce7 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -1733,7 +1733,7 @@ static int build_environment( + } + + our_env[n_env++] = NULL; +- assert(n_env <= 12); ++ assert(n_env <= 14); + + *ret = TAKE_PTR(our_env); + diff --git a/SOURCES/0785-core-add-one-more-assert.patch b/SOURCES/0785-core-add-one-more-assert.patch new file mode 100644 index 0000000..b8dc682 --- /dev/null +++ b/SOURCES/0785-core-add-one-more-assert.patch @@ -0,0 +1,24 @@ +From 09b6ae4da2d8b60d3619dcd0e6712e1a106efba0 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 11 Sep 2018 13:18:33 +0900 +Subject: [PATCH] core: add one more assert() + +(cherry picked from commit 7c1cb6f1989074e144b1625607950fce80c951ec) + +Related: #2049788 +--- + src/core/execute.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/core/execute.c b/src/core/execute.c +index c842b14ce7..3ff1a51aa1 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -1624,6 +1624,7 @@ static int build_environment( + + assert(u); + assert(c); ++ assert(p); + assert(ret); + + our_env = new0(char*, 14); diff --git a/SOURCES/0786-strv-introduce-strv_join_prefix.patch b/SOURCES/0786-strv-introduce-strv_join_prefix.patch new file mode 100644 index 0000000..8275c5b --- /dev/null +++ b/SOURCES/0786-strv-introduce-strv_join_prefix.patch @@ -0,0 +1,69 @@ +From 23ef6c470418b50119dc0bf13b681bfeae820352 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 11 Sep 2018 13:22:31 +0900 +Subject: [PATCH] strv: introduce strv_join_prefix() + +(cherry picked from commit 2b9a7d2e96f5f852cdf8cc704930ea2ee456f6a1) + +Related: #2049788 +--- + src/basic/strv.c | 10 +++++++--- + src/basic/strv.h | 5 ++++- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/basic/strv.c b/src/basic/strv.c +index b3716233b5..f1605e4fbb 100644 +--- a/src/basic/strv.c ++++ b/src/basic/strv.c +@@ -335,21 +335,22 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract + return (int) n; + } + +-char *strv_join(char **l, const char *separator) { ++char *strv_join_prefix(char **l, const char *separator, const char *prefix) { + char *r, *e; + char **s; +- size_t n, k; ++ size_t n, k, m; + + if (!separator) + separator = " "; + + k = strlen(separator); ++ m = strlen_ptr(prefix); + + n = 0; + STRV_FOREACH(s, l) { + if (s != l) + n += k; +- n += strlen(*s); ++ n += m + strlen(*s); + } + + r = new(char, n+1); +@@ -361,6 +362,9 @@ char *strv_join(char **l, const char *separator) { + if (s != l) + e = stpcpy(e, separator); + ++ if (prefix) ++ e = stpcpy(e, prefix); ++ + e = stpcpy(e, *s); + } + +diff --git a/src/basic/strv.h b/src/basic/strv.h +index a09d76706d..9285bc2642 100644 +--- a/src/basic/strv.h ++++ b/src/basic/strv.h +@@ -71,7 +71,10 @@ char **strv_split_newlines(const char *s); + + int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags); + +-char *strv_join(char **l, const char *separator); ++char *strv_join_prefix(char **l, const char *separator, const char *prefix); ++static inline char *strv_join(char **l, const char *separator) { ++ return strv_join_prefix(l, separator, NULL); ++} + + char **strv_parse_nulstr(const char *s, size_t l); + char **strv_split_nulstr(const char *s); diff --git a/SOURCES/0787-test-add-tests-for-strv_join_prefix.patch b/SOURCES/0787-test-add-tests-for-strv_join_prefix.patch new file mode 100644 index 0000000..28533b3 --- /dev/null +++ b/SOURCES/0787-test-add-tests-for-strv_join_prefix.patch @@ -0,0 +1,63 @@ +From d829e7163f6a98547cef3b0106a6a98728275065 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 11 Sep 2018 13:35:27 +0900 +Subject: [PATCH] test: add tests for strv_join_prefix() + +(cherry picked from commit 474a595af7544a670de70e1eb873bcee1bb00044) + +Related: #2049788 +--- + src/test/test-strv.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/src/test/test-strv.c b/src/test/test-strv.c +index 79d999d3ed..9e7d98500f 100644 +--- a/src/test/test-strv.c ++++ b/src/test/test-strv.c +@@ -158,6 +158,38 @@ static void test_strv_join(void) { + assert_se(streq(w, "")); + } + ++static void test_strv_join_prefix(void) { ++ _cleanup_free_ char *p = NULL, *q = NULL, *r = NULL, *s = NULL, *t = NULL, *v = NULL, *w = NULL; ++ ++ p = strv_join_prefix((char **)input_table_multiple, ", ", "foo"); ++ assert_se(p); ++ assert_se(streq(p, "fooone, footwo, foothree")); ++ ++ q = strv_join_prefix((char **)input_table_multiple, ";", "foo"); ++ assert_se(q); ++ assert_se(streq(q, "fooone;footwo;foothree")); ++ ++ r = strv_join_prefix((char **)input_table_multiple, NULL, "foo"); ++ assert_se(r); ++ assert_se(streq(r, "fooone footwo foothree")); ++ ++ s = strv_join_prefix((char **)input_table_one, ", ", "foo"); ++ assert_se(s); ++ assert_se(streq(s, "fooone")); ++ ++ t = strv_join_prefix((char **)input_table_none, ", ", "foo"); ++ assert_se(t); ++ assert_se(streq(t, "")); ++ ++ v = strv_join_prefix((char **)input_table_two_empties, ", ", "foo"); ++ assert_se(v); ++ assert_se(streq(v, "foo, foo")); ++ ++ w = strv_join_prefix((char **)input_table_one_empty, ", ", "foo"); ++ assert_se(w); ++ assert_se(streq(w, "foo")); ++} ++ + static void test_strv_unquote(const char *quoted, char **list) { + _cleanup_strv_free_ char **s; + _cleanup_free_ char *j; +@@ -722,6 +754,7 @@ int main(int argc, char *argv[]) { + test_strv_find_prefix(); + test_strv_find_startswith(); + test_strv_join(); ++ test_strv_join_prefix(); + + test_strv_unquote(" foo=bar \"waldo\" zzz ", STRV_MAKE("foo=bar", "waldo", "zzz")); + test_strv_unquote("", STRV_MAKE_EMPTY); diff --git a/SOURCES/0788-test-replace-swear-words-by-hoge.patch b/SOURCES/0788-test-replace-swear-words-by-hoge.patch new file mode 100644 index 0000000..c8c8083 --- /dev/null +++ b/SOURCES/0788-test-replace-swear-words-by-hoge.patch @@ -0,0 +1,54 @@ +From 48b22b82853c6697669b078de5eae35728fbba30 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 11 Sep 2018 13:41:09 +0900 +Subject: [PATCH] test: replace swear words by 'hoge' + +(cherry picked from commit a2917d3d2a3ce926f74b63aa60a47f838a8e1f83) + +Related: #2049788 +--- + src/test/test-cgroup-util.c | 2 +- + src/test/test-strv.c | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c +index 60d7bb19cb..2cb93ad0be 100644 +--- a/src/test/test-cgroup-util.c ++++ b/src/test/test-cgroup-util.c +@@ -296,7 +296,7 @@ static void test_shift_path(void) { + test_shift_path_one("/foobar/waldo", "/", "/foobar/waldo"); + test_shift_path_one("/foobar/waldo", "", "/foobar/waldo"); + test_shift_path_one("/foobar/waldo", "/foobar", "/waldo"); +- test_shift_path_one("/foobar/waldo", "/fuckfuck", "/foobar/waldo"); ++ test_shift_path_one("/foobar/waldo", "/hogehoge", "/foobar/waldo"); + } + + static void test_mask_supported(void) { +diff --git a/src/test/test-strv.c b/src/test/test-strv.c +index 9e7d98500f..165a5de91d 100644 +--- a/src/test/test-strv.c ++++ b/src/test/test-strv.c +@@ -279,18 +279,18 @@ static void test_strv_split_nulstr(void) { + + static void test_strv_parse_nulstr(void) { + _cleanup_strv_free_ char **l = NULL; +- const char nulstr[] = "fuck\0fuck2\0fuck3\0\0fuck5\0\0xxx"; ++ const char nulstr[] = "hoge\0hoge2\0hoge3\0\0hoge5\0\0xxx"; + + l = strv_parse_nulstr(nulstr, sizeof(nulstr)-1); + assert_se(l); + puts("Parse nulstr:"); + strv_print(l); + +- assert_se(streq(l[0], "fuck")); +- assert_se(streq(l[1], "fuck2")); +- assert_se(streq(l[2], "fuck3")); ++ assert_se(streq(l[0], "hoge")); ++ assert_se(streq(l[1], "hoge2")); ++ assert_se(streq(l[2], "hoge3")); + assert_se(streq(l[3], "")); +- assert_se(streq(l[4], "fuck5")); ++ assert_se(streq(l[4], "hoge5")); + assert_se(streq(l[5], "")); + assert_se(streq(l[6], "xxx")); + } diff --git a/SOURCES/0789-core-add-new-environment-variable-RUNTIME_DIRECTORY-.patch b/SOURCES/0789-core-add-new-environment-variable-RUNTIME_DIRECTORY-.patch new file mode 100644 index 0000000..ca2f947 --- /dev/null +++ b/SOURCES/0789-core-add-new-environment-variable-RUNTIME_DIRECTORY-.patch @@ -0,0 +1,124 @@ +From f41927c026d65e9005c0ba418c6bfff511055bd2 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 11 Sep 2018 14:05:08 +0900 +Subject: [PATCH] core: add new environment variable $RUNTIME_DIRECTORY= or + friends + +The variable is generated from RuntimeDirectory= or friends. +If multiple directories are set, then they are concatenated with +the separator ':'. + +(cherry picked from commit fb2042dd55de5019f55931b4f20a44700ec1222b) + +Resolves: #2049788 +--- + TODO | 9 --------- + src/core/execute.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 44 insertions(+), 11 deletions(-) + +diff --git a/TODO b/TODO +index 0705b6b08e..c52f9b25f3 100644 +--- a/TODO ++++ b/TODO +@@ -214,15 +214,6 @@ Features: + for all units. It should be both a way to pin units into memory as well as a + wait to retrieve their exit data. + +-* maybe set a new set of env vars for services, based on RuntimeDirectory=, +- StateDirectory=, LogsDirectory=, CacheDirectory= and ConfigurationDirectory= +- automatically. For example, there could be $RUNTIME_DIRECTORY, +- $STATE_DIRECTORY, $LOGS_DIRECTORY=, $CACHE_DIRECTORY and +- $CONFIGURATION_DIRECTORY or so. This could be useful to write services that +- can adapt to varying directories for these purposes. Special care has to be +- taken if multiple dirs are configured. Maybe avoid setting the env vars in +- that case? +- + * expose IO accounting data on the bus, show it in systemd-run --wait and log + about it in the resource log message + +diff --git a/src/core/execute.c b/src/core/execute.c +index 3ff1a51aa1..9cbb678ac4 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -1606,6 +1606,8 @@ static void do_idle_pipe_dance(int idle_pipe[4]) { + idle_pipe[3] = safe_close(idle_pipe[3]); + } + ++static const char *exec_directory_env_name_to_string(ExecDirectoryType t); ++ + static int build_environment( + const Unit *u, + const ExecContext *c, +@@ -1619,6 +1621,7 @@ static int build_environment( + char ***ret) { + + _cleanup_strv_free_ char **our_env = NULL; ++ ExecDirectoryType t; + size_t n_env = 0; + char *x; + +@@ -1627,7 +1630,7 @@ static int build_environment( + assert(p); + assert(ret); + +- our_env = new0(char*, 14); ++ our_env = new0(char*, 14 + _EXEC_DIRECTORY_TYPE_MAX); + if (!our_env) + return -ENOMEM; + +@@ -1733,8 +1736,37 @@ static int build_environment( + our_env[n_env++] = x; + } + ++ for (t = 0; t < _EXEC_DIRECTORY_TYPE_MAX; t++) { ++ _cleanup_free_ char *pre = NULL, *joined = NULL; ++ const char *n; ++ ++ if (!p->prefix[t]) ++ continue; ++ ++ if (strv_isempty(c->directories[t].paths)) ++ continue; ++ ++ n = exec_directory_env_name_to_string(t); ++ if (!n) ++ continue; ++ ++ pre = strjoin(p->prefix[t], "/"); ++ if (!pre) ++ return -ENOMEM; ++ ++ joined = strv_join_prefix(c->directories[t].paths, ":", pre); ++ if (!joined) ++ return -ENOMEM; ++ ++ x = strjoin(n, "=", joined); ++ if (!x) ++ return -ENOMEM; ++ ++ our_env[n_env++] = x; ++ } ++ + our_env[n_env++] = NULL; +- assert(n_env <= 14); ++ assert(n_env <= 14 + _EXEC_DIRECTORY_TYPE_MAX); + + *ret = TAKE_PTR(our_env); + +@@ -5197,6 +5229,16 @@ static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = { + + DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType); + ++static const char* const exec_directory_env_name_table[_EXEC_DIRECTORY_TYPE_MAX] = { ++ [EXEC_DIRECTORY_RUNTIME] = "RUNTIME_DIRECTORY", ++ [EXEC_DIRECTORY_STATE] = "STATE_DIRECTORY", ++ [EXEC_DIRECTORY_CACHE] = "CACHE_DIRECTORY", ++ [EXEC_DIRECTORY_LOGS] = "LOGS_DIRECTORY", ++ [EXEC_DIRECTORY_CONFIGURATION] = "CONFIGURATION_DIRECTORY", ++}; ++ ++DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(exec_directory_env_name, ExecDirectoryType); ++ + static const char* const exec_keyring_mode_table[_EXEC_KEYRING_MODE_MAX] = { + [EXEC_KEYRING_INHERIT] = "inherit", + [EXEC_KEYRING_PRIVATE] = "private", diff --git a/SOURCES/0790-test-execute-add-tests-for-RUNTIME_DIRECTORY-or-frie.patch b/SOURCES/0790-test-execute-add-tests-for-RUNTIME_DIRECTORY-or-frie.patch new file mode 100644 index 0000000..ec10dec --- /dev/null +++ b/SOURCES/0790-test-execute-add-tests-for-RUNTIME_DIRECTORY-or-frie.patch @@ -0,0 +1,76 @@ +From 5226df888c28ede9219d7f018af02cca1d1f6d2a Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 11 Sep 2018 14:07:53 +0900 +Subject: [PATCH] test-execute: add tests for $RUNTIME_DIRECTORY= or friends + +(cherry picked from commit 6088662d57bbd81167bd272d385fdd1044b287ec) + +Related: #2049788 +--- + .../test-execute/exec-dynamicuser-statedir-migrate-step1.service | 1 + + .../test-execute/exec-dynamicuser-statedir-migrate-step2.service | 1 + + test/test-execute/exec-dynamicuser-statedir.service | 1 + + test/test-execute/exec-runtimedirectory-mode.service | 1 + + test/test-execute/exec-runtimedirectory.service | 1 + + 5 files changed, 5 insertions(+) + +diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service +index 72e6d7686f..5efc5483b8 100644 +--- a/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service ++++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step1.service +@@ -10,6 +10,7 @@ ExecStart=test -d /var/lib/test-dynamicuser-migrate + ExecStart=test -d /var/lib/test-dynamicuser-migrate2/hoge + ExecStart=touch /var/lib/test-dynamicuser-migrate/yay + ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay ++ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/test-dynamicuser-migrate:%S/test-dynamicuser-migrate2/hoge"' + + Type=oneshot + DynamicUser=no +diff --git a/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service +index edb0be7ef8..c72302ffd5 100644 +--- a/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service ++++ b/test/test-execute/exec-dynamicuser-statedir-migrate-step2.service +@@ -18,6 +18,7 @@ ExecStart=touch /var/lib/test-dynamicuser-migrate/yay + ExecStart=touch /var/lib/test-dynamicuser-migrate2/hoge/yayyay + ExecStart=touch /var/lib/private/test-dynamicuser-migrate/yay + ExecStart=touch /var/lib/private/test-dynamicuser-migrate2/hoge/yayyay ++ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/test-dynamicuser-migrate:%S/test-dynamicuser-migrate2/hoge"' + + Type=oneshot + DynamicUser=yes +diff --git a/test/test-execute/exec-dynamicuser-statedir.service b/test/test-execute/exec-dynamicuser-statedir.service +index f459f3c1eb..2fb7b8660b 100644 +--- a/test/test-execute/exec-dynamicuser-statedir.service ++++ b/test/test-execute/exec-dynamicuser-statedir.service +@@ -10,6 +10,7 @@ ExecStart=test -f /var/lib/waldo/yay + ExecStart=test -f /var/lib/quux/pief/yayyay + ExecStart=test -f /var/lib/private/waldo/yay + ExecStart=test -f /var/lib/private/quux/pief/yayyay ++ExecStart=/bin/sh -x -c 'test "$$STATE_DIRECTORY" = "%S/waldo:%S/quux/pief"' + + # Make sure that /var/lib/private/waldo is really the only writable directory besides the obvious candidates + ExecStart=sh -x -c 'test $$(find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o -path /sys/fs/bpf \) -prune -o -type d -writable -print 2>/dev/null | sort -u | tr -d '\\\\n') = /var/lib/private/quux/pief/var/lib/private/waldo' +diff --git a/test/test-execute/exec-runtimedirectory-mode.service b/test/test-execute/exec-runtimedirectory-mode.service +index 480f904155..85ae5161c4 100644 +--- a/test/test-execute/exec-runtimedirectory-mode.service ++++ b/test/test-execute/exec-runtimedirectory-mode.service +@@ -3,6 +3,7 @@ Description=Test for RuntimeDirectoryMode + + [Service] + ExecStart=/bin/sh -x -c 'mode=$$(stat -c %%a %t/test-exec_runtimedirectory-mode); test "$$mode" = "750"' ++ExecStart=/bin/sh -x -c 'test "$$RUNTIME_DIRECTORY" = "%t/test-exec_runtimedirectory-mode"' + Type=oneshot + RuntimeDirectory=test-exec_runtimedirectory-mode + RuntimeDirectoryMode=0750 +diff --git a/test/test-execute/exec-runtimedirectory.service b/test/test-execute/exec-runtimedirectory.service +index 6a4383110f..a33044d23c 100644 +--- a/test/test-execute/exec-runtimedirectory.service ++++ b/test/test-execute/exec-runtimedirectory.service +@@ -4,6 +4,7 @@ Description=Test for RuntimeDirectory + [Service] + ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectory' + ExecStart=/bin/sh -x -c 'test -d %t/test-exec_runtimedirectory2/hogehoge' ++ExecStart=/bin/sh -x -c 'test "$$RUNTIME_DIRECTORY" = "%t/test-exec_runtimedirectory:%t/test-exec_runtimedirectory2/hogehoge"' + Type=oneshot + RuntimeDirectory=test-exec_runtimedirectory + RuntimeDirectory=./test-exec_runtimedirectory2///./hogehoge/. diff --git a/SOURCES/0791-man-document-RUNTIME_DIRECTORY-or-friends.patch b/SOURCES/0791-man-document-RUNTIME_DIRECTORY-or-friends.patch new file mode 100644 index 0000000..863c21b --- /dev/null +++ b/SOURCES/0791-man-document-RUNTIME_DIRECTORY-or-friends.patch @@ -0,0 +1,85 @@ +From a729ea1a59b63c5f3e7fdce6a6c4e2ce12faa972 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 11 Sep 2018 14:24:47 +0900 +Subject: [PATCH] man: document RUNTIME_DIRECTORY= or friends + +(cherry picked from commit d491e65e74a92898d6e7f95032b5b037c6e3cb60) + +Related: #2049788 +--- + man/systemd.exec.xml | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml +index 696438c4ef..dc88cf9781 100644 +--- a/man/systemd.exec.xml ++++ b/man/systemd.exec.xml +@@ -820,15 +820,18 @@ CapabilityBoundingSet=~CAP_B CAP_C + These options take a whitespace-separated list of directory names. The specified directory + names must be relative, and may not include ... If set, one or more + directories by the specified names will be created (including their parents) below the locations +- defined in the following table, when the unit is started. ++ defined in the following table, when the unit is started. Also, the corresponding environment variable ++ is defined with the full path of directories. If multiple directories are set, then int the environment variable ++ the paths are concatenated with colon (:). + +- Automatic directory creation +- ++ Automatic directory creation and environment variables ++ + + + Locations + for system + for users ++ Environment variable + + + +@@ -836,26 +839,31 @@ CapabilityBoundingSet=~CAP_B CAP_C + RuntimeDirectory= + /run + $XDG_RUNTIME_DIR ++ $RUNTIME_DIRECTORY + + + StateDirectory= + /var/lib + $XDG_CONFIG_HOME ++ $STATE_DIRECTORY + + + CacheDirectory= + /var/cache + $XDG_CACHE_HOME ++ $CACHE_DIRECTORY + + + LogsDirectory= + /var/log + $XDG_CONFIG_HOME/log ++ $LOGS_DIRECTORY + + + ConfigurationDirectory= + /etc + $XDG_CONFIG_HOME ++ $CONFIGURATION_DIRECTORY + + + +@@ -905,7 +913,13 @@ CapabilityBoundingSet=~CAP_B CAP_C + /run/foo/bar, and /run/baz. The directories + /run/foo/bar and /run/baz except /run/foo are + owned by the user and group specified in User= and Group=, and removed +- when the service is stopped. ++ when the service is stopped. ++ ++ Example: if a system service unit has the following, ++ RuntimeDirectory=foo/bar ++StateDirectory=aaa/bbb ccc ++ then the environment variable RUNTIME_DIRECTORY is set with /run/foo/bar, and ++ STATE_DIRECTORY is set with /var/lib/aaa/bbb:/var/lib/ccc. + + + diff --git a/SOURCES/0792-ci-bump-the-worker-Ubuntu-version-to-Jammy.patch b/SOURCES/0792-ci-bump-the-worker-Ubuntu-version-to-Jammy.patch new file mode 100644 index 0000000..7791008 --- /dev/null +++ b/SOURCES/0792-ci-bump-the-worker-Ubuntu-version-to-Jammy.patch @@ -0,0 +1,24 @@ +From 3a35fcaad4bb3831808280854eb84f68975279a1 Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 19 Jul 2022 22:44:07 +0200 +Subject: [PATCH] ci: bump the worker Ubuntu version to Jammy + +rhel-only +Related: #2087152 +--- + .github/workflows/unit_tests.yml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml +index 87b162fa71..f397e8ed6e 100644 +--- a/.github/workflows/unit_tests.yml ++++ b/.github/workflows/unit_tests.yml +@@ -6,7 +6,7 @@ on: [pull_request] + + jobs: + build: +- runs-on: ubuntu-20.04 ++ runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: diff --git a/SOURCES/0793-test-make-test-execute-pass-on-Linux-5.15.patch b/SOURCES/0793-test-make-test-execute-pass-on-Linux-5.15.patch new file mode 100644 index 0000000..9bc14ce --- /dev/null +++ b/SOURCES/0793-test-make-test-execute-pass-on-Linux-5.15.patch @@ -0,0 +1,43 @@ +From 434b4b64d17e16ed23f90c99c26dbd0e4ce6cd88 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 24 Nov 2021 15:58:50 +0100 +Subject: [PATCH] test: make test-execute pass on Linux 5.15 + +Linux 5.15 broke kernel API: + +https://github.com/torvalds/linux/commit/e70344c05995a190a56bbd1a23dc2218bcc8c924 + +Previously setting IOPRIO_CLASS_NONE for a process would then report +IOPRIO_CLASS_NONE back. But since 5.15 it reports IOPRIO_CLASS_BE +instead. Since IOPRIO_CLASS_NONE is an alias for a special setting of +IOPRIO_CLASS_BE this makes some sense, but it's also a kernel API +breakage that our testsuite trips up on. + +(I made some minimal effort to inform the kernel people about this API +breakage during the 5.15 rc phase, but noone was interested.) + +Either way let's hadle this gracefully in our test suite and accept +"best-effort" too when "none" was set. + +(This is only triggable if the tests are run on 5.15 with full privs) + +(cherry picked from commit d9b8771108cf2955efc3852b477391017d2c599a) + +Related: #2087152 +--- + test/test-execute/exec-ioschedulingclass-none.service | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/test/test-execute/exec-ioschedulingclass-none.service b/test/test-execute/exec-ioschedulingclass-none.service +index b6af122a1e..8f917d345d 100644 +--- a/test/test-execute/exec-ioschedulingclass-none.service ++++ b/test/test-execute/exec-ioschedulingclass-none.service +@@ -2,6 +2,7 @@ + Description=Test for IOSchedulingClass=none + + [Service] +-ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "none"' ++# Old kernels might report "none" here, new kernels "best-effort". ++ExecStart=/bin/sh -x -c 'c=$$(LC_ALL=C ionice); test "$${c%%:*}" = "none" -o "$${c%%:*}" = "best-effort"' + Type=oneshot + IOSchedulingClass=none diff --git a/SOURCES/0794-ci-install-iputils.patch b/SOURCES/0794-ci-install-iputils.patch new file mode 100644 index 0000000..97881f9 --- /dev/null +++ b/SOURCES/0794-ci-install-iputils.patch @@ -0,0 +1,25 @@ +From 128d784dacb456f9ea675911e88d4b47925bda0d Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Wed, 20 Jul 2022 10:24:36 +0200 +Subject: [PATCH] ci: install iputils + +Required by test-bpf. + +rhel-only +Related: #2087152 +--- + .github/workflows/unit_tests.sh | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/.github/workflows/unit_tests.sh b/.github/workflows/unit_tests.sh +index c1311310fb..3859433720 100755 +--- a/.github/workflows/unit_tests.sh ++++ b/.github/workflows/unit_tests.sh +@@ -11,6 +11,7 @@ ADDITIONAL_DEPS=( + dnsmasq + e2fsprogs + hostname ++ iputils + libasan + libubsan + nc diff --git a/SOURCES/0795-ci-Mergify-Add-ci-waived-logic.patch b/SOURCES/0795-ci-Mergify-Add-ci-waived-logic.patch new file mode 100644 index 0000000..4841062 --- /dev/null +++ b/SOURCES/0795-ci-Mergify-Add-ci-waived-logic.patch @@ -0,0 +1,63 @@ +From 0feaf0be515c02a10ca12f726b4a8424262cf09c Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Tue, 19 Jul 2022 12:43:43 +0200 +Subject: [PATCH] ci(Mergify): Add `ci-waived` logic + +RHEL-only + +Related: #2087152 +--- + .mergify.yml | 32 ++++++++++++++++++-------------- + 1 file changed, 18 insertions(+), 14 deletions(-) + +diff --git a/.mergify.yml b/.mergify.yml +index 6fa400effd..3afd04f18e 100644 +--- a/.mergify.yml ++++ b/.mergify.yml +@@ -4,6 +4,7 @@ + pull_request_rules: + - name: Add `needs-ci` label on CI fail + conditions: ++ - label!=ci-waived + - or: + # Unit tests + - -check-success=build (stream8, GCC) +@@ -27,21 +28,24 @@ pull_request_rules: + + - name: Remove `needs-ci` label on CI success + conditions: +- # Unit tests +- - check-success=build (stream8, GCC) +- - check-success=build (stream8, GCC_ASAN) +- # CentOS Stream CI +- - check-success=CentOS CI (CentOS Stream 8) +- # LGTM + - or: +- - "check-success=LGTM analysis: JavaScript" +- - "check-neutral=LGTM analysis: JavaScript" +- - or: +- - "check-success=LGTM analysis: Python" +- - "check-neutral=LGTM analysis: Python" +- - or: +- - "check-success=LGTM analysis: C/C++" +- - "check-neutral=LGTM analysis: C/C++" ++ - label=ci-waived ++ - and: ++ # Unit tests ++ - check-success=build (stream8, GCC) ++ - check-success=build (stream8, GCC_ASAN) ++ # CentOS Stream CI ++ - check-success=CentOS CI (CentOS Stream 8) ++ # LGTM ++ - or: ++ - "check-success=LGTM analysis: JavaScript" ++ - "check-neutral=LGTM analysis: JavaScript" ++ - or: ++ - "check-success=LGTM analysis: Python" ++ - "check-neutral=LGTM analysis: Python" ++ - or: ++ - "check-success=LGTM analysis: C/C++" ++ - "check-neutral=LGTM analysis: C/C++" + actions: + label: + remove: diff --git a/SOURCES/0796-sd-event-don-t-invalidate-source-type-on-disconnect.patch b/SOURCES/0796-sd-event-don-t-invalidate-source-type-on-disconnect.patch new file mode 100644 index 0000000..1c94030 --- /dev/null +++ b/SOURCES/0796-sd-event-don-t-invalidate-source-type-on-disconnect.patch @@ -0,0 +1,33 @@ +From e48586dcfa66731a353ecc832e43fab75559e2cf Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 30 Oct 2019 16:37:42 +0100 +Subject: [PATCH] sd-event: don't invalidate source type on disconnect + +This fixes fd closing if fd ownership is requested. + +(cherry picked from commit f59825595182d70b9ead238d1e885d0db99cc201) + +Resolves: #2115396 +--- + src/libsystemd/sd-event/sd-event.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 0adfdd9e1a..09d4584bf9 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -1104,11 +1104,13 @@ static void source_disconnect(sd_event_source *s) { + + event = s->event; + +- s->type = _SOURCE_EVENT_SOURCE_TYPE_INVALID; + s->event = NULL; + LIST_REMOVE(sources, event->sources, s); + event->n_sources--; + ++ /* Note that we don't invalidate the type here, since we still need it in order to close the fd or ++ * pidfd associated with this event source, which we'll do only on source_free(). */ ++ + if (!s->floating) + sd_event_unref(event); + } diff --git a/SOURCES/0797-tests-make-sure-we-delay-running-mount-start-jobs-wh.patch b/SOURCES/0797-tests-make-sure-we-delay-running-mount-start-jobs-wh.patch new file mode 100644 index 0000000..eb18da9 --- /dev/null +++ b/SOURCES/0797-tests-make-sure-we-delay-running-mount-start-jobs-wh.patch @@ -0,0 +1,98 @@ +From e6cd875a767ba23b218cdca395307ac6fb7fd882 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 30 May 2022 14:50:05 +0200 +Subject: [PATCH] tests: make sure we delay running mount start jobs when + /p/s/mountinfo is rate limited + +(cherry picked from commit 9e15be6c8d55abd800bf33f9776dd0e307ed37bc) + +Related: #2095744 +--- + test/TEST-60-MOUNT-RATELIMIT/testsuite.sh | 53 +++++++++++++++++++++++ + test/test-functions | 2 +- + 2 files changed, 54 insertions(+), 1 deletion(-) + +diff --git a/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh b/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh +index 6211050faf..84fe9640e1 100755 +--- a/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh ++++ b/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh +@@ -2,6 +2,56 @@ + set -eux + set -o pipefail + ++test_issue_20329() { ++ local tmpdir unit ++ tmpdir="$(mktemp -d)" ++ unit=$(systemd-escape --suffix mount --path "$tmpdir") ++ ++ # Set up test mount unit ++ cat > /run/systemd/system/"$unit" <&2 "Test mount \"$unit\" unit isn't mounted" ++ return 1 ++ } ++ mountpoint -q "$tmpdir" ++ ++ trap 'systemctl stop $unit' RETURN ++ ++ # Trigger the mount ratelimiting ++ cd "$(mktemp -d)" ++ mkdir foo ++ for ((i=0;i<50;++i)); do ++ mount --bind foo foo ++ umount foo ++ done ++ ++ # Unmount the test mount and start it immediately again via systemd ++ umount "$tmpdir" ++ systemctl start "$unit" ++ ++ # Make sure it is seen as mounted by systemd and it actually is mounted ++ [[ "$(systemctl show --property SubState --value "$unit")" = "mounted" ]] || { ++ echo >&2 "Test mount \"$unit\" unit isn't in \"mounted\" state" ++ return 1 ++ } ++ ++ mountpoint -q "$tmpdir" || { ++ echo >&2 "Test mount \"$unit\" is in \"mounted\" state, actually is not mounted" ++ return 1 ++ } ++} ++ + systemd-analyze log-level debug + systemd-analyze log-target journal + +@@ -85,6 +135,9 @@ if systemctl list-units -t mount tmp-meow* | grep -q tmp-meow; then + exit 42 + fi + ++# test that handling of mount start jobs is delayed when /proc/self/mouninfo monitor is rate limited ++test_issue_20329 ++ + systemd-analyze log-level info + + echo OK >/testok +diff --git a/test/test-functions b/test/test-functions +index 4d7832b1fb..ed8ab98173 100644 +--- a/test/test-functions ++++ b/test/test-functions +@@ -23,7 +23,7 @@ fi + + PATH_TO_INIT=$ROOTLIBDIR/systemd + +-BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env" ++BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env mktemp mountpoint" + DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find" + + STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))" diff --git a/SOURCES/0798-core-drop-references-to-StandardOutputFileToCreate.patch b/SOURCES/0798-core-drop-references-to-StandardOutputFileToCreate.patch new file mode 100644 index 0000000..b789e1f --- /dev/null +++ b/SOURCES/0798-core-drop-references-to-StandardOutputFileToCreate.patch @@ -0,0 +1,29 @@ +From 0bf1df5c35c310c3efe49c7a3cb8c3be3e33492b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 26 Nov 2018 21:05:37 +0100 +Subject: [PATCH] core: drop references to 'StandardOutputFileToCreate' + +This property never existed, let's drop any reference to it. + +(cherry picked from commit 922ce049d1ed37ce77e3322711e29f256d9e5959) + +Related: #2093479 +--- + src/core/dbus-execute.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 2e64f0baf4..05134851c5 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -1809,8 +1809,8 @@ int bus_exec_context_set_transient_property( + + } else if (STR_IN_SET(name, + "StandardInputFile", +- "StandardOutputFile", "StandardOutputFileToCreate", "StandardOutputFileToAppend", +- "StandardErrorFile", "StandardErrorFileToCreate", "StandardErrorFileToAppend")) { ++ "StandardOutputFile", "StandardOutputFileToAppend", ++ "StandardErrorFile", "StandardErrorFileToAppend")) { + const char *s; + + r = sd_bus_message_read(message, "s", &s); diff --git a/SOURCES/0799-dbus-execute-fix-indentation.patch b/SOURCES/0799-dbus-execute-fix-indentation.patch new file mode 100644 index 0000000..741b756 --- /dev/null +++ b/SOURCES/0799-dbus-execute-fix-indentation.patch @@ -0,0 +1,29 @@ +From 2ba82e6b7e9a7b138c985561dd7d26b9e4111fbe Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 26 Nov 2018 21:06:19 +0100 +Subject: [PATCH] dbus-execute: fix indentation + +(cherry picked from commit dbe6c4b657aa5c58bfc049d869b94f00b41b7d95) + +Related: #2093479 +--- + src/core/dbus-execute.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 05134851c5..fc433cc96f 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -1858,9 +1858,9 @@ int bus_exec_context_set_transient_property( + c->std_error = EXEC_OUTPUT_FILE; + unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s); + } else { +- assert(streq(name, "StandardErrorFileToAppend")); +- c->std_error = EXEC_OUTPUT_FILE_APPEND; +- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s); ++ assert(streq(name, "StandardErrorFileToAppend")); ++ c->std_error = EXEC_OUTPUT_FILE_APPEND; ++ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s); + } + } + } diff --git a/SOURCES/0800-dbus-execute-generate-the-correct-transient-unit-set.patch b/SOURCES/0800-dbus-execute-generate-the-correct-transient-unit-set.patch new file mode 100644 index 0000000..c84dea6 --- /dev/null +++ b/SOURCES/0800-dbus-execute-generate-the-correct-transient-unit-set.patch @@ -0,0 +1,30 @@ +From 4fbd505c5a15f2b6078dc43e5a1ff999993e8b23 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 26 Nov 2018 21:07:06 +0100 +Subject: [PATCH] dbus-execute: generate the correct transient unit setting + +(cherry picked from commit 1704fba92f7b2c92238b0833943669045374daf9) + +Related: #2093479 +--- + src/core/dbus-execute.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index fc433cc96f..00f4aeacef 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -1856,11 +1856,11 @@ int bus_exec_context_set_transient_property( + + if (streq(name, "StandardErrorFile")) { + c->std_error = EXEC_OUTPUT_FILE; +- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=file:%s", s); ++ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=file:%s", s); + } else { + assert(streq(name, "StandardErrorFileToAppend")); + c->std_error = EXEC_OUTPUT_FILE_APPEND; +- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardOutput=append:%s", s); ++ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardError=append:%s", s); + } + } + } diff --git a/SOURCES/0801-bus-unit-util-properly-accept-StandardOutput-append-.patch b/SOURCES/0801-bus-unit-util-properly-accept-StandardOutput-append-.patch new file mode 100644 index 0000000..004b1fa --- /dev/null +++ b/SOURCES/0801-bus-unit-util-properly-accept-StandardOutput-append-.patch @@ -0,0 +1,33 @@ +From b06347d1e85c98507ba386b24e6c7159edf4784f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 26 Nov 2018 21:07:39 +0100 +Subject: [PATCH] =?UTF-8?q?bus-unit-util:=20properly=20accept=20StandardOu?= + =?UTF-8?q?tput=3Dappend:=E2=80=A6=20settings?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +(cherry picked from commit 8d33232ef1ad051b5ed00bd7b5fffb5a19bb83ae) + +Resolves: #2093479 +--- + src/shared/bus-unit-util.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 9010448aaf..3910dfa812 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -894,9 +894,11 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con + } else if ((n = startswith(eq, "file:"))) { + appended = strjoina(field, "File"); + r = sd_bus_message_append(m, "(sv)", appended, "s", n); ++ } else if ((n = startswith(eq, "append:"))) { ++ appended = strjoina(field, "FileToAppend"); ++ r = sd_bus_message_append(m, "(sv)", appended, "s", n); + } else + r = sd_bus_message_append(m, "(sv)", field, "s", eq); +- + if (r < 0) + return bus_log_create_error(r); + diff --git a/SOURCES/0802-core-be-more-careful-when-inheriting-stdout-fds-to-s.patch b/SOURCES/0802-core-be-more-careful-when-inheriting-stdout-fds-to-s.patch new file mode 100644 index 0000000..68ef399 --- /dev/null +++ b/SOURCES/0802-core-be-more-careful-when-inheriting-stdout-fds-to-s.patch @@ -0,0 +1,68 @@ +From d6ffd324cc933efec946a3ffbed6fccfe7077203 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 26 Nov 2018 21:07:48 +0100 +Subject: [PATCH] core: be more careful when inheriting stdout fds to stderr + +We need to compare the fd name/file name if we inherit an fd from stdout +to stderr. Let's do that. + +Fixes: #10875 +(cherry picked from commit 41fc585a7a3b8ae857cad5fdad1bc70cdacfa8e5) + +Related: #2093479 +--- + src/core/execute.c | 27 +++++++++++++++++++++++++-- + 1 file changed, 25 insertions(+), 2 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index 9cbb678ac4..b1d8dceb32 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -545,6 +545,30 @@ static int setup_input( + } + } + ++static bool can_inherit_stderr_from_stdout( ++ const ExecContext *context, ++ ExecOutput o, ++ ExecOutput e) { ++ ++ assert(context); ++ ++ /* Returns true, if given the specified STDERR and STDOUT output we can directly dup() the stdout fd to the ++ * stderr fd */ ++ ++ if (e == EXEC_OUTPUT_INHERIT) ++ return true; ++ if (e != o) ++ return false; ++ ++ if (e == EXEC_OUTPUT_NAMED_FD) ++ return streq_ptr(context->stdio_fdname[STDOUT_FILENO], context->stdio_fdname[STDERR_FILENO]); ++ ++ if (IN_SET(e, EXEC_OUTPUT_FILE, EXEC_OUTPUT_FILE_APPEND)) ++ return streq_ptr(context->stdio_file[STDOUT_FILENO], context->stdio_file[STDERR_FILENO]); ++ ++ return true; ++} ++ + static int setup_output( + const Unit *unit, + const ExecContext *context, +@@ -603,7 +627,7 @@ static int setup_output( + return fileno; + + /* Duplicate from stdout if possible */ +- if ((e == o && e != EXEC_OUTPUT_NAMED_FD) || e == EXEC_OUTPUT_INHERIT) ++ if (can_inherit_stderr_from_stdout(context, o, e)) + return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno; + + o = e; +@@ -694,7 +718,6 @@ static int setup_output( + flags |= O_APPEND; + + fd = acquire_path(context->stdio_file[fileno], flags, 0666 & ~context->umask); +- + if (fd < 0) + return fd; + diff --git a/SOURCES/0803-test-add-a-test-for-StandardError-file.patch b/SOURCES/0803-test-add-a-test-for-StandardError-file.patch new file mode 100644 index 0000000..ed9f18d --- /dev/null +++ b/SOURCES/0803-test-add-a-test-for-StandardError-file.patch @@ -0,0 +1,136 @@ +From 2bbaa4b647c8a60a6c6a591f71313b0667447246 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 26 Nov 2018 21:09:07 +0100 +Subject: [PATCH] =?UTF-8?q?test:=20add=20a=20test=20for=20StandardError=3D?= + =?UTF-8?q?file:=E2=80=A6?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This deserves a test of its, given how broken on so many levels this +previously was. + +(cherry picked from commit 196b0a11f306b8041e35316feb05ed1f00380957) + +Related: #2093479 +--- + test/TEST-27-STDOUTFILE/Makefile | 1 + + test/TEST-27-STDOUTFILE/test.sh | 52 ++++++++++++++++++++++++++++ + test/TEST-27-STDOUTFILE/testsuite.sh | 40 +++++++++++++++++++++ + 3 files changed, 93 insertions(+) + create mode 120000 test/TEST-27-STDOUTFILE/Makefile + create mode 100755 test/TEST-27-STDOUTFILE/test.sh + create mode 100755 test/TEST-27-STDOUTFILE/testsuite.sh + +diff --git a/test/TEST-27-STDOUTFILE/Makefile b/test/TEST-27-STDOUTFILE/Makefile +new file mode 120000 +index 0000000000..e9f93b1104 +--- /dev/null ++++ b/test/TEST-27-STDOUTFILE/Makefile +@@ -0,0 +1 @@ ++../TEST-01-BASIC/Makefile +\ No newline at end of file +diff --git a/test/TEST-27-STDOUTFILE/test.sh b/test/TEST-27-STDOUTFILE/test.sh +new file mode 100755 +index 0000000000..724dbef231 +--- /dev/null ++++ b/test/TEST-27-STDOUTFILE/test.sh +@@ -0,0 +1,52 @@ ++#!/bin/bash ++# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- ++# ex: ts=8 sw=4 sts=4 et filetype=sh ++set -e ++TEST_DESCRIPTION="test StandardOutput=file:" ++ ++. $TEST_BASE_DIR/test-functions ++ ++test_setup() { ++ create_empty_image ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ ++ ( ++ LOG_LEVEL=5 ++ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) ++ ++ inst_binary cmp ++ ++ setup_basic_environment ++ ++ # mask some services that we do not want to run in these tests ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service ++ ++ # setup the testsuite service ++ cat >$initdir/etc/systemd/system/testsuite.service <&2' ++cmp /tmp/stdout <&2' ++cmp /tmp/stdout <&2' ++cmp /tmp/stdout < /testok ++ ++exit 0 diff --git a/SOURCES/0804-tree-wide-allow-ASCII-fallback-for-in-logs.patch b/SOURCES/0804-tree-wide-allow-ASCII-fallback-for-in-logs.patch new file mode 100644 index 0000000..d4e5b2c --- /dev/null +++ b/SOURCES/0804-tree-wide-allow-ASCII-fallback-for-in-logs.patch @@ -0,0 +1,260 @@ +From aa93c2acd6c9ed4eb0152be9002f59ecd9cc277e Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Fri, 24 Jun 2022 09:13:42 +0200 +Subject: [PATCH] =?UTF-8?q?tree-wide:=20allow=20ASCII=20fallback=20for=20?= + =?UTF-8?q?=E2=86=92=20in=20logs?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +(cherry picked from commit e2341b6bc325932b3f9f10874956952cbdbd6361) + +Resolves: #2093479 +--- + src/basic/mount-util.c | 5 +++-- + src/core/dbus.c | 4 +++- + src/core/namespace.c | 7 +++++-- + src/core/socket.c | 4 +++- + src/libsystemd/sd-bus/sd-bus.c | 4 +++- + src/login/logind-acl.c | 5 +++-- + src/resolve/resolved-dns-query.c | 11 +++++++++-- + src/shared/dns-domain.c | 9 ++++++--- + src/tmpfiles/tmpfiles.c | 4 +++- + 9 files changed, 38 insertions(+), 15 deletions(-) + +diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c +index 0c709001be..e7f9e514c2 100644 +--- a/src/basic/mount-util.c ++++ b/src/basic/mount-util.c +@@ -18,6 +18,7 @@ + #include "fileio.h" + #include "fs-util.h" + #include "hashmap.h" ++#include "locale-util.h" + #include "mount-util.h" + #include "parse-util.h" + #include "path-util.h" +@@ -844,8 +845,8 @@ int mount_verbose( + log_debug("Bind-mounting %s on %s (%s \"%s\")...", + what, where, strnull(fl), strempty(o)); + else if (f & MS_MOVE) +- log_debug("Moving mount %s → %s (%s \"%s\")...", +- what, where, strnull(fl), strempty(o)); ++ log_debug("Moving mount %s %s %s (%s \"%s\")...", ++ what, special_glyph(ARROW), where, strnull(fl), strempty(o)); + else + log_debug("Mounting %s on %s (%s \"%s\")...", + strna(type), where, strnull(fl), strempty(o)); +diff --git a/src/core/dbus.c b/src/core/dbus.c +index 584a8a1b01..66d838cdb4 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -31,6 +31,7 @@ + #include "dbus.h" + #include "fd-util.h" + #include "fs-util.h" ++#include "locale-util.h" + #include "log.h" + #include "missing.h" + #include "mkdir.h" +@@ -751,7 +752,8 @@ static int manager_dispatch_sync_bus_names(sd_event_source *es, void *userdata) + assert(s); + + if (!streq_ptr(s->bus_name, name)) { +- log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name); ++ log_unit_warning(u, "Bus name has changed from %s %s %s, ignoring.", ++ s->bus_name, special_glyph(ARROW), name); + continue; + } + +diff --git a/src/core/namespace.c b/src/core/namespace.c +index e4930db15c..3566795d46 100644 +--- a/src/core/namespace.c ++++ b/src/core/namespace.c +@@ -15,6 +15,7 @@ + #include "fd-util.h" + #include "fs-util.h" + #include "label.h" ++#include "locale-util.h" + #include "loop-util.h" + #include "loopback-setup.h" + #include "missing.h" +@@ -841,7 +842,8 @@ static int follow_symlink( + return -ELOOP; + } + +- log_debug("Followed mount entry path symlink %s → %s.", mount_entry_path(m), target); ++ log_debug("Followed mount entry path symlink %s %s %s.", ++ mount_entry_path(m), special_glyph(ARROW), target); + + free_and_replace(m->path_malloc, target); + m->has_prefix = true; +@@ -920,7 +922,8 @@ static int apply_mount( + if (r < 0) + return log_debug_errno(r, "Failed to follow symlinks on %s: %m", mount_entry_source(m)); + +- log_debug("Followed source symlinks %s → %s.", mount_entry_source(m), chased); ++ log_debug("Followed source symlinks %s %s %s.", ++ mount_entry_source(m), special_glyph(ARROW), chased); + + free_and_replace(m->source_malloc, chased); + +diff --git a/src/core/socket.c b/src/core/socket.c +index 6f9a0f7575..bdfeb43a70 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -25,6 +25,7 @@ + #include "in-addr-util.h" + #include "io-util.h" + #include "label.h" ++#include "locale-util.h" + #include "log.h" + #include "missing.h" + #include "mkdir.h" +@@ -1355,7 +1356,8 @@ static int socket_symlink(Socket *s) { + } + + if (r < 0) +- log_unit_warning_errno(UNIT(s), r, "Failed to create symlink %s → %s, ignoring: %m", p, *i); ++ log_unit_warning_errno(UNIT(s), r, "Failed to create symlink %s %s %s, ignoring: %m", ++ p, special_glyph(ARROW), *i); + } + + return 0; +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 803f3f50d6..21e54591f7 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -31,6 +31,7 @@ + #include "cgroup-util.h" + #include "def.h" + #include "fd-util.h" ++#include "locale-util.h" + #include "hexdecoct.h" + #include "hostname-util.h" + #include "macro.h" +@@ -518,7 +519,8 @@ void bus_set_state(sd_bus *bus, enum bus_state state) { + if (state == bus->state) + return; + +- log_debug("Bus %s: changing state %s → %s", strna(bus->description), table[bus->state], table[state]); ++ log_debug("Bus %s: changing state %s %s %s", strna(bus->description), ++ table[bus->state], special_glyph(ARROW), table[state]); + bus->state = state; + } + +diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c +index cafeb8822f..fe17eac0e6 100644 +--- a/src/login/logind-acl.c ++++ b/src/login/logind-acl.c +@@ -9,6 +9,7 @@ + #include "escape.h" + #include "fd-util.h" + #include "format-util.h" ++#include "locale-util.h" + #include "logind-acl.h" + #include "set.h" + #include "string-util.h" +@@ -260,8 +261,8 @@ int devnode_acl_all(struct udev *udev, + SET_FOREACH(n, nodes, i) { + int k; + +- log_debug("Changing ACLs at %s for seat %s (uid "UID_FMT"→"UID_FMT"%s%s)", +- n, seat, old_uid, new_uid, ++ log_debug("Changing ACLs at %s for seat %s (uid "UID_FMT"%s"UID_FMT"%s%s)", ++ n, seat, old_uid, special_glyph(ARROW), new_uid, + del ? " del" : "", add ? " add" : ""); + + k = devnode_acl(n, flush, del, old_uid, add, new_uid); +diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c +index c921fe841f..573e27d662 100644 +--- a/src/resolve/resolved-dns-query.c ++++ b/src/resolve/resolved-dns-query.c +@@ -3,6 +3,7 @@ + #include "alloc-util.h" + #include "dns-domain.h" + #include "dns-type.h" ++#include "locale-util.h" + #include "hostname-util.h" + #include "local-addresses.h" + #include "resolved-dns-query.h" +@@ -942,7 +943,10 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) + if (r < 0) + return r; + else if (r > 0) +- log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q->question_idna), dns_question_first_name(nq_idna)); ++ log_debug("Following CNAME/DNAME %s %s %s.", ++ dns_question_first_name(q->question_idna), ++ special_glyph(ARROW), ++ dns_question_first_name(nq_idna)); + + k = dns_question_is_equal(q->question_idna, q->question_utf8); + if (k < 0) +@@ -956,7 +960,10 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) + if (k < 0) + return k; + else if (k > 0) +- log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q->question_utf8), dns_question_first_name(nq_utf8)); ++ log_debug("Following UTF8 CNAME/DNAME %s %s %s.", ++ dns_question_first_name(q->question_utf8), ++ special_glyph(ARROW), ++ dns_question_first_name(nq_utf8)); + } + + if (r == 0 && k == 0) /* No actual cname happened? */ +diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c +index de2fcca8b2..59799dec56 100644 +--- a/src/shared/dns-domain.c ++++ b/src/shared/dns-domain.c +@@ -17,6 +17,7 @@ + + #include "alloc-util.h" + #include "dns-domain.h" ++#include "locale-util.h" + #include "hashmap.h" + #include "hexdecoct.h" + #include "in-addr-util.h" +@@ -1260,7 +1261,7 @@ int dns_name_apply_idna(const char *name, char **ret) { + + r = idn2_lookup_u8((uint8_t*) name, (uint8_t**) &t, + IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL); +- log_debug("idn2_lookup_u8: %s → %s", name, t); ++ log_debug("idn2_lookup_u8: %s %s %s", name, special_glyph(ARROW), t); + if (r == IDN2_OK) { + if (!startswith(name, "xn--")) { + _cleanup_free_ char *s = NULL; +@@ -1273,8 +1274,10 @@ int dns_name_apply_idna(const char *name, char **ret) { + } + + if (!streq_ptr(name, s)) { +- log_debug("idn2 roundtrip failed: \"%s\" → \"%s\" → \"%s\", ignoring.", +- name, t, s); ++ log_debug("idn2 roundtrip failed: \"%s\" %s \"%s\" %s \"%s\", ignoring.", ++ name, special_glyph(ARROW), t, ++ special_glyph(ARROW), s); ++ *ret = NULL; + return 0; + } + } +diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c +index 50fada99dd..b3c2aac746 100644 +--- a/src/tmpfiles/tmpfiles.c ++++ b/src/tmpfiles/tmpfiles.c +@@ -36,6 +36,7 @@ + #include "fs-util.h" + #include "glob-util.h" + #include "io-util.h" ++#include "locale-util.h" + #include "label.h" + #include "log.h" + #include "macro.h" +@@ -2143,7 +2144,8 @@ static int patch_var_run(const char *fname, unsigned line, char **path) { + * there's no immediate need for action by the user. However, in the interest of making things less confusing + * to the user, let's still inform the user that these snippets should really be updated. */ + +- log_notice("[%s:%u] Line references path below legacy directory /var/run/, updating %s → %s; please update the tmpfiles.d/ drop-in file accordingly.", fname, line, *path, n); ++ log_notice("[%s:%u] Line references path below legacy directory /var/run/, updating %s %s %s; please update the tmpfiles.d/ drop-in file accordingly.", ++ fname, line, *path, special_glyph(ARROW), n); + + free(*path); + *path = n; diff --git a/SOURCES/0805-tree-wide-allow-ASCII-fallback-for-in-logs.patch b/SOURCES/0805-tree-wide-allow-ASCII-fallback-for-in-logs.patch new file mode 100644 index 0000000..19fb968 --- /dev/null +++ b/SOURCES/0805-tree-wide-allow-ASCII-fallback-for-in-logs.patch @@ -0,0 +1,129 @@ +From f27568d24a29590b34fec3a96a5b3b5d290ba3d8 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Fri, 24 Jun 2022 09:59:44 +0200 +Subject: [PATCH] =?UTF-8?q?tree-wide:=20allow=20ASCII=20fallback=20for=20?= + =?UTF-8?q?=E2=80=A6=20in=20logs?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +(cherry picked from commit 28e5e1e97f47067bce190ea6b3404907d63e4320) + +Related: #2093479 +--- + src/core/manager.c | 5 +++-- + src/shared/vlan-util.c | 3 ++- + src/sysusers/sysusers.c | 5 +++-- + src/tmpfiles/tmpfiles.c | 6 +++--- + 4 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index 845c26f498..5873e5b6d7 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -49,6 +49,7 @@ + #include "io-util.h" + #include "label.h" + #include "locale-setup.h" ++#include "locale-util.h" + #include "log.h" + #include "macro.h" + #include "manager.h" +@@ -1404,7 +1405,7 @@ static void manager_coldplug(Manager *m) { + + assert(m); + +- log_debug("Invoking unit coldplug() handlers…"); ++ log_debug("Invoking unit coldplug() handlers%s", special_glyph(ELLIPSIS)); + + /* Let's place the units back into their deserialized state */ + HASHMAP_FOREACH_KEY(u, k, m->units, i) { +@@ -1426,7 +1427,7 @@ static void manager_catchup(Manager *m) { + + assert(m); + +- log_debug("Invoking unit catchup() handlers…"); ++ log_debug("Invoking unit catchup() handlers%s", special_glyph(ELLIPSIS)); + + /* Let's catch up on any state changes that happened while we were reloading/reexecing */ + HASHMAP_FOREACH_KEY(u, k, m->units, i) { +diff --git a/src/shared/vlan-util.c b/src/shared/vlan-util.c +index 400994a354..9301dacbe2 100644 +--- a/src/shared/vlan-util.c ++++ b/src/shared/vlan-util.c +@@ -1,6 +1,7 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include "conf-parser.h" ++#include "locale-util.h" + #include "parse-util.h" + #include "string-util.h" + #include "vlan-util.h" +@@ -67,7 +68,7 @@ int config_parse_vlanid( + + r = parse_vlanid(rvalue, id); + if (r == -ERANGE) { +- log_syntax(unit, LOG_ERR, filename, line, r, "VLAN identifier outside of valid range 0…4094, ignoring: %s", rvalue); ++ log_syntax(unit, LOG_ERR, filename, line, r, "VLAN identifier outside of valid range 0%s4094, ignoring: %s", special_glyph(ELLIPSIS), rvalue); + return 0; + } + if (r < 0) { +diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c +index a374ebaaf4..f547388151 100644 +--- a/src/sysusers/sysusers.c ++++ b/src/sysusers/sysusers.c +@@ -12,6 +12,7 @@ + #include "format-util.h" + #include "fs-util.h" + #include "hashmap.h" ++#include "locale-util.h" + #include "pager.h" + #include "path-util.h" + #include "selinux-util.h" +@@ -1890,13 +1891,13 @@ static int read_config_files(char **args) { + + STRV_FOREACH(f, files) + if (p && path_equal(*f, p)) { +- log_debug("Parsing arguments at position \"%s\"…", *f); ++ log_debug("Parsing arguments at position \"%s\"%s", *f, special_glyph(ELLIPSIS)); + + r = parse_arguments(args); + if (r < 0) + return r; + } else { +- log_debug("Reading config file \"%s\"…", *f); ++ log_debug("Reading config file \"%s\"%s", *f, special_glyph(ELLIPSIS)); + + /* Just warn, ignore result otherwise */ + (void) read_config_file(*f, true); +diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c +index b3c2aac746..8da525120b 100644 +--- a/src/tmpfiles/tmpfiles.c ++++ b/src/tmpfiles/tmpfiles.c +@@ -2654,7 +2654,7 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe + assert(fn); + + if (streq(fn, "-")) { +- log_debug("Reading config from stdin…"); ++ log_debug("Reading config from stdin%s", special_glyph(ELLIPSIS)); + fn = ""; + f = stdin; + } else { +@@ -2667,7 +2667,7 @@ static int read_config_file(char **config_dirs, const char *fn, bool ignore_enoe + + return log_error_errno(r, "Failed to open '%s': %m", fn); + } +- log_debug("Reading config file \"%s\"…", fn); ++ log_debug("Reading config file \"%s\"%s", fn, special_glyph(ELLIPSIS)); + f = _f; + } + +@@ -2765,7 +2765,7 @@ static int read_config_files(char **config_dirs, char **args, bool *invalid_conf + + STRV_FOREACH(f, files) + if (p && path_equal(*f, p)) { +- log_debug("Parsing arguments at position \"%s\"…", *f); ++ log_debug("Parsing arguments at position \"%s\"%s", *f, special_glyph(ELLIPSIS)); + + r = parse_arguments(config_dirs, args, invalid_config); + if (r < 0) diff --git a/SOURCES/0806-core-allow-to-set-default-timeout-for-devices.patch b/SOURCES/0806-core-allow-to-set-default-timeout-for-devices.patch new file mode 100644 index 0000000..a730ce9 --- /dev/null +++ b/SOURCES/0806-core-allow-to-set-default-timeout-for-devices.patch @@ -0,0 +1,115 @@ +From 207f51115c18c668982ef8bdb8a024fccaeb87f0 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Sat, 16 Jul 2022 09:49:12 +0200 +Subject: [PATCH] core: allow to set default timeout for devices + +Fixes: #19879 +(cherry picked from commit a0fe19f9f791c05af236265954b1d73e8fcf5468) + +Resolves: #1967245 +--- + src/core/dbus-manager.c | 1 + + src/core/device.c | 2 +- + src/core/main.c | 4 ++++ + src/core/manager.c | 1 + + src/core/manager.h | 1 + + src/core/system.conf.in | 1 + + 6 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c +index 7488f22116..5b1ed3646e 100644 +--- a/src/core/dbus-manager.c ++++ b/src/core/dbus-manager.c +@@ -2509,6 +2509,7 @@ const sd_bus_vtable bus_manager_vtable[] = { + SD_BUS_PROPERTY("DefaultTimerAccuracyUSec", "t", bus_property_get_usec, offsetof(Manager, default_timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("DefaultDeviceTimeoutUSec", "t", bus_property_get_usec, offsetof(Manager, default_device_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultRestartUSec", "t", bus_property_get_usec, offsetof(Manager, default_restart_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("DefaultStartLimitIntervalUSec", "t", bus_property_get_usec, offsetof(Manager, default_start_limit_interval), SD_BUS_VTABLE_PROPERTY_CONST), + /* The following two items are obsolete alias */ +diff --git a/src/core/device.c b/src/core/device.c +index cb8b66dfc5..71b7c1ef81 100644 +--- a/src/core/device.c ++++ b/src/core/device.c +@@ -97,7 +97,7 @@ static void device_init(Unit *u) { + * indefinitely for plugged in devices, something which cannot + * happen for the other units since their operations time out + * anyway. */ +- u->job_running_timeout = u->manager->default_timeout_start_usec; ++ u->job_running_timeout = u->manager->default_device_timeout_usec; + + u->ignore_on_isolate = true; + +diff --git a/src/core/main.c b/src/core/main.c +index 08a4df3c97..bfd4c531a7 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -109,6 +109,7 @@ static usec_t arg_default_restart_usec; + static usec_t arg_default_timeout_start_usec; + static usec_t arg_default_timeout_stop_usec; + static usec_t arg_default_timeout_abort_usec; ++static usec_t arg_default_device_timeout_usec; + static bool arg_default_timeout_abort_set; + static usec_t arg_default_start_limit_interval; + static unsigned arg_default_start_limit_burst; +@@ -687,6 +688,7 @@ static int parse_config_file(void) { + { "Manager", "DefaultStandardError", config_parse_output_restricted,0, &arg_default_std_error }, + { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec }, + { "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec }, ++ { "Manager", "DefaultDeviceTimeoutSec", config_parse_sec, 0, &arg_default_device_timeout_usec }, + { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec }, + { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */ + { "Manager", "DefaultStartLimitIntervalSec",config_parse_sec, 0, &arg_default_start_limit_interval }, +@@ -754,6 +756,7 @@ static void set_manager_defaults(Manager *m) { + m->default_std_error = arg_default_std_error; + m->default_timeout_start_usec = arg_default_timeout_start_usec; + m->default_timeout_stop_usec = arg_default_timeout_stop_usec; ++ m->default_device_timeout_usec = arg_default_device_timeout_usec; + m->default_restart_usec = arg_default_restart_usec; + m->default_start_limit_interval = arg_default_start_limit_interval; + m->default_start_limit_burst = arg_default_start_limit_burst; +@@ -2077,6 +2080,7 @@ static void reset_arguments(void) { + arg_default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; + arg_default_timeout_abort_usec = DEFAULT_TIMEOUT_USEC; + arg_default_timeout_abort_set = false; ++ arg_default_device_timeout_usec = DEFAULT_TIMEOUT_USEC; + arg_default_start_limit_interval = DEFAULT_START_LIMIT_INTERVAL; + arg_default_start_limit_burst = DEFAULT_START_LIMIT_BURST; + arg_runtime_watchdog = 0; +diff --git a/src/core/manager.c b/src/core/manager.c +index 5873e5b6d7..f4611e6f8f 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -731,6 +731,7 @@ int manager_new(UnitFileScope scope, unsigned test_run_flags, Manager **_m) { + m->default_tasks_max = UINT64_MAX; + m->default_timeout_start_usec = DEFAULT_TIMEOUT_USEC; + m->default_timeout_stop_usec = DEFAULT_TIMEOUT_USEC; ++ m->default_device_timeout_usec = DEFAULT_TIMEOUT_USEC, + m->default_restart_usec = DEFAULT_RESTART_USEC; + m->original_log_level = -1; + m->original_log_target = _LOG_TARGET_INVALID; +diff --git a/src/core/manager.h b/src/core/manager.h +index 7b572c8dfd..3f2cfc5e2e 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -285,6 +285,7 @@ struct Manager { + ExecOutput default_std_output, default_std_error; + + usec_t default_restart_usec, default_timeout_start_usec, default_timeout_stop_usec; ++ usec_t default_device_timeout_usec; + + usec_t default_start_limit_interval; + unsigned default_start_limit_burst; +diff --git a/src/core/system.conf.in b/src/core/system.conf.in +index 84246c0e36..2f6852a89f 100644 +--- a/src/core/system.conf.in ++++ b/src/core/system.conf.in +@@ -37,6 +37,7 @@ + #DefaultStandardError=inherit + #DefaultTimeoutStartSec=90s + #DefaultTimeoutStopSec=90s ++#DefaultDeviceTimeoutSec=90s + #DefaultRestartSec=100ms + #DefaultStartLimitIntervalSec=10s + #DefaultStartLimitBurst=5 diff --git a/SOURCES/0807-man-document-DefaultDeviceTimeoutSec.patch b/SOURCES/0807-man-document-DefaultDeviceTimeoutSec.patch new file mode 100644 index 0000000..eb248e3 --- /dev/null +++ b/SOURCES/0807-man-document-DefaultDeviceTimeoutSec.patch @@ -0,0 +1,34 @@ +From ba81eba0feaf5c34f52141301e2b7ca93128fed0 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Sat, 16 Jul 2022 10:16:41 +0200 +Subject: [PATCH] man: document DefaultDeviceTimeoutSec= + +(cherry picked from commit 9e69bd4801588c12811c611a1c68b54cecbe1718) + +Related: #1967245 +--- + man/systemd-system.conf.xml | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml +index 988c4e7665..3670f34cb5 100644 +--- a/man/systemd-system.conf.xml ++++ b/man/systemd-system.conf.xml +@@ -305,6 +305,17 @@ + 100ms. + + ++ ++ DefaultDeviceTimeoutSec= ++ ++ Configures the default timeout for waiting for devices. It can be changed per ++ device via the x-systemd.device-timeout= option in /etc/fstab ++ and /etc/crypttab (see ++ systemd.mount5, ++ crypttab5). ++ Defaults to 90s. ++ ++ + + DefaultStartLimitIntervalSec= + DefaultStartLimitBurst= diff --git a/SOURCES/0808-Revert-core-Propagate-condition-failed-state-to-trig.patch b/SOURCES/0808-Revert-core-Propagate-condition-failed-state-to-trig.patch new file mode 100644 index 0000000..51df34e --- /dev/null +++ b/SOURCES/0808-Revert-core-Propagate-condition-failed-state-to-trig.patch @@ -0,0 +1,255 @@ +From f1a1ff976ed0787c79a0f57d773bc555ab756b8c Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Fri, 17 Dec 2021 19:39:29 +0100 +Subject: [PATCH] Revert "core: Propagate condition failed state to triggering + units." + +This reverts commit 12ab94a1e4961a39c32efb60b71866ab588d3ea2. + +(cherry picked from commit 40f41f34d4af15d0147b5b2525f0b87ff62eae9a) + +Related: #2114005 +--- + src/core/automount.c | 14 ++++---------- + src/core/automount.h | 1 - + src/core/path.c | 16 +++++----------- + src/core/path.h | 1 - + src/core/socket.c | 28 +++++++++------------------- + src/core/socket.h | 1 - + src/core/timer.c | 12 +++--------- + src/core/timer.h | 1 - + src/core/unit.c | 10 ---------- + src/core/unit.h | 2 -- + 10 files changed, 21 insertions(+), 65 deletions(-) + +diff --git a/src/core/automount.c b/src/core/automount.c +index bac3b2fab7..c1c513d4a5 100644 +--- a/src/core/automount.c ++++ b/src/core/automount.c +@@ -776,11 +776,6 @@ static void automount_enter_running(Automount *a) { + goto fail; + } + +- if (unit_has_failed_condition_or_assert(trigger)) { +- automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED); +- return; +- } +- + r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) { + log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r)); +@@ -1092,11 +1087,10 @@ static int automount_can_start(Unit *u) { + } + + static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = { +- [AUTOMOUNT_SUCCESS] = "success", +- [AUTOMOUNT_FAILURE_RESOURCES] = "resources", +- [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +- [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit", +- [AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED] = "mount-condition-failed", ++ [AUTOMOUNT_SUCCESS] = "success", ++ [AUTOMOUNT_FAILURE_RESOURCES] = "resources", ++ [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit", ++ [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit", + }; + + DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult); +diff --git a/src/core/automount.h b/src/core/automount.h +index a7417d195c..21dd1c0774 100644 +--- a/src/core/automount.h ++++ b/src/core/automount.h +@@ -10,7 +10,6 @@ typedef enum AutomountResult { + AUTOMOUNT_FAILURE_RESOURCES, + AUTOMOUNT_FAILURE_START_LIMIT_HIT, + AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT, +- AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED, + _AUTOMOUNT_RESULT_MAX, + _AUTOMOUNT_RESULT_INVALID = -1 + } AutomountResult; +diff --git a/src/core/path.c b/src/core/path.c +index bf7e1bf3c2..c2facf0b16 100644 +--- a/src/core/path.c ++++ b/src/core/path.c +@@ -453,7 +453,7 @@ static void path_enter_dead(Path *p, PathResult f) { + else + unit_log_failure(UNIT(p), path_result_to_string(p->result)); + +- path_set_state(p, p->result == PATH_SUCCESS ? PATH_DEAD : PATH_FAILED); ++ path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD); + } + + static void path_enter_running(Path *p) { +@@ -711,11 +711,6 @@ static void path_trigger_notify(Unit *u, Unit *other) { + return; + } + +- if (unit_has_failed_condition_or_assert(other)) { +- path_enter_dead(p, PATH_FAILURE_UNIT_CONDITION_FAILED); +- return; +- } +- + /* Don't propagate anything if there's still a job queued */ + if (other->job) + return; +@@ -768,11 +763,10 @@ static const char* const path_type_table[_PATH_TYPE_MAX] = { + DEFINE_STRING_TABLE_LOOKUP(path_type, PathType); + + static const char* const path_result_table[_PATH_RESULT_MAX] = { +- [PATH_SUCCESS] = "success", +- [PATH_FAILURE_RESOURCES] = "resources", +- [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +- [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit", +- [PATH_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed", ++ [PATH_SUCCESS] = "success", ++ [PATH_FAILURE_RESOURCES] = "resources", ++ [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", ++ [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit", + }; + + DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); +diff --git a/src/core/path.h b/src/core/path.h +index 0ad6bd12c6..8a69f06c13 100644 +--- a/src/core/path.h ++++ b/src/core/path.h +@@ -46,7 +46,6 @@ typedef enum PathResult { + PATH_FAILURE_RESOURCES, + PATH_FAILURE_START_LIMIT_HIT, + PATH_FAILURE_UNIT_START_LIMIT_HIT, +- PATH_FAILURE_UNIT_CONDITION_FAILED, + _PATH_RESULT_MAX, + _PATH_RESULT_INVALID = -1 + } PathResult; +diff --git a/src/core/socket.c b/src/core/socket.c +index bdfeb43a70..9d47ca2616 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -2274,15 +2274,6 @@ static void socket_enter_running(Socket *s, int cfd) { + goto refuse; + } + +- if (UNIT_ISSET(s->service) && cfd < 0) { +- Unit *service = UNIT_DEREF(s->service); +- +- if (unit_has_failed_condition_or_assert(service)) { +- socket_enter_dead(s, SOCKET_FAILURE_SERVICE_CONDITION_FAILED); +- return; +- } +- } +- + if (cfd < 0) { + bool pending = false; + Unit *other; +@@ -3298,16 +3289,15 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = { + DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand); + + static const char* const socket_result_table[_SOCKET_RESULT_MAX] = { +- [SOCKET_SUCCESS] = "success", +- [SOCKET_FAILURE_RESOURCES] = "resources", +- [SOCKET_FAILURE_TIMEOUT] = "timeout", +- [SOCKET_FAILURE_EXIT_CODE] = "exit-code", +- [SOCKET_FAILURE_SIGNAL] = "signal", +- [SOCKET_FAILURE_CORE_DUMP] = "core-dump", +- [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +- [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit", +- [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit", +- [SOCKET_FAILURE_SERVICE_CONDITION_FAILED] = "service-condition-failed", ++ [SOCKET_SUCCESS] = "success", ++ [SOCKET_FAILURE_RESOURCES] = "resources", ++ [SOCKET_FAILURE_TIMEOUT] = "timeout", ++ [SOCKET_FAILURE_EXIT_CODE] = "exit-code", ++ [SOCKET_FAILURE_SIGNAL] = "signal", ++ [SOCKET_FAILURE_CORE_DUMP] = "core-dump", ++ [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit", ++ [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit", ++ [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit" + }; + + DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult); +diff --git a/src/core/socket.h b/src/core/socket.h +index b171b94316..2409dbf2a0 100644 +--- a/src/core/socket.h ++++ b/src/core/socket.h +@@ -39,7 +39,6 @@ typedef enum SocketResult { + SOCKET_FAILURE_START_LIMIT_HIT, + SOCKET_FAILURE_TRIGGER_LIMIT_HIT, + SOCKET_FAILURE_SERVICE_START_LIMIT_HIT, +- SOCKET_FAILURE_SERVICE_CONDITION_FAILED, + _SOCKET_RESULT_MAX, + _SOCKET_RESULT_INVALID = -1 + } SocketResult; +diff --git a/src/core/timer.c b/src/core/timer.c +index 3c8d89771d..990f05fee4 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -567,11 +567,6 @@ static void timer_enter_running(Timer *t) { + return; + } + +- if (unit_has_failed_condition_or_assert(trigger)) { +- timer_enter_dead(t, TIMER_FAILURE_UNIT_CONDITION_FAILED); +- return; +- } +- + r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) + goto fail; +@@ -855,10 +850,9 @@ static const char* const timer_base_table[_TIMER_BASE_MAX] = { + DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase); + + static const char* const timer_result_table[_TIMER_RESULT_MAX] = { +- [TIMER_SUCCESS] = "success", +- [TIMER_FAILURE_RESOURCES] = "resources", +- [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit", +- [TIMER_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed", ++ [TIMER_SUCCESS] = "success", ++ [TIMER_FAILURE_RESOURCES] = "resources", ++ [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit", + }; + + DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult); +diff --git a/src/core/timer.h b/src/core/timer.h +index d23e19d622..833aadb0b8 100644 +--- a/src/core/timer.h ++++ b/src/core/timer.h +@@ -32,7 +32,6 @@ typedef enum TimerResult { + TIMER_SUCCESS, + TIMER_FAILURE_RESOURCES, + TIMER_FAILURE_START_LIMIT_HIT, +- TIMER_FAILURE_UNIT_CONDITION_FAILED, + _TIMER_RESULT_MAX, + _TIMER_RESULT_INVALID = -1 + } TimerResult; +diff --git a/src/core/unit.c b/src/core/unit.c +index 0810bf5a58..dfe0c243ef 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -5661,16 +5661,6 @@ int unit_thaw_vtable_common(Unit *u) { + return unit_cgroup_freezer_action(u, FREEZER_THAW); + } + +-bool unit_has_failed_condition_or_assert(Unit *u) { +- if (dual_timestamp_is_set(&u->condition_timestamp) && !u->condition_result) +- return true; +- +- if (dual_timestamp_is_set(&u->assert_timestamp) && !u->assert_result) +- return true; +- +- return false; +-} +- + static const char* const collect_mode_table[_COLLECT_MODE_MAX] = { + [COLLECT_INACTIVE] = "inactive", + [COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed", +diff --git a/src/core/unit.h b/src/core/unit.h +index a924bd2e83..b8b914711f 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -847,8 +847,6 @@ void unit_thawed(Unit *u); + int unit_freeze_vtable_common(Unit *u); + int unit_thaw_vtable_common(Unit *u); + +-bool unit_has_failed_condition_or_assert(Unit *u); +- + /* Macros which append UNIT= or USER_UNIT= to the message */ + + #define log_unit_full(unit, level, error, ...) \ diff --git a/SOURCES/0809-core-Check-unit-start-rate-limiting-earlier.patch b/SOURCES/0809-core-Check-unit-start-rate-limiting-earlier.patch new file mode 100644 index 0000000..45f95d4 --- /dev/null +++ b/SOURCES/0809-core-Check-unit-start-rate-limiting-earlier.patch @@ -0,0 +1,137 @@ +From e393372ad5ba67acb9b397f044efdb1c9a100644 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Tue, 24 Aug 2021 16:46:47 +0100 +Subject: [PATCH] core: Check unit start rate limiting earlier + +[dtardon: This adds the test that's been left out by commit +471eda89a25a3ceac91a2d05e39a54aae78038ed] + +(cherry picked from commit 9727f2427ff6b2e1f4ab927cc57ad8e888f04e95) + +Related: #2114005 +--- + test/TEST-10-ISSUE-2467/test.sh | 3 ++ + test/TEST-63-ISSUE-17433/Makefile | 1 + + test/TEST-63-ISSUE-17433/test.sh | 42 ++++++++++++++++++++++ + test/TEST-63-ISSUE-17433/test63.path | 2 ++ + test/TEST-63-ISSUE-17433/test63.service | 5 +++ + test/TEST-63-ISSUE-17433/testsuite.service | 17 +++++++++ + 6 files changed, 70 insertions(+) + create mode 120000 test/TEST-63-ISSUE-17433/Makefile + create mode 100755 test/TEST-63-ISSUE-17433/test.sh + create mode 100644 test/TEST-63-ISSUE-17433/test63.path + create mode 100644 test/TEST-63-ISSUE-17433/test63.service + create mode 100644 test/TEST-63-ISSUE-17433/testsuite.service + +diff --git a/test/TEST-10-ISSUE-2467/test.sh b/test/TEST-10-ISSUE-2467/test.sh +index 0e61236686..a839ef79de 100755 +--- a/test/TEST-10-ISSUE-2467/test.sh ++++ b/test/TEST-10-ISSUE-2467/test.sh +@@ -42,6 +42,9 @@ EOF + [Unit] + Requires=test.socket + ConditionPathExistsGlob=/tmp/nonexistent ++# Make sure we hit the socket trigger limit in the test and not the service start limit. ++StartLimitInterval=1000 ++StartLimitBurst=1000 + + [Service] + ExecStart=/bin/true +diff --git a/test/TEST-63-ISSUE-17433/Makefile b/test/TEST-63-ISSUE-17433/Makefile +new file mode 120000 +index 0000000000..e9f93b1104 +--- /dev/null ++++ b/test/TEST-63-ISSUE-17433/Makefile +@@ -0,0 +1 @@ ++../TEST-01-BASIC/Makefile +\ No newline at end of file +diff --git a/test/TEST-63-ISSUE-17433/test.sh b/test/TEST-63-ISSUE-17433/test.sh +new file mode 100755 +index 0000000000..406a1e214c +--- /dev/null ++++ b/test/TEST-63-ISSUE-17433/test.sh +@@ -0,0 +1,42 @@ ++#!/usr/bin/env bash ++set -e ++ ++TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/17433" ++ ++# shellcheck source=test/test-functions ++. "${TEST_BASE_DIR:?}/test-functions" ++ ++test_setup() { ++ create_empty_image ++ mkdir -p $TESTDIR/root ++ mount ${LOOPDEV}p1 $TESTDIR/root ++ ++ # Create what will eventually be our root filesystem onto an overlay ++ ( ++ LOG_LEVEL=5 ++ eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) ++ ++ setup_basic_environment ++ ++ # setup the testsuite service ++ cp testsuite.service $initdir/etc/systemd/system/testsuite.service ++ ++ cp test63.path $initdir/etc/systemd/system/test63.path ++ cp test63.service $initdir/etc/systemd/system/test63.service ++ ++ setup_testsuite ++ ) || return 1 ++ setup_nspawn_root ++ ++ # mask some services that we do not want to run in these tests ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ++ ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service ++ ++ ddebug "umount $TESTDIR/root" ++ umount $TESTDIR/root ++} ++ ++do_test "$@" +diff --git a/test/TEST-63-ISSUE-17433/test63.path b/test/TEST-63-ISSUE-17433/test63.path +new file mode 100644 +index 0000000000..a6573bda0a +--- /dev/null ++++ b/test/TEST-63-ISSUE-17433/test63.path +@@ -0,0 +1,2 @@ ++[Path] ++PathExists=/tmp/test63 +diff --git a/test/TEST-63-ISSUE-17433/test63.service b/test/TEST-63-ISSUE-17433/test63.service +new file mode 100644 +index 0000000000..c83801874d +--- /dev/null ++++ b/test/TEST-63-ISSUE-17433/test63.service +@@ -0,0 +1,5 @@ ++[Unit] ++ConditionPathExists=!/tmp/nonexistent ++ ++[Service] ++ExecStart=true +diff --git a/test/TEST-63-ISSUE-17433/testsuite.service b/test/TEST-63-ISSUE-17433/testsuite.service +new file mode 100644 +index 0000000000..d3ca5b002b +--- /dev/null ++++ b/test/TEST-63-ISSUE-17433/testsuite.service +@@ -0,0 +1,17 @@ ++[Unit] ++Description=TEST-63-ISSUE-17433 ++ ++[Service] ++ExecStartPre=rm -f /failed /testok ++Type=oneshot ++ExecStart=rm -f /tmp/nonexistent ++ExecStart=systemctl start test63.path ++ExecStart=touch /tmp/test63 ++# Make sure systemd has sufficient time to hit the start limit for test63.service. ++ExecStart=sleep 2 ++ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p ActiveState)" = failed' ++ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p Result)" = start-limit-hit' ++# FIXME: The path remains active, which it should not ++# ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p ActiveState)" = failed' ++# ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p Result)" = unit-start-limit-hit' ++ExecStart=sh -x -c 'echo OK >/testok' diff --git a/SOURCES/0810-core-Add-trigger-limit-for-path-units.patch b/SOURCES/0810-core-Add-trigger-limit-for-path-units.patch new file mode 100644 index 0000000..7ddde88 --- /dev/null +++ b/SOURCES/0810-core-Add-trigger-limit-for-path-units.patch @@ -0,0 +1,127 @@ +From 9d3f5e5d222308d29aad9bf7b2bfc440143a8606 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Fri, 17 Dec 2021 20:01:31 +0100 +Subject: [PATCH] core: Add trigger limit for path units + +When conditions fail on a service unit, a path unit can cause +PID 1 to busy loop as it keeps trying to activate the service unit. +To avoid this from happening, add a trigger limit to the path unit, +identical to the trigger limit we have for socket units. + +Initially, let's start with a high limit and not make it configurable. +If needed, we can add properties to configure the rate limit similar +to the ones we have for socket units. + +(cherry picked from commit aaae822b37aa3ca39aebb516fdc6bef36d730c25) + +Resolves: #2114005 +--- + src/core/path.c | 10 ++++++++++ + src/core/path.h | 3 +++ + test/TEST-63-ISSUE-17433/test63.service | 2 +- + test/TEST-63-ISSUE-17433/testsuite.service | 21 +++++++++++++++++---- + 4 files changed, 31 insertions(+), 5 deletions(-) + +diff --git a/src/core/path.c b/src/core/path.c +index c2facf0b16..b899bde0de 100644 +--- a/src/core/path.c ++++ b/src/core/path.c +@@ -238,6 +238,9 @@ static void path_init(Unit *u) { + assert(u->load_state == UNIT_STUB); + + p->directory_mode = 0755; ++ ++ p->trigger_limit.interval = 2 * USEC_PER_SEC; ++ p->trigger_limit.burst = 200; + } + + void path_free_specs(Path *p) { +@@ -467,6 +470,12 @@ static void path_enter_running(Path *p) { + if (unit_stop_pending(UNIT(p))) + return; + ++ if (!ratelimit_below(&p->trigger_limit)) { ++ log_unit_warning(UNIT(p), "Trigger limit hit, refusing further activation."); ++ path_enter_dead(p, PATH_FAILURE_TRIGGER_LIMIT_HIT); ++ return; ++ } ++ + trigger = UNIT_TRIGGER(UNIT(p)); + if (!trigger) { + log_unit_error(UNIT(p), "Unit to trigger vanished."); +@@ -767,6 +776,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = { + [PATH_FAILURE_RESOURCES] = "resources", + [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", + [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit", ++ [PATH_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit", + }; + + DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); +diff --git a/src/core/path.h b/src/core/path.h +index 8a69f06c13..12fd13fbe3 100644 +--- a/src/core/path.h ++++ b/src/core/path.h +@@ -46,6 +46,7 @@ typedef enum PathResult { + PATH_FAILURE_RESOURCES, + PATH_FAILURE_START_LIMIT_HIT, + PATH_FAILURE_UNIT_START_LIMIT_HIT, ++ PATH_FAILURE_TRIGGER_LIMIT_HIT, + _PATH_RESULT_MAX, + _PATH_RESULT_INVALID = -1 + } PathResult; +@@ -63,6 +64,8 @@ struct Path { + mode_t directory_mode; + + PathResult result; ++ ++ RateLimit trigger_limit; + }; + + void path_free_specs(Path *p); +diff --git a/test/TEST-63-ISSUE-17433/test63.service b/test/TEST-63-ISSUE-17433/test63.service +index c83801874d..6292434c5c 100644 +--- a/test/TEST-63-ISSUE-17433/test63.service ++++ b/test/TEST-63-ISSUE-17433/test63.service +@@ -1,5 +1,5 @@ + [Unit] +-ConditionPathExists=!/tmp/nonexistent ++ConditionPathExists=/tmp/nonexistent + + [Service] + ExecStart=true +diff --git a/test/TEST-63-ISSUE-17433/testsuite.service b/test/TEST-63-ISSUE-17433/testsuite.service +index d3ca5b002b..39f9643890 100644 +--- a/test/TEST-63-ISSUE-17433/testsuite.service ++++ b/test/TEST-63-ISSUE-17433/testsuite.service +@@ -4,14 +4,27 @@ Description=TEST-63-ISSUE-17433 + [Service] + ExecStartPre=rm -f /failed /testok + Type=oneshot ++ ++# Test that a path unit continuously triggering a service that fails condition checks eventually fails with ++# the trigger-limit-hit error. + ExecStart=rm -f /tmp/nonexistent + ExecStart=systemctl start test63.path + ExecStart=touch /tmp/test63 +-# Make sure systemd has sufficient time to hit the start limit for test63.service. ++# Make sure systemd has sufficient time to hit the trigger limit for test63.path. + ExecStart=sleep 2 +-ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p ActiveState)" = failed' +-ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p Result)" = start-limit-hit' ++ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p ActiveState)" = inactive' ++ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p Result)" = success' + # FIXME: The path remains active, which it should not + # ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p ActiveState)" = failed' +-# ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p Result)" = unit-start-limit-hit' ++# ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p Result)" = trigger-limit-hit' ++ ++# Test that starting the service manually doesn't affect the path unit. ++ExecStart=rm -f /tmp/test63 ++ExecStart=systemctl reset-failed ++ExecStart=systemctl start test63.path ++ExecStart=systemctl start test63.service ++ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p ActiveState)" = inactive' ++ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p Result)" = success' ++ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p ActiveState)" = active' ++ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p Result)" = success' + ExecStart=sh -x -c 'echo OK >/testok' diff --git a/SOURCES/0811-meson-add-syscall-names-update-target.patch b/SOURCES/0811-meson-add-syscall-names-update-target.patch new file mode 100644 index 0000000..84961ed --- /dev/null +++ b/SOURCES/0811-meson-add-syscall-names-update-target.patch @@ -0,0 +1,680 @@ +From f20ccc0d505eccd59bb3814f59a63ea036be5bd5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 18 Aug 2020 16:27:20 +0200 +Subject: [PATCH] meson: add syscall-names-update target + +The calls to find_program("tools/*") are moved earlier so they can be used +in libshared/ (and it doesn't make sense to split them). + +(cherry picked from commit 47354b440e90626c320d8f142cb742ff569e3a40) + +Related: #2040247 +--- + meson.build | 13 +- + src/shared/meson.build | 6 + + src/shared/syscall-names.text | 597 ++++++++++++++++++++++++++++++++++ + tools/syscall-names-update.sh | 6 + + 4 files changed, 617 insertions(+), 5 deletions(-) + create mode 100644 src/shared/syscall-names.text + create mode 100755 tools/syscall-names-update.sh + +diff --git a/meson.build b/meson.build +index 57de947367..6729a9ea5e 100644 +--- a/meson.build ++++ b/meson.build +@@ -1417,6 +1417,14 @@ install_libsystemd_static = static_library( + + ############################################################ + ++hwdb_update_sh = find_program('tools/meson-hwdb-update.sh') ++make_directive_index_py = find_program('tools/make-directive-index.py') ++make_man_index_py = find_program('tools/make-man-index.py') ++syscall_names_update_sh = find_program('tools/syscall-names-update.sh') ++xml_helper_py = find_program('tools/xml_helper.py') ++ ++############################################################ ++ + # binaries that have --help and are intended for use by humans, + # usually, but not always, installed in /bin. + public_programs = [] +@@ -2721,11 +2729,6 @@ run_target('fuzzers', + + ############################################################ + +-make_directive_index_py = find_program('tools/make-directive-index.py') +-make_man_index_py = find_program('tools/make-man-index.py') +-xml_helper_py = find_program('tools/xml_helper.py') +-hwdb_update_sh = find_program('tools/meson-hwdb-update.sh') +- + subdir('units') + subdir('sysctl.d') + subdir('sysusers.d') +diff --git a/src/shared/meson.build b/src/shared/meson.build +index d0a1bba4c6..c9dd0a3a4e 100644 +--- a/src/shared/meson.build ++++ b/src/shared/meson.build +@@ -165,3 +165,9 @@ libshared = shared_library( + dependencies : libshared_deps, + install : true, + install_dir : rootlibexecdir) ++ ++############################################################ ++ ++run_target( ++ 'syscall-names-update', ++ command : [syscall_names_update_sh, meson.current_source_dir()]) +diff --git a/src/shared/syscall-names.text b/src/shared/syscall-names.text +new file mode 100644 +index 0000000000..40d18a8894 +--- /dev/null ++++ b/src/shared/syscall-names.text +@@ -0,0 +1,597 @@ ++_llseek ++_newselect ++_sysctl ++accept ++accept4 ++access ++acct ++add_key ++adjtimex ++alarm ++arc_gettls ++arc_settls ++arc_usr_cmpxchg ++arch_prctl ++arm_fadvise64_64 ++arm_sync_file_range ++atomic_barrier ++atomic_cmpxchg_32 ++bdflush ++bfin_spinlock ++bind ++bpf ++brk ++cache_sync ++cachectl ++cacheflush ++capget ++capset ++chdir ++chmod ++chown ++chown32 ++chroot ++clock_adjtime ++clock_adjtime64 ++clock_getres ++clock_getres_time64 ++clock_gettime ++clock_gettime64 ++clock_nanosleep ++clock_nanosleep_time64 ++clock_settime ++clock_settime64 ++clone ++clone2 ++clone3 ++close ++close_range ++connect ++copy_file_range ++creat ++create_module ++delete_module ++dipc ++dup ++dup2 ++dup3 ++epoll_create ++epoll_create1 ++epoll_ctl ++epoll_ctl_old ++epoll_pwait ++epoll_wait ++epoll_wait_old ++eventfd ++eventfd2 ++exec_with_loader ++execv ++execve ++execveat ++exit ++exit_group ++faccessat ++faccessat2 ++fadvise64 ++fadvise64_64 ++fallocate ++fanotify_init ++fanotify_mark ++fchdir ++fchmod ++fchmodat ++fchown ++fchown32 ++fchownat ++fcntl ++fcntl64 ++fdatasync ++fgetxattr ++finit_module ++flistxattr ++flock ++fork ++fp_udfiex_crtl ++fremovexattr ++fsconfig ++fsetxattr ++fsmount ++fsopen ++fspick ++fstat ++fstat64 ++fstatat64 ++fstatfs ++fstatfs64 ++fsync ++ftruncate ++ftruncate64 ++futex ++futex_time64 ++futimesat ++get_kernel_syms ++get_mempolicy ++get_robust_list ++get_thread_area ++getcpu ++getcwd ++getdents ++getdents64 ++getdomainname ++getdtablesize ++getegid ++getegid32 ++geteuid ++geteuid32 ++getgid ++getgid32 ++getgroups ++getgroups32 ++gethostname ++getitimer ++getpagesize ++getpeername ++getpgid ++getpgrp ++getpid ++getpmsg ++getppid ++getpriority ++getrandom ++getresgid ++getresgid32 ++getresuid ++getresuid32 ++getrlimit ++getrusage ++getsid ++getsockname ++getsockopt ++gettid ++gettimeofday ++getuid ++getuid32 ++getunwind ++getxattr ++getxgid ++getxpid ++getxuid ++idle ++init_module ++inotify_add_watch ++inotify_init ++inotify_init1 ++inotify_rm_watch ++io_cancel ++io_destroy ++io_getevents ++io_pgetevents ++io_pgetevents_time64 ++io_setup ++io_submit ++io_uring_enter ++io_uring_register ++io_uring_setup ++ioctl ++ioperm ++iopl ++ioprio_get ++ioprio_set ++ipc ++kcmp ++kern_features ++kexec_file_load ++kexec_load ++keyctl ++kill ++lchown ++lchown32 ++lgetxattr ++link ++linkat ++listen ++listxattr ++llistxattr ++lookup_dcookie ++lremovexattr ++lseek ++lsetxattr ++lstat ++lstat64 ++madvise ++mbind ++membarrier ++memfd_create ++memory_ordering ++migrate_pages ++mincore ++mkdir ++mkdirat ++mknod ++mknodat ++mlock ++mlock2 ++mlockall ++mmap ++mmap2 ++modify_ldt ++mount ++move_mount ++move_pages ++mprotect ++mq_getsetattr ++mq_notify ++mq_open ++mq_timedreceive ++mq_timedreceive_time64 ++mq_timedsend ++mq_timedsend_time64 ++mq_unlink ++mremap ++msgctl ++msgget ++msgrcv ++msgsnd ++msync ++multiplexer ++munlock ++munlockall ++munmap ++name_to_handle_at ++nanosleep ++newfstatat ++nfsservctl ++ni_syscall ++nice ++old_adjtimex ++old_getpagesize ++oldfstat ++oldlstat ++oldolduname ++oldstat ++oldumount ++olduname ++open ++open_by_handle_at ++open_tree ++openat ++openat2 ++or1k_atomic ++osf_adjtime ++osf_afs_syscall ++osf_alt_plock ++osf_alt_setsid ++osf_alt_sigpending ++osf_asynch_daemon ++osf_audcntl ++osf_audgen ++osf_chflags ++osf_execve ++osf_exportfs ++osf_fchflags ++osf_fdatasync ++osf_fpathconf ++osf_fstat ++osf_fstatfs ++osf_fstatfs64 ++osf_fuser ++osf_getaddressconf ++osf_getdirentries ++osf_getdomainname ++osf_getfh ++osf_getfsstat ++osf_gethostid ++osf_getitimer ++osf_getlogin ++osf_getmnt ++osf_getrusage ++osf_getsysinfo ++osf_gettimeofday ++osf_kloadcall ++osf_kmodcall ++osf_lstat ++osf_memcntl ++osf_mincore ++osf_mount ++osf_mremap ++osf_msfs_syscall ++osf_msleep ++osf_mvalid ++osf_mwakeup ++osf_naccept ++osf_nfssvc ++osf_ngetpeername ++osf_ngetsockname ++osf_nrecvfrom ++osf_nrecvmsg ++osf_nsendmsg ++osf_ntp_adjtime ++osf_ntp_gettime ++osf_old_creat ++osf_old_fstat ++osf_old_getpgrp ++osf_old_killpg ++osf_old_lstat ++osf_old_open ++osf_old_sigaction ++osf_old_sigblock ++osf_old_sigreturn ++osf_old_sigsetmask ++osf_old_sigvec ++osf_old_stat ++osf_old_vadvise ++osf_old_vtrace ++osf_old_wait ++osf_oldquota ++osf_pathconf ++osf_pid_block ++osf_pid_unblock ++osf_plock ++osf_priocntlset ++osf_profil ++osf_proplist_syscall ++osf_reboot ++osf_revoke ++osf_sbrk ++osf_security ++osf_select ++osf_set_program_attributes ++osf_set_speculative ++osf_sethostid ++osf_setitimer ++osf_setlogin ++osf_setsysinfo ++osf_settimeofday ++osf_shmat ++osf_signal ++osf_sigprocmask ++osf_sigsendset ++osf_sigstack ++osf_sigwaitprim ++osf_sstk ++osf_stat ++osf_statfs ++osf_statfs64 ++osf_subsys_info ++osf_swapctl ++osf_swapon ++osf_syscall ++osf_sysinfo ++osf_table ++osf_uadmin ++osf_usleep_thread ++osf_uswitch ++osf_utc_adjtime ++osf_utc_gettime ++osf_utimes ++osf_utsname ++osf_wait4 ++osf_waitid ++pause ++pciconfig_iobase ++pciconfig_read ++pciconfig_write ++perf_event_open ++perfctr ++perfmonctl ++personality ++pidfd_getfd ++pidfd_open ++pidfd_send_signal ++pipe ++pipe2 ++pivot_root ++pkey_alloc ++pkey_free ++pkey_mprotect ++poll ++ppoll ++ppoll_time64 ++prctl ++pread64 ++preadv ++preadv2 ++prlimit64 ++process_vm_readv ++process_vm_writev ++pselect6 ++pselect6_time64 ++ptrace ++pwrite64 ++pwritev ++pwritev2 ++query_module ++quotactl ++read ++readahead ++readdir ++readlink ++readlinkat ++readv ++reboot ++recv ++recvfrom ++recvmmsg ++recvmmsg_time64 ++recvmsg ++remap_file_pages ++removexattr ++rename ++renameat ++renameat2 ++request_key ++restart_syscall ++riscv_flush_icache ++rmdir ++rseq ++rt_sigaction ++rt_sigpending ++rt_sigprocmask ++rt_sigqueueinfo ++rt_sigreturn ++rt_sigsuspend ++rt_sigtimedwait ++rt_sigtimedwait_time64 ++rt_tgsigqueueinfo ++rtas ++s390_guarded_storage ++s390_pci_mmio_read ++s390_pci_mmio_write ++s390_runtime_instr ++s390_sthyi ++sched_get_affinity ++sched_get_priority_max ++sched_get_priority_min ++sched_getaffinity ++sched_getattr ++sched_getparam ++sched_getscheduler ++sched_rr_get_interval ++sched_rr_get_interval_time64 ++sched_set_affinity ++sched_setaffinity ++sched_setattr ++sched_setparam ++sched_setscheduler ++sched_yield ++seccomp ++select ++semctl ++semget ++semop ++semtimedop ++semtimedop_time64 ++send ++sendfile ++sendfile64 ++sendmmsg ++sendmsg ++sendto ++set_mempolicy ++set_robust_list ++set_thread_area ++set_tid_address ++setdomainname ++setfsgid ++setfsgid32 ++setfsuid ++setfsuid32 ++setgid ++setgid32 ++setgroups ++setgroups32 ++sethae ++sethostname ++setitimer ++setns ++setpgid ++setpgrp ++setpriority ++setregid ++setregid32 ++setresgid ++setresgid32 ++setresuid ++setresuid32 ++setreuid ++setreuid32 ++setrlimit ++setsid ++setsockopt ++settimeofday ++setuid ++setuid32 ++setxattr ++sgetmask ++shmat ++shmctl ++shmdt ++shmget ++shutdown ++sigaction ++sigaltstack ++signal ++signalfd ++signalfd4 ++sigpending ++sigprocmask ++sigreturn ++sigsuspend ++socket ++socketcall ++socketpair ++splice ++spu_create ++spu_run ++ssetmask ++stat ++stat64 ++statfs ++statfs64 ++statx ++stime ++subpage_prot ++swapcontext ++swapoff ++swapon ++switch_endian ++symlink ++symlinkat ++sync ++sync_file_range ++sync_file_range2 ++syncfs ++sys_debug_setcontext ++syscall ++sysfs ++sysinfo ++syslog ++sysmips ++tee ++tgkill ++time ++timer_create ++timer_delete ++timer_getoverrun ++timer_gettime ++timer_gettime64 ++timer_settime ++timer_settime64 ++timerfd ++timerfd_create ++timerfd_gettime ++timerfd_gettime64 ++timerfd_settime ++timerfd_settime64 ++times ++tkill ++truncate ++truncate64 ++udftrap ++ugetrlimit ++umask ++umount ++umount2 ++uname ++unlink ++unlinkat ++unshare ++uselib ++userfaultfd ++ustat ++utime ++utimensat ++utimensat_time64 ++utimes ++utimesat ++utrap_install ++vfork ++vhangup ++vm86 ++vm86old ++vmsplice ++wait4 ++waitid ++waitpid ++write ++writev +diff --git a/tools/syscall-names-update.sh b/tools/syscall-names-update.sh +new file mode 100755 +index 0000000000..c884b93cda +--- /dev/null ++++ b/tools/syscall-names-update.sh +@@ -0,0 +1,6 @@ ++#!/bin/sh ++set -eu ++ ++cd "$1" ++ ++curl -L -o syscall-names.text 'https://raw.githubusercontent.com/hrw/syscalls-table/master/syscall-names.text' diff --git a/SOURCES/0812-syscall-names-add-process_madvise-which-is-planned-f.patch b/SOURCES/0812-syscall-names-add-process_madvise-which-is-planned-f.patch new file mode 100644 index 0000000..4bd00ec --- /dev/null +++ b/SOURCES/0812-syscall-names-add-process_madvise-which-is-planned-f.patch @@ -0,0 +1,27 @@ +From bcc0f8bfbc0ea220895c1d3a8bf2d3124ddcef16 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 25 Oct 2020 13:54:20 +0100 +Subject: [PATCH] syscall-names: add process_madvise which is planned for 5.10 + +It was added in v5.9-11793-gecb8ac8b1f and is still present in v5.10-rc1, so it +seems likely that it'll be in 5.10 too. + +(cherry picked from commit 397cca2453465d4ad5a51b16ad71acf45a3de352) + +Related: #2040247 +--- + src/shared/syscall-names.text | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/shared/syscall-names.text b/src/shared/syscall-names.text +index 40d18a8894..f1b7e29d50 100644 +--- a/src/shared/syscall-names.text ++++ b/src/shared/syscall-names.text +@@ -392,6 +392,7 @@ pread64 + preadv + preadv2 + prlimit64 ++process_madvise + process_vm_readv + process_vm_writev + pselect6 diff --git a/SOURCES/0813-shared-add-known-syscall-list.patch b/SOURCES/0813-shared-add-known-syscall-list.patch new file mode 100644 index 0000000..eb4f2f4 --- /dev/null +++ b/SOURCES/0813-shared-add-known-syscall-list.patch @@ -0,0 +1,157 @@ +From f3c6abebbe4718085fcf17ed3ab0690e379fbb7e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 19 Aug 2020 17:43:23 +0200 +Subject: [PATCH] shared: add @known syscall list + +(cherry picked from commit 95aac01259db689dac7d8e5bfafb60e8c70cd734) + +Related: #2040247 +--- + man/systemd.exec.xml | 4 ++++ + src/shared/generate-syscall-list.py | 5 +++++ + src/shared/meson.build | 11 +++++++++++ + src/shared/seccomp-util.c | 6 ++++++ + src/shared/seccomp-util.h | 3 ++- + src/test/test-seccomp.c | 19 ++++++++++++------- + 6 files changed, 40 insertions(+), 8 deletions(-) + create mode 100755 src/shared/generate-syscall-list.py + +diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml +index dc88cf9781..b04b4ba552 100644 +--- a/man/systemd.exec.xml ++++ b/man/systemd.exec.xml +@@ -1556,6 +1556,10 @@ RestrictNamespaces=~cgroup net + @timer + System calls for scheduling operations by time (alarm2, timer_create2, …) + ++ ++ @known ++ All system calls defined by the kernel. This list is defined statically in systemd based on a kernel version that was available when this systmed version was released. It will become progressively more out-of-date as the kernel is updated. ++ + + +
+diff --git a/src/shared/generate-syscall-list.py b/src/shared/generate-syscall-list.py +new file mode 100755 +index 0000000000..13a6ae9241 +--- /dev/null ++++ b/src/shared/generate-syscall-list.py +@@ -0,0 +1,5 @@ ++#!/usr/bin/env python ++import sys ++ ++for line in open(sys.argv[1]): ++ print('"{}\\0"'.format(line.strip())) +diff --git a/src/shared/meson.build b/src/shared/meson.build +index c9dd0a3a4e..fed08571d1 100644 +--- a/src/shared/meson.build ++++ b/src/shared/meson.build +@@ -109,6 +109,16 @@ shared_sources = files(''' + test_tables_h = files('test-tables.h') + shared_sources += [test_tables_h] + ++generate_syscall_list = find_program('generate-syscall-list.py') ++fname = 'syscall-list.h' ++syscall_list_h = custom_target( ++ fname, ++ input : 'syscall-names.text', ++ output : fname, ++ command : [generate_syscall_list, ++ '@INPUT@'], ++ capture : true) ++ + if conf.get('HAVE_ACL') == 1 + shared_sources += files('acl-util.c') + endif +@@ -119,6 +129,7 @@ endif + + if conf.get('HAVE_SECCOMP') == 1 + shared_sources += files('seccomp-util.c') ++ shared_sources += syscall_list_h + endif + + if conf.get('HAVE_LIBIPTC') == 1 +diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c +index c57c409433..c2b2f2da92 100644 +--- a/src/shared/seccomp-util.c ++++ b/src/shared/seccomp-util.c +@@ -855,6 +855,12 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { + "timerfd_settime\0" + "times\0" + }, ++ [SYSCALL_FILTER_SET_KNOWN] = { ++ .name = "@known", ++ .help = "All known syscalls declared in the kernel", ++ .value = ++#include "syscall-list.h" ++ }, + }; + + const SyscallFilterSet *syscall_filter_set_find(const char *name) { +diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h +index 602f092255..541ba1e067 100644 +--- a/src/shared/seccomp-util.h ++++ b/src/shared/seccomp-util.h +@@ -21,7 +21,7 @@ typedef struct SyscallFilterSet { + } SyscallFilterSet; + + enum { +- /* Please leave DEFAULT first, but sort the rest alphabetically */ ++ /* Please leave DEFAULT first and KNOWN last, but sort the rest alphabetically */ + SYSCALL_FILTER_SET_DEFAULT, + SYSCALL_FILTER_SET_AIO, + SYSCALL_FILTER_SET_BASIC_IO, +@@ -49,6 +49,7 @@ enum { + SYSCALL_FILTER_SET_SYNC, + SYSCALL_FILTER_SET_SYSTEM_SERVICE, + SYSCALL_FILTER_SET_TIMER, ++ SYSCALL_FILTER_SET_KNOWN, + _SYSCALL_FILTER_SET_MAX + }; + +diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c +index 6ec04c4c55..286f01b5ce 100644 +--- a/src/test/test-seccomp.c ++++ b/src/test/test-seccomp.c +@@ -106,8 +106,10 @@ static void test_filter_sets(void) { + if (pid == 0) { /* Child? */ + int fd; + +- /* If we look at the default set (or one that includes it), whitelist instead of blacklist */ +- if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, SYSCALL_FILTER_SET_SYSTEM_SERVICE)) ++ /* If we look at the default set (or one that includes it), allow-list instead of deny-list */ ++ if (IN_SET(i, SYSCALL_FILTER_SET_DEFAULT, ++ SYSCALL_FILTER_SET_SYSTEM_SERVICE, ++ SYSCALL_FILTER_SET_KNOWN)) + r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW, true); + else + r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN), true); +@@ -639,20 +641,23 @@ static void test_lock_personality(void) { + } + + static void test_filter_sets_ordered(void) { +- size_t i; +- + /* Ensure "@default" always remains at the beginning of the list */ + assert_se(SYSCALL_FILTER_SET_DEFAULT == 0); + assert_se(streq(syscall_filter_sets[0].name, "@default")); + +- for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { ++ /* Ensure "@known" always remains at the end of the list */ ++ assert_se(SYSCALL_FILTER_SET_KNOWN == _SYSCALL_FILTER_SET_MAX - 1); ++ assert_se(streq(syscall_filter_sets[SYSCALL_FILTER_SET_KNOWN].name, "@known")); ++ ++ for (size_t i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) { + const char *k, *p = NULL; + + /* Make sure each group has a description */ + assert_se(!isempty(syscall_filter_sets[0].help)); + +- /* Make sure the groups are ordered alphabetically, except for the first entry */ +- assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0); ++ /* Make sure the groups are ordered alphabetically, except for the first and last entries */ ++ assert_se(i < 2 || i == _SYSCALL_FILTER_SET_MAX - 1 || ++ strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0); + + NULSTR_FOREACH(k, syscall_filter_sets[i].value) { + diff --git a/SOURCES/0814-generate-syscall-list-require-python3.patch b/SOURCES/0814-generate-syscall-list-require-python3.patch new file mode 100644 index 0000000..20891a6 --- /dev/null +++ b/SOURCES/0814-generate-syscall-list-require-python3.patch @@ -0,0 +1,24 @@ +From da722bc383c359b77fab671a0e7872fe4c0232ce Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sat, 22 Aug 2020 16:07:05 +0200 +Subject: [PATCH] generate-syscall-list: require python3 + +Python3.4 works, but 2.7 returns a tuple from os.uname(). + +(cherry picked from commit 8694114b809f92f6a882134f3635aa42bfb41e11) + +Related: #2040247 +--- + src/shared/generate-syscall-list.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/generate-syscall-list.py b/src/shared/generate-syscall-list.py +index 13a6ae9241..0b90d2d276 100755 +--- a/src/shared/generate-syscall-list.py ++++ b/src/shared/generate-syscall-list.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + import sys + + for line in open(sys.argv[1]): diff --git a/SOURCES/0815-shared-seccomp-reduce-scope-of-indexing-variables.patch b/SOURCES/0815-shared-seccomp-reduce-scope-of-indexing-variables.patch new file mode 100644 index 0000000..afd8d57 --- /dev/null +++ b/SOURCES/0815-shared-seccomp-reduce-scope-of-indexing-variables.patch @@ -0,0 +1,82 @@ +From 64705366e134f06438e88f0b7fbef341d0a01431 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 19 Aug 2020 17:43:40 +0200 +Subject: [PATCH] shared/seccomp: reduce scope of indexing variables + +(cherry picked from commit 077e8fc0cad5a4532348d20a1eef8621295dd75a) + +Related: #2040247 +--- + src/shared/seccomp-util.c | 14 +++++--------- + 1 file changed, 5 insertions(+), 9 deletions(-) + +diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c +index c2b2f2da92..4d2ba31d47 100644 +--- a/src/shared/seccomp-util.c ++++ b/src/shared/seccomp-util.c +@@ -864,12 +864,10 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { + }; + + const SyscallFilterSet *syscall_filter_set_find(const char *name) { +- unsigned i; +- + if (isempty(name) || name[0] != '@') + return NULL; + +- for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) ++ for (unsigned i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) + if (streq(syscall_filter_sets[i].name, name)) + return syscall_filter_sets + i; + +@@ -1105,7 +1103,6 @@ int seccomp_restrict_namespaces(unsigned long retain) { + + SECCOMP_FOREACH_LOCAL_ARCH(arch) { + _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL; +- unsigned i; + + log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch)); + +@@ -1135,7 +1132,7 @@ int seccomp_restrict_namespaces(unsigned long retain) { + continue; + } + +- for (i = 0; namespace_flag_map[i].name; i++) { ++ for (unsigned i = 0; namespace_flag_map[i].name; i++) { + unsigned long f; + + f = namespace_flag_map[i].flag; +@@ -1288,7 +1285,7 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) { + return r; + + if (whitelist) { +- int af, first = 0, last = 0; ++ int first = 0, last = 0; + void *afp; + + /* If this is a whitelist, we first block the address families that are out of range and then +@@ -1296,7 +1293,7 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) { + * the set. */ + + SET_FOREACH(afp, address_families, i) { +- af = PTR_TO_INT(afp); ++ int af = PTR_TO_INT(afp); + + if (af <= 0 || af >= af_max()) + continue; +@@ -1350,7 +1347,7 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) { + } + + /* Block everything between the first and last entry */ +- for (af = 1; af < af_max(); af++) { ++ for (int af = 1; af < af_max(); af++) { + + if (set_contains(address_families, INT_TO_PTR(af))) + continue; +@@ -1378,7 +1375,6 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) { + * checks. */ + + SET_FOREACH(af, address_families, i) { +- + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EAFNOSUPPORT), diff --git a/SOURCES/0816-shared-syscall-list-filter-out-some-obviously-platfo.patch b/SOURCES/0816-shared-syscall-list-filter-out-some-obviously-platfo.patch new file mode 100644 index 0000000..e061a38 --- /dev/null +++ b/SOURCES/0816-shared-syscall-list-filter-out-some-obviously-platfo.patch @@ -0,0 +1,32 @@ +From 2e33a4ffdd54de1f88c3cd37ca5ace94a637b1dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 19 Aug 2020 17:46:30 +0200 +Subject: [PATCH] shared/syscall-list: filter out some obviously + platform-specific syscalls + +(cherry picked from commit 752fedbea7c02c82287c7ff2a4139f528b3f7ba8) + +Related: #2040247 +--- + src/shared/generate-syscall-list.py | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/shared/generate-syscall-list.py b/src/shared/generate-syscall-list.py +index 0b90d2d276..030c3feec4 100755 +--- a/src/shared/generate-syscall-list.py ++++ b/src/shared/generate-syscall-list.py +@@ -1,5 +1,14 @@ + #!/usr/bin/env python3 + import sys ++import os ++ ++s390 = 's390' in os.uname().machine ++arm = 'arm' in os.uname().machine + + for line in open(sys.argv[1]): ++ if line.startswith('s390_') and not s390: ++ continue ++ if line.startswith('arm_') and not arm: ++ continue ++ + print('"{}\\0"'.format(line.strip())) diff --git a/SOURCES/0817-seccomp-tighten-checking-of-seccomp-filter-creation.patch b/SOURCES/0817-seccomp-tighten-checking-of-seccomp-filter-creation.patch new file mode 100644 index 0000000..8e297c6 --- /dev/null +++ b/SOURCES/0817-seccomp-tighten-checking-of-seccomp-filter-creation.patch @@ -0,0 +1,123 @@ +From 42ed3377b5817f2c1f84e1bdca301ea51ecc3299 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 20 Sep 2018 14:19:41 +0200 +Subject: [PATCH] seccomp: tighten checking of seccomp filter creation + +In seccomp code, the code is changed to propagate errors which are about +anything other than unknown/unimplemented syscalls. I *think* such errors +should not happen in normal usage, but so far we would summarilly ignore all +errors, so that part is uncertain. If it turns out that other errors occur and +should be ignored, this should be added later. + +In nspawn, we would count the number of added filters, but didn't use this for +anything. Drop that part. + +The comments suggested that seccomp_add_syscall_filter_item() returned negative +if the syscall is unknown, but this wasn't true: it returns 0. + +The error at this point can only be if the syscall was known but couldn't be +added. If the error comes from our internal whitelist in nspawn, treat this as +error, because it means that our internal table is wrong. If the error comes +from user arguments, warn and ignore. (If some syscall is not known at current +architecture, it is still silently ignored.) + +(cherry picked from commit 7e86bd73a47f2b8dd3d9a743e69fb0117f450ad8) + +Related: #2040247 +--- + src/nspawn/nspawn-seccomp.c | 14 +++++--------- + src/shared/seccomp-util.c | 26 ++++++++++++++++---------- + 2 files changed, 21 insertions(+), 19 deletions(-) + +diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c +index fba22644da..17abfcec26 100644 +--- a/src/nspawn/nspawn-seccomp.c ++++ b/src/nspawn/nspawn-seccomp.c +@@ -140,7 +140,7 @@ static int seccomp_add_default_syscall_filter( + */ + }; + +- int r, c = 0; ++ int r; + size_t i; + char **p; + +@@ -150,21 +150,17 @@ static int seccomp_add_default_syscall_filter( + + r = seccomp_add_syscall_filter_item(ctx, whitelist[i].name, SCMP_ACT_ALLOW, syscall_blacklist, false); + if (r < 0) +- /* If the system call is not known on this architecture, then that's fine, let's ignore it */ +- log_debug_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", whitelist[i].name, seccomp_arch_to_string(arch)); +- else +- c++; ++ return log_error_errno(r, "Failed to add syscall filter item %s: %m", whitelist[i].name); + } + + STRV_FOREACH(p, syscall_whitelist) { + r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist, false); + if (r < 0) +- log_debug_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", *p, seccomp_arch_to_string(arch)); +- else +- c++; ++ log_warning_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", ++ *p, seccomp_arch_to_string(arch)); + } + +- return c; ++ return 0; + } + + int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **syscall_blacklist) { +diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c +index 4d2ba31d47..710a734715 100644 +--- a/src/shared/seccomp-util.c ++++ b/src/shared/seccomp-util.c +@@ -907,9 +907,13 @@ int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, + r = seccomp_rule_add_exact(seccomp, action, id, 0); + if (r < 0) { + /* If the system call is not known on this architecture, then that's fine, let's ignore it */ +- if (log_missing) +- log_debug_errno(r, "Failed to add rule for system call %s() / %d, ignoring: %m", +- name, id); ++ bool ignore = r == -EDOM; ++ ++ if (!ignore || log_missing) ++ log_debug_errno(r, "Failed to add rule for system call %s() / %d%s: %m", ++ name, id, ignore ? ", ignoring" : ""); ++ if (!ignore) ++ return r; + } + + return 0; +@@ -957,10 +961,8 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter + return r; + + r = seccomp_add_syscall_filter_set(seccomp, set, action, NULL, log_missing); +- if (r < 0) { +- log_debug_errno(r, "Failed to add filter set, ignoring: %m"); +- continue; +- } ++ if (r < 0) ++ return log_debug_errno(r, "Failed to add filter set: %m"); + + r = seccomp_load(seccomp); + if (IN_SET(r, -EPERM, -EACCES)) +@@ -1005,11 +1007,15 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u + if (r < 0) { + /* If the system call is not known on this architecture, then that's fine, let's ignore it */ + _cleanup_free_ char *n = NULL; ++ bool ignore; + + n = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, id); +- if (log_missing) +- log_debug_errno(r, "Failed to add rule for system call %s() / %d, ignoring: %m", +- strna(n), id); ++ ignore = r == -EDOM; ++ if (!ignore || log_missing) ++ log_debug_errno(r, "Failed to add rule for system call %s() / %d%s: %m", ++ strna(n), id, ignore ? ", ignoring" : ""); ++ if (!ignore) ++ return r; + } + } + diff --git a/SOURCES/0818-shared-seccomp-util-added-functionality-to-make-list.patch b/SOURCES/0818-shared-seccomp-util-added-functionality-to-make-list.patch new file mode 100644 index 0000000..6dcde52 --- /dev/null +++ b/SOURCES/0818-shared-seccomp-util-added-functionality-to-make-list.patch @@ -0,0 +1,156 @@ +From eaad892c513806801e3d2055788fa202372b3f15 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 21 Aug 2020 17:21:04 +0200 +Subject: [PATCH] shared/seccomp-util: added functionality to make list of + filtred syscalls + +While at it, start removing the "seccomp_" prefix from our +own functions. It is used by libseccomp. + +(cherry picked from commit 000c05207d68658b76af9e1caf9aa3a4e3fa697b) + +Related: #2040247 +--- + src/nspawn/nspawn-seccomp.c | 9 +++++++-- + src/shared/seccomp-util.c | 39 ++++++++++++++++++++++++++++++------- + src/shared/seccomp-util.h | 8 +++++++- + 3 files changed, 46 insertions(+), 10 deletions(-) + +diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c +index 17abfcec26..2b4a65e875 100644 +--- a/src/nspawn/nspawn-seccomp.c ++++ b/src/nspawn/nspawn-seccomp.c +@@ -148,13 +148,18 @@ static int seccomp_add_default_syscall_filter( + if (whitelist[i].capability != 0 && (cap_list_retain & (1ULL << whitelist[i].capability)) == 0) + continue; + +- r = seccomp_add_syscall_filter_item(ctx, whitelist[i].name, SCMP_ACT_ALLOW, syscall_blacklist, false); ++ r = seccomp_add_syscall_filter_item(ctx, ++ whitelist[i].name, ++ SCMP_ACT_ALLOW, ++ syscall_blacklist, ++ false, ++ NULL); + if (r < 0) + return log_error_errno(r, "Failed to add syscall filter item %s: %m", whitelist[i].name); + } + + STRV_FOREACH(p, syscall_whitelist) { +- r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist, false); ++ r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist, false, NULL); + if (r < 0) + log_warning_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", + *p, seccomp_arch_to_string(arch)); +diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c +index 710a734715..56075d92e0 100644 +--- a/src/shared/seccomp-util.c ++++ b/src/shared/seccomp-util.c +@@ -874,15 +874,31 @@ const SyscallFilterSet *syscall_filter_set_find(const char *name) { + return NULL; + } + +-static int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action, char **exclude, bool log_missing); ++static int add_syscall_filter_set( ++ scmp_filter_ctx seccomp, ++ const SyscallFilterSet *set, ++ uint32_t action, ++ char **exclude, ++ bool log_missing, ++ char ***added); ++ ++int seccomp_add_syscall_filter_item( ++ scmp_filter_ctx *seccomp, ++ const char *name, ++ uint32_t action, ++ char **exclude, ++ bool log_missing, ++ char ***added) { + +-int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, uint32_t action, char **exclude, bool log_missing) { + assert(seccomp); + assert(name); + + if (strv_contains(exclude, name)) + return 0; + ++ /* Any syscalls that are handled are added to the *added strv. The pointer ++ * must be either NULL or point to a valid pre-initialized possibly-empty strv. */ ++ + if (name[0] == '@') { + const SyscallFilterSet *other; + +@@ -892,7 +908,7 @@ int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, + return -EINVAL; + } + +- return seccomp_add_syscall_filter_set(seccomp, other, action, exclude, log_missing); ++ return add_syscall_filter_set(seccomp, other, action, exclude, log_missing, added); + + } else { + int id, r; +@@ -916,25 +932,34 @@ int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, + return r; + } + ++ if (added) { ++ r = strv_extend(added, name); ++ if (r < 0) ++ return r; ++ } ++ + return 0; + } + } + +-static int seccomp_add_syscall_filter_set( ++static int add_syscall_filter_set( + scmp_filter_ctx seccomp, + const SyscallFilterSet *set, + uint32_t action, + char **exclude, +- bool log_missing) { ++ bool log_missing, ++ char ***added) { + + const char *sys; + int r; + ++ /* Any syscalls that are handled are added to the *added strv. It needs to be initialized. */ ++ + assert(seccomp); + assert(set); + + NULSTR_FOREACH(sys, set->value) { +- r = seccomp_add_syscall_filter_item(seccomp, sys, action, exclude, log_missing); ++ r = seccomp_add_syscall_filter_item(seccomp, sys, action, exclude, log_missing, added); + if (r < 0) + return r; + } +@@ -960,7 +985,7 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter + if (r < 0) + return r; + +- r = seccomp_add_syscall_filter_set(seccomp, set, action, NULL, log_missing); ++ r = add_syscall_filter_set(seccomp, set, action, NULL, log_missing, NULL); + if (r < 0) + return log_debug_errno(r, "Failed to add filter set: %m"); + +diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h +index 541ba1e067..291b2bffe0 100644 +--- a/src/shared/seccomp-util.h ++++ b/src/shared/seccomp-util.h +@@ -59,7 +59,13 @@ const SyscallFilterSet *syscall_filter_set_find(const char *name); + + int seccomp_filter_set_add(Hashmap *s, bool b, const SyscallFilterSet *set); + +-int seccomp_add_syscall_filter_item(scmp_filter_ctx *ctx, const char *name, uint32_t action, char **exclude, bool log_missing); ++int seccomp_add_syscall_filter_item( ++ scmp_filter_ctx *ctx, ++ const char *name, ++ uint32_t action, ++ char **exclude, ++ bool log_missing, ++ char ***added); + + int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action, bool log_missing); + int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action, bool log_missing); diff --git a/SOURCES/0819-nspawn-return-ENOSYS-by-default-EPERM-for-known-call.patch b/SOURCES/0819-nspawn-return-ENOSYS-by-default-EPERM-for-known-call.patch new file mode 100644 index 0000000..7b29f41 --- /dev/null +++ b/SOURCES/0819-nspawn-return-ENOSYS-by-default-EPERM-for-known-call.patch @@ -0,0 +1,77 @@ +From 65d64ba146c30a5f205b650381f331fd8db2eb22 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 21 Aug 2020 17:23:48 +0200 +Subject: [PATCH] nspawn: return ENOSYS by default, EPERM for "known" calls + +(cherry picked from commit 3573e032f26724949e86626eace058d006b8bf70) + +Resolves: #2040247 +--- + src/nspawn/nspawn-seccomp.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c +index 2b4a65e875..563cda140e 100644 +--- a/src/nspawn/nspawn-seccomp.c ++++ b/src/nspawn/nspawn-seccomp.c +@@ -20,7 +20,7 @@ + + #if HAVE_SECCOMP + +-static int seccomp_add_default_syscall_filter( ++static int add_syscall_filters( + scmp_filter_ctx ctx, + uint32_t arch, + uint64_t cap_list_retain, +@@ -140,6 +140,7 @@ static int seccomp_add_default_syscall_filter( + */ + }; + ++ _cleanup_strv_free_ char **added = NULL; + int r; + size_t i; + char **p; +@@ -153,18 +154,25 @@ static int seccomp_add_default_syscall_filter( + SCMP_ACT_ALLOW, + syscall_blacklist, + false, +- NULL); ++ &added); + if (r < 0) + return log_error_errno(r, "Failed to add syscall filter item %s: %m", whitelist[i].name); + } + + STRV_FOREACH(p, syscall_whitelist) { +- r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist, false, NULL); ++ r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist, true, &added); + if (r < 0) + log_warning_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", + *p, seccomp_arch_to_string(arch)); + } + ++ /* The default action is ENOSYS. Respond with EPERM to all other "known" but not allow-listed ++ * syscalls. */ ++ r = seccomp_add_syscall_filter_item(ctx, "@known", SCMP_ACT_ERRNO(EPERM), added, true, NULL); ++ if (r < 0) ++ log_warning_errno(r, "Failed to add rule for @known set on %s, ignoring: %m", ++ seccomp_arch_to_string(arch)); ++ + return 0; + } + +@@ -182,11 +190,13 @@ int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **sys + + log_debug("Applying whitelist on architecture: %s", seccomp_arch_to_string(arch)); + +- r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ERRNO(EPERM)); ++ /* We install ENOSYS as the default action, but it will only apply to syscalls which are not ++ * in the @known set, see above. */ ++ r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ERRNO(ENOSYS)); + if (r < 0) + return log_error_errno(r, "Failed to allocate seccomp object: %m"); + +- r = seccomp_add_default_syscall_filter(seccomp, arch, cap_list_retain, syscall_whitelist, syscall_blacklist); ++ r = add_syscall_filters(seccomp, arch, cap_list_retain, syscall_whitelist, syscall_blacklist); + if (r < 0) + return r; + diff --git a/SOURCES/0820-test-procfs-util-skip-test-on-certain-errors.patch b/SOURCES/0820-test-procfs-util-skip-test-on-certain-errors.patch new file mode 100644 index 0000000..55ece1d --- /dev/null +++ b/SOURCES/0820-test-procfs-util-skip-test-on-certain-errors.patch @@ -0,0 +1,75 @@ +From 33305c6801c10b741b11a3f329dc339d2e8c5514 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Thu, 18 Aug 2022 16:35:23 +0200 +Subject: [PATCH] test-procfs-util: skip test on certain errors + +Inspired by upstream bf47f71c1c + +RHEL-only +Related: #2087152 +--- + src/shared/tests.c | 12 ++++++++++++ + src/shared/tests.h | 2 ++ + src/test/test-procfs-util.c | 6 ++++-- + 3 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/src/shared/tests.c b/src/shared/tests.c +index 1da80d653f..b1c71b992f 100644 +--- a/src/shared/tests.c ++++ b/src/shared/tests.c +@@ -78,6 +78,18 @@ void test_setup_logging(int level) { + log_open(); + } + ++int log_tests_skipped(const char *message) { ++ log_notice("%s: %s, skipping tests.", ++ program_invocation_short_name, message); ++ return EXIT_TEST_SKIP; ++} ++ ++int log_tests_skipped_errno(int r, const char *message) { ++ log_notice_errno(r, "%s: %s, skipping tests: %m", ++ program_invocation_short_name, message); ++ return EXIT_TEST_SKIP; ++} ++ + const char *ci_environment(void) { + /* We return a string because we might want to provide multiple bits of information later on: not + * just the general CI environment type, but also whether we're sanitizing or not, etc. The caller is +diff --git a/src/shared/tests.h b/src/shared/tests.h +index 4f8f349097..d50711338c 100644 +--- a/src/shared/tests.h ++++ b/src/shared/tests.h +@@ -5,6 +5,8 @@ char* setup_fake_runtime_dir(void); + bool test_is_running_from_builddir(char **exedir); + const char* get_testdata_dir(void); + void test_setup_logging(int level); ++int log_tests_skipped(const char *message); ++int log_tests_skipped_errno(int r, const char *message); + + /* Provide a convenient way to check if we're running in CI. */ + const char *ci_environment(void); +diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c +index d656c4df4f..aba5692e54 100644 +--- a/src/test/test-procfs-util.c ++++ b/src/test/test-procfs-util.c +@@ -7,6 +7,7 @@ + #include "procfs-util.h" + #include "process-util.h" + #include "util.h" ++#include "tests.h" + + int main(int argc, char *argv[]) { + char buf[CONST_MAX(FORMAT_TIMESPAN_MAX, FORMAT_BYTES_MAX)]; +@@ -52,8 +53,9 @@ int main(int argc, char *argv[]) { + log_info("Reducing limit by one to %"PRIu64"…", v-1); + + r = procfs_tasks_set_limit(v-1); +- log_info_errno(r, "procfs_tasks_set_limit: %m"); +- assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || r == -EROFS); ++ if (IN_SET(r, -ENOENT, -EROFS) || ERRNO_IS_PRIVILEGE(r)) ++ return log_tests_skipped_errno(r, "can't set tasks limit"); ++ assert_se(r >= 0); + + assert_se(procfs_get_threads_max(&w) >= 0); + assert_se(r >= 0 ? w == v - 1 : w == v); diff --git a/SOURCES/0821-Try-stopping-MD-RAID-devices-in-shutdown-too.patch b/SOURCES/0821-Try-stopping-MD-RAID-devices-in-shutdown-too.patch new file mode 100644 index 0000000..bea238f --- /dev/null +++ b/SOURCES/0821-Try-stopping-MD-RAID-devices-in-shutdown-too.patch @@ -0,0 +1,292 @@ +From c7532112a37ffdd3cc9851ae04fdcb543b99ed1c Mon Sep 17 00:00:00 2001 +From: Hubert Kario +Date: Sun, 20 Sep 2020 18:59:58 +0200 +Subject: [PATCH] Try stopping MD RAID devices in shutdown too + +Currently the systemd-shutdown command attempts to stop swaps, DM +(crypt, LVM2) and loop devices, but it doesn't attempt to stop MD +RAID devices, which means that if the RAID is set up on crypt, +loop, etc. device, it won't be able to stop those underlying devices. + +This code extends the shutdown application to also attempt stopping +the MD RAID devices. + +Signed-off-by: Hubert Kario +(cherry picked from commit 0b220a5f2a31844eaa1f5426bab02d41d54f471c) + +Resolves: #1817706 +--- + src/core/shutdown.c | 37 +++++++++---- + src/core/umount.c | 125 ++++++++++++++++++++++++++++++++++++++++++++ + src/core/umount.h | 2 + + 3 files changed, 154 insertions(+), 10 deletions(-) + +diff --git a/src/core/shutdown.c b/src/core/shutdown.c +index 038345b752..b8a983986a 100644 +--- a/src/core/shutdown.c ++++ b/src/core/shutdown.c +@@ -251,7 +251,7 @@ static void sync_with_progress(void) { + } + + int main(int argc, char *argv[]) { +- bool need_umount, need_swapoff, need_loop_detach, need_dm_detach; ++ bool need_umount, need_swapoff, need_loop_detach, need_dm_detach, need_md_detach; + bool in_container, use_watchdog = false, can_initrd; + _cleanup_free_ char *cgroup = NULL; + char *arguments[3]; +@@ -331,6 +331,7 @@ int main(int argc, char *argv[]) { + need_swapoff = !in_container; + need_loop_detach = !in_container; + need_dm_detach = !in_container; ++ need_md_detach = !in_container; + can_initrd = !in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0; + + /* Unmount all mountpoints, swaps, and loopback devices */ +@@ -383,6 +384,18 @@ int main(int argc, char *argv[]) { + log_error_errno(r, "Failed to detach loop devices: %m"); + } + ++ if (need_md_detach) { ++ log_info("Stopping MD devices."); ++ r = md_detach_all(&changed, umount_log_level); ++ if (r == 0) { ++ need_md_detach = false; ++ log_info("All MD devices stopped."); ++ } else if (r > 0) ++ log_info("Not all MD devices stopped, %d left.", r); ++ else ++ log_error_errno(r, "Failed to stop MD devices: %m"); ++ } ++ + if (need_dm_detach) { + log_info("Detaching DM devices."); + r = dm_detach_all(&changed, umount_log_level); +@@ -395,8 +408,9 @@ int main(int argc, char *argv[]) { + log_error_errno(r, "Failed to detach DM devices: %m"); + } + +- if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) { +- log_info("All filesystems, swaps, loop devices and DM devices detached."); ++ if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach ++ && !need_md_detach) { ++ log_info("All filesystems, swaps, loop devices, MD devices and DM devices detached."); + /* Yay, done */ + break; + } +@@ -414,19 +428,21 @@ int main(int argc, char *argv[]) { + /* If in this iteration we didn't manage to + * unmount/deactivate anything, we simply give up */ + if (!changed) { +- log_info("Cannot finalize remaining%s%s%s%s continuing.", ++ log_info("Cannot finalize remaining%s%s%s%s%s continuing.", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", +- need_dm_detach ? " DM devices," : ""); ++ need_dm_detach ? " DM devices," : "", ++ need_md_detach ? " MD devices," : ""); + break; + } + +- log_debug("Couldn't finalize remaining %s%s%s%s trying again.", ++ log_debug("Couldn't finalize remaining %s%s%s%s%s trying again.", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", +- need_dm_detach ? " DM devices," : ""); ++ need_dm_detach ? " DM devices," : "", ++ need_md_detach ? " MD devices," : ""); + } + + /* We're done with the watchdog. */ +@@ -455,12 +471,13 @@ int main(int argc, char *argv[]) { + + } + +- if (need_umount || need_swapoff || need_loop_detach || need_dm_detach) +- log_error("Failed to finalize %s%s%s%s ignoring", ++ if (need_umount || need_swapoff || need_loop_detach || need_dm_detach || need_md_detach) ++ log_error("Failed to finalize%s%s%s%s%s ignoring.", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", +- need_dm_detach ? " DM devices," : ""); ++ need_dm_detach ? " DM devices," : "", ++ need_md_detach ? " MD devices," : ""); + + /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be + * sync'ed explicitly in advance. So let's do this here, but not needlessly slow down containers. Note that we +diff --git a/src/core/umount.c b/src/core/umount.c +index 3f02bf141a..ed90c6b1fc 100644 +--- a/src/core/umount.c ++++ b/src/core/umount.c +@@ -5,6 +5,8 @@ + + #include + #include ++#include ++#include + #include + #include + #include +@@ -332,6 +334,66 @@ static int dm_list_get(MountPoint **head) { + return 0; + } + ++static int md_list_get(MountPoint **head) { ++ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL; ++ struct udev_list_entry *item = NULL, *first = NULL; ++ _cleanup_(udev_unrefp) struct udev *udev = NULL; ++ int r; ++ ++ assert(head); ++ ++ udev = udev_new(); ++ if (!udev) ++ return -ENOMEM; ++ ++ e = udev_enumerate_new(udev); ++ if (!e) ++ return -ENOMEM; ++ ++ r = udev_enumerate_add_match_subsystem(e, "block"); ++ if (r < 0) ++ return r; ++ ++ r = udev_enumerate_add_match_sysname(e, "md*"); ++ if (r < 0) ++ return r; ++ ++ first = udev_enumerate_get_list_entry(e); ++ udev_list_entry_foreach(item, first) { ++ _cleanup_(udev_device_unrefp) struct udev_device *d; ++ _cleanup_free_ char *p = NULL; ++ const char *dn; ++ MountPoint *m; ++ dev_t devnum; ++ ++ d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); ++ if (!d) ++ return -ENOMEM; ++ ++ devnum = udev_device_get_devnum(d); ++ dn = udev_device_get_devnode(d); ++ if (major(devnum) == 0 || !dn) ++ continue; ++ ++ p = strdup(dn); ++ if (!p) ++ return -ENOMEM; ++ ++ m = new(MountPoint, 1); ++ if (!m) ++ return -ENOMEM; ++ ++ *m = (MountPoint) { ++ .path = TAKE_PTR(p), ++ .devnum = devnum, ++ }; ++ ++ LIST_PREPEND(mount_point, *head, m); ++ } ++ ++ return 0; ++} ++ + static int delete_loopback(const char *device) { + _cleanup_close_ int fd = -1; + int r; +@@ -379,6 +441,23 @@ static int delete_dm(dev_t devnum) { + return 0; + } + ++static int delete_md(MountPoint *m) { ++ ++ _cleanup_close_ int fd = -1; ++ ++ assert(major(m->devnum) != 0); ++ assert(m->path != 0); ++ ++ fd = open(m->path, O_RDONLY|O_CLOEXEC|O_EXCL); ++ if (fd < 0) ++ return -errno; ++ ++ if (ioctl(fd, STOP_ARRAY, NULL) < 0) ++ return -errno; ++ ++ return 0; ++} ++ + static bool nonunmountable_path(const char *path) { + return path_equal(path, "/") + #if ! HAVE_SPLIT_USR +@@ -618,6 +697,37 @@ static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_lo + return n_failed; + } + ++static int md_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) { ++ MountPoint *m, *n; ++ int n_failed = 0, r; ++ dev_t rootdev = 0; ++ ++ assert(head); ++ assert(changed); ++ ++ (void) get_block_device("/", &rootdev); ++ ++ LIST_FOREACH_SAFE(mount_point, m, n, *head) { ++ if (major(rootdev) != 0 && rootdev == m->devnum) { ++ n_failed ++; ++ continue; ++ } ++ ++ log_info("Stopping MD %s (%u:%u).", m->path, major(m->devnum), minor(m->devnum)); ++ r = delete_md(m); ++ if (r < 0) { ++ log_full_errno(umount_log_level, r, "Could not stop MD %s: %m", m->path); ++ n_failed++; ++ continue; ++ } ++ ++ *changed = true; ++ mount_point_free(head, m); ++ } ++ ++ return n_failed; ++} ++ + static int umount_all_once(bool *changed, int umount_log_level) { + int r; + _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head); +@@ -696,3 +806,18 @@ int dm_detach_all(bool *changed, int umount_log_level) { + + return dm_points_list_detach(&dm_list_head, changed, umount_log_level); + } ++ ++int md_detach_all(bool *changed, int umount_log_level) { ++ _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, md_list_head); ++ int r; ++ ++ assert(changed); ++ ++ LIST_HEAD_INIT(md_list_head); ++ ++ r = md_list_get(&md_list_head); ++ if (r < 0) ++ return r; ++ ++ return md_points_list_detach(&md_list_head, changed, umount_log_level); ++} +diff --git a/src/core/umount.h b/src/core/umount.h +index 6f2b24d195..b01062484f 100644 +--- a/src/core/umount.h ++++ b/src/core/umount.h +@@ -15,6 +15,8 @@ int loopback_detach_all(bool *changed, int umount_log_level); + + int dm_detach_all(bool *changed, int umount_log_level); + ++int md_detach_all(bool *changed, int umount_log_level); ++ + /* This is exported just for testing */ + typedef struct MountPoint { + char *path; diff --git a/SOURCES/0822-shutdown-get-only-active-md-arrays.patch b/SOURCES/0822-shutdown-get-only-active-md-arrays.patch new file mode 100644 index 0000000..9bd3ce2 --- /dev/null +++ b/SOURCES/0822-shutdown-get-only-active-md-arrays.patch @@ -0,0 +1,70 @@ +From ebb3e759bba99ea85b3be9608258d6a5bb7e907a Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 29 Mar 2022 12:49:54 +0200 +Subject: [PATCH] shutdown: get only active md arrays. + +Current md_list_get() implementation filters all block devices, started from +"md*". This is ambiguous because list could contain: +- partitions created upon md device (mdXpY) +- external metadata container- specific type of md array. + +For partitions there is no issue, because they aren't handle STOP_ARRAY +ioctl sent later. It generates misleading errors only. + +Second case is more problematic because containers are not locked in kernel. +They are stopped even if container member array is active. For that reason +reboot or shutdown flow could be blocked because metadata manager cannot be +restarted after switch root on shutdown. + +Add filters to remove partitions and containers from md_list. Partitions +can be excluded by DEVTYPE. Containers are determined by MD_LEVEL +property, we are excluding all with "container" value. + +Signed-off-by: Mariusz Tkaczyk +(cherry picked from commit 3a3b022d2cc112803ea7b9beea98bbcad110368a) + +Related: #1817706 +--- + src/core/umount.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/src/core/umount.c b/src/core/umount.c +index ed90c6b1fc..b513e91c4d 100644 +--- a/src/core/umount.c ++++ b/src/core/umount.c +@@ -358,11 +358,16 @@ static int md_list_get(MountPoint **head) { + if (r < 0) + return r; + ++ /* Filter out partitions. */ ++ r = udev_enumerate_add_match_property(e, "DEVTYPE", "disk"); ++ if (r < 0) ++ return r; ++ + first = udev_enumerate_get_list_entry(e); + udev_list_entry_foreach(item, first) { + _cleanup_(udev_device_unrefp) struct udev_device *d; + _cleanup_free_ char *p = NULL; +- const char *dn; ++ const char *dn, *md_level; + MountPoint *m; + dev_t devnum; + +@@ -375,6 +380,17 @@ static int md_list_get(MountPoint **head) { + if (major(devnum) == 0 || !dn) + continue; + ++ md_level = udev_device_get_property_value(d, "MD_LEVEL"); ++ if (!m) { ++ log_warning("Failed to get MD_LEVEL property for %s, ignoring", dn); ++ continue; ++ } ++ ++ /* MD "containers" are a special type of MD devices, used for external metadata. ++ * Since it doesn't provide RAID functionality in itself we don't need to stop it. */ ++ if (streq(md_level, "container")) ++ continue; ++ + p = strdup(dn); + if (!p) + return -ENOMEM; diff --git a/SOURCES/0823-scope-allow-unprivileged-delegation-on-scopes.patch b/SOURCES/0823-scope-allow-unprivileged-delegation-on-scopes.patch new file mode 100644 index 0000000..a62f3bc --- /dev/null +++ b/SOURCES/0823-scope-allow-unprivileged-delegation-on-scopes.patch @@ -0,0 +1,347 @@ +From 5b5571de21d1ddf9a00511a6b2f25d630a903f05 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 1 Jun 2022 10:15:06 +0200 +Subject: [PATCH] scope: allow unprivileged delegation on scopes + +Previously it was possible to set delegate property for scope, but you +were not able to allow unprivileged process to manage the scope's cgroup +hierarchy. This is useful when launching manager process that will run +unprivileged but is supposed to manage its own (scope) sub-hierarchy. + +Fixes #21683 + +(cherry picked from commit 03860190fefce8bbea3a6f0e77919b882ade517c) + +Resolves: #2068575 +--- + src/basic/unit-def.c | 1 + + src/basic/unit-def.h | 1 + + src/core/dbus-scope.c | 6 ++ + src/core/scope.c | 135 +++++++++++++++++++++++++---- + src/core/scope.h | 3 + + src/shared/bus-unit-util.c | 5 ++ + test/TEST-19-DELEGATE/testsuite.sh | 13 +++ + 7 files changed, 145 insertions(+), 19 deletions(-) + +diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c +index e79cc73dd3..16c4d38d41 100644 +--- a/src/basic/unit-def.c ++++ b/src/basic/unit-def.c +@@ -160,6 +160,7 @@ DEFINE_STRING_TABLE_LOOKUP(path_state, PathState); + + static const char* const scope_state_table[_SCOPE_STATE_MAX] = { + [SCOPE_DEAD] = "dead", ++ [SCOPE_START_CHOWN] = "start-chown", + [SCOPE_RUNNING] = "running", + [SCOPE_ABANDONED] = "abandoned", + [SCOPE_STOP_SIGTERM] = "stop-sigterm", +diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h +index 8eea379a6d..03d151ec19 100644 +--- a/src/basic/unit-def.h ++++ b/src/basic/unit-def.h +@@ -99,6 +99,7 @@ typedef enum PathState { + + typedef enum ScopeState { + SCOPE_DEAD, ++ SCOPE_START_CHOWN, + SCOPE_RUNNING, + SCOPE_ABANDONED, + SCOPE_STOP_SIGTERM, +diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c +index 0bbf64fff1..534302d188 100644 +--- a/src/core/dbus-scope.c ++++ b/src/core/dbus-scope.c +@@ -178,6 +178,12 @@ int bus_scope_set_property( + r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error); + if (r != 0) + return r; ++ ++ if (streq(name, "User")) ++ return bus_set_transient_user_relaxed(u, name, &s->user, message, flags, error); ++ ++ if (streq(name, "Group")) ++ return bus_set_transient_user_relaxed(u, name, &s->group, message, flags, error); + } + + return 0; +diff --git a/src/core/scope.c b/src/core/scope.c +index 5a595c65a6..9cc5f89099 100644 +--- a/src/core/scope.c ++++ b/src/core/scope.c +@@ -5,6 +5,8 @@ + + #include "alloc-util.h" + #include "dbus-scope.h" ++#include "dbus-unit.h" ++#include "exit-status.h" + #include "load-dropin.h" + #include "log.h" + #include "scope.h" +@@ -14,9 +16,11 @@ + #include "strv.h" + #include "unit-name.h" + #include "unit.h" ++#include "user-util.h" + + static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = { + [SCOPE_DEAD] = UNIT_INACTIVE, ++ [SCOPE_START_CHOWN] = UNIT_ACTIVATING, + [SCOPE_RUNNING] = UNIT_ACTIVE, + [SCOPE_ABANDONED] = UNIT_ACTIVE, + [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING, +@@ -34,6 +38,7 @@ static void scope_init(Unit *u) { + + s->timeout_stop_usec = u->manager->default_timeout_stop_usec; + u->ignore_on_isolate = true; ++ s->user = s->group = NULL; + } + + static void scope_done(Unit *u) { +@@ -45,6 +50,9 @@ static void scope_done(Unit *u) { + s->controller_track = sd_bus_track_unref(s->controller_track); + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); ++ ++ s->user = mfree(s->user); ++ s->group = mfree(s->group); + } + + static int scope_arm_timer(Scope *s, usec_t usec) { +@@ -84,7 +92,7 @@ static void scope_set_state(Scope *s, ScopeState state) { + old_state = s->state; + s->state = state; + +- if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) ++ if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL, SCOPE_START_CHOWN)) + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + + if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED)) { +@@ -301,26 +309,72 @@ fail: + scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); + } + +-static int scope_start(Unit *u) { +- Scope *s = SCOPE(u); ++static int scope_enter_start_chown(Scope *s) { ++ Unit *u = UNIT(s); ++ pid_t pid; + int r; + + assert(s); ++ assert(s->user); + +- if (unit_has_name(u, SPECIAL_INIT_SCOPE)) +- return -EPERM; ++ r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), u->manager->default_timeout_start_usec)); ++ if (r < 0) ++ return r; + +- if (s->state == SCOPE_FAILED) +- return -EPERM; ++ r = unit_fork_helper_process(u, "(sd-chown-cgroup)", &pid); ++ if (r < 0) ++ goto fail; + +- /* We can't fulfill this right now, please try again later */ +- if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) +- return -EAGAIN; ++ if (r == 0) { ++ uid_t uid = UID_INVALID; ++ gid_t gid = GID_INVALID; + +- assert(s->state == SCOPE_DEAD); ++ if (!isempty(s->user)) { ++ const char *user = s->user; + +- if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) +- return -ENOENT; ++ r = get_user_creds(&user, &uid, &gid, NULL, NULL); ++ if (r < 0) { ++ log_unit_error_errno(UNIT(s), r, "Failed to resolve user \"%s\": %m", user); ++ _exit(EXIT_USER); ++ } ++ } ++ ++ if (!isempty(s->group)) { ++ const char *group = s->group; ++ ++ r = get_group_creds(&group, &gid); ++ if (r < 0) { ++ log_unit_error_errno(UNIT(s), r, "Failed to resolve group \"%s\": %m", group); ++ _exit(EXIT_GROUP); ++ } ++ } ++ ++ r = cg_set_access(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, uid, gid); ++ if (r < 0) { ++ log_unit_error_errno(UNIT(s), r, "Failed to adjust control group access: %m"); ++ _exit(EXIT_CGROUP); ++ } ++ ++ _exit(EXIT_SUCCESS); ++ } ++ ++ r = unit_watch_pid(UNIT(s), pid, true); ++ if (r < 0) ++ goto fail; ++ ++ scope_set_state(s, SCOPE_START_CHOWN); ++ ++ return 1; ++fail: ++ s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source); ++ return r; ++} ++ ++static int scope_enter_running(Scope *s) { ++ Unit *u = UNIT(s); ++ int r; ++ ++ assert(s); + + (void) bus_scope_track_controller(s); + +@@ -328,11 +382,7 @@ static int scope_start(Unit *u) { + if (r < 0) + return r; + +- (void) unit_realize_cgroup(u); +- (void) unit_reset_cpu_accounting(u); +- (void) unit_reset_ip_accounting(u); +- +- unit_export_state_files(UNIT(s)); ++ unit_export_state_files(u); + + r = unit_attach_pids_to_cgroup(u, UNIT(s)->pids, NULL); + if (r < 0) { +@@ -350,6 +400,38 @@ static int scope_start(Unit *u) { + return 1; + } + ++static int scope_start(Unit *u) { ++ Scope *s = SCOPE(u); ++ ++ assert(s); ++ ++ if (unit_has_name(u, SPECIAL_INIT_SCOPE)) ++ return -EPERM; ++ ++ if (s->state == SCOPE_FAILED) ++ return -EPERM; ++ ++ /* We can't fulfill this right now, please try again later */ ++ if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) ++ return -EAGAIN; ++ ++ assert(s->state == SCOPE_DEAD); ++ ++ if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) ++ return -ENOENT; ++ ++ (void) unit_realize_cgroup(u); ++ (void) unit_reset_cpu_accounting(u); ++ (void) unit_reset_ip_accounting(u); ++ ++ /* We check only for User= option to keep behavior consistent with logic for service units, ++ * i.e. having 'Delegate=true Group=foo' w/o specifing User= has no effect. */ ++ if (s->user && unit_cgroup_delegate(u)) ++ return scope_enter_start_chown(s); ++ ++ return scope_enter_running(s); ++} ++ + static int scope_stop(Unit *u) { + Scope *s = SCOPE(u); + +@@ -462,7 +544,17 @@ static void scope_notify_cgroup_empty_event(Unit *u) { + } + + static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) { +- assert(u); ++ Scope *s = SCOPE(u); ++ ++ assert(s); ++ ++ if (s->state == SCOPE_START_CHOWN) { ++ if (!is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL)) ++ scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); ++ else ++ scope_enter_running(s); ++ return; ++ } + + /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to + * watch, under the assumption that we'll sooner or later get a SIGCHLD for them, as the original +@@ -495,6 +587,11 @@ static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *user + scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); + break; + ++ case SCOPE_START_CHOWN: ++ log_unit_warning(UNIT(s), "User lookup timed out. Entering failed state."); ++ scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); ++ break; ++ + default: + assert_not_reached("Timeout at wrong time."); + } +diff --git a/src/core/scope.h b/src/core/scope.h +index c38afb5e5d..7bed3eed9e 100644 +--- a/src/core/scope.h ++++ b/src/core/scope.h +@@ -32,6 +32,9 @@ struct Scope { + bool was_abandoned; + + sd_event_source *timer_event_source; ++ ++ char *user; ++ char *group; + }; + + extern const UnitVTable scope_vtable; +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 3910dfa812..c475bbafe0 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -1615,6 +1615,11 @@ static int bus_append_unit_property(sd_bus_message *m, const char *field, const + + return bus_append_parse_sec_rename(m, field, eq); + ++ /* Scope units don't have execution context but we still want to allow setting these two, ++ * so let's handle them separately. */ ++ if (STR_IN_SET(field, "User", "Group")) ++ return bus_append_string(m, field, eq); ++ + if (streq(field, "StartLimitBurst")) + + return bus_append_safe_atou(m, field, eq); +diff --git a/test/TEST-19-DELEGATE/testsuite.sh b/test/TEST-19-DELEGATE/testsuite.sh +index c738bea10e..c4c948cc11 100755 +--- a/test/TEST-19-DELEGATE/testsuite.sh ++++ b/test/TEST-19-DELEGATE/testsuite.sh +@@ -4,6 +4,16 @@ + set -ex + set -o pipefail + ++test_scope_unpriv_delegation() { ++ useradd test ||: ++ trap "userdel -r test" RETURN ++ ++ systemd-run --uid=test -p User=test -p Delegate=yes --slice workload.slice --unit workload0.scope --scope \ ++ test -w /sys/fs/cgroup/workload.slice/workload0.scope -a \ ++ -w /sys/fs/cgroup/workload.slice/workload0.scope/cgroup.procs -a \ ++ -w /sys/fs/cgroup/workload.slice/workload0.scope/cgroup.subtree_control ++} ++ + if grep -q cgroup2 /proc/filesystems ; then + systemd-run --wait --unit=test0.service -p "DynamicUser=1" -p "Delegate=" \ + test -w /sys/fs/cgroup/system.slice/test0.service/ -a \ +@@ -15,6 +25,9 @@ if grep -q cgroup2 /proc/filesystems ; then + + systemd-run --wait --unit=test2.service -p "DynamicUser=1" -p "Delegate=memory pids" \ + grep pids /sys/fs/cgroup/system.slice/test2.service/cgroup.controllers ++ ++ # Check that unprivileged delegation works for scopes ++ test_scope_unpriv_delegation + else + echo "Skipping TEST-19-DELEGATE, as the kernel doesn't actually support cgroupsv2" >&2 + fi diff --git a/SOURCES/0824-resolved-pin-stream-while-calling-callbacks-for-it.patch b/SOURCES/0824-resolved-pin-stream-while-calling-callbacks-for-it.patch new file mode 100644 index 0000000..9b60e51 --- /dev/null +++ b/SOURCES/0824-resolved-pin-stream-while-calling-callbacks-for-it.patch @@ -0,0 +1,39 @@ +From 3f3b00c8753fb591a4cd7b770ce069d455dcc4d6 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 4 Dec 2018 22:13:39 +0100 +Subject: [PATCH] resolved: pin stream while calling callbacks for it + +These callbacks might unref the stream, but we still have to access it, +let's hence ref it explicitly. + +Maybe fixes: #10725 + +(cherry picked from commit d973d94dec349fb676fdd844f6fe2ada3538f27c) + +Resolves: #2110549 +--- + src/resolve/resolved-dns-stream.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c +index 555e200a23..ca0313d1d7 100644 +--- a/src/resolve/resolved-dns-stream.c ++++ b/src/resolve/resolved-dns-stream.c +@@ -42,6 +42,8 @@ static int dns_stream_update_io(DnsStream *s) { + } + + static int dns_stream_complete(DnsStream *s, int error) { ++ _cleanup_(dns_stream_unrefp) _unused_ DnsStream *ref = dns_stream_ref(s); /* Protect stream while we process it */ ++ + assert(s); + + #if ENABLE_DNS_OVER_TLS +@@ -316,7 +318,7 @@ static int on_stream_timeout(sd_event_source *es, usec_t usec, void *userdata) { + } + + static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *userdata) { +- DnsStream *s = userdata; ++ _cleanup_(dns_stream_unrefp) DnsStream *s = dns_stream_ref(userdata); /* Protect stream while we process it */ + int r; + + assert(s); diff --git a/SOURCES/0825-ci-functions-Add-useradd-and-userdel.patch b/SOURCES/0825-ci-functions-Add-useradd-and-userdel.patch new file mode 100644 index 0000000..a483ce3 --- /dev/null +++ b/SOURCES/0825-ci-functions-Add-useradd-and-userdel.patch @@ -0,0 +1,28 @@ +From 10758905f159bbe87a10f185f7e9afefbbd21fd4 Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Fri, 26 Aug 2022 13:06:42 +0200 +Subject: [PATCH] ci(functions): Add `useradd` and `userdel` + +Inspired by upstream commit: +https://github.com/systemd/systemd/commit/9c94ab0f6ff22da4278a6e9a93ddc480607c55ac + +RHEL-only + +Related: #2110549 +--- + test/test-functions | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/test-functions b/test/test-functions +index ed8ab98173..19363be858 100644 +--- a/test/test-functions ++++ b/test/test-functions +@@ -23,7 +23,7 @@ fi + + PATH_TO_INIT=$ROOTLIBDIR/systemd + +-BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env mktemp mountpoint" ++BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env mktemp mountpoint useradd userdel" + DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find" + + STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))" diff --git a/SOURCES/systemd-user b/SOURCES/systemd-user index 2725df9..8607d4f 100644 --- a/SOURCES/systemd-user +++ b/SOURCES/systemd-user @@ -2,6 +2,7 @@ # # Used by systemd --user instances. +account sufficient pam_unix.so no_pass_expiry account include system-auth session required pam_selinux.so close diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index 4aee86b..079c082 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -13,7 +13,7 @@ Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 239 -Release: 58%{?dist} +Release: 67%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -793,7 +793,88 @@ Patch0740: 0740-sysctl-fix-segfault.patch Patch0741: 0741-ci-drop-CentOS-8-CI.patch Patch0742: 0742-test-adapt-to-the-new-capsh-format.patch Patch0743: 0743-test-ignore-IAB-capabilities-in-test-execute.patch - +Patch0744: 0744-core-disallow-using-.service-as-a-service-name.patch +Patch0745: 0745-shared-dropin-support-.service.d-top-level-drop-in-f.patch +Patch0746: 0746-core-change-top-level-drop-in-from-.service.d-to-ser.patch +Patch0747: 0747-shared-dropin-fix-assert-for-invalid-drop-in.patch +Patch0748: 0748-udev-fix-slot-based-network-names-on-s390.patch +Patch0749: 0749-udev-add-missing-initialization-to-fix-freeing-inval.patch +Patch0750: 0750-udev-it-is-not-necessary-that-the-path-is-readable.patch +Patch0751: 0751-udev-allow-onboard-index-up-to-65535.patch +Patch0752: 0752-Revert-basic-use-comma-as-separator-in-cpuset-cgroup.patch +Patch0753: 0753-acpi-fpdt-mark-structures-as-packed.patch +Patch0754: 0754-core-slice-make-slice_freezer_action-return-0-if-fre.patch +Patch0755: 0755-core-unit-fix-use-after-free.patch +Patch0756: 0756-sd-bus-fix-reference-counter-to-be-incremented.patch +Patch0757: 0757-sd-bus-do-not-read-unused-value.patch +Patch0758: 0758-sd-bus-do-not-return-negative-errno-when-unknown-nam.patch +Patch0759: 0759-sd-bus-switch-to-a-manual-overflow-check-in-sd_bus_t.patch +Patch0760: 0760-resolved-let-s-preferably-route-reverse-lookups-for-.patch +Patch0761: 0761-unit-don-t-emit-PropertiesChanged-signal-if-adding-a.patch +Patch0762: 0762-tests-make-inverted-tests-actually-count.patch +Patch0763: 0763-TEST-make-failure-tests-actually-fail-on-failure.patch +Patch0764: 0764-ci-Mergify-configuration-update.patch +Patch0765: 0765-core-propagate-triggered-unit-in-more-load-states.patch +Patch0766: 0766-core-propagate-unit-start-limit-hit-state-to-trigger.patch +Patch0767: 0767-core-Move-r-variable-declaration-to-start-of-unit_st.patch +Patch0768: 0768-core-Delay-start-rate-limit-check-when-starting-a-un.patch +Patch0769: 0769-core-Propagate-condition-failed-state-to-triggering-.patch +Patch0770: 0770-unit-check-for-mount-rate-limiting-before-checking-a.patch +Patch0771: 0771-mkosi-Add-gnutls-package.patch +Patch0772: 0772-unit-name-tighten-checks-for-building-valid-unit-nam.patch +Patch0773: 0773-core-shorten-long-unit-names-that-are-based-on-paths.patch +Patch0774: 0774-test-add-extended-test-for-triggering-mount-rate-lim.patch +Patch0775: 0775-tests-add-test-case-for-long-unit-names.patch +Patch0776: 0776-core-unset-HOME-that-the-kernel-gives-us.patch +Patch0777: 0777-journal-remote-check-return-value-from-MHD_add_respo.patch +Patch0778: 0778-journalctl-in-follow-mode-watch-stdout-for-POLLHUP-P.patch +Patch0779: 0779-sd-bus-make-BUS_DEFAULT_TIMEOUT-configurable.patch +Patch0780: 0780-fstab-generator-fix-debug-log.patch +Patch0781: 0781-logind-session-dbus-allow-to-set-display-name-via-db.patch +Patch0782: 0782-Allow-restart-for-oneshot-units.patch +Patch0783: 0783-test-correct-TEST-41-StartLimitBurst-test.patch +Patch0784: 0784-core-fix-assert-about-number-of-built-environment-va.patch +Patch0785: 0785-core-add-one-more-assert.patch +Patch0786: 0786-strv-introduce-strv_join_prefix.patch +Patch0787: 0787-test-add-tests-for-strv_join_prefix.patch +Patch0788: 0788-test-replace-swear-words-by-hoge.patch +Patch0789: 0789-core-add-new-environment-variable-RUNTIME_DIRECTORY-.patch +Patch0790: 0790-test-execute-add-tests-for-RUNTIME_DIRECTORY-or-frie.patch +Patch0791: 0791-man-document-RUNTIME_DIRECTORY-or-friends.patch +Patch0792: 0792-ci-bump-the-worker-Ubuntu-version-to-Jammy.patch +Patch0793: 0793-test-make-test-execute-pass-on-Linux-5.15.patch +Patch0794: 0794-ci-install-iputils.patch +Patch0795: 0795-ci-Mergify-Add-ci-waived-logic.patch +Patch0796: 0796-sd-event-don-t-invalidate-source-type-on-disconnect.patch +Patch0797: 0797-tests-make-sure-we-delay-running-mount-start-jobs-wh.patch +Patch0798: 0798-core-drop-references-to-StandardOutputFileToCreate.patch +Patch0799: 0799-dbus-execute-fix-indentation.patch +Patch0800: 0800-dbus-execute-generate-the-correct-transient-unit-set.patch +Patch0801: 0801-bus-unit-util-properly-accept-StandardOutput-append-.patch +Patch0802: 0802-core-be-more-careful-when-inheriting-stdout-fds-to-s.patch +Patch0803: 0803-test-add-a-test-for-StandardError-file.patch +Patch0804: 0804-tree-wide-allow-ASCII-fallback-for-in-logs.patch +Patch0805: 0805-tree-wide-allow-ASCII-fallback-for-in-logs.patch +Patch0806: 0806-core-allow-to-set-default-timeout-for-devices.patch +Patch0807: 0807-man-document-DefaultDeviceTimeoutSec.patch +Patch0808: 0808-Revert-core-Propagate-condition-failed-state-to-trig.patch +Patch0809: 0809-core-Check-unit-start-rate-limiting-earlier.patch +Patch0810: 0810-core-Add-trigger-limit-for-path-units.patch +Patch0811: 0811-meson-add-syscall-names-update-target.patch +Patch0812: 0812-syscall-names-add-process_madvise-which-is-planned-f.patch +Patch0813: 0813-shared-add-known-syscall-list.patch +Patch0814: 0814-generate-syscall-list-require-python3.patch +Patch0815: 0815-shared-seccomp-reduce-scope-of-indexing-variables.patch +Patch0816: 0816-shared-syscall-list-filter-out-some-obviously-platfo.patch +Patch0817: 0817-seccomp-tighten-checking-of-seccomp-filter-creation.patch +Patch0818: 0818-shared-seccomp-util-added-functionality-to-make-list.patch +Patch0819: 0819-nspawn-return-ENOSYS-by-default-EPERM-for-known-call.patch +Patch0820: 0820-test-procfs-util-skip-test-on-certain-errors.patch +Patch0821: 0821-Try-stopping-MD-RAID-devices-in-shutdown-too.patch +Patch0822: 0822-shutdown-get-only-active-md-arrays.patch +Patch0823: 0823-scope-allow-unprivileged-delegation-on-scopes.patch +Patch0824: 0824-resolved-pin-stream-while-calling-callbacks-for-it.patch +Patch0825: 0825-ci-functions-Add-useradd-and-userdel.patch %ifarch %{ix86} x86_64 aarch64 %global have_gnu_efi 1 @@ -1291,7 +1372,7 @@ fi function mod_nss() { if [ -f "$1" ] ; then - # sed-fu to add myhostanme to hosts line + # sed-fu to add myhostname to hosts line grep -E -q '^hosts:.* myhostname' "$1" || sed -i.bak -e ' /^hosts:/ !b @@ -1308,14 +1389,14 @@ function mod_nss() { } FILE="$(readlink /etc/nsswitch.conf || echo /etc/nsswitch.conf)" -mod_nss "$FILE" - -if [ "$FILE" = "/etc/authselect/user-nsswitch.conf" ] ; then - authselect apply-changes &> /dev/null +if [ "$FILE" = "/etc/authselect/nsswitch.conf" ] && authselect check &>/dev/null; then + mod_nss "/etc/authselect/user-nsswitch.conf" + authselect apply-changes &> /dev/null || : else - # also apply the same changes to nsswitch.conf to affect + mod_nss "$FILE" + # also apply the same changes to user-nsswitch.conf to affect # possible future authselect configuration - mod_nss "/etc/authselect/user-nsswitch.conf" + mod_nss "/etc/authselect/user-nsswitch.conf" fi # check if nobody or nfsnobody is defined @@ -1423,6 +1504,108 @@ fi %files tests -f .file-list-tests %changelog +* Fri Aug 26 2022 systemd maintenance team - 239-67 +- resolved: pin stream while calling callbacks for it (#2110549) +- ci(functions): Add `useradd` and `userdel` (#2110549) + +* Thu Aug 25 2022 systemd maintenance team - 239-66 +- Try stopping MD RAID devices in shutdown too (#1817706) +- shutdown: get only active md arrays. (#1817706) +- scope: allow unprivileged delegation on scopes (#2068575) + +* Fri Aug 19 2022 systemd maintenance team - 239-65 +- test-procfs-util: skip test on certain errors (#2087152) + +* Thu Aug 18 2022 systemd maintenance team - 239-64 +- ci: bump the worker Ubuntu version to Jammy (#2087152) +- test: make test-execute pass on Linux 5.15 (#2087152) +- ci: install iputils (#2087152) +- ci(Mergify): Add `ci-waived` logic (#2087152) +- sd-event: don't invalidate source type on disconnect (#2115396) +- tests: make sure we delay running mount start jobs when /p/s/mountinfo is rate limited (#2095744) +- core: drop references to 'StandardOutputFileToCreate' (#2093479) +- dbus-execute: fix indentation (#2093479) +- dbus-execute: generate the correct transient unit setting (#2093479) +- bus-unit-util: properly accept StandardOutput=append:… settings (#2093479) +- core: be more careful when inheriting stdout fds to stderr (#2093479) +- test: add a test for StandardError=file:… (#2093479) +- tree-wide: allow ASCII fallback for → in logs (#2093479) +- tree-wide: allow ASCII fallback for … in logs (#2093479) +- core: allow to set default timeout for devices (#1967245) +- man: document DefaultDeviceTimeoutSec= (#1967245) +- Revert "core: Propagate condition failed state to triggering units." (#2114005) +- core: Check unit start rate limiting earlier (#2114005) +- core: Add trigger limit for path units (#2114005) +- meson: add syscall-names-update target (#2040247) +- syscall-names: add process_madvise which is planned for 5.10 (#2040247) +- shared: add @known syscall list (#2040247) +- generate-syscall-list: require python3 (#2040247) +- shared/seccomp: reduce scope of indexing variables (#2040247) +- shared/syscall-list: filter out some obviously platform-specific syscalls (#2040247) +- seccomp: tighten checking of seccomp filter creation (#2040247) +- shared/seccomp-util: added functionality to make list of filtred syscalls (#2040247) +- nspawn: return ENOSYS by default, EPERM for "known" calls (#2040247) +- revert: resolved: pin stream while calling callbacks for it (#2110549) + +* Wed Aug 03 2022 systemd maintenance team - 239-63 +- resolved: pin stream while calling callbacks for it (#2110549) + +* Mon Jul 18 2022 systemd maintenance team - 239-62 +- spec: Remove dependency on timedatex (#2066946) + +* Thu Jul 14 2022 systemd maintenance team - 239-61 +- mkosi: Add gnutls package (#2101227) +- unit-name: tighten checks for building valid unit names (#1940973) +- core: shorten long unit names that are based on paths and append path hash at the end (#1940973) +- test: add extended test for triggering mount rate limit (#1940973) +- tests: add test case for long unit names (#1940973) +- core: unset HOME=/ that the kernel gives us (#2056527) +- journal-remote: check return value from MHD_add_response_header (#2051981) +- journalctl: in --follow mode watch stdout for POLLHUP/POLLERR and exit (#2003236) +- sd-bus: make BUS_DEFAULT_TIMEOUT configurable (#2039461) +- fstab-generator: fix debug log (#2101433) +- logind-session-dbus: allow to set display name via dbus (#1857969) +- Allow restart for oneshot units (#2042896) +- test: correct TEST-41 StartLimitBurst test (#2042896) +- core: fix assert() about number of built environment variables (#2049788) +- core: add one more assert() (#2049788) +- strv: introduce strv_join_prefix() (#2049788) +- test: add tests for strv_join_prefix() (#2049788) +- test: replace swear words by 'hoge' (#2049788) +- core: add new environment variable $RUNTIME_DIRECTORY= or friends (#2049788) +- test-execute: add tests for $RUNTIME_DIRECTORY= or friends (#2049788) +- man: document RUNTIME_DIRECTORY= or friends (#2049788) + +* Thu Jun 23 2022 systemd maintenance team - 239-60 +- unit: don't emit PropertiesChanged signal if adding a dependency to a unit is a no-op (#1948480) +- tests: make inverted tests actually count (#2087152) +- TEST-*: make failure tests actually fail on failure (#2087152) +- ci(Mergify): configuration update (#2087152) +- core: propagate triggered unit in more load states (#2065322) +- core: propagate unit start limit hit state to triggering path unit (#2065322) +- core: Move 'r' variable declaration to start of unit_start() (#2065322) +- core: Delay start rate limit check when starting a unit (#2065322) +- core: Propagate condition failed state to triggering units. (#2065322) +- unit: check for mount rate limiting before checking active state (#2095744) + +* Wed May 18 2022 systemd maintenance team - 239-59 +- core: disallow using '-.service' as a service name (#2051520) +- shared/dropin: support -.service.d/ top level drop-in for service units (#2051520) +- core: change top-level drop-in from -.service.d to service.d (#2051520) +- shared/dropin: fix assert for invalid drop-in (#2051520) +- udev: fix slot based network names on s390 (#1939914) +- udev: it is not necessary that the path is readable (#1939914) +- udev: allow onboard index up to 65535 (#1939914) +- Revert "basic: use comma as separator in cpuset cgroup cpu ranges" (#1858220) +- acpi-fpdt: mark structures as packed (#2047373) +- core/slice: make slice_freezer_action() return 0 if freezing state is unchanged (#2047373) +- core/unit: fix use-after-free (#2047373) +- sd-bus: fix reference counter to be incremented (#2047373) +- sd-bus: do not read unused value (#2047373) +- sd-bus: do not return negative errno when unknown name is specified (#2047373) +- sd-bus: switch to a manual overflow check in sd_bus_track_add_name() (#2047373) +- spec: Add dependency on timedatex (#2066946) + * Tue Feb 08 2022 systemd maintenance team - 239-58 - ci: drop CentOS 8 CI (#2017033) - test: adapt to the new capsh format (#2017033)