Просмотр исходного кода

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 лет назад
Родитель
Сommit
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
 maint
   * Disable demo TCL support by default to prevent confusion during build.
   * Disable demo TCL support by default to prevent confusion during build.
   * Avoid apparmor ptrace(2) warnings on Ubuntu
   * 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
 1.4.5
   * Remove ahbl as it now positively identifies all hosts as abusive
   * 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)
 void check_trace(int start)
 {
 {
-  if (trace == DET_IGNORE || trace == DET_WARN)
-    trace = DET_DIE;
-//    return;
-
 #ifdef DEBUG
 #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;
     return;
 
 
   pid_t parent = getpid();
   pid_t parent = getpid();
@@ -306,35 +306,47 @@ void check_trace(int start)
       return;
       return;
 
 
 #ifndef __sun__
 #ifndef __sun__
-    int x, i;
+    int x, i, filedes[2];
+
+    (void)pipe(filedes);
 
 
   /* now, let's attempt to ptrace ourself */
   /* now, let's attempt to ptrace ourself */
     switch ((x = fork())) {
     switch ((x = fork())) {
       case -1:
       case -1:
         return;
         return;
       case 0:		//child
       case 0:		//child
+        char buf[1];
+
+        while (read(filedes[0], buf, sizeof(buf)) != 1)
+          ;
+
         i = ptrace(PT_ATTACH, parent, 0, 0);
         i = ptrace(PT_ATTACH, parent, 0, 0);
+        if (i == -1 &&
         /* EPERM is given on fbsd when security.bsd.unprivileged_proc_debug=0 */
         /* 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) {
           if (start) {
             kill(parent, SIGKILL);
             kill(parent, SIGKILL);
             exit(1);
             exit(1);
           } else
           } else
             detected(DETECT_TRACE, STR("I'm being traced!"));
             detected(DETECT_TRACE, STR("I'm being traced!"));
-        } else {
+        } else if (i == 0) {
           waitpid(parent, NULL, 0);
           waitpid(parent, NULL, 0);
           ptrace(PT_DETACH, parent, (char *) 1, 0);
           ptrace(PT_DETACH, parent, (char *) 1, 0);
-          kill(parent, SIGCHLD);
         }
         }
         exit(0);
         exit(0);
       default:		//parent
       default:		//parent
 #ifdef PR_SET_PTRACER
 #ifdef PR_SET_PTRACER
         // Allow the child to debug the parent on Ubuntu
         // Allow the child to debug the parent on Ubuntu
         // https://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace
         // 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);
         prctl(PR_SET_PTRACER, x, 0, 0, 0);
 #endif
 #endif
+        (void)write(filedes[1], "+", 1);
         waitpid(x, NULL, 0);
         waitpid(x, NULL, 0);
+        close(filedes[0]);
+        close(filedes[1]);
     }
     }
 #endif
 #endif
   }
   }
@@ -347,7 +359,6 @@ int shell_exec(char *cmdline, char *input, char **output, char **erroutput, bool
 
 
   Tempfile *in = NULL, *out = NULL, *err = NULL;
   Tempfile *in = NULL, *out = NULL, *err = NULL;
   int x;
   int x;
-  int parent = getpid();
 
 
   /* Set up temp files */
   /* Set up temp files */
   in = new Tempfile("in");
   in = new Tempfile("in");
@@ -450,15 +461,12 @@ int shell_exec(char *cmdline, char *input, char **output, char **erroutput, bool
 //    errd = fileno(errFile);
 //    errd = fileno(errFile);
 
 
     if (dup2(in->fd, STDIN_FILENO) == (-1)) {
     if (dup2(in->fd, STDIN_FILENO) == (-1)) {
-      kill(parent, SIGCHLD);
       exit(1);
       exit(1);
     }
     }
     if (dup2(out->fd, STDOUT_FILENO) == (-1)) {
     if (dup2(out->fd, STDOUT_FILENO) == (-1)) {
-      kill(parent, SIGCHLD);
       exit(1);
       exit(1);
     }
     }
     if (dup2(err->fd, STDERR_FILENO) == (-1)) {
     if (dup2(err->fd, STDERR_FILENO) == (-1)) {
-      kill(parent, SIGCHLD);
       exit(1);
       exit(1);
     }
     }
 
 
@@ -483,7 +491,6 @@ int shell_exec(char *cmdline, char *input, char **output, char **erroutput, bool
     }
     }
 
 
     execvp(argv[0], &argv[0]);
     execvp(argv[0], &argv[0]);
-    kill(parent, SIGCHLD);
     exit(1);
     exit(1);
   }
   }
 }
 }