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> : 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> : 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> : 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> : 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 <em>timeout</em></tt> : 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>