]> granicus.if.org Git - sudo/commitdiff
Detach from tracee on SIGHUP, SIGINT and SIGTERM. Now "sudo reboot"
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 5 Oct 2004 19:13:56 +0000 (19:13 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 5 Oct 2004 19:13:56 +0000 (19:13 +0000)
doesn't cause reboot to inadvertanly kill itself.

mon_systrace.c
mon_systrace.h

index 27c265c3e31168f8ae45136412e3a8aaad785af4..55ea73e8312ed91b1ff1c3e3c4ffd87a46937485 100644 (file)
@@ -86,18 +86,16 @@ bad:
 }
 
 static void
-sigusr1(signo)
+catchsig(signo)
     int signo;
 {
+    dodetach = signo;
     return;
 }
 
 /*
- * Fork a process that traces the command to be run and its descendents.
- *
- * TODO:
- *     should the tracing process catch signals and detach?
- *     (right now "sudo reboot" fails due to tracing)
+ * Fork a process that monitors the command to be run and its descendents.
+ * The monitoring process will detach upon receipt of SIGHUP, SIGINT or SIGTERM.
  */
 void
 systrace_attach(pid)
@@ -124,7 +122,7 @@ systrace_attach(pid)
        err(1, "sigprocmask");
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = 0;
-    sa.sa_handler = sigusr1;
+    sa.sa_handler = catchsig;
     if (sigaction(SIGUSR1, &sa, &osa) != 0)
        err(1, "sigaction");
 
@@ -146,14 +144,22 @@ systrace_attach(pid)
        return;
     }
 
-    /* reset signal state for tracer */
+    /* set signal state for tracer */
+    dodetach = 0;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = catchsig;
     if (sigaction(SIGUSR1, &osa, NULL) != 0 ||
+       sigaction(SIGHUP, &sa, NULL) != 0 ||
+       sigaction(SIGINT, &sa, NULL) != 0 ||
+       sigaction(SIGTERM, &sa, NULL) != 0 ||
        sigprocmask(SIG_SETMASK, &oset, NULL) != 0) {
        warn("unable to setup signals for %s", user_cmnd);
        goto fail;
     }
 
     /* become a daemon */
+    set_perms(PERM_FULL_ROOT);
     if (setsid() == -1) {
        warn("setsid");
        kill(pid, SIGKILL);
@@ -190,9 +196,13 @@ systrace_attach(pid)
     for (;;) {
        nread = read(fd, &msg, sizeof(msg));
        if (nread != sizeof(msg)) {
+           if (dodetach) {
+               detachall(fd);
+               _exit(0);
+           }
            if (nread == -1 && (errno == EINTR || errno == EAGAIN))
                continue;
-           killall(&children, SIGKILL);
+           killall(SIGKILL);
            _exit(nread != 0);  /* shouldn't happen */
        }
 
@@ -275,7 +285,7 @@ systrace_attach(pid)
     }
 
 fail:
-    killall(&children, SIGKILL);
+    killall(SIGKILL);
     _exit(1);
 }
 
@@ -903,12 +913,24 @@ check_execve(fd, pid, seqnr, askp, cookie, policyp, errorp)
  * Kill all pids in the list
  */
 static void
-killall(head, sig)
-    struct listhead *head;
+killall(sig)
     int sig;
 {
     struct childinfo *child;
 
-    for (child = head->first; child != NULL; child = child->next)
+    for (child = children.first; child != NULL; child = child->next)
        (void) kill(child->pid, sig);
 }
+
+/*
+ * Detach all traced processes.
+ */
+static void
+detachall(fd)
+    int fd;
+{
+    struct childinfo *child;
+
+    for (child = children.first; child != NULL; child = child->next)
+       (void) ioctl(fd, STRIOCDETACH, &child->pid);
+}
index f1063aa0bf095ad6d5d458c072aeaf8258380ca3..24206ecf6993655778a4a03354ae9f5dd554e9a2 100644 (file)
@@ -41,7 +41,9 @@ static int update_env         __P((int, pid_t, u_int16_t, struct str_msg_ask *));
 static schandler_t find_handler        __P((pid_t, int));
 static ssize_t read_string     __P((int, pid_t, void *, char *, size_t));
 static struct childinfo *find_child __P((pid_t));
-static void killall            __P((struct listhead *, int));
+static void catchsig           __P((int));
+static void detachall          __P((int));
+static void killall            __P((int));
 static void new_child          __P((pid_t, pid_t));
 static void rm_child           __P((pid_t));
 static void update_child       __P((pid_t, uid_t));
@@ -49,6 +51,7 @@ static void update_child      __P((pid_t, uid_t));
 
 static struct listhead children;       /* list of children being traced */
 static int initialized;                        /* set to true when we are inited */
+static volatile sig_atomic_t dodetach; /* caught signal */
 
 struct listhead {
     void *first;