summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemctl.xml20
-rw-r--r--man/systemd-socket-proxyd.xml2
-rw-r--r--po/lt.po49
-rw-r--r--shell-completion/bash/systemctl.in2
-rw-r--r--shell-completion/zsh/_systemctl.in1
-rw-r--r--src/basic/process-util.c46
-rw-r--r--src/basic/process-util.h12
-rw-r--r--src/core/unit.c21
-rw-r--r--src/home/homed-home.c12
-rw-r--r--src/import/import-common.c26
-rw-r--r--src/import/importd.c16
-rw-r--r--src/import/pull-common.c14
-rw-r--r--src/journal-remote/journal-remote-main.c13
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c10
-rw-r--r--src/libsystemd/sd-journal/journal-file.c50
-rw-r--r--src/libsystemd/sd-journal/journal-file.h1
-rw-r--r--src/libsystemd/sd-journal/sd-journal.c47
-rw-r--r--src/login/logind-brightness.c2
-rw-r--r--src/login/pam_systemd.c38
-rw-r--r--src/nspawn/nspawn-setuid.c18
-rw-r--r--src/resolve/test-resolved-stream.c12
-rw-r--r--src/shared/dissect-image.c3
-rw-r--r--src/shared/elf-util.c1
-rw-r--r--src/shared/exec-util.c1
-rw-r--r--src/shared/pager.c2
-rw-r--r--src/shutdown/umount.c10
-rw-r--r--src/socket-proxy/socket-proxyd.c3
-rw-r--r--src/systemctl/systemctl-list-units.c311
-rw-r--r--src/systemctl/systemctl-list-units.h1
-rw-r--r--src/systemctl/systemctl.c3
-rw-r--r--src/sysupdate/sysupdate-resource.c14
-rw-r--r--src/test/test-execute.c10
-rw-r--r--src/test/test-process-util.c2
-rw-r--r--src/udev/udev-event.c12
-rwxr-xr-xtest/units/testsuite-26.sh17
-rwxr-xr-xtest/units/testsuite-70.sh3
36 files changed, 523 insertions, 282 deletions
diff --git a/man/systemctl.xml b/man/systemctl.xml
index dfaca638c2..7ac3a4267d 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -128,6 +128,26 @@ binfmt_misc /proc/sys/fs/binfmt_misc yes 0 proc-sys-fs-binfmt_mis
</varlistentry>
<varlistentry>
+ <term><command>list-paths</command> <optional><replaceable>PATTERN</replaceable>…</optional></term>
+
+ <listitem>
+ <para>List path units currently in memory, ordered by path. If one or more
+ <replaceable>PATTERN</replaceable>s are specified, only path units matching one of them are shown.
+ Produces output similar to
+ <programlisting>
+PATH CONDITION UNIT ACTIVATES
+/run/systemd/ask-password DirectoryNotEmpty systemd-ask-password-plymouth.path systemd-ask-password-plymouth.service
+/run/systemd/ask-password DirectoryNotEmpty systemd-ask-password-wall.path systemd-ask-password-wall.service
+/var/cache/cups/org.cups.cupsd PathExists cups.path cups.service
+
+3 paths listed.</programlisting>
+ </para>
+
+ <para>Also see <option>--show-types</option>, <option>--all</option>, and <option>--state=</option>.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><command>list-sockets</command> <optional><replaceable>PATTERN</replaceable>…</optional></term>
<listitem>
diff --git a/man/systemd-socket-proxyd.xml b/man/systemd-socket-proxyd.xml
index e512a4334e..bf51c0558c 100644
--- a/man/systemd-socket-proxyd.xml
+++ b/man/systemd-socket-proxyd.xml
@@ -104,6 +104,7 @@ Requires=proxy-to-nginx.socket
After=proxy-to-nginx.socket
[Service]
+Type=notify
ExecStart=/usr/lib/systemd/systemd-socket-proxyd /run/nginx/socket
PrivateTmp=yes
PrivateNetwork=yes]]></programlisting>
@@ -151,6 +152,7 @@ After=proxy-to-nginx.socket
JoinsNamespaceOf=nginx.service
[Service]
+Type=notify
ExecStart=/usr/lib/systemd/systemd-socket-proxyd 127.0.0.1:8080
PrivateTmp=yes
PrivateNetwork=yes]]></programlisting>
diff --git a/po/lt.po b/po/lt.po
index dba667b2b3..d4d0c5ac4f 100644
--- a/po/lt.po
+++ b/po/lt.po
@@ -1,20 +1,22 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Moo, 2018. #zanata
+# mooo <hazap@hotmail.com>, 2023.
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-10-20 10:35+0200\n"
-"PO-Revision-Date: 2019-04-08 22:01+0300\n"
-"Last-Translator: Moo\n"
-"Language-Team: Lithuanian\n"
+"PO-Revision-Date: 2023-02-21 23:20+0000\n"
+"Last-Translator: mooo <hazap@hotmail.com>\n"
+"Language-Team: Lithuanian <https://translate.fedoraproject.org/projects/"
+"systemd/master/lt/>\n"
"Language: lt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.2.1\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
-"%100<10 || n%100>=20) ? 1 : 2);\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && ("
+"n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Weblate 4.15.2\n"
#: src/core/org.freedesktop.systemd1.policy.in:22
msgid "Send passphrase back to system"
@@ -176,14 +178,12 @@ msgid "Authentication is required to get hardware serial number."
msgstr "Norint nustatyti sistemos laiką, reikia nustatyti tapatybę."
#: src/hostname/org.freedesktop.hostname1.policy:71
-#, fuzzy
msgid "Get system description"
-msgstr "Nustatyti sistemos laiko juostą"
+msgstr "Gauti sistemos aprašą"
#: src/hostname/org.freedesktop.hostname1.policy:72
-#, fuzzy
msgid "Authentication is required to get system description."
-msgstr "Norint nustatyti sistemos laiko juostą, reikia nustatyti tapatybę."
+msgstr "Norint gauti sistemos aprašą, reikia nustatyti tapatybę."
#: src/import/org.freedesktop.import1.policy:22
msgid "Import a VM or container image"
@@ -617,7 +617,7 @@ msgstr "Norint nustatyti sienos pranešimą, reikia nustatyti tapatybę"
#: src/login/org.freedesktop.login1.policy:406
msgid "Change Session"
-msgstr ""
+msgstr "Keisti seansą"
#: src/login/org.freedesktop.login1.policy:407
#, fuzzy
@@ -712,15 +712,13 @@ msgstr "Norint nustatyti sistemos laiką, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:33
#: src/resolve/org.freedesktop.resolve1.policy:44
-#, fuzzy
msgid "Set DNS servers"
-msgstr "Registruoti DNS-SD tarnybą"
+msgstr "Nustatyti DNS serverius"
#: src/network/org.freedesktop.network1.policy:34
#: src/resolve/org.freedesktop.resolve1.policy:45
-#, fuzzy
msgid "Authentication is required to set DNS servers."
-msgstr "Norint registruoti DNS-SD tarnybą, reikia nustatyti tapatybę"
+msgstr "Norint nustatyti DNS serverius, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:44
#: src/resolve/org.freedesktop.resolve1.policy:55
@@ -736,25 +734,22 @@ msgstr "Norint stabdyti \"$(unit)\", reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:55
#: src/resolve/org.freedesktop.resolve1.policy:66
msgid "Set default route"
-msgstr ""
+msgstr "Nustatyti numatytąjį maršrutą"
#: src/network/org.freedesktop.network1.policy:56
#: src/resolve/org.freedesktop.resolve1.policy:67
-#, fuzzy
msgid "Authentication is required to set default route."
-msgstr ""
-"Norint nustatyti vietinio serverio pavadinimą, reikia nustatyti tapatybę."
+msgstr "Norint nustatyti numatytąjį maršrutą, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:66
#: src/resolve/org.freedesktop.resolve1.policy:77
msgid "Enable/disable LLMNR"
-msgstr ""
+msgstr "Įjungti/išjungti LLMNR"
#: src/network/org.freedesktop.network1.policy:67
#: src/resolve/org.freedesktop.resolve1.policy:78
-#, fuzzy
msgid "Authentication is required to enable or disable LLMNR."
-msgstr "Norint užmigdyti sistemą, reikia nustatyti tapatybę."
+msgstr "Norint įjungti ar išjungti LLMNR, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:77
#: src/resolve/org.freedesktop.resolve1.policy:88
@@ -770,24 +765,22 @@ msgstr "Norint gauti produkto UUID, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:88
#: src/resolve/org.freedesktop.resolve1.policy:99
msgid "Enable/disable DNS over TLS"
-msgstr ""
+msgstr "Įjungti/išjungti DNS per TLS"
#: src/network/org.freedesktop.network1.policy:89
#: src/resolve/org.freedesktop.resolve1.policy:100
-#, fuzzy
msgid "Authentication is required to enable or disable DNS over TLS."
-msgstr "Norint registruoti DNS-SD tarnybą, reikia nustatyti tapatybę"
+msgstr "Norint įjungti ar išjungti DNS per TLS, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:99
#: src/resolve/org.freedesktop.resolve1.policy:110
msgid "Enable/disable DNSSEC"
-msgstr ""
+msgstr "Įjungti/išjungti DNSSEC"
#: src/network/org.freedesktop.network1.policy:100
#: src/resolve/org.freedesktop.resolve1.policy:111
-#, fuzzy
msgid "Authentication is required to enable or disable DNSSEC."
-msgstr "Norint užmigdyti sistemą, reikia nustatyti tapatybę."
+msgstr "Norint įjungti ar išjungti DNSSEC, reikia nustatyti tapatybę."
#: src/network/org.freedesktop.network1.policy:110
#: src/resolve/org.freedesktop.resolve1.policy:121
diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
index 3c64467e2f..0e411f5a5f 100644
--- a/shell-completion/bash/systemctl.in
+++ b/shell-completion/bash/systemctl.in
@@ -216,7 +216,7 @@ _systemctl () {
suspend-then-hibernate kexec list-jobs list-sockets
list-timers list-units list-unit-files poweroff
reboot rescue show-environment suspend get-default
- is-system-running preset-all list-automounts'
+ is-system-running preset-all list-automounts list-paths'
[FILE]='link switch-root bind mount-image'
[TARGETS]='set-default'
[MACHINES]='list-machines'
diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
index 2811582236..9df9e571a1 100644
--- a/shell-completion/zsh/_systemctl.in
+++ b/shell-completion/zsh/_systemctl.in
@@ -8,6 +8,7 @@
local -a unit_commands=(
# Unit Commands
"list-automounts:List automounts"
+ "list-paths:List paths"
"list-sockets:List sockets"
"list-timers:List timers"
"list-units:List units"
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 4df369dd2a..919387f958 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -1134,6 +1134,7 @@ static void restore_sigsetp(sigset_t **ssp) {
int safe_fork_full(
const char *name,
+ const int stdio_fds[3],
const int except_fds[],
size_t n_except_fds,
ForkFlags flags,
@@ -1292,6 +1293,27 @@ int safe_fork_full(
}
}
+ if (flags & FORK_REARRANGE_STDIO) {
+ if (stdio_fds) {
+ r = rearrange_stdio(stdio_fds[0], stdio_fds[1], stdio_fds[2]);
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to rearrange stdio fds: %m");
+ _exit(EXIT_FAILURE);
+ }
+ } else {
+ r = make_null_stdio();
+ if (r < 0) {
+ log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+ } else if (flags & FORK_STDOUT_TO_STDERR) {
+ if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
+ log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
if (flags & FORK_CLOSE_ALL_FDS) {
/* Close the logs here in case it got reopened above, as close_all_fds() would close them for us */
log_close();
@@ -1317,20 +1339,6 @@ int safe_fork_full(
log_set_open_when_needed(false);
}
- if (flags & FORK_NULL_STDIO) {
- r = make_null_stdio();
- if (r < 0) {
- log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
- _exit(EXIT_FAILURE);
- }
-
- } else if (flags & FORK_STDOUT_TO_STDERR) {
- if (dup2(STDERR_FILENO, STDOUT_FILENO) < 0) {
- log_full_errno(prio, errno, "Failed to connect stdout to stderr: %m");
- _exit(EXIT_FAILURE);
- }
- }
-
if (flags & FORK_RLIMIT_NOFILE_SAFE) {
r = rlimit_nofile_safe();
if (r < 0) {
@@ -1364,7 +1372,10 @@ int namespace_fork(
* process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that
* /proc/self/fd works correctly. */
- r = safe_fork_full(outer_name, except_fds, n_except_fds, (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
+ r = safe_fork_full(outer_name,
+ NULL,
+ except_fds, n_except_fds,
+ (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
if (r < 0)
return r;
if (r == 0) {
@@ -1379,7 +1390,10 @@ int namespace_fork(
}
/* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */
- r = safe_fork_full(inner_name, except_fds, n_except_fds, flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NULL_STDIO), &pid);
+ r = safe_fork_full(inner_name,
+ NULL,
+ except_fds, n_except_fds,
+ flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO), &pid);
if (r < 0)
_exit(EXIT_FAILURE);
if (r == 0) {
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 279f5d6e6b..6f6fc7d94e 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -143,7 +143,7 @@ typedef enum ForkFlags {
FORK_CLOSE_ALL_FDS = 1 << 1, /* Close all open file descriptors in the child, except for 0,1,2 */
FORK_DEATHSIG = 1 << 2, /* Set PR_DEATHSIG in the child to SIGTERM */
FORK_DEATHSIG_SIGINT = 1 << 3, /* Set PR_DEATHSIG in the child to SIGINT */
- FORK_NULL_STDIO = 1 << 4, /* Connect 0,1,2 to /dev/null */
+ FORK_REARRANGE_STDIO = 1 << 4, /* Connect 0,1,2 to specified fds or /dev/null */
FORK_REOPEN_LOG = 1 << 5, /* Reopen log connection */
FORK_LOG = 1 << 6, /* Log above LOG_DEBUG log level about failures */
FORK_WAIT = 1 << 7, /* Wait until child exited */
@@ -157,10 +157,16 @@ typedef enum ForkFlags {
FORK_CLOEXEC_OFF = 1 << 15, /* In the child: turn off O_CLOEXEC on all fds in except_fds[] */
} ForkFlags;
-int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
+int safe_fork_full(
+ const char *name,
+ const int stdio_fds[3],
+ const int except_fds[],
+ size_t n_except_fds,
+ ForkFlags flags,
+ pid_t *ret_pid);
static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
- return safe_fork_full(name, NULL, 0, flags, ret_pid);
+ return safe_fork_full(name, NULL, NULL, 0, flags, ret_pid);
}
int namespace_fork(const char *outer_name, const char *inner_name, const int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid);
diff --git a/src/core/unit.c b/src/core/unit.c
index be7b19877f..8cd1e0370d 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -4213,14 +4213,21 @@ int unit_patch_contexts(Unit *u) {
}
/* If there are encrypted credentials we might need to access the TPM. */
- ExecLoadCredential *cred;
- HASHMAP_FOREACH(cred, ec->load_credentials)
- if (cred->encrypted) {
- r = cgroup_add_device_allow(cc, "/dev/tpmrm0", "rw");
- if (r < 0)
- return r;
+ bool allow_tpm = false;
+ ExecLoadCredential *load_cred;
+ ExecSetCredential *set_cred;
+ HASHMAP_FOREACH(load_cred, ec->load_credentials)
+ if ((allow_tpm |= load_cred->encrypted))
break;
- }
+ HASHMAP_FOREACH(set_cred, ec->set_credentials)
+ if ((allow_tpm |= set_cred->encrypted))
+ break;
+
+ if (allow_tpm) {
+ r = cgroup_add_device_allow(cc, "/dev/tpmrm0", "rw");
+ if (r < 0)
+ return r;
+ }
}
}
diff --git a/src/home/homed-home.c b/src/home/homed-home.c
index e6b7740600..413fcf1773 100644
--- a/src/home/homed-home.c
+++ b/src/home/homed-home.c
@@ -1180,8 +1180,9 @@ static int home_start_work(Home *h, const char *verb, UserRecord *hr, UserRecord
return -errno;
r = safe_fork_full("(sd-homework)",
- (int[]) { stdin_fd, stdout_fd }, 2,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_REOPEN_LOG, &pid);
+ (int[]) { stdin_fd, stdout_fd, STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_REOPEN_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
@@ -1226,13 +1227,6 @@ static int home_start_work(Home *h, const char *verb, UserRecord *hr, UserRecord
if (r < 0)
log_warning_errno(r, "Failed to update $SYSTEMD_EXEC_PID, ignoring: %m");
- r = rearrange_stdio(TAKE_FD(stdin_fd), TAKE_FD(stdout_fd), STDERR_FILENO); /* fds are invalidated by rearrange_stdio() even on failure */
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout/stderr: %m");
- _exit(EXIT_FAILURE);
- }
-
-
/* Allow overriding the homework path via an environment variable, to make debugging
* easier. */
homework = getenv("SYSTEMD_HOMEWORK_PATH") ?: SYSTEMD_HOMEWORK_PATH;
diff --git a/src/import/import-common.c b/src/import/import-common.c
index 874d27d292..7227f885a8 100644
--- a/src/import/import-common.c
+++ b/src/import/import-common.c
@@ -36,7 +36,10 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
use_selinux = mac_selinux_use();
- r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork_full("(tar)",
+ (int[]) { pipefd[0], -EBADF, STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
@@ -63,14 +66,6 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
/* Child */
- pipefd[1] = safe_close(pipefd[1]);
-
- r = rearrange_stdio(TAKE_FD(pipefd[0]), -EBADF, STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
if (unshare(CLONE_NEWNET) < 0)
log_warning_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
@@ -110,7 +105,10 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
use_selinux = mac_selinux_use();
- r = safe_fork("(tar)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork_full("(tar)",
+ (int[]) { -EBADF, pipefd[1], STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
@@ -129,14 +127,6 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
/* Child */
- pipefd[0] = safe_close(pipefd[0]);
-
- r = rearrange_stdio(-EBADF, TAKE_FD(pipefd[1]), STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
if (unshare(CLONE_NEWNET) < 0)
log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
diff --git a/src/import/importd.c b/src/import/importd.c
index 65647a66a6..5f7b9c3163 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -365,7 +365,10 @@ static int transfer_start(Transfer *t) {
if (pipe2(pipefd, O_CLOEXEC) < 0)
return -errno;
- r = safe_fork("(sd-transfer)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &t->pid);
+ r = safe_fork_full("(sd-transfer)",
+ (int[]) { t->stdin_fd, t->stdout_fd < 0 ? pipefd[1] : t->stdout_fd, pipefd[1] },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO, &t->pid);
if (r < 0)
return r;
if (r == 0) {
@@ -387,17 +390,6 @@ static int transfer_start(Transfer *t) {
/* Child */
- pipefd[0] = safe_close(pipefd[0]);
-
- r = rearrange_stdio(TAKE_FD(t->stdin_fd),
- t->stdout_fd < 0 ? pipefd[1] : TAKE_FD(t->stdout_fd),
- pipefd[1]);
- TAKE_FD(pipefd[1]);
- if (r < 0) {
- log_error_errno(r, "Failed to set stdin/stdout/stderr: %m");
- _exit(EXIT_FAILURE);
- }
-
if (setenv("SYSTEMD_LOG_TARGET", "console-prefixed", 1) < 0 ||
setenv("NOTIFY_SOCKET", "/run/systemd/import/notify", 1) < 0) {
log_error_errno(errno, "setenv() failed: %m");
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index c8a3bf370e..3b80e64b32 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -414,7 +414,11 @@ static int verify_gpg(
gpg_home_created = true;
- r = safe_fork("(gpg)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
+ r = safe_fork_full("(gpg)",
+ (int[]) { gpg_pipe[0], -EBADF, STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
+ &pid);
if (r < 0)
return r;
if (r == 0) {
@@ -437,14 +441,6 @@ static int verify_gpg(
/* Child */
- gpg_pipe[1] = safe_close(gpg_pipe[1]);
-
- r = rearrange_stdio(TAKE_FD(gpg_pipe[0]), -EBADF, STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
cmd[k++] = strjoina("--homedir=", gpg_home);
/* We add the user keyring only to the command line arguments, if it's around since gpg fails
diff --git a/src/journal-remote/journal-remote-main.c b/src/journal-remote/journal-remote-main.c
index 7df264fb53..e620b60a31 100644
--- a/src/journal-remote/journal-remote-main.c
+++ b/src/journal-remote/journal-remote-main.c
@@ -85,7 +85,10 @@ static int spawn_child(const char* child, char** argv) {
if (pipe(fd) < 0)
return log_error_errno(errno, "Failed to create pager pipe: %m");
- r = safe_fork("(remote)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &child_pid);
+ r = safe_fork_full("(remote)",
+ (int[]) {STDIN_FILENO, fd[1], STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &child_pid);
if (r < 0) {
safe_close_pair(fd);
return r;
@@ -93,14 +96,6 @@ static int spawn_child(const char* child, char** argv) {
/* In the child */
if (r == 0) {
- fd[0] = safe_close(fd[0]);
-
- r = rearrange_stdio(STDIN_FILENO, TAKE_FD(fd[1]), STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to dup pipe to stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
execvp(child, argv);
log_error_errno(errno, "Failed to exec child %s: %m", child);
_exit(EXIT_FAILURE);
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 64037e4fe0..33cfeebda7 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -994,7 +994,10 @@ int bus_socket_exec(sd_bus *b) {
if (r < 0)
return -errno;
- r = safe_fork_full("(sd-busexec)", s+1, 1, FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE, &b->busexec_pid);
+ r = safe_fork_full("(sd-busexec)",
+ (int[]) { s[1], s[1], STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO|FORK_RLIMIT_NOFILE_SAFE, &b->busexec_pid);
if (r < 0) {
safe_close_pair(s);
return r;
@@ -1002,11 +1005,6 @@ int bus_socket_exec(sd_bus *b) {
if (r == 0) {
/* Child */
- r = rearrange_stdio(s[1], s[1], STDERR_FILENO);
- TAKE_FD(s[1]);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
if (b->exec_argv)
execvp(b->exec_path, b->exec_argv);
else
diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c
index b1064a6982..c4971a807c 100644
--- a/src/libsystemd/sd-journal/journal-file.c
+++ b/src/libsystemd/sd-journal/journal-file.c
@@ -3193,56 +3193,6 @@ void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset) {
f->current_xor_hash = le64toh(o->entry.xor_hash);
}
-int journal_file_compare_locations(JournalFile *af, JournalFile *bf) {
- int r;
-
- assert(af);
- assert(af->header);
- assert(bf);
- assert(bf->header);
- assert(af->location_type == LOCATION_SEEK);
- assert(bf->location_type == LOCATION_SEEK);
-
- /* If contents, timestamps and seqnum match, these entries are
- * identical. */
- if (sd_id128_equal(af->current_boot_id, bf->current_boot_id) &&
- af->current_monotonic == bf->current_monotonic &&
- af->current_realtime == bf->current_realtime &&
- af->current_xor_hash == bf->current_xor_hash &&
- sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id) &&
- af->current_seqnum == bf->current_seqnum)
- return 0;
-
- if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
-
- /* If this is from the same seqnum source, compare
- * seqnums */
- r = CMP(af->current_seqnum, bf->current_seqnum);
- if (r != 0)
- return r;
-
- /* Wow! This is weird, different data but the same
- * seqnums? Something is borked, but let's make the
- * best of it and compare by time. */
- }
-
- if (sd_id128_equal(af->current_boot_id, bf->current_boot_id)) {
-
- /* If the boot id matches, compare monotonic time */
- r = CMP(af->current_monotonic, bf->current_monotonic);
- if (r != 0)
- return r;
- }
-
- /* Otherwise, compare UTC time */
- r = CMP(af->current_realtime, bf->current_realtime);
- if (r != 0)
- return r;
-
- /* Finally, compare by contents */
- return CMP(af->current_xor_hash, bf->current_xor_hash);
-}
-
static bool check_properly_ordered(uint64_t new_offset, uint64_t old_offset, direction_t direction) {
/* Consider it an error if any of the two offsets is uninitialized */
diff --git a/src/libsystemd/sd-journal/journal-file.h b/src/libsystemd/sd-journal/journal-file.h
index c1f1ab4e4f..2a0691ae19 100644
--- a/src/libsystemd/sd-journal/journal-file.h
+++ b/src/libsystemd/sd-journal/journal-file.h
@@ -275,7 +275,6 @@ int journal_file_find_field_object_with_hash(JournalFile *f, const void *field,
void journal_file_reset_location(JournalFile *f);
void journal_file_save_location(JournalFile *f, Object *o, uint64_t offset);
-int journal_file_compare_locations(JournalFile *af, JournalFile *bf);
int journal_file_next_entry(JournalFile *f, uint64_t p, direction_t direction, Object **ret_object, uint64_t *ret_offset);
int journal_file_next_entry_for_data(JournalFile *f, Object *d, direction_t direction, Object **ret_object, uint64_t *ret_offset);
diff --git a/src/libsystemd/sd-journal/sd-journal.c b/src/libsystemd/sd-journal/sd-journal.c
index afbf255266..053149d675 100644
--- a/src/libsystemd/sd-journal/sd-journal.c
+++ b/src/libsystemd/sd-journal/sd-journal.c
@@ -801,6 +801,51 @@ static int next_beyond_location(sd_journal *j, JournalFile *f, direction_t direc
}
}
+static int compare_locations(JournalFile *af, JournalFile *bf) {
+ int r;
+
+ assert(af);
+ assert(af->header);
+ assert(bf);
+ assert(bf->header);
+ assert(af->location_type == LOCATION_SEEK);
+ assert(bf->location_type == LOCATION_SEEK);
+
+ /* If contents, timestamps and seqnum match, these entries are identical. */
+ if (sd_id128_equal(af->current_boot_id, bf->current_boot_id) &&
+ af->current_monotonic == bf->current_monotonic &&
+ af->current_realtime == bf->current_realtime &&
+ af->current_xor_hash == bf->current_xor_hash &&
+ sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id) &&
+ af->current_seqnum == bf->current_seqnum)
+ return 0;
+
+ if (sd_id128_equal(af->header->seqnum_id, bf->header->seqnum_id)) {
+ /* If this is from the same seqnum source, compare seqnums */
+ r = CMP(af->current_seqnum, bf->current_seqnum);
+ if (r != 0)
+ return r;
+
+ /* Wow! This is weird, different data but the same seqnums? Something is borked, but let's
+ * make the best of it and compare by time. */
+ }
+
+ if (sd_id128_equal(af->current_boot_id, bf->current_boot_id)) {
+ /* If the boot id matches, compare monotonic time */
+ r = CMP(af->current_monotonic, bf->current_monotonic);
+ if (r != 0)
+ return r;
+ }
+
+ /* Otherwise, compare UTC time */
+ r = CMP(af->current_realtime, bf->current_realtime);
+ if (r != 0)
+ return r;
+
+ /* Finally, compare by contents */
+ return CMP(af->current_xor_hash, bf->current_xor_hash);
+}
+
static int real_journal_next(sd_journal *j, direction_t direction) {
JournalFile *new_file = NULL;
unsigned n_files;
@@ -834,7 +879,7 @@ static int real_journal_next(sd_journal *j, direction_t direction) {
else {
int k;
- k = journal_file_compare_locations(f, new_file);
+ k = compare_locations(f, new_file);
found = direction == DIRECTION_DOWN ? k < 0 : k > 0;
}
diff --git a/src/login/logind-brightness.c b/src/login/logind-brightness.c
index 21feaae0c3..d238cb74c9 100644
--- a/src/login/logind-brightness.c
+++ b/src/login/logind-brightness.c
@@ -136,7 +136,7 @@ static int brightness_writer_fork(BrightnessWriter *w) {
assert(w->child == 0);
assert(!w->child_event_source);
- r = safe_fork("(sd-bright)", FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &w->child);
+ r = safe_fork("(sd-bright)", FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &w->child);
if (r < 0)
return r;
if (r == 0) {
diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c
index ba2fca32c6..2cfe52288e 100644
--- a/src/login/pam_systemd.c
+++ b/src/login/pam_systemd.c
@@ -390,24 +390,40 @@ static int append_session_tasks_max(pam_handle_t *handle, sd_bus_message *m, con
return PAM_SUCCESS;
}
-static int append_session_cg_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit, const char *field) {
+static int append_session_cpu_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
uint64_t val;
int r;
- bool is_cpu_weight;
- is_cpu_weight = streq(field, "CPUWeight");
if (isempty(limit))
return PAM_SUCCESS;
- r = is_cpu_weight ? cg_cpu_weight_parse(limit, &val) : cg_weight_parse(limit, &val);
- if (r >= 0) {
- r = sd_bus_message_append(m, "(sv)", field, "t", val);
+ r = cg_cpu_weight_parse(limit, &val);
+ if (r < 0)
+ pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight, ignoring: %s", limit);
+ else {
+ r = sd_bus_message_append(m, "(sv)", "CPUWeight", "t", val);
if (r < 0)
return pam_bus_log_create_error(handle, r);
- } else if (is_cpu_weight)
- pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.cpu_weight, ignoring: %s", limit);
- else
+ }
+
+ return PAM_SUCCESS;
+}
+
+static int append_session_io_weight(pam_handle_t *handle, sd_bus_message *m, const char *limit) {
+ uint64_t val;
+ int r;
+
+ if (isempty(limit))
+ return PAM_SUCCESS;
+
+ r = cg_weight_parse(limit, &val);
+ if (r < 0)
pam_syslog(handle, LOG_WARNING, "Failed to parse systemd.io_weight, ignoring: %s", limit);
+ else {
+ r = sd_bus_message_append(m, "(sv)", "IOWeight", "t", val);
+ if (r < 0)
+ return pam_bus_log_create_error(handle, r);
+ }
return PAM_SUCCESS;
}
@@ -869,11 +885,11 @@ _public_ PAM_EXTERN int pam_sm_open_session(
if (r != PAM_SUCCESS)
return r;
- r = append_session_cg_weight(handle, m, cpu_weight, "CPUWeight");
+ r = append_session_cpu_weight(handle, m, cpu_weight);
if (r != PAM_SUCCESS)
return r;
- r = append_session_cg_weight(handle, m, io_weight, "IOWeight");
+ r = append_session_io_weight(handle, m, io_weight);
if (r != PAM_SUCCESS)
return r;
diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c
index 5772d96b2f..3c12648b9d 100644
--- a/src/nspawn/nspawn-setuid.c
+++ b/src/nspawn/nspawn-setuid.c
@@ -28,23 +28,17 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
if (pipe2(pipe_fds, O_CLOEXEC) < 0)
return log_error_errno(errno, "Failed to allocate pipe: %m");
- r = safe_fork("(getent)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
+ r = safe_fork_full("(getent)",
+ (int[]) { -EBADF, pipe_fds[1], -EBADF }, NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
+ &pid);
if (r < 0) {
safe_close_pair(pipe_fds);
return r;
}
if (r == 0) {
- char *empty_env = NULL;
-
- pipe_fds[0] = safe_close(pipe_fds[0]);
-
- if (rearrange_stdio(-EBADF, TAKE_FD(pipe_fds[1]), -EBADF) < 0)
- _exit(EXIT_FAILURE);
-
- (void) close_all_fds(NULL, 0);
-
- execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env);
- execle("/bin/getent", "getent", database, key, NULL, &empty_env);
+ execle("/usr/bin/getent", "getent", database, key, NULL, &(char*[1]){});
+ execle("/bin/getent", "getent", database, key, NULL, &(char*[1]){});
_exit(EXIT_FAILURE);
}
diff --git a/src/resolve/test-resolved-stream.c b/src/resolve/test-resolved-stream.c
index c708eb4da8..ae851f67f0 100644
--- a/src/resolve/test-resolved-stream.c
+++ b/src/resolve/test-resolved-stream.c
@@ -147,16 +147,14 @@ static void *tls_dns_server(void *p) {
fd_tls = fd[1];
}
- r = safe_fork_full("(test-resolved-stream-tls-openssl)", (int[]) { fd_server, fd_tls }, 2,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_REOPEN_LOG, &openssl_pid);
+ r = safe_fork_full("(test-resolved-stream-tls-openssl)",
+ (int[]) { fd_tls, fd_tls, STDOUT_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_REOPEN_LOG,
+ &openssl_pid);
assert_se(r >= 0);
if (r == 0) {
/* Child */
- assert_se(dup2(fd_tls, STDIN_FILENO) >= 0);
- assert_se(dup2(fd_tls, STDOUT_FILENO) >= 0);
- close(TAKE_FD(fd_server));
- close(TAKE_FD(fd_tls));
-
execlp("openssl", "openssl", "s_server", "-accept", bind_str,
"-key", key_path, "-cert", cert_path,
"-quiet", "-naccept", "1", NULL);
diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c
index 9a4bac99a1..ce37dd31ce 100644
--- a/src/shared/dissect-image.c
+++ b/src/shared/dissect-image.c
@@ -1436,8 +1436,9 @@ static int run_fsck(int node_fd, const char *fstype) {
r = safe_fork_full(
"(fsck)",
+ NULL,
&node_fd, 1, /* Leave the node fd open */
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOEXEC_OFF,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF,
&pid);
if (r < 0)
return log_debug_errno(r, "Failed to fork off fsck: %m");
diff --git a/src/shared/elf-util.c b/src/shared/elf-util.c
index 8da16f528f..98c47d9125 100644
--- a/src/shared/elf-util.c
+++ b/src/shared/elf-util.c
@@ -784,6 +784,7 @@ int parse_elf_object(int fd, const char *executable, bool fork_disable_dump, cha
* system call or interacting with the system in any way, besides reading from
* the file descriptor and writing into these four pipes. */
r = safe_fork_full("(sd-parse-elf)",
+ NULL,
(int[]){ fd, error_pipe[1], return_pipe[1], json_pipe[1] },
4,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_WAIT|FORK_REOPEN_LOG,
diff --git a/src/shared/exec-util.c b/src/shared/exec-util.c
index 2e8f5b8562..40e9342cd5 100644
--- a/src/shared/exec-util.c
+++ b/src/shared/exec-util.c
@@ -487,6 +487,7 @@ int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret
/* Spawns a temporary TTY agent, making sure it goes away when we go away */
r = safe_fork_full(name,
+ NULL,
except,
n_except,
FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE,
diff --git a/src/shared/pager.c b/src/shared/pager.c
index 6ed35a3ca9..7bede85752 100644
--- a/src/shared/pager.c
+++ b/src/shared/pager.c
@@ -316,7 +316,7 @@ int show_man_page(const char *desc, bool null_stdio) {
} else
args[1] = desc;
- r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_NULL_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
+ r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c
index 61bd9d2601..bae4d9d023 100644
--- a/src/shutdown/umount.c
+++ b/src/shutdown/umount.c
@@ -618,7 +618,10 @@ static int remount_with_timeout(MountPoint *m, bool last_try) {
/* Due to the possibility of a remount operation hanging, we fork a child process and set a
* timeout. If the timeout lapses, the assumption is that the particular remount failed. */
- r = safe_fork_full("(sd-remount)", pfd, ELEMENTSOF(pfd), FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
+ r = safe_fork_full("(sd-remount)",
+ NULL,
+ pfd, ELEMENTSOF(pfd),
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
@@ -671,7 +674,10 @@ static int umount_with_timeout(MountPoint *m, bool last_try) {
/* Due to the possibility of a umount operation hanging, we fork a child process and set a
* timeout. If the timeout lapses, the assumption is that the particular umount failed. */
- r = safe_fork_full("(sd-umount)", pfd, ELEMENTSOF(pfd), FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
+ r = safe_fork_full("(sd-umount)",
+ NULL,
+ pfd, ELEMENTSOF(pfd),
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
diff --git a/src/socket-proxy/socket-proxyd.c b/src/socket-proxy/socket-proxyd.c
index 821049e667..f336fbd55e 100644
--- a/src/socket-proxy/socket-proxyd.c
+++ b/src/socket-proxy/socket-proxyd.c
@@ -15,6 +15,7 @@
#include "alloc-util.h"
#include "build.h"
+#include "daemon-util.h"
#include "errno-util.h"
#include "fd-util.h"
#include "log.h"
@@ -672,6 +673,7 @@ static int parse_argv(int argc, char *argv[]) {
static int run(int argc, char *argv[]) {
_cleanup_(context_clear) Context context = {};
+ _unused_ _cleanup_(notify_on_cleanup) const char *notify_stop = NULL;
int r, n, fd;
log_parse_environment();
@@ -709,6 +711,7 @@ static int run(int argc, char *argv[]) {
return r;
}
+ notify_stop = notify_start(NOTIFY_READY, NOTIFY_STOPPING);
r = sd_event_loop(context.event);
if (r < 0)
return log_error_errno(r, "Failed to run event loop: %m");
diff --git a/src/systemctl/systemctl-list-units.c b/src/systemctl/systemctl-list-units.c
index 6bfaf97236..86e7311d3c 100644
--- a/src/systemctl/systemctl-list-units.c
+++ b/src/systemctl/systemctl-list-units.c
@@ -6,6 +6,7 @@
#include "bus-locator.h"
#include "format-table.h"
#include "locale-util.h"
+#include "path-util.h"
#include "set.h"
#include "sort-util.h"
#include "systemctl-list-units.h"
@@ -101,6 +102,26 @@ static void output_legend(const char *type, size_t n_items) {
printf("Pass --all to see loaded but inactive %ss, too.\n", type);
}
+static int table_add_triggered(Table *table, char **triggered) {
+ assert(table);
+
+ if (strv_isempty(triggered))
+ return table_add_cell(table, NULL, TABLE_EMPTY, NULL);
+ else if (strv_length(triggered) == 1)
+ return table_add_cell(table, NULL, TABLE_STRING, triggered[0]);
+ else
+ /* This should never happen, currently our socket units can only trigger a
+ * single unit. But let's handle this anyway, who knows what the future
+ * brings? */
+ return table_add_cell(table, NULL, TABLE_STRV, triggered);
+}
+
+static char *format_unit_id(const char *unit, const char *machine) {
+ assert(unit);
+
+ return machine ? strjoin(machine, ":", unit) : strdup(unit);
+}
+
static int output_units_list(const UnitInfo *unit_infos, size_t c) {
_cleanup_(table_unrefp) Table *table = NULL;
size_t job_count = 0;
@@ -123,9 +144,8 @@ static int output_units_list(const UnitInfo *unit_infos, size_t c) {
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
for (const UnitInfo *u = unit_infos; unit_infos && (size_t) (u - unit_infos) < c; u++) {
- _cleanup_free_ char *j = NULL;
- const char *on_underline = "", *on_loaded = "", *on_active = "";
- const char *on_circle = "", *id;
+ _cleanup_free_ char *id = NULL;
+ const char *on_underline = "", *on_loaded = "", *on_active = "", *on_circle = "";
bool circle = false, underline = false;
if (u + 1 < unit_infos + c &&
@@ -148,14 +168,9 @@ static int output_units_list(const UnitInfo *unit_infos, size_t c) {
on_loaded = on_underline;
}
- if (u->machine) {
- j = strjoin(u->machine, ":", u->id);
- if (!j)
- return log_oom();
-
- id = j;
- } else
- id = u->id;
+ id = format_unit_id(u->id, u->machine);
+ if (!id)
+ return log_oom();
r = table_add_many(table,
TABLE_STRING, circle ? special_glyph(SPECIAL_GLYPH_BLACK_CIRCLE) : " ",
@@ -384,33 +399,20 @@ static int output_sockets_list(struct socket_info *socket_infos, size_t cs) {
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
for (struct socket_info *s = socket_infos; s < socket_infos + cs; s++) {
- _cleanup_free_ char *j = NULL;
- const char *path;
+ _cleanup_free_ char *unit = NULL;
- if (s->machine) {
- j = strjoin(s->machine, ":", s->path);
- if (!j)
- return log_oom();
- path = j;
- } else
- path = s->path;
+ unit = format_unit_id(s->id, s->machine);
+ if (!unit)
+ return log_oom();
r = table_add_many(table,
- TABLE_STRING, path,
+ TABLE_STRING, s->path,
TABLE_STRING, s->type,
- TABLE_STRING, s->id);
+ TABLE_STRING, unit);
if (r < 0)
return table_log_add_error(r);
- if (strv_isempty(s->triggered))
- r = table_add_cell(table, NULL, TABLE_EMPTY, NULL);
- else if (strv_length(s->triggered) == 1)
- r = table_add_cell(table, NULL, TABLE_STRING, s->triggered[0]);
- else
- /* This should never happen, currently our socket units can only trigger a
- * single unit. But let's handle this anyway, who knows what the future
- * brings? */
- r = table_add_cell(table, NULL, TABLE_STRV, s->triggered);
+ r = table_add_triggered(table, s->triggered);
if (r < 0)
return table_log_add_error(r);
}
@@ -615,19 +617,10 @@ static int output_timers_list(struct timer_info *timer_infos, size_t n) {
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
for (struct timer_info *t = timer_infos; t < timer_infos + n; t++) {
- _cleanup_free_ char *j = NULL, *activates = NULL;
- const char *unit;
-
- if (t->machine) {
- j = strjoin(t->machine, ":", t->id);
- if (!j)
- return log_oom();
- unit = j;
- } else
- unit = t->id;
+ _cleanup_free_ char *unit = NULL;
- activates = strv_join(t->triggered, ", ");
- if (!activates)
+ unit = format_unit_id(t->id, t->machine);
+ if (!unit)
return log_oom();
r = table_add_many(table,
@@ -635,8 +628,11 @@ static int output_timers_list(struct timer_info *timer_infos, size_t n) {
TABLE_TIMESTAMP_RELATIVE, t->next_elapse,
TABLE_TIMESTAMP, t->last_trigger,
TABLE_TIMESTAMP_RELATIVE, t->last_trigger,
- TABLE_STRING, unit,
- TABLE_STRING, activates);
+ TABLE_STRING, unit);
+ if (r < 0)
+ return table_log_add_error(r);
+
+ r = table_add_triggered(table, t->triggered);
if (r < 0)
return table_log_add_error(r);
}
@@ -847,16 +843,11 @@ static int output_automounts_list(struct automount_info *infos, size_t n_infos)
table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
for (struct automount_info *info = infos; info < infos + n_infos; info++) {
- _cleanup_free_ char *j = NULL;
- const char *unit;
+ _cleanup_free_ char *unit = NULL;
- if (info->machine) {
- j = strjoin(info->machine, ":", info->id);
- if (!j)
- return log_oom();
- unit = j;
- } else
- unit = info->id;
+ unit = format_unit_id(info->id, info->machine);
+ if (!unit)
+ return log_oom();
r = table_add_many(table,
TABLE_STRING, info->what,
@@ -932,3 +923,215 @@ int verb_list_automounts(int argc, char *argv[], void *userdata) {
return r;
}
+
+struct path_info {
+ const char *machine;
+ const char *id;
+
+ char *path;
+ char *condition;
+
+ /* Note: triggered is a list here, although it almost certainly will always be one
+ * unit. Nevertheless, dbus API allows for multiple values, so let's follow that. */
+ char** triggered;
+};
+
+struct path_infos {
+ size_t count;
+ struct path_info *items;
+};
+
+static int path_info_compare(const struct path_info *a, const struct path_info *b) {
+ int r;
+
+ assert(a);
+ assert(b);
+
+ r = strcasecmp_ptr(a->machine, b->machine);
+ if (r != 0)
+ return r;
+
+ r = path_compare(a->path, b->path);
+ if (r != 0)
+ return r;
+
+ r = strcmp(a->condition, b->condition);
+ if (r != 0)
+ return r;
+
+ return strcasecmp_ptr(a->id, b->id);
+}
+
+static void path_infos_done(struct path_infos *ps) {
+ assert(ps);
+ assert(ps->items || ps->count == 0);
+
+ for (struct path_info *p = ps->items; p < ps->items + ps->count; p++) {
+ free(p->condition);
+ free(p->path);
+ strv_free(p->triggered);
+ }
+
+ free(ps->items);
+}
+
+static int get_paths(sd_bus *bus, const char *unit_path, char ***ret_conditions, char ***ret_paths) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_strv_free_ char **conditions = NULL, **paths = NULL;
+ const char *condition, *path;
+ int r, n = 0;
+
+ assert(bus);
+ assert(unit_path);
+ assert(ret_conditions);
+ assert(ret_paths);
+
+ r = sd_bus_get_property(bus,
+ "org.freedesktop.systemd1",
+ unit_path,
+ "org.freedesktop.systemd1.Path",
+ "Paths",
+ &error,
+ &reply,
+ "a(ss)");
+ if (r < 0)
+ return log_error_errno(r, "Failed to get paths: %s", bus_error_message(&error, r));
+
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ss)");
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ while ((r = sd_bus_message_read(reply, "(ss)", &condition, &path)) > 0) {
+ if (strv_extend(&conditions, condition) < 0)
+ return log_oom();
+
+ if (strv_extend(&paths, path) < 0)
+ return log_oom();
+
+ n++;
+ }
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0)
+ return bus_log_parse_error(r);
+
+ *ret_conditions = TAKE_PTR(conditions);
+ *ret_paths = TAKE_PTR(paths);
+
+ return n;
+}
+
+static int output_paths_list(struct path_infos *ps) {
+ _cleanup_(table_unrefp) Table *table = NULL;
+ int r;
+
+ assert(ps);
+ assert(ps->items || ps->count == 0);
+
+ table = table_new("path", "condition", "unit", "activates");
+ if (!table)
+ return log_oom();
+
+ table_set_header(table, arg_legend != 0);
+ if (arg_full)
+ table_set_width(table, 0);
+
+ table_set_ersatz_string(table, TABLE_ERSATZ_DASH);
+
+ for (struct path_info *p = ps->items; p < ps->items + ps->count; p++) {
+ _cleanup_free_ char *unit = NULL;
+
+ unit = format_unit_id(p->id, p->machine);
+ if (!unit)
+ return log_oom();
+
+ r = table_add_many(table,
+ TABLE_STRING, p->path,
+ TABLE_STRING, p->condition,
+ TABLE_STRING, unit);
+ if (r < 0)
+ return table_log_add_error(r);
+
+ r = table_add_triggered(table, p->triggered);
+ if (r < 0)
+ return table_log_add_error(r);
+ }
+
+ r = output_table(table);
+ if (r < 0)
+ return r;
+
+ if (arg_legend != 0)
+ output_legend("path", ps->count);
+
+ return 0;
+}
+
+int verb_list_paths(int argc, char *argv[], void *userdata) {
+ _cleanup_(message_set_freep) Set *replies = NULL;
+ _cleanup_strv_free_ char **machines = NULL, **units = NULL;
+ _cleanup_free_ UnitInfo *unit_infos = NULL;
+ _cleanup_(path_infos_done) struct path_infos path_infos = {};
+ int r, n;
+ sd_bus *bus;
+
+ r = acquire_bus(BUS_MANAGER, &bus);
+ if (r < 0)
+ return r;
+
+ pager_open(arg_pager_flags);
+
+ r = expand_unit_names(bus, strv_skip(argv, 1), ".path", &units, NULL);
+ if (r < 0)
+ return r;
+
+ if (argc == 1 || units) {
+ n = get_unit_list_recursive(bus, units, &unit_infos, &replies, &machines);
+ if (n < 0)
+ return n;
+
+ for (const UnitInfo *u = unit_infos; u < unit_infos + n; u++) {
+ _cleanup_strv_free_ char **conditions = NULL, **paths = NULL, **triggered = NULL;
+ int c;
+
+ if (!endswith(u->id, ".path"))
+ continue;
+
+ r = get_triggered_units(bus, u->unit_path, &triggered);
+ if (r < 0)
+ return r;
+
+ c = get_paths(bus, u->unit_path, &conditions, &paths);
+ if (c < 0)
+ return c;
+
+ if (!GREEDY_REALLOC(path_infos.items, path_infos.count + c))
+ return log_oom();
+
+ for (int i = c - 1; i >= 0; i--) {
+ char **t;
+
+ t = strv_copy(triggered);
+ if (!t)
+ return log_oom();
+
+ path_infos.items[path_infos.count++] = (struct path_info) {
+ .machine = u->machine,
+ .id = u->id,
+ .condition = TAKE_PTR(conditions[i]),
+ .path = TAKE_PTR(paths[i]),
+ .triggered = t,
+ };
+ }
+ }
+
+ typesafe_qsort(path_infos.items, path_infos.count, path_info_compare);
+ }
+
+ output_paths_list(&path_infos);
+
+ return 0;
+}
diff --git a/src/systemctl/systemctl-list-units.h b/src/systemctl/systemctl-list-units.h
index 117b7e378a..f7353d037e 100644
--- a/src/systemctl/systemctl-list-units.h
+++ b/src/systemctl/systemctl-list-units.h
@@ -5,5 +5,6 @@ int verb_list_units(int argc, char *argv[], void *userdata);
int verb_list_sockets(int argc, char *argv[], void *userdata);
int verb_list_timers(int argc, char *argv[], void *userdata);
int verb_list_automounts(int argc, char *argv[], void *userdata);
+int verb_list_paths(int argc, char *argv[], void *userdata);
usec_t calc_next_elapse(dual_timestamp *nw, dual_timestamp *next);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index a752c6dce4..0155036572 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -152,6 +152,8 @@ static int systemctl_help(void) {
" list-units [PATTERN...] List units currently in memory\n"
" list-automounts [PATTERN...] List automount units currently in memory,\n"
" ordered by path\n"
+ " list-paths [PATTERN...] List path units currently in memory,\n"
+ " ordered by path\n"
" list-sockets [PATTERN...] List socket units currently in memory,\n"
" ordered by address\n"
" list-timers [PATTERN...] List timer units currently in memory,\n"
@@ -1091,6 +1093,7 @@ static int systemctl_main(int argc, char *argv[]) {
{ "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_ONLINE_ONLY, verb_list_units },
{ "list-unit-files", VERB_ANY, VERB_ANY, 0, verb_list_unit_files },
{ "list-automounts", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_automounts },
+ { "list-paths", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_paths },
{ "list-sockets", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_sockets },
{ "list-timers", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_timers },
{ "list-jobs", VERB_ANY, VERB_ANY, VERB_ONLINE_ONLY, verb_list_jobs },
diff --git a/src/sysupdate/sysupdate-resource.c b/src/sysupdate/sysupdate-resource.c
index e1e260addc..6c05d245f8 100644
--- a/src/sysupdate/sysupdate-resource.c
+++ b/src/sysupdate/sysupdate-resource.c
@@ -264,7 +264,11 @@ static int download_manifest(
log_info("%s Acquiring manifest file %s%s", special_glyph(SPECIAL_GLYPH_DOWNLOAD),
suffixed_url, special_glyph(SPECIAL_GLYPH_ELLIPSIS));
- r = safe_fork("(sd-pull)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork_full("(sd-pull)",
+ (int[]) { -EBADF, pfd[1], STDERR_FILENO },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG,
+ &pid);
if (r < 0)
return r;
if (r == 0) {
@@ -280,14 +284,6 @@ static int download_manifest(
NULL
};
- pfd[0] = safe_close(pfd[0]);
-
- r = rearrange_stdio(-EBADF, pfd[1], STDERR_FILENO);
- if (r < 0) {
- log_error_errno(r, "Failed to rearrange stdin/stdout: %m");
- _exit(EXIT_FAILURE);
- }
-
(void) unsetenv("NOTIFY_SOCKET");
execv(pull_binary_path(), (char *const*) cmdline);
log_error_errno(errno, "Failed to execute %s tool: %m", pull_binary_path());
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index f6d05afc1b..7363ea95db 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -583,14 +583,12 @@ static int find_libraries(const char *exec, char ***ret) {
assert_se(pipe2(outpipe, O_NONBLOCK|O_CLOEXEC) == 0);
assert_se(pipe2(errpipe, O_NONBLOCK|O_CLOEXEC) == 0);
- r = safe_fork("(spawn-ldd)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+ r = safe_fork_full("(spawn-ldd)",
+ (int[]) { -EBADF, outpipe[1], errpipe[1] },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
- if (rearrange_stdio(-EBADF, TAKE_FD(outpipe[1]), TAKE_FD(errpipe[1])) < 0)
- _exit(EXIT_FAILURE);
-
- (void) close_all_fds(NULL, 0);
-
execlp("ldd", "ldd", exec, NULL);
_exit(EXIT_FAILURE);
}
diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c
index 9c24ca8204..9a0c15dffe 100644
--- a/src/test/test-process-util.c
+++ b/src/test/test-process-util.c
@@ -589,7 +589,7 @@ TEST(safe_fork) {
BLOCK_SIGNALS(SIGCHLD);
- r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NULL_STDIO|FORK_REOPEN_LOG, &pid);
+ r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c
index ec4ad30824..a8d7db40b4 100644
--- a/src/udev/udev-event.c
+++ b/src/udev/udev-event.c
@@ -810,18 +810,16 @@ int udev_event_spawn(
log_device_debug(event->dev, "Starting '%s'", cmd);
- r = safe_fork("(spawn)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
+ r = safe_fork_full("(spawn)",
+ (int[]) { -EBADF, outpipe[WRITE_END], errpipe[WRITE_END] },
+ NULL, 0,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
+ &pid);
if (r < 0)
return log_device_error_errno(event->dev, r,
"Failed to fork() to execute command '%s': %m", cmd);
if (r == 0) {
- if (rearrange_stdio(-EBADF, TAKE_FD(outpipe[WRITE_END]), TAKE_FD(errpipe[WRITE_END])) < 0)
- _exit(EXIT_FAILURE);
-
- (void) close_all_fds(NULL, 0);
-
DEVICE_TRACE_POINT(spawn_exec, event->dev, cmd);
-
execve(argv[0], argv, envp);
_exit(EXIT_FAILURE);
}
diff --git a/test/units/testsuite-26.sh b/test/units/testsuite-26.sh
index 2d438e2748..8ff96a1d97 100755
--- a/test/units/testsuite-26.sh
+++ b/test/units/testsuite-26.sh
@@ -61,6 +61,9 @@ printf '%b' '[Service]\n' 'ExecStart=\n' 'ExecStart=sleep 10d' >"+4"
EDITOR='mv' script -ec 'systemctl edit "$UNIT_NAME"' /dev/null
printf '%s\n' '[Service]' 'ExecStart=' 'ExecStart=sleep 10d' | cmp - "/etc/systemd/system/$UNIT_NAME.d/override.conf"
+# Double free when editing a template unit (#26483)
+EDITOR='true' script -ec 'systemctl edit user@0' /dev/null
+
# Argument help
systemctl --state help
systemctl --signal help
@@ -102,6 +105,8 @@ systemctl list-jobs "*"
systemctl list-dependencies sysinit.target --type=socket,mount
systemctl list-dependencies multi-user.target --state=active
systemctl list-dependencies sysinit.target --state=mounted --all
+systemctl list-paths
+systemctl list-paths --legend=no -a "systemd*"
# is-* verbs
# Should return 4 for a missing unit file
@@ -427,5 +432,17 @@ EOF
systemctl stop issue-24990
fi
+# %J in WantedBy= causes ABRT (#26467)
+cat >/run/systemd/system/test-WantedBy.service <<EOF
+[Service]
+ExecStart=true
+
+[Install]
+WantedBy=user-%i@%J.service
+EOF
+systemctl daemon-reload
+systemctl enable --now test-WantedBy.service || :
+systemctl daemon-reload
+
touch /testok
rm /failed
diff --git a/test/units/testsuite-70.sh b/test/units/testsuite-70.sh
index 3499d6160f..a8d3d2422b 100755
--- a/test/units/testsuite-70.sh
+++ b/test/units/testsuite-70.sh
@@ -211,7 +211,10 @@ fi
# Ensure that sandboxing doesn't stop creds from being accessible
echo "test" > /tmp/testdata
systemd-creds encrypt /tmp/testdata /tmp/testdata.encrypted --with-key=tpm2
+# LoadCredentialEncrypted
systemd-run -p PrivateDevices=yes -p LoadCredentialEncrypted=testdata.encrypted:/tmp/testdata.encrypted --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata
+# SetCredentialEncrypted
+systemd-run -p PrivateDevices=yes -p SetCredentialEncrypted=testdata.encrypted:"$(cat /tmp/testdata.encrypted)" --pipe --wait systemd-creds cat testdata.encrypted | cmp - /tmp/testdata
rm /tmp/testdata
echo OK >/testok