import systemd-239-58.el8_6.8

This commit is contained in:
CentOS Sources 2022-10-25 03:35:06 -04:00 committed by Stepan Oksanichenko
parent 3494a638bc
commit c7097e3e7c
10 changed files with 1252 additions and 8 deletions

View File

@ -0,0 +1,181 @@
From d4caf8718db1d2dddf7f87cbc192cff401ebcf59 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
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: #2094712
---
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;
}

View File

@ -0,0 +1,275 @@
From b2cfcb1f3801ae007698fce9139b39cefdfd66e1 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
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: #2094712
---
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 <stdlib.h>
#include <string.h>
+#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();

View File

@ -0,0 +1,162 @@
From 294efa52d47be083704da51b148c685d347be4ac Mon Sep 17 00:00:00 2001
From: Anita Zhang <the.anitazha@gmail.com>
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: #2094712
---
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 <<EOF
+[Unit]
+Description=Testsuite service
+
+[Service]
+ExecStart=/bin/bash -x /testsuite.sh
+Type=oneshot
+StandardOutput=tty
+StandardError=tty
+NotifyAccess=all
+EOF
+ cp testsuite.sh $initdir/
+
+ setup_testsuite
+ ) || return 1
+ setup_nspawn_root
+
+ ddebug "umount $TESTDIR/root"
+ umount $TESTDIR/root
+}
+
+do_test "$@"
diff --git a/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh b/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh
new file mode 100755
index 0000000000..8158754667
--- /dev/null
+++ b/test/TEST-60-MOUNT-RATELIMIT/testsuite.sh
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+set -eux
+set -o pipefail
+
+systemd-analyze log-level debug
+systemd-analyze log-target journal
+
+NUM_DIRS=20
+
+# mount/unmount enough times to trigger the /proc/self/mountinfo parsing rate limiting
+
+for ((i = 0; i < NUM_DIRS; i++)); do
+ mkdir "/tmp/meow${i}"
+done
+
+for ((i = 0; i < NUM_DIRS; i++)); do
+ mount -t tmpfs tmpfs "/tmp/meow${i}"
+done
+
+systemctl daemon-reload
+systemctl list-units -t mount tmp-meow* | grep -q tmp-meow
+
+for ((i = 0; i < NUM_DIRS; i++)); do
+ umount "/tmp/meow${i}"
+done
+
+# figure out if we have entered the rate limit state
+
+exited_rl=0
+timeout="$(date -ud "2 minutes" +%s)"
+while [[ $(date -u +%s) -le ${timeout} ]]; do
+ if journalctl -u init.scope | grep -q "(mount-monitor-dispatch) entered rate limit"; then
+ entered_rl=1
+ break
+ fi
+ sleep 5
+done
+
+# if the infra is slow we might not enter the rate limit state; in that case skip the exit check
+
+if [ "${entered_rl}" = "1" ]; then
+ exited_rl=0
+ timeout="$(date -ud "2 minutes" +%s)"
+ while [[ $(date -u +%s) -le ${timeout} ]]; do
+ if journalctl -u init.scope | grep -q "(mount-monitor-dispatch) left rate limit"; then
+ exited_rl=1
+ break
+ fi
+ sleep 5
+ done
+
+ if [ "${exited_rl}" = "0" ]; then
+ exit 24
+ fi
+fi
+
+# give some time for units to settle so we don't race between exiting the rate limit state and cleaning up the units
+
+sleep 60
+systemctl daemon-reload
+sleep 60
+
+# verify that the mount units are always cleaned up at the end
+
+if systemctl list-units -t mount tmp-meow* | grep -q tmp-meow; then
+ exit 42
+fi
+
+systemd-analyze log-level info
+
+echo OK >/testok
+
+exit 0

View File

@ -0,0 +1,42 @@
From 7363f240c0bb9032c0c615934d5fe4d1eaa56077 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
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: #2094712
---
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

View File

@ -0,0 +1,255 @@
From eef171ea21cf4b77f62269aabfd8bf0fdd92b7bf Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
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: #2123801
---
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 6f9a0f7575..74c1cc70cb 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2272,15 +2272,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;
@@ -3296,16 +3287,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, ...) \

View File

@ -0,0 +1,137 @@
From 6ec2c387cd4fe081e6a5561b5c7e66ec0555c353 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
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: #2123801
---
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'

View File

@ -0,0 +1,127 @@
From d61bd956e599dd747490d36ff793b63fb6a9fedc Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
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: #2123801
---
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'

View File

@ -1,4 +1,4 @@
From a4f08c798cabd5c43f2578a9e2b048fa1ad4a52c Mon Sep 17 00:00:00 2001
From b92fae31236301ba1fcca604c68bb4e908318c49 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 4 Dec 2018 22:13:39 +0100
Subject: [PATCH] resolved: pin stream while calling callbacks for it
@ -16,7 +16,7 @@ Resolves: #2110548
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c
index 066daef96e..2d0162483a 100644
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) {
@ -28,7 +28,7 @@ index 066daef96e..2d0162483a 100644
assert(s);
#if ENABLE_DNS_OVER_TLS
@@ -315,7 +317,7 @@ static int on_stream_timeout(sd_event_source *es, usec_t usec, void *userdata) {
@@ -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) {
@ -37,6 +37,3 @@ index 066daef96e..2d0162483a 100644
int r;
assert(s);
--
2.37.1

View File

@ -0,0 +1,49 @@
From 34aeec27c86917e7284ea562f62e46384d5da5ba Mon Sep 17 00:00:00 2001
From: Anita Zhang <the.anitazha@gmail.com>
Date: Thu, 17 Sep 2020 01:49:17 -0700
Subject: [PATCH] core: move reset_arguments() to the end of main's finish
Fixes #16991
fb39af4ce42d7ef9af63009f271f404038703704 replaced `free_arguments()` with
`reset_arguments()`, which frees arg_* variables as before, but also resets all
of them to the default values. `reset_arguments()` was positioned
in such a way that it overrode some arg_* values still in use at shutdown.
To avoid further unintentional resets, I moved `reset_arguments()`
right before the return, when nothing else will be using the arg_* variables.
(cherry picked from commit 7d9eea2bd3d4f83668c7a78754d201b226acbf1e)
Resolves: #2127171
---
src/core/main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/core/main.c b/src/core/main.c
index d897155644..a4cdb28884 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -2622,7 +2622,6 @@ finish:
m = manager_free(m);
}
- reset_arguments();
mac_selinux_finish();
if (reexecute)
@@ -2647,6 +2646,7 @@ finish:
* in become_shutdown() so normally we cannot free them yet. */
watchdog_free_device();
arg_watchdog_device = mfree(arg_watchdog_device);
+ reset_arguments();
return retval;
}
#endif
@@ -2668,5 +2668,6 @@ finish:
freeze_or_reboot();
}
+ reset_arguments();
return retval;
}

View File

@ -13,7 +13,7 @@
Name: systemd
Url: http://www.freedesktop.org/wiki/Software/systemd
Version: 239
Release: 58%{?dist}.7
Release: 58%{?dist}.8
# For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+
Summary: System and Service Manager
@ -811,8 +811,16 @@ Patch0758: 0758-sd-event-don-t-invalidate-source-type-on-disconnect.patch
Patch0759: 0759-test-procfs-util-skip-test-on-certain-errors.patch
Patch0760: 0760-Try-stopping-MD-RAID-devices-in-shutdown-too.patch
Patch0761: 0761-shutdown-get-only-active-md-arrays.patch
Patch0762: 0762-unit-name-tighten-checks-for-building-valid-unit-nam.patch
Patch0763: 0763-core-shorten-long-unit-names-that-are-based-on-paths.patch
Patch0764: 0764-test-add-extended-test-for-triggering-mount-rate-lim.patch
Patch0765: 0765-tests-add-test-case-for-long-unit-names.patch
Patch0766: 0766-Revert-core-Propagate-condition-failed-state-to-trig.patch
Patch0767: 0767-core-Check-unit-start-rate-limiting-earlier.patch
Patch0768: 0768-core-Add-trigger-limit-for-path-units.patch
Patch0769: 0769-resolved-pin-stream-while-calling-callbacks-for-it.patch
Patch0770: 0770-core-move-reset_arguments-to-the-end-of-main-s-finis.patch
Patch9000: 9000-resolved-pin-stream-while-calling-callbacks-for-it.patch
%ifarch %{ix86} x86_64 aarch64
%global have_gnu_efi 1
@ -1442,6 +1450,17 @@ fi
%files tests -f .file-list-tests
%changelog
* Wed Sep 21 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-58.8
- unit-name: tighten checks for building valid unit names (#2094712)
- core: shorten long unit names that are based on paths and append path hash at the end (#2094712)
- test: add extended test for triggering mount rate limit (#2094712)
- tests: add test case for long unit names (#2094712)
- Revert "core: Propagate condition failed state to triggering units." (#2123801)
- core: Check unit start rate limiting earlier (#2123801)
- core: Add trigger limit for path units (#2123801)
- resolved: pin stream while calling callbacks for it (#2110548)
- core: move reset_arguments() to the end of main's finish (#2127171)
* Thu Aug 25 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-58.7
- sd-event: don't invalidate source type on disconnect (#2116892)
- test-procfs-util: skip test on certain errors (#2087152)