ソースを参照

Merge branch 'maint'

* maint:
  Linux ptrace(2) is returning EPERM rather than EBUSY for 'already traced'.
  Allow all processes to trace when built with DEBUG.
  Allow 'set trace ignore' again. Undoes a change from 2005.
  Only try detaching if it was successful
  Make the Ubuntu prctl(2) fix in 4e89f5 less racy
  Remove useless SIGCHLD raising
Bryan Drewery 11 年 前
コミット
9fcd56f03e
2 ファイル変更26 行追加17 行削除
  1. 2 0
      doc/UPDATES
  2. 24 17
      src/shell.cc

+ 2 - 0
doc/UPDATES

@@ -4,6 +4,8 @@ master
 maint
   * Disable demo TCL support by default to prevent confusion during build.
   * Avoid apparmor ptrace(2) warnings on Ubuntu
+  * Allow 'set trace ignore' again. Undoes a change from 2005.
+  * Fix ptrace detection on Linux
 
 1.4.5
   * Remove ahbl as it now positively identifies all hosts as abusive

+ 24 - 17
src/shell.cc

@@ -268,15 +268,15 @@ static void got_sigtrap(int z)
 
 void check_trace(int start)
 {
-  if (trace == DET_IGNORE || trace == DET_WARN)
-    trace = DET_DIE;
-//    return;
-
 #ifdef DEBUG
-  trace = DET_IGNORE;
-#endif /* DEBUG */
+#ifdef PR_SET_PTRACER
+  if (start == 1)
+    prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
+#endif
+  return;
+#endif
 
-  if (trace == DET_IGNORE)
+  if (start == 0 && trace == DET_IGNORE)
     return;
 
   pid_t parent = getpid();
@@ -306,35 +306,47 @@ void check_trace(int start)
       return;
 
 #ifndef __sun__
-    int x, i;
+    int x, i, filedes[2];
+
+    (void)pipe(filedes);
 
   /* now, let's attempt to ptrace ourself */
     switch ((x = fork())) {
       case -1:
         return;
       case 0:		//child
+        char buf[1];
+
+        while (read(filedes[0], buf, sizeof(buf)) != 1)
+          ;
+
         i = ptrace(PT_ATTACH, parent, 0, 0);
+        if (i == -1 &&
         /* EPERM is given on fbsd when security.bsd.unprivileged_proc_debug=0 */
-        if (i == -1 && errno != EPERM && errno != EINVAL) {
+#ifdef __FreeBSD__
+            errno != EPERM &&
+#endif
+            errno != EINVAL) {
           if (start) {
             kill(parent, SIGKILL);
             exit(1);
           } else
             detected(DETECT_TRACE, STR("I'm being traced!"));
-        } else {
+        } else if (i == 0) {
           waitpid(parent, NULL, 0);
           ptrace(PT_DETACH, parent, (char *) 1, 0);
-          kill(parent, SIGCHLD);
         }
         exit(0);
       default:		//parent
 #ifdef PR_SET_PTRACER
         // Allow the child to debug the parent on Ubuntu
         // https://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace
-        // XXX: This is probably racy with the child's ptrace(2) attempt.
         prctl(PR_SET_PTRACER, x, 0, 0, 0);
 #endif
+        (void)write(filedes[1], "+", 1);
         waitpid(x, NULL, 0);
+        close(filedes[0]);
+        close(filedes[1]);
     }
 #endif
   }
@@ -347,7 +359,6 @@ int shell_exec(char *cmdline, char *input, char **output, char **erroutput, bool
 
   Tempfile *in = NULL, *out = NULL, *err = NULL;
   int x;
-  int parent = getpid();
 
   /* Set up temp files */
   in = new Tempfile("in");
@@ -450,15 +461,12 @@ int shell_exec(char *cmdline, char *input, char **output, char **erroutput, bool
 //    errd = fileno(errFile);
 
     if (dup2(in->fd, STDIN_FILENO) == (-1)) {
-      kill(parent, SIGCHLD);
       exit(1);
     }
     if (dup2(out->fd, STDOUT_FILENO) == (-1)) {
-      kill(parent, SIGCHLD);
       exit(1);
     }
     if (dup2(err->fd, STDERR_FILENO) == (-1)) {
-      kill(parent, SIGCHLD);
       exit(1);
     }
 
@@ -483,7 +491,6 @@ int shell_exec(char *cmdline, char *input, char **output, char **erroutput, bool
     }
 
     execvp(argv[0], &argv[0]);
-    kill(parent, SIGCHLD);
     exit(1);
   }
 }