Compare commits

...

20 Commits

Author SHA1 Message Date
eabdullin 745a636f7e import CS systemd-239-82.el8 2024-05-22 10:48:13 +00:00
eabdullin 969a05ab78 import UBI systemd-239-78.el8 2023-11-14 20:04:46 +00:00
eabdullin 8002c35e3f import UBI systemd-239-74.el8_8.5 2023-09-21 08:44:01 +00:00
eabdullin 85b5341ca1 import UBI systemd-239-74.el8_8.3 2023-08-08 13:37:56 +00:00
Andrew Lukoshko 8bfaff043a import systemd-239-74.el8_8.2 2023-06-29 20:09:24 +00:00
CentOS Sources 020374c810 import systemd-239-74.el8_8 2023-05-16 07:37:56 +00:00
CentOS Sources d8ae20ffcd import systemd-239-68.el8_7.4 2023-02-21 08:48:41 +00:00
CentOS Sources 388e2f69c7 import systemd-239-68.el8_7.2 2023-01-12 09:26:12 +00:00
CentOS Sources 6aee57833d import systemd-239-68.el8_7.1 2023-01-12 09:26:06 +00:00
CentOS Sources b340d628a9 import systemd-239-68.el8 2022-11-08 08:08:37 +00:00
CentOS Sources c7097e3e7c import systemd-239-58.el8_6.8 2022-10-25 08:44:08 +00:00
CentOS Sources 3494a638bc import systemd-239-58.el8_6.7 2022-09-13 07:41:43 +00:00
CentOS Sources 6a2ab047ad import systemd-239-58.el8_6.4 2022-08-29 15:58:43 +00:00
CentOS Sources 4b5a13cea2 import systemd-239-58.el8_6.3 2022-08-02 07:03:49 +00:00
CentOS Sources ff9b3458f8 import systemd-239-58.el8 2022-05-10 11:55:39 +00:00
CentOS Sources 253862ee4a import systemd-239-51.el8_5.5 2022-03-25 12:43:58 +00:00
CentOS Sources 5a26f68386 import systemd-239-51.el8_5.2 2021-12-21 09:10:23 +00:00
CentOS Sources 02cc916713 import systemd-239-51.el8_5.3 2021-12-16 19:33:28 +00:00
CentOS Sources b59a7e755d import systemd-239-51.el8 2021-11-09 10:12:47 +00:00
CentOS Sources a26ecff55e import systemd-239-45.el8_4.3 2021-09-10 05:03:35 +00:00
449 changed files with 147405 additions and 68 deletions

View File

@ -1,4 +1,4 @@
From 43c0bcb8b24edb83bc265cdde264e6d2a36d1cea Mon Sep 17 00:00:00 2001
From 1afb38f39a9b4508533cc1c7262e5fff418cb317 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 17 May 2021 15:49:08 +0200
Subject: [PATCH] Revert "udev: run link_update() with increased retry count in
@ -6,7 +6,7 @@ Subject: [PATCH] Revert "udev: run link_update() with increased retry count in
This reverts commit 1f3165bda13c8572c8c31d23c998835c4e2ad8f3.
Related: #1963980
Related: #1942299
---
src/udev/udev-event.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

View File

@ -1,4 +1,4 @@
From 612773fa8b6333dcdac382849e81fa5a473dd1f9 Mon Sep 17 00:00:00 2001
From 897b4d1e19c706d9198b9308125df57a5d469a6b Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 17 May 2021 15:50:31 +0200
Subject: [PATCH] Revert "udev: make algorithm that selects highest priority
@ -6,7 +6,7 @@ Subject: [PATCH] Revert "udev: make algorithm that selects highest priority
This reverts commit 1d5f966c1758eb620755fcae54abd07a1ac36d3d.
Related: #1963980
Related: #1942299
---
src/udev/udev-event.c | 71 +++++-------
src/udev/udev-node.c | 244 ++++++++++++------------------------------

View File

@ -1,4 +1,4 @@
From bc21daeb780911d586de7ff0004ed2bc515b8826 Mon Sep 17 00:00:00 2001
From 94ad224240140a7287f9e2be5905b9c506350193 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 17 May 2021 15:54:10 +0200
Subject: [PATCH] test/udev-test.pl: drop test cases that add mutliple devices
@ -7,7 +7,7 @@ Subject: [PATCH] test/udev-test.pl: drop test cases that add mutliple devices
udev test fail. Once we reintroduce the fix for link_update()
we will revert this commit.]
Related: #1963980
Related: #1942299
---
test/udev-test.pl | 179 ----------------------------------------------
1 file changed, 179 deletions(-)

View File

@ -0,0 +1,41 @@
From 4e589237979fdf90af38d466abd7fcd852356f02 Mon Sep 17 00:00:00 2001
From: Kai Krakow <kai@kaishome.de>
Date: Sat, 17 Aug 2019 02:33:43 +0200
Subject: [PATCH] cgroup: Also set io.bfq.weight
Current kernels with BFQ scheduler do not yet set their IO weight
through "io.weight" but through "io.bfq.weight" (using a slightly
different interface supporting only default weights, not per-device
weights). This commit enables "IOWeight=" to just to that.
This patch may be dropped at some time later.
Github-Link: https://github.com/systemd/systemd/issues/7057
Signed-off-by: Kai Krakow <kai@kaishome.de>
(cherry picked from commit 21221ce1ce9a572e82d46d80692afd65c224fc50)
Related: #1927290
---
src/core/cgroup.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 71e30fd4db..f02cc31c6e 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -984,6 +984,14 @@ static void cgroup_context_apply(
log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to set io.weight: %m");
+ /* FIXME: drop this when distro kernels properly support BFQ through "io.weight"
+ * See also: https://github.com/systemd/systemd/pull/13335 */
+ xsprintf(buf, "%" PRIu64 "\n", weight);
+ r = cg_set_attribute("io", path, "io.bfq.weight", buf);
+ if (r < 0)
+ log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
+ "Failed to set io.bfq.weight: %m");
+
if (has_io) {
CGroupIODeviceWeight *w;

View File

@ -0,0 +1,82 @@
From e706f5df66b7189a7df526aeeb45c86b8c4b057a Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 2 Nov 2020 14:51:10 +0100
Subject: [PATCH] seccomp: allow turning off of seccomp filtering via env var
Fixes: #17504
(While we are it, also move $SYSTEMD_SECCOMP_LOG= env var description
into the right document section)
Also suggested in: https://github.com/systemd/systemd/issues/17245#issuecomment-704773603
(cherry picked from commit ce8f6d478e3f6c6a313fb19615aa5029bb18f86d)
Resolves: #1916835
---
doc/ENVIRONMENT.md | 3 +++
src/nspawn/nspawn-seccomp.c | 2 +-
src/shared/seccomp-util.c | 19 +++++++++++++++----
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/doc/ENVIRONMENT.md b/doc/ENVIRONMENT.md
index 0e763b6302..36b649afe1 100644
--- a/doc/ENVIRONMENT.md
+++ b/doc/ENVIRONMENT.md
@@ -117,3 +117,6 @@ systemd-sulogin-shell:
* `$SYSTEMD_SULOGIN_FORCE=1` — This skips asking for the root password if the
root password is not available (such as when the root account is locked).
See `sulogin(8)` for more details.
+
+* `$SYSTEMD_SECCOMP=0` if set, seccomp filters will not be enforced, even if
+ support for it is compiled in and available in the kernel.
diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c
index b56c5b04a8..fba22644da 100644
--- a/src/nspawn/nspawn-seccomp.c
+++ b/src/nspawn/nspawn-seccomp.c
@@ -172,7 +172,7 @@ int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **sys
int r;
if (!is_seccomp_available()) {
- log_debug("SECCOMP features not detected in the kernel, disabling SECCOMP filterering");
+ log_debug("SECCOMP features not detected in the kernel or disabled at runtime, disabling SECCOMP filtering");
return 0;
}
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index d91fb4e269..e903512d45 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -12,6 +12,7 @@
#include "af-list.h"
#include "alloc-util.h"
+#include "env-util.h"
#include "macro.h"
#include "nsflags.h"
#include "process-util.h"
@@ -244,10 +245,20 @@ static bool is_seccomp_filter_available(void) {
bool is_seccomp_available(void) {
static int cached_enabled = -1;
- if (cached_enabled < 0)
- cached_enabled =
- is_basic_seccomp_available() &&
- is_seccomp_filter_available();
+ if (cached_enabled < 0) {
+ int b;
+
+ b = getenv_bool("SYSTEMD_SECCOMP");
+ if (b != 0) {
+ if (b < 0 && b != -ENXIO) /* ENXIO: env var unset */
+ log_debug_errno(b, "Failed to parse $SYSTEMD_SECCOMP value, ignoring.");
+
+ cached_enabled =
+ is_basic_seccomp_available() &&
+ is_seccomp_filter_available();
+ } else
+ cached_enabled = false;
+ }
return cached_enabled;
}

View File

@ -0,0 +1,36 @@
From 7fb2d86b58201341a582b739a5445821bec66eea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 6 Nov 2019 12:44:39 +0100
Subject: [PATCH] meson: remove strange dep that causes meson to enter infinite
loop
The value is obviously bogus, but didn't seem to cause problems so far.
With meson-0.52.0, it causes a hang. The number of aliases is always rather
small (usually just one or two, possibly up to a dozen in a few cases), so
even if this causes some looping, it is strange that it has such a huge impact.
But let's just remove it.
Fixes #13742.
Tested with meson-0.52.0-1.module_f31+6771+f5d842eb.noarch,
meson-0.51.1-1.fc29.noarch.
(cherry picked from commit af336643a01d0b210b18312c253a50594ba54b0a)
Resolves: #1970860
---
man/meson.build | 1 -
1 file changed, 1 deletion(-)
diff --git a/man/meson.build b/man/meson.build
index ec05d73bc6..a953d34098 100644
--- a/man/meson.build
+++ b/man/meson.build
@@ -68,7 +68,6 @@ foreach tuple : xsltproc.found() ? manpages : []
foreach htmlalias : htmlaliases
link = custom_target(
htmlalias,
- input : p2,
output : htmlalias,
command : ['ln', '-fs', html, '@OUTPUT@'])
if want_html

View File

@ -0,0 +1,182 @@
From 8df650c7c5adc2bb24a0077d8332f5ee342e7fd8 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 26 Feb 2021 10:25:24 +0100
Subject: [PATCH] copy: handle copy_file_range() weirdness on procfs/sysfs
This addresses the issue described in https://lwn.net/Articles/846403/
and makes sure we will be able to stream bytes from procfs/sysfs via
copy_bytes() if people ask us to.
Based on: ee1aa61c4710ae567a2b844e0f0bb8cb0456ab8c
Related: #1970860
---
src/basic/copy.c | 75 +++++++++++++++++++++++++++++---------------
src/test/test-copy.c | 17 ++++++++++
2 files changed, 66 insertions(+), 26 deletions(-)
diff --git a/src/basic/copy.c b/src/basic/copy.c
index e06a503a29..a48c42c5c6 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -92,7 +92,7 @@ int copy_bytes_full(
void **ret_remains,
size_t *ret_remains_size) {
- bool try_cfr = true, try_sendfile = true, try_splice = true;
+ bool try_cfr = true, try_sendfile = true, try_splice = true, copied_something = false;
int r, nonblock_pipe = -1;
size_t m = SSIZE_MAX; /* that is the maximum that sendfile and c_f_r accept */
@@ -185,9 +185,20 @@ int copy_bytes_full(
try_cfr = false;
/* use fallback below */
- } else if (n == 0) /* EOF */
- break;
- else
+ } else if (n == 0) { /* likely EOF */
+
+ if (copied_something)
+ break;
+
+ /* So, we hit EOF immediately, without having copied a single byte. This
+ * could indicate two things: the file is actually empty, or we are on some
+ * virtual file system such as procfs/sysfs where the syscall actually
+ * doesn't work but doesn't return an error. Try to handle that, by falling
+ * back to simple read()s in case we encounter empty files.
+ *
+ * See: https://lwn.net/Articles/846403/ */
+ try_cfr = try_sendfile = try_splice = false;
+ } else
/* Success! */
goto next;
}
@@ -201,9 +212,14 @@ int copy_bytes_full(
try_sendfile = false;
/* use fallback below */
- } else if (n == 0) /* EOF */
+ } else if (n == 0) { /* likely EOF */
+
+ if (copied_something)
+ break;
+
+ try_sendfile = try_splice = false; /* same logic as above for copy_file_range() */
break;
- else
+ } else
/* Success! */
goto next;
}
@@ -213,14 +229,14 @@ int copy_bytes_full(
/* splice()'s asynchronous I/O support is a bit weird. When it encounters a pipe file
* descriptor, then it will ignore its O_NONBLOCK flag and instead only honour the
- * SPLICE_F_NONBLOCK flag specified in its flag parameter. Let's hide this behaviour here, and
- * check if either of the specified fds are a pipe, and if so, let's pass the flag
- * automatically, depending on O_NONBLOCK being set.
+ * SPLICE_F_NONBLOCK flag specified in its flag parameter. Let's hide this behaviour
+ * here, and check if either of the specified fds are a pipe, and if so, let's pass
+ * the flag automatically, depending on O_NONBLOCK being set.
*
- * Here's a twist though: when we use it to move data between two pipes of which one has
- * O_NONBLOCK set and the other has not, then we have no individual control over O_NONBLOCK
- * behaviour. Hence in that case we can't use splice() and still guarantee systematic
- * O_NONBLOCK behaviour, hence don't. */
+ * Here's a twist though: when we use it to move data between two pipes of which one
+ * has O_NONBLOCK set and the other has not, then we have no individual control over
+ * O_NONBLOCK behaviour. Hence in that case we can't use splice() and still guarantee
+ * systematic O_NONBLOCK behaviour, hence don't. */
if (nonblock_pipe < 0) {
int a, b;
@@ -238,12 +254,13 @@ int copy_bytes_full(
(a == FD_IS_BLOCKING_PIPE && b == FD_IS_NONBLOCKING_PIPE) ||
(a == FD_IS_NONBLOCKING_PIPE && b == FD_IS_BLOCKING_PIPE))
- /* splice() only works if one of the fds is a pipe. If neither is, let's skip
- * this step right-away. As mentioned above, if one of the two fds refers to a
- * blocking pipe and the other to a non-blocking pipe, we can't use splice()
- * either, hence don't try either. This hence means we can only use splice() if
- * either only one of the two fds is a pipe, or if both are pipes with the same
- * nonblocking flag setting. */
+ /* splice() only works if one of the fds is a pipe. If neither is,
+ * let's skip this step right-away. As mentioned above, if one of the
+ * two fds refers to a blocking pipe and the other to a non-blocking
+ * pipe, we can't use splice() either, hence don't try either. This
+ * hence means we can only use splice() if either only one of the two
+ * fds is a pipe, or if both are pipes with the same nonblocking flag
+ * setting. */
try_splice = false;
else
@@ -259,9 +276,13 @@ int copy_bytes_full(
try_splice = false;
/* use fallback below */
- } else if (n == 0) /* EOF */
- break;
- else
+ } else if (n == 0) { /* likely EOF */
+
+ if (copied_something)
+ break;
+
+ try_splice = false; /* same logic as above for copy_file_range() + sendfile() */
+ } else
/* Success! */
goto next;
}
@@ -312,11 +333,13 @@ int copy_bytes_full(
assert(max_bytes >= (uint64_t) n);
max_bytes -= n;
}
- /* sendfile accepts at most SSIZE_MAX-offset bytes to copy,
- * so reduce our maximum by the amount we already copied,
- * but don't go below our copy buffer size, unless we are
- * close the limit of bytes we are allowed to copy. */
+
+ /* sendfile accepts at most SSIZE_MAX-offset bytes to copy, so reduce our maximum by the
+ * amount we already copied, but don't go below our copy buffer size, unless we are close the
+ * limit of bytes we are allowed to copy. */
m = MAX(MIN(COPY_BUFFER_SIZE, max_bytes), m - n);
+
+ copied_something = true;
}
return 0; /* return 0 if we hit EOF earlier than the size limit */
diff --git a/src/test/test-copy.c b/src/test/test-copy.c
index 2e8d251ac1..29ac33e47a 100644
--- a/src/test/test-copy.c
+++ b/src/test/test-copy.c
@@ -253,6 +253,22 @@ static void test_copy_atomic(void) {
assert_se(copy_file_atomic("/etc/fstab", q, 0644, 0, COPY_REPLACE) >= 0);
}
+static void test_copy_proc(void) {
+ _cleanup_(rm_rf_physical_and_freep) char *p = NULL;
+ _cleanup_free_ char *f = NULL, *a = NULL, *b = NULL;
+
+ /* Check if copying data from /proc/ works correctly, i.e. let's see if https://lwn.net/Articles/846403/ is a problem for us */
+
+ assert_se(mkdtemp_malloc(NULL, &p) >= 0);
+ assert_se(f = path_join(NULL, p, "version"));
+ assert_se(copy_file("/proc/version", f, 0, (mode_t) -1, 0, 0) >= 0);
+
+ assert_se(read_one_line_file("/proc/version", &a) >= 0);
+ assert_se(read_one_line_file(f, &b) >= 0);
+ assert_se(streq(a, b));
+ assert_se(strlen(a) > 0);
+}
+
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
@@ -267,6 +283,7 @@ int main(int argc, char *argv[]) {
test_copy_bytes_regular_file(argv[0], false, 32000); /* larger than copy buffer size */
test_copy_bytes_regular_file(argv[0], true, 32000);
test_copy_atomic();
+ test_copy_proc();
return 0;
}

View File

@ -0,0 +1,33 @@
From 4dc498258bd0cce1bc8ad2311c5f12de5678e0af Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Thu, 27 May 2021 12:25:51 +0200
Subject: [PATCH] core: Hide "Deactivated successfully" message
Show message "Deactivated successfully" in debug mode (when manager is
user) rather than in info mode. This message has low information value
for regular users and it might be a bit overwhelming on a system with
a lot of devices.
(cherry picked from commit edf2ee22f54005d76b2fb8fdcc9c60974feb88bc)
Resolves: #1954802
---
src/core/unit.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index cd3e7c806d..93c13e58d9 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -5525,7 +5525,10 @@ int unit_pid_attachable(Unit *u, pid_t pid, sd_bus_error *error) {
void unit_log_success(Unit *u) {
assert(u);
- log_struct(LOG_INFO,
+ /* Let's show message "Deactivated successfully" in debug mode (when manager is user) rather than in info mode.
+ * This message has low information value for regular users and it might be a bit overwhelming on a system with
+ * a lot of devices. */
+ log_struct(MANAGER_IS_USER(u->manager) ? LOG_DEBUG : LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_UNIT_SUCCESS_STR,
LOG_UNIT_ID(u),
LOG_UNIT_INVOCATION_ID(u),

View File

@ -0,0 +1,35 @@
From 42f639d3689b7cbc9ce6b9578a2790c254508384 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Fri, 8 Jan 2021 14:52:26 +0800
Subject: [PATCH] util: rework in_initrd() to make use of
path_is_temporary_fs()
(cherry picked from commit 96cceb35e7985f5ee6c9b17e129a76259273cdde)
Related: #1959339
---
src/basic/util.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/basic/util.c b/src/basic/util.c
index 82cb937314..b443e639f3 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -130,7 +130,6 @@ int prot_from_flags(int flags) {
}
bool in_initrd(void) {
- struct statfs s;
if (saved_in_initrd >= 0)
return saved_in_initrd;
@@ -146,8 +145,7 @@ bool in_initrd(void) {
*/
saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
- statfs("/", &s) >= 0 &&
- is_temporary_fs(&s);
+ path_is_temporary_fs("/") > 0;
return saved_in_initrd;
}

View File

@ -0,0 +1,99 @@
From 99ca5b681fceedd010b2616b1248a483f4bfbd97 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Wed, 13 Jan 2021 00:04:53 +0800
Subject: [PATCH] initrd: extend SYSTEMD_IN_INITRD to accept non-ramfs rootfs
Sometimes, non-ramfs initrd root are useful. Eg, for kdump, because
initramfs is memory consuming, so mount a compressed image in earlier
initrd, chroot into it then let systemd do the rest of job is a good
solution.
But systemd doesn't recognize the initrd environment if rootfs is not a
temporary fs. This is a reasonable check, because switch-root in initrd
will wipe the whole rootfs, will be a disaster if there are any
misdetect.
So extend SYSTEMD_IN_INITRD environment variable, now it accepts boolean
value and two extra keyword, "auto" and "lenient". "auto" is same as
before, and it's the default value. "lenient" will let systemd bypass
the rootfs check.
(cherry picked from commit db4c45cf4f10ca094b9e9570b758abd445d65381)
Related: #1959339
---
doc/ENVIRONMENT.md | 8 ++++++++
src/basic/util.c | 28 +++++++++++++++++++++++++---
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/doc/ENVIRONMENT.md b/doc/ENVIRONMENT.md
index 36b649afe1..8d7ce6ae2c 100644
--- a/doc/ENVIRONMENT.md
+++ b/doc/ENVIRONMENT.md
@@ -37,6 +37,14 @@ All tools:
useful for debugging, in order to test generators and other code against
specific kernel command lines.
+* `$SYSTEMD_IN_INITRD=[auto|lenient|0|1]` — if set, specifies initrd detection
+ method. Defaults to `auto`. Behavior is defined as follows:
+ `auto`: Checks if `/etc/initrd-release` exists, and a temporary fs is mounted
+ on `/`. If both conditions meet, then it's in initrd.
+ `lenient`: Similiar to `auto`, but the rootfs check is skipped.
+ `0|1`: Simply overrides initrd detection. This is useful for debugging and
+ testing initrd-only programs in the main system.
+
* `$SYSTEMD_EMOJI=0` — if set, tools such as "systemd-analyze security" will
not output graphical smiley emojis, but ASCII alternatives instead. Note that
this only controls use of Unicode emoji glyphs, and has no effect on other
diff --git a/src/basic/util.c b/src/basic/util.c
index b443e639f3..59bcf7b00c 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -130,11 +130,14 @@ int prot_from_flags(int flags) {
}
bool in_initrd(void) {
+ int r;
+ const char *e;
+ bool lenient = false;
if (saved_in_initrd >= 0)
return saved_in_initrd;
- /* We make two checks here:
+ /* We have two checks here:
*
* 1. the flag file /etc/initrd-release must exist
* 2. the root file system must be a memory file system
@@ -142,10 +145,29 @@ bool in_initrd(void) {
* The second check is extra paranoia, since misdetecting an
* initrd can have bad consequences due the initrd
* emptying when transititioning to the main systemd.
+ *
+ * If env var $SYSTEMD_IN_INITRD is not set or set to "auto",
+ * both checks are used. If it's set to "lenient", only check
+ * 1 is used. If set to a booleen value, then the boolean
+ * value is returned.
*/
- saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0 &&
- path_is_temporary_fs("/") > 0;
+ e = secure_getenv("SYSTEMD_IN_INITRD");
+ if (e) {
+ if (streq(e, "lenient"))
+ lenient = true;
+ else if (!streq(e, "auto")) {
+ r = parse_boolean(e);
+ if (r >= 0) {
+ saved_in_initrd = r > 0;
+ return saved_in_initrd;
+ }
+ log_debug_errno(r, "Failed to parse $SYSTEMD_IN_INITRD, ignoring: %m");
+ }
+ }
+
+ saved_in_initrd = (lenient || path_is_temporary_fs("/") > 0) &&
+ access("/etc/initrd-release", F_OK) >= 0;
return saved_in_initrd;
}

View File

@ -0,0 +1,35 @@
From 3299c855c6e65596ff9d8635dcbd45ff6818499a Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Thu, 14 Jan 2021 00:39:10 +0800
Subject: [PATCH] initrd: do a debug log if failed to detect rootfs type
(cherry picked from commit 3377c740d9121f38385e70d6a380b5e4bd8c672a)
Related: #1959339
---
src/basic/util.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/basic/util.c b/src/basic/util.c
index 59bcf7b00c..fef52ad5ff 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -166,8 +166,16 @@ bool in_initrd(void) {
}
}
- saved_in_initrd = (lenient || path_is_temporary_fs("/") > 0) &&
- access("/etc/initrd-release", F_OK) >= 0;
+ if (!lenient) {
+ r = path_is_temporary_fs("/");
+ if (r < 0)
+ log_debug_errno(r, "Couldn't determine if / is a temporary file system: %m");
+
+ saved_in_initrd = r > 0;
+ }
+
+ if (saved_in_initrd != 0)
+ saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0;
return saved_in_initrd;
}

View File

@ -0,0 +1,39 @@
From a1417c121d19272b1389098648132106a5ffc661 Mon Sep 17 00:00:00 2001
From: Kairui Song <kasong@redhat.com>
Date: Thu, 14 Jan 2021 01:25:20 +0800
Subject: [PATCH] initrd: do a debug log if /etc/initrd-release doesn't take
effect
Signed-off-by: Kairui Song <kasong@redhat.com>
(cherry picked from commit 4a60d8cbcae574896a28f9f1f6204a1bddca8e99)
Related: #1959339
---
src/basic/util.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/basic/util.c b/src/basic/util.c
index fef52ad5ff..609f8c2f33 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -174,8 +174,17 @@ bool in_initrd(void) {
saved_in_initrd = r > 0;
}
- if (saved_in_initrd != 0)
- saved_in_initrd = access("/etc/initrd-release", F_OK) >= 0;
+ r = access("/etc/initrd-release", F_OK);
+ if (r >= 0) {
+ if (saved_in_initrd == 0)
+ log_debug("/etc/initrd-release exists, but it's not an initrd.");
+ else
+ saved_in_initrd = 1;
+ } else {
+ if (errno != ENOENT)
+ log_debug_errno(errno, "Failed to test if /etc/initrd-release exists: %m");
+ saved_in_initrd = 0;
+ }
return saved_in_initrd;
}

View File

@ -0,0 +1,25 @@
From 64975b046d5a0877690aa6de9389b8234ee1cfab Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 3 Aug 2018 10:45:31 +0200
Subject: [PATCH] units: assign user-runtime-dir@.service to user-%i.slice
This service won't use much resources, but it's certainly nicer to see
it attached th the user's slice along with user@.service, so that
everything we run for a specific user is properly bound into one unit.
(cherry picked from commit 1193c11a04b3ecc29925904fbeb5d64834bce73e)
Related: #1946453
---
units/user-runtime-dir@.service.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/units/user-runtime-dir@.service.in b/units/user-runtime-dir@.service.in
index 8c02beda3b..13b3ed52f8 100644
--- a/units/user-runtime-dir@.service.in
+++ b/units/user-runtime-dir@.service.in
@@ -15,3 +15,4 @@ StopWhenUnneeded=yes
ExecStart=@rootlibexecdir@/systemd-user-runtime-dir start %i
ExecStop=@rootlibexecdir@/systemd-user-runtime-dir stop %i
RemainAfterExit=true
+Slice=user-%i.slice

View File

@ -0,0 +1,30 @@
From 1fa9a6bf51a1a1d0fa2ccc23283739d16e9179b4 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 3 Aug 2018 10:42:09 +0200
Subject: [PATCH] units: order user-runtime-dir@.service after
systemd-user-sessions.service
We use systemd-user-sessions.service as barrier when to allow login
sessions. With this patch user@.service is ordered after that too, so
that any login related code (which user-runtime-dir@.service is) is
guaranteed to run after the barrier, and never before.
(cherry picked from commit eb748aef4fbfd03b64938aa471bb8ceda1bc89a8)
Related: #1946453
---
units/user-runtime-dir@.service.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/units/user-runtime-dir@.service.in b/units/user-runtime-dir@.service.in
index 13b3ed52f8..31354c9bf2 100644
--- a/units/user-runtime-dir@.service.in
+++ b/units/user-runtime-dir@.service.in
@@ -9,6 +9,7 @@
[Unit]
Description=/run/user/%i mount wrapper
+After=systemd-user-sessions.service
StopWhenUnneeded=yes
[Service]

View File

@ -0,0 +1,26 @@
From 780d1d9fa7ccc036e6e237221ac51ed69453c8c6 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 2 Aug 2018 20:57:56 +0200
Subject: [PATCH] units: make sure user-runtime-dir@.service is Type=oneshot
We order user@.service after it, hence we need to properly know when it
finished starting up.
(cherry picked from commit d06e8fbce35c2b52ee1d09af4888876d5f2d7ae4)
Related: #1946453
---
units/user-runtime-dir@.service.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/units/user-runtime-dir@.service.in b/units/user-runtime-dir@.service.in
index 31354c9bf2..bfd6488d61 100644
--- a/units/user-runtime-dir@.service.in
+++ b/units/user-runtime-dir@.service.in
@@ -15,5 +15,6 @@ StopWhenUnneeded=yes
[Service]
ExecStart=@rootlibexecdir@/systemd-user-runtime-dir start %i
ExecStop=@rootlibexecdir@/systemd-user-runtime-dir stop %i
+Type=oneshot
RemainAfterExit=true
Slice=user-%i.slice

View File

@ -0,0 +1,52 @@
From 354b894aa3e79f54ab75bf6fae76ce28ca80db38 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Thu, 2 Aug 2018 20:56:34 +0200
Subject: [PATCH] user-runtime-dir: downgrade a few log messages to LOG_DEBUG
that we ignore
As the comments already say it might be quite likely that
$XDG_RUNTIME_DIR is not set up as mount, and we shouldn't complain about
that.
Moreover, let's make this idempotent, so that a runtime dir that is
already gone and is removed again doesn't cause failure.
(cherry picked from commit 3a13442bbf72e7ebdd0b4d60c2922ea7c5cc9496)
Related: #1946453
---
src/login/user-runtime-dir.c | 15 +++++++--------
1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c
index 1bb26c99e4..9693821990 100644
--- a/src/login/user-runtime-dir.c
+++ b/src/login/user-runtime-dir.c
@@ -95,20 +95,19 @@ static int user_remove_runtime_path(const char *runtime_path) {
r = rm_rf(runtime_path, 0);
if (r < 0)
- log_error_errno(r, "Failed to remove runtime directory %s (before unmounting): %m", runtime_path);
+ log_debug_errno(r, "Failed to remove runtime directory %s (before unmounting), ignoring: %m", runtime_path);
- /* Ignore cases where the directory isn't mounted, as that's
- * quite possible, if we lacked the permissions to mount
- * something */
+ /* Ignore cases where the directory isn't mounted, as that's quite possible, if we lacked the permissions to
+ * mount something */
r = umount2(runtime_path, MNT_DETACH);
if (r < 0 && !IN_SET(errno, EINVAL, ENOENT))
- log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", runtime_path);
+ log_debug_errno(errno, "Failed to unmount user runtime directory %s, ignoring: %m", runtime_path);
r = rm_rf(runtime_path, REMOVE_ROOT);
- if (r < 0)
- log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", runtime_path);
+ if (r < 0 && r != -ENOENT)
+ return log_error_errno(r, "Failed to remove runtime directory %s (after unmounting): %m", runtime_path);
- return r;
+ return 0;
}
static int do_mount(const char *runtime_path, uid_t uid, gid_t gid) {

View File

@ -0,0 +1,33 @@
From 91ed691ff73d4d71fae8f6896a1bba73e6a76bba Mon Sep 17 00:00:00 2001
From: David Michael <dm0@redhat.com>
Date: Wed, 20 Mar 2019 15:14:32 +0000
Subject: [PATCH] shared/install: Preserve escape characters for escaped unit
names
Since switching to extract_first_word with no flags for parsing
unit names in 4c9565eea534cd233a913c8c21f7920dba229743, escape
characters will be stripped from escaped unit names such as
"mnt-persistent\x2dvolume.mount" resulting in the unit not being
configured as defined. Preserve escape characters again for
compatibility with existing preset definitions.
(cherry picked from commit 82bd4da71e9cdd5a2e9266332f5a7399845e31f6)
Resolves: #1952686
---
src/shared/install.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/shared/install.c b/src/shared/install.c
index c2847df3f8..c9fef6bde2 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -2774,7 +2774,7 @@ static int split_pattern_into_name_and_instances(const char *pattern, char **out
assert(out_instances);
assert(out_unit_name);
- r = extract_first_word(&pattern, &unit_name, NULL, 0);
+ r = extract_first_word(&pattern, &unit_name, NULL, EXTRACT_RETAIN_ESCAPE);
if (r < 0)
return r;

View File

@ -0,0 +1,80 @@
From 48dacf8d30cd61b72939e9c3419acced4b2fde74 Mon Sep 17 00:00:00 2001
From: Michal Suchanek <msuchanek@suse.de>
Date: Fri, 2 Oct 2020 11:05:23 +0200
Subject: [PATCH] basic/virt: Detect PowerVM hypervisor
Currently systemd-detect-virt fails to detect running under PowerVM.
Add code to detect PowerVM based on code in util-linux.
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
(cherry picked from commit 3224e38bb6b3287ca253cbafb460a150544d5818)
Resolves: #1937989
---
man/systemd-detect-virt.xml | 7 ++++++-
src/basic/virt.c | 6 ++++++
src/basic/virt.h | 1 +
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/man/systemd-detect-virt.xml b/man/systemd-detect-virt.xml
index c4763fd561..6beb2c2aa1 100644
--- a/man/systemd-detect-virt.xml
+++ b/man/systemd-detect-virt.xml
@@ -65,7 +65,7 @@
</thead>
<tbody>
<row>
- <entry valign="top" morerows="11">VM</entry>
+ <entry valign="top" morerows="12">VM</entry>
<entry><varname>qemu</varname></entry>
<entry>QEMU software virtualization, without KVM</entry>
</row>
@@ -95,6 +95,11 @@
<entry>Oracle VM VirtualBox (historically marketed by innotek and Sun Microsystems), for legacy and KVM hypervisor</entry>
</row>
+ <row>
+ <entry><varname>powervm</varname></entry>
+ <entry>IBM PowerVM hypervisor - comes as firmware with some IBM POWER servers</entry>
+ </row>
+
<row>
<entry><varname>xen</varname></entry>
<entry>Xen hypervisor (only domU, not dom0)</entry>
diff --git a/src/basic/virt.c b/src/basic/virt.c
index dfa1525219..0b88005ed6 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -92,6 +92,11 @@ static int detect_vm_device_tree(void) {
_cleanup_closedir_ DIR *dir = NULL;
struct dirent *dent;
+ if (access("/proc/device-tree/ibm,partition-name", F_OK) == 0 &&
+ access("/proc/device-tree/hmc-managed?", F_OK) == 0 &&
+ access("/proc/device-tree/chosen/qemu,graphic-width", F_OK) != 0)
+ return VIRTUALIZATION_POWERVM;
+
dir = opendir("/proc/device-tree");
if (!dir) {
if (errno == ENOENT) {
@@ -635,6 +640,7 @@ static const char *const virtualization_table[_VIRTUALIZATION_MAX] = {
[VIRTUALIZATION_PARALLELS] = "parallels",
[VIRTUALIZATION_BHYVE] = "bhyve",
[VIRTUALIZATION_QNX] = "qnx",
+ [VIRTUALIZATION_POWERVM] = "powervm",
[VIRTUALIZATION_VM_OTHER] = "vm-other",
[VIRTUALIZATION_SYSTEMD_NSPAWN] = "systemd-nspawn",
diff --git a/src/basic/virt.h b/src/basic/virt.h
index c4cf4bfeab..640b3ed779 100644
--- a/src/basic/virt.h
+++ b/src/basic/virt.h
@@ -21,6 +21,7 @@ enum {
VIRTUALIZATION_PARALLELS,
VIRTUALIZATION_BHYVE,
VIRTUALIZATION_QNX,
+ VIRTUALIZATION_POWERVM,
VIRTUALIZATION_VM_OTHER,
VIRTUALIZATION_VM_LAST = VIRTUALIZATION_VM_OTHER,

View File

@ -0,0 +1,57 @@
From 102f4ff97a24c2ddaf6e569c678a0a713f972863 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Fri, 19 Mar 2021 10:05:47 +0100
Subject: [PATCH] man: document differences in clean exit status for
Type=oneshot
See commit 1f0958f640b87175cd547c1e69084cfe54a22e9d .
(cherry picked from commit f055cf77862bc580f3afbfaac161d1c060f39411)
Resolves: #1940078
---
man/systemd.service.xml | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 54586d1948..1e30a564df 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -669,14 +669,19 @@
If set to <option>no</option> (the default), the service will
not be restarted. If set to <option>on-success</option>, it
will be restarted only when the service process exits cleanly.
- In this context, a clean exit means an exit code of 0, or one
- of the signals
- <constant>SIGHUP</constant>,
- <constant>SIGINT</constant>,
- <constant>SIGTERM</constant> or
- <constant>SIGPIPE</constant>, and
- additionally, exit statuses and signals specified in
- <varname>SuccessExitStatus=</varname>. If set to
+ In this context, a clean exit means any of the following:
+ <itemizedlist>
+ <listitem><simpara>exit code of 0;</simpara></listitem>
+ <listitem><simpara>for types other than
+ <varname>Type=oneshot</varname>, one of the signals
+ <constant>SIGHUP</constant>,
+ <constant>SIGINT</constant>,
+ <constant>SIGTERM</constant>, or
+ <constant>SIGPIPE</constant>;</simpara></listitem>
+ <listitem><simpara>exit statuses and signals specified in
+ <varname>SuccessExitStatus=</varname>.</simpara></listitem>
+ </itemizedlist>
+ If set to
<option>on-failure</option>, the service will be restarted
when the process exits with a non-zero exit code, is
terminated by a signal (including on core dump, but excluding
@@ -798,7 +803,8 @@
<listitem><para>Takes a list of exit status definitions that,
when returned by the main service process, will be considered
successful termination, in addition to the normal successful
- exit code 0 and the signals <constant>SIGHUP</constant>,
+ exit code 0 and, except for <varname>Type=oneshot</varname>,
+ the signals <constant>SIGHUP</constant>,
<constant>SIGINT</constant>, <constant>SIGTERM</constant>, and
<constant>SIGPIPE</constant>. Exit status definitions can
either be numeric exit codes or termination signal names,

View File

@ -0,0 +1,42 @@
From 53673326ea78039b27e1dbd5328a8fe9a1a17445 Mon Sep 17 00:00:00 2001
From: d032747 <michael.trapp@sap.com>
Date: Tue, 15 Dec 2020 10:40:06 +0100
Subject: [PATCH] busctl: add a timestamp to the output of the busctl monitor
command
(cherry picked from commit 6fe2a70b9160e35fdeed9d37bd31727c2d46a8b2)
Resolves: #1909214
---
src/libsystemd/sd-bus/bus-dump.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
index 2bd06053a6..36f592e0ba 100644
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ b/src/libsystemd/sd-bus/bus-dump.c
@@ -55,6 +55,15 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
f = stdout;
if (flags & BUS_MESSAGE_DUMP_WITH_HEADER) {
+ char buf[FORMAT_TIMESTAMP_MAX];
+ const char *p;
+ usec_t ts = m->realtime;
+
+ if (ts == 0)
+ ts = now(CLOCK_REALTIME);
+
+ p = format_timestamp_us_utc(buf, sizeof(buf), ts);
+
fprintf(f,
"%s%s%s Type=%s%s%s Endian=%c Flags=%u Version=%u Priority=%"PRIi64,
m->header->type == SD_BUS_MESSAGE_METHOD_ERROR ? ansi_highlight_red() :
@@ -82,6 +91,8 @@ int bus_message_dump(sd_bus_message *m, FILE *f, unsigned flags) {
if (m->reply_cookie != 0)
fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie);
+ fprintf(f, " Timestamp=\"%s\"", strna(p));
+
fputs("\n", f);
if (m->sender)

View File

@ -0,0 +1,90 @@
From 240c55f1526300daac640ef2c1f4941de4579493 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Thu, 9 Jul 2020 23:15:47 +0200
Subject: [PATCH] basic/cap-list: parse/print numerical capabilities
We would refuse to print capabilities which were didn't have a name
for. The kernel adds new capabilities from time to time, most recently
cap_bpf. 'systmectl show -p CapabilityBoundingSet ...' would fail with
"Failed to parse bus message: Invalid argument" because
capability_set_to_string_alloc() would fail with -EINVAL. So let's
print such capabilities in hexadecimal:
CapabilityBoundingSet=cap_chown cap_dac_override cap_dac_read_search
cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap
cap_linux_immutable cap_net_bind_service cap_net_broadcast cap_net_admin
cap_net_raw cap_ipc_lock cap_ipc_owner 0x10 0x11 0x12 0x13 0x14 0x15 0x16
0x17 0x18 0x19 0x1a ...
For symmetry, also allow capabilities that we don't know to be specified.
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1853736.
(cherry picked from commit 417770f3033c426ca848b158d0bf057cd8ad1329)
Resolves: #1946943
---
src/basic/cap-list.c | 10 +++++++---
src/test/test-cap-list.c | 4 +++-
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c
index bfcda33520..56a81c7dfc 100644
--- a/src/basic/cap-list.c
+++ b/src/basic/cap-list.c
@@ -10,6 +10,7 @@
#include "macro.h"
#include "missing.h"
#include "parse-util.h"
+#include "stdio-util.h"
#include "util.h"
static const struct capability_name* lookup_capability(register const char *str, register GPERF_LEN_TYPE len);
@@ -37,7 +38,7 @@ int capability_from_name(const char *name) {
/* Try to parse numeric capability */
r = safe_atoi(name, &i);
if (r >= 0) {
- if (i >= 0 && i < (int) ELEMENTSOF(capability_names))
+ if (i >= 0 && i < 64)
return i;
else
return -EINVAL;
@@ -65,11 +66,14 @@ int capability_set_to_string_alloc(uint64_t set, char **s) {
for (i = 0; i < cap_last_cap(); i++)
if (set & (UINT64_C(1) << i)) {
const char *p;
+ char buf[2 + 16 + 1];
size_t add;
p = capability_to_name(i);
- if (!p)
- return -EINVAL;
+ if (!p) {
+ xsprintf(buf, "0x%lx", i);
+ p = buf;
+ }
add = strlen(p);
diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c
index de5fa729cc..84bbb7b7e7 100644
--- a/src/test/test-cap-list.c
+++ b/src/test/test-cap-list.c
@@ -30,6 +30,8 @@ static void test_cap_list(void) {
assert_se(capability_from_name("cAp_aUdIt_rEAd") == CAP_AUDIT_READ);
assert_se(capability_from_name("0") == 0);
assert_se(capability_from_name("15") == 15);
+ assert_se(capability_from_name("63") == 63);
+ assert_se(capability_from_name("64") == -EINVAL);
assert_se(capability_from_name("-1") == -EINVAL);
for (i = 0; i < capability_list_length(); i++) {
@@ -64,7 +66,7 @@ static void test_capability_set_one(uint64_t c, const char *t) {
free(t1);
assert_se(t1 = strjoin("'cap_chown cap_dac_override' \"cap_setgid cap_setuid\"", t,
- " hogehoge foobar 12345 3.14 -3 ", t));
+ " hogehoge foobar 18446744073709551616 3.14 -3 ", t));
assert_se(capability_set_from_string(t1, &c1) == 0);
assert_se(c1 == c_masked);
}

View File

@ -0,0 +1,318 @@
From ca634baa10e2249d4a706d59b67be764867e5f32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 30 Nov 2020 10:37:06 +0100
Subject: [PATCH] shared/mount-util: convert to libmount
It seems better to use just a single parsing algorithm for /proc/self/mountinfo.
Also, unify the naming of variables in all places that use mnt_table_next_fs().
It makes it easier to compare the different call sites.
(cherry picked from commit 13dcfe4661b467131c943620d0f44711798bfd54)
Related: #1885143
---
src/basic/mount-util.c | 133 ++++++++++++++++++-----------------------
src/core/mount.c | 22 +++----
src/core/umount.c | 14 ++---
3 files changed, 76 insertions(+), 93 deletions(-)
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 5b04e21f34..bac1a25cc8 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -13,7 +13,6 @@
#include <libmount.h>
#include "alloc-util.h"
-#include "escape.h"
#include "extract-word.h"
#include "fd-util.h"
#include "fileio.h"
@@ -27,6 +26,9 @@
#include "string-util.h"
#include "strv.h"
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_table*, mnt_free_table);
+DEFINE_TRIVIAL_CLEANUP_FUNC(struct libmnt_iter*, mnt_free_iter);
+
/* This is the original MAX_HANDLE_SZ definition from the kernel, when the API was introduced. We use that in place of
* any more currently defined value to future-proof things: if the size is increased in the API headers, and our code
* is recompiled then it would cease working on old kernels, as those refuse any sizes larger than this value with
@@ -313,55 +315,43 @@ int umount_recursive(const char *prefix, int flags) {
* unmounting them until they are gone. */
do {
- _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
+ _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+ _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
again = false;
- r = 0;
- proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
- if (!proc_self_mountinfo)
- return -errno;
+ table = mnt_new_table();
+ iter = mnt_new_iter(MNT_ITER_FORWARD);
+ if (!table || !iter)
+ return -ENOMEM;
- (void) __fsetlocking(proc_self_mountinfo, FSETLOCKING_BYCALLER);
+ r = mnt_table_parse_mtab(table, NULL);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m");
for (;;) {
- _cleanup_free_ char *path = NULL, *p = NULL;
- int k;
-
- k = fscanf(proc_self_mountinfo,
- "%*s " /* (1) mount id */
- "%*s " /* (2) parent id */
- "%*s " /* (3) major:minor */
- "%*s " /* (4) root */
- "%ms " /* (5) mount point */
- "%*s" /* (6) mount options */
- "%*[^-]" /* (7) optional fields */
- "- " /* (8) separator */
- "%*s " /* (9) file system type */
- "%*s" /* (10) mount source */
- "%*s" /* (11) mount options 2 */
- "%*[^\n]", /* some rubbish at the end */
- &path);
- if (k != 1) {
- if (k == EOF)
- break;
+ struct libmnt_fs *fs;
+ const char *path;
- continue;
- }
-
- r = cunescape(path, UNESCAPE_RELAX, &p);
+ r = mnt_table_next_fs(table, iter, &fs);
+ if (r == 1)
+ break;
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
- if (!path_startswith(p, prefix))
+ path = mnt_fs_get_target(fs);
+ if (!path)
continue;
- if (umount2(p, flags) < 0) {
- r = log_debug_errno(errno, "Failed to umount %s: %m", p);
+ if (!path_startswith(path, prefix))
+ continue;
+
+ if (umount2(path, flags) < 0) {
+ r = log_debug_errno(errno, "Failed to umount %s: %m", path);
continue;
}
- log_debug("Successfully unmounted %s", p);
+ log_debug("Successfully unmounted %s", path);
again = true;
n++;
@@ -416,6 +406,8 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
for (;;) {
_cleanup_set_free_free_ Set *todo = NULL;
+ _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+ _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
bool top_autofs = false;
char *x;
unsigned long orig_flags;
@@ -424,58 +416,52 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
if (!todo)
return -ENOMEM;
+ table = mnt_new_table();
+ iter = mnt_new_iter(MNT_ITER_FORWARD);
+ if (!table || !iter)
+ return -ENOMEM;
+
rewind(proc_self_mountinfo);
- for (;;) {
- _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL;
- int k;
-
- k = fscanf(proc_self_mountinfo,
- "%*s " /* (1) mount id */
- "%*s " /* (2) parent id */
- "%*s " /* (3) major:minor */
- "%*s " /* (4) root */
- "%ms " /* (5) mount point */
- "%*s" /* (6) mount options (superblock) */
- "%*[^-]" /* (7) optional fields */
- "- " /* (8) separator */
- "%ms " /* (9) file system type */
- "%*s" /* (10) mount source */
- "%*s" /* (11) mount options (bind mount) */
- "%*[^\n]", /* some rubbish at the end */
- &path,
- &type);
- if (k != 2) {
- if (k == EOF)
- break;
+ r = mnt_table_parse_stream(table, proc_self_mountinfo, "/proc/self/mountinfo");
+ if (r < 0)
+ return log_debug_errno(r, "Failed to parse /proc/self/mountinfo: %m");
- continue;
- }
+ for (;;) {
+ struct libmnt_fs *fs;
+ const char *path, *type;
- r = cunescape(path, UNESCAPE_RELAX, &p);
+ r = mnt_table_next_fs(table, iter, &fs);
+ if (r == 1)
+ break;
if (r < 0)
- return r;
+ return log_debug_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
+
+ path = mnt_fs_get_target(fs);
+ type = mnt_fs_get_fstype(fs);
+ if (!path || !type)
+ continue;
- if (!path_startswith(p, cleaned))
+ if (!path_startswith(path, cleaned))
continue;
- /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount we shall
- * operate on. */
- if (!path_equal(cleaned, p)) {
+ /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount
+ * we shall operate on. */
+ if (!path_equal(path, cleaned)) {
bool blacklisted = false;
char **i;
STRV_FOREACH(i, blacklist) {
-
if (path_equal(*i, cleaned))
continue;
if (!path_startswith(*i, cleaned))
continue;
- if (path_startswith(p, *i)) {
+ if (path_startswith(path, *i)) {
blacklisted = true;
- log_debug("Not remounting %s, because blacklisted by %s, called for %s", p, *i, cleaned);
+ log_debug("Not remounting %s blacklisted by %s, called for %s",
+ path, *i, cleaned);
break;
}
}
@@ -490,15 +476,12 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
* already triggered, then we will find
* another entry for this. */
if (streq(type, "autofs")) {
- top_autofs = top_autofs || path_equal(cleaned, p);
+ top_autofs = top_autofs || path_equal(path, cleaned);
continue;
}
- if (!set_contains(done, p)) {
- r = set_consume(todo, p);
- p = NULL;
- if (r == -EEXIST)
- continue;
+ if (!set_contains(done, path)) {
+ r = set_put_strdup(todo, path);
if (r < 0)
return r;
}
diff --git a/src/core/mount.c b/src/core/mount.c
index 076dfd06a3..7e80a0c974 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1606,18 +1606,18 @@ fail:
}
static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
- _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
- _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
- int r = 0;
+ _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+ _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
+ int r;
assert(m);
- t = mnt_new_table();
- i = mnt_new_iter(MNT_ITER_FORWARD);
- if (!t || !i)
+ table = mnt_new_table();
+ iter = mnt_new_iter(MNT_ITER_FORWARD);
+ if (!table || !iter)
return log_oom();
- r = mnt_table_parse_mtab(t, NULL);
+ r = mnt_table_parse_mtab(table, NULL);
if (r < 0)
return log_error_errno(r, "Failed to parse /proc/self/mountinfo: %m");
@@ -1628,11 +1628,11 @@ static int mount_load_proc_self_mountinfo(Manager *m, bool set_flags) {
_cleanup_free_ char *d = NULL, *p = NULL;
int k;
- k = mnt_table_next_fs(t, i, &fs);
- if (k == 1)
+ r = mnt_table_next_fs(table, iter, &fs);
+ if (r == 1)
break;
- if (k < 0)
- return log_error_errno(k, "Failed to get next entry from /proc/self/mountinfo: %m");
+ if (r < 0)
+ return log_error_errno(r, "Failed to get next entry from /proc/self/mountinfo: %m");
device = mnt_fs_get_source(fs);
path = mnt_fs_get_target(fs);
diff --git a/src/core/umount.c b/src/core/umount.c
index 241fe6fc62..3f02bf141a 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -55,18 +55,18 @@ void mount_points_list_free(MountPoint **head) {
}
int mount_points_list_get(const char *mountinfo, MountPoint **head) {
- _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
- _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
+ _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
+ _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
int r;
assert(head);
- t = mnt_new_table();
- i = mnt_new_iter(MNT_ITER_FORWARD);
- if (!t || !i)
+ table = mnt_new_table();
+ iter = mnt_new_iter(MNT_ITER_FORWARD);
+ if (!table || !iter)
return log_oom();
- r = mnt_table_parse_mtab(t, mountinfo);
+ r = mnt_table_parse_mtab(table, mountinfo);
if (r < 0)
return log_error_errno(r, "Failed to parse %s: %m", mountinfo);
@@ -79,7 +79,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
bool try_remount_ro;
MountPoint *m;
- r = mnt_table_next_fs(t, i, &fs);
+ r = mnt_table_next_fs(table, iter, &fs);
if (r == 1)
break;
if (r < 0)

View File

@ -0,0 +1,92 @@
From 996f88461c45e8620c5a8a0c958dc133bd02c50e Mon Sep 17 00:00:00 2001
From: Jakob Unterwurzacher <jakobunt@gmail.com>
Date: Mon, 30 Nov 2020 10:27:48 +0100
Subject: [PATCH] mount-util: bind_remount: avoid calling statvfs
The commit
"util: Do not clear parent mount flags when setting up namespaces"
introduced a statvfs call read the flags of the original mount
and have them applied to the bind mount.
This has two problems:
(1) The mount flags returned by statvfs(2) do not match the flags
accepted by mount(2). For example, the value 4096 means ST_RELATIME
when returned by statvfs(2), but means MS_BIND when passed to mount(2).
(2) A call to statvfs blocks indefinitely when ran against a disconnected
network drive ( https://github.com/systemd/systemd/issues/12667 ).
We already use libmount to parse `/proc/self/mountinfo` but did not use the
mount flag information from there. This patch changes that to use the mount
flags parsed by libmount instead of calling statvfs. Only if getting the
flags through libmount fails we call statvfs.
Fixes https://github.com/systemd/systemd/issues/12667
(cherry picked from commit d34a40082db3ffca8de66bfa4df50951101bdae5)
Resolves: #1885143
---
src/basic/mount-util.c | 31 +++++++++++++++++++++++++++----
1 file changed, 27 insertions(+), 4 deletions(-)
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index bac1a25cc8..2cf98eaa84 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -364,11 +364,34 @@ int umount_recursive(const char *prefix, int flags) {
return r ? r : n;
}
-static int get_mount_flags(const char *path, unsigned long *flags) {
- struct statvfs buf;
+/* Get the mount flags for the mountpoint at "path" from "table" */
+static int get_mount_flags(const char *path, unsigned long *flags, struct libmnt_table *table) {
+ struct statvfs buf = {};
+ struct libmnt_fs *fs = NULL;
+ const char *opts = NULL;
+ int r = 0;
+
+ fs = mnt_table_find_target(table, path, MNT_ITER_FORWARD);
+ if (fs == NULL) {
+ log_warning("Could not find '%s' in mount table", path);
+ goto fallback;
+ }
+
+ opts = mnt_fs_get_vfs_options(fs);
+ r = mnt_optstr_get_flags(opts, flags, mnt_get_builtin_optmap(MNT_LINUX_MAP));
+ if (r != 0) {
+ log_warning_errno(r, "Could not get flags for '%s': %m", path);
+ goto fallback;
+ }
+ /* relatime is default and trying to set it in an unprivileged container causes EPERM */
+ *flags &= ~MS_RELATIME;
+ return 0;
+
+fallback:
if (statvfs(path, &buf) < 0)
return -errno;
+
*flags = buf.f_flag;
return 0;
}
@@ -501,7 +524,7 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
return -errno;
orig_flags = 0;
- (void) get_mount_flags(cleaned, &orig_flags);
+ (void) get_mount_flags(cleaned, &orig_flags, table);
orig_flags &= ~MS_RDONLY;
if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)
@@ -535,7 +558,7 @@ int bind_remount_recursive_with_mountinfo(const char *prefix, bool ro, char **bl
/* Try to reuse the original flag set */
orig_flags = 0;
- (void) get_mount_flags(x, &orig_flags);
+ (void) get_mount_flags(x, &orig_flags, table);
orig_flags &= ~MS_RDONLY;
if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0)

View File

@ -0,0 +1,30 @@
From b6ffe7ec63d86c5ac66171d6731068b87e3e7b50 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Sat, 27 Jun 2020 11:13:01 +0200
Subject: [PATCH] mount-util: use UMOUNT_NOFOLLOW in recursive umounter
When we only want to unmount mount points below some path then it is
against our interest to follow symlinks. Hence don't.
(cherry picked from commit 827ea5212507c3833b6ae14cdf65e446b36b5e05)
Related: #1885143
---
src/basic/mount-util.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 2cf98eaa84..be26bb5ec1 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -346,8 +346,8 @@ int umount_recursive(const char *prefix, int flags) {
if (!path_startswith(path, prefix))
continue;
- if (umount2(path, flags) < 0) {
- r = log_debug_errno(errno, "Failed to umount %s: %m", path);
+ if (umount2(path, flags | UMOUNT_NOFOLLOW) < 0) {
+ log_debug_errno(errno, "Failed to umount %s: %m", path);
continue;
}

View File

@ -0,0 +1,29 @@
From 55cde82204724df756a198da691471f2f3f83d5a Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Wed, 31 Mar 2021 10:08:31 +0200
Subject: [PATCH] test-install-root: create referenced targets
(cherry picked from commit cd228002ccedb927b4531a4b7dd9ea7015fdb657)
Related: #1835351
---
src/test/test-install-root.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
index fe1ca5b16f..f8b41b04db 100644
--- a/src/test/test-install-root.c
+++ b/src/test/test-install-root.c
@@ -1061,6 +1061,12 @@ int main(int argc, char *argv[]) {
p = strjoina(root, "/usr/lib/systemd/system-preset/");
assert_se(mkdir_p(p, 0755) >= 0);
+ p = strjoina(root, "/usr/lib/systemd/system/multi-user.target");
+ assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
+ p = strjoina(root, "/usr/lib/systemd/system/graphical.target");
+ assert_se(write_string_file(p, "# pretty much empty", WRITE_STRING_FILE_CREATE) >= 0);
+
test_basic_mask_and_enable(root);
test_linked_units(root);
test_default(root);

View File

@ -0,0 +1,113 @@
From dfb4e03e0865d189a5c171072d6d7b31f49e1088 Mon Sep 17 00:00:00 2001
From: Jan Synacek <jsynacek@redhat.com>
Date: Wed, 3 Jun 2020 10:33:21 +0200
Subject: [PATCH] install: warn if WantedBy targets don't exist
Currently, if [Install] section contains WantedBy=target that doesn't exist,
systemd creates the symlinks anyway. That is just user-unfriendly.
Let's be nice and warn about installing non-existent targets.
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1835351.
Replaces: #15834
(cherry picked from commit 8ae27441c2dcf585f58242991302b09778d4d710)
Resolves: #1835351
---
src/shared/install.c | 25 ++++++++++++++++++-------
src/shared/install.h | 1 +
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/src/shared/install.c b/src/shared/install.c
index c9fef6bde2..055b09f98c 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -362,6 +362,11 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang
log_info("Unit %s is an alias to a unit that is not present, ignoring.",
changes[i].path);
break;
+ case UNIT_FILE_DESTINATION_NOT_PRESENT:
+ if (!quiet)
+ log_warning("Unit %s is added as a dependency to a non-existent unit %s.",
+ changes[i].source, changes[i].path);
+ break;
case -EEXIST:
if (changes[i].source)
log_error_errno(changes[i].type,
@@ -1730,6 +1735,7 @@ static int install_info_symlink_alias(
}
static int install_info_symlink_wants(
+ UnitFileScope scope,
UnitFileInstallInfo *i,
const LookupPaths *paths,
const char *config_path,
@@ -1795,6 +1801,9 @@ static int install_info_symlink_wants(
q = create_symlink(paths, i->path, path, true, changes, n_changes);
if (r == 0)
r = q;
+
+ if (unit_file_exists(scope, paths, dst) == 0)
+ unit_file_changes_add(changes, n_changes, UNIT_FILE_DESTINATION_NOT_PRESENT, dst, i->path);
}
return r;
@@ -1830,6 +1839,7 @@ static int install_info_symlink_link(
}
static int install_info_apply(
+ UnitFileScope scope,
UnitFileInstallInfo *i,
const LookupPaths *paths,
const char *config_path,
@@ -1848,11 +1858,11 @@ static int install_info_apply(
r = install_info_symlink_alias(i, paths, config_path, force, changes, n_changes);
- q = install_info_symlink_wants(i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
+ q = install_info_symlink_wants(scope, i, paths, config_path, i->wanted_by, ".wants/", changes, n_changes);
if (r == 0)
r = q;
- q = install_info_symlink_wants(i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
+ q = install_info_symlink_wants(scope, i, paths, config_path, i->required_by, ".requires/", changes, n_changes);
if (r == 0)
r = q;
@@ -1916,7 +1926,7 @@ static int install_context_apply(
if (i->type != UNIT_FILE_TYPE_REGULAR)
continue;
- q = install_info_apply(i, paths, config_path, force, changes, n_changes);
+ q = install_info_apply(scope, i, paths, config_path, force, changes, n_changes);
if (r >= 0) {
if (q < 0)
r = q;
@@ -3324,10 +3334,11 @@ static const char* const unit_file_state_table[_UNIT_FILE_STATE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(unit_file_state, UnitFileState);
static const char* const unit_file_change_type_table[_UNIT_FILE_CHANGE_TYPE_MAX] = {
- [UNIT_FILE_SYMLINK] = "symlink",
- [UNIT_FILE_UNLINK] = "unlink",
- [UNIT_FILE_IS_MASKED] = "masked",
- [UNIT_FILE_IS_DANGLING] = "dangling",
+ [UNIT_FILE_SYMLINK] = "symlink",
+ [UNIT_FILE_UNLINK] = "unlink",
+ [UNIT_FILE_IS_MASKED] = "masked",
+ [UNIT_FILE_IS_DANGLING] = "dangling",
+ [UNIT_FILE_DESTINATION_NOT_PRESENT] = "destination not present",
};
DEFINE_STRING_TABLE_LOOKUP(unit_file_change_type, UnitFileChangeType);
diff --git a/src/shared/install.h b/src/shared/install.h
index e452940991..f07bebb415 100644
--- a/src/shared/install.h
+++ b/src/shared/install.h
@@ -57,6 +57,7 @@ enum UnitFileChangeType {
UNIT_FILE_UNLINK,
UNIT_FILE_IS_MASKED,
UNIT_FILE_IS_DANGLING,
+ UNIT_FILE_DESTINATION_NOT_PRESENT,
_UNIT_FILE_CHANGE_TYPE_MAX,
_UNIT_FILE_CHANGE_TYPE_INVALID = INT_MIN
};

View File

@ -0,0 +1,56 @@
From 430445a936cdb4c32c55affdfdd94b7eb910d5e6 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Wed, 31 Mar 2021 10:38:00 +0200
Subject: [PATCH] test-install-root: add test for unknown WantedBy= target
(cherry picked from commit 8adbad370f522831dd9246fe272caf37ce748d4a)
Related: #1835351
---
src/test/test-install-root.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c
index f8b41b04db..73e1e0ae03 100644
--- a/src/test/test-install-root.c
+++ b/src/test/test-install-root.c
@@ -20,6 +20,7 @@ static void test_basic_mask_and_enable(const char *root) {
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", NULL) == -ENOENT);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", NULL) == -ENOENT);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "f.service", NULL) == -ENOENT);
p = strjoina(root, "/usr/lib/systemd/system/a.service");
assert_se(write_string_file(p,
@@ -147,6 +148,31 @@ static void test_basic_mask_and_enable(const char *root) {
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "b.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "c.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "d.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
+
+ /* Test enabling with unknown dependency target */
+
+ p = strjoina(root, "/usr/lib/systemd/system/f.service");
+ assert_se(write_string_file(p,
+ "[Install]\n"
+ "WantedBy=x.target\n", WRITE_STRING_FILE_CREATE) >= 0);
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "f.service", NULL) >= 0);
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "f.service", &state) >= 0 && state == UNIT_FILE_DISABLED);
+
+ assert_se(unit_file_enable(UNIT_FILE_SYSTEM, 0, root, STRV_MAKE("f.service"), &changes, &n_changes) == 1);
+ assert_se(n_changes == 2);
+ assert_se(changes[0].type == UNIT_FILE_SYMLINK);
+ assert_se(streq(changes[0].source, "/usr/lib/systemd/system/f.service"));
+ p = strjoina(root, SYSTEM_CONFIG_UNIT_PATH"/x.target.wants/f.service");
+ assert_se(streq(changes[0].path, p));
+ assert_se(changes[1].type == UNIT_FILE_DESTINATION_NOT_PRESENT);
+ p = strjoina(root, "/usr/lib/systemd/system/f.service");
+ assert_se(streq(changes[1].source, p));
+ assert_se(streq(changes[1].path, "x.target"));
+ unit_file_changes_free(changes, n_changes);
+ changes = NULL; n_changes = 0;
+
+ assert_se(unit_file_get_state(UNIT_FILE_SYSTEM, root, "f.service", &state) >= 0 && state == UNIT_FILE_ENABLED);
}
static void test_linked_units(const char *root) {

View File

@ -0,0 +1,24 @@
From d284fd2b036ed874f9f38da63f1ab4e9fd9e96a3 Mon Sep 17 00:00:00 2001
From: Jonas Jelten <jj@sft.mx>
Date: Thu, 17 Oct 2019 12:10:13 +0200
Subject: [PATCH] ceph is a network filesystem
(cherry picked from commit c4742de6d801b125abf3c4d1c710280f51d7c701)
Resolves: #1952013
---
src/basic/mount-util.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index be26bb5ec1..45348bf878 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -608,6 +608,7 @@ bool fstype_is_network(const char *fstype) {
return STR_IN_SET(fstype,
"afs",
+ "ceph",
"cifs",
"smb3",
"smbfs",

View File

@ -0,0 +1,49 @@
From 8bdc512d2651b4600f7e744b06633a7524b64346 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 12 Oct 2020 16:31:42 +0200
Subject: [PATCH] sysctl: set kernel.core_pipe_limit=16
We need to make sure that our coredump pattern handler manages to read
process metadata from /proc/$PID/ before the kernel reaps the crashed
process. By default the kernel will reap the process as soon as it can.
By setting kernel.core_pipe_limit to a non-zero the kernel will wait for
userspace to finish before reaping.
We'll set the value to 16, which allows 16 crashes to be
processed in parallel. This matches the MaxConnections= setting in
systemd-coredump.socket.
See: #17301
(This doesn't close 17301, since we probably should also gracefully
handle if /proc/$PID/ vanished already while our coredump handler runs,
just in case people loclly set the sysctl back to zero. i.e. we should
collect what we can and rather issue an incomplete log record than
none.)
(cherry picked from commit 2a9b9323cd844baae3229e9dba67e478bee70654)
Resolves: #1949729
---
sysctl.d/50-coredump.conf.in | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in
index ccd5c2cc56..8d6fbb718c 100644
--- a/sysctl.d/50-coredump.conf.in
+++ b/sysctl.d/50-coredump.conf.in
@@ -10,3 +10,14 @@
# setting below.
kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %c %h %e
+
+# Allow that 16 coredumps are dispatched in parallel by the kernel. We want to
+# be able to collect process metadata from /proc/%P/ while processing
+# coredumps, and thus need to make sure the crashed processes are not reaped
+# until we finished collecting what we need. The kernel default for this sysctl
+# is "0" which means the kernel doesn't wait for userspace processes to finish
+# processing before reaping the crashed processes — by setting this higher the
+# kernel will delay reaping until we are done, but only for the specified
+# number of crashes in parallel. The value of 16 is chosen to match
+# systemd-coredump.socket's MaxConnections= value.
+kernel.core_pipe_limit=16

View File

@ -0,0 +1,116 @@
From 73bf41a783edbff1b367e645956ed602de1889e2 Mon Sep 17 00:00:00 2001
From: Insun <iplayinsun@gmail.com>
Date: Sun, 28 Oct 2018 21:26:13 +0900
Subject: [PATCH] core: don't drop timer expired but not yet processed when
system date is changed
There is difference between time set by the user and real elapsed time because of accuracy feature.
If you change the system date(or time) between these times, the timer drops.
You can easily reproduce it with the following command.
-----------------------------------------------------------
$ systemd-run --on-active=3s ls; sleep 3; date -s "`date`"
-----------------------------------------------------------
In the following command, the problem is rarely reproduced. But it exists.
---------------------------------------------------------------------------------------------
$ systemd-run --on-active=3s --timer-property=AccuracySec=1us ls ; sleep 1; date -s "`date`"
---------------------------------------------------------------------------------------------
Note : Global AccuracySec value.
----------------------------------------------------------------------
$ cat /etc/systemd/system.conf
DefaultTimerAccuracySec=1min
----------------------------------------------------------------------
(cherry picked from commit fee04d7f3ab810e99b97535ca5fda2f9517acda9)
Related: #1899402
---
src/core/timer.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/core/timer.c b/src/core/timer.c
index 281ac7f97f..ef240a6f19 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -262,7 +262,7 @@ static void timer_set_state(Timer *t, TimerState state) {
unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
}
-static void timer_enter_waiting(Timer *t, bool initial);
+static void timer_enter_waiting(Timer *t, bool initial, bool time_change);
static int timer_coldplug(Unit *u) {
Timer *t = TIMER(u);
@@ -274,7 +274,7 @@ static int timer_coldplug(Unit *u) {
return 0;
if (t->deserialized_state == TIMER_WAITING)
- timer_enter_waiting(t, false);
+ timer_enter_waiting(t, false, false);
else
timer_set_state(t, t->deserialized_state);
@@ -334,7 +334,7 @@ static void add_random(Timer *t, usec_t *v) {
log_unit_debug(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
}
-static void timer_enter_waiting(Timer *t, bool initial) {
+static void timer_enter_waiting(Timer *t, bool initial, bool time_change) {
bool found_monotonic = false, found_realtime = false;
bool leave_around = false;
triple_timestamp ts;
@@ -444,7 +444,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
v->next_elapse = usec_add(usec_shift_clock(base, CLOCK_MONOTONIC, TIMER_MONOTONIC_CLOCK(t)), v->value);
- if (!initial &&
+ if (!initial && !time_change &&
v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)) &&
IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
/* This is a one time trigger, disable it now */
@@ -642,7 +642,7 @@ static int timer_start(Unit *u) {
}
t->result = TIMER_SUCCESS;
- timer_enter_waiting(t, true);
+ timer_enter_waiting(t, true, false);
return 1;
}
@@ -764,14 +764,14 @@ static void timer_trigger_notify(Unit *u, Unit *other) {
case TIMER_ELAPSED:
/* Recalculate sleep time */
- timer_enter_waiting(t, false);
+ timer_enter_waiting(t, false, false);
break;
case TIMER_RUNNING:
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
log_unit_debug(UNIT(t), "Got notified about unit deactivation.");
- timer_enter_waiting(t, false);
+ timer_enter_waiting(t, false, false);
}
break;
@@ -813,7 +813,7 @@ static void timer_time_change(Unit *u) {
t->last_trigger.realtime = ts;
log_unit_debug(u, "Time change, recalculating next elapse.");
- timer_enter_waiting(t, false);
+ timer_enter_waiting(t, false, true);
}
static void timer_timezone_change(Unit *u) {
@@ -825,7 +825,7 @@ static void timer_timezone_change(Unit *u) {
return;
log_unit_debug(u, "Timezone change, recalculating next elapse.");
- timer_enter_waiting(t, false);
+ timer_enter_waiting(t, false, false);
}
static const char* const timer_base_table[_TIMER_BASE_MAX] = {

View File

@ -0,0 +1,152 @@
From 3d4280d0a487109f8f648147083baf573e4418a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Koutn=C3=BD?= <mkoutny@suse.com>
Date: Fri, 2 Nov 2018 20:56:08 +0100
Subject: [PATCH] core: Detect initial timer state from serialized data
We keep a mark whether a single-shot timer was triggered in the caller's
variable initial. When such a timer elapses while we are
serializing/deserializing the inner state, we consider the timer
incorrectly as elapsed and don't trigger it later.
This patch exploits last_trigger timestamp that we already serialize,
hence we can eliminate the argument initial completely.
A reproducer for OnBootSec= timers:
cat >repro.c <<EOD
/*
* Compile: gcc repro.c -o repro
* Run: ./repro
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
char command[1024];
int pause;
struct timespec now;
while (1) {
usleep(rand() % 200000); // prevent periodic repeats
clock_gettime(CLOCK_MONOTONIC, &now);
printf("%i\n", now.tv_sec);
system("rm -f $PWD/mark");
snprintf(command, 1024, "systemd-run --user --on-boot=%i --timer-property=AccuracySec=100ms "
"touch $PWD/mark", now.tv_sec + 1);
system(command);
system("systemctl --user list-timers");
pause = (1000000000 - now.tv_nsec)/1000 - 70000; // fiddle to hit the middle of reloading
usleep(pause > 0 ? pause : 0);
system("systemctl --user daemon-reload");
sync();
sleep(2);
if (open("./mark", 0) < 0)
if (errno == ENOENT) {
printf("mark file does not exist\n");
break;
}
}
return 0;
}
EOD
(cherry picked from commit aa1f95d2647197eca84c33a0f10adaeada08467d)
Resolves: #1899402
---
src/core/timer.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/core/timer.c b/src/core/timer.c
index ef240a6f19..1718ffc5a5 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -262,7 +262,7 @@ static void timer_set_state(Timer *t, TimerState state) {
unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], 0);
}
-static void timer_enter_waiting(Timer *t, bool initial, bool time_change);
+static void timer_enter_waiting(Timer *t, bool time_change);
static int timer_coldplug(Unit *u) {
Timer *t = TIMER(u);
@@ -274,7 +274,7 @@ static int timer_coldplug(Unit *u) {
return 0;
if (t->deserialized_state == TIMER_WAITING)
- timer_enter_waiting(t, false, false);
+ timer_enter_waiting(t, false);
else
timer_set_state(t, t->deserialized_state);
@@ -334,7 +334,7 @@ static void add_random(Timer *t, usec_t *v) {
log_unit_debug(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
}
-static void timer_enter_waiting(Timer *t, bool initial, bool time_change) {
+static void timer_enter_waiting(Timer *t, bool time_change) {
bool found_monotonic = false, found_realtime = false;
bool leave_around = false;
triple_timestamp ts;
@@ -444,7 +444,8 @@ static void timer_enter_waiting(Timer *t, bool initial, bool time_change) {
v->next_elapse = usec_add(usec_shift_clock(base, CLOCK_MONOTONIC, TIMER_MONOTONIC_CLOCK(t)), v->value);
- if (!initial && !time_change &&
+ if (dual_timestamp_is_set(&t->last_trigger) &&
+ !time_change &&
v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)) &&
IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
/* This is a one time trigger, disable it now */
@@ -642,7 +643,7 @@ static int timer_start(Unit *u) {
}
t->result = TIMER_SUCCESS;
- timer_enter_waiting(t, true, false);
+ timer_enter_waiting(t, false);
return 1;
}
@@ -764,14 +765,14 @@ static void timer_trigger_notify(Unit *u, Unit *other) {
case TIMER_ELAPSED:
/* Recalculate sleep time */
- timer_enter_waiting(t, false, false);
+ timer_enter_waiting(t, false);
break;
case TIMER_RUNNING:
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
log_unit_debug(UNIT(t), "Got notified about unit deactivation.");
- timer_enter_waiting(t, false, false);
+ timer_enter_waiting(t, false);
}
break;
@@ -813,7 +814,7 @@ static void timer_time_change(Unit *u) {
t->last_trigger.realtime = ts;
log_unit_debug(u, "Time change, recalculating next elapse.");
- timer_enter_waiting(t, false, true);
+ timer_enter_waiting(t, true);
}
static void timer_timezone_change(Unit *u) {
@@ -825,7 +826,7 @@ static void timer_timezone_change(Unit *u) {
return;
log_unit_debug(u, "Timezone change, recalculating next elapse.");
- timer_enter_waiting(t, false, false);
+ timer_enter_waiting(t, false);
}
static const char* const timer_base_table[_TIMER_BASE_MAX] = {

View File

@ -0,0 +1,29 @@
From 8cd99937562cde7533519303a7a0ad1df749e075 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Thu, 11 Mar 2021 15:48:23 +0100
Subject: [PATCH] rc-local: order after network-online.target
I think this was the intent of commit 91b684c7300879a8d2006038f7d9185d92c3c3bf,
just network-online.target didn't exist back then.
RHEL-only
Resolves: #1934028
---
units/rc-local.service.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/units/rc-local.service.in b/units/rc-local.service.in
index 78ce69e0ae..74e83d8c07 100644
--- a/units/rc-local.service.in
+++ b/units/rc-local.service.in
@@ -13,7 +13,8 @@
Description=@RC_LOCAL_SCRIPT_PATH_START@ Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=@RC_LOCAL_SCRIPT_PATH_START@
-After=network.target
+After=network-online.target
+Wants=network-online.target
[Service]
Type=forking

View File

@ -0,0 +1,25 @@
From 830bd662276ee117e65a4b3d541f77e8b172eafd Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Mon, 25 Jan 2021 16:19:56 +0100
Subject: [PATCH] set core ulimit to 0 like on RHEL-7
RHEL-only
Resolves: #1905582
---
src/core/system.conf.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/system.conf.in b/src/core/system.conf.in
index 0d93fbf147..b4d6dfa15a 100644
--- a/src/core/system.conf.in
+++ b/src/core/system.conf.in
@@ -52,7 +52,7 @@
#DefaultLimitFSIZE=
#DefaultLimitDATA=
#DefaultLimitSTACK=
-#DefaultLimitCORE=
+DefaultLimitCORE=0
#DefaultLimitRSS=
#DefaultLimitNOFILE=
#DefaultLimitAS=

View File

@ -0,0 +1,129 @@
From 4ad39b0531f550cde6e01df0801f177c08514c8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 14 Sep 2020 17:58:03 +0200
Subject: [PATCH] test-mountpointutil-util: do not assert in test_mnt_id()
https://bugzilla.redhat.com/show_bug.cgi?id=1803070
I *think* this a kernel bug: the mnt_id as listed in /proc/self/mountinfo is different
than the one we get from /proc/self/fdinfo/. This only matters when both statx and
name_to_handle_at are unavailable and we hit the fallback path that goes through fdinfo:
(gdb) !uname -r
5.6.19-200.fc31.ppc64le
(gdb) !cat /proc/self/mountinfo
697 664 253:0 /var/lib/mock/fedora-31-ppc64le/root / rw,relatime shared:298 master:1 - xfs /dev/mapper/fedora_rh--power--vm14-root rw,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota
698 697 253:0 /var/cache/mock/fedora-31-ppc64le/yum_cache /var/cache/yum rw,relatime shared:299 master:1 - xfs /dev/mapper/fedora_rh--power--vm14-root rw,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota
699 697 253:0 /var/cache/mock/fedora-31-ppc64le/dnf_cache /var/cache/dnf rw,relatime shared:300 master:1 - xfs /dev/mapper/fedora_rh--power--vm14-root rw,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota
700 697 0:32 /mock-selinux-plugin.7me9bfpi /proc/filesystems rw,nosuid,nodev shared:301 master:18 - tmpfs tmpfs rw,seclabel <==========================================================
701 697 0:41 / /sys ro,nosuid,nodev,noexec,relatime shared:302 - sysfs sysfs ro,seclabel
702 701 0:21 / /sys/fs/selinux ro,nosuid,nodev,noexec,relatime shared:306 master:8 - selinuxfs selinuxfs rw
703 697 0:42 / /dev rw,nosuid shared:303 - tmpfs tmpfs rw,seclabel,mode=755
704 703 0:43 / /dev/shm rw,nosuid,nodev shared:304 - tmpfs tmpfs rw,seclabel
705 703 0:45 / /dev/pts rw,nosuid,noexec,relatime shared:307 - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=666
706 703 0:6 /btrfs-control /dev/btrfs-control rw,nosuid shared:308 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
707 703 0:6 /loop-control /dev/loop-control rw,nosuid shared:309 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
708 703 0:6 /loop0 /dev/loop0 rw,nosuid shared:310 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
709 703 0:6 /loop1 /dev/loop1 rw,nosuid shared:311 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
710 703 0:6 /loop10 /dev/loop10 rw,nosuid shared:312 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
711 703 0:6 /loop11 /dev/loop11 rw,nosuid shared:313 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
712 703 0:6 /loop2 /dev/loop2 rw,nosuid shared:314 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
713 703 0:6 /loop3 /dev/loop3 rw,nosuid shared:315 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
714 703 0:6 /loop4 /dev/loop4 rw,nosuid shared:316 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
715 703 0:6 /loop5 /dev/loop5 rw,nosuid shared:317 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
716 703 0:6 /loop6 /dev/loop6 rw,nosuid shared:318 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
717 703 0:6 /loop7 /dev/loop7 rw,nosuid shared:319 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
718 703 0:6 /loop8 /dev/loop8 rw,nosuid shared:320 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
719 703 0:6 /loop9 /dev/loop9 rw,nosuid shared:321 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755
720 697 0:44 / /run rw,nosuid,nodev shared:305 - tmpfs tmpfs rw,seclabel,mode=755
721 720 0:25 /systemd/nspawn/propagate/9cc8a155d0244558b273f773d2b92142 /run/systemd/nspawn/incoming ro master:12 - tmpfs tmpfs rw,seclabel,mode=755
722 697 0:32 /mock-resolv.dvml91hp /etc/resolv.conf rw,nosuid,nodev shared:322 master:18 - tmpfs tmpfs rw,seclabel
725 697 0:47 / /proc rw,nosuid,nodev,noexec,relatime shared:323 - proc proc rw
603 725 0:47 /sys /proc/sys ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw
604 725 0:44 /systemd/inaccessible/reg /proc/kallsyms ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755
605 725 0:44 /systemd/inaccessible/reg /proc/kcore ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755
606 725 0:44 /systemd/inaccessible/reg /proc/keys ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755
607 725 0:44 /systemd/inaccessible/reg /proc/sysrq-trigger ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755
608 725 0:44 /systemd/inaccessible/reg /proc/timer_list ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755
609 725 0:47 /bus /proc/bus ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw
610 725 0:47 /fs /proc/fs ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw
611 725 0:47 /irq /proc/irq ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw
612 725 0:47 /scsi /proc/scsi ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw
613 703 0:46 / /dev/mqueue rw,nosuid,nodev,noexec,relatime shared:324 - mqueue mqueue rw,seclabel
614 701 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:325 - cgroup2 cgroup rw,seclabel,nsdelegate
615 603 0:44 /.#proc-sys-kernel-random-boot-id4fbdce67af46d1c2//deleted /proc/sys/kernel/random/boot_id ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755
616 725 0:44 /.#proc-sys-kernel-random-boot-id4fbdce67af46d1c2//deleted /proc/sys/kernel/random/boot_id rw,nosuid,nodev shared:305 - tmpfs tmpfs rw,seclabel,mode=755
617 725 0:44 /.#proc-kmsg5b7a8bcfe6717139//deleted /proc/kmsg rw,nosuid,nodev shared:305 - tmpfs tmpfs rw,seclabel,mode=755
The test process does
name_to_handle_at("/proc/filesystems") which returns -EOPNOTSUPP, and then
openat(AT_FDCWD, "/proc/filesystems") which returns 4, and then
read(open("/proc/self/fdinfo/4", ...)) which gives
"pos:\t0\nflags:\t012100000\nmnt_id:\t725\n"
and the "725" is clearly inconsistent with "700" in /proc/self/mountinfo.
We could either drop the fallback path (and fail name_to_handle_at() is not
avaliable) or ignore the error in the test. Not sure what is better. I think
this issue only occurs sometimes and with older kernels, so probably continuing
with the current flaky implementation is better than ripping out the fallback.
Another strace:
writev(2</dev/pts/0>, [{iov_base="mnt ids of /proc/sys is 603", iov_len=27}, {iov_base="\n", iov_len=1}], 2mnt ids of /proc/sys is 603
) = 28
name_to_handle_at(AT_FDCWD, "/", {handle_bytes=128 => 12, handle_type=129, f_handle=0x52748401000000008b93e20d}, [697], 0) = 0
writev(2</dev/pts/0>, [{iov_base="mnt ids of / is 697", iov_len=19}, {iov_base="\n", iov_len=1}], 2mnt ids of / is 697
) = 20
name_to_handle_at(AT_FDCWD, "/proc/kcore", {handle_bytes=128 => 12, handle_type=1, f_handle=0x92ddcfcd2e802d0100000000}, [605], 0) = 0
writev(2</dev/pts/0>, [{iov_base="mnt ids of /proc/kcore is 605", iov_len=29}, {iov_base="\n", iov_len=1}], 2mnt ids of /proc/kcore is 605
) = 30
name_to_handle_at(AT_FDCWD, "/dev", {handle_bytes=128 => 12, handle_type=1, f_handle=0x8ae269160c802d0100000000}, [703], 0) = 0
writev(2</dev/pts/0>, [{iov_base="mnt ids of /dev is 703", iov_len=22}, {iov_base="\n", iov_len=1}], 2mnt ids of /dev is 703
) = 23
name_to_handle_at(AT_FDCWD, "/proc/filesystems", {handle_bytes=128}, 0x7fffe36ddb84, 0) = -1 EOPNOTSUPP (Operation not supported)
openat(AT_FDCWD, "/proc/filesystems", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 4</proc/filesystems>
openat(AT_FDCWD, "/proc/self/fdinfo/4", O_RDONLY|O_CLOEXEC) = 5</proc/20/fdinfo/4>
fstat(5</proc/20/fdinfo/4>, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
fstat(5</proc/20/fdinfo/4>, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0
read(5</proc/20/fdinfo/4>, "pos:\t0\nflags:\t012100000\nmnt_id:\t725\n", 2048) = 36
read(5</proc/20/fdinfo/4>, "", 1024) = 0
close(5</proc/20/fdinfo/4>) = 0
close(4</proc/filesystems>) = 0
writev(2</dev/pts/0>, [{iov_base="mnt ids of /proc/filesystems are 700, 725", iov_len=41}, {iov_base="\n", iov_len=1}], 2mnt ids of /proc/filesystems are 700, 725
) = 42
writev(2</dev/pts/0>, [{iov_base="the other path for mnt id 725 is /proc", iov_len=38}, {iov_base="\n", iov_len=1}], 2the other path for mnt id 725 is /proc
) = 39
writev(2</dev/pts/0>, [{iov_base="Assertion 'path_equal(p, t)' failed at src/test/test-mountpoint-util.c:94, function test_mnt_id(). Aborting.", iov_len=108}, {iov_base="\n", iov_len=1}], 2Assertion 'path_equal(p, t)' failed at src/test/test-mountpoint-util.c:94, function test_mnt_id(). Aborting.
) = 109
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
getpid() = 20
gettid() = 20
tgkill(20, 20, SIGABRT) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
Resolves: #1910425
---
src/test/test-mount-util.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c
index c10e1681fb..991d165fc3 100644
--- a/src/test/test-mount-util.c
+++ b/src/test/test-mount-util.c
@@ -74,7 +74,13 @@ static void test_mnt_id(void) {
/* The ids don't match? If so, then there are two mounts on the same path, let's check if that's really
* the case */
- assert_se(path_equal_ptr(hashmap_get(h, INT_TO_PTR(mnt_id2)), p));
+ char *t = hashmap_get(h, INT_TO_PTR(mnt_id2));
+ log_debug("Path for mnt id %i from /proc/self/mountinfo is %s\n", mnt_id2, t);
+
+ if (!path_equal(p, t))
+ /* Apparent kernel bug in /proc/self/fdinfo */
+ log_warning("Bad mount id given for %s: %d, should be %d",
+ p, mnt_id2, mnt_id);
}
hashmap_free_free(h);

View File

@ -0,0 +1,29 @@
From 5944138a54017fc8f1f4c878a1eea96ea18736c4 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Fri, 25 Jun 2021 10:42:53 +0200
Subject: [PATCH] remove a left-over break
By the "same logic as above...", we want to continue to fallback here,
but the break prohibits that.
This is a follow-up for ee1aa61c4710ae567a2b844e0f0bb8cb0456ab8c .
(cherry picked from commit 99df1cb6f50875db513a5b45f18191460a150f3d)
Related: #1970860
---
src/basic/copy.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/basic/copy.c b/src/basic/copy.c
index a48c42c5c6..1a0db29ac9 100644
--- a/src/basic/copy.c
+++ b/src/basic/copy.c
@@ -218,7 +218,6 @@ int copy_bytes_full(
break;
try_sendfile = try_splice = false; /* same logic as above for copy_file_range() */
- break;
} else
/* Success! */
goto next;

View File

@ -1,4 +1,4 @@
From df7a2c629e700a510ce59b8745d240d2a43a12aa Mon Sep 17 00:00:00 2001
From c5d2964d498da0ac06799e5f040de74a0f5d2deb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 23 Jun 2021 11:46:41 +0200
Subject: [PATCH] basic/unit-name: do not use strdupa() on a path
@ -19,12 +19,16 @@ simplification, which in turns uses a copy of the string we can write to.
So we can't reject paths that are too long before doing the duplication.
Hence the most obvious solution is to switch back to strdup(), as before
7410616cd9dbbec97cf98d75324da5cda2b2f7a2.
Resolves: #1974700
(cherry picked from commit 441e0115646d54f080e5c3bb0ba477c892861ab9)
---
src/basic/unit-name.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c
index 1b81fe2..614eb86 100644
index 1b81fe268f..614eb8649b 100644
--- a/src/basic/unit-name.c
+++ b/src/basic/unit-name.c
@@ -369,12 +369,13 @@ int unit_name_unescape(const char *f, char **ret) {
@ -59,6 +63,3 @@ index 1b81fe2..614eb86 100644
}
if (!s)
return -ENOMEM;
--
2.31.1

View File

@ -0,0 +1,96 @@
From f863f89d8a5cbb47676d5114e349918c4e009fe5 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 8 Jun 2021 00:07:51 -0700
Subject: [PATCH] sd-event: change ordering of pending/ratelimited events
Instead of ordering non-pending before pending we should order
"non-pending OR ratelimited" before "pending AND not-ratelimited".
This fixes a bug where ratelimited events were ordered at the end of the
priority queue and could be stuck there for an indeterminate amount of
time.
(cherry picked from commit 81107b8419c39f726fd2805517a5b9faab204e59)
Related: #1968528
---
src/libsystemd/sd-event/sd-event.c | 48 +++++++++++++-----------------
1 file changed, 20 insertions(+), 28 deletions(-)
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index be912d94e3..3e77f4e810 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -427,25 +427,6 @@ static usec_t time_event_source_next(const sd_event_source *s) {
return USEC_INFINITY;
}
-static int earliest_time_prioq_compare(const void *a, const void *b) {
- const sd_event_source *x = a, *y = b;
-
- /* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
-
- /* Move the pending ones to the end */
- if (!x->pending && y->pending)
- return -1;
- if (x->pending && !y->pending)
- return 1;
-
- /* Order by time */
- return CMP(time_event_source_next(x), time_event_source_next(y));
-}
-
static usec_t time_event_source_latest(const sd_event_source *s) {
assert(s);
@@ -464,7 +445,15 @@ static usec_t time_event_source_latest(const sd_event_source *s) {
return USEC_INFINITY;
}
-static int latest_time_prioq_compare(const void *a, const void *b) {
+static bool event_source_timer_candidate(const sd_event_source *s) {
+ assert(s);
+
+ /* Returns true for event sources that either are not pending yet (i.e. where it's worth to mark them pending)
+ * or which are currently ratelimited (i.e. where it's worth leaving the ratelimited state) */
+ return !s->pending || s->ratelimited;
+}
+
+static int time_prioq_compare(const void *a, const void *b, usec_t (*time_func)(const sd_event_source *s)) {
const sd_event_source *x = a, *y = b;
/* Enabled ones first */
@@ -473,19 +462,22 @@ static int latest_time_prioq_compare(const void *a, const void *b) {
if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
return 1;
- /* Move the pending ones to the end */
- if (!x->pending && y->pending)
+ /* Order "non-pending OR ratelimited" before "pending AND not-ratelimited" */
+ if (event_source_timer_candidate(x) && !event_source_timer_candidate(y))
return -1;
- if (x->pending && !y->pending)
+ if (!event_source_timer_candidate(x) && event_source_timer_candidate(y))
return 1;
/* Order by time */
- if (time_event_source_latest(x) < time_event_source_latest(y))
- return -1;
- if (time_event_source_latest(x) > time_event_source_latest(y))
- return 1;
+ return CMP(time_func(x), time_func(y));
+}
- return 0;
+static int earliest_time_prioq_compare(const void *a, const void *b) {
+ return time_prioq_compare(a, b, time_event_source_next);
+}
+
+static int latest_time_prioq_compare(const void *a, const void *b) {
+ return time_prioq_compare(a, b, time_event_source_latest);
}
static int exit_prioq_compare(const void *a, const void *b) {

View File

@ -0,0 +1,27 @@
From 9faf4d1a39b7fc8c9f986a808e1c0d3ed9b44357 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 15 Jun 2021 00:44:04 +0900
Subject: [PATCH] sd-event: drop unnecessary "else"
(cherry picked from commit 7e2bf71ca3638e36ee33215ceee386ba8013da6d)
Related: #1968528
---
src/libsystemd/sd-event/sd-event.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index 3e77f4e810..2b0b76aa1c 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -2883,8 +2883,8 @@ static int event_arm_timer(
if (!d->needs_rearm)
return 0;
- else
- d->needs_rearm = false;
+
+ d->needs_rearm = false;
a = prioq_peek(d->earliest);
if (!a || a->enabled == SD_EVENT_OFF || time_event_source_next(a) == USEC_INFINITY) {

View File

@ -0,0 +1,90 @@
From 7419222d3811d60c0a8f5ea27778108a1ca8ee71 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 15 Jun 2021 00:51:33 +0900
Subject: [PATCH] sd-event: use CMP() macro
(cherry picked from commit 06e131477d82b83c5d516e66d6e413affd7c774a)
Related: #1968528
---
src/libsystemd/sd-event/sd-event.c | 37 ++++++++++++++----------------
1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index 2b0b76aa1c..6a20b658e4 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -358,10 +358,9 @@ static int pending_prioq_compare(const void *a, const void *b) {
assert(y->pending);
/* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
+ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF);
+ if (r != 0)
+ return r;
/* Non rate-limited ones first. */
r = CMP(!!x->ratelimited, !!y->ratelimited);
@@ -385,10 +384,9 @@ static int prepare_prioq_compare(const void *a, const void *b) {
assert(y->prepare);
/* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
+ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF);
+ if (r != 0)
+ return r;
/* Non rate-limited ones first. */
r = CMP(!!x->ratelimited, !!y->ratelimited);
@@ -455,18 +453,17 @@ static bool event_source_timer_candidate(const sd_event_source *s) {
static int time_prioq_compare(const void *a, const void *b, usec_t (*time_func)(const sd_event_source *s)) {
const sd_event_source *x = a, *y = b;
+ int r;
/* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
+ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF);
+ if (r != 0)
+ return r;
/* Order "non-pending OR ratelimited" before "pending AND not-ratelimited" */
- if (event_source_timer_candidate(x) && !event_source_timer_candidate(y))
- return -1;
- if (!event_source_timer_candidate(x) && event_source_timer_candidate(y))
- return 1;
+ r = CMP(!event_source_timer_candidate(x), !event_source_timer_candidate(y));
+ if (r != 0)
+ return r;
/* Order by time */
return CMP(time_func(x), time_func(y));
@@ -482,15 +479,15 @@ static int latest_time_prioq_compare(const void *a, const void *b) {
static int exit_prioq_compare(const void *a, const void *b) {
const sd_event_source *x = a, *y = b;
+ int r;
assert(x->type == SOURCE_EXIT);
assert(y->type == SOURCE_EXIT);
/* Enabled ones first */
- if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF)
- return -1;
- if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF)
- return 1;
+ r = CMP(x->enabled == SD_EVENT_OFF, y->enabled == SD_EVENT_OFF);
+ if (r != 0)
+ return r;
/* Lower priority values first */
if (x->priority < y->priority)

View File

@ -0,0 +1,27 @@
From b79e00d8f97b8c959c5b17f0547c680f86dd9132 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 15 Jun 2021 01:01:48 +0900
Subject: [PATCH] sd-event: use usec_add()
(cherry picked from commit a595fb5ca9c69c589e758e9ebe3b70ac90450ba3)
Related: #1968528
---
src/libsystemd/sd-event/sd-event.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index 6a20b658e4..f675c09d84 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -3514,8 +3514,8 @@ static int arm_watchdog(sd_event *e) {
assert(e->watchdog_fd >= 0);
t = sleep_between(e,
- e->watchdog_last + (e->watchdog_period / 2),
- e->watchdog_last + (e->watchdog_period * 3 / 4));
+ usec_add(e->watchdog_last, (e->watchdog_period / 2)),
+ usec_add(e->watchdog_last, (e->watchdog_period * 3 / 4)));
timespec_store(&its.it_value, t);

View File

@ -0,0 +1,40 @@
From bf370d05bbc8c4d91c8c2b455116e59a24e48911 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 15 Jun 2021 02:03:02 +0900
Subject: [PATCH] sd-event: make event_source_time_prioq_reshuffle() accept all
event source type
But it does nothing for an event source which is neither a timer nor
ratelimited.
(cherry picked from commit 5c08c7ab23dbf02aaf4e4bbae8e08a195da230a4)
Related: #1968528
---
src/libsystemd/sd-event/sd-event.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index f675c09d84..ae46392901 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -954,14 +954,15 @@ static void event_source_time_prioq_reshuffle(sd_event_source *s) {
assert(s);
/* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy,
- * pending, enable state. Makes sure the two prioq's are ordered properly again. */
+ * pending, enable state, and ratelimiting state. Makes sure the two prioq's are ordered
+ * properly again. */
if (s->ratelimited)
d = &s->event->monotonic;
- else {
- assert(EVENT_SOURCE_IS_TIME(s->type));
+ else if (EVENT_SOURCE_IS_TIME(s->type))
assert_se(d = event_get_clock_data(s->event, s->type));
- }
+ else
+ return; /* no-op for an event source which is neither a timer nor ratelimited. */
prioq_reshuffle(d->earliest, s, &s->earliest_index);
prioq_reshuffle(d->latest, s, &s->latest_index);

View File

@ -0,0 +1,90 @@
From 1ce5187fb47bec57de4d8d3fd0068072228ec5e3 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 15 Jun 2021 02:13:59 +0900
Subject: [PATCH] sd-event: always reshuffle time prioq on changing
online/offline state
Before 81107b8419c39f726fd2805517a5b9faab204e59, the compare functions
for the latest or earliest prioq did not handle ratelimited flag.
So, it was ok to not reshuffle the time prioq when changing the flag.
But now, those two compare functions also compare the source is
ratelimited or not. So, it is necessary to reshuffle the time prioq
after changing the ratelimited flag.
Hopefully fixes #19903.
(cherry picked from commit 2115b9b6629eeba7bc9f42f757f38205febb1cb7)
Related: #1968528
---
src/libsystemd/sd-event/sd-event.c | 33 ++++++++++--------------------
1 file changed, 11 insertions(+), 22 deletions(-)
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index ae46392901..f78da00c3a 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -2390,14 +2390,6 @@ static int event_source_offline(
source_io_unregister(s);
break;
- case SOURCE_TIME_REALTIME:
- case SOURCE_TIME_BOOTTIME:
- case SOURCE_TIME_MONOTONIC:
- case SOURCE_TIME_REALTIME_ALARM:
- case SOURCE_TIME_BOOTTIME_ALARM:
- event_source_time_prioq_reshuffle(s);
- break;
-
case SOURCE_SIGNAL:
event_gc_signal_data(s->event, &s->priority, s->signal.sig);
break;
@@ -2415,6 +2407,11 @@ static int event_source_offline(
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
break;
+ case SOURCE_TIME_REALTIME:
+ case SOURCE_TIME_BOOTTIME:
+ case SOURCE_TIME_MONOTONIC:
+ case SOURCE_TIME_REALTIME_ALARM:
+ case SOURCE_TIME_BOOTTIME_ALARM:
case SOURCE_DEFER:
case SOURCE_POST:
case SOURCE_INOTIFY:
@@ -2424,6 +2421,9 @@ static int event_source_offline(
assert_not_reached("Wut? I shouldn't exist.");
}
+ /* Always reshuffle time prioq, as the ratelimited flag may be changed. */
+ event_source_time_prioq_reshuffle(s);
+
return 1;
}
@@ -2505,22 +2505,11 @@ static int event_source_online(
s->ratelimited = ratelimited;
/* Non-failing operations below */
- switch (s->type) {
- case SOURCE_TIME_REALTIME:
- case SOURCE_TIME_BOOTTIME:
- case SOURCE_TIME_MONOTONIC:
- case SOURCE_TIME_REALTIME_ALARM:
- case SOURCE_TIME_BOOTTIME_ALARM:
- event_source_time_prioq_reshuffle(s);
- break;
-
- case SOURCE_EXIT:
+ if (s->type == SOURCE_EXIT)
prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index);
- break;
- default:
- break;
- }
+ /* Always reshuffle time prioq, as the ratelimited flag may be changed. */
+ event_source_time_prioq_reshuffle(s);
return 1;
}

View File

@ -0,0 +1,27 @@
From 68cedfd41f1ea3eda34b0023e951649b92953709 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 15 Jul 2021 12:27:33 +0200
Subject: [PATCH] ci: run unit tests on z-stream branches as well
Resolves: #1970860
rhel-only
---
.github/workflows/unit_tests.yml | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
index 15f5127a75..428bde4ed8 100644
--- a/.github/workflows/unit_tests.yml
+++ b/.github/workflows/unit_tests.yml
@@ -2,10 +2,7 @@
# vi: ts=2 sw=2 et:
#
name: Unit tests
-on:
- pull_request:
- branches:
- - master
+on: [pull_request]
jobs:
build:

View File

@ -0,0 +1,32 @@
From 9bb57b7bed93e79f578e7c5b0c95f1f454e5d829 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 3 Mar 2021 12:33:38 +0100
Subject: [PATCH] ci: drop forgotten Travis references
rhel-only
Related: #1934504
---
.github/workflows/unit_tests.sh | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/unit_tests.sh b/.github/workflows/unit_tests.sh
index ea4f7e7592..43882b27da 100755
--- a/.github/workflows/unit_tests.sh
+++ b/.github/workflows/unit_tests.sh
@@ -68,7 +68,7 @@ for phase in "${PHASES[@]}"; do
case $phase in
SETUP)
info "Setup phase"
- info "Using Travis $CENTOS_RELEASE"
+ info "Using $CENTOS_RELEASE image"
# Pull a Docker image and start a new container
docker pull quay.io/centos/centos:$CENTOS_RELEASE
info "Starting container $CONT_NAME"
@@ -110,7 +110,6 @@ for phase in "${PHASES[@]}"; do
docker exec --interactive=false \
-e UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 \
-e ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 \
- -e "TRAVIS=$TRAVIS" \
-t $CONT_NAME \
meson test --timeout-multiplier=3 -C ./build/ --print-errorlogs
;;

View File

@ -0,0 +1,113 @@
From ccde55a339d211af488b1f1c148597d7977a9bb8 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 3 Mar 2021 12:49:20 +0100
Subject: [PATCH] ci: run unit tests on CentOS 8 Stream as well
rhel-only
Related: #1934504
---
.github/workflows/unit_tests.sh | 52 +++++++++++++++++++++++++++++++-
.github/workflows/unit_tests.yml | 13 ++++----
2 files changed, 58 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/unit_tests.sh b/.github/workflows/unit_tests.sh
index 43882b27da..8648e7149e 100755
--- a/.github/workflows/unit_tests.sh
+++ b/.github/workflows/unit_tests.sh
@@ -58,6 +58,53 @@ CONFIGURE_OPTS=(
-Ddefault-hierarchy=legacy
)
+# CentOS 8 Stream still doesn't provide SRPMs, so we can't use dnf's builddep
+# command to fetch this list for us. Hopefully, we'll be able to get rid
+# of this in the future.
+# See: https://bugs.centos.org/view.php?id=16715
+SYSTEMD_BUILD_DEPS=(
+ audit-libs-devel
+ bzip2-devel
+ cryptsetup-devel
+ dbus-devel
+ docbook-style-xsl
+ elfutils-devel
+ firewalld-filesystem
+ gcc
+ gcc-c++
+ gettext
+ git
+ gnu-efi
+ gnu-efi-devel
+ gnutls-devel
+ gobject-introspection-devel
+ gperf
+ iptables-devel
+ kmod-devel
+ libacl-devel
+ libblkid-devel
+ libcap-devel
+ libcurl-devel
+ libgcrypt-devel
+ libgpg-error-devel
+ libidn2-devel
+ libmicrohttpd-devel
+ libmount-devel
+ libseccomp-devel
+ libselinux-devel
+ libxkbcommon-devel
+ libxslt
+ lz4
+ lz4-devel
+ meson
+ pam-devel
+ pkgconf-pkg-config
+ python3-lxml
+ python36-devel
+ tree
+ xz-devel
+)
+
function info() {
echo -e "\033[33;1m$1\033[0m"
}
@@ -85,7 +132,10 @@ for phase in "${PHASES[@]}"; do
# Upgrade the container to get the most recent environment
$DOCKER_EXEC dnf -y upgrade
# Install systemd's build dependencies
- $DOCKER_EXEC dnf -q -y --enablerepo "powertools" builddep systemd
+ if ! $DOCKER_EXEC dnf -q -y --enablerepo "powertools" builddep systemd; then
+ # See the $SYSTEMD_BUILD_DEPS above for reasoning
+ $DOCKER_EXEC dnf -q -y --enablerepo "powertools" install "${SYSTEMD_BUILD_DEPS[@]}"
+ fi
;;
RUN|RUN_GCC)
info "Run phase"
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
index 428bde4ed8..b363118be8 100644
--- a/.github/workflows/unit_tests.yml
+++ b/.github/workflows/unit_tests.yml
@@ -7,19 +7,20 @@ on: [pull_request]
jobs:
build:
runs-on: ubuntu-20.04
- env:
- CENTOS_RELEASE: "centos8"
- CONT_NAME: "systemd-centos8-ci"
strategy:
fail-fast: false
matrix:
- run_phase: [GCC, GCC_ASAN]
+ image: [centos8, stream8]
+ phase: [GCC, GCC_ASAN]
+ env:
+ CONT_NAME: "systemd-centos8-ci"
+ CENTOS_RELEASE: ${{ matrix.image }}
steps:
- name: Repository checkout
uses: actions/checkout@v1
- name: Install build dependencies
run: sudo -E .github/workflows/unit_tests.sh SETUP
- - name: Build & test (${{ matrix.run_phase }})
- run: sudo -E .github/workflows/unit_tests.sh RUN_${{ matrix.run_phase }}
+ - name: Build & test (${{ env.CENTOS_RELEASE }} / ${{ matrix.phase }})
+ run: sudo -E .github/workflows/unit_tests.sh RUN_${{ matrix.phase }}
- name: Cleanup
run: sudo -E .github/workflows/unit_tests.sh CLEANUP

View File

@ -0,0 +1,37 @@
From 68555d26da9e46efbd70703b39a81cee601d265a Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Wed, 3 Mar 2021 13:14:02 +0100
Subject: [PATCH] ci: add missing test dependencies
rhel-only
Related: #1934504
---
.github/workflows/unit_tests.sh | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/unit_tests.sh b/.github/workflows/unit_tests.sh
index 8648e7149e..ad4584ec1d 100755
--- a/.github/workflows/unit_tests.sh
+++ b/.github/workflows/unit_tests.sh
@@ -6,7 +6,20 @@ CONT_NAME="${CONT_NAME:-centos-$CENTOS_RELEASE-$RANDOM}"
DOCKER_EXEC="${DOCKER_EXEC:-docker exec $CONT_NAME}"
DOCKER_RUN="${DOCKER_RUN:-docker run}"
REPO_ROOT="${REPO_ROOT:-$PWD}"
-ADDITIONAL_DEPS=(libasan libubsan net-tools strace nc e2fsprogs quota dnsmasq diffutils)
+ADDITIONAL_DEPS=(
+ diffutils
+ dnsmasq
+ e2fsprogs
+ hostname
+ libasan
+ libubsan
+ nc
+ net-tools
+ perl-IPC-SysV
+ perl-Time-HiRes
+ quota
+ strace
+)
# RHEL8 options
CONFIGURE_OPTS=(
-Dsysvinit-path=/etc/rc.d/init.d

View File

@ -0,0 +1,30 @@
From 998041fbb2b4114f2f1df604cdebc4afbf682d63 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Fri, 18 Jan 2019 22:32:42 +0100
Subject: [PATCH] meson: bump timeout for test-udev to 180s
On some (mainly virtual) machines the last test takes more than 30
seconds, which causes unnecessary fails, as the test itself is working
properly.
(cherry picked from commit bb0e960448fce037f5b82b1829863da8ccbe636b)
Related: #1934504
---
test/meson.build | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/test/meson.build b/test/meson.build
index 52e4fa2e3c..535354f3ab 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -246,7 +246,8 @@ custom_target(
if perl.found()
udev_test_pl = find_program('udev-test.pl')
test('udev-test',
- udev_test_pl)
+ udev_test_pl,
+ timeout : 180)
else
message('Skipping udev-test because perl is not available')
endif

View File

@ -0,0 +1,222 @@
From f875436b93c6c5e83f46ab32429c977db4f0b10c Mon Sep 17 00:00:00 2001
From: Felix Stupp <felix.stupp@outlook.com>
Date: Thu, 29 Oct 2020 12:48:48 +0100
Subject: [PATCH] Added option --check-inhibitors for non-tty usage
As described in #2680, systemctl did ignore inhibitors if it is not
attached to a tty to allow scripts to ignore inhibitors automatically.
This pull request preserves this behavior but allows scripts to
explicit check inhibitors if required.
The new parameter '--check-inhibitors=yes' enables this feature.
The old parameter '-i'/'--ignore-inhibitors' was deprecated in favor
of '--check-inhibitors=no', the default behaviour can be specified
with '--check-inhibitors=auto'.
The new parameter is also described in the documentations and shell
completions found here.
(cherry picked from commit b8ebe378b49a31549b8531d4b3177095ef385d55)
Related: #1269726
---
man/systemctl.xml | 38 ++++++++++++++++++++----------
shell-completion/bash/systemctl.in | 7 ++++--
shell-completion/zsh/_systemctl.in | 9 ++++++-
src/systemctl/systemctl.c | 37 +++++++++++++++++++++--------
4 files changed, 65 insertions(+), 26 deletions(-)
diff --git a/man/systemctl.xml b/man/systemctl.xml
index ed60a0739f..9f0f4d46ea 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -323,23 +323,35 @@
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--check-inhibitors=</option></term>
+
+ <listitem>
+ <para>When system shutdown or sleep state is request, this option controls how to deal with
+ inhibitor locks. It takes one of <literal>auto</literal>, <literal>yes</literal> or
+ <literal>no</literal>. Defaults to <literal>auto</literal>, which will behave like
+ <literal>yes</literal> for interactive invocations (i.e. from a TTY) and <literal>no</literal>
+ for non-interactive invocations.
+ <literal>yes</literal> will let the request respect inhibitor locks.
+ <literal>no</literal> will let the request ignore inhibitor locks.
+ </para>
+ <para>Applications can establish inhibitor locks to avoid that certain important operations
+ (such as CD burning or suchlike) are interrupted by system shutdown or a sleep state. Any user may
+ take these locks and privileged users may override these locks.
+ If any locks are taken, shutdown and sleep state requests will normally fail (unless privileged)
+ and a list of active locks is printed.
+ However, if <literal>no</literal> is specified or <literal>auto</literal> is specified on a
+ non-interactive requests, the established locks are ignored and not shown, and the operation
+ attempted anyway, possibly requiring additional privileges.
+ May be overriden by <option>--force</option>.</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>-i</option></term>
- <term><option>--ignore-inhibitors</option></term>
<listitem>
- <para>When system shutdown or a sleep state is requested,
- ignore inhibitor locks. Applications can establish inhibitor
- locks to avoid that certain important operations (such as CD
- burning or suchlike) are interrupted by system shutdown or a
- sleep state. Any user may take these locks and privileged
- users may override these locks. If any locks are taken,
- shutdown and sleep state requests will normally fail
- (regardless of whether privileged or not) and a list of active locks
- is printed. However, if <option>--ignore-inhibitors</option>
- is specified, the locks are ignored and not printed, and the
- operation attempted anyway, possibly requiring additional
- privileges.</para>
+ <para>Shortcut for <option>--check-inhibitors=no</option>.</para>
</listitem>
</varlistentry>
diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
index ba51ae0d34..0c7afea57d 100644
--- a/shell-completion/bash/systemctl.in
+++ b/shell-completion/bash/systemctl.in
@@ -111,9 +111,9 @@ _systemctl () {
[STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global
--help -h --no-ask-password --no-block --no-legend --no-pager --no-reload --no-wall --now
--quiet -q --system --user --version --runtime --recursive -r --firmware-setup
- --show-types -i --ignore-inhibitors --plain --failed --value --fail --dry-run --wait'
+ --show-types --plain --failed --value --fail --dry-run --wait'
[ARG]='--host -H --kill-who --property -p --signal -s --type -t --state --job-mode --root
- --preset-mode -n --lines -o --output -M --machine --message'
+ --preset-mode -n --lines -o --output -M --machine --message --check-inhibitors'
)
if __contains_word "--user" ${COMP_WORDS[*]}; then
@@ -163,6 +163,9 @@ _systemctl () {
--machine|-M)
comps=$( __get_machines )
;;
+ --check-inhibitors)
+ comps='auto yes no'
+ ;;
esac
COMPREPLY=( $(compgen -W '$comps' -- "$cur") )
return 0
diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
index 9f576ed77d..b3c51cc843 100644
--- a/shell-completion/zsh/_systemctl.in
+++ b/shell-completion/zsh/_systemctl.in
@@ -363,6 +363,13 @@ _job_modes() {
_values -s , "${_modes[@]}"
}
+(( $+functions[_systemctl_check_inhibitors] )) ||
+ _systemctl_check_inhibitors() {
+ local -a _modes
+ _modes=(auto yes no)
+ _values -s , "${_modes[@]}"
+ }
+
# Build arguments for "systemctl" to be used in completion.
local -a _modes; _modes=("--user" "--system")
# Use the last mode (they are exclusive and the last one is used).
@@ -380,7 +387,7 @@ _arguments -s \
'--before[Show units ordered before]' \
{-l,--full}"[Don't ellipsize unit names on output]" \
'--show-types[When showing sockets, show socket type]' \
- {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \
+ '--check-inhibitors[Specify if inhibitors should be checked]:mode:_systemctl_check_inhibitors' \
{-q,--quiet}'[Suppress output]' \
'--no-block[Do not wait until operation finished]' \
'--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 8bec798373..8bcbf6bf4b 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -121,7 +121,7 @@ static bool arg_no_wall = false;
static bool arg_no_reload = false;
static bool arg_value = false;
static bool arg_show_types = false;
-static bool arg_ignore_inhibitors = false;
+static int arg_check_inhibitors = -1;
static bool arg_dry_run = false;
static bool arg_quiet = false;
static bool arg_full = false;
@@ -3313,17 +3313,19 @@ static int logind_check_inhibitors(enum action a) {
char **s;
int r;
- if (arg_ignore_inhibitors || arg_force > 0)
+ if (arg_check_inhibitors == 0 || arg_force > 0)
return 0;
if (arg_when > 0)
return 0;
- if (geteuid() == 0)
- return 0;
+ if (arg_check_inhibitors < 0) {
+ if (geteuid() == 0)
+ return 0;
- if (!on_tty())
- return 0;
+ if (!on_tty())
+ return 0;
+ }
if (arg_transport != BUS_TRANSPORT_LOCAL)
return 0;
@@ -7237,8 +7239,10 @@ static void systemctl_help(void) {
" When enqueuing a unit job, show full transaction\n"
" --show-types When showing sockets, explicitly show their type\n"
" --value When showing properties, only print the value\n"
- " -i --ignore-inhibitors\n"
- " When shutting down or sleeping, ignore inhibitors\n"
+ " --check-inhibitors=MODE\n"
+ " Specify if checking inhibitors before shutting down,\n"
+ " sleeping or hibernating\n"
+ " -i Shortcut for --check-inhibitors=no\n"
" --kill-who=WHO Who to send signal to\n"
" -s --signal=SIGNAL Which signal to send\n"
" --now Start or stop unit in addition to enabling or disabling it\n"
@@ -7475,6 +7479,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_REVERSE,
ARG_AFTER,
ARG_BEFORE,
+ ARG_CHECK_INHIBITORS,
ARG_DRY_RUN,
ARG_SHOW_TYPES,
ARG_IRREVERSIBLE,
@@ -7520,7 +7525,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "fail", no_argument, NULL, ARG_FAIL }, /* compatibility only */
{ "irreversible", no_argument, NULL, ARG_IRREVERSIBLE }, /* compatibility only */
{ "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES }, /* compatibility only */
- { "ignore-inhibitors", no_argument, NULL, 'i' },
+ { "ignore-inhibitors", no_argument, NULL, 'i' }, /* compatibility only */
+ { "check-inhibitors", required_argument, NULL, ARG_CHECK_INHIBITORS },
{ "value", no_argument, NULL, ARG_VALUE },
{ "user", no_argument, NULL, ARG_USER },
{ "system", no_argument, NULL, ARG_SYSTEM },
@@ -7813,7 +7819,18 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
break;
case 'i':
- arg_ignore_inhibitors = true;
+ arg_check_inhibitors = 0;
+ break;
+
+ case ARG_CHECK_INHIBITORS:
+ if (streq(optarg, "auto"))
+ arg_check_inhibitors = -1;
+ else {
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --check-inhibitors= argument: %s", optarg);
+ arg_check_inhibitors = r;
+ }
break;
case ARG_PLAIN:

View File

@ -0,0 +1,769 @@
From d375206fe822903b16f3b9006ea47ffd938d88cb Mon Sep 17 00:00:00 2001
From: Deepak Rawat <drawat.floss@gmail.com>
Date: Mon, 25 Jan 2021 09:14:08 -0800
Subject: [PATCH] logind: Introduce RebootWithFlags and others
Add new systemd-logind WithFlags version for Reboot and others. These
methods add a unit64 parameter, with which can send additional control flags.
(cherry picked from commit 00971ea5164e2e7a5f2d7ffe12a566b62d282556)
Related: #1269726
---
src/basic/login-util.h | 8 +
src/login/logind-dbus.c | 498 +++++++++++++++++++++++++++++++-----
src/systemctl/systemctl.c | 26 ++
src/systemd/sd-bus-vtable.h | 19 +-
4 files changed, 480 insertions(+), 71 deletions(-)
diff --git a/src/basic/login-util.h b/src/basic/login-util.h
index e1e62e12b7..9832207458 100644
--- a/src/basic/login-util.h
+++ b/src/basic/login-util.h
@@ -4,6 +4,14 @@
#include <stdbool.h>
#include <unistd.h>
+#define SD_LOGIND_ROOT_CHECK_INHIBITORS (UINT64_C(1) << 0)
+
+/* For internal use only */
+#define SD_LOGIND_INTERACTIVE (UINT64_C(1) << 63)
+
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC (SD_LOGIND_ROOT_CHECK_INHIBITORS)
+#define SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_ALL (SD_LOGIND_ROOT_CHECK_INHIBITORS|SD_LOGIND_INTERACTIVE)
+
bool session_id_valid(const char *id);
static inline bool logind_running(void) {
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 3f122fcbd9..0c43fbb3e0 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1698,14 +1698,14 @@ static int verify_shutdown_creds(
Manager *m,
sd_bus_message *message,
InhibitWhat w,
- bool interactive,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
+ uint64_t flags,
sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
- bool multiple_sessions, blocked;
+ bool multiple_sessions, blocked, interactive;
uid_t uid;
int r;
@@ -1728,6 +1728,7 @@ static int verify_shutdown_creds(
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
+ interactive = flags & SD_LOGIND_INTERACTIVE;
if (multiple_sessions && action_multiple_sessions) {
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
@@ -1737,12 +1738,19 @@ static int verify_shutdown_creds(
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
}
- if (blocked && action_ignore_inhibit) {
- r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
- if (r < 0)
- return r;
- if (r == 0)
- return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+ if (blocked) {
+ /* We don't check polkit for root here, because you can't be more privileged than root */
+ if (uid == 0 && (flags & SD_LOGIND_ROOT_CHECK_INHIBITORS))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED,
+ "Access denied to root due to active block inhibitor");
+
+ if (action_ignore_inhibit) {
+ r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+ }
}
if (!multiple_sessions && !blocked && action) {
@@ -1765,9 +1773,11 @@ static int method_do_shutdown_or_sleep(
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_verb,
+ bool with_flags,
sd_bus_error *error) {
- int interactive, r;
+ int interactive = false, r;
+ uint64_t flags = 0;
assert(m);
assert(message);
@@ -1775,10 +1785,20 @@ static int method_do_shutdown_or_sleep(
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
- r = sd_bus_message_read(message, "b", &interactive);
+ if (with_flags)
+ r = sd_bus_message_read(message, "t", &flags);
+ else
+ r = sd_bus_message_read(message, "b", &interactive);
+
if (r < 0)
return r;
+ if (with_flags && (flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "Invalid flags parameter");
+
+ SET_FLAG(flags, SD_LOGIND_INTERACTIVE, interactive);
+
/* Don't allow multiple jobs being executed at the same time */
if (m->action_what)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
@@ -1795,8 +1815,8 @@ static int method_do_shutdown_or_sleep(
return r;
}
- r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
- action_ignore_inhibit, error);
+ r = verify_shutdown_creds(m, message, w, action, action_multiple_sessions,
+ action_ignore_inhibit, flags, error);
if (r != 0)
return r;
@@ -1818,6 +1838,7 @@ static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error
"org.freedesktop.login1.power-off-multiple-sessions",
"org.freedesktop.login1.power-off-ignore-inhibit",
NULL,
+ sd_bus_message_is_method_call(message, NULL, "PowerOffWithFlags"),
error);
}
@@ -1832,6 +1853,7 @@ static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.reboot-ignore-inhibit",
NULL,
+ sd_bus_message_is_method_call(message, NULL, "RebootWithFlags"),
error);
}
@@ -1846,6 +1868,7 @@ static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *er
"org.freedesktop.login1.halt-multiple-sessions",
"org.freedesktop.login1.halt-ignore-inhibit",
NULL,
+ sd_bus_message_is_method_call(message, NULL, "HaltWithFlags"),
error);
}
@@ -1860,6 +1883,7 @@ static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
"suspend",
+ sd_bus_message_is_method_call(message, NULL, "SuspendWithFlags"),
error);
}
@@ -1874,6 +1898,7 @@ static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_erro
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hibernate",
+ sd_bus_message_is_method_call(message, NULL, "HibernateWithFlags"),
error);
}
@@ -1888,6 +1913,7 @@ static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_e
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hybrid-sleep",
+ sd_bus_message_is_method_call(message, NULL, "HybridSleepWithFlags"),
error);
}
@@ -1902,6 +1928,7 @@ static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hybrid-sleep",
+ sd_bus_message_is_method_call(message, NULL, "SuspendThenHibernateWithFlags"),
error);
}
@@ -2089,8 +2116,8 @@ static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_
} else
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
- r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
- action, action_multiple_sessions, action_ignore_inhibit, error);
+ r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, action, action_multiple_sessions,
+ action_ignore_inhibit, 0, error);
if (r != 0)
return r;
@@ -2683,60 +2710,395 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
- SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
- SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
- SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SuspendThenHibernate", "b", NULL, method_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CanSuspendThenHibernate", NULL, "s", method_can_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
-
- SD_BUS_SIGNAL("SessionNew", "so", 0),
- SD_BUS_SIGNAL("SessionRemoved", "so", 0),
- SD_BUS_SIGNAL("UserNew", "uo", 0),
- SD_BUS_SIGNAL("UserRemoved", "uo", 0),
- SD_BUS_SIGNAL("SeatNew", "so", 0),
- SD_BUS_SIGNAL("SeatRemoved", "so", 0),
- SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
- SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
+ SD_BUS_METHOD_WITH_NAMES("GetSession",
+ "s",
+ SD_BUS_PARAM(session_id),
+ "o",
+ SD_BUS_PARAM(object_path),
+ method_get_session,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("GetSessionByPID",
+ "u",
+ SD_BUS_PARAM(pid),
+ "o",
+ SD_BUS_PARAM(object_path),
+ method_get_session_by_pid,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("GetUser",
+ "u",
+ SD_BUS_PARAM(uid),
+ "o",
+ SD_BUS_PARAM(object_path),
+ method_get_user,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("GetUserByPID",
+ "u",
+ SD_BUS_PARAM(pid),
+ "o",
+ SD_BUS_PARAM(object_path),
+ method_get_user_by_pid,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("GetSeat",
+ "s",
+ SD_BUS_PARAM(seat_id),
+ "o",
+ SD_BUS_PARAM(object_path),
+ method_get_seat,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ListSessions",
+ NULL,,
+ "a(susso)",
+ SD_BUS_PARAM(sessions),
+ method_list_sessions,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ListUsers",
+ NULL,,
+ "a(uso)",
+ SD_BUS_PARAM(users),
+ method_list_users,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ListSeats",
+ NULL,,
+ "a(so)",
+ SD_BUS_PARAM(seats),
+ method_list_seats,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ListInhibitors",
+ NULL,,
+ "a(ssssuu)",
+ SD_BUS_PARAM(inhibitors),
+ method_list_inhibitors,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CreateSession",
+ "uusssssussbssa(sv)",
+ SD_BUS_PARAM(uid)
+ SD_BUS_PARAM(pid)
+ SD_BUS_PARAM(service)
+ SD_BUS_PARAM(type)
+ SD_BUS_PARAM(class)
+ SD_BUS_PARAM(desktop)
+ SD_BUS_PARAM(seat_id)
+ SD_BUS_PARAM(vtnr)
+ SD_BUS_PARAM(tty)
+ SD_BUS_PARAM(display)
+ SD_BUS_PARAM(remote)
+ SD_BUS_PARAM(remote_user)
+ SD_BUS_PARAM(remote_host)
+ SD_BUS_PARAM(properties),
+ "soshusub",
+ SD_BUS_PARAM(session_id)
+ SD_BUS_PARAM(object_path)
+ SD_BUS_PARAM(runtime_path)
+ SD_BUS_PARAM(fifo_fd)
+ SD_BUS_PARAM(uid)
+ SD_BUS_PARAM(seat_id)
+ SD_BUS_PARAM(vtnr)
+ SD_BUS_PARAM(existing),
+ method_create_session,
+ 0),
+ SD_BUS_METHOD_WITH_NAMES("ReleaseSession",
+ "s",
+ SD_BUS_PARAM(session_id),
+ NULL,,
+ method_release_session,
+ 0),
+ SD_BUS_METHOD_WITH_NAMES("ActivateSession",
+ "s",
+ SD_BUS_PARAM(session_id),
+ NULL,,
+ method_activate_session,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ActivateSessionOnSeat",
+ "ss",
+ SD_BUS_PARAM(session_id)
+ SD_BUS_PARAM(seat_id),
+ NULL,,
+ method_activate_session_on_seat,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("LockSession",
+ "s",
+ SD_BUS_PARAM(session_id),
+ NULL,,
+ method_lock_session,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("UnlockSession",
+ "s",
+ SD_BUS_PARAM(session_id),
+ NULL,,
+ method_lock_session,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("LockSessions",
+ NULL,
+ NULL,
+ method_lock_sessions,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("UnlockSessions",
+ NULL,
+ NULL,
+ method_lock_sessions,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("KillSession",
+ "ssi",
+ SD_BUS_PARAM(session_id)
+ SD_BUS_PARAM(who)
+ SD_BUS_PARAM(signal_number),
+ NULL,,
+ method_kill_session,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("KillUser",
+ "ui",
+ SD_BUS_PARAM(uid)
+ SD_BUS_PARAM(signal_number),
+ NULL,,
+ method_kill_user,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("TerminateSession",
+ "s",
+ SD_BUS_PARAM(session_id),
+ NULL,,
+ method_terminate_session,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("TerminateUser",
+ "u",
+ SD_BUS_PARAM(uid),
+ NULL,,
+ method_terminate_user,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("TerminateSeat",
+ "s",
+ SD_BUS_PARAM(seat_id),
+ NULL,,
+ method_terminate_seat,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SetUserLinger",
+ "ubb",
+ SD_BUS_PARAM(uid)
+ SD_BUS_PARAM(enable)
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_set_user_linger,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("AttachDevice",
+ "ssb",
+ SD_BUS_PARAM(seat_id)
+ SD_BUS_PARAM(sysfs_path)
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_attach_device,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("FlushDevices",
+ "b",
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_flush_devices,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("PowerOff",
+ "b",
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_poweroff,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("PowerOffWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_poweroff,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("Reboot",
+ "b",
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_reboot,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("RebootWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_reboot,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("Halt",
+ "b",
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_halt,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HaltWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_halt,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("Suspend",
+ "b",
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_suspend,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SuspendWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_suspend,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("Hibernate",
+ "b",
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HibernateWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HybridSleep",
+ "b",
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_hybrid_sleep,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("HybridSleepWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_hybrid_sleep,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SuspendThenHibernate",
+ "b",
+ SD_BUS_PARAM(interactive),
+ NULL,,
+ method_suspend_then_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SuspendThenHibernateWithFlags",
+ "t",
+ SD_BUS_PARAM(flags),
+ NULL,,
+ method_suspend_then_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CanPowerOff",
+ NULL,,
+ "s",
+ SD_BUS_PARAM(result),
+ method_can_poweroff,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CanReboot",
+ NULL,,
+ "s",
+ SD_BUS_PARAM(result),
+ method_can_reboot,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CanHalt",
+ NULL,,
+ "s",
+ SD_BUS_PARAM(result),
+ method_can_halt,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CanSuspend",
+ NULL,,
+ "s",
+ SD_BUS_PARAM(result),
+ method_can_suspend,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CanHibernate",
+ NULL,,
+ "s",
+ SD_BUS_PARAM(result),
+ method_can_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CanHybridSleep",
+ NULL,,
+ "s",
+ SD_BUS_PARAM(result),
+ method_can_hybrid_sleep,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CanSuspendThenHibernate",
+ NULL,,
+ "s",
+ SD_BUS_PARAM(result),
+ method_can_suspend_then_hibernate,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("ScheduleShutdown",
+ "st",
+ SD_BUS_PARAM(type)
+ SD_BUS_PARAM(usec),
+ NULL,,
+ method_schedule_shutdown,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CancelScheduledShutdown",
+ NULL,,
+ "b",
+ SD_BUS_PARAM(cancelled),
+ method_cancel_scheduled_shutdown,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("Inhibit",
+ "ssss",
+ SD_BUS_PARAM(what)
+ SD_BUS_PARAM(who)
+ SD_BUS_PARAM(why)
+ SD_BUS_PARAM(mode),
+ "h",
+ SD_BUS_PARAM(pipe_fd),
+ method_inhibit,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("CanRebootToFirmwareSetup",
+ NULL,,
+ "s",
+ SD_BUS_PARAM(result),
+ method_can_reboot_to_firmware_setup,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SetRebootToFirmwareSetup",
+ "b",
+ SD_BUS_PARAM(enable),
+ NULL,,
+ method_set_reboot_to_firmware_setup,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_NAMES("SetWallMessage",
+ "sb",
+ SD_BUS_PARAM(wall_message)
+ SD_BUS_PARAM(enable),
+ NULL,,
+ method_set_wall_message,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+
+ SD_BUS_SIGNAL_WITH_NAMES("SessionNew",
+ "so",
+ SD_BUS_PARAM(session_id)
+ SD_BUS_PARAM(object_path),
+ 0),
+ SD_BUS_SIGNAL_WITH_NAMES("SessionRemoved",
+ "so",
+ SD_BUS_PARAM(session_id)
+ SD_BUS_PARAM(object_path),
+ 0),
+ SD_BUS_SIGNAL_WITH_NAMES("UserNew",
+ "uo",
+ SD_BUS_PARAM(uid)
+ SD_BUS_PARAM(object_path),
+ 0),
+ SD_BUS_SIGNAL_WITH_NAMES("UserRemoved",
+ "uo",
+ SD_BUS_PARAM(uid)
+ SD_BUS_PARAM(object_path),
+ 0),
+ SD_BUS_SIGNAL_WITH_NAMES("SeatNew",
+ "so",
+ SD_BUS_PARAM(seat_id)
+ SD_BUS_PARAM(object_path),
+ 0),
+ SD_BUS_SIGNAL_WITH_NAMES("SeatRemoved",
+ "so",
+ SD_BUS_PARAM(seat_id)
+ SD_BUS_PARAM(object_path),
+ 0),
+ SD_BUS_SIGNAL_WITH_NAMES("PrepareForShutdown",
+ "b",
+ SD_BUS_PARAM(start),
+ 0),
+ SD_BUS_SIGNAL_WITH_NAMES("PrepareForSleep",
+ "b",
+ SD_BUS_PARAM(start),
+ 0),
SD_BUS_VTABLE_END
};
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 8bcbf6bf4b..3dd7c1522f 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -50,6 +50,7 @@
#include "list.h"
#include "locale-util.h"
#include "log.h"
+#include "login-util.h"
#include "logs-show.h"
#include "macro.h"
#include "mkdir.h"
@@ -3266,6 +3267,8 @@ static int logind_reboot(enum action a) {
};
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ const char *method_with_flags;
+ uint64_t flags = 0;
sd_bus *bus;
int r;
@@ -3284,6 +3287,29 @@ static int logind_reboot(enum action a) {
if (arg_dry_run)
return 0;
+ SET_FLAG(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS, arg_check_inhibitors > 0);
+
+ method_with_flags = strjoina(actions[a].method, "WithFlags");
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ method_with_flags,
+ &error,
+ NULL,
+ "t", flags);
+ if (r >= 0)
+ return 0;
+
+ if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
+ return log_error_errno(r, "Failed to %s via logind: %s", actions[a].description, bus_error_message(&error, r));
+
+ /* Fallback to original methods in case there is older version of systemd-logind */
+ log_debug("Method %s not available: %s. Falling back to %s", method_with_flags, bus_error_message(&error, r), actions[a].method);
+ sd_bus_error_free(&error);
+
r = sd_bus_call_method(
bus,
"org.freedesktop.login1",
diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h
index 1268085498..8805e19477 100644
--- a/src/systemd/sd-bus-vtable.h
+++ b/src/systemd/sd-bus-vtable.h
@@ -65,10 +65,12 @@ struct sd_bus_vtable {
const char *result;
sd_bus_message_handler_t handler;
size_t offset;
+ const char *names;
} method;
struct {
const char *member;
const char *signature;
+ const char *names;
} signal;
struct {
const char *member;
@@ -91,7 +93,10 @@ struct sd_bus_vtable {
}, \
}
-#define SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, _offset, _flags) \
+/* helper macro to format method and signal parameters, one at a time */
+#define SD_BUS_PARAM(x) #x "\0"
+
+#define SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, _in_names, _result, _out_names, _handler, _offset, _flags) \
{ \
.type = _SD_BUS_VTABLE_METHOD, \
.flags = _flags, \
@@ -102,13 +107,18 @@ struct sd_bus_vtable {
.result = _result, \
.handler = _handler, \
.offset = _offset, \
+ .names = _in_names _out_names, \
}, \
}, \
}
+#define SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, _offset, _flags) \
+ SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, "", _result, "", _handler, _offset, _flags)
+#define SD_BUS_METHOD_WITH_NAMES(_member, _signature, _in_names, _result, _out_names, _handler, _flags) \
+ SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, _in_names, _result, _out_names, _handler, 0, _flags)
#define SD_BUS_METHOD(_member, _signature, _result, _handler, _flags) \
- SD_BUS_METHOD_WITH_OFFSET(_member, _signature, _result, _handler, 0, _flags)
+ SD_BUS_METHOD_WITH_NAMES_OFFSET(_member, _signature, "", _result, "", _handler, 0, _flags)
-#define SD_BUS_SIGNAL(_member, _signature, _flags) \
+#define SD_BUS_SIGNAL_WITH_NAMES(_member, _signature, _out_names, _flags) \
{ \
.type = _SD_BUS_VTABLE_SIGNAL, \
.flags = _flags, \
@@ -116,9 +126,12 @@ struct sd_bus_vtable {
.signal = { \
.member = _member, \
.signature = _signature, \
+ .names = _out_names, \
}, \
}, \
}
+#define SD_BUS_SIGNAL(_member, _signature, _flags) \
+ SD_BUS_SIGNAL_WITH_NAMES(_member, _signature, "", _flags)
#define SD_BUS_PROPERTY(_member, _signature, _get, _offset, _flags) \
{ \

View File

@ -0,0 +1,85 @@
From e1b18ab36b2457a4896e531f03713b198725c919 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 9 Mar 2021 09:03:58 +0100
Subject: [PATCH] =?UTF-8?q?logind:=20add=20=E2=80=A6WithFlags=20methods=20?=
=?UTF-8?q?to=20policy?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Without this, privilege escalation through polkit does not work, because all
methods fail with permission errors.
Forgotten in 8885fed4e3a52cf1bf105e42043203c485ed9d92.
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1933335.
(cherry picked from commit 2280db756eaff795091871feee8e47d4f6989a58)
Related: #1269726
---
src/login/org.freedesktop.login1.conf | 28 +++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf
index f880f3e2da..dcde0c22c6 100644
--- a/src/login/org.freedesktop.login1.conf
+++ b/src/login/org.freedesktop.login1.conf
@@ -130,30 +130,58 @@
send_interface="org.freedesktop.login1.Manager"
send_member="PowerOff"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="PowerOffWithFlags"/>
+
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="Reboot"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="RebootWithFlags"/>
+
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="Halt"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="HaltWithFlags"/>
+
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="Suspend"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="SuspendWithFlags"/>
+
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="Hibernate"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="HibernateWithFlags"/>
+
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="HybridSleep"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="HybridSleepWithFlags"/>
+
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="SuspendThenHibernate"/>
+ <allow send_destination="org.freedesktop.login1"
+ send_interface="org.freedesktop.login1.Manager"
+ send_member="SuspendThenHibernateWithFlags"/>
+
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="CanPowerOff"/>

View File

@ -0,0 +1,72 @@
From 6751217a032dd1a8e8ee324332f29786265f0ebe Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 2 Feb 2021 15:27:30 +0100
Subject: [PATCH] logind: simplify flags handling a bit
Let's split out the two codepaths a bit, and emphasize which ones it the
new-style and which the old-style codepath, and let's clearly convert
the params of the old-stye into the new style for further processing, so
that the old style path is brief and isolated.
No change in behaviour.
Follow-up for: 8885fed4e3a52cf1bf105e42043203c485ed9d92
(cherry picked from commit d3e99bc0c7f785dcf4e73cfed12f74002e73be5f)
Related: #1269726
---
src/login/logind-dbus.c | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 0c43fbb3e0..ae9abc9bce 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -1776,8 +1776,8 @@ static int method_do_shutdown_or_sleep(
bool with_flags,
sd_bus_error *error) {
- int interactive = false, r;
- uint64_t flags = 0;
+ uint64_t flags;
+ int r;
assert(m);
assert(message);
@@ -1785,19 +1785,25 @@ static int method_do_shutdown_or_sleep(
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
- if (with_flags)
+ if (with_flags) {
+ /* New style method: with flags parameter (and interactive bool in the bus message header) */
r = sd_bus_message_read(message, "t", &flags);
- else
- r = sd_bus_message_read(message, "b", &interactive);
-
- if (r < 0)
- return r;
+ if (r < 0)
+ return r;
+ if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
+ } else {
+ /* Old style method: no flags parameter, but interactive bool passed as boolean in
+ * payload. Let's convert this argument to the new-style flags parameter for our internal
+ * use. */
+ int interactive;
- if (with_flags && (flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
- "Invalid flags parameter");
+ r = sd_bus_message_read(message, "b", &interactive);
+ if (r < 0)
+ return r;
- SET_FLAG(flags, SD_LOGIND_INTERACTIVE, interactive);
+ flags = interactive ? SD_LOGIND_INTERACTIVE : 0;
+ }
/* Don't allow multiple jobs being executed at the same time */
if (m->action_what)

View File

@ -0,0 +1,25 @@
From 48b893c770aed3214586d529ddaba14267818c33 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Thu, 15 Jul 2021 10:35:08 +0200
Subject: [PATCH] Update link to RHEL documentation
RHEL-only
Resolves: #1982584
---
man/systemctl.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/systemctl.xml b/man/systemctl.xml
index 9f0f4d46ea..a71e6c7c4f 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -2017,7 +2017,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<para>
For examples how to use systemctl in comparsion
with old service and chkconfig command please see:
- <ulink url="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/managing-services-with-systemd_configuring-basic-system-settings">
+ <ulink url="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/configuring_basic_system_settings/managing-system-services-with-systemctl_configuring-basic-system-settings">
Managing System Services
</ulink>
</para>

View File

@ -0,0 +1,29 @@
From e2f5e8ccb27f48717b50339f58582d70ad5f59b1 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Tue, 3 Aug 2021 11:52:36 +0200
Subject: [PATCH] Set default core ulimit to 0, but keep the hard limit
ulimited
so users can change it later.
Follow-up to 830bd662276ee117e65a4b3d541f77e8b172eafd.
rhel-only
Resolves: #1905582
---
src/core/system.conf.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/system.conf.in b/src/core/system.conf.in
index b4d6dfa15a..84246c0e36 100644
--- a/src/core/system.conf.in
+++ b/src/core/system.conf.in
@@ -52,7 +52,7 @@
#DefaultLimitFSIZE=
#DefaultLimitDATA=
#DefaultLimitSTACK=
-DefaultLimitCORE=0
+DefaultLimitCORE=0:infinity
#DefaultLimitRSS=
#DefaultLimitNOFILE=
#DefaultLimitAS=

View File

@ -0,0 +1,76 @@
From 3cf73fa4599116da350a0100378e749bbcbcad37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Thu, 26 Nov 2020 11:23:54 +0100
Subject: [PATCH] shared/seccomp-util: address family filtering is broken on
ppc
This reverts the gist of da1921a5c396547261c8c7fcd94173346eb3b718 and
0d9fca76bb69e162265b2d25cb79f1890c0da31b (for ppc).
Quoting #17559:
> libseccomp 2.5 added socket syscall multiplexing on ppc64(el):
> https://github.com/seccomp/libseccomp/pull/229
>
> Like with i386, s390 and s390x this breaks socket argument filtering, so
> RestrictAddressFamilies doesn't work.
>
> This causes the unit test to fail:
> /* test_restrict_address_families */
> Operating on architecture: ppc
> Failed to install socket family rules for architecture ppc, skipping: Operation canceled
> Operating on architecture: ppc64
> Failed to add socket() rule for architecture ppc64, skipping: Invalid argument
> Operating on architecture: ppc64-le
> Failed to add socket() rule for architecture ppc64-le, skipping: Invalid argument
> Assertion 'fd < 0' failed at src/test/test-seccomp.c:424, function test_restrict_address_families(). Aborting.
>
> The socket filters can't be added so `socket(AF_UNIX, SOCK_DGRAM, 0);` still
> works, triggering the assertion.
Fixes #17559.
(cherry picked from commit d5923e38bc0e6cf9d7620ed5f1f8606fe7fe1168)
Resolves: #1982650
---
src/shared/seccomp-util.c | 6 +++---
src/test/test-seccomp.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index e903512d45..c57c409433 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -1251,9 +1251,6 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
case SCMP_ARCH_X32:
case SCMP_ARCH_ARM:
case SCMP_ARCH_AARCH64:
- case SCMP_ARCH_PPC:
- case SCMP_ARCH_PPC64:
- case SCMP_ARCH_PPC64LE:
case SCMP_ARCH_MIPSEL64N32:
case SCMP_ARCH_MIPS64N32:
case SCMP_ARCH_MIPSEL64:
@@ -1267,6 +1264,9 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
case SCMP_ARCH_X86:
case SCMP_ARCH_MIPSEL:
case SCMP_ARCH_MIPS:
+ case SCMP_ARCH_PPC:
+ case SCMP_ARCH_PPC64:
+ case SCMP_ARCH_PPC64LE:
default:
/* These we either know we don't support (i.e. are the ones that do use socketcall()), or we
* don't know */
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
index 009a2e1922..5eb1c78b8b 100644
--- a/src/test/test-seccomp.c
+++ b/src/test/test-seccomp.c
@@ -25,7 +25,7 @@
#include "util.h"
#include "virt.h"
-#if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__)
+#if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) || defined(__powerpc64__) || defined(__powerpc__)
/* On these archs, socket() is implemented via the socketcall() syscall multiplexer,
* and we can't restrict it hence via seccomp. */
# define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1

View File

@ -0,0 +1,341 @@
From 019b3a5d7530c51aa8f7f1e5f5cb5eb81113d4db Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 3 Aug 2018 18:53:09 +0200
Subject: [PATCH] logind: rework Seat/Session/User object allocation and
freeing a bit
Let's update things a bit to follow current practices:
- User structure initialization rather than zero-initialized allocation
- Always propagate proper errors from allocation functions
- Use _cleanup_ for freeing objects when allocation fails half-way
- Make destructors return NULL
(cherry picked from commit 8c29a4570993105fecc12288596d2ee77c7f82b8)
Related: #1642460
---
src/login/logind-core.c | 14 ++++++----
src/login/logind-seat.c | 38 +++++++++++++++----------
src/login/logind-seat.h | 6 ++--
src/login/logind-session.c | 57 +++++++++++++++++++++-----------------
src/login/logind-session.h | 7 +++--
src/login/logind-user.c | 21 +++++++-------
6 files changed, 83 insertions(+), 60 deletions(-)
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index cff5536ac0..f598bbaa1c 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -88,15 +88,16 @@ int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_dev
int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
Seat *s;
+ int r;
assert(m);
assert(id);
s = hashmap_get(m->seats, id);
if (!s) {
- s = seat_new(m, id);
- if (!s)
- return -ENOMEM;
+ r = seat_new(&s, m, id);
+ if (r < 0)
+ return r;
}
if (_seat)
@@ -107,15 +108,16 @@ int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
int manager_add_session(Manager *m, const char *id, Session **_session) {
Session *s;
+ int r;
assert(m);
assert(id);
s = hashmap_get(m->sessions, id);
if (!s) {
- s = session_new(m, id);
- if (!s)
- return -ENOMEM;
+ r = session_new(&s, m, id);
+ if (r < 0)
+ return r;
}
if (_session)
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 63253db5bf..f68fc0ceaa 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -21,33 +21,42 @@
#include "terminal-util.h"
#include "util.h"
-Seat *seat_new(Manager *m, const char *id) {
- Seat *s;
+int seat_new(Seat** ret, Manager *m, const char *id) {
+ _cleanup_(seat_freep) Seat *s = NULL;
+ int r;
+ assert(ret);
assert(m);
assert(id);
- s = new0(Seat, 1);
+ if (!seat_name_is_valid(id))
+ return -EINVAL;
+
+ s = new(Seat, 1);
if (!s)
- return NULL;
+ return -ENOMEM;
+
+ *s = (Seat) {
+ .manager = m,
+ };
s->state_file = strappend("/run/systemd/seats/", id);
if (!s->state_file)
- return mfree(s);
+ return -ENOMEM;
s->id = basename(s->state_file);
- s->manager = m;
- if (hashmap_put(m->seats, s->id, s) < 0) {
- free(s->state_file);
- return mfree(s);
- }
+ r = hashmap_put(m->seats, s->id, s);
+ if (r < 0)
+ return r;
- return s;
+ *ret = TAKE_PTR(s);
+ return 0;
}
-void seat_free(Seat *s) {
- assert(s);
+Seat* seat_free(Seat *s) {
+ if (!s)
+ return NULL;
if (s->in_gc_queue)
LIST_REMOVE(gc_queue, s->manager->seat_gc_queue, s);
@@ -64,7 +73,8 @@ void seat_free(Seat *s) {
free(s->positions);
free(s->state_file);
- free(s);
+
+ return mfree(s);
}
int seat_save(Seat *s) {
diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h
index 70878bbe52..51cd468e26 100644
--- a/src/login/logind-seat.h
+++ b/src/login/logind-seat.h
@@ -27,8 +27,10 @@ struct Seat {
LIST_FIELDS(Seat, gc_queue);
};
-Seat *seat_new(Manager *m, const char *id);
-void seat_free(Seat *s);
+int seat_new(Seat **ret, Manager *m, const char *id);
+Seat* seat_free(Seat *s);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Seat *, seat_free);
int seat_save(Seat *s);
int seat_load(Seat *s);
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 69d5a10319..5621d59a41 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -24,57 +24,61 @@
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
+#include "process-util.h"
#include "string-table.h"
#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
-#include "process-util.h"
#define RELEASE_USEC (20*USEC_PER_SEC)
static void session_remove_fifo(Session *s);
-Session* session_new(Manager *m, const char *id) {
- Session *s;
+int session_new(Session **ret, Manager *m, const char *id) {
+ _cleanup_(session_freep) Session *s = NULL;
+ int r;
+ assert(ret);
assert(m);
assert(id);
- assert(session_id_valid(id));
- s = new0(Session, 1);
+ if (!session_id_valid(id))
+ return -EINVAL;
+
+ s = new(Session, 1);
if (!s)
- return NULL;
+ return -ENOMEM;
+
+ *s = (Session) {
+ .manager = m,
+ .fifo_fd = -1,
+ .vtfd = -1,
+ .audit_id = AUDIT_SESSION_INVALID,
+ };
s->state_file = strappend("/run/systemd/sessions/", id);
if (!s->state_file)
- return mfree(s);
-
- s->devices = hashmap_new(&devt_hash_ops);
- if (!s->devices) {
- free(s->state_file);
- return mfree(s);
- }
+ return -ENOMEM;
s->id = basename(s->state_file);
- if (hashmap_put(m->sessions, s->id, s) < 0) {
- hashmap_free(s->devices);
- free(s->state_file);
- return mfree(s);
- }
+ s->devices = hashmap_new(&devt_hash_ops);
+ if (!s->devices)
+ return -ENOMEM;
- s->manager = m;
- s->fifo_fd = -1;
- s->vtfd = -1;
- s->audit_id = AUDIT_SESSION_INVALID;
+ r = hashmap_put(m->sessions, s->id, s);
+ if (r < 0)
+ return r;
- return s;
+ *ret = TAKE_PTR(s);
+ return 0;
}
-void session_free(Session *s) {
+Session* session_free(Session *s) {
SessionDevice *sd;
- assert(s);
+ if (!s)
+ return NULL;
if (s->in_gc_queue)
LIST_REMOVE(gc_queue, s->manager->session_gc_queue, s);
@@ -126,7 +130,8 @@ void session_free(Session *s) {
hashmap_remove(s->manager->sessions, s->id);
free(s->state_file);
- free(s);
+
+ return mfree(s);
}
void session_set_user(Session *s, User *u) {
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index 29ca399daf..572f2545c1 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -109,8 +109,11 @@ struct Session {
LIST_FIELDS(Session, gc_queue);
};
-Session *session_new(Manager *m, const char *id);
-void session_free(Session *s);
+int session_new(Session **ret, Manager *m, const char *id);
+Session* session_free(Session *s);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Session *, session_free);
+
void session_set_user(Session *s, User *u);
bool session_may_gc(Session *s, bool drop_not_started);
void session_add_to_gc_queue(Session *s);
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 56b8066f12..60ccd62abb 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -30,23 +30,24 @@
#include "user-util.h"
#include "util.h"
-int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
+int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
_cleanup_(user_freep) User *u = NULL;
char lu[DECIMAL_STR_MAX(uid_t) + 1];
int r;
- assert(out);
+ assert(ret);
assert(m);
assert(name);
- u = new0(User, 1);
+ u = new(User, 1);
if (!u)
return -ENOMEM;
- u->manager = m;
- u->uid = uid;
- u->gid = gid;
- xsprintf(lu, UID_FMT, uid);
+ *u = (User) {
+ .manager = m,
+ .uid = uid,
+ .gid = gid,
+ };
u->name = strdup(name);
if (!u->name)
@@ -58,6 +59,7 @@ int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
if (asprintf(&u->runtime_path, "/run/user/"UID_FMT, uid) < 0)
return -ENOMEM;
+ xsprintf(lu, UID_FMT, uid);
r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &u->slice);
if (r < 0)
return r;
@@ -78,8 +80,7 @@ int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name) {
if (r < 0)
return r;
- *out = TAKE_PTR(u);
-
+ *ret = TAKE_PTR(u);
return 0;
}
@@ -272,7 +273,7 @@ int user_save(User *u) {
if (!u->started)
return 0;
- return user_save_internal (u);
+ return user_save_internal(u);
}
int user_load(User *u) {

View File

@ -0,0 +1,116 @@
From 0314e68fe961cec941b1b0eb1cbcca4546cfdfdb Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 3 Aug 2018 19:04:35 +0200
Subject: [PATCH] logind: fix serialization/deserialization of user's "display
session"
Previously this was serialized as part of the user object. This didn't
work however, as we load users first, and sessions seconds and hence
referencing a session from the user load logic cannot work.
Fix this by storing an IS_DISPLAY property along with each session, and
make the session with this set display session when it is loaded.
(cherry picked from commit 1c8280fd47b6561d35b15b3b6d49bdeacf891bfd)
Related: #1642460
---
src/login/logind-session.c | 18 +++++++++++++++++-
src/login/logind-user.c | 18 ++++--------------
2 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 5621d59a41..0afb065b2b 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -184,11 +184,13 @@ int session_save(Session *s) {
"UID="UID_FMT"\n"
"USER=%s\n"
"ACTIVE=%i\n"
+ "IS_DISPLAY=%i\n"
"STATE=%s\n"
"REMOTE=%i\n",
s->user->uid,
s->user->name,
session_is_active(s),
+ s->user->display == s,
session_state_to_string(session_get_state(s)),
s->remote);
@@ -359,7 +361,8 @@ int session_load(Session *s) {
*monotonic = NULL,
*controller = NULL,
*active = NULL,
- *devices = NULL;
+ *devices = NULL,
+ *is_display = NULL;
int k, r;
@@ -389,6 +392,7 @@ int session_load(Session *s) {
"CONTROLLER", &controller,
"ACTIVE", &active,
"DEVICES", &devices,
+ "IS_DISPLAY", &is_display,
NULL);
if (r < 0)
@@ -496,6 +500,18 @@ int session_load(Session *s) {
s->was_active = k;
}
+ if (is_display) {
+ /* Note that when enumerating users are loaded before sessions, hence the display session to use is
+ * something we have to store along with the session and not the user, as in that case we couldn't
+ * apply it at the time we load the user. */
+
+ k = parse_boolean(is_display);
+ if (k < 0)
+ log_warning_errno(k, "Failed to parse IS_DISPLAY session property: %m");
+ else if (k > 0)
+ s->user->display = s;
+ }
+
if (controller) {
if (bus_name_has_owner(s->manager->bus, controller, NULL) > 0) {
session_set_controller(s, controller, false, false);
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 60ccd62abb..17ed361411 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -277,8 +277,7 @@ int user_save(User *u) {
}
int user_load(User *u) {
- _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
- Session *s = NULL;
+ _cleanup_free_ char *realtime = NULL, *monotonic = NULL;
int r;
assert(u);
@@ -286,22 +285,13 @@ int user_load(User *u) {
r = parse_env_file(NULL, u->state_file, NEWLINE,
"SERVICE_JOB", &u->service_job,
"SLICE_JOB", &u->slice_job,
- "DISPLAY", &display,
"REALTIME", &realtime,
"MONOTONIC", &monotonic,
NULL);
- if (r < 0) {
- if (r == -ENOENT)
- return 0;
-
+ if (r == -ENOENT)
+ return 0;
+ if (r < 0)
return log_error_errno(r, "Failed to read %s: %m", u->state_file);
- }
-
- if (display)
- s = hashmap_get(u->manager->sessions, display);
-
- if (s && s->display && display_is_local(s->display))
- u->display = s;
if (realtime)
timestamp_deserialize(realtime, &u->timestamp.realtime);

View File

@ -0,0 +1,39 @@
From 3eab0f1b64477792bd01ca52c3eb26ce64c5c7ba Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 3 Aug 2018 20:18:55 +0200
Subject: [PATCH] logind: turn of stdio locking when writing session files too
This just copies what we already do for user and seat files to session
files.
(cherry picked from commit 44176400138e18d9087e0864ca97041416a90d47)
Related: #1642460
---
src/login/logind-session.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 0afb065b2b..960a24d1a7 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -5,6 +5,7 @@
#include <linux/kd.h>
#include <linux/vt.h>
#include <signal.h>
+#include <stdio_ext.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
@@ -175,9 +176,8 @@ int session_save(Session *s) {
if (r < 0)
goto fail;
- assert(s->user);
-
- fchmod(fileno(f), 0644);
+ (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+ (void) fchmod(fileno(f), 0644);
fprintf(f,
"# This is private data. Do not parse.\n"

View File

@ -0,0 +1,27 @@
From f94c1bbec9e2c3efcbafd61ea1fdf8dbc3245d1b Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 3 Aug 2018 20:19:38 +0200
Subject: [PATCH] units: set StopWhenUnneeded= for the user slice units too
We'd like them to go away, just like the user-runtime-dir@.service when
they aren't needed anymore.
(cherry picked from commit 1007473b49b5aaeef0e53cd4a15f4ed8cf721926)
Related: #1642460
---
units/user-.slice.d/10-defaults.conf | 1 +
1 file changed, 1 insertion(+)
diff --git a/units/user-.slice.d/10-defaults.conf b/units/user-.slice.d/10-defaults.conf
index efc9d37c8e..1147e7aed9 100644
--- a/units/user-.slice.d/10-defaults.conf
+++ b/units/user-.slice.d/10-defaults.conf
@@ -10,6 +10,7 @@
[Unit]
Description=User Slice of UID %j
After=systemd-user-sessions.service
+StopWhenUnneeded=yes
[Slice]
TasksMax=80%

View File

@ -0,0 +1,29 @@
From 50a4e03d2da89df32f2f63eb56051d789508ae75 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 6 Aug 2018 18:15:07 +0200
Subject: [PATCH] units: improve Description= string a bit
Let's not use the word "wrapper", as it's not clear what that is, and in
some way any unit file is a "wrapper"... let's simply say that it's
about the runtime directory.
(cherry picked from commit 14df094a51e87013d96ac697ae4f14593cbcad39)
Related: #1642460
---
units/user-runtime-dir@.service.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/units/user-runtime-dir@.service.in b/units/user-runtime-dir@.service.in
index bfd6488d61..63db1cca6a 100644
--- a/units/user-runtime-dir@.service.in
+++ b/units/user-runtime-dir@.service.in
@@ -8,7 +8,7 @@
# (at your option) any later version.
[Unit]
-Description=/run/user/%i mount wrapper
+Description=User runtime directory /run/user/%i
After=systemd-user-sessions.service
StopWhenUnneeded=yes

View File

@ -0,0 +1,77 @@
From 9e9c6cbbdd60f4538cee041ffe3f9cd831c5de17 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 3 Aug 2018 20:21:27 +0200
Subject: [PATCH] logind: improve logging in manager_connect_console()
let's make sure we log about every failure
Also, complain about systems where /dev/tty0 exists but
/sys/class/tty/tty0/active does not. Such systems (usually container
environments) are pretty broken as they mount something that is not a VC
to /dev/tty0 and they really shouldn't.
Systems should either have a VC or not, but not badly fake one by
mounting things wildly.
This just adds a warning message, as before we'll simply turn off VC
handling in this case.
(cherry picked from commit 0b6d55cae9b8adc507fbea95d1b2874729a77386)
Related: #1642460
---
src/login/logind.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/login/logind.c b/src/login/logind.c
index 52fcee933c..1b366cd55f 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -815,28 +815,28 @@ static int manager_connect_console(Manager *m) {
assert(m);
assert(m->console_active_fd < 0);
- /* On certain architectures (S390 and Xen, and containers),
- /dev/tty0 does not exist, so don't fail if we can't open
- it. */
+ /* On certain systems (such as S390, Xen, and containers) /dev/tty0 does not exist (as there is no VC), so
+ * don't fail if we can't open it. */
+
if (access("/dev/tty0", F_OK) < 0)
return 0;
m->console_active_fd = open("/sys/class/tty/tty0/active", O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (m->console_active_fd < 0) {
- /* On some systems the device node /dev/tty0 may exist
- * even though /sys/class/tty/tty0 does not. */
- if (errno == ENOENT)
+ /* On some systems /dev/tty0 may exist even though /sys/class/tty/tty0 does not. These are broken, but
+ * common. Let's complain but continue anyway. */
+ if (errno == ENOENT) {
+ log_warning_errno(errno, "System has /dev/tty0 but not /sys/class/tty/tty0/active which is broken, ignoring: %m");
return 0;
+ }
return log_error_errno(errno, "Failed to open /sys/class/tty/tty0/active: %m");
}
r = sd_event_add_io(m->event, &m->console_active_event_source, m->console_active_fd, 0, manager_dispatch_console, m);
- if (r < 0) {
- log_error("Failed to watch foreground console");
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to watch foreground console: %m");
/*
* SIGRTMIN is used as global VT-release signal, SIGRTMIN + 1 is used
@@ -855,7 +855,7 @@ static int manager_connect_console(Manager *m) {
r = sd_event_add_signal(m->event, NULL, SIGRTMIN, manager_vt_switch, m);
if (r < 0)
- return r;
+ return log_error_errno(r, "Failed to subscribe to signal: %m");
return 0;
}

View File

@ -0,0 +1,90 @@
From 4703c08fe3a8bfa1bc9b893e8bde365b1cbeffd9 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 6 Aug 2018 18:14:11 +0200
Subject: [PATCH] logind: save/restore User object's "stopping" field during
restarts
Whether we are stopping or not is highly relevant, hence don't forget it
across restarts.
(cherry picked from commit d865bc024bf28c17120d7322a81e9a99997a59f6)
Related: #1642460
---
src/login/logind-user.c | 20 +++++++++++++++-----
src/login/logind-user.h | 5 +++--
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 17ed361411..35b2ca5489 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -136,9 +136,11 @@ static int user_save_internal(User *u) {
fprintf(f,
"# This is private data. Do not parse.\n"
"NAME=%s\n"
- "STATE=%s\n",
+ "STATE=%s\n" /* friendly user-facing state */
+ "STOPPING=%s\n", /* low-level state */
u->name,
- user_state_to_string(user_get_state(u)));
+ user_state_to_string(user_get_state(u)),
+ yes_no(u->stopping));
/* LEGACY: no-one reads RUNTIME= anymore, drop it at some point */
if (u->runtime_path)
@@ -277,14 +279,14 @@ int user_save(User *u) {
}
int user_load(User *u) {
- _cleanup_free_ char *realtime = NULL, *monotonic = NULL;
+ _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL;
int r;
assert(u);
r = parse_env_file(NULL, u->state_file, NEWLINE,
"SERVICE_JOB", &u->service_job,
- "SLICE_JOB", &u->slice_job,
+ "STOPPING", &stopping,
"REALTIME", &realtime,
"MONOTONIC", &monotonic,
NULL);
@@ -293,12 +295,20 @@ int user_load(User *u) {
if (r < 0)
return log_error_errno(r, "Failed to read %s: %m", u->state_file);
+ if (stopping) {
+ r = parse_boolean(stopping);
+ if (r < 0)
+ log_debug_errno(r, "Failed to parse 'STOPPING' boolean: %s", stopping);
+ else
+ u->stopping = r;
+ }
+
if (realtime)
timestamp_deserialize(realtime, &u->timestamp.realtime);
if (monotonic)
timestamp_deserialize(monotonic, &u->timestamp.monotonic);
- return r;
+ return 0;
}
static int user_start_service(User *u) {
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index eba2325284..03e020b870 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -36,8 +36,9 @@ struct User {
dual_timestamp timestamp;
bool in_gc_queue:1;
- bool started:1;
- bool stopping:1;
+
+ bool started:1; /* Whenever the user being started, has been started or is being stopped again. */
+ bool stopping:1; /* Whenever the user is being stopped or has been stopped. */
LIST_HEAD(Session, sessions);
LIST_FIELDS(User, gc_queue);

View File

@ -0,0 +1,25 @@
From eebbeada76b0fa4e252ecf4e25b088733636fe89 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 6 Aug 2018 18:19:45 +0200
Subject: [PATCH] logind: correct bad clean-up path
(cherry picked from commit d88ffeeeefda4c3447223fd36f8e30f23c931e48)
Related: #1642460
---
src/login/logind-dbus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index ae9abc9bce..4b2c418453 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -845,7 +845,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
r = sd_bus_message_enter_container(message, 'a', "(sv)");
if (r < 0)
- return r;
+ goto fail;
r = session_start(session, message);
if (r < 0)

View File

@ -0,0 +1,25 @@
From 7662d7c86d1fbb01693d4eb008fa27bf1e0030a9 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 6 Aug 2018 18:21:37 +0200
Subject: [PATCH] logind: fix bad error propagation
(cherry picked from commit cce08496e7353e3e9903b42695aba3f9d259b90a)
Related: #1642460
---
src/login/logind-seat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index f68fc0ceaa..9e4f009643 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -175,7 +175,7 @@ static int vt_allocate(unsigned int vtnr) {
xsprintf(p, "/dev/tty%u", vtnr);
fd = open_terminal(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
- return -errno;
+ return fd;
return 0;
}

View File

@ -0,0 +1,42 @@
From 35f9a7f8f4e8917725349fe764706658c02537ca Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 6 Aug 2018 19:02:29 +0200
Subject: [PATCH] logind: never elect a session that is stopping as display
(cherry picked from commit 04857cd801022d9f9933efb484c6253572f09870)
Related: #1642460
---
src/login/logind-user.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 35b2ca5489..3e4c99bdbd 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -613,11 +613,10 @@ int user_kill(User *u, int signo) {
}
static bool elect_display_filter(Session *s) {
- /* Return true if the session is a candidate for the users primary
- * session or display. */
+ /* Return true if the session is a candidate for the users primary session or display. */
assert(s);
- return (s->class == SESSION_USER && !s->stopping);
+ return s->class == SESSION_USER && s->started && !s->stopping;
}
static int elect_display_compare(Session *s1, Session *s2) {
@@ -663,9 +662,8 @@ void user_elect_display(User *u) {
assert(u);
- /* This elects a primary session for each user, which we call
- * the "display". We try to keep the assignment stable, but we
- * "upgrade" to better choices. */
+ /* This elects a primary session for each user, which we call the "display". We try to keep the assignment
+ * stable, but we "upgrade" to better choices. */
log_debug("Electing new display for user %s", u->name);
LIST_FOREACH(sessions_by_user, s, u->sessions) {

View File

@ -0,0 +1,60 @@
From 83c49a5e54dffc3dfa85b79f6375cd0a42a4ff76 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 6 Aug 2018 19:34:39 +0200
Subject: [PATCH] logind: introduce little helper that checks whether a session
is ready
(cherry picked from commit b1951bc83ffbbb92ba4de7b9cba845421c2f35b1)
Related: #1642460
---
src/login/logind-session-dbus.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c
index 88a2d33dc8..03585b7f8e 100644
--- a/src/login/logind-session-dbus.c
+++ b/src/login/logind-session-dbus.c
@@ -704,6 +704,15 @@ int session_send_lock_all(Manager *m, bool lock) {
return r;
}
+static bool session_ready(Session *s) {
+ assert(s);
+
+ /* Returns true when the session is ready, i.e. all jobs we enqueued for it are done (regardless if successful or not) */
+
+ return !s->scope_job &&
+ !s->user->service_job;
+}
+
int session_send_create_reply(Session *s, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
_cleanup_close_ int fifo_fd = -1;
@@ -711,14 +720,13 @@ int session_send_create_reply(Session *s, sd_bus_error *error) {
assert(s);
- /* This is called after the session scope and the user service
- * were successfully created, and finishes where
+ /* This is called after the session scope and the user service were successfully created, and finishes where
* bus_manager_create_session() left off. */
if (!s->create_message)
return 0;
- if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
+ if (!sd_bus_error_is_set(error) && !session_ready(s))
return 0;
c = s->create_message;
@@ -731,8 +739,7 @@ int session_send_create_reply(Session *s, sd_bus_error *error) {
if (fifo_fd < 0)
return fifo_fd;
- /* Update the session state file before we notify the client
- * about the result. */
+ /* Update the session state file before we notify the client about the result. */
session_save(s);
p = session_bus_path(s);

View File

@ -0,0 +1,40 @@
From 31aa21a13f9b91486b1a95c5b73fa088af77fcb4 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 6 Aug 2018 19:35:44 +0200
Subject: [PATCH] logind: propagate session stop errors
Let's propagate errors from stopping sessions via seat_stop(). This is
similar to how we propagate such errors in user_stop() for all sessions
associated with a user.
Note that we propagate these errors, but we don't abort the function.
(cherry picked from commit e6958b7ea33813b085966ac25817a957c0dad7f9)
Related: #1642460
---
src/login/logind-seat.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c
index 9e4f009643..96c34a6c9e 100644
--- a/src/login/logind-seat.c
+++ b/src/login/logind-seat.c
@@ -431,7 +431,7 @@ int seat_start(Seat *s) {
}
int seat_stop(Seat *s, bool force) {
- int r = 0;
+ int r;
assert(s);
@@ -441,7 +441,7 @@ int seat_stop(Seat *s, bool force) {
"SEAT_ID=%s", s->id,
LOG_MESSAGE("Removed seat %s.", s->id));
- seat_stop_sessions(s, force);
+ r = seat_stop_sessions(s, force);
unlink(s->state_file);
seat_add_to_gc_queue(s);

View File

@ -0,0 +1,618 @@
From a05c1077911652954c8b9e82cfdc0fc643eca782 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 6 Aug 2018 21:44:45 +0200
Subject: [PATCH] logind: rework how we manage the slice and
user-runtime-dir@.service unit for each user
Instead of managing it explicitly, let's simplify things and rely on
regular Wants=/Requires= dependencies to pull in these units from
user@.service and the session scope, and StopWhenUneeded= to stop these
auxiliary units again. This way, they can be pulled in easily by
unrelated units too.
This simplifies things quite a bit: for each session we now only need to
manage the session scope, and for each user the user@.service, the other
units are not something we need to manage anymore.
This patch also makes sure that if user@.service of a user is masked we
will continue to work, and user-runtime-dir@.service will still be
correctly pulled in, as it is now a dependency of the scope unit.
Fixes: #9461
Replaces: #5546
(cherry picked from commit 25a1ab4ed48b72e974f77a68dcbe3521014787bb)
Related: #1642460
---
src/login/logind-dbus.c | 58 ++++++++--------
src/login/logind-session.c | 64 ++++++++++--------
src/login/logind-session.h | 2 +-
src/login/logind-user.c | 134 ++++++++++++++-----------------------
src/login/logind-user.h | 7 +-
src/login/logind.c | 2 +-
src/login/logind.h | 2 +-
7 files changed, 123 insertions(+), 146 deletions(-)
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 4b2c418453..7eba617fff 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -847,7 +847,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (r < 0)
goto fail;
- r = session_start(session, message);
+ r = session_start(session, message, error);
if (r < 0)
goto fail;
@@ -3110,24 +3110,20 @@ const sd_bus_vtable manager_vtable[] = {
};
static int session_jobs_reply(Session *s, const char *unit, const char *result) {
- int r = 0;
-
assert(s);
assert(unit);
if (!s->started)
- return r;
+ return 0;
- if (streq(result, "done"))
- r = session_send_create_reply(s, NULL);
- else {
+ if (result && !streq(result, "done")) {
_cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
- sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
- r = session_send_create_reply(s, &e);
+ sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit '%s' failed with '%s'", unit, result);
+ return session_send_create_reply(s, &e);
}
- return r;
+ return session_send_create_reply(s, NULL);
}
int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -3160,30 +3156,29 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err
}
session = hashmap_get(m->session_units, unit);
- if (session && streq_ptr(path, session->scope_job)) {
- session->scope_job = mfree(session->scope_job);
- session_jobs_reply(session, unit, result);
+ if (session) {
+ if (streq_ptr(path, session->scope_job)) {
+ session->scope_job = mfree(session->scope_job);
+ (void) session_jobs_reply(session, unit, result);
+
+ session_save(session);
+ user_save(session->user);
+ }
- session_save(session);
- user_save(session->user);
session_add_to_gc_queue(session);
}
user = hashmap_get(m->user_units, unit);
- if (user &&
- (streq_ptr(path, user->service_job) ||
- streq_ptr(path, user->slice_job))) {
-
- if (streq_ptr(path, user->service_job))
+ if (user) {
+ if (streq_ptr(path, user->service_job)) {
user->service_job = mfree(user->service_job);
- if (streq_ptr(path, user->slice_job))
- user->slice_job = mfree(user->slice_job);
+ LIST_FOREACH(sessions_by_user, session, user->sessions)
+ (void) session_jobs_reply(session, unit, NULL /* don't propagate user service failures to the client */);
- LIST_FOREACH(sessions_by_user, session, user->sessions)
- session_jobs_reply(session, unit, result);
+ user_save(user);
+ }
- user_save(user);
user_add_to_gc_queue(user);
}
@@ -3315,13 +3310,14 @@ int manager_start_scope(
pid_t pid,
const char *slice,
const char *description,
- const char *after,
- const char *after2,
+ char **wants,
+ char **after,
sd_bus_message *more_properties,
sd_bus_error *error,
char **job) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
+ char **i;
int r;
assert(manager);
@@ -3359,14 +3355,14 @@ int manager_start_scope(
return r;
}
- if (!isempty(after)) {
- r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
+ STRV_FOREACH(i, wants) {
+ r = sd_bus_message_append(m, "(sv)", "Wants", "as", 1, *i);
if (r < 0)
return r;
}
- if (!isempty(after2)) {
- r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
+ STRV_FOREACH(i, after) {
+ r = sd_bus_message_append(m, "(sv)", "After", "as", 1, *i);
if (r < 0)
return r;
}
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index 960a24d1a7..d56b48a732 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -27,6 +27,7 @@
#include "path-util.h"
#include "process-util.h"
#include "string-table.h"
+#include "strv.h"
#include "terminal-util.h"
#include "user-util.h"
#include "util.h"
@@ -560,17 +561,18 @@ int session_activate(Session *s) {
return 0;
}
-static int session_start_scope(Session *s, sd_bus_message *properties) {
+static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_error *error) {
int r;
assert(s);
assert(s->user);
if (!s->scope) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char *scope, *job = NULL;
+ _cleanup_free_ char *scope = NULL;
const char *description;
+ s->scope_job = mfree(s->scope_job);
+
scope = strjoin("session-", s->id, ".scope");
if (!scope)
return log_oom();
@@ -583,21 +585,15 @@ static int session_start_scope(Session *s, sd_bus_message *properties) {
s->leader,
s->user->slice,
description,
- "systemd-logind.service",
- "systemd-user-sessions.service",
+ STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */
+ STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */
properties,
- &error,
- &job);
- if (r < 0) {
- log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(&error, r));
- free(scope);
- return r;
- } else {
- s->scope = scope;
+ error,
+ &s->scope_job);
+ if (r < 0)
+ return log_error_errno(r, "Failed to start session scope %s: %s", scope, bus_error_message(error, r));
- free(s->scope_job);
- s->scope_job = job;
- }
+ s->scope = TAKE_PTR(scope);
}
if (s->scope)
@@ -606,7 +602,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties) {
return 0;
}
-int session_start(Session *s, sd_bus_message *properties) {
+int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
int r;
assert(s);
@@ -614,6 +610,9 @@ int session_start(Session *s, sd_bus_message *properties) {
if (!s->user)
return -ESTALE;
+ if (s->stopping)
+ return -EINVAL;
+
if (s->started)
return 0;
@@ -621,8 +620,7 @@ int session_start(Session *s, sd_bus_message *properties) {
if (r < 0)
return r;
- /* Create cgroup */
- r = session_start_scope(s, properties);
+ r = session_start_scope(s, properties, error);
if (r < 0)
return r;
@@ -673,21 +671,24 @@ static int session_stop_scope(Session *s, bool force) {
* that is left in the scope is "left-over". Informing systemd about this has the benefit that it will log
* when killing any processes left after this point. */
r = manager_abandon_scope(s->manager, s->scope, &error);
- if (r < 0)
+ if (r < 0) {
log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
+ sd_bus_error_free(&error);
+ }
+
+ s->scope_job = mfree(s->scope_job);
/* Optionally, let's kill everything that's left now. */
if (force || manager_shall_kill(s->manager, s->user->name)) {
- char *job = NULL;
- r = manager_stop_unit(s->manager, s->scope, &error, &job);
- if (r < 0)
- return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
+ r = manager_stop_unit(s->manager, s->scope, &error, &s->scope_job);
+ if (r < 0) {
+ if (force)
+ return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
- free(s->scope_job);
- s->scope_job = job;
+ log_warning_errno(r, "Failed to stop session scope, ignoring: %s", bus_error_message(&error, r));
+ }
} else {
- s->scope_job = mfree(s->scope_job);
/* With no killing, this session is allowed to persist in "closing" state indefinitely.
* Therefore session stop and session removal may be two distinct events.
@@ -707,8 +708,17 @@ int session_stop(Session *s, bool force) {
assert(s);
+ /* This is called whenever we begin with tearing down a session record. It's called in four cases: explicit API
+ * request via the bus (either directly for the session object or for the seat or user object this session
+ * belongs to; 'force' is true), or due to automatic GC (i.e. scope vanished; 'force' is false), or because the
+ * session FIFO saw an EOF ('force' is false), or because the release timer hit ('force' is false). */
+
if (!s->user)
return -ESTALE;
+ if (!s->started)
+ return 0;
+ if (s->stopping)
+ return 0;
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
diff --git a/src/login/logind-session.h b/src/login/logind-session.h
index 572f2545c1..7d17d9a25f 100644
--- a/src/login/logind-session.h
+++ b/src/login/logind-session.h
@@ -124,7 +124,7 @@ 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_create_fifo(Session *s);
-int session_start(Session *s, sd_bus_message *properties);
+int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error);
int session_stop(Session *s, bool force);
int session_finalize(Session *s);
int session_release(Session *s);
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 3e4c99bdbd..39fc76f4dc 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -68,6 +68,10 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
if (r < 0)
return r;
+ r = unit_name_build("user-runtime-dir", lu, ".service", &u->runtime_dir_service);
+ if (r < 0)
+ return r;
+
r = hashmap_put(m->users, UID_TO_PTR(uid), u);
if (r < 0)
return r;
@@ -80,6 +84,10 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
if (r < 0)
return r;
+ r = hashmap_put(m->user_units, u->runtime_dir_service, u);
+ if (r < 0)
+ return r;
+
*ret = TAKE_PTR(u);
return 0;
}
@@ -97,15 +105,18 @@ User *user_free(User *u) {
if (u->service)
hashmap_remove_value(u->manager->user_units, u->service, u);
+ if (u->runtime_dir_service)
+ hashmap_remove_value(u->manager->user_units, u->runtime_dir_service, u);
+
if (u->slice)
hashmap_remove_value(u->manager->user_units, u->slice, u);
hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u);
- u->slice_job = mfree(u->slice_job);
u->service_job = mfree(u->service_job);
u->service = mfree(u->service);
+ u->runtime_dir_service = mfree(u->runtime_dir_service);
u->slice = mfree(u->slice);
u->runtime_path = mfree(u->runtime_path);
u->state_file = mfree(u->state_file);
@@ -149,9 +160,6 @@ static int user_save_internal(User *u) {
if (u->service_job)
fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
- if (u->slice_job)
- fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
-
if (u->display)
fprintf(f, "DISPLAY=%s\n", u->display->id);
@@ -311,66 +319,46 @@ int user_load(User *u) {
return 0;
}
-static int user_start_service(User *u) {
+static void user_start_service(User *u) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
int r;
assert(u);
+ /* Start the service containing the "systemd --user" instance (user@.service). Note that we don't explicitly
+ * start the per-user slice or the systemd-runtime-dir@.service instance, as those are pulled in both by
+ * user@.service and the session scopes as dependencies. */
+
u->service_job = mfree(u->service_job);
- r = manager_start_unit(
- u->manager,
- u->service,
- &error,
- &job);
+ r = manager_start_unit(u->manager, u->service, &error, &u->service_job);
if (r < 0)
/* we don't fail due to this, let's try to continue */
log_full_errno(sd_bus_error_has_name(&error, BUS_ERROR_UNIT_MASKED) ? LOG_DEBUG : LOG_WARNING, r,
"Failed to start user service '%s', ignoring: %s", u->service, bus_error_message(&error, r));
- else
- u->service_job = job;
-
- return 0;
}
int user_start(User *u) {
- int r;
-
assert(u);
if (u->started && !u->stopping)
return 0;
- /*
- * If u->stopping is set, the user is marked for removal and the slice
- * and service stop-jobs are queued. We have to clear that flag before
- * queing the start-jobs again. If they succeed, the user object can be
- * re-used just fine (pid1 takes care of job-ordering and proper
- * restart), but if they fail, we want to force another user_stop() so
- * possibly pending units are stopped.
- * Note that we don't clear u->started, as we have no clue what state
- * the user is in on failure here. Hence, we pretend the user is
- * running so it will be properly taken down by GC. However, we clearly
- * return an error from user_start() in that case, so no further
- * reference to the user is taken.
- */
+ /* If u->stopping is set, the user is marked for removal and service stop-jobs are queued. We have to clear
+ * that flag before queing the start-jobs again. If they succeed, the user object can be re-used just fine
+ * (pid1 takes care of job-ordering and proper restart), but if they fail, we want to force another user_stop()
+ * so possibly pending units are stopped. */
u->stopping = false;
if (!u->started)
log_debug("Starting services for new user %s.", u->name);
- /* Save the user data so far, because pam_systemd will read the
- * XDG_RUNTIME_DIR out of it while starting up systemd --user.
- * We need to do user_save_internal() because we have not
- * "officially" started yet. */
+ /* Save the user data so far, because pam_systemd will read the XDG_RUNTIME_DIR out of it while starting up
+ * systemd --user. We need to do user_save_internal() because we have not "officially" started yet. */
user_save_internal(u);
- /* Spawn user systemd */
- r = user_start_service(u);
- if (r < 0)
- return r;
+ /* Start user@UID.service */
+ user_start_service(u);
if (!u->started) {
if (!dual_timestamp_is_set(&u->timestamp))
@@ -385,68 +373,50 @@ int user_start(User *u) {
return 0;
}
-static int user_stop_slice(User *u) {
+static void user_stop_service(User *u) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
int r;
assert(u);
+ assert(u->service);
- r = manager_stop_unit(u->manager, u->slice, &error, &job);
- if (r < 0) {
- log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
- return r;
- }
+ /* The reverse of user_start_service(). Note that we only stop user@UID.service here, and let StopWhenUnneeded=
+ * deal with the slice and the user-runtime-dir@.service instance. */
- free(u->slice_job);
- u->slice_job = job;
-
- return r;
-}
-
-static int user_stop_service(User *u) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
- int r;
-
- assert(u);
-
- r = manager_stop_unit(u->manager, u->service, &error, &job);
- if (r < 0) {
- log_error("Failed to stop user service: %s", bus_error_message(&error, r));
- return r;
- }
+ u->service_job = mfree(u->service_job);
- free_and_replace(u->service_job, job);
- return r;
+ r = manager_stop_unit(u->manager, u->service, &error, &u->service_job);
+ if (r < 0)
+ log_warning_errno(r, "Failed to stop user service '%s', ignoring: %s", u->service, bus_error_message(&error, r));
}
int user_stop(User *u, bool force) {
Session *s;
- int r = 0, k;
+ int r = 0;
assert(u);
- /* Stop jobs have already been queued */
- if (u->stopping) {
+ /* This is called whenever we begin with tearing down a user record. It's called in two cases: explicit API
+ * request to do so via the bus (in which case 'force' is true) and automatically due to GC, if there's no
+ * session left pinning it (in which case 'force' is false). Note that this just initiates tearing down of the
+ * user, the User object will remain in memory until user_finalize() is called, see below. */
+
+ if (!u->started)
+ return 0;
+
+ if (u->stopping) { /* Stop jobs have already been queued */
user_save(u);
- return r;
+ return 0;
}
LIST_FOREACH(sessions_by_user, s, u->sessions) {
+ int k;
+
k = session_stop(s, force);
if (k < 0)
r = k;
}
- /* Kill systemd */
- k = user_stop_service(u);
- if (k < 0)
- r = k;
-
- /* Kill cgroup */
- k = user_stop_slice(u);
- if (k < 0)
- r = k;
+ user_stop_service(u);
u->stopping = true;
@@ -461,6 +431,9 @@ int user_finalize(User *u) {
assert(u);
+ /* Called when the user is really ready to be freed, i.e. when all unit stop jobs and suchlike for it are
+ * done. This is called as a result of an earlier user_done() when all jobs are completed. */
+
if (u->started)
log_debug("User %s logged out.", u->name);
@@ -554,9 +527,6 @@ bool user_may_gc(User *u, bool drop_not_started) {
if (user_check_linger_file(u) > 0)
return false;
- if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
- return false;
-
if (u->service_job && manager_job_is_active(u->manager, u->service_job))
return false;
@@ -581,7 +551,7 @@ UserState user_get_state(User *u) {
if (u->stopping)
return USER_CLOSING;
- if (!u->started || u->slice_job || u->service_job)
+ if (!u->started || u->service_job)
return USER_OPENING;
if (u->sessions) {
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index 03e020b870..5e1f7b813a 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -25,11 +25,12 @@ struct User {
char *name;
char *state_file;
char *runtime_path;
- char *slice;
- char *service;
+
+ char *slice; /* user-UID.slice */
+ char *service; /* user@UID.service */
+ char *runtime_dir_service; /* user-runtime-dir@UID.service */
char *service_job;
- char *slice_job;
Session *display;
diff --git a/src/login/logind.c b/src/login/logind.c
index 1b366cd55f..6c208c8e89 100644
--- a/src/login/logind.c
+++ b/src/login/logind.c
@@ -1158,7 +1158,7 @@ static int manager_startup(Manager *m) {
user_start(user);
HASHMAP_FOREACH(session, m->sessions, i)
- session_start(session, NULL);
+ (void) session_start(session, NULL, NULL);
HASHMAP_FOREACH(inhibitor, m->inhibitors, i)
inhibitor_start(inhibitor);
diff --git a/src/login/logind.h b/src/login/logind.h
index a6ebc9e152..ae4d74076b 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -161,7 +161,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_message *more_properties, sd_bus_error *error, char **job);
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, sd_bus_message *more_properties, sd_bus_error *error, char **job);
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);

View File

@ -0,0 +1,291 @@
From 35455408393cb29a5e49fd769c4823b6a6f886b4 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 7 Aug 2018 11:02:00 +0200
Subject: [PATCH] logind: optionally, keep the user@.service instance for
eached logged in user around for a while
This should speed up rapid logout/login cycles a bit.
By default this timeout is now set to 10s.
Fixes: #8410
Replaces: #4434
(cherry picked from commit 9afe9efb9340588db553950727a2a9672dc3db24)
Resolves: #1642460
---
man/logind.conf.xml | 11 +++++
src/login/logind-core.c | 2 +
src/login/logind-dbus.c | 1 +
src/login/logind-gperf.gperf | 1 +
src/login/logind-session.c | 4 ++
src/login/logind-user.c | 88 +++++++++++++++++++++++++++++++++---
src/login/logind-user.h | 7 ++-
src/login/logind.h | 1 +
8 files changed, 107 insertions(+), 8 deletions(-)
diff --git a/man/logind.conf.xml b/man/logind.conf.xml
index 7d7e869a26..0cf8a7d1f2 100644
--- a/man/logind.conf.xml
+++ b/man/logind.conf.xml
@@ -184,6 +184,17 @@
5.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>UserStopDelaySec=</varname></term>
+
+ <listitem><para>Specifies how long to keep the user record and per-user service
+ <filename>user@.service</filename> around for a user after they logged out fully. If set to zero, the per-user
+ service is terminated immediately when the last session of the user has ended. If this option is configured to
+ non-zero rapid logout/login cycles are sped up, as the user's service manager is not constantly restarted. If
+ set to <literal>infinity</literal> the per-user service for a user is never terminated again after first login,
+ and continues to run until system shutdown. Defaults to 10s.</para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>HandlePowerKey=</varname></term>
<term><varname>HandleSuspendKey=</varname></term>
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index f598bbaa1c..678c708df1 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -27,6 +27,8 @@ void manager_reset_config(Manager *m) {
m->reserve_vt = 6;
m->remove_ipc = false;
m->inhibit_delay_max = 5 * USEC_PER_SEC;
+ m->user_stop_delay = 10 * USEC_PER_SEC;
+
m->handle_power_key = HANDLE_POWEROFF;
m->handle_suspend_key = HANDLE_SUSPEND;
m->handle_hibernate_key = HANDLE_HIBERNATE;
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 7eba617fff..6586280269 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -2695,6 +2695,7 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("UserStopDelayUSec", "t", NULL, offsetof(Manager, user_stop_delay), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf
index c85339dcd3..8829ce7d85 100644
--- a/src/login/logind-gperf.gperf
+++ b/src/login/logind-gperf.gperf
@@ -23,6 +23,7 @@ Login.KillUserProcesses, config_parse_bool, 0, offse
Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manager, kill_only_users)
Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users)
Login.InhibitDelayMaxSec, config_parse_sec, 0, offsetof(Manager, inhibit_delay_max)
+Login.UserStopDelaySec, config_parse_sec, 0, offsetof(Manager, user_stop_delay)
Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manager, handle_power_key)
Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key)
Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key)
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index d56b48a732..dd4ac9482a 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -101,6 +101,8 @@ Session* session_free(Session *s) {
if (s->user->display == s)
s->user->display = NULL;
+
+ user_update_last_session_timer(s->user);
}
if (s->seat) {
@@ -142,6 +144,8 @@ void session_set_user(Session *s, User *u) {
s->user = u;
LIST_PREPEND(sessions_by_user, u->sessions, s);
+
+ user_update_last_session_timer(u);
}
static void session_save_devices(Session *s, FILE *f) {
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 39fc76f4dc..f23fcbe674 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -47,6 +47,7 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
.manager = m,
.uid = uid,
.gid = gid,
+ .last_session_timestamp = USEC_INFINITY,
};
u->name = strdup(name);
@@ -113,6 +114,8 @@ User *user_free(User *u) {
hashmap_remove_value(u->manager->users, UID_TO_PTR(u->uid), u);
+ (void) sd_event_source_unref(u->timer_event_source);
+
u->service_job = mfree(u->service_job);
u->service = mfree(u->service);
@@ -170,6 +173,10 @@ static int user_save_internal(User *u) {
u->timestamp.realtime,
u->timestamp.monotonic);
+ if (u->last_session_timestamp != USEC_INFINITY)
+ fprintf(f, "LAST_SESSION_TIMESTAMP=" USEC_FMT "\n",
+ u->last_session_timestamp);
+
if (u->sessions) {
Session *i;
bool first;
@@ -287,16 +294,17 @@ int user_save(User *u) {
}
int user_load(User *u) {
- _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL;
+ _cleanup_free_ char *realtime = NULL, *monotonic = NULL, *stopping = NULL, *last_session_timestamp = NULL;
int r;
assert(u);
r = parse_env_file(NULL, u->state_file, NEWLINE,
- "SERVICE_JOB", &u->service_job,
- "STOPPING", &stopping,
- "REALTIME", &realtime,
- "MONOTONIC", &monotonic,
+ "SERVICE_JOB", &u->service_job,
+ "STOPPING", &stopping,
+ "REALTIME", &realtime,
+ "MONOTONIC", &monotonic,
+ "LAST_SESSION_TIMESTAMP", &last_session_timestamp,
NULL);
if (r == -ENOENT)
return 0;
@@ -312,9 +320,11 @@ int user_load(User *u) {
}
if (realtime)
- timestamp_deserialize(realtime, &u->timestamp.realtime);
+ (void) timestamp_deserialize(realtime, &u->timestamp.realtime);
if (monotonic)
- timestamp_deserialize(monotonic, &u->timestamp.monotonic);
+ (void) timestamp_deserialize(monotonic, &u->timestamp.monotonic);
+ if (last_session_timestamp)
+ (void) timestamp_deserialize(last_session_timestamp, &u->last_session_timestamp);
return 0;
}
@@ -524,6 +534,17 @@ bool user_may_gc(User *u, bool drop_not_started) {
if (u->sessions)
return false;
+ if (u->last_session_timestamp != USEC_INFINITY) {
+ /* All sessions have been closed. Let's see if we shall leave the user record around for a bit */
+
+ if (u->manager->user_stop_delay == USEC_INFINITY)
+ return false; /* Leave it around forever! */
+ if (u->manager->user_stop_delay > 0 &&
+ now(CLOCK_MONOTONIC) < usec_add(u->last_session_timestamp, u->manager->user_stop_delay))
+ return false; /* Leave it around for a bit longer. */
+ }
+
+ /* Is this a user that shall stay around forever? */
if (user_check_linger_file(u) > 0)
return false;
@@ -649,6 +670,59 @@ void user_elect_display(User *u) {
}
}
+static int user_stop_timeout_callback(sd_event_source *es, uint64_t usec, void *userdata) {
+ User *u = userdata;
+
+ assert(u);
+ user_add_to_gc_queue(u);
+
+ return 0;
+}
+
+void user_update_last_session_timer(User *u) {
+ int r;
+
+ assert(u);
+
+ if (u->sessions) {
+ /* There are sessions, turn off the timer */
+ u->last_session_timestamp = USEC_INFINITY;
+ u->timer_event_source = sd_event_source_unref(u->timer_event_source);
+ return;
+ }
+
+ if (u->last_session_timestamp != USEC_INFINITY)
+ return; /* Timer already started */
+
+ u->last_session_timestamp = now(CLOCK_MONOTONIC);
+
+ assert(!u->timer_event_source);
+
+ if (u->manager->user_stop_delay == 0 || u->manager->user_stop_delay == USEC_INFINITY)
+ return;
+
+ if (sd_event_get_state(u->manager->event) == SD_EVENT_FINISHED) {
+ log_debug("Not allocating user stop timeout, since we are already exiting.");
+ return;
+ }
+
+ r = sd_event_add_time(u->manager->event,
+ &u->timer_event_source,
+ CLOCK_MONOTONIC,
+ usec_add(u->last_session_timestamp, u->manager->user_stop_delay), 0,
+ user_stop_timeout_callback, u);
+ if (r < 0)
+ log_warning_errno(r, "Failed to enqueue user stop event source, ignoring: %m");
+
+ if (DEBUG_LOGGING) {
+ char s[FORMAT_TIMESPAN_MAX];
+
+ log_debug("Last session of user '%s' logged out, terminating user context in %s.",
+ u->name,
+ format_timespan(s, sizeof(s), u->manager->user_stop_delay, USEC_PER_MSEC));
+ }
+}
+
static const char* const user_state_table[_USER_STATE_MAX] = {
[USER_OFFLINE] = "offline",
[USER_OPENING] = "opening",
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index 5e1f7b813a..e05646adc9 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -34,7 +34,11 @@ struct User {
Session *display;
- dual_timestamp timestamp;
+ dual_timestamp timestamp; /* When this User object was 'started' the first time */
+ usec_t last_session_timestamp; /* When the number of sessions of this user went from 1 to 0 the last time */
+
+ /* Set up when the last session of the user logs out */
+ sd_event_source *timer_event_source;
bool in_gc_queue:1;
@@ -62,6 +66,7 @@ int user_load(User *u);
int user_kill(User *u, int signo);
int user_check_linger_file(User *u);
void user_elect_display(User *u);
+void user_update_last_session_timer(User *u);
extern const sd_bus_vtable user_vtable[];
int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
diff --git a/src/login/logind.h b/src/login/logind.h
index ae4d74076b..7288dd7445 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -62,6 +62,7 @@ struct Manager {
Hashmap *user_units;
usec_t inhibit_delay_max;
+ usec_t user_stop_delay;
/* If an action is currently being executed or is delayed,
* this is != 0 and encodes what is being done */

View File

@ -0,0 +1,210 @@
From e9a187ea6abf1e7034ee3113355b282743a98f39 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 8 Aug 2018 15:27:49 +0200
Subject: [PATCH] logind: add a RequiresMountsFor= dependency from the session
scope unit to the home directory of the user
This is useful so that during shutdown scope units are always terminated
before the mounts necessary for the home directory.
(Ideally we'd also add a similar dependency from the user@.service
instance to the home directory, but this isn't as easy as that service
is defined statically and not dynamically, and hence not easy to modify
dynamically, in particular when it comes to deps)
(cherry picked from commit d5ac9d060267820aabdf9af509a54a1830b27b7d)
Related: #1642460
---
src/login/logind-core.c | 24 ++++++++++++++++++------
src/login/logind-dbus.c | 7 +++++++
src/login/logind-session.c | 1 +
src/login/logind-user.c | 13 ++++++++++++-
src/login/logind-user.h | 3 ++-
src/login/logind.h | 4 ++--
6 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/src/login/logind-core.c b/src/login/logind-core.c
index 678c708df1..0ed812a2c8 100644
--- a/src/login/logind-core.c
+++ b/src/login/logind-core.c
@@ -128,7 +128,14 @@ int manager_add_session(Manager *m, const char *id, Session **_session) {
return 0;
}
-int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
+int manager_add_user(
+ Manager *m,
+ uid_t uid,
+ gid_t gid,
+ const char *name,
+ const char *home,
+ User **_user) {
+
User *u;
int r;
@@ -137,7 +144,7 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **
u = hashmap_get(m->users, UID_TO_PTR(uid));
if (!u) {
- r = user_new(&u, m, uid, gid, name);
+ r = user_new(&u, m, uid, gid, name, home);
if (r < 0)
return r;
}
@@ -148,7 +155,12 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **
return 0;
}
-int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
+int manager_add_user_by_name(
+ Manager *m,
+ const char *name,
+ User **_user) {
+
+ const char *home = NULL;
uid_t uid;
gid_t gid;
int r;
@@ -156,11 +168,11 @@ int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
assert(m);
assert(name);
- r = get_user_creds(&name, &uid, &gid, NULL, NULL);
+ r = get_user_creds(&name, &uid, &gid, &home, NULL);
if (r < 0)
return r;
- return manager_add_user(m, uid, gid, name, _user);
+ return manager_add_user(m, uid, gid, name, home, _user);
}
int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
@@ -173,7 +185,7 @@ int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
if (!p)
return errno > 0 ? -errno : -ENOENT;
- return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
+ return manager_add_user(m, uid, p->pw_gid, p->pw_name, p->pw_dir, _user);
}
int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index 6586280269..1bb152bc20 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -3313,6 +3313,7 @@ int manager_start_scope(
const char *description,
char **wants,
char **after,
+ const char *requires_mounts_for,
sd_bus_message *more_properties,
sd_bus_error *error,
char **job) {
@@ -3368,6 +3369,12 @@ int manager_start_scope(
return r;
}
+ if (!empty_or_root(requires_mounts_for)) {
+ r = sd_bus_message_append(m, "(sv)", "RequiresMountsFor", "as", 1, requires_mounts_for);
+ if (r < 0)
+ return r;
+ }
+
/* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore
* SIGTERM */
r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
diff --git a/src/login/logind-session.c b/src/login/logind-session.c
index dd4ac9482a..e4c8bb36f6 100644
--- a/src/login/logind-session.c
+++ b/src/login/logind-session.c
@@ -591,6 +591,7 @@ static int session_start_scope(Session *s, sd_bus_message *properties, sd_bus_er
description,
STRV_MAKE(s->user->runtime_dir_service, s->user->service), /* These two have StopWhenUnneeded= set, hence add a dep towards them */
STRV_MAKE("systemd-logind.service", "systemd-user-sessions.service", s->user->runtime_dir_service, s->user->service), /* And order us after some more */
+ s->user->home,
properties,
error,
&s->scope_job);
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index f23fcbe674..70f5eb9d59 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -30,7 +30,13 @@
#include "user-util.h"
#include "util.h"
-int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
+int user_new(User **ret,
+ Manager *m,
+ uid_t uid,
+ gid_t gid,
+ const char *name,
+ const char *home) {
+
_cleanup_(user_freep) User *u = NULL;
char lu[DECIMAL_STR_MAX(uid_t) + 1];
int r;
@@ -54,6 +60,10 @@ int user_new(User **ret, Manager *m, uid_t uid, gid_t gid, const char *name) {
if (!u->name)
return -ENOMEM;
+ u->home = strdup(home);
+ if (!u->home)
+ return -ENOMEM;
+
if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
return -ENOMEM;
@@ -124,6 +134,7 @@ User *user_free(User *u) {
u->runtime_path = mfree(u->runtime_path);
u->state_file = mfree(u->state_file);
u->name = mfree(u->name);
+ u->home = mfree(u->home);
return mfree(u);
}
diff --git a/src/login/logind-user.h b/src/login/logind-user.h
index e05646adc9..c41973e27d 100644
--- a/src/login/logind-user.h
+++ b/src/login/logind-user.h
@@ -23,6 +23,7 @@ struct User {
uid_t uid;
gid_t gid;
char *name;
+ char *home;
char *state_file;
char *runtime_path;
@@ -49,7 +50,7 @@ struct User {
LIST_FIELDS(User, gc_queue);
};
-int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name);
+int user_new(User **out, Manager *m, uid_t uid, gid_t gid, const char *name, const char *home);
User *user_free(User *u);
DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free);
diff --git a/src/login/logind.h b/src/login/logind.h
index 7288dd7445..d29b01c75b 100644
--- a/src/login/logind.h
+++ b/src/login/logind.h
@@ -129,7 +129,7 @@ int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_dev
int manager_add_button(Manager *m, const char *name, Button **_button);
int manager_add_seat(Manager *m, const char *id, Seat **_seat);
int manager_add_session(Manager *m, const char *id, Session **_session);
-int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user);
+int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, const char *home, User **_user);
int manager_add_user_by_name(Manager *m, const char *name, User **_user);
int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user);
int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor);
@@ -162,7 +162,7 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
-int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, sd_bus_message *more_properties, sd_bus_error *error, char **job);
+int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job);
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);

View File

@ -0,0 +1,39 @@
From 117ed6bd7aa71fc79599e1d37bdb4a94b3505a38 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 8 Aug 2018 16:03:11 +0200
Subject: [PATCH] logind: improve error propagation of user_check_linger_file()
Let's make this a bit prettier, and propagate unexpected access() errors
correctly.
(The callers of this function will suppress them, but it's nicer of they
do that, rather than us doing that twice in both the callers and the
callees)
(cherry picked from commit 6996df9b864981980f5b713dc5c7d506a7a4b9bf)
Related: #1642460
---
src/login/logind-user.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 70f5eb9d59..3fd28fc66c 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -532,8 +532,14 @@ int user_check_linger_file(User *u) {
return -ENOMEM;
p = strjoina("/var/lib/systemd/linger/", cc);
+ if (access(p, F_OK) < 0) {
+ if (errno != ENOENT)
+ return -errno;
- return access(p, F_OK) >= 0;
+ return false;
+ }
+
+ return true;
}
bool user_may_gc(User *u, bool drop_not_started) {

View File

@ -0,0 +1,82 @@
From 89dd5e016a50da082e51129eecb3c5e04b8f0cf5 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 8 Aug 2018 16:04:40 +0200
Subject: [PATCH] logind: automatically GC lingering users for who now
user@.service (nor slice, not runtime dir service) is running anymore
This heavily borrows from @intelfx' PR #5546, but watches all three
units that are associated with a user now: the slice, the user@.service
and user-runtime-dir@.service.
The logic and reasoning behind it is the same though: there's no value
in keeping lingering users around if all their three services are gone.
Replaces: #5546
Fixes: #4162
(cherry picked from commit 4e5b605af202c770dfc8e3562d0f8d0440b2fe14)
Related: #1642460
---
src/login/logind-user.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 3fd28fc66c..bba3158d1a 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -26,6 +26,7 @@
#include "special.h"
#include "stdio-util.h"
#include "string-table.h"
+#include "strv.h"
#include "unit-name.h"
#include "user-util.h"
#include "util.h"
@@ -542,6 +543,25 @@ int user_check_linger_file(User *u) {
return true;
}
+static bool user_unit_active(User *u) {
+ const char *i;
+ int r;
+
+ assert(u->service);
+ assert(u->runtime_dir_service);
+ assert(u->slice);
+
+ FOREACH_STRING(i, u->service, u->runtime_dir_service, u->slice) {
+ r = manager_unit_is_active(u->manager, i);
+ if (r < 0)
+ log_debug_errno(r, "Failed to determine whether unit '%s' is active, ignoring", u->service);
+ if (r != 0)
+ return true;
+ }
+
+ return false;
+}
+
bool user_may_gc(User *u, bool drop_not_started) {
assert(u);
@@ -561,8 +581,10 @@ bool user_may_gc(User *u, bool drop_not_started) {
return false; /* Leave it around for a bit longer. */
}
- /* Is this a user that shall stay around forever? */
- if (user_check_linger_file(u) > 0)
+ /* Is this a user that shall stay around forever ("linger")? Before we say "no" to GC'ing for lingering users, let's check
+ * if any of the three units that we maintain for this user is still around. If none of them is,
+ * there's no need to keep this user around even if lingering is enabled. */
+ if (user_check_linger_file(u) > 0 && user_unit_active(u))
return false;
if (u->service_job && manager_job_is_active(u->manager, u->service_job))
@@ -608,7 +630,7 @@ UserState user_get_state(User *u) {
return all_closing ? USER_CLOSING : USER_ONLINE;
}
- if (user_check_linger_file(u) > 0)
+ if (user_check_linger_file(u) > 0 && user_unit_active(u))
return USER_LINGERING;
return USER_CLOSING;

View File

@ -0,0 +1,101 @@
From 96887ddecd1e4c36d8a32411ed515ddaf0f3a0e3 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 20 Jul 2018 11:27:55 +0200
Subject: [PATCH] pam_systemd: simplify code which with we set environment
variables
Let's shorten things a bit by splitting out common code in a new
function.
(cherry picked from commit d6baaa6978d3eb5b8e8497021c4ba576aee936a3)
Related: #1642460
---
src/login/pam_systemd.c | 46 ++++++++++++++++++++++++-----------------
1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index 78ddb7d398..b2b62540bb 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -301,6 +301,24 @@ static const char* getenv_harder(pam_handle_t *handle, const char *key, const ch
return fallback;
}
+static int update_environment(pam_handle_t *handle, const char *key, const char *value) {
+ int r;
+
+ assert(handle);
+ assert(key);
+
+ /* Updates the environment, but only if there's actually a value set. Also, log about errors */
+
+ if (isempty(value))
+ return PAM_SUCCESS;
+
+ r = pam_misc_setenv(handle, key, value, 0);
+ if (r != PAM_SUCCESS)
+ pam_syslog(handle, LOG_ERR, "Failed to set environment variable %s.", key);
+
+ return r;
+}
+
_public_ PAM_EXTERN int pam_sm_open_session(
pam_handle_t *handle,
int flags,
@@ -555,11 +573,9 @@ _public_ PAM_EXTERN int pam_sm_open_session(
"id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u original_uid=%u",
id, object_path, runtime_path, session_fd, seat, vtnr, original_uid);
- r = pam_misc_setenv(handle, "XDG_SESSION_ID", id, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set session id.");
+ r = update_environment(handle, "XDG_SESSION_ID", id);
+ if (r != PAM_SUCCESS)
return r;
- }
if (original_uid == pw->pw_uid) {
/* Don't set $XDG_RUNTIME_DIR if the user we now
@@ -568,34 +584,26 @@ _public_ PAM_EXTERN int pam_sm_open_session(
* in privileged apps clobbering the runtime directory
* unnecessarily. */
- r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
+ r = update_environment(handle, "XDG_RUNTIME_DIR", runtime_path);
+ if (r != PAM_SUCCESS)
return r;
- }
r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path);
if (r != PAM_SUCCESS)
return r;
}
- if (!isempty(seat)) {
- r = pam_misc_setenv(handle, "XDG_SEAT", seat, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set seat.");
- return r;
- }
- }
+ r = update_environment(handle, "XDG_SEAT", seat);
+ if (r != PAM_SUCCESS)
+ return r;
if (vtnr > 0) {
char buf[DECIMAL_STR_MAX(vtnr)];
sprintf(buf, "%u", vtnr);
- r = pam_misc_setenv(handle, "XDG_VTNR", buf, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set virtual terminal number.");
+ r = update_environment(handle, "XDG_VTNR", buf);
+ if (r != PAM_SUCCESS)
return r;
- }
}
r = pam_set_data(handle, "systemd.existing", INT_TO_PTR(!!existing), NULL);

View File

@ -0,0 +1,89 @@
From c8b74ac5cf508c7bcec92d197880043af1d2bad7 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Tue, 9 Oct 2018 22:23:41 +0200
Subject: [PATCH] logind: validate /run/user/1000 before we set it
Let's be safe than sorry, in particular as logind doesn't set it up
anymore, but user-runtime-dir@.service does, and logind doesn't really
track success of that.
(cherry picked from commit b92171124819305985ed292cc472f6668a027425)
Related: #1642460
---
src/login/pam_systemd.c | 48 +++++++++++++++++++++++++++++++++++------
1 file changed, 41 insertions(+), 7 deletions(-)
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index b2b62540bb..64e1b4d1bf 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -319,6 +319,36 @@ static int update_environment(pam_handle_t *handle, const char *key, const char
return r;
}
+static bool validate_runtime_directory(pam_handle_t *handle, const char *path, uid_t uid) {
+ struct stat st;
+
+ assert(path);
+
+ /* Just some extra paranoia: let's not set $XDG_RUNTIME_DIR if the directory we'd set it to isn't actually set
+ * up properly for us. */
+
+ if (lstat(path, &st) < 0) {
+ pam_syslog(handle, LOG_ERR, "Failed to stat() runtime directory '%s': %s", path, strerror(errno));
+ goto fail;
+ }
+
+ if (!S_ISDIR(st.st_mode)) {
+ pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not actually a directory.", path);
+ goto fail;
+ }
+
+ if (st.st_uid != uid) {
+ pam_syslog(handle, LOG_ERR, "Runtime directory '%s' is not owned by UID " UID_FMT ", as it should.", path, uid);
+ goto fail;
+ }
+
+ return true;
+
+fail:
+ pam_syslog(handle, LOG_WARNING, "Not setting $XDG_RUNTIME_DIR, as the directory is not in order.");
+ return false;
+}
+
_public_ PAM_EXTERN int pam_sm_open_session(
pam_handle_t *handle,
int flags,
@@ -377,10 +407,12 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0)
return PAM_BUF_ERR;
- r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
- if (r != PAM_SUCCESS) {
- pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
- return r;
+ if (validate_runtime_directory(handle, rt, pw->pw_uid)) {
+ r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0);
+ if (r != PAM_SUCCESS) {
+ pam_syslog(handle, LOG_ERR, "Failed to set runtime dir.");
+ return r;
+ }
}
r = export_legacy_dbus_address(handle, pw->pw_uid, rt);
@@ -584,9 +616,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
* in privileged apps clobbering the runtime directory
* unnecessarily. */
- r = update_environment(handle, "XDG_RUNTIME_DIR", runtime_path);
- if (r != PAM_SUCCESS)
- return r;
+ if (validate_runtime_directory(handle, runtime_path, pw->pw_uid)) {
+ r = update_environment(handle, "XDG_RUNTIME_DIR", runtime_path);
+ if (r != PAM_SUCCESS)
+ return r;
+ }
r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path);
if (r != PAM_SUCCESS)

View File

@ -0,0 +1,33 @@
From 2ab6e6ae9853e410310268efc0cea7f2276979ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 20 Oct 2020 17:12:42 +0200
Subject: [PATCH] sd-hwdb: allow empty properties
So far we didn't allow empty properties, but it makes sense to do so, for
example to distinguish empty data from lack of data. It also makes it easy to
override properties (back to the empty) value for specific cases.
(cherry picked from commit afe87974dd57741f74dd87165b251886f24c859f)
Related: #2005009
---
src/hwdb/hwdb.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/hwdb/hwdb.c b/src/hwdb/hwdb.c
index 317cad8a67..af085cdb75 100644
--- a/src/hwdb/hwdb.c
+++ b/src/hwdb/hwdb.c
@@ -462,10 +462,9 @@ static int insert_data(struct trie *trie, char **match_list, char *line,
while (isblank(line[0]) && isblank(line[1]))
line++;
- if (isempty(line + 1) || isempty(value))
+ if (isempty(line + 1))
return log_syntax(NULL, LOG_WARNING, filename, line_number, EINVAL,
- "Empty %s in \"%s=%s\", ignoring",
- isempty(line + 1) ? "key" : "value",
+ "Empty key in \"%s=%s\", ignoring",
line, value);
STRV_FOREACH(entry, match_list)

104589
SOURCES/0638-Update-hwdb.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,26 @@
From b029865ef6d8b23ecdbfda4e277a3f75cb59ee94 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Mon, 25 Oct 2021 15:27:27 +0200
Subject: [PATCH] Disable libpitc to fix CentOS Stream CI
We have disabled it in our spec starting with 8.5.0, so let's follow
suit here.
Related: #2017033
---
.github/workflows/unit_tests.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/unit_tests.sh b/.github/workflows/unit_tests.sh
index ad4584ec1d..def38bffe2 100755
--- a/.github/workflows/unit_tests.sh
+++ b/.github/workflows/unit_tests.sh
@@ -50,7 +50,7 @@ CONFIGURE_OPTS=(
-Dgnutls=true
-Dmicrohttpd=true
-Dlibidn2=true
- -Dlibiptc=true
+ -Dlibiptc=false
-Dlibcurl=true
-Defi=true
-Dtpm=true

View File

@ -0,0 +1,25 @@
From 74cbe4b73a1dbb1113c822690561b8b41b2fb60a Mon Sep 17 00:00:00 2001
From: Neal Gompa <ngompa13@gmail.com>
Date: Mon, 25 Jun 2018 12:56:50 -0400
Subject: [PATCH] rpm: Fix typo in %_environmentdir
Signed-off-by: Neal Gompa <ngompa13@gmail.com>
(cherry picked from commit 6ea4cb975f99cdfd447332ffa9631790a5975eea)
Resolves: #2018024
---
src/core/macros.systemd.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in
index f3b74f4273..a24d7bbe58 100644
--- a/src/core/macros.systemd.in
+++ b/src/core/macros.systemd.in
@@ -18,7 +18,7 @@
%_sysctldir @sysctldir@
%_sysusersdir @sysusersdir@
%_tmpfilesdir @tmpfilesdir@
-%_environmnentdir @environmentdir@
+%_environmentdir @environmentdir@
%_modulesloaddir @modulesloaddir@
%_modprobedir @modprobedir@
%_systemdgeneratordir @systemgeneratordir@

View File

@ -0,0 +1,30 @@
From 7b2d5268cf43a4ed7847bdbed2328bccddd5a716 Mon Sep 17 00:00:00 2001
From: Neal Gompa <ngompa13@gmail.com>
Date: Tue, 26 Jun 2018 07:42:29 -0400
Subject: [PATCH] rpm: Add misspelled %_environmentdir macro for temporary
compatibility
This should be removed after systemd 240 is released.
Signed-off-by: Neal Gompa <ngompa13@gmail.com>
(cherry picked from commit a6bb5504583e3267d35fa385fe20f60fd998ca5d)
Related: #2018024
---
src/core/macros.systemd.in | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in
index a24d7bbe58..abbb42b22f 100644
--- a/src/core/macros.systemd.in
+++ b/src/core/macros.systemd.in
@@ -26,6 +26,10 @@
%_systemd_system_env_generator_dir @systemenvgeneratordir@
%_systemd_user_env_generator_dir @userenvgeneratordir@
+# Because we had one release with a typo...
+# This is temporary (Remove after systemd 240 is released)
+%_environmnentdir %_environmentdir
+
%systemd_requires \
Requires(post): systemd \
Requires(preun): systemd \

View File

@ -0,0 +1,32 @@
From 4d994a262ec1ad3e33e197cb09aa5aeabb5835dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 3 Jul 2018 15:40:53 +0200
Subject: [PATCH] rpm: emit warning when macro with typo is used
Follow-up for a6bb550458. Suggested by @ignatenkobrain.
$ rpmbuild --eval %_environmentdir
/usr/lib/environment.d
$ rpmbuild --eval %_environmnentdir
warning: Use %_environmentdir instead
/usr/lib/environment.d
(cherry picked from commit be9bf171bbf764997551f8a9b3c2aba5c6a875d3)
Related: #2018024
---
src/core/macros.systemd.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in
index abbb42b22f..fe7ca26a34 100644
--- a/src/core/macros.systemd.in
+++ b/src/core/macros.systemd.in
@@ -28,7 +28,7 @@
# Because we had one release with a typo...
# This is temporary (Remove after systemd 240 is released)
-%_environmnentdir %_environmentdir
+%_environmnentdir %{warn:Use %%_environmentdir instead}%_environmentdir
%systemd_requires \
Requires(post): systemd \

View File

@ -0,0 +1,75 @@
From f29b7bcd85d4e8d824d36fecc130a0d74af718f8 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Tue, 12 Oct 2021 16:47:48 +0200
Subject: [PATCH] Remove unintended additions to systemd-analyze man page
These changes were introduced in commit
a2e00522971897909db2a81b4daf10e5700f453e .
Resolves: #2004765
---
man/systemd-analyze.xml | 51 +----------------------------------------
1 file changed, 1 insertion(+), 50 deletions(-)
diff --git a/man/systemd-analyze.xml b/man/systemd-analyze.xml
index 7c873cbdd1..e17ff0cf90 100644
--- a/man/systemd-analyze.xml
+++ b/man/systemd-analyze.xml
@@ -354,56 +354,7 @@ $ eog targets.svg</programlisting>
they elapse next. This takes the same input as the <varname>OnCalendar=</varname> setting in
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
following the syntax described in
- <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>. By
- default, only the next time the calendar expression will elapse is shown; use
- <option>--iterations=</option> to show the specified number of next times the expression
- elapses.</para>
-
- <example>
- <title>Show leap days in the near future</title>
-
- <programlisting>$ systemd-analyze calendar --iterations=5 '*-2-29 0:0:0'
- Original form: *-2-29 0:0:0
-Normalized form: *-02-29 00:00:00
- Next elapse: Sat 2020-02-29 00:00:00 UTC
- From now: 11 months 15 days left
- Iter. #2: Thu 2024-02-29 00:00:00 UTC
- From now: 4 years 11 months left
- Iter. #3: Tue 2028-02-29 00:00:00 UTC
- From now: 8 years 11 months left
- Iter. #4: Sun 2032-02-29 00:00:00 UTC
- From now: 12 years 11 months left
- Iter. #5: Fri 2036-02-29 00:00:00 UTC
- From now: 16 years 11 months left
-</programlisting>
- </example>
- </refsect2>
-
- <refsect2>
- <title><command>systemd-analyze timespan <replaceable>EXPRESSION</replaceable>...</command></title>
-
- <para>This command parses a time span and outputs the normalized form and the equivalent value in
- microseconds. The time span should adhere to the same syntax documented in
- <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
- Values without associated magnitudes are parsed as seconds.</para>
-
- <example>
- <title>Show parsing of timespans</title>
-
- <programlisting>$ systemd-analyze timespan 1s 300s '1year 0.000001s'
-Original: 1s
- μs: 1000000
- Human: 1s
-
-Original: 300s
- μs: 300000000
- Human: 5min
-
-Original: 1year 0.000001s
- μs: 31557600000001
- Human: 1y 1us
-</programlisting>
- </example>
+ <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>
</refsect2>
<refsect2>

View File

@ -0,0 +1,21 @@
From ffd20a699280a4732d0fe4cddafe12ee8010ddb6 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Wed, 13 Oct 2021 10:01:59 +0200
Subject: [PATCH] Disable iptables for CI
---
.github/workflows/unit_tests.sh | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/workflows/unit_tests.sh b/.github/workflows/unit_tests.sh
index def38bffe2..814870e7a0 100755
--- a/.github/workflows/unit_tests.sh
+++ b/.github/workflows/unit_tests.sh
@@ -92,7 +92,6 @@ SYSTEMD_BUILD_DEPS=(
gnutls-devel
gobject-introspection-devel
gperf
- iptables-devel
kmod-devel
libacl-devel
libblkid-devel

View File

@ -0,0 +1,103 @@
From 8e322f5bc24547963978be071a8a2547abad875a Mon Sep 17 00:00:00 2001
From: Henri Chain <henri.chain@enioka.com>
Date: Tue, 5 Oct 2021 13:10:31 +0200
Subject: [PATCH] core: fix SIGABRT on empty exec command argv
This verifies that the argv part of any exec_command parameters that
are sent through dbus is not empty at deserialization time.
There is an additional check in service.c service_verify() that again
checks if all exec_commands are correctly populated, after the service
has been loaded, whether through dbus or otherwise.
Fixes #20933.
(cherry picked from commit 29500cf8c47e6eb0518d171d62aa8213020c9152)
Resolves: #2020239
---
src/core/dbus-execute.c | 4 ++++
src/core/service.c | 12 +++++++++++
test/TEST-23-TYPE-EXEC/testsuite.sh | 31 +++++++++++++++++++++++++++++
3 files changed, 47 insertions(+)
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 8348663000..2e64f0baf4 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -969,6 +969,10 @@ int bus_set_transient_exec_command(
if (r < 0)
return r;
+ if (strv_isempty(argv))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
+ "\"%s\" argv cannot be empty", name);
+
r = sd_bus_message_read(message, "b", &b);
if (r < 0)
return r;
diff --git a/src/core/service.c b/src/core/service.c
index 5e3e75b5ae..12adf89dd4 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -536,6 +536,18 @@ static int service_verify(Service *s) {
if (UNIT(s)->load_state != UNIT_LOADED)
return 0;
+ for (ServiceExecCommand c = 0; c < _SERVICE_EXEC_COMMAND_MAX; c++) {
+ ExecCommand *command;
+
+ LIST_FOREACH(command, command, s->exec_command[c])
+ if (strv_isempty(command->argv)) {
+ log_unit_error(UNIT(s),
+ "Service has an empty argv in %s=. Refusing.",
+ service_exec_command_to_string(c));
+ return -ENOEXEC;
+ }
+ }
+
if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP]) {
log_unit_error(UNIT(s), "Service lacks both ExecStart= and ExecStop= setting. Refusing.");
return -ENOEXEC;
diff --git a/test/TEST-23-TYPE-EXEC/testsuite.sh b/test/TEST-23-TYPE-EXEC/testsuite.sh
index 80734bbbdc..e0c34cfd04 100755
--- a/test/TEST-23-TYPE-EXEC/testsuite.sh
+++ b/test/TEST-23-TYPE-EXEC/testsuite.sh
@@ -21,6 +21,37 @@ systemd-run --unit=four -p Type=exec /bin/sleep infinity
! systemd-run --unit=five -p Type=exec -p User=idontexist /bin/sleep infinity
! systemd-run --unit=six -p Type=exec /tmp/brokenbinary
+# For issue #20933
+
+# Should work normally
+busctl call \
+ org.freedesktop.systemd1 /org/freedesktop/systemd1 \
+ org.freedesktop.systemd1.Manager StartTransientUnit \
+ "ssa(sv)a(sa(sv))" test-20933-ok.service replace 1 \
+ ExecStart "a(sasb)" 1 \
+ /usr/bin/sleep 2 /usr/bin/sleep 1 true \
+ 0
+
+# DBus call should fail but not crash systemd
+busctl call \
+ org.freedesktop.systemd1 /org/freedesktop/systemd1 \
+ org.freedesktop.systemd1.Manager StartTransientUnit \
+ "ssa(sv)a(sa(sv))" test-20933-bad.service replace 1 \
+ ExecStart "a(sasb)" 1 \
+ /usr/bin/sleep 0 true \
+ 0 && { echo 'unexpected success'; exit 1; }
+
+# Same but with the empty argv in the middle
+busctl call \
+ org.freedesktop.systemd1 /org/freedesktop/systemd1 \
+ org.freedesktop.systemd1.Manager StartTransientUnit \
+ "ssa(sv)a(sa(sv))" test-20933-bad-middle.service replace 1 \
+ ExecStart "a(sasb)" 3 \
+ /usr/bin/sleep 2 /usr/bin/sleep 1 true \
+ /usr/bin/sleep 0 true \
+ /usr/bin/sleep 2 /usr/bin/sleep 1 true \
+ 0 && { echo 'unexpected success'; exit 1; }
+
systemd-analyze set-log-level info
echo OK > /testok

View File

@ -0,0 +1,39 @@
From 71ebbd2da606c9cb4da694bbcc925078f253f496 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 6 Oct 2021 00:19:41 +0900
Subject: [PATCH] core/service: also check path in exec commands
(cherry picked from commit 8688a389cabdff61efe187bb85cc1776de03c460)
Related: #2020239
---
src/core/service.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/core/service.c b/src/core/service.c
index 12adf89dd4..ae31973774 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -539,13 +539,21 @@ static int service_verify(Service *s) {
for (ServiceExecCommand c = 0; c < _SERVICE_EXEC_COMMAND_MAX; c++) {
ExecCommand *command;
- LIST_FOREACH(command, command, s->exec_command[c])
+ LIST_FOREACH(command, command, s->exec_command[c]) {
+ if (!path_is_absolute(command->path) && !filename_is_valid(command->path)) {
+ log_unit_error(UNIT(s),
+ "Service %s= binary path \"%s\" is neither a valid executable name nor an absolute path. Refusing.",
+ command->path,
+ service_exec_command_to_string(c));
+ return -ENOEXEC;
+ }
if (strv_isempty(command->argv)) {
log_unit_error(UNIT(s),
"Service has an empty argv in %s=. Refusing.",
service_exec_command_to_string(c));
return -ENOEXEC;
}
+ }
}
if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP]) {

View File

@ -0,0 +1,124 @@
From 397aaad6da5c4bfb160adca7a68f865086f2ed0a Mon Sep 17 00:00:00 2001
From: Franck Bui <fbui@suse.com>
Date: Thu, 30 Sep 2021 14:05:36 +0200
Subject: [PATCH] mount-util: fix fd_is_mount_point() when both the parent and
directory are network fs
The second call to name_to_handle_at_loop() didn't check for the specific
errors that can happen when the parent dir is mounted by nfs and instead of
falling back like it's done for the child dir, fd_is_mount_point() failed in
this case.
(cherry picked from commit 964ccab8286a7e75d7e9107f574f5cb23752bd5d)
Resolves: #2015057
---
src/basic/mount-util.c | 71 ++++++++++++++++++++++++------------------
1 file changed, 41 insertions(+), 30 deletions(-)
diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c
index 45348bf878..0c709001be 100644
--- a/src/basic/mount-util.c
+++ b/src/basic/mount-util.c
@@ -139,6 +139,19 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *mnt_id
return safe_atoi(p, mnt_id);
}
+static bool is_name_to_handle_at_fatal_error(int err) {
+ /* name_to_handle_at() can return "acceptable" errors that are due to the context. For
+ * example the kernel does not support name_to_handle_at() at all (ENOSYS), or the syscall
+ * was blocked (EACCES/EPERM; maybe through seccomp, because we are running inside of a
+ * container), or the mount point is not triggered yet (EOVERFLOW, think nfs4), or some
+ * general name_to_handle_at() flakiness (EINVAL). However other errors are not supposed to
+ * happen and therefore are considered fatal ones. */
+
+ assert(err < 0);
+
+ return !IN_SET(err, -EOPNOTSUPP, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL);
+}
+
int fd_is_mount_point(int fd, const char *filename, int flags) {
_cleanup_free_ struct file_handle *h = NULL, *h_parent = NULL;
int mount_id = -1, mount_id_parent = -1;
@@ -173,42 +186,40 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
* real mounts of their own. */
r = name_to_handle_at_loop(fd, filename, &h, &mount_id, flags);
- if (IN_SET(r, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL))
- /* This kernel does not support name_to_handle_at() at all (ENOSYS), or the syscall was blocked
- * (EACCES/EPERM; maybe through seccomp, because we are running inside of a container?), or the mount
- * point is not triggered yet (EOVERFLOW, think nfs4), or some general name_to_handle_at() flakiness
- * (EINVAL): fall back to simpler logic. */
- goto fallback_fdinfo;
- else if (r == -EOPNOTSUPP)
- /* This kernel or file system does not support name_to_handle_at(), hence let's see if the upper fs
- * supports it (in which case it is a mount point), otherwise fallback to the traditional stat()
- * logic */
+ if (r < 0) {
+ if (is_name_to_handle_at_fatal_error(r))
+ return r;
+ if (r != -EOPNOTSUPP)
+ goto fallback_fdinfo;
+
+ /* This kernel or file system does not support name_to_handle_at(), hence let's see
+ * if the upper fs supports it (in which case it is a mount point), otherwise fall
+ * back to the traditional stat() logic */
nosupp = true;
- else if (r < 0)
- return r;
+ }
r = name_to_handle_at_loop(fd, "", &h_parent, &mount_id_parent, AT_EMPTY_PATH);
- if (r == -EOPNOTSUPP) {
+ if (r < 0) {
+ if (is_name_to_handle_at_fatal_error(r))
+ return r;
+ if (r != -EOPNOTSUPP)
+ goto fallback_fdinfo;
if (nosupp)
- /* Neither parent nor child do name_to_handle_at()? We have no choice but to fall back. */
+ /* Both the parent and the directory can't do name_to_handle_at() */
goto fallback_fdinfo;
- else
- /* The parent can't do name_to_handle_at() but the directory we are interested in can? If so,
- * it must be a mount point. */
- return 1;
- } else if (r < 0)
- return r;
- /* The parent can do name_to_handle_at() but the
- * directory we are interested in can't? If so, it
- * must be a mount point. */
+ /* The parent can't do name_to_handle_at() but the directory we are
+ * interested in can? If so, it must be a mount point. */
+ return 1;
+ }
+
+ /* The parent can do name_to_handle_at() but the directory we are interested in can't? If
+ * so, it must be a mount point. */
if (nosupp)
return 1;
- /* If the file handle for the directory we are
- * interested in and its parent are identical, we
- * assume this is the root directory, which is a mount
- * point. */
+ /* If the file handle for the directory we are interested in and its parent are identical,
+ * we assume this is the root directory, which is a mount point. */
if (h->handle_bytes == h_parent->handle_bytes &&
h->handle_type == h_parent->handle_type &&
@@ -300,10 +311,10 @@ int path_get_mnt_id(const char *path, int *ret) {
int r;
r = name_to_handle_at_loop(AT_FDCWD, path, NULL, ret, 0);
- if (IN_SET(r, -EOPNOTSUPP, -ENOSYS, -EACCES, -EPERM, -EOVERFLOW, -EINVAL)) /* kernel/fs don't support this, or seccomp blocks access, or untriggered mount, or name_to_handle_at() is flaky */
- return fd_fdinfo_mnt_id(AT_FDCWD, path, 0, ret);
+ if (r == 0 || is_name_to_handle_at_fatal_error(r))
+ return r;
- return r;
+ return fd_fdinfo_mnt_id(AT_FDCWD, path, 0, ret);
}
int umount_recursive(const char *prefix, int flags) {

View File

@ -0,0 +1,28 @@
From 537055fc407d7cff32ddd3414a6900ccff579c46 Mon Sep 17 00:00:00 2001
From: Cyprien Laplace <claplace@vmware.com>
Date: Thu, 14 Nov 2019 09:42:14 -0500
Subject: [PATCH] basic: add vmware hypervisor detection from device-tree
Allow ConditionVirtualization=vmware to work on ESXi on arm VMs
using device-tree.
(cherry picked from commit 4d4ac92c928fcbc60b85fcbf8370af3883ee63db)
Resolves: #1959150
---
src/basic/virt.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/basic/virt.c b/src/basic/virt.c
index 0b88005ed6..8d862b6d67 100644
--- a/src/basic/virt.c
+++ b/src/basic/virt.c
@@ -122,6 +122,8 @@ static int detect_vm_device_tree(void) {
return VIRTUALIZATION_KVM;
else if (strstr(hvtype, "xen"))
return VIRTUALIZATION_XEN;
+ else if (strstr(hvtype, "vmware"))
+ return VIRTUALIZATION_VMWARE;
else
return VIRTUALIZATION_VM_OTHER;
#else

View File

@ -0,0 +1,45 @@
From a677e477ef541d172ede2a5bd728a4ff1ffb312d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 1 Jun 2021 16:17:16 +0200
Subject: [PATCH] pam: do not require a non-expired password for user@.service
Without this parameter, we would allow user@ to start if the user
has no password (i.e. the password is "locked"). But when the user does have a password,
and it is marked as expired, we would refuse to start the service.
There are other authentication mechanisms and we should not tie this service to
the password state.
The documented way to disable an *account* is to call 'chage -E0'. With a disabled
account, user@.service will still refuse to start:
systemd[16598]: PAM failed: User account has expired
systemd[16598]: PAM failed: User account has expired
systemd[16598]: user@1005.service: Failed to set up PAM session: Operation not permitted
systemd[16598]: user@1005.service: Failed at step PAM spawning /usr/lib/systemd/systemd: Operation not permitted
systemd[1]: user@1005.service: Main process exited, code=exited, status=224/PAM
systemd[1]: user@1005.service: Failed with result 'exit-code'.
systemd[1]: Failed to start user@1005.service.
systemd[1]: Stopping user-runtime-dir@1005.service...
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1961746.
(cherry picked from commit 71889176e4372b443018584c3520c1ff3efe2711)
Resolves: #1961746
---
src/login/systemd-user.m4 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/login/systemd-user.m4 b/src/login/systemd-user.m4
index 4f85b4b7fe..20c8999331 100644
--- a/src/login/systemd-user.m4
+++ b/src/login/systemd-user.m4
@@ -2,7 +2,7 @@
#
# Used by systemd --user instances.
-account required pam_unix.so
+account sufficient pam_unix.so no_pass_expiry
m4_ifdef(`HAVE_SELINUX',
session required pam_selinux.so close
session required pam_selinux.so nottys open

View File

@ -0,0 +1,26 @@
From c0e530dc95fa7842ec1a48fd5df98956a76ae26c Mon Sep 17 00:00:00 2001
From: Luca Boccassi <luca.boccassi@microsoft.com>
Date: Fri, 26 Feb 2021 10:25:31 +0000
Subject: [PATCH] udev rules: add rule to create /dev/ptp_hyperv
As for the KVM case, necessary for network cards with
PTP devices when running a guest on HyperV
(cherry picked from commit 32e868f058da8b90add00b2958c516241c532b70)
Resolves: #1991834
---
rules/50-udev-default.rules.in | 2 ++
1 file changed, 2 insertions(+)
diff --git a/rules/50-udev-default.rules.in b/rules/50-udev-default.rules.in
index 191f56f42e..36657ce1a4 100644
--- a/rules/50-udev-default.rules.in
+++ b/rules/50-udev-default.rules.in
@@ -83,4 +83,6 @@ KERNEL=="kvm", GROUP="kvm", MODE="@DEV_KVM_MODE@", OPTIONS+="static_node=kvm"
SUBSYSTEM=="ptp", ATTR{clock_name}=="KVM virtual PTP", SYMLINK += "ptp_kvm"
+SUBSYSTEM=="ptp", ATTR{clock_name}=="hyperv", SYMLINK += "ptp_hyperv"
+
LABEL="default_end"

View File

@ -0,0 +1,223 @@
From 9b30c003c8f80bf44f18168d07ea11c48e6d8864 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 7 Jul 2021 15:57:51 +0200
Subject: [PATCH] process-util: explicitly handle processes lacking parents in
get_process_ppid()
Let's make sure we signal out-of-band via an error message if a process
doesn't have a parent process whose PID we could return. Otherwise we'll
too likely hide errors, as we return an invalid PID 0, which in other
contexts has special meaning (i.e. usually "myself").
Replaces: #20153
This is based on work by @dtardon, but goes a different route, by
ensuring we propagate a proper error in this case.
This modernizes the function in question a bit in other ways, i.e.
renames stuff and makes the return parameter optional.
(cherry picked from commit 0c4d1e6d96a549054bfe0597d197f829838917f1)
Resolves: #1977569
---
src/basic/process-util.c | 27 +++++++++++++-------
src/coredump/coredump.c | 23 +++++++++--------
src/test/test-process-util.c | 48 +++++++++++++++++++++++++++++++++---
3 files changed, 74 insertions(+), 24 deletions(-)
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 0a4a747ba4..6016d83d41 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -603,20 +603,23 @@ int get_process_environ(pid_t pid, char **env) {
return 0;
}
-int get_process_ppid(pid_t pid, pid_t *_ppid) {
- int r;
+int get_process_ppid(pid_t pid, pid_t *ret) {
_cleanup_free_ char *line = NULL;
long unsigned ppid;
const char *p;
+ int r;
assert(pid >= 0);
- assert(_ppid);
if (pid == 0 || pid == getpid_cached()) {
- *_ppid = getppid();
+ if (ret)
+ *ret = getppid();
return 0;
}
+ if (pid == 1) /* PID 1 has no parent, shortcut this case */
+ return -EADDRNOTAVAIL;
+
p = procfs_file_alloca(pid, "stat");
r = read_one_line_file(p, &line);
if (r == -ENOENT)
@@ -624,9 +627,8 @@ int get_process_ppid(pid_t pid, pid_t *_ppid) {
if (r < 0)
return r;
- /* Let's skip the pid and comm fields. The latter is enclosed
- * in () but does not escape any () in its value, so let's
- * skip over it manually */
+ /* Let's skip the pid and comm fields. The latter is enclosed in () but does not escape any () in its
+ * value, so let's skip over it manually */
p = strrchr(line, ')');
if (!p)
@@ -640,10 +642,17 @@ int get_process_ppid(pid_t pid, pid_t *_ppid) {
&ppid) != 1)
return -EIO;
- if ((long unsigned) (pid_t) ppid != ppid)
+ /* If ppid is zero the process has no parent. Which might be the case for PID 1 but also for
+ * processes originating in other namespaces that are inserted into a pidns. Return a recognizable
+ * error in this case. */
+ if (ppid == 0)
+ return -EADDRNOTAVAIL;
+
+ if ((pid_t) ppid < 0 || (long unsigned) (pid_t) ppid != ppid)
return -ERANGE;
- *_ppid = (pid_t) ppid;
+ if (ret)
+ *ret = (pid_t) ppid;
return 0;
}
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 2a130e8838..fb3a6ecfe9 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -591,8 +591,7 @@ static int get_process_ns(pid_t pid, const char *namespace, ino_t *ns) {
return 0;
}
-static int get_mount_namespace_leader(pid_t pid, pid_t *container_pid) {
- pid_t cpid = pid, ppid = 0;
+static int get_mount_namespace_leader(pid_t pid, pid_t *ret) {
ino_t proc_mntns;
int r = 0;
@@ -602,8 +601,12 @@ static int get_mount_namespace_leader(pid_t pid, pid_t *container_pid) {
for (;;) {
ino_t parent_mntns;
+ pid_t ppid;
- r = get_process_ppid(cpid, &ppid);
+ r = get_process_ppid(pid, &ppid);
+ if (r == -EADDRNOTAVAIL) /* Reached the top (i.e. typically PID 1, but could also be a process
+ * whose parent is not in our pidns) */
+ return -ENOENT;
if (r < 0)
return r;
@@ -611,17 +614,13 @@ static int get_mount_namespace_leader(pid_t pid, pid_t *container_pid) {
if (r < 0)
return r;
- if (proc_mntns != parent_mntns)
- break;
-
- if (ppid == 1)
- return -ENOENT;
+ if (proc_mntns != parent_mntns) {
+ *ret = ppid;
+ return 0;
+ }
- cpid = ppid;
+ pid = ppid;
}
-
- *container_pid = ppid;
- return 0;
}
/* Returns 1 if the parent was found.
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 26e3247993..6b14ff592b 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -19,6 +19,7 @@
#include "macro.h"
#include "parse-util.h"
#include "process-util.h"
+#include "procfs-util.h"
#include "signal-util.h"
#include "stdio-util.h"
#include "string-util.h"
@@ -56,9 +57,12 @@ static void test_get_process_comm(pid_t pid) {
assert_se(get_process_cmdline(pid, 1, false, &d) >= 0);
log_info("PID"PID_FMT" cmdline truncated to 1: '%s'", pid, d);
- assert_se(get_process_ppid(pid, &e) >= 0);
- log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
- assert_se(pid == 1 ? e == 0 : e > 0);
+ r = get_process_ppid(pid, &e);
+ assert_se(pid == 1 ? r == -EADDRNOTAVAIL : r >= 0);
+ if (r >= 0) {
+ log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e);
+ assert_se(e > 0);
+ }
assert_se(is_kernel_thread(pid) == 0 || pid != 1);
@@ -585,6 +589,43 @@ static void test_ioprio_class_from_to_string(void) {
test_ioprio_class_from_to_string_one("-1", -1);
}
+static void test_get_process_ppid(void) {
+ uint64_t limit;
+ int r;
+
+ log_info("/* %s */", __func__);
+
+ assert_se(get_process_ppid(1, NULL) == -EADDRNOTAVAIL);
+
+ /* the process with the PID above the global limit definitely doesn't exist. Verify that */
+ assert_se(procfs_tasks_get_limit(&limit) >= 0);
+ assert_se(limit >= INT_MAX || get_process_ppid(limit+1, NULL) == -ESRCH);
+
+ for (pid_t pid = 0;;) {
+ _cleanup_free_ char *c1 = NULL, *c2 = NULL;
+ pid_t ppid;
+
+ r = get_process_ppid(pid, &ppid);
+ if (r == -EADDRNOTAVAIL) {
+ log_info("No further parent PID");
+ break;
+ }
+
+ assert_se(r >= 0);
+
+ /* NOTE: The size is SIZE_MAX in the original commit, but it would require backporting a
+ * lot more stuff to support that (the current version of get_process_cmdline() just fails with
+ * ENOMEM). UINT16_MAX should be enough for practical purposes.
+ */
+ assert_se(get_process_cmdline(pid, UINT16_MAX, true, &c1) >= 0);
+ assert_se(get_process_cmdline(ppid, UINT16_MAX, true, &c2) >= 0);
+
+ log_info("Parent of " PID_FMT " (%s) is " PID_FMT " (%s).", pid, c1, ppid, c2);
+
+ pid = ppid;
+ }
+}
+
int main(int argc, char *argv[]) {
log_set_max_level(LOG_DEBUG);
log_parse_environment();
@@ -614,6 +655,7 @@ int main(int argc, char *argv[]) {
test_safe_fork();
test_pid_to_ptr();
test_ioprio_class_from_to_string();
+ test_get_process_ppid();
return 0;
}

View File

@ -0,0 +1,30 @@
From c078d4d4bc3a61d186a98e03afc699b11134e09f Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 20 Nov 2019 12:22:40 +0100
Subject: [PATCH] errno-util: add ERRNO_IS_PRIVILEGE() helper
(cherry picked from commit e884e000714c2db006384058a63788ffcce8c8b8)
Related: #1977569
---
src/basic/util.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/basic/util.h b/src/basic/util.h
index c70467f98c..76b76d7e91 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -170,6 +170,13 @@ static inline int negative_errno(void) {
return -errno;
}
+/* Two different errors for access problems */
+static inline bool ERRNO_IS_PRIVILEGE(int r) {
+ return IN_SET(abs(r),
+ EACCES,
+ EPERM);
+}
+
static inline unsigned u64log2(uint64_t n) {
#if __SIZEOF_LONG_LONG__ == 8
return (n > 1) ? (unsigned) __builtin_clzll(n) ^ 63U : 0;

View File

@ -0,0 +1,318 @@
From 62678ec1aa02b53cb116b6f7dd72a54bf61153b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 2 Nov 2021 18:18:21 +0100
Subject: [PATCH] procfs-util: fix confusion wrt. quantity limit and maximum
value
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
From packit/rawhide-arm64 logs:
Assertion 'limit >= INT_MAX || get_process_ppid(limit+1, NULL) == -ESRCH' failed at src/test/test-process-util.c:855, function test_get_process_ppid(). Aborting.
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
The kernel has a few different limits. In particular kernel.threads-max can be
set to some lower value, and kernel.pid_max can be set to a higher value. This
is nice because it reduces PID reuse, even if the number of threads that is
allowed is limited. But the tests assumed that we cannot have a thread with
PID above MIN(kernel.threads-max, kernel.pid_max-1), which is not valid.
So let's rework the whole thing: let's expose the helpers to read
kernel.threads-max and kernel.pid_max, and print what they return in tests.
procfs_tasks_get_limit() was something that is only used in tests, and wasn't
very well defined, so let's drop it.
Fixes #21193.
(cherry picked from commit c3dead53d50e334f2d072a2248256983d6dc9f8c)
Related: #1977569
---
src/basic/procfs-util.c | 53 +++++++++---------------------------
src/basic/procfs-util.h | 4 ++-
src/basic/util.c | 49 +++++++++++++++++++++++----------
src/test/test-process-util.c | 10 +++++--
src/test/test-procfs-util.c | 37 +++++++++++++++++++------
5 files changed, 88 insertions(+), 65 deletions(-)
diff --git a/src/basic/procfs-util.c b/src/basic/procfs-util.c
index 7aaf95bfce..fa5671dd72 100644
--- a/src/basic/procfs-util.c
+++ b/src/basic/procfs-util.c
@@ -12,54 +12,34 @@
#include "stdio-util.h"
#include "string-util.h"
-int procfs_tasks_get_limit(uint64_t *ret) {
+int procfs_get_pid_max(uint64_t *ret) {
_cleanup_free_ char *value = NULL;
- uint64_t pid_max, threads_max;
int r;
assert(ret);
- /* So there are two sysctl files that control the system limit of processes:
- *
- * 1. kernel.threads-max: this is probably the sysctl that makes more sense, as it directly puts a limit on
- * concurrent tasks.
- *
- * 2. kernel.pid_max: this limits the numeric range PIDs can take, and thus indirectly also limits the number
- * of concurrent threads. AFAICS it's primarily a compatibility concept: some crappy old code used a signed
- * 16bit type for PIDs, hence the kernel provides a way to ensure the PIDs never go beyond INT16_MAX by
- * default.
- *
- * By default #2 is set to much lower values than #1, hence the limit people come into contact with first, as
- * it's the lowest boundary they need to bump when they want higher number of processes.
- *
- * Also note the weird definition of #2: PIDs assigned will be kept below this value, which means the number of
- * tasks that can be created is one lower, as PID 0 is not a valid process ID. */
-
r = read_one_line_file("/proc/sys/kernel/pid_max", &value);
if (r < 0)
return r;
- r = safe_atou64(value, &pid_max);
- if (r < 0)
- return r;
+ return safe_atou64(value, ret);
+}
- value = mfree(value);
- r = read_one_line_file("/proc/sys/kernel/threads-max", &value);
- if (r < 0)
- return r;
+int procfs_get_threads_max(uint64_t *ret) {
+ _cleanup_free_ char *value = NULL;
+ int r;
- r = safe_atou64(value, &threads_max);
+ assert(ret);
+
+ r = read_one_line_file("/proc/sys/kernel/threads-max", &value);
if (r < 0)
return r;
- /* Subtract one from pid_max, since PID 0 is not a valid PID */
- *ret = MIN(pid_max-1, threads_max);
- return 0;
+ return safe_atou64(value, ret);
}
int procfs_tasks_set_limit(uint64_t limit) {
char buffer[DECIMAL_STR_MAX(uint64_t)+1];
- _cleanup_free_ char *value = NULL;
uint64_t pid_max;
int r;
@@ -74,10 +54,7 @@ int procfs_tasks_set_limit(uint64_t limit) {
* set it to the maximum. */
limit = CLAMP(limit, 20U, TASKS_MAX);
- r = read_one_line_file("/proc/sys/kernel/pid_max", &value);
- if (r < 0)
- return r;
- r = safe_atou64(value, &pid_max);
+ r = procfs_get_pid_max(&pid_max);
if (r < 0)
return r;
@@ -98,14 +75,10 @@ int procfs_tasks_set_limit(uint64_t limit) {
/* Hmm, we couldn't write this? If so, maybe it was already set properly? In that case let's not
* generate an error */
- value = mfree(value);
- if (read_one_line_file("/proc/sys/kernel/threads-max", &value) < 0)
- return r; /* return original error */
-
- if (safe_atou64(value, &threads_max) < 0)
+ if (procfs_get_threads_max(&threads_max) < 0)
return r; /* return original error */
- if (MIN(pid_max-1, threads_max) != limit)
+ if (MIN(pid_max - 1, threads_max) != limit)
return r; /* return original error */
/* Yay! Value set already matches what we were trying to set, hence consider this a success. */
diff --git a/src/basic/procfs-util.h b/src/basic/procfs-util.h
index 5a44e9eff7..caaee8b0b6 100644
--- a/src/basic/procfs-util.h
+++ b/src/basic/procfs-util.h
@@ -5,7 +5,9 @@
#include "time-util.h"
-int procfs_tasks_get_limit(uint64_t *ret);
+int procfs_get_pid_max(uint64_t *ret);
+int procfs_get_threads_max(uint64_t *ret);
+
int procfs_tasks_set_limit(uint64_t limit);
int procfs_tasks_get_current(uint64_t *ret);
diff --git a/src/basic/util.c b/src/basic/util.c
index 609f8c2f33..548e3652cc 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -527,23 +527,46 @@ uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
}
uint64_t system_tasks_max(void) {
-
- uint64_t a = TASKS_MAX, b = TASKS_MAX;
+ uint64_t a = TASKS_MAX, b = TASKS_MAX, c = TASKS_MAX;
_cleanup_free_ char *root = NULL;
int r;
- /* Determine the maximum number of tasks that may run on this system. We check three sources to determine this
- * limit:
+ /* Determine the maximum number of tasks that may run on this system. We check three sources to
+ * determine this limit:
+ *
+ * a) kernel.threads-max sysctl: the maximum number of tasks (threads) the kernel allows.
+ *
+ * This puts a direct limit on the number of concurrent tasks.
+ *
+ * b) kernel.pid_max sysctl: the maximum PID value.
+ *
+ * This limits the numeric range PIDs can take, and thus indirectly also limits the number of
+ * concurrent threads. It's primarily a compatibility concept: some crappy old code used a signed
+ * 16bit type for PIDs, hence the kernel provides a way to ensure the PIDs never go beyond
+ * INT16_MAX by default.
*
- * a) the maximum tasks value the kernel allows on this architecture
- * b) the cgroups pids_max attribute for the system
- * c) the kernel's configured maximum PID value
+ * Also note the weird definition: PIDs assigned will be kept below this value, which means
+ * the number of tasks that can be created is one lower, as PID 0 is not a valid process ID.
*
- * And then pick the smallest of the three */
+ * c) pids.max on the root cgroup: the kernel's configured maximum number of tasks.
+ *
+ * and then pick the smallest of the three.
+ *
+ * By default pid_max is set to much lower values than threads-max, hence the limit people come into
+ * contact with first, as it's the lowest boundary they need to bump when they want higher number of
+ * processes.
+ */
+
+ r = procfs_get_threads_max(&a);
+ if (r < 0)
+ log_debug_errno(r, "Failed to read kernel.threads-max, ignoring: %m");
- r = procfs_tasks_get_limit(&a);
+ r = procfs_get_pid_max(&b);
if (r < 0)
- log_debug_errno(r, "Failed to read maximum number of tasks from /proc, ignoring: %m");
+ log_debug_errno(r, "Failed to read kernel.pid_max, ignoring: %m");
+ else if (b > 0)
+ /* Subtract one from pid_max, since PID 0 is not a valid PID */
+ b--;
r = cg_get_root_path(&root);
if (r < 0)
@@ -555,15 +578,13 @@ uint64_t system_tasks_max(void) {
if (r < 0)
log_debug_errno(r, "Failed to read pids.max attribute of cgroup root, ignoring: %m");
else if (!streq(value, "max")) {
- r = safe_atou64(value, &b);
+ r = safe_atou64(value, &c);
if (r < 0)
log_debug_errno(r, "Failed to parse pids.max attribute of cgroup root, ignoring: %m");
}
}
- return MIN3(TASKS_MAX,
- a <= 0 ? TASKS_MAX : a,
- b <= 0 ? TASKS_MAX : b);
+ return MIN3(a, b, c);
}
uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) {
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 6b14ff592b..6295889b47 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -598,8 +598,14 @@ static void test_get_process_ppid(void) {
assert_se(get_process_ppid(1, NULL) == -EADDRNOTAVAIL);
/* the process with the PID above the global limit definitely doesn't exist. Verify that */
- assert_se(procfs_tasks_get_limit(&limit) >= 0);
- assert_se(limit >= INT_MAX || get_process_ppid(limit+1, NULL) == -ESRCH);
+ assert_se(procfs_get_pid_max(&limit) >= 0);
+ log_debug("kernel.pid_max = %"PRIu64, limit);
+
+ if (limit < INT_MAX) {
+ r = get_process_ppid(limit + 1, NULL);
+ log_debug_errno(r, "get_process_limit(%"PRIu64") → %d/%m", limit + 1, r);
+ assert(r == -ESRCH);
+ }
for (pid_t pid = 0;;) {
_cleanup_free_ char *c1 = NULL, *c2 = NULL;
diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c
index 1d0612985b..bb6943fed0 100644
--- a/src/test/test-procfs-util.c
+++ b/src/test/test-procfs-util.c
@@ -5,11 +5,13 @@
#include "log.h"
#include "parse-util.h"
#include "procfs-util.h"
+#include "process-util.h"
+#include "util.h"
int main(int argc, char *argv[]) {
char buf[CONST_MAX(FORMAT_TIMESPAN_MAX, FORMAT_BYTES_MAX)];
nsec_t nsec;
- uint64_t v;
+ uint64_t v, w;
int r;
log_parse_environment();
@@ -24,22 +26,41 @@ int main(int argc, char *argv[]) {
assert_se(procfs_tasks_get_current(&v) >= 0);
log_info("Current number of tasks: %" PRIu64, v);
- assert_se(procfs_tasks_get_limit(&v) >= 0);
+ v = TASKS_MAX;
+ r = procfs_get_pid_max(&v);
+ assert(r >= 0 || r == -ENOENT || ERRNO_IS_PRIVILEGE(r));
+ log_info("kernel.pid_max: %"PRIu64, v);
+
+ w = TASKS_MAX;
+ r = procfs_get_threads_max(&w);
+ assert(r >= 0 || r == -ENOENT || ERRNO_IS_PRIVILEGE(r));
+ log_info("kernel.threads-max: %"PRIu64, w);
+
+ v = MIN(v - (v > 0), w);
+
+ assert_se(r >= 0);
log_info("Limit of tasks: %" PRIu64, v);
assert_se(v > 0);
- assert_se(procfs_tasks_set_limit(v) >= 0);
+ r = procfs_tasks_set_limit(v);
+ if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) {
+ log_notice_errno(r, "Skipping test: can't set task limits");
+ return EXIT_TEST_SKIP;
+ }
+ assert(r >= 0);
if (v > 100) {
- uint64_t w;
+ log_info("Reducing limit by one to %"PRIu64"…", v-1);
+
r = procfs_tasks_set_limit(v-1);
- assert_se(IN_SET(r, 0, -EPERM, -EACCES, -EROFS));
+ log_info_errno(r, "procfs_tasks_set_limit: %m");
+ assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r));
- assert_se(procfs_tasks_get_limit(&w) >= 0);
- assert_se((r == 0 && w == v - 1) || (r < 0 && w == v));
+ assert_se(procfs_get_threads_max(&w) >= 0);
+ assert_se(r >= 0 ? w == v - 1 : w == v);
assert_se(procfs_tasks_set_limit(v) >= 0);
- assert_se(procfs_tasks_get_limit(&w) >= 0);
+ assert_se(procfs_get_threads_max(&w) >= 0);
assert_se(v == w);
}

View File

@ -0,0 +1,31 @@
From fe15b97e44beb69305d3970a3748624ae76f9f04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 3 Nov 2021 09:39:16 +0100
Subject: [PATCH] test-process-util: also add EROFS to the list of "good"
errors
It is only added in the one place where we actually try to set the
setting to a new value. Before we were testing if we can set to it the
existing value, which was a noop. We could still get a permission error,
but this is the first place where we would propagate EROFS.
(cherry picked from commit 6434a83d01d96e9f9a17ed9ce1f04a7d64859950)
Related: #1977569
---
src/test/test-procfs-util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/test/test-procfs-util.c b/src/test/test-procfs-util.c
index bb6943fed0..d656c4df4f 100644
--- a/src/test/test-procfs-util.c
+++ b/src/test/test-procfs-util.c
@@ -53,7 +53,7 @@ int main(int argc, char *argv[]) {
r = procfs_tasks_set_limit(v-1);
log_info_errno(r, "procfs_tasks_set_limit: %m");
- assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r));
+ assert_se(r >= 0 || ERRNO_IS_PRIVILEGE(r) || r == -EROFS);
assert_se(procfs_get_threads_max(&w) >= 0);
assert_se(r >= 0 ? w == v - 1 : w == v);

View File

@ -0,0 +1,146 @@
From a42cf9af339f48f633fa0b17a960e1e407b7450f Mon Sep 17 00:00:00 2001
From: Lorenz Bauer <lmb@cloudflare.com>
Date: Mon, 4 Nov 2019 16:35:46 +0000
Subject: [PATCH] journal: refresh cached credentials of stdout streams
journald assumes that getsockopt(SO_PEERCRED) correctly identifies the
process on the remote end of the socket. However, this is incorrect
according to man 7 socket:
The returned credentials are those that were in effect at the
time of the call to connect(2) or socketpair(2).
This becomes a problem when a new process inherits the stdout stream
from a parent. First, log messages from the child process will
be attributed to the parent. Second, the struct ucred used by journald
becomes invalid as soon as the parent exits. Further sendmsg calls then
fail with ENOENT. Logs for the child process then vanish from the journal.
Fix this by using recvmsg on the stdout stream, and refreshing the cached
struct ucred if SCM_CREDENTIALS indicate a new process.
Fixes #13708
(cherry picked from commit 09d0b46ab61bebafe5bdc1be95ee153dfb13d6bc)
Resolves: #1931806
---
src/journal/journald-stream.c | 49 ++++++++++++++++++++++++++--
test/TEST-04-JOURNAL/test-journal.sh | 13 ++++++++
2 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c
index 6f8a4011ff..302a82d3d7 100644
--- a/src/journal/journald-stream.c
+++ b/src/journal/journald-stream.c
@@ -484,11 +484,22 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
}
static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
+ uint8_t buf[CMSG_SPACE(sizeof(struct ucred))];
StdoutStream *s = userdata;
+ struct ucred *ucred = NULL;
+ struct cmsghdr *cmsg;
+ struct iovec iovec;
size_t limit;
ssize_t l;
int r;
+ struct msghdr msghdr = {
+ .msg_iov = &iovec,
+ .msg_iovlen = 1,
+ .msg_control = buf,
+ .msg_controllen = sizeof(buf),
+ };
+
assert(s);
if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
@@ -508,20 +519,50 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
* always leave room for a terminating NUL we might need to add. */
limit = MIN(s->allocated - 1, s->server->line_max);
- l = read(s->fd, s->buffer + s->length, limit - s->length);
+ iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length);
+
+ l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (l < 0) {
- if (errno == EAGAIN)
+ if (IN_SET(errno, EINTR, EAGAIN))
return 0;
log_warning_errno(errno, "Failed to read from stream: %m");
goto terminate;
}
+ cmsg_close_all(&msghdr);
if (l == 0) {
stdout_stream_scan(s, true);
goto terminate;
}
+ CMSG_FOREACH(cmsg, &msghdr)
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_CREDENTIALS &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
+ ucred = (struct ucred *)CMSG_DATA(cmsg);
+ break;
+ }
+
+ /* Invalidate the context if the pid of the sender changed.
+ * This happens when a forked process inherits stdout / stderr
+ * from a parent. In this case getpeercred returns the ucred
+ * of the parent, which can be invalid if the parent has exited
+ * in the meantime.
+ */
+ if (ucred && ucred->pid != s->ucred.pid) {
+ /* force out any previously half-written lines from a
+ * different process, before we switch to the new ucred
+ * structure for everything we just added */
+ r = stdout_stream_scan(s, true);
+ if (r < 0)
+ goto terminate;
+
+ s->ucred = *ucred;
+ client_context_release(s->server, s->context);
+ s->context = NULL;
+ }
+
s->length += l;
r = stdout_stream_scan(s, false);
if (r < 0)
@@ -559,6 +600,10 @@ int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
if (r < 0)
return log_error_errno(r, "Failed to determine peer credentials: %m");
+ r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true);
+ if (r < 0)
+ return log_error_errno(r, "SO_PASSCRED failed: %m");
+
if (mac_selinux_use()) {
r = getpeersec(fd, &stream->label);
if (r < 0 && r != -EOPNOTSUPP)
diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh
index 260cae09ab..52a6ee84d1 100755
--- a/test/TEST-04-JOURNAL/test-journal.sh
+++ b/test/TEST-04-JOURNAL/test-journal.sh
@@ -63,6 +63,19 @@ grep -q '^PRIORITY=6$' /output
! grep -q '^FOO=' /output
! grep -q '^SYSLOG_FACILITY=' /output
+# https://github.com/systemd/systemd/issues/13708
+ID=$(journalctl --new-id128 | sed -n 2p)
+systemd-cat -t "$ID" bash -c 'echo parent; (echo child) & wait' &
+PID=$!
+wait %%
+journalctl --sync
+# We can drop this grep when https://github.com/systemd/systemd/issues/13937
+# has a fix.
+journalctl -b -o export -t "$ID" --output-fields=_PID | grep '^_PID=' >/output
+[[ `grep -c . /output` -eq 2 ]]
+grep -q "^_PID=$PID" /output
+grep -vq "^_PID=$PID" /output
+
# Don't lose streams on restart
systemctl start forever-print-hola
sleep 3

View File

@ -0,0 +1,35 @@
From 39b10c9e7e4ad80adc0e8c43f7d1917edee515dd Mon Sep 17 00:00:00 2001
From: Evgeny Vereshchagin <evvers@ya.ru>
Date: Sun, 2 Dec 2018 08:28:24 +0100
Subject: [PATCH] util-lib: introduce HAS_FEATURE_ADDRESS_SANITIZER
https://clang.llvm.org/docs/AddressSanitizer.html#conditional-compilation-with-has-feature-address-sanitizer
(cherry picked from commit 289acab951c5937fdf6d3a2666f411fd66dd20e5)
Related: #2017033
---
src/basic/macro.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/basic/macro.h b/src/basic/macro.h
index 0fe6a62aa8..62f2359633 100644
--- a/src/basic/macro.h
+++ b/src/basic/macro.h
@@ -55,6 +55,17 @@
# endif
#endif
+#if !defined(HAS_FEATURE_ADDRESS_SANITIZER)
+# if defined(__has_feature)
+# if __has_feature(address_sanitizer)
+# define HAS_FEATURE_ADDRESS_SANITIZER 1
+# endif
+# endif
+# if !defined(HAS_FEATURE_ADDRESS_SANITIZER)
+# define HAS_FEATURE_ADDRESS_SANITIZER 0
+# endif
+#endif
+
/* Temporarily disable some warnings */
#define DISABLE_WARNING_DECLARATION_AFTER_STATEMENT \
_Pragma("GCC diagnostic push"); \

View File

@ -0,0 +1,34 @@
From c0c7a5d73bd53375f90fbe70287512269bc8de16 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Tue, 12 Jan 2021 22:14:59 +0100
Subject: [PATCH] ci: skip test-execute on GH Actions under ASan
It seems to suffer from the same issue as on Travis CI, where the test
randomly fails due to timeouts in its subtests.
See: https://github.com/systemd/systemd/issues/10696#issuecomment-758501797
(cherry picked from commit f1a8fed286e3b9527b1837e9d5c6cb8d88bd2041)
Related: #2017033
---
src/test/test-execute.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 294f8fe7dd..5303652b93 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -798,6 +798,13 @@ int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
+#if HAS_FEATURE_ADDRESS_SANITIZER
+ if (strstr_ptr(ci_environment(), "travis") || strstr_ptr(ci_environment(), "github-actions")) {
+ log_notice("Running on Travis CI/GH Actions under ASan, skipping, see https://github.com/systemd/systemd/issues/10696");
+ return EXIT_TEST_SKIP;
+ }
+#endif
+
(void) unsetenv("USER");
(void) unsetenv("LOGNAME");
(void) unsetenv("SHELL");

View File

@ -0,0 +1,27 @@
From 8c15742d1194e0db9a2555553e4d77ebb441b3dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 22 Sep 2020 19:05:17 +0200
Subject: [PATCH] test-seccomp: accept ENOSYS from sysctl(2) too
It seems that kernel 5.9 started returning that.
(cherry picked from commit 0af05e485a3a88f454c714901eb6109307dc893e)
Related: #2017033
---
src/test/test-seccomp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
index 5eb1c78b8b..6ec04c4c55 100644
--- a/src/test/test-seccomp.c
+++ b/src/test/test-seccomp.c
@@ -239,7 +239,7 @@ static void test_protect_sysctl(void) {
if (pid == 0) {
#if defined __NR__sysctl && __NR__sysctl >= 0
assert_se(syscall(__NR__sysctl, NULL) < 0);
- assert_se(errno == EFAULT);
+ assert_se(IN_SET(errno, EFAULT, ENOSYS));
#endif
assert_se(seccomp_protect_sysctl() >= 0);

View File

@ -0,0 +1,51 @@
From e61aa66a63bcfe9ce0d80f0db691ba40218b872a Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 14 Aug 2020 21:50:55 +0200
Subject: [PATCH] test: accept that char device 0/0 can now be created witout
privileges
Fixes: #16721
(cherry picked from commit 5b5ce6298e5a1c09beacd5c963e2350979cbf94a)
Related: #2017033
---
src/test/test-fs-util.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index e3338ea440..aa32629f62 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -518,8 +518,8 @@ static void test_touch_file(void) {
assert_se(timespec_load(&st.st_mtim) == test_mtime);
if (geteuid() == 0) {
- a = strjoina(p, "/cdev");
- r = mknod(a, 0775 | S_IFCHR, makedev(0, 0));
+ a = strjoina(p, "/bdev");
+ r = mknod(a, 0775 | S_IFBLK, makedev(0, 0));
if (r < 0 && errno == EPERM && detect_container() > 0) {
log_notice("Running in unprivileged container? Skipping remaining tests in %s", __func__);
return;
@@ -529,17 +529,17 @@ static void test_touch_file(void) {
assert_se(lstat(a, &st) >= 0);
assert_se(st.st_uid == test_uid);
assert_se(st.st_gid == test_gid);
- assert_se(S_ISCHR(st.st_mode));
+ assert_se(S_ISBLK(st.st_mode));
assert_se((st.st_mode & 0777) == 0640);
assert_se(timespec_load(&st.st_mtim) == test_mtime);
- a = strjoina(p, "/bdev");
- assert_se(mknod(a, 0775 | S_IFBLK, makedev(0, 0)) >= 0);
+ a = strjoina(p, "/cdev");
+ assert_se(mknod(a, 0775 | S_IFCHR, makedev(0, 0)) >= 0);
assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
assert_se(lstat(a, &st) >= 0);
assert_se(st.st_uid == test_uid);
assert_se(st.st_gid == test_gid);
- assert_se(S_ISBLK(st.st_mode));
+ assert_se(S_ISCHR(st.st_mode));
assert_se((st.st_mode & 0777) == 0640);
assert_se(timespec_load(&st.st_mtim) == test_mtime);
}

View File

@ -0,0 +1,54 @@
From d5cefb7293d2999dcad81bd71933b319ca6c3590 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 12 Apr 2021 14:03:32 +0200
Subject: [PATCH] meson: do not fail if rsync is not installed with meson
0.57.2
https://github.com/mesonbuild/meson/issues/8641
Our CI started to fail. Even if the change is reverted in meson,
we need a quick workaround here.
(cherry picked from commit 7c5fd25119a495009ea62f79e5daec34cc464628)
Related: #2017033
---
man/meson.build | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/man/meson.build b/man/meson.build
index a953d34098..efc8836d0c 100644
--- a/man/meson.build
+++ b/man/meson.build
@@ -178,17 +178,20 @@ html = custom_target(
depends : html_pages,
command : ['echo'])
-run_target(
- 'doc-sync',
- depends : man_pages + html_pages,
- command : ['rsync', '-rlv',
- '--delete-excluded',
- '--include=man',
- '--include=*.html',
- '--exclude=*',
- '--omit-dir-times',
- meson.current_build_dir(),
- get_option('www-target')])
+rsync = find_program('rsync', required : false)
+if rsync.found()
+ run_target(
+ 'doc-sync',
+ depends : man_pages + html_pages,
+ command : [rsync, '-rlv',
+ '--delete-excluded',
+ '--include=man',
+ '--include=*.html',
+ '--exclude=*',
+ '--omit-dir-times',
+ meson.current_build_dir(),
+ get_option('www-target')])
+endif
############################################################

View File

@ -0,0 +1,27 @@
From 30afbfdc82eb61f3bf47d6b1fa67a61d0ffcc4f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Fri, 14 Dec 2018 08:16:31 +0100
Subject: [PATCH] pid1: fix free of uninitialized pointer in
unit_fail_if_noncanonical()
https://bugzilla.redhat.com/show_bug.cgi?id=1653068
(cherry picked from commit 58d9d89b4b41189bdcea86c2ad5cf708b7d54aca)
Related: #1970945
---
src/core/unit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 93c13e58d9..152a860d08 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -4785,7 +4785,7 @@ void unit_warn_if_dir_nonempty(Unit *u, const char* where) {
}
int unit_fail_if_noncanonical(Unit *u, const char* where) {
- _cleanup_free_ char *canonical_where;
+ _cleanup_free_ char *canonical_where = NULL;
int r;
assert(u);

View File

@ -0,0 +1,32 @@
From f025def77efc6bb1473b719e905fa70ed20b08d3 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Wed, 8 Sep 2021 15:42:11 +0200
Subject: [PATCH] sd-event: take ref on event loop object before dispatching
event sources
Idea is that all public APIs should take reference on objects that get
exposed to user-provided callbacks. We take the reference as a
protection from callbacks dropping it. We used to do this also here in
sd_event_loop(). However, in cleanup portion of f814c871e6 this was
accidentally dropped.
(cherry picked from commit 9f6ef467818f902fe5369c8e37a39a3901bdcf4f)
Related: #1970945
---
src/libsystemd/sd-event/sd-event.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index f78da00c3a..47cf93b3f4 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -3838,7 +3838,7 @@ _public_ int sd_event_loop(sd_event *e) {
assert_return(!event_pid_changed(e), -ECHILD);
assert_return(e->state == SD_EVENT_INITIAL, -EBUSY);
- _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = NULL;
+ _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e);
while (e->state != SD_EVENT_FINISHED) {
r = sd_event_run(e, (uint64_t) -1);

View File

@ -0,0 +1,33 @@
From c667291303bb876707d86ac3ab9ca62355bae1b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 16 Oct 2018 22:45:34 +0200
Subject: [PATCH] core: consider service with no start command immediately
started
The service would always be in state == SERVICE_INACTIVE, but it needs to go
through state == SERVICE_START so that SuccessAction/FailureAction are executed.
(cherry picked from commit ef5ae8e71329e43c277e6d4f983f0c0793047b94)
Related: #1860899
---
src/core/service.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/core/service.c b/src/core/service.c
index ae31973774..4da1c5accb 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -2055,6 +2055,12 @@ static void service_enter_start(Service *s) {
goto fail;
}
+ /* We force a fake state transition here. Otherwise, the unit would go directly from
+ * SERVICE_DEAD to SERVICE_DEAD without SERVICE_ACTIVATING or SERVICE_ACTIVE
+ * inbetween. This way we can later trigger actions that depend on the state
+ * transition, including SuccessAction=. */
+ service_set_state(s, SERVICE_START);
+
service_enter_start_post(s);
return;
}

Some files were not shown because too many files have changed in this diff Show More