Merge pull request #29748 from poettering/tgtmode

Storage target mode, inspired by "target disk mode" á la MacOS, but with NVMe-TCP
This commit is contained in:
Luca Boccassi
2023-11-02 17:26:05 +00:00
committed by GitHub
94 changed files with 1604 additions and 201 deletions
+9
View File
@@ -379,6 +379,15 @@ CHANGES WITH 255 in spe:
* Options and verbs in man pages are now tagged with the version they
were first introduced in.
* A new component "systemd-storagetm" has been added, which exposes all
local block devices as NVMe-TCP devices, fully automatically. It's
hooked into a new target unit storage-target-mode.target that is
suppsoed to be booted into via
rd.systemd.unit=storage-target-mode.target on the kernel command
line. This is intended to be used for installers and debugging to
quickly get access to the local disk. It's inspired by MacOS "target
disk mode".
Contributions from: 김인수, Abderrahim Kitouni, Adam Williamson,
Alexandre Peixoto Ferreira, Alex Hudspith, Alvin Alvarado,
André Paiusco, Antonio Alvarez Feijoo, Anton Lundin,
+11 -11
View File
@@ -175,18 +175,18 @@ Features:
* systemd-repart: add support for formatting dm-crypt + dm-integrity file
systems.
* homed: add small tool that exposes a homed home dir via nvme-over-tcp (just a
bunch of sysfs writes). Then, teach homed/pam_systemd_homed with a user name
such as lennart%nvmettcp_192.168.100.77_8787_nqn to log in from any linux
host with the same home dir. Similar maybe for nbd, iscsi? this should then
first ask for the local root pw, to authenticate that logging in like this is
ok, and would then be followed by another password prompt asking for the
user's own password. Also, do something similar for CIFS: if you log in via
* homed: use systemd-storagetm to expose home dirs via nvme-tcp. Then,
teach homed/pam_systemd_homed with a user name such as
lennart%nvme_tcp_192.168.100.77_8787 to log in from any linux host with the
same home dir. Similar maybe for nbd, iscsi? this should then first ask for
the local root pw, to authenticate that logging in like this is ok, and would
then be followed by another password prompt asking for the user's own
password. Also, do something similar for CIFS: if you log in via
lennart%cifs-someserver_someshare, then set up the homed dir for it
automatically. The PAM module should update the user name used for login to the
short version once it set up the user. Some care should be taken, so that the
long version can be still be resolved via NSS afterwards, to deal with PAM
clients that do not support PAM sessions where PAM_USER changes half-way.
automatically. The PAM module should update the user name used for login to
the short version once it set up the user. Some care should be taken, so that
the long version can be still be resolved via NSS afterwards, to deal with
PAM clients that do not support PAM sessions where PAM_USER changes half-way.
* redefine /var/lib/extensions/ as the dir one can place all three of sysext,
confext as well is multi-modal DDIs that qualify as both. Then introduce
+1
View File
@@ -1045,6 +1045,7 @@ manpages = [
['systemd-socket-proxyd', '8', [], ''],
['systemd-soft-reboot.service', '8', [], ''],
['systemd-stdio-bridge', '1', [], ''],
['systemd-storagetm.service', '8', ['systemd-storagetm'], 'ENABLE_STORAGETM'],
['systemd-stub',
'7',
['linuxaa64.efi.stub', 'linuxia32.efi.stub', 'linuxx64.efi.stub', 'sd-stub'],
+104
View File
@@ -0,0 +1,104 @@
<?xml version="1.0"?>
<!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1-or-later -->
<refentry id="systemd-storagetm.service" conditional='ENABLE_STORAGETM'
xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>systemd-storagetm.service</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>systemd-storagetm.service</refentrytitle>
<manvolnum>8</manvolnum>
</refmeta>
<refnamediv>
<refname>systemd-storagetm.service</refname>
<refname>systemd-storagetm</refname>
<refpurpose>Exposes all local block devices as NVMe-TCP mass storage devices</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>systemd-storagetm.service</filename></para>
<cmdsynopsis>
<command>/usr/lib/systemd/systemd-storagetm</command>
<arg choice="opt" rep="repeat">OPTIONS</arg>
<arg choice="opt"><replaceable>DEVICE</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><filename>systemd-storagetm.service</filename> is a service that exposes all local block devices as
NVMe-TCP mass storage devices. Its primary use-case is to be invoked by the
<filename>storage-target-mode.target</filename> unit that can be booted into.</para>
<para>Warning: the NVMe disks are currently exposed without authentication or encryption, in read/write
mode. This means network peers may read from and write to the device without any restrictions. This
functionality should hence only be used in a local setup.</para>
<para>Note that to function properly networking must be configured too. The recommended mechanism to boot
into a storage target mode is by adding <literal>rd.systemd.unit=storage-target-mode.target
ip=link-local</literal> on the kernel command line. Note that <literal>ip=link-local</literal> only
configures link-local IP, i.e. IPv4LL and IPv6LL, which means non-routable addresses. This is done for
security reasons, so that only systems on the local link can access the devices. Use
<literal>ip=dhcp</literal> to assign routable addresses too. For further details see
<citerefentry><refentrytitle>systemd-network-generator.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<para>Unless the <option>--all</option> switch is used expects one or more block devices or regular files to expose
via NVMe-TCP as argument.</para>
</refsect1>
<refsect1>
<title>Options</title>
<para>The following options are understood:</para>
<variablelist>
<varlistentry>
<term><option>--nqn=</option></term>
<listitem><para>Takes a string. If specified configures the NVMe Qualified Name to use for the
exposed NVMe-TCP mass storage devices. The NQN should follow the syntax described in <ulink
url="https://nvmexpress.org/wp-content/uploads/NVM-Express-Base-Specification-2.0c-2022.10.04-Ratified.pdf">NVM
Express Base Specification 2.0c</ulink>, section 4.5 "NVMe Qualified Names". Note that the NQN
specified here will be suffixed with a dot and the the block device name before it is exposed on the
NVMe target. If not specified defaults to
<literal>nqn.2023-10.io.systemd:storagetm.<replaceable>ID</replaceable></literal>, where ID is
replaced by a 128bit ID derived from
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--all</option></term>
<term><option>-a</option></term>
<listitem><para>If specified exposes all local block devices via NVMe-TCP, current and future
(i.e. it watches block devices come and go and updates the NVMe-TCP list as needed). Note that by
default any block devices that originate on the same block device as the block device backing the
current root file system are excluded. If the switch is specified twice this safety mechanism is
disabled.</para>
<xi:include href="version-info.xml" xpointer="v255"/></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="help" />
<xi:include href="standard-options.xml" xpointer="version" />
</variablelist>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd.special</refentrytitle><manvolnum>7</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>
+13
View File
@@ -83,6 +83,7 @@
<filename>sockets.target</filename>,
<filename>soft-reboot.target</filename>,
<filename>sound.target</filename>,
<filename>storage-target-mode.target</filename>,
<filename>suspend.target</filename>,
<filename>swap.target</filename>,
<filename>sysinit.target</filename>,
@@ -767,6 +768,18 @@
<xi:include href="version-info.xml" xpointer="v254"/>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>storage-target-mode.target</filename></term>
<listitem>
<para>A special target unit that can be booted into that selects the "Storage Target Mode" for
the OS. In this mode all local storage disks are exposed to external systems as block
devices. This invokes
<citerefentry><refentrytitle>systemd-storagetm.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
which exposes all local disks as NVMe-TCP devices for access over the network. It might as well
invoke other services too that make local disks available via other mechanisms.</para>
<xi:include href="version-info.xml" xpointer="v255"/>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>suspend.target</filename></term>
<listitem>
+5 -1
View File
@@ -1533,6 +1533,8 @@ have = get_option('sysupdate').require(
error_message : 'fdisk and openssl required').allowed()
conf.set10('ENABLE_SYSUPDATE', have)
conf.set10('ENABLE_STORAGETM', get_option('storagetm'))
have = get_option('importd').require(
conf.get('HAVE_LIBCURL') == 1 and
conf.get('HAVE_OPENSSL_OR_GCRYPT') == 1 and
@@ -2196,10 +2198,11 @@ subdir('src/systemctl')
subdir('src/sysupdate')
subdir('src/sysusers')
subdir('src/sysv-generator')
subdir('src/storagetm')
subdir('src/timedate')
subdir('src/timesync')
subdir('src/tpm2-setup')
subdir('src/tmpfiles')
subdir('src/tpm2-setup')
subdir('src/tty-ask-password-agent')
subdir('src/update-done')
subdir('src/update-utmp')
@@ -2793,6 +2796,7 @@ foreach tuple : [
['systemd-analyze', conf.get('ENABLE_ANALYZE') == 1],
['sysupdate'],
['sysusers'],
['storagetm'],
['timedated'],
['timesyncd'],
['tmpfiles'],
+2
View File
@@ -158,6 +158,8 @@ option('quotacheck', type : 'boolean',
description : 'support for the quotacheck tools')
option('sysusers', type : 'boolean',
description : 'support for the sysusers configuration')
option('storagetm', type : 'boolean',
description : 'support for Storage Target Mode')
option('tmpfiles', type : 'boolean',
description : 'support for tmpfiles.d')
option('importd', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
+8
View File
@@ -988,3 +988,11 @@ const char *accmode_to_string(int flags) {
return NULL;
}
}
char *format_proc_pid_fd_path(char buf[static PROC_PID_FD_PATH_MAX], pid_t pid, int fd) {
assert(buf);
assert(fd >= 0);
assert(pid >= 0);
assert_se(snprintf_ok(buf, PROC_PID_FD_PATH_MAX, "/proc/" PID_FMT "/fd/%i", pid == 0 ? getpid_cached() : pid, fd));
return buf;
}
+10
View File
@@ -131,6 +131,16 @@ static inline char *format_proc_fd_path(char buf[static PROC_FD_PATH_MAX], int f
#define FORMAT_PROC_FD_PATH(fd) \
format_proc_fd_path((char[PROC_FD_PATH_MAX]) {}, (fd))
/* The maximum length a buffer for a /proc/<pid>/fd/<fd> path needs */
#define PROC_PID_FD_PATH_MAX \
(STRLEN("/proc//fd/") + DECIMAL_STR_MAX(pid_t) + DECIMAL_STR_MAX(int))
char *format_proc_pid_fd_path(char buf[static PROC_PID_FD_PATH_MAX], pid_t pid, int fd);
/* Kinda the same as FORMAT_PROC_FD_PATH(), but goes by PID rather than "self" symlink */
#define FORMAT_PROC_PID_FD_PATH(pid, fd) \
format_proc_pid_fd_path((char[PROC_PID_FD_PATH_MAX]) {}, (pid), (fd))
const char *accmode_to_string(int flags);
/* Like ASSERT_PTR, but for fds */
+2
View File
@@ -134,6 +134,8 @@ const char *special_glyph_full(SpecialGlyph code, bool force_utf) {
[SPECIAL_GLYPH_SPARKLES] = u8"✨",
[SPECIAL_GLYPH_LOW_BATTERY] = u8"🪫",
[SPECIAL_GLYPH_WARNING_SIGN] = u8"⚠️",
[SPECIAL_GLYPH_COMPUTER_DISK] = u8"💽",
[SPECIAL_GLYPH_WORLD] = u8"🌍",
},
};
+2
View File
@@ -47,6 +47,8 @@ typedef enum SpecialGlyph {
SPECIAL_GLYPH_SPARKLES,
SPECIAL_GLYPH_LOW_BATTERY,
SPECIAL_GLYPH_WARNING_SIGN,
SPECIAL_GLYPH_COMPUTER_DISK,
SPECIAL_GLYPH_WORLD,
_SPECIAL_GLYPH_MAX,
_SPECIAL_GLYPH_INVALID = -EINVAL,
} SpecialGlyph;
+89
View File
@@ -2,10 +2,12 @@
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "alloc-util.h"
#include "fd-util.h"
@@ -14,6 +16,7 @@
#include "macro.h"
#include "missing_fcntl.h"
#include "path-util.h"
#include "process-util.h"
int make_lock_file_at(int dir_fd, const char *p, int operation, LockFile *ret) {
_cleanup_close_ int fd = -EBADF, dfd = -EBADF;
@@ -186,3 +189,89 @@ int lock_generic(int fd, LockType type, int operation) {
assert_not_reached();
}
}
int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeout) {
_cleanup_(sigkill_waitp) pid_t pid = 0;
int r;
assert(fd >= 0);
/* A version of lock_generic(), but with a time-out. We do this in a child process, since the kernel
* APIs natively don't support a timeout. We set a SIGALRM timer that will kill the child after the
* timeout is hit. Returns -ETIMEDOUT if the time-out is hit, and 0 on success.
*
* This only works for BSD and UNPOSIX locks, as only those are fd-bound, and hence can be acquired
* from any process that has access to the fd. POSIX locks OTOH are process-bound, and hence if we'd
* acquire them in a child process they'd remain unlocked in the parent. */
if (type == LOCK_NONE)
return 0;
if (!IN_SET(type, LOCK_BSD, LOCK_UNPOSIX)) /* Not for POSIX locks, see above. */
return -EOPNOTSUPP;
/* First, try without forking anything off */
r = lock_generic(fd, type, operation | (timeout == USEC_INFINITY ? 0 : LOCK_NB));
if (r != -EAGAIN || timeout == 0 || FLAGS_SET(operation, LOCK_NB))
return r;
/* If that didn't work, try with a child */
r = safe_fork("(sd-flock)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid);
if (r < 0)
return log_error_errno(r, "Failed to flock block device in child process: %m");
if (r == 0) {
struct sigevent sev = {
.sigev_notify = SIGEV_SIGNAL,
.sigev_signo = SIGALRM,
};
timer_t id = 0;
if (timer_create(CLOCK_MONOTONIC, &sev, &id) < 0) {
log_error_errno(errno, "Failed to allocate CLOCK_MONOTONIC timer: %m");
_exit(EXIT_FAILURE);
}
struct itimerspec its = {};
timespec_store(&its.it_value, timeout);
if (timer_settime(id, /* flags= */ 0, &its, NULL) < 0) {
log_error_errno(errno, "Failed to start CLOCK_MONOTONIC timer: %m");
_exit(EXIT_FAILURE);
}
if (lock_generic(fd, type, operation) < 0) {
log_error_errno(errno, "Unable to get an exclusive lock on the device: %m");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
siginfo_t status;
r = wait_for_terminate(pid, &status);
if (r < 0)
return r;
TAKE_PID(pid);
switch (status.si_code) {
case CLD_EXITED:
if (status.si_status != EXIT_SUCCESS)
return -EPROTO;
return 0;
case CLD_KILLED:
if (status.si_status == SIGALRM)
return -ETIMEDOUT;
_fallthrough_;
case CLD_DUMPED:
return -EPROTO;
default:
assert_not_reached();
}
}
+2
View File
@@ -41,3 +41,5 @@ typedef enum LockType {
} LockType;
int lock_generic(int fd, LockType type, int operation);
int lock_generic_with_timeout(int fd, LockType type, int operation, usec_t timeout);
+1
View File
@@ -273,6 +273,7 @@ libbasic = static_library(
include_directories : basic_includes,
dependencies : [libcap,
libm,
librt,
threads,
userspace],
c_args : ['-fvisibility=default'],
+1 -1
View File
@@ -219,7 +219,7 @@ int userns_acquire(const char *uid_map, const char *gid_map) {
* and then kills the process again. This way we have a userns fd that is not bound to any
* process. We can use that for file system mounts and similar. */
r = safe_fork("(sd-mkuserns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_NEW_USERNS, &pid);
r = safe_fork("(sd-mkuserns)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_NEW_USERNS, &pid);
if (r < 0)
return r;
if (r == 0)
+17 -9
View File
@@ -1380,6 +1380,12 @@ pid_t clone_with_nested_stack(int (*fn)(void *), int flags, void *userdata) {
return pid;
}
static int fork_flags_to_signal(ForkFlags flags) {
return (flags & FORK_DEATHSIG_SIGTERM) ? SIGTERM :
(flags & FORK_DEATHSIG_SIGINT) ? SIGINT :
SIGKILL;
}
int safe_fork_full(
const char *name,
const int stdio_fds[3],
@@ -1409,9 +1415,10 @@ int safe_fork_full(
fflush(stderr); /* This one shouldn't be necessary, stderr should be unbuffered anyway, but let's better be safe than sorry */
}
if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG)) {
/* We temporarily block all signals, so that the new child has them blocked initially. This way, we can
* be sure that SIGTERMs are not lost we might send to the child. */
if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT)) {
/* We temporarily block all signals, so that the new child has them blocked initially. This
* way, we can be sure that SIGTERMs are not lost we might send to the child. (Note that for
* FORK_DEATHSIG_SIGKILL we don't bother, since it cannot be blocked anyway.) */
assert_se(sigfillset(&ss) >= 0);
block_signals = block_all = true;
@@ -1512,8 +1519,8 @@ int safe_fork_full(
r, "Failed to rename process, ignoring: %m");
}
if (flags & (FORK_DEATHSIG|FORK_DEATHSIG_SIGINT))
if (prctl(PR_SET_PDEATHSIG, (flags & FORK_DEATHSIG_SIGINT) ? SIGINT : SIGTERM) < 0) {
if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGKILL))
if (prctl(PR_SET_PDEATHSIG, fork_flags_to_signal(flags)) < 0) {
log_full_errno(prio, errno, "Failed to set death signal: %m");
_exit(EXIT_FAILURE);
}
@@ -1538,7 +1545,7 @@ int safe_fork_full(
}
}
if (flags & FORK_DEATHSIG) {
if (flags & (FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGKILL|FORK_DEATHSIG_SIGINT)) {
pid_t ppid;
/* Let's see if the parent PID is still the one we started from? If not, then the parent
* already died by the time we set PR_SET_PDEATHSIG, hence let's emulate the effect */
@@ -1547,8 +1554,9 @@ int safe_fork_full(
if (ppid == 0)
/* Parent is in a different PID namespace. */;
else if (ppid != original_pid) {
log_debug("Parent died early, raising SIGTERM.");
(void) raise(SIGTERM);
int sig = fork_flags_to_signal(flags);
log_debug("Parent died early, raising %s.", signal_to_string(sig));
(void) raise(sig);
_exit(EXIT_FAILURE);
}
}
@@ -1664,7 +1672,7 @@ int namespace_fork(
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);
(flags|FORK_DEATHSIG_SIGINT|FORK_DEATHSIG_SIGTERM|FORK_DEATHSIG_SIGKILL) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
if (r < 0)
return r;
if (r == 0) {
+16 -15
View File
@@ -160,22 +160,23 @@ pid_t clone_with_nested_stack(int (*fn)(void *), int flags, void *userdata);
typedef enum ForkFlags {
FORK_RESET_SIGNALS = 1 << 0, /* Reset all signal handlers and signal mask */
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_SIGTERM = 1 << 2, /* Set PR_DEATHSIG in the child to SIGTERM */
FORK_DEATHSIG_SIGINT = 1 << 3, /* Set PR_DEATHSIG in the child to SIGINT */
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 */
FORK_NEW_MOUNTNS = 1 << 8, /* Run child in its own mount namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */
FORK_MOUNTNS_SLAVE = 1 << 9, /* Make child's mount namespace MS_SLAVE */
FORK_PRIVATE_TMP = 1 << 10, /* Mount new /tmp/ in the child (combine with FORK_NEW_MOUNTNS!) */
FORK_RLIMIT_NOFILE_SAFE = 1 << 11, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */
FORK_STDOUT_TO_STDERR = 1 << 12, /* Make stdout a copy of stderr */
FORK_FLUSH_STDIO = 1 << 13, /* fflush() stdout (and stderr) before forking */
FORK_NEW_USERNS = 1 << 14, /* Run child in its own user namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */
FORK_CLOEXEC_OFF = 1 << 15, /* In the child: turn off O_CLOEXEC on all fds in except_fds[] */
FORK_KEEP_NOTIFY_SOCKET = 1 << 16, /* Unless this specified, $NOTIFY_SOCKET will be unset. */
FORK_DETACH = 1 << 17, /* Double fork if needed to ensure PID1/subreaper is parent */
FORK_DEATHSIG_SIGKILL = 1 << 4, /* Set PR_DEATHSIG in the child to SIGKILL */
FORK_REARRANGE_STDIO = 1 << 5, /* Connect 0,1,2 to specified fds or /dev/null */
FORK_REOPEN_LOG = 1 << 6, /* Reopen log connection */
FORK_LOG = 1 << 7, /* Log above LOG_DEBUG log level about failures */
FORK_WAIT = 1 << 8, /* Wait until child exited */
FORK_NEW_MOUNTNS = 1 << 9, /* Run child in its own mount namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */
FORK_MOUNTNS_SLAVE = 1 << 10, /* Make child's mount namespace MS_SLAVE */
FORK_PRIVATE_TMP = 1 << 11, /* Mount new /tmp/ in the child (combine with FORK_NEW_MOUNTNS!) */
FORK_RLIMIT_NOFILE_SAFE = 1 << 12, /* Set RLIMIT_NOFILE soft limit to 1K for select() compat */
FORK_STDOUT_TO_STDERR = 1 << 13, /* Make stdout a copy of stderr */
FORK_FLUSH_STDIO = 1 << 14, /* fflush() stdout (and stderr) before forking */
FORK_NEW_USERNS = 1 << 15, /* Run child in its own user namespace 💣 DO NOT USE IN THREADED PROGRAMS! 💣 */
FORK_CLOEXEC_OFF = 1 << 16, /* In the child: turn off O_CLOEXEC on all fds in except_fds[] */
FORK_KEEP_NOTIFY_SOCKET = 1 << 17, /* Unless this specified, $NOTIFY_SOCKET will be unset. */
FORK_DETACH = 1 << 18, /* Double fork if needed to ensure PID1/subreaper is parent */
} ForkFlags;
int safe_fork_full(
+2 -2
View File
@@ -1204,7 +1204,7 @@ int openpt_allocate_in_namespace(pid_t pid, int flags, char **ret_slave) {
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
return -errno;
r = namespace_fork("(sd-openptns)", "(sd-openpt)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
r = namespace_fork("(sd-openptns)", "(sd-openpt)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
if (r < 0)
return r;
@@ -1255,7 +1255,7 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
return -errno;
r = namespace_fork("(sd-terminalns)", "(sd-terminal)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
r = namespace_fork("(sd-terminalns)", "(sd-terminal)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
if (r < 0)
return r;
+1 -1
View File
@@ -1044,7 +1044,7 @@ int parse_timestamp(const char *t, usec_t *ret) {
if (shared == MAP_FAILED)
return negative_errno();
r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL);
r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_WAIT, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
+1 -1
View File
@@ -930,7 +930,7 @@ int exec_setup_credentials(
if (r < 0 && r != -EEXIST)
return r;
r = safe_fork("(sd-mkdcreds)", FORK_DEATHSIG|FORK_WAIT|FORK_NEW_MOUNTNS, NULL);
r = safe_fork("(sd-mkdcreds)", FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_NEW_MOUNTNS, NULL);
if (r < 0) {
_cleanup_(rmdir_and_freep) char *u = NULL; /* remove the temporary workspace if we can */
_cleanup_free_ char *t = NULL;
+1 -1
View File
@@ -2136,7 +2136,7 @@ static int setup_private_users(uid_t ouid, gid_t ogid, uid_t uid, gid_t gid) {
if (pipe2(errno_pipe, O_CLOEXEC) < 0)
return -errno;
r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(sd-userns)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -5426,7 +5426,7 @@ int unit_fork_helper_process(Unit *u, const char *name, PidRef *ret) {
(void) unit_realize_cgroup(u);
r = safe_fork(name, FORK_REOPEN_LOG|FORK_DEATHSIG, &pid);
r = safe_fork(name, FORK_REOPEN_LOG|FORK_DEATHSIG_SIGTERM, &pid);
if (r < 0)
return r;
if (r > 0) {
+1 -1
View File
@@ -1443,7 +1443,7 @@ static int forward_coredump_to_container(Context *context) {
return log_debug_errno(r, "Failed to join namespaces of PID " PID_FMT ": %m", pid);
r = namespace_fork("(sd-coredumpns)", "(sd-coredump)", NULL, 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM,
pidnsfd, mntnsfd, netnsfd, usernsfd, rootfd, &child);
if (r < 0)
return log_debug_errno(r, "Failed to fork into namespaces of PID " PID_FMT ": %m", pid);
+1 -1
View File
@@ -1253,7 +1253,7 @@ static int run_debug(int argc, char **argv, void *userdata) {
fork_name = strjoina("(", debugger_call[0], ")");
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO, &pid);
r = safe_fork(fork_name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_FLUSH_STDIO, &pid);
if (r < 0)
goto finish;
if (r == 0) {
+1 -1
View File
@@ -168,7 +168,7 @@ static int found_override(const char *top, const char *bottom) {
fflush(stdout);
r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
r = safe_fork("(diff)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -339,7 +339,7 @@ static int run(int argc, char *argv[]) {
pipe(progress_pipe) < 0)
return log_error_errno(errno, "pipe(): %m");
r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
r = safe_fork("(fsck)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -2025,7 +2025,7 @@ static int with_home(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
r = safe_fork("(with)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REOPEN_LOG, &pid);
r = safe_fork("(with)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE|FORK_REOPEN_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
+2 -2
View File
@@ -1184,7 +1184,7 @@ static int home_start_work(Home *h, const char *verb, UserRecord *hr, UserRecord
r = safe_fork_full("(sd-homework)",
(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);
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_REOPEN_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
@@ -2080,7 +2080,7 @@ int home_killall(Home *h) {
/* Let's kill everything matching the specified UID */
r = safe_fork("(sd-killer)",
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT|FORK_LOG|FORK_REOPEN_LOG,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_WAIT|FORK_LOG|FORK_REOPEN_LOG,
NULL);
if (r < 0)
return r;
+1 -1
View File
@@ -91,7 +91,7 @@ int home_setup_cifs(
if (!strextend_with_separator(&options, ",", h->cifs_extra_mount_options))
return log_oom();
r = safe_fork("(mount)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_STDOUT_TO_STDERR, &mount_pid);
r = safe_fork("(mount)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR, &mount_pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -314,7 +314,7 @@ int home_setup_fscrypt(
if (uid_is_valid(h->uid)) {
r = safe_fork("(sd-addkey)",
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_REOPEN_LOG,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_REOPEN_LOG,
NULL);
if (r < 0)
return log_error_errno(r, "Failed install encryption key in user's keyring: %m");
+3 -3
View File
@@ -228,7 +228,7 @@ static int run_fsck(const char *node, const char *fstype) {
}
r = safe_fork("(fsck)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
&fsck_pid);
if (r < 0)
return r;
@@ -2596,7 +2596,7 @@ static int ext4_offline_resize_fs(
/* resize2fs requires that the file system is force checked first, do so. */
r = safe_fork("(e2fsck)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
&fsck_pid);
if (r < 0)
return r;
@@ -2628,7 +2628,7 @@ static int ext4_offline_resize_fs(
/* Resize the thing */
r = safe_fork("(e2resize)",
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS,
&resize_pid);
if (r < 0)
return r;
+2 -2
View File
@@ -39,7 +39,7 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
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);
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
@@ -108,7 +108,7 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
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);
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -369,7 +369,7 @@ static int transfer_start(Transfer *t) {
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);
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO, &t->pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -417,7 +417,7 @@ static int verify_gpg(
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,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pid);
if (r < 0)
return r;
+1 -1
View File
@@ -91,7 +91,7 @@ static int spawn_child(const char* child, char** argv) {
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);
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &child_pid);
if (r < 0) {
safe_close_pair(fd);
return r;
+1 -1
View File
@@ -51,7 +51,7 @@ int bus_container_connect_socket(sd_bus *b) {
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
return log_debug_errno(errno, "Failed to create a socket pair: %m");
r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
if (r < 0)
return log_debug_errno(r, "Failed to create namespace for (sd-buscntr): %m");
+6
View File
@@ -761,6 +761,12 @@ int sd_netlink_detach_event(sd_netlink *nl) {
return 0;
}
sd_event* sd_netlink_get_event(sd_netlink *nl) {
assert_return(nl, NULL);
return nl->event;
}
int netlink_add_match_internal(
sd_netlink *nl,
sd_netlink_slot **ret_slot,
+1 -1
View File
@@ -300,7 +300,7 @@ static int run(int argc, char *argv[]) {
if (!arguments)
return log_oom();
r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
r = safe_fork("(inhibit)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -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_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &w->child);
r = safe_fork("(sd-bright)", FORK_DEATHSIG_SIGKILL|FORK_REARRANGE_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &w->child);
if (r < 0)
return r;
if (r == 0) {
+3 -3
View File
@@ -248,7 +248,7 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
return -errno;
r = namespace_fork("(sd-addrns)", "(sd-addr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
r = namespace_fork("(sd-addrns)", "(sd-addr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
-1, -1, netns_fd, -1, -1, &child);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
@@ -382,7 +382,7 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
return -errno;
r = namespace_fork("(sd-osrelns)", "(sd-osrel)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
r = namespace_fork("(sd-osrelns)", "(sd-osrel)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
pidns_fd, mntns_fd, -1, -1, root_fd,
&child);
if (r < 0)
@@ -1103,7 +1103,7 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
return -errno;
r = namespace_fork("(sd-openrootns)", "(sd-openroot)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
r = namespace_fork("(sd-openrootns)", "(sd-openroot)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
-1, mntns_fd, -1, -1, root_fd, &child);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
+1 -1
View File
@@ -30,7 +30,7 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
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,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pid);
if (r < 0) {
safe_close_pair(pipe_fds);
+1 -1
View File
@@ -5276,7 +5276,7 @@ static int run_container(
if (arg_private_network) {
/* Move network interfaces back to the parent network namespace. We use `safe_fork`
* to avoid having to move the parent to the child network namespace. */
r = safe_fork(NULL, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_WAIT|FORK_LOG, NULL);
r = safe_fork(NULL, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
if (r < 0)
return r;
+1 -1
View File
@@ -4673,7 +4673,7 @@ static int partition_populate_filesystem(Context *context, Partition *p, const c
* appear in the host namespace. Hence we fork a child that has its own file system namespace and
* detached mount propagation. */
r = safe_fork("(sd-copy)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
r = safe_fork("(sd-copy)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -411,7 +411,7 @@ static int portable_extract_by_path(
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, seq) < 0)
return log_debug_errno(errno, "Failed to allocated SOCK_SEQPACKET socket: %m");
r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child);
r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_LOG, &child);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -79,7 +79,7 @@ static int run(int argc, char *argv[]) {
return 0;
}
r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_WAIT|FORK_LOG, NULL);
r = safe_fork("(quotacheck)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_WAIT|FORK_LOG, NULL);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -51,7 +51,7 @@ static int do_remount(const char *path, bool force_rw, Hashmap **pids) {
log_debug("Remounting %s...", path);
r = safe_fork(force_rw ? "(remount-rw)" : "(remount)",
FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
+2 -2
View File
@@ -151,7 +151,7 @@ static void *tls_dns_server(void *p) {
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,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_REOPEN_LOG,
&openssl_pid);
assert_se(r >= 0);
if (r == 0) {
@@ -336,7 +336,7 @@ static void try_isolate_network(void) {
/* First test if CLONE_NEWUSER/CLONE_NEWNET can actually work for us, i.e. we can open the namespaces
* and then still access the build dir we are run from. We do that in a child process since it's
* nasty if we have to go back from the namespace once we entered it and realized it cannot work. */
r = safe_fork("(usernstest)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(usernstest)", FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT, NULL);
if (r == 0) { /* child */
_cleanup_free_ char *rt = NULL, *d = NULL;
+1 -1
View File
@@ -104,7 +104,7 @@ int block_device_get_whole_disk(sd_device *dev, sd_device **ret) {
return 0;
}
static int block_device_get_originating(sd_device *dev, sd_device **ret) {
int block_device_get_originating(sd_device *dev, sd_device **ret) {
_cleanup_(sd_device_unrefp) sd_device *first_found = NULL;
const char *suffix;
dev_t devnum = 0; /* avoid false maybe-uninitialized warning */
+1
View File
@@ -27,6 +27,7 @@ int block_device_new_from_path(const char *path, BlockDeviceLookupFlag flag, sd_
int block_device_is_whole_disk(sd_device *dev);
int block_device_get_whole_disk(sd_device *dev, sd_device **ret);
int block_device_get_originating(sd_device *dev, sd_device **ret);
int block_get_whole_disk(dev_t d, dev_t *ret);
int block_get_originating(dev_t d, dev_t *ret);
+1 -1
View File
@@ -1401,7 +1401,7 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *ret_n
if (shared == MAP_FAILED)
return negative_errno();
r = safe_fork("(sd-calendar)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL);
r = safe_fork("(sd-calendar)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_WAIT, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
+2 -2
View File
@@ -1718,7 +1718,7 @@ static int run_fsck(int node_fd, const char *fstype) {
"(fsck)",
NULL,
&node_fd, 1, /* Leave the node fd open */
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_CLOEXEC_OFF,
&pid);
if (r < 0)
return log_debug_errno(r, "Failed to fork off fsck: %m");
@@ -3410,7 +3410,7 @@ int dissected_image_acquire_metadata(DissectedImage *m, DissectImageFlags extra_
goto finish;
}
r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child);
r = safe_fork("(sd-dissect)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, &child);
if (r < 0)
goto finish;
if (r == 0) {
+1 -1
View File
@@ -270,7 +270,7 @@ static int run_editor(const EditFileContext *context) {
assert(context);
r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(editor)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT, NULL);
if (r < 0)
return r;
if (r == 0) { /* Child */
+3 -3
View File
@@ -45,7 +45,7 @@ static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid, b
return 0;
}
r = safe_fork("(direxec)", FORK_DEATHSIG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &_pid);
r = safe_fork("(direxec)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE, &_pid);
if (r < 0)
return r;
if (r == 0) {
@@ -250,7 +250,7 @@ int execute_strv(
* them to finish. Optionally a timeout is applied. If a file with the same name
* exists in more than one directory, the earliest one wins. */
r = safe_fork("(sd-executor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &executor_pid);
r = safe_fork("(sd-executor)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &executor_pid);
if (r < 0)
return r;
if (r == 0) {
@@ -541,7 +541,7 @@ int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret
NULL,
except,
n_except,
FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_REOPEN_LOG|FORK_RLIMIT_NOFILE_SAFE,
ret_pid);
if (r < 0)
return r;
+1 -1
View File
@@ -1692,7 +1692,7 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
return -errno;
r = namespace_fork("(sd-bootidns)", "(sd-bootid)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
r = namespace_fork("(sd-bootidns)", "(sd-bootid)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
pidnsfd, mntnsfd, -1, -1, rootfd, &child);
if (r < 0)
return r;
+2 -2
View File
@@ -155,7 +155,7 @@ static int do_mcopy(const char *node, const char *root) {
if (strv_extend(&argv, "::") < 0)
return log_oom();
r = safe_fork("(mcopy)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS, NULL);
r = safe_fork("(mcopy)", FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_STDOUT_TO_STDERR|FORK_CLOSE_ALL_FDS, NULL);
if (r < 0)
return r;
if (r == 0) {
@@ -336,7 +336,7 @@ int make_filesystem(
_cleanup_(unlink_and_freep) char *protofile = NULL;
char vol_id[CONST_MAX(SD_ID128_UUID_STRING_MAX, 8U + 1U)] = {};
int stdio_fds[3] = { -EBADF, STDERR_FILENO, STDERR_FILENO};
ForkFlags flags = FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|
ForkFlags flags = FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|
FORK_CLOSE_ALL_FDS|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG;
int r;
+2 -2
View File
@@ -981,7 +981,7 @@ static int mount_in_namespace_legacy(
goto finish;
}
r = namespace_fork("(sd-bindmnt)", "(sd-bindmnt-inner)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
r = namespace_fork("(sd-bindmnt)", "(sd-bindmnt-inner)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM,
pidns_fd, mntns_fd, -1, -1, root_fd, &child);
if (r < 0)
goto finish;
@@ -1184,7 +1184,7 @@ static int mount_in_namespace(
"(sd-bindmnt-inner)",
/* except_fds= */ NULL,
/* n_except_fds= */ 0,
FORK_RESET_SIGNALS|FORK_DEATHSIG,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM,
pidns_fd,
mntns_fd,
/* netns_fd= */ -1,
+1 -1
View File
@@ -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_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
r = safe_fork("(man)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|(null_stdio ? FORK_REARRANGE_STDIO : 0)|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -452,7 +452,7 @@ int varlink_connect_exec(Varlink **ret, const char *_command, char **_argv) {
/* stdio_fds= */ NULL,
/* except_fds= */ (int[]) { pair[1] },
/* n_except_fds= */ 1,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pid);
if (r < 0)
return log_debug_errno(r, "Failed to spawn process: %m");
+1 -1
View File
@@ -223,7 +223,7 @@ static int fork_and_exec_process(const char *child, char **argv, int fd) {
return log_oom();
r = safe_fork("(activate)",
FORK_RESET_SIGNALS | FORK_DEATHSIG | FORK_RLIMIT_NOFILE_SAFE | FORK_LOG,
FORK_RESET_SIGNALS | FORK_DEATHSIG_SIGTERM | FORK_RLIMIT_NOFILE_SAFE | FORK_LOG,
&child_pid);
if (r < 0)
return r;
+11
View File
@@ -0,0 +1,11 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
executables += [
libexec_template + {
'name' : 'systemd-storagetm',
'conditions' : [
'ENABLE_STORAGETM',
],
'sources' : files('storagetm.c'),
},
]
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -70,7 +70,7 @@ static int fork_wait(const char* const cmdline[]) {
pid_t pid;
int r;
r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
r = safe_fork("(sulogin)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -973,7 +973,7 @@ static int merge(ImageClass image_class,
pid_t pid;
int r;
r = safe_fork("(sd-merge)", FORK_DEATHSIG|FORK_LOG|FORK_NEW_MOUNTNS, &pid);
r = safe_fork("(sd-merge)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_NEW_MOUNTNS, &pid);
if (r < 0)
return log_error_errno(r, "Failed to fork off child: %m");
if (r == 0) {
+1 -1
View File
@@ -84,7 +84,7 @@ static int load_kexec_kernel(void) {
if (arg_dry_run)
return 0;
r = safe_fork("(kexec)", FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
r = safe_fork("(kexec)", FORK_WAIT|FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -210,7 +210,7 @@ int enable_sysv_units(const char *verb, char **args) {
if (!arg_quiet)
log_info("Executing: %s", l);
j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
j = safe_fork("(sysv-install)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (j < 0)
return j;
if (j == 0) {
+1
View File
@@ -67,6 +67,7 @@ int sd_netlink_add_match(sd_netlink *nl, sd_netlink_slot **ret_slot, uint16_t ma
int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int64_t priority);
int sd_netlink_detach_event(sd_netlink *nl);
sd_event* sd_netlink_get_event(sd_netlink *nl);
int sd_netlink_attach_filter(sd_netlink *nl, size_t len, const struct sock_filter *filter);
/* Message construction */
+1 -1
View File
@@ -292,7 +292,7 @@ static int download_manifest(
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,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG,
&pid);
if (r < 0)
return r;
+1 -1
View File
@@ -793,7 +793,7 @@ static int run_helper(
assert(path);
assert(cmdline);
r = safe_fork(name, FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork(name, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
if (r < 0)
return r;
if (r == 0) {
+2 -2
View File
@@ -30,7 +30,7 @@ TEST(asynchronous_close) {
assert_se(fcntl(fd, F_GETFD) == -1);
assert_se(errno == EBADF);
r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGKILL|FORK_LOG|FORK_WAIT, NULL);
assert(r >= 0);
if (r == 0) {
@@ -63,7 +63,7 @@ TEST(asynchronous_rm_rf) {
/* Do this once more, form a subreaper. Which is nice, because we can watch the async child even
* though detached */
r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(subreaper)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
+1 -1
View File
@@ -254,7 +254,7 @@ static void test_capability_get_ambient(void) {
assert_se(capability_get_ambient(&c) >= 0);
r = safe_fork("(getambient)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_WAIT|FORK_LOG, NULL);
r = safe_fork("(getambient)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
assert_se(r >= 0);
if (r == 0) {
+1 -1
View File
@@ -115,7 +115,7 @@ TEST(copy_data_fd) {
assert_se(socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sfd) >= 0);
r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
r = safe_fork("(sd-pipe)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
+1 -1
View File
@@ -475,7 +475,7 @@ TEST(setenv_systemd_exec_pid) {
TEST(getenv_steal_erase) {
int r;
r = safe_fork("(sd-getenvstealerase)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(sd-getenvstealerase)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
if (r == 0) {
_cleanup_strv_free_ char **l = NULL;
+2 -2
View File
@@ -602,7 +602,7 @@ static int find_libraries(const char *exec, char ***ret) {
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);
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
execlp("ldd", "ldd", exec, NULL);
@@ -1299,7 +1299,7 @@ static int prepare_ns(const char *process_name) {
r = safe_fork(process_name,
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG |
FORK_DEATHSIG_SIGTERM |
FORK_WAIT |
FORK_REOPEN_LOG |
FORK_LOG |
+4 -4
View File
@@ -337,7 +337,7 @@ TEST(close_all_fds) {
* with /proc/ overmounted, and once with the combination of both. This should trigger all fallbacks
* in the close_range_all() function. */
r = safe_fork("(caf-plain)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(caf-plain)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
if (r == 0) {
test_close_all_fds_inner();
_exit(EXIT_SUCCESS);
@@ -347,7 +347,7 @@ TEST(close_all_fds) {
if (geteuid() != 0)
return (void) log_tests_skipped("Lacking privileges for test with close_range() blocked and /proc/ overmounted");
r = safe_fork("(caf-noproc)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
r = safe_fork("(caf-noproc)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
if (r == 0) {
r = mount_nofollow_verbose(LOG_WARNING, "tmpfs", "/proc", "tmpfs", 0, NULL);
if (r < 0)
@@ -361,7 +361,7 @@ TEST(close_all_fds) {
if (!is_seccomp_available())
return (void) log_tests_skipped("Seccomp not available");
r = safe_fork("(caf-seccomp)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(caf-seccomp)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
if (r == 0) {
r = seccomp_prohibit_close_range();
if (r < 0)
@@ -373,7 +373,7 @@ TEST(close_all_fds) {
}
assert_se(r >= 0);
r = safe_fork("(caf-scnp)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
r = safe_fork("(caf-scnp)", FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE, NULL);
if (r == 0) {
r = seccomp_prohibit_close_range();
if (r < 0)
+1 -1
View File
@@ -969,7 +969,7 @@ TEST(read_full_file_socket) {
/* Bind the *client* socket to some randomized name, to verify that this works correctly. */
assert_se(asprintf(&clientname, "@%" PRIx64 "/test-bindname", random_u64()) >= 0);
r = safe_fork("(server)", FORK_DEATHSIG|FORK_LOG, &pid);
r = safe_fork("(server)", FORK_DEATHSIG_SIGTERM|FORK_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
union sockaddr_union peer = {};
+3 -1
View File
@@ -82,7 +82,7 @@ TEST(keymaps) {
#define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x))
TEST(dump_special_glyphs) {
assert_cc(SPECIAL_GLYPH_WARNING_SIGN + 1 == _SPECIAL_GLYPH_MAX);
assert_cc(SPECIAL_GLYPH_WORLD + 1 == _SPECIAL_GLYPH_MAX);
log_info("is_locale_utf8: %s", yes_no(is_locale_utf8()));
@@ -125,6 +125,8 @@ TEST(dump_special_glyphs) {
dump_glyph(SPECIAL_GLYPH_SPARKLES);
dump_glyph(SPECIAL_GLYPH_LOW_BATTERY);
dump_glyph(SPECIAL_GLYPH_WARNING_SIGN);
dump_glyph(SPECIAL_GLYPH_COMPUTER_DISK);
dump_glyph(SPECIAL_GLYPH_WORLD);
}
DEFINE_TEST_MAIN(LOG_INFO);
+27
View File
@@ -35,4 +35,31 @@ TEST(make_lock_file) {
assert_se(make_lock_file("lock", LOCK_EX|LOCK_NB, &lock2) == -EBUSY);
}
static void test_lock_generic_with_timeout_for_type(LockType type) {
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
_cleanup_close_ int tfd = -EBADF, tfd2 = -EBADF;
tfd = mkdtemp_open(NULL, 0, &t);
assert_se(tfd >= 0);
tfd2 = fd_reopen(tfd, O_CLOEXEC|O_DIRECTORY);
assert_se(tfd2 >= 0);
assert_se(lock_generic(tfd, LOCK_BSD, LOCK_EX) >= 0);
assert_se(lock_generic(tfd2, LOCK_BSD, LOCK_EX|LOCK_NB) == -EWOULDBLOCK);
usec_t start = now(CLOCK_MONOTONIC);
assert_se(lock_generic_with_timeout(tfd2, LOCK_BSD, LOCK_EX, 200 * USEC_PER_MSEC) == -ETIMEDOUT);
assert_se(usec_sub_unsigned(now(CLOCK_MONOTONIC), start) >= 200 * USEC_PER_MSEC);
assert_se(lock_generic(tfd, LOCK_BSD, LOCK_UN) >= 0);
assert_se(lock_generic_with_timeout(tfd2, LOCK_BSD, LOCK_EX, 200 * USEC_PER_MSEC) == 0);
assert_se(lock_generic(tfd, LOCK_BSD, LOCK_EX|LOCK_NB) == -EWOULDBLOCK);
}
TEST(lock_generic_with_timeout) {
test_lock_generic_with_timeout_for_type(LOCK_BSD);
test_lock_generic_with_timeout_for_type(LOCK_UNPOSIX);
}
DEFINE_TEST_MAIN(LOG_INFO);
+1 -1
View File
@@ -226,7 +226,7 @@ TEST(real_pressure) {
assert_se(pipe2(pipe_fd, O_CLOEXEC) >= 0);
r = safe_fork("(eat-memory)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &pid);
r = safe_fork("(eat-memory)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, &pid);
assert_se(r >= 0);
if (r == 0) {
real_pressure_eat_memory(pipe_fd[0]);
+1 -1
View File
@@ -80,7 +80,7 @@ TEST(mkdir_p_safe) {
p = mfree(p);
assert_se(p = path_join(tmp, "zero-mode/should-fail-to-create-child"));
assert_se(mkdir_parents_safe(tmp, p, 0000, UID_INVALID, GID_INVALID, 0) >= 0);
r = safe_fork("(test-mkdir-no-cap)", FORK_DEATHSIG | FORK_WAIT | FORK_LOG, NULL);
r = safe_fork("(test-mkdir-no-cap)", FORK_DEATHSIG_SIGTERM | FORK_WAIT | FORK_LOG, NULL);
if (r == 0) {
(void) capability_bounding_set_drop(0, /* right_now = */ true);
assert_se(mkdir_p_safe(tmp, p, 0000, UID_INVALID, GID_INVALID, 0) == -EACCES);
+3 -3
View File
@@ -280,7 +280,7 @@ TEST(make_mount_switch_root) {
r = safe_fork("(switch-root)",
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG |
FORK_DEATHSIG_SIGTERM |
FORK_WAIT |
FORK_REOPEN_LOG |
FORK_LOG |
@@ -332,7 +332,7 @@ TEST(umount_recursive) {
r = safe_fork("(umount-rec)",
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG |
FORK_DEATHSIG_SIGTERM |
FORK_WAIT |
FORK_REOPEN_LOG |
FORK_LOG |
@@ -406,7 +406,7 @@ TEST(fd_make_mount_point) {
r = safe_fork("(make_mount-point)",
FORK_RESET_SIGNALS |
FORK_CLOSE_ALL_FDS |
FORK_DEATHSIG |
FORK_DEATHSIG_SIGTERM |
FORK_WAIT |
FORK_REOPEN_LOG |
FORK_LOG |
+3 -3
View File
@@ -634,7 +634,7 @@ TEST(safe_fork) {
BLOCK_SIGNALS(SIGCHLD);
r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
r = safe_fork("(test-child)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_REOPEN_LOG, &pid);
assert_se(r >= 0);
if (r == 0) {
@@ -701,7 +701,7 @@ TEST(setpriority_closest) {
int r;
r = safe_fork("(test-setprio)",
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT|FORK_LOG, NULL);
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_LOG, NULL);
assert_se(r >= 0);
if (r == 0) {
@@ -855,7 +855,7 @@ TEST(get_process_threads) {
int r;
/* Run this test in a child, so that we can guarantee there's exactly one thread around in the child */
r = safe_fork("(nthreads)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_REOPEN_LOG|FORK_WAIT|FORK_LOG, NULL);
r = safe_fork("(nthreads)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_WAIT|FORK_LOG, NULL);
assert_se(r >= 0);
if (r == 0) {
+1 -1
View File
@@ -93,7 +93,7 @@ TEST(rm_rf_chmod) {
/* This test only works unpriv (as only then the access mask for the owning user matters),
* hence drop privs here */
r = safe_fork("(setresuid)", FORK_DEATHSIG|FORK_WAIT, NULL);
r = safe_fork("(setresuid)", FORK_DEATHSIG_SIGTERM|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
+7 -7
View File
@@ -158,7 +158,7 @@ TEST(in_addr_is_multicast) {
TEST(getpeercred_getpeergroups) {
int r;
r = safe_fork("(getpeercred)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(getpeercred)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
@@ -228,7 +228,7 @@ TEST(passfd_read) {
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
r = safe_fork("(passfd_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(passfd_read)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
@@ -270,7 +270,7 @@ TEST(passfd_contents_read) {
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
@@ -322,7 +322,7 @@ TEST(pass_many_fds_contents_read) {
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(passfd_contents_read)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
@@ -382,7 +382,7 @@ TEST(receive_nopassfd) {
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
r = safe_fork("(receive_nopassfd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(receive_nopassfd)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
@@ -418,7 +418,7 @@ TEST(send_nodata_nofd) {
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
r = safe_fork("(send_nodata_nofd)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(send_nodata_nofd)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
@@ -451,7 +451,7 @@ TEST(send_emptydata) {
assert_se(socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) >= 0);
r = safe_fork("(send_emptydata)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
r = safe_fork("(send_emptydata)", FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_WAIT, NULL);
assert_se(r >= 0);
if (r == 0) {
+1 -1
View File
@@ -381,7 +381,7 @@ static int worker_spawn(Manager *manager, Event *event) {
if (r < 0)
return log_error_errno(r, "Worker: Failed to enable receiving of device: %m");
r = safe_fork("(udev-worker)", FORK_DEATHSIG, &pid);
r = safe_fork("(udev-worker)", FORK_DEATHSIG_SIGTERM, &pid);
if (r < 0) {
event->state = EVENT_QUEUED;
return log_error_errno(r, "Failed to fork() worker: %m");
+1 -1
View File
@@ -280,7 +280,7 @@ int udev_event_spawn(
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,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_REARRANGE_STDIO|FORK_LOG|FORK_RLIMIT_NOFILE_SAFE,
&pid);
if (r < 0)
return log_device_error_errno(event->dev, r,
+14 -73
View File
@@ -10,6 +10,7 @@
#include "device-util.h"
#include "fd-util.h"
#include "fdset.h"
#include "lock-util.h"
#include "main-func.h"
#include "parse-util.h"
#include "path-util.h"
@@ -194,91 +195,31 @@ static int lock_device(
if (!S_ISBLK(st.st_mode) || st.st_rdev != devno)
return log_error_errno(SYNTHETIC_ERRNO(ENXIO), "Path '%s' no longer refers to specified block device %u:%u: %m", path, major(devno), minor(devno));
if (flock(fd, LOCK_EX|LOCK_NB) < 0) {
if (errno != EAGAIN)
return log_error_errno(errno, "Failed to lock device '%s': %m", path);
r = lock_generic(fd, LOCK_BSD, LOCK_EX|LOCK_NB);
if (r < 0) {
if (r != -EAGAIN)
return log_error_errno(r, "Failed to lock device '%s': %m", path);
if (deadline == 0)
return log_error_errno(SYNTHETIC_ERRNO(EBUSY), "Device '%s' is currently locked.", path);
if (deadline == USEC_INFINITY) {
log_info("Device '%s' is currently locked, waiting%s", path, special_glyph(SPECIAL_GLYPH_ELLIPSIS));
if (flock(fd, LOCK_EX) < 0)
return log_error_errno(errno, "Failed to lock device '%s': %m", path);
r = lock_generic(fd, LOCK_BSD, LOCK_EX);
} else {
_cleanup_(sigkill_waitp) pid_t flock_pid = 0;
/* flock() doesn't support a time-out. Let's fake one then. The traditional way to do
* this is via alarm()/setitimer()/timer_create(), but that's racy, given that the
* SIGALRM might already fire between the alarm() and the flock() in which case the
* flock() is never cancelled and we lock up (this is a short time window, but with
* short timeouts on a loaded machine we might run into it, who knows?). Let's
* instead do the lock out-of-process: fork off a child that does the locking, and
* that we'll wait on and kill if it takes too long. */
usec_t left = usec_sub_unsigned(deadline, now(CLOCK_MONOTONIC));
log_info("Device '%s' is currently locked, waiting %s%s",
path, FORMAT_TIMESPAN(usec_sub_unsigned(deadline, now(CLOCK_MONOTONIC)), 0),
path, FORMAT_TIMESPAN(left, 0),
special_glyph(SPECIAL_GLYPH_ELLIPSIS));
BLOCK_SIGNALS(SIGCHLD);
r = safe_fork("(timed-flock)", FORK_DEATHSIG|FORK_LOG, &flock_pid);
if (r < 0)
return r;
if (r == 0) {
/* Child */
if (flock(fd, LOCK_EX) < 0) {
log_error_errno(errno, "Failed to lock device '%s': %m", path);
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
for (;;) {
siginfo_t si;
sigset_t ss;
usec_t n;
assert_se(sigemptyset(&ss) >= 0);
assert_se(sigaddset(&ss, SIGCHLD) >= 0);
n = now(CLOCK_MONOTONIC);
if (n >= deadline)
return log_error_errno(SYNTHETIC_ERRNO(ETIMEDOUT), "Timeout reached.");
r = sigtimedwait(&ss, NULL, TIMESPEC_STORE(deadline - n));
if (r < 0) {
if (errno != EAGAIN)
return log_error_errno(errno, "Failed to wait for SIGCHLD: %m");
return log_error_errno(SYNTHETIC_ERRNO(ETIMEDOUT), "Timeout reached.");
}
assert(r == SIGCHLD);
zero(si);
if (waitid(P_PID, flock_pid, &si, WEXITED|WNOHANG|WNOWAIT) < 0)
return log_error_errno(errno, "Failed to wait for child: %m");
if (si.si_pid != 0) {
assert(si.si_pid == flock_pid);
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
return log_error_errno(SYNTHETIC_ERRNO(EPROTO), "Unexpected exit status of file lock child.");
break;
}
log_debug("Got SIGCHLD for other child, continuing.");
}
r = lock_generic_with_timeout(fd, LOCK_BSD, LOCK_EX, left);
if (r == -ETIMEDOUT)
return log_error_errno(r, "Timeout reached.");
}
if (r < 0)
return log_error_errno(r, "Failed to lock device '%s': %m", path);
}
log_debug("Successfully locked %s (%u:%u)%s", path, major(devno), minor(devno), special_glyph(SPECIAL_GLYPH_ELLIPSIS));
@@ -349,7 +290,7 @@ int lock_main(int argc, char *argv[], void *userdata) {
/* Ignore SIGINT and allow the forked process to receive it */
(void) ignore_signals(SIGINT);
r = safe_fork("(lock)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
r = safe_fork("(lock)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_CLOSE_ALL_FDS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG, &pid);
if (r < 0)
return r;
if (r == 0) {
+1 -1
View File
@@ -149,7 +149,7 @@ static int start_one_worker(Manager *m) {
"(sd-worker)",
/* stdio_fds= */ NULL,
&m->listen_fd, 1,
FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_REOPEN_LOG|FORK_LOG|FORK_CLOSE_ALL_FDS,
FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM|FORK_REOPEN_LOG|FORK_LOG|FORK_CLOSE_ALL_FDS,
&pid);
if (r < 0)
return log_error_errno(r, "Failed to fork new worker child: %m");
+1
View File
@@ -0,0 +1 @@
../TEST-01-BASIC/Makefile
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -e
TEST_DESCRIPTION="test storagetm"
TEST_NO_NSPAWN=1
# shellcheck source=test/test-functions
. "${TEST_BASE_DIR:?}/test-functions"
test_require_bin nvme
modprobe -nv nvmet-tcp || exit 0
test_append_files() {
inst_binary nvme
instmods "=nvme"
instmods configfs
generate_module_dependencies
}
do_test "$@"
+9
View File
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
[Unit]
Description=TEST-84-STORAGETM
After=multi-user.target
[Service]
ExecStartPre=rm -f /failed /testok
ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
Type=oneshot
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
modprobe -v nvmet-tcp
modprobe -v nvme-tcp
systemctl start sys-kernel-config.mount
dd if=/dev/urandom of=/var/tmp/storagetm.test bs=1024 count=10240
systemd-run -u teststoragetm.service -p Type=notify /usr/lib/systemd/systemd-storagetm /var/tmp/storagetm.test --nqn=quux
nvme connect-all -t tcp -a 127.0.0.1 -s 16858 --hostid="$(cat /proc/sys/kernel/random/uuid)"
dd if=/dev/nvme1n1 bs=1024 | cmp /var/tmp/storagetm.test -
nvme disconnect --device=nvme1
systemctl stop teststoragetm.service
rm /var/tmp/storagetm.test
touch /testok
+8
View File
@@ -559,6 +559,14 @@ units = [
'conditions' : ['ENABLE_SYSUSERS'],
'symlinks' : ['sysinit.target.wants/'],
},
{
'file' : 'systemd-storagetm.service.in',
'conditions' : ['ENABLE_STORAGETM'],
},
{
'file' : 'storage-target-mode.target',
'conditions' : ['ENABLE_STORAGETM'],
},
{
'file' : 'systemd-time-wait-sync.service.in',
'conditions' : ['ENABLE_TIMESYNCD'],
+16
View File
@@ -0,0 +1,16 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Storage Target Mode
Documentation=man:systemd.special(7)
Wants=systemd-storagetm.service systemd-udevd.service systemd-udev-trigger.service systemd-networkd.service systemd-network-generator.service systemd-journald.socket systemd-journald-dev-log.socket
Conflicts=rescue.service rescue.target
After=systemd-storagetm.service systemd-udevd.service systemd-udev-trigger.service systemd-networkd.service systemd-network-generator.service systemd-journald.socket systemd-journald-dev-log.socket rescue.service rescue.target
AllowIsolate=yes
+27
View File
@@ -0,0 +1,27 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Storage Target Mode (NVMe-TCP)
Documentation=man:systemd-storagetm.service(8)
ConditionVirtualization=!container
DefaultDependencies=no
Wants=modprobe@nvmet_tcp.service modprobe@thunderbolt_net.service sys-kernel-config.mount
After=modprobe@nvmet_tcp.service modprobe@thunderbolt_net.service sys-kernel-config.mount
Conflicts=shutdown.target
Before=shutdown.target
FailureAction=reboot
SuccessAction=reboot
[Service]
Type=notify
RemainAfterExit=yes
StandardInput=tty
StandardOutput=tty
ExecStart={{LIBEXECDIR}}/systemd-storagetm --all