]> git.proxmox.com Git - swtpm.git/blob - src/swtpm/daemonize.c
swtpm: Add missing signal.h include (BSDs)
[swtpm.git] / src / swtpm / daemonize.c
1 /*
2 * daemonize.c -- Utility functions for race-free daemonization
3 *
4 * (c) Two Sigma Open Source, LLC 2021.
5 *
6 * Author: Nicolas Williams <nico@twosigma.com>
7 *
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
12 * met:
13 *
14 * Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
16 *
17 * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * Neither the names of the IBM Corporation nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include "config.h"
39
40 #include "daemonize.h"
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <sys/wait.h>
44 #include <fcntl.h>
45 #include <errno.h>
46 #include <signal.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51
52 /*
53 * daemon(3) is racy because it fork()s and exits in the parent before the
54 * child can get ready to provide its services.
55 *
56 * Not every daemon can set up services before calling daemon(3), as some
57 * APIs are not fork-safe and must be called in the child-side of the
58 * daemon(3)'s fork() calls.
59 *
60 * Even if a daemon can set up services before calling daemon(3), it will not
61 * be able to write the correct PID into a pidfile until after daemon(3)
62 * returns.
63 *
64 * E.g.,
65 *
66 * #!/bin/bash
67 *
68 * # Start a service:
69 * some-serviced --daemon --pid=... ...
70 *
71 * # Call it:
72 * call-some-service ping || echo "oops, we won the race but lost the game"
73 *
74 * To address this we split daemon(3) into two functions, daemonize_prep() and
75 * daemonize_finish(). A daemon program should call daemonize_prep() early
76 * when it knows it will have to daemonize (e.g., because of a --daemon
77 * command-line option), then it should do all the setup required to start
78 * providing its services, then it should call daemonize_finish().
79 *
80 * These two functions do all that daemon(3) does, but in two phases so that
81 * the original process that calls daemonize_prep() does not exit until the
82 * service is ready.
83 *
84 * daemonize_prep() calls fork(), setsid(), and then forks again, and returns
85 * in the grandchild, but exits in the original and middle processes when the
86 * grandchild calls daemonize_finish().
87 *
88 * How to use this:
89 *
90 * if (daemonize) {
91 * pid_t old_pid, new_pid;
92 *
93 * old_pid = getpid();
94 * if (daemonize_prep() == -1)
95 * err(1, "Failed to daemonize");
96 *
97 * // We're now in a grandchild, but the original parent should still be
98 * // waiting.
99 * new_pid = getpid();
100 * assert(old_pid != new_pid);
101 * }
102 *
103 * // setup sockets, listen() on them, etc...
104 * my_setup_service_and_listen_on_sockets();
105 *
106 * // Tell the waiting parent and grandparent that we're ready:
107 * // (doing this even if daemonize_prep() wasn't called is ok)
108 * daemonize_finish();
109 *
110 * // daemonize_finish() did not fork() again:
111 * assert(new_pid == getpid());
112 *
113 * Note: the processes that exit will use _exit(). The process that
114 * daemonize_prep() returns to should be able to use exit().
115 */
116
117 static int devnullfd = -1;
118 static int pfd = -1;
119
120 static int
121 wait_or_die_like_it(pid_t pid)
122 {
123 int status;
124
125 while (waitpid(pid, &status, 0) == -1) {
126 if (errno == EINTR)
127 continue;
128 /* XXX Should just use err(3). */
129 fprintf(stderr, "waitpid() failed: %s\n", strerror(errno));
130 fflush(stderr);
131 _exit(1);
132 }
133 if (WIFSIGNALED(status)) {
134 /*
135 * Child died in a fire; die like it so the parent sees the same exit
136 * status.
137 */
138 kill(getpid(), WTERMSIG(status));
139 }
140 if (!WIFEXITED(status)) {
141 /* If fire doesn't kill us, _exit(). */
142 _exit(1);
143 }
144 /* Child exited willingly. */
145 return WEXITSTATUS(status);
146 }
147
148 /*
149 * Prepare to daemonize. When ready, the caller should call
150 * daemonize_finish().
151 *
152 * This arranges for the parent to exit when and only when the child is ready
153 * to service clients.
154 *
155 * This forks a grandchild and returns in the grandchild
156 * but exits in the parent and grandparent, but only once the child calls
157 * daemonize_finish() (or exits/dies, whichever comes first).
158 *
159 * Because the parent side of the fork() calls _exit(), the child can exit().
160 *
161 * Returns -1 on error (sets errno), 0 on success.
162 */
163 int
164 daemonize_prep(void)
165 {
166 ssize_t bytes;
167 char buf;
168 int save_errno = errno;
169 int pfds[2] = { -1, -1 };
170 pid_t pid;
171
172 /*
173 * Be idempotent. If called twice because, e.g., --daemon is given twice,
174 * do nothing the second time.
175 */
176 if (pfd != -1)
177 return 0;
178
179 /* Grand parent process. */
180 fflush(stdout);
181 fflush(stderr);
182 pid = fork();
183 if (pid == (pid_t)-1) {
184 fprintf(stderr, "Failed to daemonize: Failed to fork: %s\n",
185 strerror(errno));
186 return -1;
187 }
188
189 if (pid != 0) {
190 /*
191 * Grand parent process: exit when the grandchild is ready or die in
192 * the same way.
193 */
194 _exit(wait_or_die_like_it(pid));
195 }
196
197 /* Intermediate process. Detach from tty, fork() again. */
198 if (setsid() == -1) {
199 fprintf(stderr, "Failed to daemonize: Failed to detach from tty: %s\n",
200 strerror(errno));
201 _exit(1);
202 }
203
204 /* Set things up so the grandchild can finish daemonizing. */
205 devnullfd = open("/dev/null", O_RDWR);
206 if (devnullfd == -1) {
207 fprintf(stderr, "Failed to daemonize: Could not open /dev/null: %s\n",
208 strerror(errno));
209 _exit(1);
210 }
211 if (pipe(pfds) == -1) {
212 fprintf(stderr, "Failed to daemonize: Could not make a pipe: %s\n",
213 strerror(errno));
214 _exit(1);
215 }
216 pfd = pfds[1];
217
218 /* Fork the grandchild so it cannot get a controlling tty by accident. */
219 pid = fork();
220 if (pid == (pid_t)-1) {
221 fprintf(stderr, "Failed to daemonize: Could not fork: %s\n",
222 strerror(errno));
223 _exit(1);
224 }
225 if (pid != 0) {
226 /*
227 * Middle process.
228 *
229 * Wait for ready notification from the child, then _exit()
230 * accordingly.
231 */
232 (void) close(pfds[1]);
233 do {
234 bytes = read(pfds[0], &buf, sizeof(buf));
235 } while (bytes == -1 && errno == EINTR);
236 if (bytes < 0) {
237 fprintf(stderr, "Failed to daemonize: "
238 "Error reading from pipe: %s\n", strerror(errno));
239 /* Let init reap the grandchild. */
240 _exit(1);
241 }
242 if (bytes == 0) {
243 /* Die like the grandchild. */
244 _exit(wait_or_die_like_it(pid));
245 }
246 /* Ready! */
247 _exit(0);
248 }
249
250 /*
251 * We're on the grandchild side now, and we'll return with the expectation
252 * that the caller will call daemonize_finish(). The parent, which will
253 * continue executing this function, will _exit() when the child indicates
254 * that it is ready.
255 */
256 (void) close(pfds[0]);
257 errno = save_errno;
258 return 0;
259 }
260
261 /*
262 * Indicate that the service is now ready.
263 *
264 * Will cause the ancestor processes waiting in daemonize_prep() to _exit().
265 */
266 void
267 daemonize_finish(void)
268 {
269 ssize_t bytes;
270 int save_errno = errno;
271
272 /* pfds[1] will be > -1 IFF daemonize_prep() was called */
273 if (pfd == -1) {
274 return;
275 }
276
277 if (chdir("/") == -1) {
278 fprintf(stderr, "Failed to change directory to /: %s\n",
279 strerror(errno));
280 fflush(stderr);
281 exit(1);
282 }
283 if (dup2(devnullfd, STDOUT_FILENO) == -1) {
284 fprintf(stderr, "Failed to redirect output stream to /dev/null: %s\n",
285 strerror(errno));
286 fflush(stderr);
287 exit(1);
288 }
289 if (dup2(devnullfd, STDERR_FILENO) == -1) {
290 fprintf(stderr, "Failed to redirect error stream to /dev/null: %s\n",
291 strerror(errno));
292 fflush(stderr);
293 exit(1);
294 }
295 (void) close(devnullfd);
296 devnullfd = -1;
297
298 do {
299 bytes = write(pfd, "", sizeof(""));
300 } while (bytes == -1 && errno == EINTR);
301 if (bytes <= 0) {
302 /* There's no point writing to stderr now that it goes to /dev/null */
303 exit(1);
304 }
305 (void) close(pfd);
306 pfd = -1;
307 errno = save_errno;
308 }