be established on top of dm-crypt or dm-verity devices, or an allowlist of
file systems (which should probably include vfat, for compat with the ESP)
-* $LISTEN_PID, $SYSTEMD_EXECPID env vars that the service manager sets should
- be augmented with $LISTEN_PIDFDID, and $SYSTEMD_EXECPIDFD (and similar for
+* $SYSTEMD_EXECPID that the service manager sets should
+ be augmented with $SYSTEMD_EXECPIDFD (and similar for
other env vars we might send).
* port copy.c over to use LabelOps for all labelling.
Whenever the service is restarted the fds in its fdstore will be passed to the
new instance following the same protocol as for socket activation fds. i.e. the
-`$LISTEN_FDS`, `$LISTEN_PIDS`, `$LISTEN_FDNAMES` environment variables will be
-set (the latter will be populated from the `FDNAME=…` field mentioned
-above). See
+`$LISTEN_FDS`, `$LISTEN_PID`, `$LISTEN_PIDFDID`, and `$LISTEN_FDNAMES`
+environment variables will be set (the latter will be populated from the
+`FDNAME=…` field mentioned above). See
[`sd_listen_fds()`](https://www.freedesktop.org/software/systemd/man/sd_listen_fds.html)
for details on receiving such fds in a service. (Note that the name set in
`FDNAME=…` does not need to be unique, which is useful when operating with
<para>If the <parameter>unset_environment</parameter> parameter is
non-zero, <function>sd_listen_fds()</function> will unset the
- <varname>$LISTEN_FDS</varname>, <varname>$LISTEN_PID</varname> and
- <varname>$LISTEN_FDNAMES</varname> environment variables before
- returning (regardless of whether the function call itself
- succeeded or not). Further calls to
+ <varname>$LISTEN_FDS</varname>, <varname>$LISTEN_PID</varname>,
+ <varname>$LISTEN_PIDFDID</varname>, and <varname>$LISTEN_FDNAMES</varname>
+ environment variables before returning (regardless of whether the function
+ call itself succeeded or not). Further calls to
<function>sd_listen_fds()</function> will then return zero, but the
variables are no longer inherited by child processes.</para>
<para>On failure, these calls returns a negative errno-style error
code. If
<varname>$LISTEN_FDS</varname>/<varname>$LISTEN_PID</varname> was
- not set or was not correctly set for this daemon and hence no file
- descriptors were received, 0 is returned. Otherwise, the number of
+ not set, or one of those variables or <varname>$LISTEN_PIDFDID</varname>
+ was not correctly set for this daemon, no file
+ descriptors were received and 0 is returned. Otherwise, the number of
file descriptors passed is returned. The application may find them
starting with file descriptor SD_LISTEN_FDS_START, i.e. file
descriptor 3.</para>
<para>Internally, <function>sd_listen_fds()</function> checks
whether the <varname>$LISTEN_PID</varname> environment variable
- equals the daemon PID. If not, it returns immediately. Otherwise,
+ equals the daemon PID. If not, it returns immediately. Since version 259,
+ if the <varname>$LISTEN_PIDFDID</varname> environment variable is set,
+ it also checks whether it matches the inode of this process' pidfd.
+ If both of these checks pass,
it parses the number passed in the <varname>$LISTEN_FDS</varname>
environment variable, then sets the FD_CLOEXEC flag for the parsed
number of file descriptors starting from SD_LISTEN_FDS_START.
<variablelist class='environment-variables'>
<varlistentry>
<term><varname>$LISTEN_PID</varname></term>
+ <term><varname>$LISTEN_PIDFDID</varname></term>
<term><varname>$LISTEN_FDS</varname></term>
<term><varname>$LISTEN_FDNAMES</varname></term>
<varlistentry>
<term><varname>$LISTEN_FDS</varname></term>
<term><varname>$LISTEN_PID</varname></term>
+ <term><varname>$LISTEN_PIDFDID</varname></term>
<term><varname>$LISTEN_FDNAMES</varname></term>
<listitem><para>See
<varlistentry>
<term><varname>$LISTEN_FDS</varname></term>
<term><varname>$LISTEN_PID</varname></term>
+ <term><varname>$LISTEN_PIDFDID</varname></term>
<term><varname>$LISTEN_FDNAMES</varname></term>
<listitem><para>Information about file descriptors passed to a
<varlistentry>
<term><varname>$LISTEN_PID</varname></term>
+ <term><varname>$LISTEN_PIDFDID</varname></term>
<term><varname>$LISTEN_FDS</varname></term>
<term><varname>$LISTEN_FDNAMES</varname></term>
#include "osc-context.h"
#include "pam-util.h"
#include "path-util.h"
+#include "pidfd-util.h"
#include "pidref.h"
#include "proc-cmdline.h"
#include "process-util.h"
assert(cgroup_context);
assert(ret);
-#define N_ENV_VARS 19
+#define N_ENV_VARS 20
our_env = new0(char*, N_ENV_VARS + _EXEC_DIRECTORY_TYPE_MAX + 1);
if (!our_env)
return -ENOMEM;
return -ENOMEM;
our_env[n_env++] = x;
+ uint64_t pidfdid;
+ if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
+ if (asprintf(&x, "LISTEN_PIDFDID=%"PRIu64, pidfdid) < 0)
+ return -ENOMEM;
+ our_env[n_env++] = x;
+ }
+
if (asprintf(&x, "LISTEN_FDS=%zu", n_fds) < 0)
return -ENOMEM;
our_env[n_env++] = x;
"LISTEN_FDNAMES",
"LISTEN_FDS",
"LISTEN_PID",
+ "LISTEN_PIDFDID",
"LOGS_DIRECTORY",
"LOG_NAMESPACE",
"MAINPID",
return;
assert_se(unsetenv("LISTEN_PID") == 0);
+ assert_se(unsetenv("LISTEN_PIDFDID") == 0);
assert_se(unsetenv("LISTEN_FDS") == 0);
assert_se(unsetenv("LISTEN_FDNAMES") == 0);
}
goto finish;
}
+ e = getenv("LISTEN_PIDFDID");
+ if (e) {
+ uint64_t own_pidfdid, pidfdid;
+
+ r = safe_atou64(e, &pidfdid);
+ if (r < 0)
+ goto finish;
+
+ if (pidfd_get_inode_id_self_cached(&own_pidfdid) >= 0) {
+ /* Is this *really* for us? */
+ if (pidfdid != own_pidfdid) {
+ r = 0;
+ goto finish;
+ }
+ }
+ }
+
e = getenv("LISTEN_FDS");
if (!e) {
r = 0;
#include "log.h"
#include "mkdir.h"
#include "path-util.h"
+#include "pidfd-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "string-table.h"
xsprintf(spid, PID_FMT, pid);
+ uint64_t pidfdid;
+ if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
+ char spidfdid[DECIMAL_STR_MAX(uint64_t)+1];
+ xsprintf(spidfdid, "%" PRIu64, pidfdid);
+
+ if (setenv("LISTEN_PIDFDID", spidfdid, /* override= */ true) < 0) {
+ log_debug_errno(errno,
+ "Failed to set environment variable 'LISTEN_PIDFDID': %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
STRV_FOREACH_PAIR(a, b, setenv_list) {
if (setenv(*a, *b, /* override= */ true) < 0) {
log_debug_errno(errno, "Failed to set environment variable '%s': %m", *a);
#include "format-util.h"
#include "log.h"
#include "mountfsd-manager.h"
+#include "pidfd-util.h"
#include "process-util.h"
#include "set.h"
#include "signal-util.h"
_exit(EXIT_FAILURE);
}
+ uint64_t pidfdid;
+ if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
+ char pidfdids[DECIMAL_STR_MAX(uint64_t)];
+
+ xsprintf(pidfdids, "%" PRIu64, pidfdid);
+ if (setenv("LISTEN_PIDFDID", pidfdids, 1) < 0) {
+ log_error_errno(errno, "Failed to set $LISTEN_PIDFDID: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
if (setenv("LISTEN_FDS", "1", 1) < 0) {
log_error_errno(errno, "Failed to set $LISTEN_FDS: %m");
_exit(EXIT_FAILURE);
#include "mkdir.h"
#include "nsresourced-manager.h"
#include "parse-util.h"
+#include "pidfd-util.h"
#include "process-util.h"
#include "recurse-dir.h"
#include "set.h"
_exit(EXIT_FAILURE);
}
+ uint64_t pidfdid;
+ if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
+ char pidfdids[DECIMAL_STR_MAX(uint64_t)];
+
+ xsprintf(pidfdids, "%" PRIu64, pidfdid);
+ if (setenv("LISTEN_PIDFDID", pidfdids, 1) < 0) {
+ log_error_errno(errno, "Failed to set $LISTEN_PIDFDID: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
if (setenv("LISTEN_FDS", "1", 1) < 0) {
log_error_errno(errno, "Failed to set $LISTEN_FDS: %m");
_exit(EXIT_FAILURE);
#include "format-util.h"
#include "log.h"
#include "main-func.h"
+#include "pidfd-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "socket-netlink.h"
if (r < 0)
return r;
+ uint64_t pidfdid;
+ if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
+ r = strv_extendf(&envp, "LISTEN_PIDFDID=%" PRIu64, pidfdid);
+ if (r < 0)
+ return r;
+ }
+
if (arg_fdnames) {
_cleanup_free_ char *names = NULL;
size_t len;
/*
Returns how many file descriptors have been passed, or a negative
- errno code on failure. Optionally, removes the $LISTEN_FDS and
- $LISTEN_PID file descriptors from the environment (recommended, but
- problematic in threaded environments). If r is the return value of
- this function you'll find the file descriptors passed as fds
- SD_LISTEN_FDS_START to SD_LISTEN_FDS_START+r-1. Returns a negative
- errno style error code on failure. This function call ensures that
- the FD_CLOEXEC flag is set for the passed file descriptors, to make
- sure they are not passed on to child processes. If FD_CLOEXEC shall
- not be set, the caller needs to unset it after this call for all file
- descriptors that are used.
+ errno code on failure. Optionally, removes the $LISTEN_FDS,
+ $LISTEN_PID, $LISTEN_PIDFDID, and $LISTEN_FDNAMES variables from the
+ environment (recommended, but problematic in threaded environments).
+ If r is the return value of this function you'll find the file
+ descriptors passed as fds SD_LISTEN_FDS_START to
+ SD_LISTEN_FDS_START+r-1. Returns a negative errno style error code on
+ failure. This function call ensures that the FD_CLOEXEC flag is set
+ for the passed file descriptors, to make sure they are not passed on
+ to child processes. If FD_CLOEXEC shall not be set, the caller needs
+ to unset it after this call for all file descriptors that are used.
See sd_listen_fds(3) for more information.
*/
#include "fs-util.h"
#include "log.h"
#include "mkdir.h"
+#include "pidfd-util.h"
#include "process-util.h"
#include "set.h"
#include "signal-util.h"
_exit(EXIT_FAILURE);
}
+ uint64_t pidfdid;
+ if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
+ r = setenvf("LISTEN_PIDFDID", true, "%" PRIu64, pidfdid);
+ if (r < 0) {
+ log_error_errno(r, "Failed to set $LISTEN_PIDFDID: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
if (setenv("LISTEN_FDS", "1", 1) < 0) {
log_error_errno(errno, "Failed to set $LISTEN_FDS: %m");
_exit(EXIT_FAILURE);
#include "pager.h"
#include "parse-argument.h"
#include "parse-util.h"
+#include "pidfd-util.h"
#include "pretty-print.h"
#include "process-util.h"
#include "string-util.h"
log_error_errno(r, "Failed to set $LISTEN_PID environment variable: %m");
_exit(EXIT_FAILURE);
}
+
+ uint64_t pidfdid;
+ if (pidfd_get_inode_id_self_cached(&pidfdid) >= 0) {
+ r = setenvf("LISTEN_PIDFDID", /* overwrite= */ true, "%" PRIu64, pidfdid);
+ if (r < 0) {
+ log_error_errno(r, "Failed to set $LISTEN_PIDFDID environment variable: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
} else {
(void) unsetenv("LISTEN_FDS");
(void) unsetenv("LISTEN_PID");
+ (void) unsetenv("LISTEN_PIDFDID");
}
(void) unsetenv("LISTEN_FDNAMES");