s6

Mirror/fork of https://skarnet.org/software/s6/
git clone https://ccx.te2000.cz/git/s6
Log | Files | Refs | README | LICENSE

s6-sudod.html (9130B)


      1 <html>
      2   <head>
      3     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      5     <meta http-equiv="Content-Language" content="en" />
      6     <title>s6: the s6-sudod program</title>
      7     <meta name="Description" content="s6: the s6-sudod program" />
      8     <meta name="Keywords" content="s6 s6-sudod sudo setuid suid unix privilege gain getpeereid server" />
      9     <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
     10   </head>
     11 <body>
     12 
     13 <p>
     14 <a href="index.html">s6</a><br />
     15 <a href="//skarnet.org/software/">Software</a><br />
     16 <a href="//skarnet.org/">skarnet.org</a>
     17 </p>
     18 
     19 <h1> The <tt>s6-sudod</tt> program </h1>
     20 
     21 <p>
     22 <tt>s6-sudod</tt> receives command-line arguments, environment variables
     23 and standard descriptors from a peer <a href="s6-sudoc.html">s6-sudoc</a>
     24 program over a Unix socket, then forks another program.
     25 </p>
     26 
     27 <h2> Interface </h2>
     28 
     29 <pre>
     30      s6-sudod [ -0 ] [ -1 ] [ -2 ] [ -d ] [ -t <em>timeout</em> ] [ <em>sargv...</em> ]
     31 </pre>
     32 
     33 <ul>
     34  <li> s6-sudod gets 3 file descriptors via fd-passing over a Unix socket that
     35 must be open on its descriptors 0 and 1. (The received descriptors will be the
     36 stdin, stdout and stderr of the server program.) It expects a
     37 <a href="s6-sudoc.html">s6-sudoc</a> process to be sending them on the
     38 client side. </li>
     39  <li> It also receives a list of command-line arguments <em>cargv...</em>, and
     40 an environment <em>clientenv</em>. </li>
     41  <li> s6-sudod forks and executes <em>sargv...</em> <em>cargv</em>...
     42 The client command line is appended to the server command line. </li>
     43  <li> s6-sudod waits for its child to exit and transmits its exit code
     44 to the peer <a href="s6-sudoc.html">s6-sudoc</a> process. It then exits 0. </li>
     45 </ul>
     46 
     47 <h2> Environment </h2>
     48 
     49 <p>
     50 s6-sudod transmits its own environment to its child, plus the environment sent
     51 by <a href="s6-sudoc.html">s6-sudoc</a>, filtered in the following manner:
     52 for every variable sent by <a href="s6-sudoc.html">s6-sudoc</a>, if the
     53 variable is <strong>present but empty</strong> in s6-sudod's environment, then
     54 its value is overriden by the value given by s6-sudoc. A variable that is
     55 already nonempty, or that doesn't exist, in s6-sudod's environment, will not
     56 be transmitted to the child. In other words:
     57 </p>
     58 
     59 <ul>
     60  <li> If there's no variable <tt>X</tt> in s6-sudod's environment, the child
     61 will have no variable <tt>X</tt> defined </li>
     62  <li> If there's a non-empty variable <tt>X</tt> in s6-sudod's environment,
     63 the child will inherit that variable, with its value, from s6-sudod </li>
     64  <li> If there's an empty variable <tt>X</tt> in s6-sudod's environment,
     65 and s6-sudoc transmits variable <tt>X</tt>, then the child will inherit that
     66 variable with the value from s6-sudoc. (If s6-sudoc does not transmit <tt>X</tt>,
     67 the variable will be present, but empty, in the child's environment.) </li>
     68 </ul>
     69 
     70 <h2> Options </h2>
     71 
     72 <ul>
     73  <li> <tt>-0</tt>&nbsp;: do not inherit stdin from s6-sudoc. The child will be
     74 run with its stdin pointing to <tt>/dev/null</tt> instead. </li>
     75  <li> <tt>-1</tt>&nbsp;: do not inherit stdout from s6-sudoc. The child will be
     76 run with its stdout pointing to <tt>/dev/null</tt> instead. </li>
     77  <li> <tt>-2</tt>&nbsp;: do not inherit stderr from s6-sudoc. The child will be
     78 run with its stderr being a copy of s6-sudod's stderr instead. (This is useful
     79 to still log the child's error messages without sending them to the client.) </li>
     80  <li> <tt>-d</tt>&nbsp;: detach. The child will keep running until it naturally
     81 exits, even if the client disconnects. Setting this option also enforces
     82 <tt>-0</tt>, <tt>-1</tt> and <tt>-2</tt>. Bear in mind that this option
     83 relinquishes a lot of control over the child, and administrators should make sure
     84 it is appropriately short-lived. </li>
     85  <li> <tt>-t&nbsp;<em>timeout</em></tt>&nbsp;: if s6-sudod has not
     86 received all the needed data from the client after <em>timeout</em>
     87 milliseconds, it will exit without spawning a child. By default, <em>timeout</em>
     88 is 0, meaning infinite. This mechanism exists to protect the server from
     89 malicious or buggy clients that would uselessly consume resources. </li>
     90 </ul>
     91 
     92 <h2> Usage example </h2>
     93 
     94 <p>
     95  The typical use of s6-sudod is in a
     96 <a href="localservice.html">local service</a> with a
     97 <a href="s6-ipcserver.html">s6-ipcserver</a> process listening on a Unix
     98 socket, an <a href="s6-ipcserver-access.html">s6-ipcserver-access</a> process
     99 performing client authentication and access control, and possibly a
    100 <a href="s6-envdir.html">s6-envdir</a>
    101 process setting up the environment variables that will be accepted by
    102 s6-sudod. The following script, meant to be a <em>run script</em> in a
    103 <a href="servicedir.html">service directory</a>,
    104 will set up a privileged program:
    105 </p>
    106 
    107 <pre>
    108 #!/command/execlineb -P
    109 fdmove -c 2 1
    110 fdmove 1 3
    111 s6-envuidgid serveruser
    112 s6-ipcserver -U -1 -- serversocket
    113 s6-ipcserver-access -v2 -l0 -i rules --
    114 exec -c
    115 s6-envdir env
    116 s6-sudod
    117 sargv
    118 </pre>
    119 
    120 <ul>
    121  <li> <a href="//skarnet.org/software/execline/execlineb.html">execlineb</a>
    122 executes the script. </li>
    123  <li> <a href="//skarnet.org/software/execline/fdmove.html">fdmove</a> makes
    124 sure the script's error messages are sent to the service's logger. </li>
    125  <li> <a href="//skarnet.org/software/execline/fdmove.html">fdmove</a>
    126 redirects the script's stdout to file descriptor 3. This is useful if
    127 the service directory contains a <tt>notification-fd</tt> file containing
    128 <tt>3</tt>, so the daemon can perform
    129 <a href="notifywhenup.html">readiness notification</a> by writing a
    130 newline to its stdout. (The
    131 <tt>-1</tt> option to s6-ipcserver tells it to do this.) </li>
    132  <li> <a href="s6-envuidgid.html">s6-envuidgid</a>
    133 sets the UID, GID and GIDLIST environment variables for s6-ipcserver to interpret. </li>
    134  <li> <a href="s6-ipcserver.html">s6-ipcserver</a> binds to <em>serversocket</em>,
    135 drops its privileges to those of <em>serveruser</em>, and announces its
    136 readiness. Then, for every client connecting to <em>serversocket</em>:
    137   <ul>
    138    <li> <a href="s6-ipcserver-access.html">s6-ipcserver-access</a> checks the
    139 client's credentials according to the rules in directory <em>rules</em>.
    140    <li> <a href="//skarnet.org/software/execline/exec.html">exec -c</a>
    141 clears the environment. </li>
    142    <li> <a href="//skarnet.org/software/s6/s6-envdir.html">s6-envdir</a>
    143 sets environment variables according to the directory <em>env</em>. You can
    144 make sure that a variable VAR will be present but empty by performing
    145 <tt>echo > env/VAR</tt>. (A single newline is interpreted by s6-envdir as
    146 an empty variable; whereas if <tt>env/VAR</tt> is totally empty, then the
    147 VAR variable will be removed from the environment.) </li>
    148    <li> s6-sudod reads a command line <em>cargv</em>, a client environment
    149 and file descriptors over the socket. </li>
    150    <li> s6-sudod spawns <tt>sargv cargv</tt>. </li>
    151   </ul>
    152  (Actually, <a href="s6-ipcserver.html">s6-ipcserver</a> does not do this
    153 itself: it executes into other programs that each do one of the tasks. But for
    154 our example, it does not matter.) </li>
    155 </ul>
    156 
    157 <p>
    158  This means that user <em>clientuser</em> running
    159 <tt><a href="s6-sudo.html">s6-sudo</a> serversocket cargv</tt> will be
    160 able, if authorized by the configuration in <em>rules</em>, to run
    161 <tt>sargv cargv</tt> as user <em>serveruser</em>, with stdin,
    162 stdout, stderr and the environment variables properly listed in <em>env</em>
    163 transmitted to <em>sargv</em>.
    164 </p>
    165 
    166 <h2> Notes </h2>
    167 
    168 <ul>
    169  <li> If the <tt>-d</tt> option to s6-sudod has not been given, and
    170 s6-sudoc is killed (or exits after <em>timeoutrun</em> milliseconds)
    171 while the server program is still running, s6-sudod will send a SIGTERM and a
    172 SIGCONT to its child, then exit 1. However, sending a SIGTERM to the child
    173 does not guarantee that it will die; and
    174 if it keeps running, it might still read from the file that
    175 was s6-sudoc's stdin, or write to the files that were s6-sudoc's stdout or
    176 stderr. <strong>This is a potential security risk</strong>.
    177 Administrators should audit their server programs to make sure this does not
    178 happen. </li>
    179  <li> More generally, anything using signals or terminals will not be
    180 handled transparently by the s6-sudoc + s6-sudod mechanism. The mechanism
    181 was designed to allow programs to gain privileges in specific situations:
    182 short-lived, simple, noninteractive processes. It was not designed to emulate
    183 the full suid functionality and will not go out of its way to do so. </li>
    184  <li> Administrators should also make sure that it's not a problem if
    185 s6-sudod's child keeps running after the s6-sudoc client exits, if they
    186 have given the <tt>-d</tt> option to s6-sudod. In particular, they should
    187 study what happens if another connection to the same service occurs while
    188 an instance is still running. </li>
    189  <li> <em>sargv</em> may be empty. In that case, the client is in complete
    190 control of the command line executed as <em>serveruser</em>. This setup is
    191 permitted by s6-sudod, but it is very dangerous, and extreme attention should
    192 be paid to the construction of the s6-ipcserver-access rules. </li>
    193 </ul>
    194 
    195 </body>
    196 </html>