S6-FDHOLDERD(8)

NAME
s6-fdholderd - serving part of the s6-fdholder-daemon(8) fd-holding server

SYNOPSIS
s6-fdholderd [-1] [-v verbosity] [-c maxconn] [-n maxfds] [-t clienttimeout] [-T lameducktimeout] [-i rulesdir | -x rulesfile]

DESCRIPTION
s6-fdholderd assumes that its stdin is a bound and listening Unix domain socket; it accepts connections from clients connecting to that socket, and stores and retrieves file descriptors on their behalf.

s6-fdholderd accepts connections from clients to an already bound and listening SOCK_STREAM Unix domain socket which is its standard input.

Depending on the verbosity level, it logs what it does to stderr.

It runs until killed by a signal (normally SIGTERM). When s6-fdholderd is killed, all the fds it is currently holding are lost; if they need to be preserved, the admin should make sure to transfer them beforehand with s6-fdholder-transferdump(8).

Client connections are short-lived. Clients generally perform one operation, then disconnect.

Possible operations include:

•   Storing a file descriptor: s6-fdholder-store(8).

•   Retrieving a file descriptor: s6-fdholder-retrieve(8).

•   Deleting a file descriptor: s6-fdholder-delete(8).

•   Listing stored file descriptor identifiers: s6-fdholder-list(8).

•   Getting the whole server state: s6-fdholder-getdump(8).

•   Setting the whole server state, or more accurately adding a set of file descriptors to the already existing state: s6-fdholder-setdump(8).

s6-fdholderd is meant to be execve'd into by a program that gets the listening socket. That program is normally s6-ipcserver-socketbinder(8), which creates the socket itself; but it can be a different one if the socket is to be obtained by another means, for instance if it has been retrieved from another fd-holding daemon.

s6-fdholderd will store any open file descriptor, without discriminating on its type. However, it makes more sense to store certain file descriptor types than others: for instance, Unix domain or INET domain sockets, or named pipes, are good candidates for fd-holding. On the other hand, it makes little sense to fd-hold regular files, and if done anyway, the results can be surprising, because the read/write file offset is stored with the descriptor, and no automatic rewind is performed by the daemon.

Despite there being access control for listing, the security of the system should not depend on a client not knowing what identifier a certain descriptor is stored under. If you need to hold descriptors that only a few programs are supposed to access, you can always run a separate s6-fdholderd instance in a private directory with a configuration tailored to your needs - and you can even make the name of the listening socket private. s6-fdholderd is lightweight; you can start as many instances as you need, and you can run them as long as you need, then kill them with SIGTERM.

s6-fdholderd pre-allocates its storage at start, in the stack. It uses a small amount of heap memory for communication with a client, but frees it as soon as the client disconnects. It should never run out of memory in normal usage, even if used intensively.

  Signals

SIGTERM
    Enter lameduck mode, then exit when no more operation is pending.

SIGHUP
    Reopen rulesfile, if s6-fdholderd has been run with the -x option. It is not necessary to send s6-fdholderd a SIGHUP when the -i option is used instead: configuration changes in the filesystem are automatically picked up.

  Identifiers
Every file descriptor is stored in the s6-fdholderd daemon via the s6-fdholder-store(8) program, with an identifier. That identifier is a zero-terminated character string, containing 1 to 255 characters.

Any non-null character can be used in an identifier. Non-printable or special characters will be quoted when printed by s6-fdholder-list(8). However, it is recommended to only use reasonable characters in identifiers: clients should be able to know at a glance what file descriptor is represented by an identifier. Identifiers have no special meaning to the server.

A good convention is to use ‘unix:path/to/socket’ for Unix domain sockets and ‘protocol:ip:port’ for INET domain sockets.

An identifier is chosen by the storing client, within the limits of what the server authorizes it to use.

The retrieving client must know the exact identifier corresponding to a descriptor to be able to retrieve that descriptor. It must also be authorized by the server.

When an identifier is in use, it cannot be used again to store another descriptor. However, once the descriptor has been deleted or has expired, it is possible to reuse the same identifier.

  Configuration
Before running s6-fdholderd ( or its wrapper s6-fdholder-daemon(8)), it is necessary to configure it. This is done by a series of rules, or ruleset, stored in either a rulesfile in the CDB[1] format, or in a rulesdir, i.e. a directory in the filesystem following a certain format. s6-fdholderd will refuse to run if neither the -i nor the -x option has been provided.

Rulesets can be converted between the rulesdir and rulesfile formats with the s6-accessrules-cdb-from-fs(8) and s6-accessrules-fs-from-cdb(8) conversion tools.

  Rules format
The rules file, or rules directory, follows the s6-accessrules(7) format for uid and gid checking. For every connecting client, s6-fdholderd matches the uid and gid of the client against the provided ruleset, and determines what the client is authorized to do.

By default, no client is allowed to do anything - not even connect to the server. Even ‘root’, the super-user, will be denied access. That is why it is essential to create a sensible ruleset prior to running the server in order to do anything useful.

The various rights that a client can have are the following (using a rulesdir as an example, but a rulesfile works the same way):

•   Connect to the server. This is a prerequisite for doing anything. It will allow a client to perform “public” operations, ones that do not require specific access rights other than connecting. (There are no such operations for now, but it could change in the future; for now, when you allow a client to connect to the server, make sure to give him other rights too.) This right is given if an allow file is found in one of the subdirectories checked by s6_accessrules_keycheck_uidgid(). For instance, to allow everyone to connect, touch rulesdir/uid/default/allow.

The other rights are defined in the “environment” part of the ruleset:

•   File descriptor storage rights. This will be checked for storage and deletion of individual file descriptors. This right is given if a non-empty file named S6_FDHOLDER_STORE_REGEX is found in the env/ subdirectory of one of the subdirectories checked by s6_accessrules_keycheck_uidgid(). This file should contain a single line, which will be interpreted as an Extended Regular Expression[2] by s6-fdholderd; the regular expression describes the set of identifiers that the client is allowed to use to store file descriptors. For instance, ‘^unix:/tmp/’ indicates that a client that matches this rule will be allowed to store or delete file descriptors using any identifier starting with ‘unix:/tmp/’.

•   File descriptor retrieval rights. This will be checked for retrieval of individual file descriptors. This right is given if a non-empty file named S6_FDHOLDER_RETRIEVE_REGEX is found in the env/ subdirectory of one of the subdirectories checked by s6_accessrules_keycheck_uidgid(). This file should contain a single line, which will be interpreted as an Extended Regular Expression[2] by s6-fdholderd; the regular expression describes the set of identifiers that the client is allowed to use to retrieve file descriptors. For instance, ‘^unix:/tmp/’ indicates that a client that matches this rule will be allowed to retrieve file descriptors that are identified by strings starting with ‘unix:/tmp/’.

•   Listing rights. This will be checked for clients wanting to list the identifiers of the descriptors currently stored in the server. This right is given if a non-empty file named S6_FDHOLDER_LIST is found in the env/ subdirectory of one of the subdirectories checked by s6_accessrules_keycheck_uidgid().

•   Dump reading rights. This will be checked for clients wanting to copy the whole state of the server. This right is given if a non-empty file named S6_FDHOLDER_GETDUMP is found is the env/ subdirectory of one of the subdirectories checked by s6_accessrules_keycheck_uidgid(). This is very powerful: you should only give this right to ‘root’, or to a dedicated uid that is only used to perform dump transfers.

•   Dump writing rights. This will be checked for clients wanting to copy an entire set of file descriptors into the server. This right is given if a non-empty file named S6_FDHOLDER_SETDUMP is found is the env/ subdirectory of one of the subdirectories checked by s6_accessrules_keycheck_uidgid(). This is very powerful: you should only give this right to ‘root’, or to a dedicated uid that is only used to perform dump transfers.

OPTIONS

-1  Write a newline to stdout, and close stdout, right before entering the client-accepting loop. If stdout is suitably redirected, this can be used by monitoring programs to check when the server is accepting connections. See s6-notifywhenup(7) for more information on readiness notification.

-v verbosity
    Be more or less verbose. verbosity can be 0 (quiet), 1 (normal), or 2 or more (verbose).

-c maxconn
    Accept at most maxconn concurrent connections. Default is 16. It is impossible to set it higher than the value of the S6_FDHOLDER_MAX macro, i.e. 256. Client connections to this server are short-lived, so this number needs not be too high. Every client connection eats up one available file descriptor, so it is best for maxconn to be as small as possible.

-n maxfds
    Store at most maxfds file descriptors. Default is 1000. It is impossible to set it higher than the number of files that can be opened by the s6-fdholderd process, minus a few descriptors needed for correct operation. Before running s6-fdholderd, make sure to use s6-softlimit(8) to properly adjust the number of openable files[3] of the current process.

-t clienttimeout
    Disconnect a client if it's in the middle of an operation and it has not written or read any data in clienttimeout milliseconds. By default, clienttimeout is 0, which means infinite.

-t lameducktimeout
    Give clients lameducktimeout milliseconds to finish their current operation before exiting after receiving a SIGTERM. By default, lameducktimeout is 0, which means infinite.

-x rulesfile
    Read access rights configuration from CDB[1] file rulesfile.

-i rulesdir
    Read access rights configuration from the filesystem in directory rulesdir.

EXAMPLES
Assuming you want to run an s6-fdholderd daemon in the /service/fdholder directory with the -i rules option, you should:

•   Prepare the rules directory:

        mkdir /service/fdholder/rules
        cd /service/fdholder/rules
        mkdir uid gid

•   Allow a few users, or everyone, to connect. To allow root to connect:

        mkdir uid/0
        touch uid/0/allow

    To allow everyone to connect:

        mkdir uid/default
        touch uid/default/allow

Depending on your policy, you should now give certain rights to certain users or groups. For instance:

•   To allow user number 50 to perform dump transfers from and to this server:

        mkdir -p uid/50/env
        touch uid/50/allow
        echo > uid/50/env/S6_FDHOLDER_GETDUMP
        echo > uid/50/env/S6_FDHOLDER_SETDUMP

•   To allow user number 72 to store a descriptor under the name ‘foobar’ and only this name:

        mkdir -p uid/72/env
        touch uid/72/allow
        echo '^foobar$' > uid/72/env/S6_FDHOLDER_STORE_REGEX

•   To allow users having 23 as their primary group number to retrieve file descriptors with an identifier containing ‘foo’, then one character, then ‘bar’:

        mkdir -p gid/23/env
        touch gid/23/allow
        echo foo.bar > gid/23/env/S6_FDHOLDER_RETRIEVE_REGEX

•   To allow the same users to list all identifiers:

        echo > gid/23/env/S6_FDHOLDER_LIST

•   To allow everyone to dump entire states into the server ( never do this! it's only an example):

        mkdir -p uid/default/env
        touch uid/default/allow
        echo > uid/default/env/S6_FDHOLDER_SETDUMP

SEE ALSO
s6-fdholder-daemon(8), s6-fdholder-delete(8), s6-fdholder-getdump(8), s6-fdholder-list(8), s6-fdholder-retrieve(8), s6-fdholder-setdump(8), s6-fdholder-store(8), s6-fdholder-transferdump(8)

[1] https://en.wikipedia.org/wiki/Cdb_%28software%29

[2] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_04

[3] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_resource.h.html

This man page is ported from the authoritative documentation at: https://skarnet.org/software/s6/s6-fdholderd.html

AUTHORS
Laurent Bercot Alexis <flexibeast@gmail.com> (man page port)