• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***
2   This file is part of libdaemon.
3 
4   Copyright 2003-2008 Lennart Poettering
5 
6   Permission is hereby granted, free of charge, to any person obtaining a copy
7   of this software and associated documentation files (the "Software"), to deal
8   in the Software without restriction, including without limitation the rights
9   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10   copies of the Software, and to permit persons to whom the Software is
11   furnished to do so, subject to the following conditions:
12 
13   The above copyright notice and this permission notice shall be included in
14   all copies or substantial portions of the Software.
15 
16   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   SOFTWARE.
23 
24 ***/
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <sys/stat.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <sys/wait.h>
39 #include <assert.h>
40 #include <sys/ioctl.h>
41 #include <signal.h>
42 #include <sys/time.h>
43 #include <sys/resource.h>
44 #include <dirent.h>
45 
46 #include "dfork.h"
47 #include "dnonblock.h"
48 #include "dlog.h"
49 
50 #if defined(_NSIG) /* On glibc NSIG does not count RT signals */
51 # define SIGNAL_UPPER_BOUND _NSIG
52 #elif defined(NSIG) /* Solaris defines just this */
53 # define SIGNAL_UPPER_BOUND NSIG
54 #else
55 # error "Unknown upper bound for signals"
56 #endif
57 
58 static int _daemon_retval_pipe[2] = { -1, -1 };
59 
_null_open(int f,int fd)60 static int _null_open(int f, int fd) {
61     int fd2;
62 
63     if ((fd2 = open("/dev/null", f)) < 0)
64         return -1;
65 
66     if (fd2 == fd)
67         return fd;
68 
69     if (dup2(fd2, fd) < 0)
70         return -1;
71 
72     close(fd2);
73     return fd;
74 }
75 
atomic_read(int fd,void * d,size_t l)76 static ssize_t atomic_read(int fd, void *d, size_t l) {
77     ssize_t t = 0;
78 
79     while (l > 0) {
80         ssize_t r;
81 
82         if ((r = read(fd, d, l)) <= 0) {
83 
84             if (r < 0)
85                 return t > 0 ? t : -1;
86             else
87                 return t;
88         }
89 
90         t += r;
91         d = (char*) d + r;
92         l -= r;
93     }
94 
95     return t;
96 }
97 
atomic_write(int fd,const void * d,size_t l)98 static ssize_t atomic_write(int fd, const void *d, size_t l) {
99     ssize_t t = 0;
100 
101     while (l > 0) {
102         ssize_t r;
103 
104         if ((r = write(fd, d, l)) <= 0) {
105 
106             if (r < 0)
107                 return t > 0 ? t : -1;
108             else
109                 return t;
110         }
111 
112         t += r;
113         d = (const char*) d + r;
114         l -= r;
115     }
116 
117     return t;
118 }
119 
move_fd_up(int * fd)120 static int move_fd_up(int *fd) {
121     assert(fd);
122 
123     while (*fd <= 2) {
124         if ((*fd = dup(*fd)) < 0) {
125             daemon_log(LOG_ERR, "dup(): %s", strerror(errno));
126             return -1;
127         }
128     }
129 
130     return 0;
131 }
132 
sigchld(int s)133 static void sigchld(int s) {
134 }
135 
daemon_fork(void)136 pid_t daemon_fork(void) {
137     pid_t pid;
138     int pipe_fds[2] = {-1, -1};
139     struct sigaction sa_old, sa_new;
140     sigset_t ss_old, ss_new;
141     int saved_errno;
142 
143     memset(&sa_new, 0, sizeof(sa_new));
144     sa_new.sa_handler = sigchld;
145     sa_new.sa_flags = SA_RESTART;
146 
147     if (sigemptyset(&ss_new) < 0) {
148         daemon_log(LOG_ERR, "sigemptyset() failed: %s", strerror(errno));
149         return (pid_t) -1;
150     }
151 
152     if (sigaddset(&ss_new, SIGCHLD) < 0) {
153         daemon_log(LOG_ERR, "sigaddset() failed: %s", strerror(errno));
154         return (pid_t) -1;
155     }
156 
157     if (sigaction(SIGCHLD, &sa_new, &sa_old) < 0) {
158         daemon_log(LOG_ERR, "sigaction() failed: %s", strerror(errno));
159         return (pid_t) -1;
160     }
161 
162     if (sigprocmask(SIG_UNBLOCK, &ss_new, &ss_old) < 0) {
163         daemon_log(LOG_ERR, "sigprocmask() failed: %s", strerror(errno));
164 
165         saved_errno = errno;
166         sigaction(SIGCHLD, &sa_old, NULL);
167         errno = saved_errno;
168 
169         return (pid_t) -1;
170     }
171 
172     if (pipe(pipe_fds) < 0) {
173         daemon_log(LOG_ERR, "pipe() failed: %s", strerror(errno));
174 
175         saved_errno = errno;
176         sigaction(SIGCHLD, &sa_old, NULL);
177         sigprocmask(SIG_SETMASK, &ss_old, NULL);
178         errno = saved_errno;
179 
180         return (pid_t) -1;
181     }
182 
183     if ((pid = fork()) < 0) { /* First fork */
184         daemon_log(LOG_ERR, "First fork() failed: %s", strerror(errno));
185 
186         saved_errno = errno;
187         close(pipe_fds[0]);
188         close(pipe_fds[1]);
189         sigaction(SIGCHLD, &sa_old, NULL);
190         sigprocmask(SIG_SETMASK, &ss_old, NULL);
191         errno = saved_errno;
192 
193         return (pid_t) -1;
194 
195     } else if (pid == 0) {
196         pid_t dpid;
197 
198         /* First child. Now we are sure not to be a session leader or
199          * process group leader anymore, i.e. we know that setsid()
200          * will succeed. */
201 
202         if (daemon_log_use & DAEMON_LOG_AUTO)
203             daemon_log_use = DAEMON_LOG_SYSLOG;
204 
205         if (close(pipe_fds[0]) < 0) {
206             daemon_log(LOG_ERR, "close() failed: %s", strerror(errno));
207             goto fail;
208         }
209 
210         /* Move file descriptors up*/
211         if (move_fd_up(&pipe_fds[1]) < 0)
212             goto fail;
213 
214         if (_daemon_retval_pipe[0] >= 0 && move_fd_up(&_daemon_retval_pipe[0]) < 0)
215             goto fail;
216         if (_daemon_retval_pipe[1] >= 0 && move_fd_up(&_daemon_retval_pipe[1]) < 0)
217             goto fail;
218 
219         if (_null_open(O_RDONLY, 0) < 0) {
220             daemon_log(LOG_ERR, "Failed to open /dev/null for STDIN: %s", strerror(errno));
221             goto fail;
222         }
223 
224         if (_null_open(O_WRONLY, 1) < 0) {
225             daemon_log(LOG_ERR, "Failed to open /dev/null for STDOUT: %s", strerror(errno));
226             goto fail;
227         }
228 
229         if (_null_open(O_WRONLY, 2) < 0) {
230             daemon_log(LOG_ERR, "Failed to open /dev/null for STDERR: %s", strerror(errno));
231             goto fail;
232         }
233 
234         /* Create a new session. This will create a new session and a
235          * new process group for us and we will be the ledaer of
236          * both. This should always succeed because we cannot be the
237          * process group leader because we just forked. */
238         if (setsid() < 0) {
239             daemon_log(LOG_ERR, "setsid() failed: %s", strerror(errno));
240             goto fail;
241         }
242 
243         umask(0077);
244 
245         if (chdir("/") < 0) {
246             daemon_log(LOG_ERR, "chdir() failed: %s", strerror(errno));
247             goto fail;
248         }
249 
250         if ((pid = fork()) < 0) { /* Second fork */
251             daemon_log(LOG_ERR, "Second fork() failed: %s", strerror(errno));
252             goto fail;
253 
254         } else if (pid == 0) {
255             /* Second child. Our father will exit right-away. That way
256              * we can be sure that we are a child of init now, even if
257              * the process which spawned us stays around for a longer
258              * time. Also, since we are no session leader anymore we
259              * can be sure that we will never acquire a controlling
260              * TTY. */
261 
262             if (sigaction(SIGCHLD, &sa_old, NULL) < 0) {
263                 daemon_log(LOG_ERR, "close() failed: %s", strerror(errno));
264                 goto fail;
265             }
266 
267             if (sigprocmask(SIG_SETMASK, &ss_old, NULL) < 0) {
268                 daemon_log(LOG_ERR, "sigprocmask() failed: %s", strerror(errno));
269                 goto fail;
270             }
271 
272             if (signal(SIGTTOU, SIG_IGN) == SIG_ERR) {
273                 daemon_log(LOG_ERR, "signal(SIGTTOU, SIG_IGN) failed: %s", strerror(errno));
274                 goto fail;
275             }
276 
277             if (signal(SIGTTIN, SIG_IGN) == SIG_ERR) {
278                 daemon_log(LOG_ERR, "signal(SIGTTIN, SIG_IGN) failed: %s", strerror(errno));
279                 goto fail;
280             }
281 
282             if (signal(SIGTSTP, SIG_IGN) == SIG_ERR) {
283                 daemon_log(LOG_ERR, "signal(SIGTSTP, SIG_IGN) failed: %s", strerror(errno));
284                 goto fail;
285             }
286 
287             dpid = getpid();
288             if (atomic_write(pipe_fds[1], &dpid, sizeof(dpid)) != sizeof(dpid)) {
289                 daemon_log(LOG_ERR, "write() failed: %s", strerror(errno));
290                 goto fail;
291             }
292 
293             if (close(pipe_fds[1]) < 0) {
294                 daemon_log(LOG_ERR, "close() failed: %s", strerror(errno));
295                 goto fail;
296             }
297 
298             return 0;
299 
300         } else {
301             /* Second father */
302             close(pipe_fds[1]);
303             _exit(0);
304         }
305 
306     fail:
307         dpid = (pid_t) -1;
308 
309         if (atomic_write(pipe_fds[1], &dpid, sizeof(dpid)) != sizeof(dpid))
310             daemon_log(LOG_ERR, "Failed to write error PID: %s", strerror(errno));
311 
312         close(pipe_fds[1]);
313         _exit(0);
314 
315     } else {
316         /* First father */
317         pid_t dpid;
318 
319         close(pipe_fds[1]);
320 
321         if (waitpid(pid, NULL, WUNTRACED) < 0) {
322             saved_errno = errno;
323             close(pipe_fds[0]);
324             sigaction(SIGCHLD, &sa_old, NULL);
325             sigprocmask(SIG_SETMASK, &ss_old, NULL);
326             errno = saved_errno;
327             return -1;
328         }
329 
330         sigprocmask(SIG_SETMASK, &ss_old, NULL);
331         sigaction(SIGCHLD, &sa_old, NULL);
332 
333         if (atomic_read(pipe_fds[0], &dpid, sizeof(dpid)) != sizeof(dpid)) {
334             daemon_log(LOG_ERR, "Failed to read daemon PID.");
335             dpid = (pid_t) -1;
336             errno = EINVAL;
337         } else if (dpid == (pid_t) -1)
338             errno = EIO;
339 
340         saved_errno = errno;
341         close(pipe_fds[0]);
342         errno = saved_errno;
343 
344         return dpid;
345     }
346 }
347 
daemon_retval_init(void)348 int daemon_retval_init(void) {
349 
350     if (_daemon_retval_pipe[0] < 0 || _daemon_retval_pipe[1] < 0) {
351 
352         if (pipe(_daemon_retval_pipe) < 0) {
353             daemon_log(LOG_ERR, "pipe(): %s", strerror(errno));
354             return -1;
355         }
356     }
357 
358     return 0;
359 }
360 
daemon_retval_done(void)361 void daemon_retval_done(void) {
362     int saved_errno = errno;
363 
364     if (_daemon_retval_pipe[0] >= 0)
365         close(_daemon_retval_pipe[0]);
366 
367     if (_daemon_retval_pipe[1] >= 0)
368         close(_daemon_retval_pipe[1]);
369 
370     _daemon_retval_pipe[0] = _daemon_retval_pipe[1] = -1;
371 
372     errno = saved_errno;
373 }
374 
daemon_retval_send(int i)375 int daemon_retval_send(int i) {
376     ssize_t r;
377 
378     if (_daemon_retval_pipe[1] < 0) {
379         errno = EINVAL;
380         return -1;
381     }
382 
383     r = atomic_write(_daemon_retval_pipe[1], &i, sizeof(i));
384 
385     daemon_retval_done();
386 
387     if (r != sizeof(i)) {
388 
389         if (r < 0)
390             daemon_log(LOG_ERR, "write() failed while writing return value to pipe: %s", strerror(errno));
391         else {
392             daemon_log(LOG_ERR, "write() too short while writing return value from pipe");
393             errno = EINVAL;
394         }
395 
396         return -1;
397     }
398 
399     return 0;
400 }
401 
daemon_retval_wait(int timeout)402 int daemon_retval_wait(int timeout) {
403     ssize_t r;
404     int i;
405 
406     if (timeout > 0) {
407         struct timeval tv;
408         int s;
409         fd_set fds;
410 
411         tv.tv_sec = timeout;
412         tv.tv_usec = 0;
413 
414         FD_ZERO(&fds);
415         FD_SET(_daemon_retval_pipe[0], &fds);
416 
417         if ((s = select(FD_SETSIZE, &fds, 0, 0, &tv)) != 1) {
418 
419             if (s < 0)
420                 daemon_log(LOG_ERR, "select() failed while waiting for return value: %s", strerror(errno));
421             else {
422                 errno = ETIMEDOUT;
423                 daemon_log(LOG_ERR, "Timeout reached while wating for return value");
424             }
425 
426             return -1;
427         }
428     }
429 
430     if ((r = atomic_read(_daemon_retval_pipe[0], &i, sizeof(i))) != sizeof(i)) {
431 
432         if (r < 0)
433             daemon_log(LOG_ERR, "read() failed while reading return value from pipe: %s", strerror(errno));
434         else if (r == 0) {
435             daemon_log(LOG_ERR, "read() failed with EOF while reading return value from pipe.");
436             errno = EINVAL;
437         } else if (r > 0) {
438             daemon_log(LOG_ERR, "read() too short while reading return value from pipe.");
439             errno = EINVAL;
440         }
441 
442         return -1;
443     }
444 
445     daemon_retval_done();
446 
447     return i;
448 }
449 
daemon_close_all(int except_fd,...)450 int daemon_close_all(int except_fd, ...) {
451     va_list ap;
452     int n = 0, i, r;
453     int *p;
454     int saved_errno;
455 
456     va_start(ap, except_fd);
457 
458     if (except_fd >= 0)
459         for (n = 1; va_arg(ap, int) >= 0; n++)
460             ;
461 
462     va_end(ap);
463 
464     if (!(p = malloc(sizeof(int) * (n+1))))
465         return -1;
466 
467     va_start(ap, except_fd);
468 
469     i = 0;
470     if (except_fd >= 0) {
471         int fd;
472         p[i++] = except_fd;
473 
474         while ((fd = va_arg(ap, int)) >= 0)
475             p[i++] = fd;
476     }
477     p[i] = -1;
478 
479     va_end(ap);
480 
481     r = daemon_close_allv(p);
482 
483     saved_errno = errno;
484     free(p);
485     errno = saved_errno;
486 
487     return r;
488 }
489 
490 /** Same as daemon_close_all but takes an array of fds, terminated by -1 */
daemon_close_allv(const int except_fds[])491 int daemon_close_allv(const int except_fds[]) {
492     struct rlimit rl;
493     int fd, maxfd;
494 
495 #ifdef __linux__
496     int saved_errno;
497 
498     DIR *d;
499 
500     if ((d = opendir("/proc/self/fd"))) {
501 
502         struct dirent *de;
503 
504         while ((de = readdir(d))) {
505             int found;
506             long l;
507             char *e = NULL;
508             int i;
509 
510             if (de->d_name[0] == '.')
511                 continue;
512 
513             errno = 0;
514             l = strtol(de->d_name, &e, 10);
515             if (errno != 0 || !e || *e) {
516                 closedir(d);
517                 errno = EINVAL;
518                 return -1;
519             }
520 
521             fd = (int) l;
522 
523             if ((long) fd != l) {
524                 closedir(d);
525                 errno = EINVAL;
526                 return -1;
527             }
528 
529             if (fd < 3)
530                 continue;
531 
532             if (fd == dirfd(d))
533                 continue;
534 
535             if (fd == _daemon_retval_pipe[1])
536                 continue;
537 
538             found = 0;
539             for (i = 0; except_fds[i] >= 0; i++)
540                 if (except_fds[i] == fd) {
541                     found = 1;
542                     break;
543                 }
544 
545             if (found)
546                 continue;
547 
548             if (close(fd) < 0) {
549                 saved_errno = errno;
550                 closedir(d);
551                 errno = saved_errno;
552 
553                 return -1;
554             }
555 
556             if (fd == _daemon_retval_pipe[0])
557                 _daemon_retval_pipe[0] = -1;    /* mark as closed */
558         }
559 
560         closedir(d);
561         return 0;
562     }
563 
564 #endif
565 
566     if (getrlimit(RLIMIT_NOFILE, &rl) > 0)
567         maxfd = (int) rl.rlim_max;
568     else
569         maxfd = sysconf(_SC_OPEN_MAX);
570 
571     for (fd = 3; fd < maxfd; fd++) {
572         int i, found;
573 
574         if (fd == _daemon_retval_pipe[1])
575             continue;
576 
577         found = 0;
578         for (i = 0; except_fds[i] >= 0; i++)
579             if (except_fds[i] == fd) {
580                 found = 1;
581                 break;
582             }
583 
584         if (found)
585             continue;
586 
587         if (close(fd) < 0 && errno != EBADF)
588             return -1;
589 
590         if (fd == _daemon_retval_pipe[0])
591             _daemon_retval_pipe[0] = -1;        /* mark as closed */
592     }
593 
594     return 0;
595 }
596 
daemon_unblock_sigs(int except,...)597 int daemon_unblock_sigs(int except, ...) {
598     va_list ap;
599     int n = 0, i, r;
600     int *p;
601     int saved_errno;
602 
603     va_start(ap, except);
604 
605     if (except >= 1)
606         for (n = 1; va_arg(ap, int) >= 0; n++)
607             ;
608 
609     va_end(ap);
610 
611     if (!(p = malloc(sizeof(int) * (n+1))))
612         return -1;
613 
614     va_start(ap, except);
615 
616     i = 0;
617     if (except >= 1) {
618         int sig;
619         p[i++] = except;
620 
621         while ((sig = va_arg(ap, int)) >= 0)
622             p[i++] = sig;
623     }
624     p[i] = -1;
625 
626     va_end(ap);
627 
628     r = daemon_unblock_sigsv(p);
629 
630     saved_errno = errno;
631     free(p);
632     errno = saved_errno;
633 
634     return r;
635 }
636 
daemon_unblock_sigsv(const int except[])637 int daemon_unblock_sigsv(const int except[]) {
638     int i;
639     sigset_t ss;
640 
641     if (sigemptyset(&ss) < 0)
642         return -1;
643 
644     for (i = 0; except[i] > 0; i++)
645         if (sigaddset(&ss, except[i]) < 0)
646             return -1;
647 
648     return sigprocmask(SIG_SETMASK, &ss, NULL);
649 }
650 
daemon_reset_sigs(int except,...)651 int daemon_reset_sigs(int except, ...) {
652     va_list ap;
653     int n = 0, i, r;
654     int *p;
655     int saved_errno;
656 
657     va_start(ap, except);
658 
659     if (except >= 1)
660         for (n = 1; va_arg(ap, int) >= 0; n++)
661             ;
662 
663     va_end(ap);
664 
665     if (!(p = malloc(sizeof(int) * (n+1))))
666         return -1;
667 
668     va_start(ap, except);
669 
670     i = 0;
671     if (except >= 1) {
672         int sig;
673         p[i++] = except;
674 
675         while ((sig = va_arg(ap, int)) >= 0)
676             p[i++] = sig;
677     }
678     p[i] = -1;
679 
680     va_end(ap);
681 
682     r = daemon_reset_sigsv(p);
683 
684     saved_errno = errno;
685     free(p);
686     errno = saved_errno;
687 
688     return r;
689 }
690 
daemon_reset_sigsv(const int except[])691 int daemon_reset_sigsv(const int except[]) {
692     int sig;
693 
694     for (sig = 1; sig < SIGNAL_UPPER_BOUND; sig++) {
695         int reset = 1;
696 
697         switch (sig) {
698             case SIGKILL:
699             case SIGSTOP:
700                 reset = 0;
701                 break;
702 
703             default: {
704                 int i;
705 
706                 for (i = 0; except[i] > 0; i++) {
707                     if (sig == except[i]) {
708                         reset = 0;
709                         break;
710                     }
711                 }
712             }
713         }
714 
715         if (reset) {
716             struct sigaction sa;
717 
718             memset(&sa, 0, sizeof(sa));
719             sa.sa_handler = SIG_DFL;
720 
721             /* On Linux the first two RT signals are reserved by
722              * glibc, and sigaction() will return EINVAL for them. */
723             if ((sigaction(sig, &sa, NULL) < 0))
724                 if (errno != EINVAL)
725                     return -1;
726         }
727     }
728 
729     return 0;
730 }
731