diff --git a/man/sd_notify.xml b/man/sd_notify.xml index cb07add95eb..707e3515118 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -238,25 +238,29 @@ FDSTORE=1 - 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 - sd_listen_fds3. 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 /run/, or better, stored - in a memfd_create2 memory - file descriptor. Note that the service manager will accept messages for a service only if its + 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 + sd_listen_fds3. + 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 + /run/, or better, stored in a + memfd_create2 + memory file descriptor. Note that the service manager will accept messages for a service only if its FileDescriptorStoreMax= setting is non-zero (defaults to zero, see systemd.service5). If FDPOLL=0 is not set and the file descriptors sent are pollable (see - epoll_ctl2), then any - EPOLLHUP or EPOLLERR 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 sd_pid_notify_with_fds() - to send messages with FDSTORE=1, see below. + epoll_ctl2), then + any EPOLLHUP or EPOLLERR 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 + sd_pid_notify_with_fds() to send messages with FDSTORE=1, see + below. The service manager will set the $FDSTORE environment variable for services + that have the file descriptor store enabled. @@ -348,19 +352,14 @@ sd_notify() and sd_notifyf(). - sd_pid_notify_with_fds() is similar to - sd_pid_notify() 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 FDSTORE=1 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 sd_pid_notify(), 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 FDSTORE=1) they are immediately closed - on reception. + sd_pid_notify_with_fds() is similar to sd_pid_notify() + 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 FDSTORE=1 + 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 sd_pid_notify(), i.e. no file descriptors are passed. Note + that file descriptors sent to the service manager on a message without FDSTORE=1 are + immediately closed on reception. sd_notify_barrier() allows the caller to synchronize against reception of previously sent notification messages diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 17be33c56a2..3a4af9cabe1 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -3476,8 +3476,7 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX $NOTIFY_SOCKET - The socket - sd_notify() talks to. See + The socket sd_notify() talks to. See sd_notify3. @@ -3799,6 +3798,19 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX convey. + + $FDSTORE + + If the file descriptor store is enabled for a service + (i.e. FileDescriptorStoreMax= is set to a non-zero value, see + systemd.service5 + 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 sd_pid_notify_with_fds() (see + sd_notify3 for + details). + + For system services, when PAMName= is enabled and pam_systemd is part diff --git a/man/systemd.service.xml b/man/systemd.service.xml index f64a8e538ff..1b116b8372a 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -1089,7 +1089,12 @@ 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. + descriptors. + + If this option is set to a non-zero value the $FDSTORE environment variable + will be set for processes invoked for this service. See + systemd.exec5 for + details. diff --git a/src/core/service.c b/src/core/service.c index 48229f96ee3..650741cc7ce 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -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) diff --git a/test/units/testsuite-80.sh b/test/units/testsuite-80.sh index 0072133cd4e..15ea36bf88d 100755 --- a/test/units/testsuite-80.sh +++ b/test/units/testsuite-80.sh @@ -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"