import systemd-239-62.el8

This commit is contained in:
CentOS Sources 2022-07-22 08:10:56 +00:00 committed by Stepan Oksanichenko
parent 3d4c7390b9
commit e2881b4302
22 changed files with 2073 additions and 9 deletions

View File

@ -0,0 +1,24 @@
From 3cdbda49a4eca0dc28f1ebc7923c387bc9b69a9f Mon Sep 17 00:00:00 2001
From: Jacek Migacz <jmigacz@redhat.com>
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

View File

@ -0,0 +1,181 @@
From e3e479fc9c51e0b6f2c21087e2e78e7c6f55169c 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: #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;
}

View File

@ -0,0 +1,275 @@
From f62231a54abff6566415ea82aa8773e61f5688d6 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: #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 <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 2b390a10d826f060a672d9f01c6ad43714691274 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: #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 <<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 1c2a0bde1bc3510d9bdc07410ff90429ebed391f 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: #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

View File

@ -0,0 +1,33 @@
From 9ba5d8811630a3d2af90fdc52f4fd6b03ee9e692 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
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;
}

View File

@ -0,0 +1,94 @@
From c20e06c1c0319e3759a11bf9051a8041898f79b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
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);
}

View File

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

View File

@ -0,0 +1,182 @@
From 3022d49ba2276eb5634d84a89a078aa3c357b70a Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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);

View File

@ -0,0 +1,25 @@
From bbf71447d5de3b2cb86623a870cad21bbf114390 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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));

View File

@ -0,0 +1,123 @@
From 54a8d932442d02f5a7dbf6038c8f557ce41f468b Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
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"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Session"
+ send_member="SetDisplay"/>
+
<allow receive_sender="org.freedesktop.login1"/>
</policy>

View File

@ -0,0 +1,160 @@
From ffc616d9c4d2c64d211c9e63601a321524fe2d31 Mon Sep 17 00:00:00 2001
From: Claudio Zumbo <claudioz@fb.com>
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</programlisting>
<para><varname>Type=</varname><option>oneshot</option> are the
only service units that may have more than one
- <varname>ExecStart=</varname> specified. They will be executed
- in order until either they are all successful or one of them
- fails.</para>
+ <varname>ExecStart=</varname> specified. For units with multiple
+ commands (<varname noindex="true">Type=oneshot</varname>), all commands will be run again.</para>
+ <para> For <varname noindex="true">Type=oneshot</varname>, <varname>Restart=</varname><option>always</option>
+ and <varname>Restart=</varname><option>on-success</option> are <emphasis>not</emphasis> allowed.</para>
</example>
<example>
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 <<EOF
+[Unit]
+Description=Testsuite service
+
+[Service]
+ExecStart=/testsuite.sh
+Type=oneshot
+EOF
+ cp testsuite.sh $initdir/
+
+ setup_testsuite
+ )
+ setup_nspawn_root
+
+ ddebug "umount $TESTDIR/root"
+ umount $TESTDIR/root
+}
+
+do_test "$@"
diff --git a/test/TEST-41-ONESHOT-RESTART/testsuite.sh b/test/TEST-41-ONESHOT-RESTART/testsuite.sh
new file mode 100755
index 0000000000..f7423dbf9a
--- /dev/null
+++ b/test/TEST-41-ONESHOT-RESTART/testsuite.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+set -ex
+set -o pipefail
+
+systemd-analyze log-level debug
+systemd-analyze log-target console
+
+# These three commands should succeed.
+! systemd-run --unit=one -p Type=oneshot -p Restart=on-failure /bin/bash -c "exit 1"
+
+sleep 5
+
+if [[ "$(systemctl show one.service -p NRestarts --value)" -le 0 ]]; then
+ exit 1
+fi
+
+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"
+
+sleep 5
+
+if [[ $(cat $TMP_FILE) != "aaa" ]]; then
+ exit 1
+fi
+
+systemd-analyze log-level info
+
+echo OK > /testok
+
+exit 0

View File

@ -0,0 +1,76 @@
From a7375d12da80d633dfa802f2b66d2361c70c62f5 Mon Sep 17 00:00:00 2001
From: Dan Streetman <ddstreet@canonical.com>
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

View File

@ -0,0 +1,29 @@
From 32ef99e27ca6242cd86e06b7f63ba49562a77335 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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);

View File

@ -0,0 +1,24 @@
From 09b6ae4da2d8b60d3619dcd0e6712e1a106efba0 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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);

View File

@ -0,0 +1,69 @@
From 23ef6c470418b50119dc0bf13b681bfeae820352 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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);

View File

@ -0,0 +1,63 @@
From d829e7163f6a98547cef3b0106a6a98728275065 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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);

View File

@ -0,0 +1,54 @@
From 48b22b82853c6697669b078de5eae35728fbba30 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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"));
}

View File

@ -0,0 +1,124 @@
From f41927c026d65e9005c0ba418c6bfff511055bd2 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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",

View File

@ -0,0 +1,76 @@
From 5226df888c28ede9219d7f018af02cca1d1f6d2a Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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/.

View File

@ -0,0 +1,85 @@
From a729ea1a59b63c5f3e7fdce6a6c4e2ce12faa972 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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</programlisting>
<listitem><para>These options take a whitespace-separated list of directory names. The specified directory
names must be relative, and may not include <literal>..</literal>. 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.</para>
+ 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 (<literal>:</literal>).</para>
<table>
- <title>Automatic directory creation</title>
- <tgroup cols='3'>
+ <title>Automatic directory creation and environment variables</title>
+ <tgroup cols='4'>
<thead>
<row>
<entry>Locations</entry>
<entry>for system</entry>
<entry>for users</entry>
+ <entry>Environment variable</entry>
</row>
</thead>
<tbody>
@@ -836,26 +839,31 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
<entry><varname>RuntimeDirectory=</varname></entry>
<entry><filename>/run</filename></entry>
<entry><varname>$XDG_RUNTIME_DIR</varname></entry>
+ <entry><varname>$RUNTIME_DIRECTORY</varname></entry>
</row>
<row>
<entry><varname>StateDirectory=</varname></entry>
<entry><filename>/var/lib</filename></entry>
<entry><varname>$XDG_CONFIG_HOME</varname></entry>
+ <entry><varname>$STATE_DIRECTORY</varname></entry>
</row>
<row>
<entry><varname>CacheDirectory=</varname></entry>
<entry><filename>/var/cache</filename></entry>
<entry><varname>$XDG_CACHE_HOME</varname></entry>
+ <entry><varname>$CACHE_DIRECTORY</varname></entry>
</row>
<row>
<entry><varname>LogsDirectory=</varname></entry>
<entry><filename>/var/log</filename></entry>
<entry><varname>$XDG_CONFIG_HOME</varname><filename>/log</filename></entry>
+ <entry><varname>$LOGS_DIRECTORY</varname></entry>
</row>
<row>
<entry><varname>ConfigurationDirectory=</varname></entry>
<entry><filename>/etc</filename></entry>
<entry><varname>$XDG_CONFIG_HOME</varname></entry>
+ <entry><varname>$CONFIGURATION_DIRECTORY</varname></entry>
</row>
</tbody>
</tgroup>
@@ -905,7 +913,13 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
<filename>/run/foo/bar</filename>, and <filename>/run/baz</filename>. The directories
<filename>/run/foo/bar</filename> and <filename>/run/baz</filename> except <filename>/run/foo</filename> are
owned by the user and group specified in <varname>User=</varname> and <varname>Group=</varname>, and removed
- when the service is stopped.</para></listitem>
+ when the service is stopped.</para>
+
+ <para>Example: if a system service unit has the following,
+ <programlisting>RuntimeDirectory=foo/bar
+StateDirectory=aaa/bbb ccc</programlisting>
+ then the environment variable <literal>RUNTIME_DIRECTORY</literal> is set with <literal>/run/foo/bar</literal>, and
+ <literal>STATE_DIRECTORY</literal> is set with <literal>/var/lib/aaa/bbb:/var/lib/ccc</literal>.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -13,7 +13,7 @@
Name: systemd
Url: http://www.freedesktop.org/wiki/Software/systemd
Version: 239
Release: 60%{?dist}
Release: 62%{?dist}
# For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+
Summary: System and Service Manager
@ -820,6 +820,27 @@ 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
%ifarch %{ix86} x86_64 aarch64
@ -883,7 +904,6 @@ Requires: %{name}-pam = %{version}-%{release}
Requires: %{name}-libs = %{version}-%{release}
Recommends: diffutils
Requires: util-linux
Requires: timedatex
Recommends: libxkbcommon%{?_isa}
Provides: /bin/systemctl
Provides: /sbin/shutdown
@ -1319,7 +1339,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
@ -1336,14 +1356,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
@ -1451,6 +1471,32 @@ fi
%files tests -f .file-list-tests
%changelog
* Mon Jul 18 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-62
- spec: Remove dependency on timedatex (#2066946)
* Thu Jul 14 2022 systemd maintenance team <systemd-maint@redhat.com> - 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 <systemd-maint@redhat.com> - 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)