service: tell service processes that the fdstore is available via an env var
authorLennart Poettering <lennart@poettering.net>
Wed, 5 Apr 2023 13:48:31 +0000 (15:48 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 12 Apr 2023 08:34:31 +0000 (10:34 +0200)
man/sd_notify.xml
man/systemd.exec.xml
man/systemd.service.xml
src/core/service.c
test/units/testsuite-80.sh

index cb07add95eb2f35c1a51b331d711fde17c000030..707e3515118c9386440e5d2a9a0f731387a78fa3 100644 (file)
       <varlistentry>
         <term>FDSTORE=1</term>
 
-        <listitem><para>Stores additional file descriptors in the service manager. File descriptors sent this way will
-        be maintained per-service by the service manager and will later be handed back using the usual file descriptor
-        passing logic at the next invocation of the service (e.g. when it is restarted), see
-        <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.  This is
-        useful for implementing services that can restart after an explicit request or a crash without losing
-        state. Any open sockets and other file descriptors which should not be closed during the restart may be stored
-        this way. Application state can either be serialized to a file in <filename>/run/</filename>, or better, stored
-        in a <citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry> memory
-        file descriptor. Note that the service manager will accept messages for a service only if its
+        <listitem><para>Stores additional file descriptors in the service manager. File descriptors sent this
+        way will be maintained per-service by the service manager and will later be handed back using the
+        usual file descriptor passing logic at the next invocation of the service (e.g. when it is
+        restarted), see
+        <citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+        This is useful for implementing services that can restart after an explicit request or a crash
+        without losing state. Any open sockets and other file descriptors which should not be closed during
+        the restart may be stored this way. Application state can either be serialized to a file in
+        <filename>/run/</filename>, or better, stored in a
+        <citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+        memory file descriptor. Note that the service manager will accept messages for a service only if its
         <varname>FileDescriptorStoreMax=</varname> setting is non-zero (defaults to zero, see
         <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>). If
         <varname>FDPOLL=0</varname> is not set and the file descriptors sent are pollable (see
-        <citerefentry><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>), then any
-        <constant>EPOLLHUP</constant> or <constant>EPOLLERR</constant> event seen on them will result in their
-        automatic removal from the store. Multiple arrays of file descriptors may be sent in separate messages, in
-        which case the arrays are combined. Note that the service manager removes duplicate (pointing to the same
-        object) file descriptors before passing them to the service. When a service is stopped, its file descriptor
-        store is discarded and all file descriptors in it are closed. Use <function>sd_pid_notify_with_fds()</function>
-        to send messages with <literal>FDSTORE=1</literal>, see below.</para></listitem>
+        <citerefentry><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>), then
+        any <constant>EPOLLHUP</constant> or <constant>EPOLLERR</constant> event seen on them will result in
+        their automatic removal from the store. Multiple arrays of file descriptors may be sent in separate
+        messages, in which case the arrays are combined. Note that the service manager removes duplicate
+        (pointing to the same object) file descriptors before passing them to the service. When a service is
+        stopped, its file descriptor store is discarded and all file descriptors in it are closed. Use
+        <function>sd_pid_notify_with_fds()</function> to send messages with <literal>FDSTORE=1</literal>, see
+        below. The service manager will set the <varname>$FDSTORE</varname> environment variable for services
+        that have the file descriptor store enabled.</para></listitem>
       </varlistentry>
 
       <varlistentry>
     <function>sd_notify()</function> and
     <function>sd_notifyf()</function>.</para>
 
-    <para><function>sd_pid_notify_with_fds()</function> is similar to
-    <function>sd_pid_notify()</function> but takes an additional array
-    of file descriptors. These file descriptors are sent along the
-    notification message to the service manager. This is particularly
-    useful for sending <literal>FDSTORE=1</literal> messages, as
-    described above. The additional arguments are a pointer to the
-    file descriptor array plus the number of file descriptors in the
-    array. If the number of file descriptors is passed as 0, the call
-    is fully equivalent to <function>sd_pid_notify()</function>, i.e.
-    no file descriptors are passed. Note that sending file descriptors
-    to the service manager on messages that do not expect them (i.e.
-    without <literal>FDSTORE=1</literal>) they are immediately closed
-    on reception.</para>
+    <para><function>sd_pid_notify_with_fds()</function> is similar to <function>sd_pid_notify()</function>
+    but takes an additional array of file descriptors. These file descriptors are sent along the notification
+    message to the service manager. This is particularly useful for sending <literal>FDSTORE=1</literal>
+    messages, as described above. The additional arguments are a pointer to the file descriptor array plus
+    the number of file descriptors in the array. If the number of file descriptors is passed as 0, the call
+    is fully equivalent to <function>sd_pid_notify()</function>, i.e. no file descriptors are passed. Note
+    that file descriptors sent to the service manager on a message without <literal>FDSTORE=1</literal> are
+    immediately closed on reception.</para>
 
     <para><function>sd_notify_barrier()</function> allows the caller to
     synchronize against reception of previously sent notification messages
index 17be33c56a28338f4591e4a008a1e6c25bdaebae..3a4af9cabe1dd2e1ff9796181b5772e0a3a2d386 100644 (file)
@@ -3476,8 +3476,7 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
         <varlistentry>
           <term><varname>$NOTIFY_SOCKET</varname></term>
 
-          <listitem><para>The socket
-          <function>sd_notify()</function> talks to. See
+          <listitem><para>The socket <function>sd_notify()</function> talks to. See
           <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
           </para></listitem>
         </varlistentry>
@@ -3799,6 +3798,19 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
           convey.</para></listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>$FDSTORE</varname></term>
+
+          <listitem><para>If the file descriptor store is enabled for a service
+          (i.e. <varname>FileDescriptorStoreMax=</varname> is set to a non-zero value, see
+          <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          for details), this environment variable will be set to the maximum number of permitted entries, as
+          per the setting. Applications may check this environment variable before sending file descriptors
+          to the service manager via <function>sd_pid_notify_with_fds()</function> (see
+          <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
+          details).</para></listitem>
+        </varlistentry>
+
       </variablelist>
 
       <para>For system services, when <varname>PAMName=</varname> is enabled and <command>pam_systemd</command> is part
index f64a8e538ff473370f248594f83395ca584b989f..1b116b8372aaae7f0c75c326af3ace2c4d156e04 100644 (file)
         allow unprivileged clients to query the list of currently open file descriptors of a
         service. Sensitive data may hence be safely placed inside the referenced files, but should not be
         attached to the metadata (e.g. included in filenames) of the stored file
-        descriptors.</para></listitem>
+        descriptors.</para>
+
+        <para>If this option is set to a non-zero value the <varname>$FDSTORE</varname> environment variable
+        will be set for processes invoked for this service. See
+        <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+        details.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 48229f96ee3da629f4c57a0eb8399b0cec3d6927..650741cc7ce18f57fbc60bec0e3f6915b6a4093e 100644 (file)
@@ -1677,7 +1677,7 @@ static int service_spawn_internal(
         if (r < 0)
                 return r;
 
-        our_env = new0(char*, 12);
+        our_env = new0(char*, 13);
         if (!our_env)
                 return -ENOMEM;
 
@@ -1686,6 +1686,10 @@ static int service_spawn_internal(
                         return -ENOMEM;
 
                 exec_params.notify_socket = UNIT(s)->manager->notify_socket;
+
+                if (s->n_fd_store_max > 0)
+                        if (asprintf(our_env + n_env++, "FDSTORE=%u", s->n_fd_store_max) < 0)
+                                return -ENOMEM;
         }
 
         if (s->main_pid > 0)
index 0072133cd4e1ca4adc274aea26fe9c1dca86a92f..15ea36bf88d7a8e9a3cee002350785649087c106 100755 (executable)
@@ -53,6 +53,7 @@ cat >> "$MYSCRIPT" <<'EOF'
 #!/usr/bin/env bash
 set -eux
 set -o pipefail
+test "$FDSTORE" -eq 7
 N="/tmp/$RANDOM"
 echo $RANDOM > "$N"
 systemd-notify --fd=4 --fdname=quux --pid=parent 4< "$N"