diff options
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> @@ -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 |