Pārlūkot izejas kodu

* Ptrace blocker watcher/child

svn: 1057
Bryan Drewery 22 gadi atpakaļ
vecāks
revīzija
eba1744ca6
7 mainītis faili ar 113 papildinājumiem un 25 dzēšanām
  1. 1 0
      doc/UPDATES
  2. 88 23
      src/bg.c
  3. 3 0
      src/bg.h
  4. 2 0
      src/cmds.c
  5. 12 1
      src/conf.c
  6. 1 0
      src/conf.h
  7. 6 1
      src/main.c

+ 1 - 0
doc/UPDATES

@@ -29,6 +29,7 @@ This is a summary of ChangeLog basically.
 25.Now dumping the stack on SIGSEGV.
 26.FreeBSD packages now have release # again, ie: FreeBSD4.
 27.Fixed hub not searching for update bins in it's own dir.
+28.Shell config option 'watcher', will make 1 extra PID per bot to block process hijackers.
 
 1.1.7
 

+ 88 - 23
src/bg.c

@@ -7,21 +7,27 @@
 
 #include "common.h"
 #include "bg.h"
+#include "thread.h"
 #include "main.h"
 #include <signal.h>
-#ifdef CRAZY_TRACE
 #include <sys/ptrace.h>
-#endif
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
 
-time_t  lastfork = 0;
+time_t lastfork = 0;
+pid_t watcher;                  /* my child/watcher */
 
 /* Do everything we normally do after we have split off a new
  * process to the background. This includes writing a PID file
  * and informing the user of the split.
  */
-static void bg_do_detach(pid_t) __attribute__((noreturn));
+static void bg_do_detach(pid_t) __attribute__ ((noreturn));
 
-static void bg_do_detach(pid_t p)
+static void
+bg_do_detach(pid_t p)
 {
   FILE *fp = NULL;
 
@@ -53,7 +59,61 @@ static void bg_do_detach(pid_t p)
   exit(0);
 }
 
-void bg_do_split(void)
+#ifdef BSD
+#  define PT_CONT PTRACE_CONTINUE
+#endif /* BSD */
+#ifdef __linux__
+#  define PT_CONT PTRACE_CONT
+#endif /* __linux__ */
+
+static void
+init_watcher()
+{
+  if (conf.watcher) {
+    int x = 0;
+    pid_t parent = getpid();
+
+    x = fork();
+
+    if (x == -1)
+      fatal("Could not fork off a watcher process", 0);
+    if (x != 0) {               /* parent [bot] */
+      watcher = x;
+      /* printf("WATCHER: %d\n", watcher); */
+      return;
+    } else {                    /* child */
+      watcher = getpid();
+      /* printf("MY PARENT: %d\n", parent); */
+      /* printf("my pid: %d\n", watcher); */
+      if (ptrace(PTRACE_ATTACH, parent, 0, 0) == -1)
+        fatal("Cannot attach to parent", 0);
+
+      while (1) {
+        int status = 0, sig = 0, ret = 0;
+
+        waitpid(parent, &status, 0);
+        sig = WSTOPSIG(status);
+        if (sig) {
+          ret = ptrace(PT_CONT, parent, (char *) 1, sig);
+          if (ret == -1)        /* send the signal! */
+            fatal("Could not send signal to parent", 0);
+          /* printf("Sent signal %s (%d) to parent\n", strsignal(sig), sig); */
+        } else {
+          ret = ptrace(PT_CONT, parent, (char *) 1, 0);
+          if (ret == -1) {
+            if (errno == ESRCH) /* parent is gone! */
+              exit(0);          /* just exit */
+            else
+              fatal("Could not continue parent", 0);
+          }
+        }
+      }
+    }
+  }
+}
+
+void
+bg_do_split(void)
 {
   /* Split off a new process.
    */
@@ -61,35 +121,40 @@ void bg_do_split(void)
 
   if (xx == -1)
     fatal("CANNOT FORK PROCESS.", 0);
-  if (xx != 0)		/* parent */
+  if (xx != 0)                  /* parent */
     bg_do_detach(xx);
+  else                          /* child */
+    init_watcher();
+/*    init_thread(getpid()); */
 #ifdef CRAZY_TRACE
-  else			/* new child */
-    /* block ptrace? */
-# ifdef __linux__
-    ptrace(PTRACE_TRACEME, 0, NULL, NULL);
-# endif
-# ifdef BSD
-    ptrace(PT_TRACE_ME, 0, NULL, NULL);
-# endif /* BSD */
+  /* block ptrace? */
+#  ifdef __linux__
+  ptrace(PTRACE_TRACEME, 0, NULL, NULL);
+#  endif
+#  ifdef BSD
+  ptrace(PT_TRACE_ME, 0, NULL, NULL);
+#  endif /* BSD */
 #endif /* CRAZY_TRACE */
 
 }
 
-void do_fork() {
+void
+do_fork()
+{
   int xx;
 
   xx = fork();
   if (xx == -1)
     return;
   if (xx != 0) {
-      FILE *fp;
-      unlink(conf.bot->pid_file);
-      fp = fopen(conf.bot->pid_file, "w");
-      if (fp != NULL) {
-        fprintf(fp, "%u\n", xx);
-        fclose(fp);
-      }
+    FILE *fp;
+
+    unlink(conf.bot->pid_file);
+    fp = fopen(conf.bot->pid_file, "w");
+    if (fp != NULL) {
+      fprintf(fp, "%u\n", xx);
+      fclose(fp);
+    }
   }
   if (xx) {
 #if HAVE_SETPGID

+ 3 - 0
src/bg.h

@@ -1,7 +1,10 @@
 #ifndef _BG_H
 #define _BG_H
 
+#include <sys/types.h>
+
 extern time_t 		lastfork;
+extern pid_t 		watcher;
 
 void do_fork();
 void bg_do_split();

+ 2 - 0
src/cmds.c

@@ -1907,6 +1907,7 @@ static void cmd_conf(struct userrec *u, int idx, char *par)
         else if (!egg_strcasecmp(what, "pscloak"))   conffile.pscloak = atoi(par);
         else if (!egg_strcasecmp(what, "autocron"))  conffile.autocron = atoi(par);
         else if (!egg_strcasecmp(what, "autouname")) conffile.autouname = atoi(par);
+        else if (!egg_strcasecmp(what, "watcher"))  conffile.watcher = atoi(par);
         else { 
           set--;
           save = 0;
@@ -1929,6 +1930,7 @@ static void cmd_conf(struct userrec *u, int idx, char *par)
       if (!what || !egg_strcasecmp(what, "pscloak"))    dprintf(idx, "%spscloak: %d\n", ss, conffile.pscloak);
       if (!what || !egg_strcasecmp(what, "autocron"))   dprintf(idx, "%sautocron: %d\n", ss, conffile.autocron);
       if (!what || !egg_strcasecmp(what, "autouname"))  dprintf(idx, "%sautouname: %d\n", ss, conffile.autouname);
+      if (!what || !egg_strcasecmp(what, "watcher"))    dprintf(idx, "%swatcher: %d\n", ss, conffile.watcher);
     }
   }
 #endif /* !CYGWIN_HACKS || HUB */

+ 12 - 1
src/conf.c

@@ -219,6 +219,7 @@ init_conf()
   conffile.bots->next = NULL;
   conffile.bot = NULL;
 
+  conffile.watcher = 0;
 #ifdef CYGWIN_HACKS
   conffile.autocron = 0;
 #else
@@ -526,7 +527,7 @@ readconf(char *fname, int bits)
         if (!strcmp(option, "autocron")) {      /* automatically check/create crontab? */
           if (egg_isdigit(line[0]))
             conffile.autocron = atoi(line);
-
+       
         } else if (!strcmp(option, "autouname")) {      /* auto update uname contents? */
           if (egg_isdigit(line[0]))
             conffile.autouname = atoi(line);
@@ -563,6 +564,10 @@ readconf(char *fname, int bits)
           if (!conffile.uname)
             conffile.uname = strdup(line);
 
+        } else if (!strcmp(option, "watcher")) {
+          if (egg_isdigit(line[0]))
+            conffile.watcher = atoi(line);
+
         } else {
           putlog(LOG_MISC, "*", "Unrecognized config option '%s'", option);
 
@@ -688,6 +693,11 @@ writeconf(char *filename, FILE * stream, int bits)
 
   comment("");
 
+  comment("# This will spawn a child process for EACH BOT that will block ALL process hijackers.");
+  my_write(f, "! watcher %d\n", conffile.watcher);
+
+  comment("");
+
   comment("# '|' means OR, [] means the enclosed is optional");
   comment("# A '+' in front of HOST means the HOST is ipv6");
   comment("# A '/' in front of BOT will disable that bot.");
@@ -754,6 +764,7 @@ fillconf(conf_t * inconf)
   inconf->username = conffile.username ? strdup(conffile.username) : NULL;
   inconf->homedir = conffile.homedir ? strdup(conffile.homedir) : NULL;
   inconf->autocron = conffile.autocron;
+  inconf->watcher = conffile.watcher;
   inconf->autouname = conffile.autouname;
   inconf->portmin = conffile.portmin;
   inconf->portmax = conffile.portmax;

+ 1 - 0
src/conf.h

@@ -37,6 +37,7 @@ typedef struct conf_b {
   char *binpath;        /* path to binary, ie: ~/ */
   char *binname;        /* binary name, ie: .sshrc */
   int autocron;         /* should the bot auto crontab itself? */
+  int watcher;		/* spawn a watcher pid to block ptrace? */
   char *comments;       /* we dont want to lose our comments now do we?! */
 } conf_t;
 

+ 6 - 1
src/main.c

@@ -11,6 +11,7 @@
 #include "binary.h"
 #include "dcc.h"
 #include "misc.h"
+#include "thread.h"
 #include "settings.h"
 #include "salt.h"
 #include "misc_file.h"
@@ -36,6 +37,7 @@
 #include <time.h>
 #include <errno.h>
 #include <unistd.h>
+#include <sys/wait.h>
 #ifdef STOP_UAC				/* osf/1 complains a lot */
 # include <sys/sysinfo.h>
 # define UAC_NOPRINT			/* Don't report unaligned fixups */
@@ -902,9 +904,12 @@ int main(int argc, char **argv)
   while (1) {
 //if (tracecheck_breakpoint())
 //exit(0);
-    int socket_cleanup = 0, i, xx;
+    int socket_cleanup = 0, i, xx, status = 0;
     char buf[SGRAB + 10] = "";
 
+    if (conf.watcher && waitpid(watcher, &status, WNOHANG))
+      fatal("watcher PID died/stopped", 0);
+
     /* Lets move some of this here, reducing the numer of actual
      * calls to periodic_timers
      */