]> granicus.if.org Git - sudo/commitdiff
Replace the double fork with a fork + daemonize.
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 22 Jun 2008 20:19:42 +0000 (20:19 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 22 Jun 2008 20:19:42 +0000 (20:19 +0000)
config.h.in
configure
configure.in
logging.c

index 063b5d656a853fae43e3661d0ab82e419de3480a..6db9461ff19a16dce838622060e057fe0937947d 100644 (file)
 /* Define to 1 if you have the `setrlimit' function. */
 #undef HAVE_SETRLIMIT
 
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
 /* Define to 1 if you have the `set_auth_parameters' function. */
 #undef HAVE_SET_AUTH_PARAMETERS
 
index 2f53618adc0d20b0b9e1e0fd61c97f1b386c9cf3..3d7545394c4b2ff0fd89ab7c5c1b6a88755b53d0 100755 (executable)
--- a/configure
+++ b/configure
@@ -15506,9 +15506,10 @@ LIBS=$ac_save_LIBS
 
 
 
+
 for ac_func in strchr strrchr memchr memcpy memset sysconf tzset \
               strftime setrlimit initgroups getgroups fstat gettimeofday \
-              setlocale getaddrinfo
+              setlocale getaddrinfo setsid
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
 { echo "$as_me:$LINENO: checking for $ac_func" >&5
index eb68f969a4a72d5188965f7da412b3f956fac82f..1ac289554f5cf1add00f9207e7f2b75b25cdddb6 100644 (file)
@@ -1757,7 +1757,7 @@ dnl
 AC_FUNC_GETGROUPS
 AC_CHECK_FUNCS(strchr strrchr memchr memcpy memset sysconf tzset \
               strftime setrlimit initgroups getgroups fstat gettimeofday \
-              setlocale getaddrinfo)
+              setlocale getaddrinfo setsid)
 if test -z "$SKIP_SETRESUID"; then
     AC_CHECK_FUNCS(setresuid, [SKIP_SETREUID=yes])
 fi
index 4b29aa591e11b517446b8311c7b65d811623d7c9..57ac3cf8aba96ef3263eac5ca25a53ca1681b7f7 100644 (file)
--- a/logging.c
+++ b/logging.c
@@ -27,6 +27,7 @@
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <sys/wait.h>
 #include <stdio.h>
 #ifdef STDC_HEADERS
@@ -52,6 +53,7 @@
 #include <signal.h>
 #include <time.h>
 #include <errno.h>
+#include <fcntl.h>
 
 #include "sudo.h"
 
@@ -425,9 +427,9 @@ send_mail(line)
 {
     FILE *mail;
     char *p;
-    int pfd[2], status;
+    int fd, pfd[2], status;
     pid_t pid, rv;
-    sigaction_t sa, saved_sa_pipe;
+    sigaction_t sa;
 #ifndef NO_ROOT_MAILER
     static char *root_envp[] = {
        "HOME=/",
@@ -443,20 +445,32 @@ send_mail(line)
     if (!def_mailerpath || !def_mailto)
        return;
 
-    /* Fork a child so we can be asyncronous. */
+    /* Fork and return, child will daemonize. */
     switch (pid = fork()) {
        case -1:
            /* Error. */
            error(1, "cannot fork");
            break;
        case 0:
-           /* Child continues below. */
+           /* Child. */
+           switch (pid = fork()) {
+               case -1:
+                   /* Error. */
+                   mysyslog(LOG_ERR, "cannot fork: %m");
+                   _exit(1);
+               case 0:
+                   /* Grandchild continues below. */
+                   break;
+               default:
+                   /* Parent will wait for us. */
+                   _exit(0);
+           }
            break;
        default:
-           /* Parent waits and returns. */
+           /* Parent. */
            do {
-#ifdef sudo_waitpid
-               rv = sudo_waitpid(pid, &status, 0);
+#ifdef HAVE_WAITPID
+               rv = waitpid(pid, &status, 0);
 #else
                rv = wait(&status);
 #endif
@@ -464,36 +478,46 @@ send_mail(line)
            return;
     }
 
-    /* Fork again and orphan the grandchild so parent can continue. */
-    switch (pid = fork()) {
-       case -1:
-           /* Error. */
-           warning("cannot fork");
-           _exit(1);
-           break;
-       case 0:
-           /* Grandchild continues below. */
-           break;
-       default:
-           /* Orphan grandchild. */
-           _exit(0);
+    /* Daemonize - disassociate from session/tty. */
+#ifdef HAVE_SETSID
+    if (setsid() == -1)
+      warning("setsid");
+#else
+    setpgrp(0, 0);
+# ifdef TIOCNOTTY
+    if ((fd = open(_PATH_TTY, O_RDWR, 0644)) != -1) {
+       ioctl(fd, TIOCNOTTY, NULL);
+       close(fd);
+    }
+# endif
+#endif
+    chdir("/");
+    if ((fd = open(_PATH_DEVNULL, O_RDWR, 0644)) != -1) {
+       (void) dup2(fd, STDIN_FILENO);
+       (void) dup2(fd, STDOUT_FILENO);
+       (void) dup2(fd, STDERR_FILENO);
     }
 
+    /* Close password, group and other fds so we don't leak. */
+    sudo_endpwent();
+    sudo_endgrent();
+    closefrom(STDERR_FILENO + 1);
+
     /* Ignore SIGPIPE in case mailer exits prematurely (or is missing). */
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = 0;
     sa.sa_handler = SIG_IGN;
-    (void) sigaction(SIGPIPE, &sa, &saved_sa_pipe);
+    (void) sigaction(SIGPIPE, &sa, NULL);
 
     if (pipe(pfd) == -1) {
-       warning("cannot open pipe");
+       mysyslog(LOG_ERR, "cannot open pipe: %m");
        _exit(1);
     }
 
     switch (pid = fork()) {
        case -1:
            /* Error. */
-           warning("cannot fork");
+           mysyslog(LOG_ERR, "cannot fork: %m");
            _exit(1);
            break;
        case 0:
@@ -502,7 +526,7 @@ send_mail(line)
                char *mpath, *mflags;
                int i;
 
-               /* Great-grandchild, set stdin to output side of the pipe */
+               /* Child, set stdin to output side of the pipe */
                if (pfd[0] != STDIN_FILENO) {
                    (void) dup2(pfd[0], STDIN_FILENO);
                    (void) close(pfd[0]);
@@ -525,11 +549,6 @@ send_mail(line)
                }
                argv[i] = NULL;
 
-               /* Close password, group and other fds so we don't leak. */
-               sudo_endpwent();
-               sudo_endgrent();
-               closefrom(STDERR_FILENO + 1);
-
                /*
                 * Depending on the config, either run the mailer as root
                 * (so user cannot kill it) or as the user (for the paranoid).
@@ -541,6 +560,7 @@ send_mail(line)
                set_perms(PERM_FULL_USER);
                execv(mpath, argv);
 #endif /* NO_ROOT_MAILER */
+               mysyslog(LOG_ERR, "cannot execute %s: %m", mpath);
                _exit(127);
            }
            break;
@@ -573,13 +593,13 @@ send_mail(line)
        get_timestr(), user_name, line);
     fclose(mail);
     do {
-#ifdef sudo_waitpid
-        rv = sudo_waitpid(pid, &status, 0);
+#ifdef HAVE_WAITPID
+        rv = waitpid(pid, &status, 0);
 #else
         rv = wait(&status);
 #endif
     } while (rv == -1 && errno == EINTR);
-    (void) sigaction(SIGPIPE, &saved_sa_pipe, NULL);
+    _exit(0);
 }
 
 /*