new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / rootcheck / check_rc_pids.c
old mode 100755 (executable)
new mode 100644 (file)
index bd06f2d..7c1c645
@@ -1,6 +1,3 @@
-/* @(#) $Id: ./src/rootcheck/check_rc_pids.c, 2011/09/08 dcid Exp $
- */
-
 /* Copyright (C) 2009 Trend Micro Inc.
  * All right reserved.
  *
 #include "shared.h"
 #include "rootcheck.h"
 
+/* Prototypes */
+static int  proc_read(int pid);
+static int  proc_chdir(int pid);
+static int  proc_stat(int pid);
+static void loop_all_pids(const char *ps, pid_t max_pid, int *_errors, int *_total);
 
-int noproc;
+/* Global variables */
+static int noproc;
 
 
-/** int proc_read(int pid)
- * If /proc is mounted, check to see if the pid is present
- */
-int proc_read(int pid)
+/* If /proc is mounted, check to see if the pid is present */
+static int proc_read(int pid)
 {
-    char dir[OS_SIZE_1024 +1];
+    char dir[OS_SIZE_1024 + 1];
 
-    if(noproc)
-        return(0);
+    if (noproc) {
+        return (0);
+    }
 
     snprintf(dir, OS_SIZE_1024, "%d", pid);
-    if(isfile_ondir(dir, "/proc"))
-    {
-        return(1);
+    if (isfile_ondir(dir, "/proc")) {
+        return (1);
     }
-    return(0);
+    return (0);
 }
 
-
-/** int proc_chdir(int pid)
- * If /proc is mounted, check to see if the pid is present
- */
-int proc_chdir(int pid)
+/* If /proc is mounted, check to see if the pid is present */
+static int proc_chdir(int pid)
 {
     int ret = 0;
     char curr_dir[OS_SIZE_1024 + 1];
     char dir[OS_SIZE_1024 + 1];
 
-    if(noproc)
-        return(0);
-
-    if(!getcwd(curr_dir, OS_SIZE_1024))
-    {
-        return(0);
+    if (noproc) {
+        return (0);
+    }
+    if (getcwd(curr_dir, OS_SIZE_1024) == NULL) {
+        return (0);
+    }
+    if (chdir("/proc") == -1) {
+        return (0);
     }
-
-    if(chdir("/proc") == -1)
-        return(0);
 
     snprintf(dir, OS_SIZE_1024, "/proc/%d", pid);
-    if(chdir(dir) == 0)
-    {
+    if (chdir(dir) == 0) {
         ret = 1;
     }
 
     /* Returning to the previous directory */
-    chdir(curr_dir);
+    if (chdir(curr_dir) == -1) {
+        return (0);
+    }
 
-    return(ret);
+    return (ret);
 }
 
-
-/** int proc_stat(int pid)
- * If /proc is mounted, check to see if the pid is present there.
- */
-int proc_stat(int pid)
+/* If /proc is mounted, check to see if the pid is present there */
+static int proc_stat(int pid)
 {
     char proc_dir[OS_SIZE_1024 + 1];
 
-    if(noproc)
-        return(0);
+    if (noproc) {
+        return (0);
+    }
 
     snprintf(proc_dir, OS_SIZE_1024, "%s/%d", "/proc", pid);
 
-    if(is_file(proc_dir))
-    {
-        return(1);
+    if (is_file(proc_dir)) {
+        return (1);
     }
 
-    return(0);
+    return (0);
 }
 
-
-/** void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
- * Check all the available PIDs for hidden stuff.
- */
-void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
+/* Check all the available PIDs for hidden stuff */
+static void loop_all_pids(const char *ps, pid_t max_pid, int *_errors, int *_total)
 {
     int _kill0 = 0;
     int _kill1 = 0;
@@ -110,14 +102,14 @@ void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
     pid_t i = 1;
     pid_t my_pid;
 
-    char command[OS_SIZE_1024 +1];
+    char command[OS_SIZE_1024 + 1];
 
     my_pid = getpid();
 
-    for(;;i++)
-    {
-        if((i <= 0)||(i > max_pid))
+    for (;; i++) {
+        if ((i <= 0) || (i > max_pid)) {
             break;
+        }
 
         (*_total)++;
 
@@ -128,205 +120,157 @@ void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
         _gpid0 = 0;
         _gpid1 = 0;
         _ps0 = -1;
-        _proc_stat  = 0;
-        _proc_read  = 0;
-        _proc_chdir = 0;
-
 
         /* kill test */
-        if(!((kill(i, 0) == -1)&&(errno == ESRCH)))
-        {
+        if (!((kill(i, 0) == -1) && (errno == ESRCH))) {
             _kill0 = 1;
         }
 
-        /* getsid to test */
-        if(!((getsid(i) == -1)&&(errno == ESRCH)))
-        {
+        /* getsid test */
+        if (!((getsid(i) == -1) && (errno == ESRCH))) {
             _gsid0 = 1;
         }
 
         /* getpgid test */
-        if(!((getpgid(i) == -1)&&(errno == ESRCH)))
-        {
+        if (!((getpgid(i) == -1) && (errno == ESRCH))) {
             _gpid0 = 1;
         }
 
-
-        /* proc stat */
+        /* /proc test */
         _proc_stat = proc_stat(i);
-
-        /* proc readdir */
         _proc_read = proc_read(i);
-
-        /* proc chdir */
         _proc_chdir = proc_chdir(i);
 
-
-        /* IF PID does not exist, keep going */
-        if(!_kill0 && !_gsid0 && !_gpid0 &&
-           !_proc_stat && !_proc_read && !_proc_chdir)
-        {
+        /* If PID does not exist, move on */
+        if (!_kill0     && !_gsid0     && !_gpid0 &&
+                !_proc_stat && !_proc_read && !_proc_chdir) {
             continue;
         }
 
-        /* We do not need to look at our own pid */
-        else if(i == my_pid)
-        {
+        /* Ignore our own pid */
+        if (i == my_pid) {
             continue;
         }
 
-        /* Checking the number of errors */
-        if((*_errors) > 15)
-        {
-            char op_msg[OS_SIZE_1024 +1];
-            snprintf(op_msg,OS_SIZE_1024,"Excessive number of hidden processes"
-                    ". It maybe a false-positive or "
-                    "something really bad is going on.");
+        /* Check the number of errors */
+        if ((*_errors) > 15) {
+            char op_msg[OS_SIZE_1024 + 1];
+            snprintf(op_msg, OS_SIZE_1024, "Excessive number of hidden processes"
+                     ". It maybe a false-positive or "
+                     "something really bad is going on.");
             notify_rk(ALERT_SYSTEM_CRIT, op_msg);
             return;
         }
 
-
-        /* checking if process appears on ps */
-        if(*ps)
-        {
-            snprintf(command, OS_SIZE_1024, "%s -p %d > /dev/null 2>&1",
-                                                        ps,
-                                                        (int)i);
-
-            /* Found PID on ps */
+        /* Check if the process appears in ps(1) output */
+        if (*ps) {
+            snprintf(command, OS_SIZE_1024, "%s -p %d > /dev/null 2>&1", ps, (int)i);
             _ps0 = 0;
-            if(system(command) == 0)
+            if (system(command) == 0) {
                 _ps0 = 1;
+            }
         }
 
-        /* If we are being run by the ossec hids, sleep here (no rush) */
-        #ifdef OSSECHIDS
-        sleep(2);
-        #endif
+        /* If we are run in the context of OSSEC-HIDS, sleep here (no rush) */
+#ifdef OSSECHIDS
+        debug1("%s: DEBUG: pause for %u", ARGV0, rootcheck.tsleep);
+        sleep(rootcheck.tsleep);
+#endif
 
-        /* Everyone returned ok */
-        if(_ps0 && _kill0 && _gsid0 && _gpid0 && _proc_stat && _proc_read)
-        {
+        /* Everything fine, move on */
+        if (_ps0 && _kill0 && _gsid0 && _gpid0 && _proc_stat && _proc_read) {
             continue;
         }
 
-
-
-        /* If our kill or getsid system call, got the
-         * PID , but ps didn't, we need to find if it was a problem
-         * with a PID being deleted (not used anymore)
+        /*
+         * If our kill or getsid system call got the PID but ps(1) did not,
+         * find out if the PID is deleted (not used anymore)
          */
-        {
-            if(!((getsid(i) == -1)&&(errno == ESRCH)))
-            {
-                _gsid1 = 1;
-            }
-
-            if(!((kill(i, 0) == -1)&&(errno == ESRCH)))
-            {
-                _kill1 = 1;
-            }
-
-            if(!((getpgid(i) == -1)&&(errno == ESRCH)))
-            {
-                _gpid1 = 1;
-            }
-
-
-            _proc_stat = proc_stat(i);
-
-            _proc_read = proc_read(i);
+        if (!((getsid(i) == -1) && (errno == ESRCH))) {
+            _gsid1 = 1;
+        }
+        if (!((kill(i, 0) == -1) && (errno == ESRCH))) {
+            _kill1 = 1;
+        }
+        if (!((getpgid(i) == -1) && (errno == ESRCH))) {
+            _gpid1 = 1;
+        }
 
-            _proc_chdir = proc_chdir(i);
+        _proc_stat = proc_stat(i);
+        _proc_read = proc_read(i);
+        _proc_chdir = proc_chdir(i);
 
-            /* If it matches, process was terminated */
-            if(!_gsid1 &&!_kill1 &&!_gpid1 &&!_proc_stat &&
-               !_proc_read &&!_proc_chdir)
-            {
-                continue;
-            }
+        /* If it matches, process was terminated in the meantime, so move on */
+        if (!_gsid1 && !_kill1 && !_gpid1 && !_proc_stat &&
+                !_proc_read && !_proc_chdir) {
+            continue;
         }
 
-        #ifdef AIX
-        /* Ignoring AIX wait and sched programs. */
-        if((_gsid0 == _gsid1) &&
-           (_kill0 == _kill1) &&
-           (_gpid0 == _gpid1) &&
-           (_ps0 == 1) &&
-           (_gsid0 == 1) &&
-           (_kill0 == 0))
-        {
+#ifdef AIX
+        /* Ignore AIX wait and sched programs */
+        if (_gsid0 == _gsid1 &&
+                _kill0 == _kill1 &&
+                _gpid0 == _gpid1 &&
+                _ps0 == 1 &&
+                _gsid0 == 1 &&
+                _kill0 == 0) {
             /* The wait and sched programs do not respond to kill 0.
-             * So, if everything else finds it, including ps, getpid, getsid,
-             * but not
-             * kill, we can safely ignore on AIX.
-             * A malicious program would specially try to hide from ps..
+             * So if everything else finds it, including ps, getpid, getsid,
+             * but not kill, we can safely ignore on AIX.
+             * A malicious program would specially try to hide from ps.
              */
             continue;
         }
-        #endif
-
+#endif
 
-        if((_gsid0 == _gsid1)&&
-           (_kill0 == _kill1)&&
-           (_gsid0 != _kill0))
-        {
-            /* If kill found, but getsid and getpgid didnt', it may
+        if (_gsid0 == _gsid1 &&
+                _kill0 == _kill1 &&
+                _gsid0 != _kill0) {
+            /* If kill worked, but getsid and getpgid did not, it may
              * be a defunct process -- ignore.
              */
-            if(!((_kill0 == 1)&&(_gsid0 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0)))
-            {
-                char op_msg[OS_SIZE_1024 +1];
+            if (! (_kill0 == 1 && _gsid0 == 0 && _gpid0 == 0) ) {
+                char op_msg[OS_SIZE_1024 + 1];
 
                 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
-                        "kill (%d) or getsid (%d). Possible kernel-level"
-                        " rootkit.", (int)i, _kill0, _gsid0);
-
+                         "kill (%d) or getsid (%d). Possible kernel-level"
+                         " rootkit.", (int)i, _kill0, _gsid0);
                 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                 (*_errors)++;
             }
-        }
-        else if((_kill1 != _gsid1)||
-                (_gpid1 != _kill1)||
-                (_gpid1 != _gsid1))
-        {
-            /* See defunct process comment above. */
-            if(!((_kill1 == 1)&&(_gsid1 == 0)&&(_gpid0 == 0)&&(_gsid1 == 0)))
-            {
-                char op_msg[OS_SIZE_1024 +1];
-                snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
-                        "kill (%d), getsid (%d) or getpgid. Possible "
-                        "kernel-level rootkit.", (int)i, _kill1, _gsid1);
+        } else if (_kill1 != _gsid1 ||
+                   _gpid1 != _kill1 ||
+                   _gpid1 != _gsid1) {
+            /* See defunct process comment above */
+            if (! (_kill1 == 1 && _gsid0 == 0 && _gpid0 == 0 && _gsid1 == 0) ) {
+                char op_msg[OS_SIZE_1024 + 1];
 
+                snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
+                         "kill (%d), getsid (%d) or getpgid. Possible "
+                         "kernel-level rootkit.", (int)i, _kill1, _gsid1);
                 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                 (*_errors)++;
             }
-        }
-        else if((_proc_read != _proc_stat)||
-                (_proc_read != _proc_chdir)||
-                (_proc_stat != _kill1))
-        {
-            /* checking if the pid is a thread (not showing on proc */
-            if(!noproc && !check_rc_readproc((int)i))
-            {
-                char op_msg[OS_SIZE_1024 +1];
+        } else if (_proc_read != _proc_stat  ||
+                   _proc_read != _proc_chdir ||
+                   _proc_stat != _kill1) {
+            /* Check if the pid is a thread (not showing in /proc */
+            if (!noproc && !check_rc_readproc((int)i)) {
+                char op_msg[OS_SIZE_1024 + 1];
+
                 snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
-                        "/proc. Possible kernel level rootkit.", (int)i);
+                         "/proc. Possible kernel level rootkit.", (int)i);
                 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                 (*_errors)++;
             }
-        }
-        else if(_gsid1 && _kill1 && !_ps0)
-        {
+        } else if (_gsid1 && _kill1 && !_ps0) {
             /* checking if the pid is a thread (not showing on ps */
-            if(!check_rc_readproc((int)i))
-            {
-                char op_msg[OS_SIZE_1024 +1];
-                snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
-                             "ps. Possible trojaned version installed.",
-                             (int)i);
+            if (!check_rc_readproc((int)i)) {
+                char op_msg[OS_SIZE_1024 + 1];
 
+                snprintf(op_msg, OS_SIZE_1024, "Process '%d' hidden from "
+                         "ps. Possible trojaned version installed.",
+                         (int)i);
                 notify_rk(ALERT_ROOTKIT_FOUND, op_msg);
                 (*_errors)++;
             }
@@ -334,59 +278,52 @@ void loop_all_pids(char *ps, pid_t max_pid, int *_errors, int *_total)
     }
 }
 
-
-/*  check_rc_sys: v0.1
- *  Scan the whole filesystem looking for possible issues
- */
+/* Scan the whole filesystem looking for possible issues */
 void check_rc_pids()
 {
     int _total = 0;
     int _errors = 0;
 
-    char ps[OS_SIZE_1024 +1];
+    char ps[OS_SIZE_1024 + 1];
 
     char proc_0[] = "/proc";
     char proc_1[] = "/proc/1";
 
     pid_t max_pid = MAX_PID;
-
     noproc = 1;
 
     /* Checking where ps is */
-    memset(ps, '\0', OS_SIZE_1024 +1);
+    memset(ps, '\0', OS_SIZE_1024 + 1);
     strncpy(ps, "/bin/ps", OS_SIZE_1024);
-    if(!is_file(ps))
-    {
+    if (!is_file(ps)) {
         strncpy(ps, "/usr/bin/ps", OS_SIZE_1024);
-        if(!is_file(ps))
+        if (!is_file(ps)) {
             ps[0] = '\0';
+        }
     }
 
-
     /* Proc is mounted */
-    if(is_file(proc_0) && is_file(proc_1))
-    {
+    if (is_file(proc_0) && is_file(proc_1)) {
         noproc = 0;
     }
 
     loop_all_pids(ps, max_pid, &_errors, &_total);
 
-    if(_errors == 0)
-    {
-        char op_msg[OS_SIZE_1024 +1];
+    if (_errors == 0) {
+        char op_msg[OS_SIZE_1024 + 1];
         snprintf(op_msg, OS_SIZE_1024, "No hidden process by Kernel-level "
-                                    "rootkits.\n      %s is not trojaned. "
-                                    "Analyzed %d processes.", ps, _total);
+                 "rootkits.\n      %s is not trojaned. "
+                 "Analyzed %d processes.", ps, _total);
         notify_rk(ALERT_OK, op_msg);
     }
 
     return;
 }
 
-/* EOF */
 #else
 void check_rc_pids()
 {
     return;
 }
 #endif
+