| [67] | 1 | /* SAMHAIN file system integrity testing                                   */
 | 
|---|
 | 2 | /* Copyright (C) 2006 Rainer Wichmann                                      */
 | 
|---|
 | 3 | /*                                                                         */
 | 
|---|
 | 4 | /*  This program is free software; you can redistribute it                 */
 | 
|---|
 | 5 | /*  and/or modify                                                          */
 | 
|---|
 | 6 | /*  it under the terms of the GNU General Public License as                */
 | 
|---|
 | 7 | /*  published by                                                           */
 | 
|---|
 | 8 | /*  the Free Software Foundation; either version 2 of the License, or      */
 | 
|---|
 | 9 | /*  (at your option) any later version.                                    */
 | 
|---|
 | 10 | /*                                                                         */
 | 
|---|
 | 11 | /*  This program is distributed in the hope that it will be useful,        */
 | 
|---|
 | 12 | /*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
 | 
|---|
 | 13 | /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
 | 
|---|
 | 14 | /*  GNU General Public License for more details.                           */
 | 
|---|
 | 15 | /*                                                                         */
 | 
|---|
 | 16 | /*  You should have received a copy of the GNU General Public License      */
 | 
|---|
 | 17 | /*  along with this program; if not, write to the Free Software            */
 | 
|---|
 | 18 | /*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
 | 
|---|
 | 19 | 
 | 
|---|
 | 20 | /***************************************************************************
 | 
|---|
 | 21 |  *
 | 
|---|
 | 22 |  * This file provides a module for samhain to check for hidden/faked/missing
 | 
|---|
 | 23 |  * processes on the host.
 | 
|---|
 | 24 |  *
 | 
|---|
 | 25 |  */
 | 
|---|
 | 26 | 
 | 
|---|
 | 27 | #include "config_xor.h"
 | 
|---|
 | 28 | 
 | 
|---|
| [384] | 29 | /* changed from 500 to 600 b/o FreeBSD (see sys/cdefs.h) 
 | 
|---|
 | 30 |  * which needs _POSIX_C_SOURCE >= 200112 for lstat()
 | 
|---|
 | 31 |  */
 | 
|---|
| [394] | 32 | #if defined(__sun) || defined(__sun__) || defined(sun)
 | 
|---|
 | 33 | #define _XOPEN_SOURCE 500
 | 
|---|
 | 34 | #else
 | 
|---|
| [384] | 35 | #define _XOPEN_SOURCE 600
 | 
|---|
| [394] | 36 | #endif
 | 
|---|
| [67] | 37 | 
 | 
|---|
 | 38 | #include <stdio.h>
 | 
|---|
 | 39 | #include <stdlib.h>
 | 
|---|
 | 40 | #include <ctype.h>
 | 
|---|
 | 41 | #include <string.h>
 | 
|---|
 | 42 | #include <sys/types.h>
 | 
|---|
| [384] | 43 | #include <sys/stat.h>
 | 
|---|
| [67] | 44 | #include <dirent.h>
 | 
|---|
 | 45 | #include <signal.h>
 | 
|---|
 | 46 | #include <unistd.h>
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | #ifdef _POSIX_PRIORITY_SCHEDULING
 | 
|---|
 | 49 | #include <sched.h>
 | 
|---|
 | 50 | #endif
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | #ifdef HAVE_GETPRIORITY
 | 
|---|
 | 53 | #include <errno.h>
 | 
|---|
 | 54 | #include <sys/resource.h>
 | 
|---|
 | 55 | #endif
 | 
|---|
 | 56 | 
 | 
|---|
| [78] | 57 | #ifdef HAVE_SYS_STATVFS_H
 | 
|---|
 | 58 | #include <sys/statvfs.h>
 | 
|---|
 | 59 | #endif
 | 
|---|
 | 60 | 
 | 
|---|
 | 61 | 
 | 
|---|
| [67] | 62 | #ifdef HAVE_REGEX_H
 | 
|---|
 | 63 | #include <regex.h>
 | 
|---|
 | 64 | #endif
 | 
|---|
 | 65 | 
 | 
|---|
 | 66 | #include "samhain.h"
 | 
|---|
 | 67 | #include "sh_modules.h"
 | 
|---|
 | 68 | #include "sh_processcheck.h"
 | 
|---|
 | 69 | #include "sh_utils.h"
 | 
|---|
 | 70 | #include "sh_error.h"
 | 
|---|
 | 71 | #include "sh_extern.h"
 | 
|---|
| [78] | 72 | #include "sh_calls.h"
 | 
|---|
| [143] | 73 | #include "sh_pthread.h"
 | 
|---|
| [67] | 74 | 
 | 
|---|
 | 75 | #ifdef SH_USE_PROCESSCHECK
 | 
|---|
 | 76 | 
 | 
|---|
 | 77 | #define FIL__  _("sh_processcheck.c")
 | 
|---|
 | 78 | 
 | 
|---|
 | 79 | #ifdef __linux__
 | 
|---|
| [143] | 80 | #define PS_THREADS
 | 
|---|
| [67] | 81 | #endif
 | 
|---|
 | 82 | 
 | 
|---|
 | 83 | /* We won't want to build this into yule 
 | 
|---|
 | 84 |  */
 | 
|---|
 | 85 | #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
 | 
|---|
 | 86 | 
 | 
|---|
| [143] | 87 | SH_MUTEX_STATIC(mutex_proc_check, PTHREAD_MUTEX_INITIALIZER);
 | 
|---|
 | 88 | 
 | 
|---|
| [67] | 89 | /* sh_prochk_maxpid is one more than the largest pid
 | 
|---|
 | 90 |  */
 | 
|---|
 | 91 | static  size_t  sh_prochk_minpid = 0x0001;
 | 
|---|
 | 92 | static  size_t  sh_prochk_maxpid = 0x8000;
 | 
|---|
 | 93 | static  size_t  sh_prochk_size   = 0;
 | 
|---|
 | 94 | 
 | 
|---|
 | 95 | static  int     ShProchkActive  = S_TRUE;
 | 
|---|
 | 96 | static  short * sh_prochk_res   = NULL; 
 | 
|---|
 | 97 | 
 | 
|---|
 | 98 | static  char  * sh_prochk_pspath = NULL;
 | 
|---|
 | 99 | static  char  * sh_prochk_psarg  = NULL;
 | 
|---|
 | 100 | 
 | 
|---|
 | 101 | #define SH_PROCHK_INTERVAL 300
 | 
|---|
 | 102 | static time_t   sh_prochk_interval = SH_PROCHK_INTERVAL;
 | 
|---|
 | 103 | static int      sh_prochk_severity = SH_ERR_SEVERE;
 | 
|---|
| [204] | 104 | static int      sh_prochk_openvz   = S_FALSE;
 | 
|---|
| [67] | 105 | 
 | 
|---|
 | 106 | static int sh_prochk_set_maxpid  (const char * str);
 | 
|---|
 | 107 | static int sh_prochk_set_minpid  (const char * str);
 | 
|---|
 | 108 | static int sh_prochk_set_active  (const char *str);
 | 
|---|
 | 109 | static int sh_prochk_add_process (const char *str);
 | 
|---|
 | 110 | static int sh_prochk_set_pspath  (const char *str);
 | 
|---|
 | 111 | static int sh_prochk_set_psarg   (const char *str);
 | 
|---|
 | 112 | static int sh_prochk_set_interval(const char *str);
 | 
|---|
 | 113 | static int sh_prochk_set_severity(const char *str);
 | 
|---|
| [204] | 114 | static int sh_prochk_set_openvz  (const char *str);
 | 
|---|
| [67] | 115 | 
 | 
|---|
 | 116 | sh_rconf sh_prochk_table[] = {
 | 
|---|
 | 117 |     {
 | 
|---|
 | 118 |         N_("severityprocesscheck"),
 | 
|---|
 | 119 |         sh_prochk_set_severity,
 | 
|---|
 | 120 |     },
 | 
|---|
 | 121 |     {
 | 
|---|
 | 122 |         N_("processcheckexists"),
 | 
|---|
 | 123 |         sh_prochk_add_process,
 | 
|---|
 | 124 |     },
 | 
|---|
 | 125 |     {
 | 
|---|
 | 126 |         N_("processcheckactive"),
 | 
|---|
 | 127 |         sh_prochk_set_active,
 | 
|---|
 | 128 |     },
 | 
|---|
 | 129 |     {
 | 
|---|
 | 130 |         N_("processcheckminpid"),
 | 
|---|
 | 131 |         sh_prochk_set_minpid,
 | 
|---|
 | 132 |     },
 | 
|---|
 | 133 |     {
 | 
|---|
 | 134 |         N_("processcheckmaxpid"),
 | 
|---|
 | 135 |         sh_prochk_set_maxpid,
 | 
|---|
 | 136 |     },
 | 
|---|
 | 137 |     {
 | 
|---|
 | 138 |         N_("processcheckpspath"),
 | 
|---|
 | 139 |         sh_prochk_set_pspath,
 | 
|---|
 | 140 |     },
 | 
|---|
 | 141 |     {
 | 
|---|
 | 142 |         N_("processcheckpsarg"),
 | 
|---|
 | 143 |         sh_prochk_set_psarg,
 | 
|---|
 | 144 |     },
 | 
|---|
 | 145 |     {
 | 
|---|
 | 146 |         N_("processcheckinterval"),
 | 
|---|
 | 147 |         sh_prochk_set_interval,
 | 
|---|
 | 148 |     },
 | 
|---|
 | 149 |     {
 | 
|---|
| [204] | 150 |         N_("processcheckisopenvz"),
 | 
|---|
 | 151 |         sh_prochk_set_openvz,
 | 
|---|
 | 152 |     },
 | 
|---|
 | 153 |     {
 | 
|---|
| [67] | 154 |         NULL,
 | 
|---|
 | 155 |         NULL
 | 
|---|
 | 156 |     }
 | 
|---|
 | 157 | };
 | 
|---|
 | 158 | 
 | 
|---|
 | 159 | #define    SH_PROC_MISSING 1
 | 
|---|
 | 160 | #define    SH_PROC_FAKED   2
 | 
|---|
 | 161 | #define    SH_PROC_HIDDEN  4
 | 
|---|
 | 162 | #define    SH_PROC_EXISTS  8
 | 
|---|
 | 163 | 
 | 
|---|
 | 164 | #ifndef HAVE_LSTAT
 | 
|---|
 | 165 | #define lstat(x,y) stat(x,y)
 | 
|---|
 | 166 | #endif /* HAVE_LSTAT */
 | 
|---|
 | 167 | 
 | 
|---|
| [82] | 168 | #if defined(S_IFLNK) && !defined(S_ISLNK)
 | 
|---|
 | 169 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
 | 
|---|
 | 170 | #else
 | 
|---|
 | 171 | #if !defined(S_ISLNK)
 | 
|---|
 | 172 | #define S_ISLNK(mode) (0)
 | 
|---|
 | 173 | #endif
 | 
|---|
 | 174 | #endif
 | 
|---|
 | 175 | 
 | 
|---|
| [67] | 176 | static const short SH_PR_PS       = 0x0001;
 | 
|---|
 | 177 | 
 | 
|---|
 | 178 | static const short SH_PR_GETSID   = 0x0002;
 | 
|---|
 | 179 | static const short SH_PR_KILL     = 0x0004;
 | 
|---|
 | 180 | static const short SH_PR_GETPGID  = 0x0008;
 | 
|---|
 | 181 | 
 | 
|---|
 | 182 | static const short SH_PR_LSTAT    = 0x0010;
 | 
|---|
 | 183 | static const short SH_PR_OPENDIR  = 0x0020;
 | 
|---|
 | 184 | static const short SH_PR_CHDIR    = 0x0040;
 | 
|---|
 | 185 | static const short SH_PR_SCHED    = 0x0080;
 | 
|---|
 | 186 | 
 | 
|---|
 | 187 | static const short SH_PR_PRIORITY = 0x0100;
 | 
|---|
| [78] | 188 | static const short SH_PR_STATVSF  = 0x0200;
 | 
|---|
| [67] | 189 | 
 | 
|---|
| [78] | 190 | static const short SH_PR_PS2      = 0x1000;
 | 
|---|
 | 191 | static const short SH_PR_PS_ANY   = 0x2000;
 | 
|---|
 | 192 | static const short SH_PR_ALL      = 0x4000;
 | 
|---|
 | 193 | static const short SH_PR_ANY      = 0x8000;
 | 
|---|
| [67] | 194 | 
 | 
|---|
| [77] | 195 | /* /proc: 
 | 
|---|
 | 196 |  *        linux:     /proc/pid/exe
 | 
|---|
 | 197 |  *        freebsd:   /proc/pid/file
 | 
|---|
 | 198 |  *        solaris10: /proc/pid/path/a.out
 | 
|---|
 | 199 |  */
 | 
|---|
| [78] | 200 | static char * get_user_and_path (pid_t pid, char * user, size_t usrlen)
 | 
|---|
 | 201 | {
 | 
|---|
| [132] | 202 |   extern char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
 | 
|---|
| [77] | 203 | 
 | 
|---|
| [78] | 204 |   char        path[128];
 | 
|---|
 | 205 |   char *      buf;
 | 
|---|
 | 206 |   struct stat sbuf;
 | 
|---|
 | 207 |   int         len;
 | 
|---|
 | 208 |   char *      tmp;
 | 
|---|
 | 209 | 
 | 
|---|
| [203] | 210 |   sl_snprintf (path, sizeof(path), _("/proc/%ld/exe"), (unsigned long) pid);
 | 
|---|
| [78] | 211 | 
 | 
|---|
 | 212 |   if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
 | 
|---|
 | 213 |     {
 | 
|---|
 | 214 |       goto linkread;
 | 
|---|
 | 215 |     }
 | 
|---|
 | 216 | 
 | 
|---|
| [203] | 217 |   sl_snprintf (path, sizeof(path), _("/proc/%ld/file"), (unsigned long) pid);
 | 
|---|
| [78] | 218 | 
 | 
|---|
 | 219 |   if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
 | 
|---|
 | 220 |     {
 | 
|---|
 | 221 |       goto linkread;
 | 
|---|
 | 222 |     }
 | 
|---|
 | 223 | 
 | 
|---|
| [203] | 224 |   sl_snprintf (path, sizeof(path), _("/proc/%ld/path/a.out"), (unsigned long) pid);
 | 
|---|
| [78] | 225 | 
 | 
|---|
 | 226 |   if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
 | 
|---|
 | 227 |     {
 | 
|---|
 | 228 |       goto linkread;
 | 
|---|
 | 229 |     }
 | 
|---|
 | 230 | 
 | 
|---|
 | 231 |   return NULL;
 | 
|---|
 | 232 | 
 | 
|---|
 | 233 |  linkread:
 | 
|---|
 | 234 | 
 | 
|---|
 | 235 |   buf = SH_ALLOC(PATH_MAX);
 | 
|---|
 | 236 |   len = readlink(path, buf, PATH_MAX);   /* flawfinder: ignore */
 | 
|---|
 | 237 |   len = (len >= PATH_MAX) ? (PATH_MAX-1) : len;
 | 
|---|
 | 238 | 
 | 
|---|
 | 239 |   if (len > 0)
 | 
|---|
 | 240 |     { 
 | 
|---|
 | 241 |       buf[len] = '\0';
 | 
|---|
 | 242 |     }
 | 
|---|
 | 243 |   else
 | 
|---|
 | 244 |     {
 | 
|---|
 | 245 |       SH_FREE(buf);
 | 
|---|
 | 246 |       return NULL;
 | 
|---|
 | 247 |     }
 | 
|---|
 | 248 | 
 | 
|---|
| [132] | 249 |   tmp = sh_unix_getUIDname (SH_ERR_ALL, sbuf.st_uid, user, usrlen);
 | 
|---|
| [78] | 250 | 
 | 
|---|
| [132] | 251 |   if (!tmp)
 | 
|---|
| [78] | 252 |     sl_snprintf (user, usrlen, "%ld", (unsigned long) sbuf.st_uid);
 | 
|---|
 | 253 | 
 | 
|---|
 | 254 |   return buf;
 | 
|---|
 | 255 | }
 | 
|---|
 | 256 | 
 | 
|---|
 | 257 | 
 | 
|---|
| [67] | 258 | struct watchlist {
 | 
|---|
 | 259 |   char        * str;
 | 
|---|
 | 260 |   unsigned long pid;
 | 
|---|
 | 261 | #ifdef HAVE_REGEX_H
 | 
|---|
 | 262 |   regex_t       preg;
 | 
|---|
 | 263 | #endif
 | 
|---|
 | 264 |   int           seen;
 | 
|---|
 | 265 | 
 | 
|---|
 | 266 |   struct watchlist *next;
 | 
|---|
 | 267 | };
 | 
|---|
 | 268 | 
 | 
|---|
 | 269 | static struct watchlist * process_check = NULL;
 | 
|---|
 | 270 | 
 | 
|---|
 | 271 | static struct watchlist * list_missing  = NULL;
 | 
|---|
 | 272 | static struct watchlist * list_fake     = NULL;
 | 
|---|
 | 273 | static struct watchlist * list_hidden   = NULL;
 | 
|---|
 | 274 | 
 | 
|---|
 | 275 | /* recursively remove all list entries
 | 
|---|
 | 276 |  */
 | 
|---|
 | 277 | static void kill_list (struct watchlist * head)
 | 
|---|
 | 278 | {
 | 
|---|
 | 279 |   if (head->next)
 | 
|---|
 | 280 |     kill_list (head->next);
 | 
|---|
 | 281 | 
 | 
|---|
 | 282 |   if (head->str)
 | 
|---|
 | 283 |     SH_FREE(head->str);
 | 
|---|
 | 284 |   SH_FREE(head);
 | 
|---|
 | 285 | 
 | 
|---|
 | 286 |   return;
 | 
|---|
 | 287 | }
 | 
|---|
 | 288 | 
 | 
|---|
 | 289 |   
 | 
|---|
 | 290 | /* check the list for old entries; clean out old entries; reset others
 | 
|---|
 | 291 |  * Return number of non-obsolete entries
 | 
|---|
 | 292 |  */
 | 
|---|
 | 293 | static size_t clean_list (struct watchlist ** head_ptr)
 | 
|---|
 | 294 | {
 | 
|---|
 | 295 |   size_t count = 0;
 | 
|---|
 | 296 |   struct watchlist * ptr = *head_ptr;
 | 
|---|
 | 297 |   struct watchlist * pre = *head_ptr;
 | 
|---|
 | 298 | 
 | 
|---|
 | 299 |   while (ptr)
 | 
|---|
 | 300 |     {
 | 
|---|
 | 301 |       if (ptr->seen == S_FALSE) /* obsolete entry */
 | 
|---|
 | 302 |         {
 | 
|---|
 | 303 |           if (ptr == pre)       /* at head        */
 | 
|---|
 | 304 |             {
 | 
|---|
 | 305 |               ptr       = pre->next;
 | 
|---|
 | 306 |               *head_ptr = pre->next;
 | 
|---|
 | 307 |               if (pre->str) 
 | 
|---|
 | 308 |                 SH_FREE(pre->str);
 | 
|---|
 | 309 |               SH_FREE(pre);
 | 
|---|
 | 310 |               pre       = ptr;
 | 
|---|
 | 311 |             }
 | 
|---|
 | 312 |           else
 | 
|---|
 | 313 |             {
 | 
|---|
 | 314 |               pre->next = ptr->next;
 | 
|---|
 | 315 |               if (ptr->str) 
 | 
|---|
 | 316 |                 SH_FREE(ptr->str);
 | 
|---|
 | 317 |               SH_FREE(ptr);
 | 
|---|
 | 318 |               ptr       = pre->next;
 | 
|---|
 | 319 |             }
 | 
|---|
 | 320 |         }
 | 
|---|
 | 321 |       else
 | 
|---|
 | 322 |         {
 | 
|---|
 | 323 |           ++count;
 | 
|---|
 | 324 |           ptr->seen = S_FALSE; /* reset status */
 | 
|---|
 | 325 |           pre = ptr;
 | 
|---|
 | 326 |           ptr = ptr->next;
 | 
|---|
 | 327 |         }
 | 
|---|
 | 328 |     }
 | 
|---|
 | 329 |   return count;
 | 
|---|
 | 330 | }
 | 
|---|
 | 331 | 
 | 
|---|
 | 332 | /* check if process is in list; if not, add it and return false
 | 
|---|
 | 333 |  */
 | 
|---|
 | 334 | static int  is_in_list (struct watchlist ** head_ptr, 
 | 
|---|
 | 335 |                         char * str, unsigned long pid)
 | 
|---|
 | 336 | {
 | 
|---|
 | 337 |   struct watchlist * ptr = *head_ptr;
 | 
|---|
 | 338 | 
 | 
|---|
 | 339 |   if (str)
 | 
|---|
 | 340 |     {
 | 
|---|
 | 341 |       while (ptr)
 | 
|---|
 | 342 |         {
 | 
|---|
 | 343 |           if (ptr->str && (0 == strcmp(str, ptr->str)))
 | 
|---|
 | 344 |             {
 | 
|---|
 | 345 |               ptr->seen = S_TRUE;
 | 
|---|
 | 346 |               return S_TRUE;
 | 
|---|
 | 347 |             }
 | 
|---|
 | 348 |           ptr = ptr->next;
 | 
|---|
 | 349 |         }
 | 
|---|
 | 350 |     }
 | 
|---|
 | 351 |   else
 | 
|---|
 | 352 |     {
 | 
|---|
 | 353 |       while (ptr)
 | 
|---|
 | 354 |         {
 | 
|---|
 | 355 |           if (ptr->pid == pid)
 | 
|---|
 | 356 |             {
 | 
|---|
 | 357 |               ptr->seen = S_TRUE;
 | 
|---|
 | 358 |               return S_TRUE;
 | 
|---|
 | 359 |             }
 | 
|---|
 | 360 |           ptr = ptr->next;
 | 
|---|
 | 361 |         }
 | 
|---|
 | 362 |     }
 | 
|---|
 | 363 | 
 | 
|---|
 | 364 |   ptr = SH_ALLOC(sizeof(struct watchlist));
 | 
|---|
 | 365 | 
 | 
|---|
 | 366 |   if (str)
 | 
|---|
 | 367 |     {
 | 
|---|
 | 368 |       ptr->str = sh_util_strdup(str);
 | 
|---|
 | 369 |     }
 | 
|---|
 | 370 |   else
 | 
|---|
 | 371 |     {
 | 
|---|
 | 372 |       ptr->str = NULL;
 | 
|---|
 | 373 |       ptr->pid = pid;
 | 
|---|
 | 374 |     }
 | 
|---|
 | 375 |   ptr->next = *head_ptr;
 | 
|---|
 | 376 |   ptr->seen = S_TRUE;
 | 
|---|
 | 377 |   *head_ptr = ptr;
 | 
|---|
 | 378 | 
 | 
|---|
 | 379 |   return S_FALSE;
 | 
|---|
 | 380 | }
 | 
|---|
 | 381 | 
 | 
|---|
 | 382 | static int is_in_watchlist (const char *str, unsigned long num)
 | 
|---|
 | 383 | {
 | 
|---|
 | 384 |   struct watchlist * list = process_check;
 | 
|---|
 | 385 | 
 | 
|---|
 | 386 |   while (list) 
 | 
|---|
 | 387 |     {
 | 
|---|
 | 388 | #ifdef HAVE_REGEX_H
 | 
|---|
 | 389 |       if (0 == regexec(&(list->preg), str, 0, NULL, 0))
 | 
|---|
 | 390 |         {
 | 
|---|
 | 391 |           list->seen = S_TRUE;
 | 
|---|
 | 392 |           list->pid  = num;
 | 
|---|
 | 393 |           return S_TRUE;
 | 
|---|
 | 394 |         }
 | 
|---|
 | 395 | #else
 | 
|---|
 | 396 |       if (strstr(str, list->str)) 
 | 
|---|
 | 397 |         {
 | 
|---|
 | 398 |           list->seen = S_TRUE;
 | 
|---|
 | 399 |           list->pid  = num;
 | 
|---|
 | 400 |           return S_TRUE;
 | 
|---|
 | 401 |         }
 | 
|---|
 | 402 | #endif
 | 
|---|
 | 403 |       list = list->next;
 | 
|---|
 | 404 |     }
 | 
|---|
 | 405 |   return S_FALSE;
 | 
|---|
 | 406 | } 
 | 
|---|
 | 407 | 
 | 
|---|
| [170] | 408 | /* These variables are not used anywhere. They only exist
 | 
|---|
 | 409 |  * to assign &userold, &user to them, which keeps gcc from
 | 
|---|
 | 410 |  * putting them into a register, and avoids the 'clobbered
 | 
|---|
 | 411 |  * by longjmp' warning. And no, 'volatile' proved insufficient.
 | 
|---|
 | 412 |  */
 | 
|---|
 | 413 | static void * sh_dummy_watchlist = NULL;
 | 
|---|
 | 414 | 
 | 
|---|
| [67] | 415 | static void check_watchlist (short * res)
 | 
|---|
 | 416 | {
 | 
|---|
 | 417 |   struct watchlist * list = process_check;
 | 
|---|
 | 418 |   char * tmp;
 | 
|---|
 | 419 |   size_t indx;
 | 
|---|
 | 420 | 
 | 
|---|
| [170] | 421 |   /* Take the address to keep gcc from putting them into registers. 
 | 
|---|
 | 422 |    * Avoids the 'clobbered by longjmp' warning. 
 | 
|---|
 | 423 |    */
 | 
|---|
 | 424 |   sh_dummy_watchlist = (void*) &list;
 | 
|---|
 | 425 | 
 | 
|---|
| [67] | 426 |   while (list) 
 | 
|---|
 | 427 |     {
 | 
|---|
 | 428 |       if (list->seen == S_FALSE)
 | 
|---|
 | 429 |         {
 | 
|---|
 | 430 |           /* avoid repetition of messages
 | 
|---|
 | 431 |            */
 | 
|---|
 | 432 |           if (S_FALSE == is_in_list(&list_missing, list->str, 0))
 | 
|---|
 | 433 |             {
 | 
|---|
| [143] | 434 |               SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [170] | 435 |               tmp = sh_util_safe_name (list->str);
 | 
|---|
| [67] | 436 |               sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
 | 
|---|
 | 437 |                               MSG_PCK_MISS,
 | 
|---|
| [170] | 438 |                               tmp);
 | 
|---|
| [230] | 439 |               SH_FREE(tmp);
 | 
|---|
| [143] | 440 |               SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 441 |             }
 | 
|---|
 | 442 |         }
 | 
|---|
 | 443 |       else
 | 
|---|
 | 444 |         {
 | 
|---|
 | 445 |           indx = list->pid - sh_prochk_minpid;
 | 
|---|
 | 446 | 
 | 
|---|
 | 447 |           if (list->pid < sh_prochk_maxpid && list->pid >= sh_prochk_minpid && 
 | 
|---|
 | 448 |               ((res[indx] & SH_PR_ANY) == 0) && /* not found         */
 | 
|---|
 | 449 |               ((res[indx] & SH_PR_PS)  != 0) && /* seen in first ps  */ 
 | 
|---|
 | 450 |               ((res[indx] & SH_PR_PS2) != 0))   /* seen in second ps */
 | 
|---|
 | 451 |             {
 | 
|---|
 | 452 |               /* fake process, thus considered missing
 | 
|---|
 | 453 |                */
 | 
|---|
 | 454 |               if (S_FALSE == is_in_list(&list_missing, list->str, 0))
 | 
|---|
 | 455 |                 {
 | 
|---|
| [170] | 456 |                   SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 457 |                   tmp = sh_util_safe_name (list->str);
 | 
|---|
 | 458 |                   sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
 | 
|---|
 | 459 |                                   MSG_PCK_MISS, 
 | 
|---|
 | 460 |                                   tmp);
 | 
|---|
| [230] | 461 |                   SH_FREE(tmp);
 | 
|---|
| [143] | 462 |                   SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 463 |                 }
 | 
|---|
 | 464 |             }
 | 
|---|
 | 465 |           list->seen = S_FALSE;
 | 
|---|
 | 466 |         }
 | 
|---|
 | 467 |       list = list->next;
 | 
|---|
 | 468 |     }
 | 
|---|
| [383] | 469 | 
 | 
|---|
 | 470 |   sh_dummy_watchlist = NULL;
 | 
|---|
 | 471 |   return;
 | 
|---|
| [67] | 472 | }
 | 
|---|
 | 473 | 
 | 
|---|
 | 474 | /* Add 'str' to the list of watched processes for which
 | 
|---|
 | 475 |  * existence should be checked.
 | 
|---|
 | 476 |  */
 | 
|---|
 | 477 | int sh_prochk_add_process (const char *str) 
 | 
|---|
 | 478 | {
 | 
|---|
 | 479 |   struct watchlist *new;
 | 
|---|
 | 480 |   int               status;
 | 
|---|
 | 481 |   char              errbuf[256];
 | 
|---|
 | 482 |     
 | 
|---|
 | 483 |   SL_ENTER(_("sh_prochk_add_process"));
 | 
|---|
 | 484 | 
 | 
|---|
 | 485 |   if( str == NULL )
 | 
|---|
 | 486 |     SL_RETURN(-1, _("sh_prochk_add_process") );
 | 
|---|
 | 487 | 
 | 
|---|
 | 488 |   new       = SH_ALLOC(sizeof(struct watchlist));
 | 
|---|
 | 489 |   new->next = process_check;
 | 
|---|
 | 490 |   new->str  = sh_util_strdup(str);
 | 
|---|
 | 491 | #ifdef HAVE_REGEX_H
 | 
|---|
 | 492 |   status = regcomp(&(new->preg), str, REG_NOSUB|REG_EXTENDED);
 | 
|---|
 | 493 |   if (status != 0)
 | 
|---|
 | 494 |     {
 | 
|---|
 | 495 |       regerror(status, &(new->preg), errbuf, sizeof(errbuf));
 | 
|---|
| [143] | 496 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 497 |       sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, 
 | 
|---|
| [143] | 498 |                       errbuf, _("sh_processes_add_process"));
 | 
|---|
 | 499 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 500 |       SH_FREE(new->str);
 | 
|---|
 | 501 |       SH_FREE(new);
 | 
|---|
 | 502 |       SL_RETURN(-1, _("sh_prochk_add_process") );
 | 
|---|
 | 503 |     }
 | 
|---|
 | 504 | #endif
 | 
|---|
 | 505 |   new->pid  = 0;
 | 
|---|
 | 506 |   new->seen = S_FALSE;
 | 
|---|
 | 507 | 
 | 
|---|
 | 508 |   process_check = new;
 | 
|---|
 | 509 |   SL_RETURN(0, _("sh_prochk_add_process") );
 | 
|---|
 | 510 | }
 | 
|---|
 | 511 | 
 | 
|---|
 | 512 | /* severity
 | 
|---|
 | 513 |  */
 | 
|---|
 | 514 | int sh_prochk_set_severity  (const char * c)
 | 
|---|
 | 515 | {
 | 
|---|
 | 516 |   char tmp[32];
 | 
|---|
 | 517 |   tmp[0] = '='; tmp[1] = '\0';
 | 
|---|
 | 518 |   sl_strlcat (tmp, c, 32);
 | 
|---|
 | 519 |   return sh_error_set_level (tmp, &sh_prochk_severity);
 | 
|---|
 | 520 | }
 | 
|---|
 | 521 | 
 | 
|---|
 | 522 | 
 | 
|---|
 | 523 | 
 | 
|---|
 | 524 | /* Path to ps
 | 
|---|
 | 525 |  */
 | 
|---|
 | 526 | int sh_prochk_set_pspath(const char *str) 
 | 
|---|
 | 527 | {
 | 
|---|
 | 528 |   SL_ENTER(_("sh_prochk_set_pspath"));
 | 
|---|
 | 529 | 
 | 
|---|
| [383] | 530 |   if (!str || ('/' != str[0]))
 | 
|---|
| [204] | 531 |     SL_RETURN((-1), _("sh_prochk_set_pspath"));
 | 
|---|
| [67] | 532 |   if (sh_prochk_pspath)
 | 
|---|
 | 533 |     SH_FREE(sh_prochk_pspath);
 | 
|---|
| [374] | 534 | #ifdef SH_EVAL_SHELL
 | 
|---|
| [67] | 535 |   sh_prochk_pspath = sh_util_strdup (str);
 | 
|---|
 | 536 |   SL_RETURN((0), _("sh_prochk_set_pspath"));
 | 
|---|
| [374] | 537 | #else
 | 
|---|
 | 538 |   sh_prochk_pspath = NULL;
 | 
|---|
 | 539 |   SL_RETURN((-1), _("sh_prochk_set_pspath"));
 | 
|---|
 | 540 | #endif
 | 
|---|
| [67] | 541 | }
 | 
|---|
 | 542 | 
 | 
|---|
 | 543 | /* argument for ps
 | 
|---|
 | 544 |  */
 | 
|---|
 | 545 | int sh_prochk_set_psarg(const char *str) 
 | 
|---|
 | 546 | {
 | 
|---|
 | 547 |   SL_ENTER(_("sh_prochk_set_psarg"));
 | 
|---|
 | 548 | 
 | 
|---|
 | 549 |   if (sh_prochk_psarg)
 | 
|---|
 | 550 |     SH_FREE(sh_prochk_psarg);
 | 
|---|
| [374] | 551 | #ifdef SH_EVAL_SHELL
 | 
|---|
| [67] | 552 |   sh_prochk_psarg = sh_util_strdup (str);
 | 
|---|
 | 553 |   SL_RETURN((0), _("sh_prochk_set_psarg"));
 | 
|---|
| [374] | 554 | #else
 | 
|---|
 | 555 |   sh_prochk_psarg = NULL;
 | 
|---|
 | 556 |   SL_RETURN((-1), _("sh_prochk_set_psarg"));
 | 
|---|
 | 557 | #endif
 | 
|---|
| [67] | 558 | }
 | 
|---|
 | 559 | 
 | 
|---|
 | 560 | 
 | 
|---|
 | 561 | /* Decide if we're active.
 | 
|---|
 | 562 |  */
 | 
|---|
 | 563 | int sh_prochk_set_active(const char *str) 
 | 
|---|
 | 564 | {
 | 
|---|
 | 565 |   int value;
 | 
|---|
 | 566 |     
 | 
|---|
 | 567 |   SL_ENTER(_("sh_prochk_set_active"));
 | 
|---|
 | 568 | 
 | 
|---|
 | 569 |   value = sh_util_flagval(str, &ShProchkActive);
 | 
|---|
 | 570 | 
 | 
|---|
 | 571 |   SL_RETURN((value), _("sh_prochk_set_active"));
 | 
|---|
 | 572 | }
 | 
|---|
 | 573 | 
 | 
|---|
| [204] | 574 | /* Are we on openvz.
 | 
|---|
 | 575 |  */
 | 
|---|
 | 576 | static int openvz_hidden = 0;
 | 
|---|
 | 577 | 
 | 
|---|
 | 578 | int sh_prochk_set_openvz(const char *str) 
 | 
|---|
 | 579 | {
 | 
|---|
 | 580 |   int value;
 | 
|---|
 | 581 |     
 | 
|---|
 | 582 |   SL_ENTER(_("sh_prochk_set_openvz"));
 | 
|---|
 | 583 | 
 | 
|---|
 | 584 |   value = sh_util_flagval(str, &sh_prochk_openvz);
 | 
|---|
 | 585 | 
 | 
|---|
 | 586 |   if (sh_prochk_openvz != S_FALSE) {
 | 
|---|
 | 587 |     openvz_hidden = 1;
 | 
|---|
 | 588 |   }
 | 
|---|
 | 589 | 
 | 
|---|
 | 590 |   SL_RETURN((value), _("sh_prochk_set_openvz"));
 | 
|---|
 | 591 | }
 | 
|---|
 | 592 | 
 | 
|---|
| [67] | 593 | /* Minimum PID
 | 
|---|
 | 594 |  */
 | 
|---|
 | 595 | int sh_prochk_set_minpid(const char * str)
 | 
|---|
 | 596 | {
 | 
|---|
 | 597 |   size_t  value;
 | 
|---|
 | 598 |   char * foo;
 | 
|---|
 | 599 |   int    retval = 0;
 | 
|---|
 | 600 | 
 | 
|---|
 | 601 |   SL_ENTER(_("sh_prochk_set_minpid"));
 | 
|---|
 | 602 | 
 | 
|---|
 | 603 |   value = (size_t) strtoul(str, &foo, 0);
 | 
|---|
 | 604 |   if (*foo != '\0')
 | 
|---|
 | 605 |     retval = -1;
 | 
|---|
 | 606 |   else
 | 
|---|
 | 607 |     sh_prochk_minpid = value;
 | 
|---|
 | 608 | 
 | 
|---|
 | 609 |   SL_RETURN((retval), _("sh_prochk_set_minpid"));
 | 
|---|
 | 610 | }
 | 
|---|
 | 611 | 
 | 
|---|
 | 612 | /* Maximum PID
 | 
|---|
 | 613 |  */
 | 
|---|
 | 614 | static int userdef_maxpid = 0;
 | 
|---|
 | 615 | 
 | 
|---|
 | 616 | int sh_prochk_set_maxpid(const char * str)
 | 
|---|
 | 617 | {
 | 
|---|
 | 618 |   size_t  value;
 | 
|---|
 | 619 |   char * foo;
 | 
|---|
| [78] | 620 |   int    retval = -1;
 | 
|---|
| [67] | 621 | 
 | 
|---|
 | 622 |   SL_ENTER(_("sh_prochk_set_maxpid"));
 | 
|---|
 | 623 | 
 | 
|---|
 | 624 |   value = (size_t) strtoul(str, &foo, 0);
 | 
|---|
| [78] | 625 | 
 | 
|---|
 | 626 |   if (*foo == '\0' && SL_TRUE == sl_ok_adds(value, 1)) {
 | 
|---|
| [67] | 627 |     sh_prochk_maxpid = value + 1;
 | 
|---|
 | 628 |     userdef_maxpid   = 1;
 | 
|---|
| [290] | 629 |     retval = 0;
 | 
|---|
| [67] | 630 |   }
 | 
|---|
 | 631 | 
 | 
|---|
 | 632 |   SL_RETURN((retval), _("sh_prochk_set_maxpid"));
 | 
|---|
 | 633 | }
 | 
|---|
 | 634 | 
 | 
|---|
 | 635 | int sh_prochk_set_interval (const char * c)
 | 
|---|
 | 636 | {
 | 
|---|
 | 637 |   int retval = 0;
 | 
|---|
 | 638 |   long val;
 | 
|---|
 | 639 | 
 | 
|---|
 | 640 |   SL_ENTER(_("sh_prochk_set_interval"));
 | 
|---|
 | 641 |   val = strtol (c, (char **)NULL, 10);
 | 
|---|
 | 642 |   if (val <= 0)
 | 
|---|
 | 643 |     {
 | 
|---|
| [143] | 644 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 645 |       sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
 | 
|---|
 | 646 |                        _("process check interval"), c);
 | 
|---|
| [143] | 647 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 648 |       retval = -1;
 | 
|---|
 | 649 |     }
 | 
|---|
| [362] | 650 |   else
 | 
|---|
 | 651 |     {
 | 
|---|
 | 652 |       sh_prochk_interval = (time_t) val;
 | 
|---|
 | 653 |     }
 | 
|---|
 | 654 |   SL_RETURN(retval, _("sh_prochk_set_interval"));
 | 
|---|
| [67] | 655 | }
 | 
|---|
 | 656 | 
 | 
|---|
 | 657 | 
 | 
|---|
 | 658 | 
 | 
|---|
 | 659 | /* Recurse to the end of the list and then free the data as we return
 | 
|---|
 | 660 |  * back up towards the start, making sure to free any strdupped strings
 | 
|---|
 | 661 |  */
 | 
|---|
 | 662 | static void sh_prochk_free_list(struct watchlist *head) 
 | 
|---|
 | 663 | {
 | 
|---|
 | 664 |   if ( head != NULL ) 
 | 
|---|
 | 665 |     {
 | 
|---|
 | 666 |       sh_prochk_free_list(head->next);
 | 
|---|
 | 667 |       if (head->str)
 | 
|---|
 | 668 |         SH_FREE(head->str);
 | 
|---|
 | 669 | #ifdef HAVE_REGEX_H
 | 
|---|
 | 670 |       regfree(&(head->preg));
 | 
|---|
 | 671 | #endif
 | 
|---|
 | 672 |       SH_FREE(head);
 | 
|---|
 | 673 |     }
 | 
|---|
 | 674 |   return;
 | 
|---|
 | 675 | }
 | 
|---|
 | 676 | 
 | 
|---|
 | 677 | #if defined(__linux__)
 | 
|---|
 | 678 | #define PROC_PID_MAX _("/proc/sys/kernel/pid_max")
 | 
|---|
 | 679 | 
 | 
|---|
 | 680 | static int proc_max_pid (size_t * procpid)
 | 
|---|
 | 681 | {
 | 
|---|
| [170] | 682 |   char * ret;
 | 
|---|
| [67] | 683 |   unsigned long  pid;
 | 
|---|
 | 684 |   FILE * fd;
 | 
|---|
 | 685 |   char   str[128];
 | 
|---|
 | 686 |   char * ptr;
 | 
|---|
 | 687 | 
 | 
|---|
 | 688 |   SL_ENTER(_("proc_max_pid"));
 | 
|---|
 | 689 | 
 | 
|---|
 | 690 |   if (userdef_maxpid != 0)
 | 
|---|
 | 691 |     SL_RETURN((-1), _("proc_max_pid"));
 | 
|---|
 | 692 |     
 | 
|---|
| [73] | 693 |   if (0 == access(PROC_PID_MAX, R_OK)) /* flawfinder: ignore */
 | 
|---|
| [67] | 694 |     {
 | 
|---|
 | 695 |       if (NULL != (fd = fopen(PROC_PID_MAX, "r")))
 | 
|---|
 | 696 |         {
 | 
|---|
 | 697 |           str[0] = '\0';
 | 
|---|
| [170] | 698 |           ret = fgets(str, 128, fd);
 | 
|---|
 | 699 |           if (ret && *str != '\0')
 | 
|---|
| [67] | 700 |             {
 | 
|---|
 | 701 |               pid = strtoul(str, &ptr, 0);
 | 
|---|
 | 702 |               if (*ptr == '\0' || *ptr == '\n')
 | 
|---|
 | 703 |                 {
 | 
|---|
| [252] | 704 |                   sl_fclose(FIL__, __LINE__, fd);
 | 
|---|
| [67] | 705 |                   *procpid = (size_t) pid;
 | 
|---|
 | 706 |                   SL_RETURN(0, _("proc_max_pid"));
 | 
|---|
 | 707 |                 }
 | 
|---|
 | 708 |             }
 | 
|---|
| [252] | 709 |           sl_fclose(FIL__, __LINE__, fd);
 | 
|---|
| [67] | 710 |         }
 | 
|---|
 | 711 |     }
 | 
|---|
 | 712 |   SL_RETURN((-1), _("proc_max_pid"));
 | 
|---|
 | 713 | }
 | 
|---|
 | 714 | #else
 | 
|---|
 | 715 | static int proc_max_pid(size_t * dummy)
 | 
|---|
 | 716 | {
 | 
|---|
 | 717 |   (void) dummy;
 | 
|---|
 | 718 |   return -1;
 | 
|---|
 | 719 | }
 | 
|---|
 | 720 | #endif
 | 
|---|
 | 721 | 
 | 
|---|
 | 722 | static void sh_processes_tlist (char * list, size_t len, short res)
 | 
|---|
 | 723 | {
 | 
|---|
 | 724 |   if (res & SH_PR_PS)       sl_strlcat(list, _(" ps(initial)"), len);
 | 
|---|
 | 725 |   if (res & SH_PR_CHDIR)    sl_strlcat(list, _(" chdir"), len);
 | 
|---|
 | 726 |   if (res & SH_PR_OPENDIR)  sl_strlcat(list, _(" opendir"), len);
 | 
|---|
 | 727 |   if (res & SH_PR_LSTAT)    sl_strlcat(list, _(" lstat"), len);
 | 
|---|
 | 728 |   if (res & SH_PR_PRIORITY) sl_strlcat(list, _(" getpriority"), len);
 | 
|---|
 | 729 |   if (res & SH_PR_SCHED)    sl_strlcat(list, _(" sched_getparam"), len);
 | 
|---|
 | 730 |   if (res & SH_PR_GETSID)   sl_strlcat(list, _(" getsid"), len);
 | 
|---|
 | 731 |   if (res & SH_PR_GETPGID)  sl_strlcat(list, _(" getpgid"), len);
 | 
|---|
 | 732 |   if (res & SH_PR_KILL)     sl_strlcat(list, _(" kill"), len);
 | 
|---|
| [78] | 733 |   if (res & SH_PR_STATVSF)  sl_strlcat(list, _(" statvfs"), len);
 | 
|---|
| [67] | 734 |   if (res & SH_PR_PS2)      sl_strlcat(list, _(" ps(final)"), len);
 | 
|---|
 | 735 |   return;
 | 
|---|
 | 736 | }
 | 
|---|
 | 737 | 
 | 
|---|
| [78] | 738 | 
 | 
|---|
| [67] | 739 | static short sh_processes_check (pid_t pid, short res)
 | 
|---|
 | 740 | {
 | 
|---|
 | 741 |   int  have_checks = 0;
 | 
|---|
 | 742 |   int  need_checks = 0;
 | 
|---|
 | 743 | #ifdef HAVE_PROCFS
 | 
|---|
 | 744 |   char path[128];
 | 
|---|
 | 745 |   struct stat buf;
 | 
|---|
 | 746 |   DIR * dir;
 | 
|---|
| [144] | 747 |   int  retval;
 | 
|---|
| [258] | 748 | #if defined(HAVE_STATVFS) && !defined(__FreeBSD__)
 | 
|---|
| [78] | 749 |   struct statvfs vfsbuf;
 | 
|---|
 | 750 | #endif
 | 
|---|
| [82] | 751 | #endif
 | 
|---|
| [67] | 752 | 
 | 
|---|
 | 753 | #if !defined(sun) && !defined(__sun) && !defined(__sun__)
 | 
|---|
 | 754 | #ifdef _POSIX_PRIORITY_SCHEDULING
 | 
|---|
 | 755 |   struct sched_param p;
 | 
|---|
 | 756 | #endif
 | 
|---|
 | 757 | #endif
 | 
|---|
 | 758 | 
 | 
|---|
 | 759 |   if (0 == kill(pid, 0))
 | 
|---|
 | 760 |     { 
 | 
|---|
 | 761 |       res |= SH_PR_KILL;    res |= SH_PR_ANY; ++have_checks;
 | 
|---|
 | 762 |       ++need_checks;
 | 
|---|
 | 763 |     }
 | 
|---|
 | 764 |   else if (errno != EPERM)
 | 
|---|
 | 765 |     {
 | 
|---|
 | 766 |       ++need_checks;
 | 
|---|
 | 767 |     }
 | 
|---|
 | 768 | 
 | 
|---|
| [78] | 769 | 
 | 
|---|
| [67] | 770 | #ifdef HAVE_GETPGID
 | 
|---|
 | 771 |   if ((pid_t)-1 != getpgid(pid))
 | 
|---|
 | 772 |     { 
 | 
|---|
 | 773 |       res |= SH_PR_GETPGID; res |= SH_PR_ANY; ++have_checks;
 | 
|---|
 | 774 |     }
 | 
|---|
 | 775 |   ++need_checks;
 | 
|---|
 | 776 | #endif
 | 
|---|
 | 777 | 
 | 
|---|
 | 778 | #ifdef HAVE_GETSID
 | 
|---|
 | 779 |   if ((pid_t)-1 != getsid(pid))
 | 
|---|
 | 780 |     { 
 | 
|---|
 | 781 |       res |= SH_PR_GETSID;  res |= SH_PR_ANY; ++have_checks;
 | 
|---|
 | 782 |     }
 | 
|---|
 | 783 |   ++need_checks;
 | 
|---|
 | 784 | #endif
 | 
|---|
 | 785 | 
 | 
|---|
 | 786 |   /* sched_getparam() is broken on solaris 10, may segfault in librt
 | 
|---|
 | 787 |    */
 | 
|---|
 | 788 | #if !defined(sun) && !defined(__sun) && !defined(__sun__)
 | 
|---|
 | 789 | #ifdef _POSIX_PRIORITY_SCHEDULING
 | 
|---|
 | 790 |   if (0 == sched_getparam (pid, &p))
 | 
|---|
 | 791 |     { 
 | 
|---|
 | 792 |       res |= SH_PR_SCHED;   res |= SH_PR_ANY; ++have_checks;
 | 
|---|
 | 793 |     }
 | 
|---|
 | 794 |   ++need_checks;
 | 
|---|
 | 795 | #endif
 | 
|---|
 | 796 | #endif
 | 
|---|
 | 797 | 
 | 
|---|
 | 798 | #ifdef HAVE_GETPRIORITY
 | 
|---|
 | 799 |   errno = 0;
 | 
|---|
 | 800 |   if (((-1) == getpriority (PRIO_PROCESS, (int) pid)) && (errno == ESRCH));
 | 
|---|
 | 801 |   else
 | 
|---|
 | 802 |     { 
 | 
|---|
 | 803 |       res |= SH_PR_PRIORITY; res |= SH_PR_ANY; ++have_checks;
 | 
|---|
 | 804 |     }
 | 
|---|
 | 805 |   ++need_checks;
 | 
|---|
 | 806 | #endif
 | 
|---|
 | 807 | 
 | 
|---|
 | 808 | #ifdef HAVE_PROCFS
 | 
|---|
 | 809 |   sl_snprintf (path, sizeof(path), "/proc/%ld", (unsigned long) pid);
 | 
|---|
 | 810 | 
 | 
|---|
| [144] | 811 |   do {
 | 
|---|
 | 812 |     retval = lstat (path, &buf);
 | 
|---|
 | 813 |   } while (retval < 0 && errno == EINTR);
 | 
|---|
 | 814 | 
 | 
|---|
 | 815 |   if (0 == retval)
 | 
|---|
| [67] | 816 |     { 
 | 
|---|
 | 817 |       res |= SH_PR_LSTAT;   res |= SH_PR_ANY; ++have_checks;
 | 
|---|
 | 818 |     }
 | 
|---|
 | 819 |   ++need_checks;
 | 
|---|
 | 820 | 
 | 
|---|
 | 821 |   if (NULL != (dir = opendir(path)))
 | 
|---|
 | 822 |     {
 | 
|---|
 | 823 |       res |= SH_PR_OPENDIR; res |= SH_PR_ANY; ++have_checks;
 | 
|---|
 | 824 |       closedir(dir);
 | 
|---|
 | 825 |     }
 | 
|---|
 | 826 |   ++need_checks;
 | 
|---|
 | 827 | 
 | 
|---|
| [258] | 828 | #if defined(HAVE_STATVFS) && !defined(__FreeBSD__)
 | 
|---|
| [78] | 829 |   do {
 | 
|---|
 | 830 |     retval = statvfs (path, &vfsbuf);
 | 
|---|
 | 831 |   } while (retval < 0 && errno == EINTR);
 | 
|---|
 | 832 | 
 | 
|---|
 | 833 |   if (0 == retval)
 | 
|---|
 | 834 |     { 
 | 
|---|
 | 835 |       res |= SH_PR_STATVSF;   res |= SH_PR_ANY; ++have_checks;
 | 
|---|
 | 836 |     }
 | 
|---|
 | 837 |   ++need_checks;
 | 
|---|
 | 838 | #endif
 | 
|---|
 | 839 | 
 | 
|---|
| [67] | 840 | #if !defined(SH_PROFILE)
 | 
|---|
 | 841 |   if (0 == chdir(path))
 | 
|---|
 | 842 |     {
 | 
|---|
 | 843 |       res |= SH_PR_CHDIR;   res |= SH_PR_ANY; ++have_checks;
 | 
|---|
| [144] | 844 |       do {
 | 
|---|
 | 845 |         retval = chdir ("/");
 | 
|---|
 | 846 |       } while (retval < 0 && errno == EINTR);
 | 
|---|
| [67] | 847 |     }
 | 
|---|
 | 848 |   ++need_checks;
 | 
|---|
 | 849 | #endif
 | 
|---|
 | 850 | #endif
 | 
|---|
 | 851 | 
 | 
|---|
 | 852 |   if (have_checks == need_checks)
 | 
|---|
 | 853 |     {
 | 
|---|
 | 854 |       res |= SH_PR_ALL;
 | 
|---|
 | 855 |     }
 | 
|---|
 | 856 |   return res;
 | 
|---|
 | 857 | }
 | 
|---|
 | 858 | 
 | 
|---|
| [102] | 859 | extern int flag_err_debug;
 | 
|---|
 | 860 | 
 | 
|---|
| [67] | 861 | static int sh_processes_readps (FILE * in, short * res, 
 | 
|---|
 | 862 |                                 char * str, size_t len, 
 | 
|---|
 | 863 |                                 short flag, pid_t pid)
 | 
|---|
 | 864 | {
 | 
|---|
 | 865 |   int  cc; 
 | 
|---|
 | 866 |   unsigned int  lnum   = 0;
 | 
|---|
 | 867 |   unsigned long num    = 0;
 | 
|---|
 | 868 |   char c;
 | 
|---|
 | 869 |   unsigned int  pos = 0;
 | 
|---|
 | 870 |   char tstr[256];
 | 
|---|
| [103] | 871 |   enum { SKIP_TO_WS, SKIP_WS, SKIP_TO_WS2, SKIP_WS2, GET_NUM, SKIP_END, GET_NUM2 } line;
 | 
|---|
| [67] | 872 | 
 | 
|---|
 | 873 |   SL_ENTER(_("sh_processes_readps"));
 | 
|---|
 | 874 | 
 | 
|---|
 | 875 |   if (!in) {
 | 
|---|
 | 876 |     SL_RETURN((-1), _("sh_processes_readps"));
 | 
|---|
 | 877 |   }
 | 
|---|
 | 878 | 
 | 
|---|
 | 879 |   tstr[(sizeof(tstr)-1)] = '\0';
 | 
|---|
 | 880 |   tstr[0]                = '\0';
 | 
|---|
 | 881 |   line = SKIP_END;              /* Skip 1st line */
 | 
|---|
 | 882 | 
 | 
|---|
 | 883 |   do
 | 
|---|
 | 884 |     {
 | 
|---|
 | 885 |       cc = fgetc(in);
 | 
|---|
 | 886 | 
 | 
|---|
 | 887 |       if (EOF == cc) 
 | 
|---|
 | 888 |         {
 | 
|---|
 | 889 |           if (feof(in))
 | 
|---|
 | 890 |             {
 | 
|---|
 | 891 |               break;
 | 
|---|
 | 892 |             }
 | 
|---|
 | 893 |           else if (errno == EAGAIN)
 | 
|---|
 | 894 |             {
 | 
|---|
| [169] | 895 |               clearerr(in);
 | 
|---|
| [67] | 896 |               continue;
 | 
|---|
 | 897 |             }
 | 
|---|
| [169] | 898 | #ifdef HOST_IS_OPENBSD
 | 
|---|
 | 899 |           else if (errno == ENODEV)
 | 
|---|
 | 900 |             {
 | 
|---|
 | 901 |               clearerr(in);
 | 
|---|
 | 902 |               continue;
 | 
|---|
 | 903 |             }
 | 
|---|
 | 904 | #endif
 | 
|---|
| [67] | 905 |           else
 | 
|---|
 | 906 |             {
 | 
|---|
| [132] | 907 |               char errbuf[SH_ERRBUF_SIZE];
 | 
|---|
 | 908 | 
 | 
|---|
| [143] | 909 |               /* SH_MUTEX_LOCK(mutex_thread_nolog) is in caller */
 | 
|---|
| [67] | 910 |               sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, errno, MSG_E_SUBGEN,
 | 
|---|
| [132] | 911 |                               sh_error_message(errno, errbuf, sizeof(errbuf)),
 | 
|---|
| [67] | 912 |                               _("sh_processes_readps"));
 | 
|---|
 | 913 |               break;
 | 
|---|
 | 914 |             }
 | 
|---|
 | 915 |         }
 | 
|---|
 | 916 | 
 | 
|---|
 | 917 |       c = (char) cc;
 | 
|---|
 | 918 | 
 | 
|---|
 | 919 |       if (pos < (sizeof(tstr)-1))
 | 
|---|
 | 920 |         { 
 | 
|---|
 | 921 |           tstr[pos] = c; ++pos; 
 | 
|---|
 | 922 |         }
 | 
|---|
 | 923 | 
 | 
|---|
 | 924 |       switch(line)
 | 
|---|
 | 925 |         {
 | 
|---|
 | 926 |         case SKIP_END:
 | 
|---|
 | 927 |           if (c == '\n')
 | 
|---|
 | 928 |             { 
 | 
|---|
 | 929 |               tstr[pos-1] = '\0';
 | 
|---|
| [102] | 930 |               if (flag_err_debug == SL_TRUE)
 | 
|---|
 | 931 |                 {
 | 
|---|
| [143] | 932 |                   /* SH_MUTEX_LOCK(mutex_thread_nolog) is in caller */
 | 
|---|
 | 933 |                   sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, num, 
 | 
|---|
 | 934 |                                   MSG_E_SUBGEN,
 | 
|---|
| [102] | 935 |                                   tstr,
 | 
|---|
 | 936 |                                   _("sh_processes_readps"));
 | 
|---|
 | 937 |                 }
 | 
|---|
| [67] | 938 |               /* fprintf(stderr, "<%ld> %s\n", num, tstr); */
 | 
|---|
 | 939 |               line = SKIP_WS; pos = 0;
 | 
|---|
 | 940 |               if (str != NULL && num == (unsigned long) pid)
 | 
|---|
 | 941 |                 sl_strlcpy(str, tstr, len);
 | 
|---|
 | 942 |               if (lnum != 0)
 | 
|---|
 | 943 |                 is_in_watchlist (tstr, num);
 | 
|---|
 | 944 |               ++lnum;
 | 
|---|
 | 945 |             }
 | 
|---|
 | 946 |           break;
 | 
|---|
| [103] | 947 |         case SKIP_TO_WS:
 | 
|---|
 | 948 |           if (!isspace(cc))
 | 
|---|
 | 949 |             break;
 | 
|---|
 | 950 |           line = SKIP_WS;
 | 
|---|
 | 951 |           /* fallthrough */
 | 
|---|
| [67] | 952 |         case SKIP_WS:
 | 
|---|
 | 953 |           if (isspace(cc))
 | 
|---|
 | 954 |             break;
 | 
|---|
 | 955 |           num  = 0;
 | 
|---|
 | 956 |           line = GET_NUM;
 | 
|---|
 | 957 |           /* fallthrough */
 | 
|---|
 | 958 |         case GET_NUM:
 | 
|---|
 | 959 |           if (isdigit(cc))
 | 
|---|
 | 960 |             {
 | 
|---|
 | 961 |               num = num * 10 + (c - '0');
 | 
|---|
 | 962 |               break;
 | 
|---|
 | 963 |             }
 | 
|---|
| [103] | 964 |           else if (isspace(cc))
 | 
|---|
 | 965 |             {
 | 
|---|
| [143] | 966 | #ifdef PS_THREADS
 | 
|---|
| [103] | 967 |               num  = 0;
 | 
|---|
 | 968 |               line = SKIP_WS2;
 | 
|---|
| [67] | 969 | #else
 | 
|---|
| [103] | 970 |               if (num < sh_prochk_maxpid && num >= sh_prochk_minpid)
 | 
|---|
 | 971 |                 {
 | 
|---|
 | 972 |                   res[num - sh_prochk_minpid] |= flag;
 | 
|---|
 | 973 |                 }
 | 
|---|
 | 974 |               line = SKIP_END;
 | 
|---|
 | 975 | #endif
 | 
|---|
 | 976 |               break;
 | 
|---|
 | 977 |             }
 | 
|---|
 | 978 |           else
 | 
|---|
| [67] | 979 |             {
 | 
|---|
| [103] | 980 |               line = SKIP_TO_WS;
 | 
|---|
 | 981 |               break;
 | 
|---|
| [67] | 982 |             }
 | 
|---|
| [103] | 983 |         case SKIP_TO_WS2:
 | 
|---|
 | 984 |           if (!isspace(cc))
 | 
|---|
 | 985 |             break;
 | 
|---|
 | 986 |           line = SKIP_WS2;
 | 
|---|
 | 987 |           /* fallthrough */
 | 
|---|
| [67] | 988 |         case SKIP_WS2:
 | 
|---|
 | 989 |           if (isspace(cc))
 | 
|---|
 | 990 |             break;
 | 
|---|
 | 991 |           num  = 0;
 | 
|---|
 | 992 |           line = GET_NUM2;
 | 
|---|
 | 993 |           /* fallthrough */
 | 
|---|
 | 994 |         case GET_NUM2:
 | 
|---|
 | 995 |           if (isdigit(cc))
 | 
|---|
 | 996 |             {
 | 
|---|
 | 997 |               num = num * 10 + (c - '0');
 | 
|---|
 | 998 |               break;
 | 
|---|
 | 999 |             }
 | 
|---|
| [103] | 1000 |           else if (isspace(cc))
 | 
|---|
| [67] | 1001 |             {
 | 
|---|
| [103] | 1002 |               if (num < sh_prochk_maxpid && num >= sh_prochk_minpid)
 | 
|---|
 | 1003 |                 {
 | 
|---|
 | 1004 |                   res[num - sh_prochk_minpid] |= flag;
 | 
|---|
 | 1005 |                 }
 | 
|---|
 | 1006 |               line = SKIP_END;
 | 
|---|
 | 1007 |               break;
 | 
|---|
| [67] | 1008 |             }
 | 
|---|
| [103] | 1009 |           else
 | 
|---|
 | 1010 |             {
 | 
|---|
 | 1011 |               line = SKIP_TO_WS2;
 | 
|---|
 | 1012 |               break;
 | 
|---|
 | 1013 |             }
 | 
|---|
| [67] | 1014 |         default:
 | 
|---|
 | 1015 |           SL_RETURN ((-1), _("sh_processes_readps"));
 | 
|---|
 | 1016 |         }
 | 
|---|
 | 1017 |     } while (1);
 | 
|---|
 | 1018 | 
 | 
|---|
 | 1019 |   if (ferror(in))
 | 
|---|
 | 1020 |     {
 | 
|---|
 | 1021 |       SL_RETURN ((-1), _("sh_processes_readps"));
 | 
|---|
 | 1022 |     }
 | 
|---|
 | 1023 | 
 | 
|---|
 | 1024 |   SL_RETURN ((0), _("sh_processes_readps"));
 | 
|---|
 | 1025 | }
 | 
|---|
 | 1026 | 
 | 
|---|
 | 1027 | static int sh_processes_runps (short * res, char * str, size_t len, 
 | 
|---|
 | 1028 |                                short flag, pid_t pid)
 | 
|---|
 | 1029 | {
 | 
|---|
 | 1030 |   sh_tas_t task;
 | 
|---|
 | 1031 | 
 | 
|---|
 | 1032 |   int    status = 0;
 | 
|---|
 | 1033 |   char * p;
 | 
|---|
 | 1034 |   int retval = 0;
 | 
|---|
| [132] | 1035 |   char  dir[SH_PATHBUF];
 | 
|---|
| [67] | 1036 | 
 | 
|---|
 | 1037 |   SL_ENTER(_("sh_processes_runps"));
 | 
|---|
 | 1038 | 
 | 
|---|
 | 1039 |   sh_ext_tas_init(&task);
 | 
|---|
| [132] | 1040 |   p = sh_unix_getUIDdir (SH_ERR_ERR, task.run_user_uid, dir, sizeof(dir));
 | 
|---|
| [67] | 1041 |   if (p)
 | 
|---|
 | 1042 |     {
 | 
|---|
 | 1043 |       (void) sh_ext_tas_add_envv (&task, _("HOME"), p);
 | 
|---|
 | 1044 |     }
 | 
|---|
 | 1045 |   (void) sh_ext_tas_add_envv (&task, _("SHELL"), 
 | 
|---|
 | 1046 |                               _("/bin/sh")); 
 | 
|---|
 | 1047 |   (void) sh_ext_tas_add_envv (&task, _("PATH"),  
 | 
|---|
 | 1048 |                               _("/sbin:/usr/sbin:/bin:/usr/bin")); 
 | 
|---|
 | 1049 |   if (sh.timezone != NULL)
 | 
|---|
 | 1050 |     {
 | 
|---|
 | 1051 |       (void) sh_ext_tas_add_envv(&task,  "TZ", sh.timezone);
 | 
|---|
 | 1052 |     }
 | 
|---|
 | 1053 | 
 | 
|---|
 | 1054 |   if (!sh_prochk_pspath)
 | 
|---|
 | 1055 |     sh_ext_tas_command(&task,  PSPATH);
 | 
|---|
 | 1056 |   else
 | 
|---|
 | 1057 |     sh_ext_tas_command(&task,  sh_prochk_pspath);
 | 
|---|
 | 1058 | 
 | 
|---|
 | 1059 |   (void) sh_ext_tas_add_argv(&task,  _("ps"));
 | 
|---|
 | 1060 | 
 | 
|---|
 | 1061 |   if (!sh_prochk_psarg)
 | 
|---|
 | 1062 |     {
 | 
|---|
| [143] | 1063 | #ifdef PS_THREADS
 | 
|---|
| [67] | 1064 |       (void) sh_ext_tas_add_argv(&task,  _("-eT"));
 | 
|---|
 | 1065 | #else
 | 
|---|
 | 1066 |       (void) sh_ext_tas_add_argv(&task,  PSARG);
 | 
|---|
 | 1067 | #endif
 | 
|---|
 | 1068 |     }
 | 
|---|
 | 1069 |   else
 | 
|---|
 | 1070 |     {
 | 
|---|
 | 1071 |       (void) sh_ext_tas_add_argv(&task,  sh_prochk_psarg);
 | 
|---|
 | 1072 |     }
 | 
|---|
 | 1073 | 
 | 
|---|
 | 1074 |   task.rw = 'r';
 | 
|---|
 | 1075 |   task.fork_twice = S_FALSE;
 | 
|---|
 | 1076 | 
 | 
|---|
 | 1077 |   status = sh_ext_popen(&task);
 | 
|---|
 | 1078 |   if (status != 0)
 | 
|---|
 | 1079 |     {
 | 
|---|
| [143] | 1080 |       /* SH_MUTEX_LOCK(mutex_thread_nolog) is in caller */
 | 
|---|
| [67] | 1081 |       sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN, 
 | 
|---|
 | 1082 |                       _("Could not open pipe"), _("sh_processes_runps"));
 | 
|---|
 | 1083 |       SL_RETURN ((-1), _("sh_processes_runps"));
 | 
|---|
 | 1084 |     }
 | 
|---|
 | 1085 | 
 | 
|---|
 | 1086 |   /* read from the open pipe
 | 
|---|
 | 1087 |    */
 | 
|---|
 | 1088 |   if (task.pipe != NULL)
 | 
|---|
 | 1089 |     {
 | 
|---|
 | 1090 |       retval = sh_processes_readps (task.pipe, res, str, len, flag, pid);
 | 
|---|
 | 1091 |     }
 | 
|---|
 | 1092 | 
 | 
|---|
 | 1093 |   /* close pipe and return exit status
 | 
|---|
 | 1094 |    */
 | 
|---|
 | 1095 |   (void) sh_ext_pclose(&task);
 | 
|---|
| [103] | 1096 |   sh_ext_tas_free (&task);
 | 
|---|
| [67] | 1097 |   SL_RETURN ((retval), _("sh_processes_runps"));
 | 
|---|
 | 1098 | }
 | 
|---|
 | 1099 | 
 | 
|---|
| [204] | 1100 | /* Check whether there is a visible process
 | 
|---|
 | 1101 |  * with PID = i + 1024
 | 
|---|
 | 1102 |  */
 | 
|---|
| [205] | 1103 | static size_t p_store = 0;
 | 
|---|
 | 1104 | 
 | 
|---|
| [204] | 1105 | static int openvz_ok(short * res, size_t i)
 | 
|---|
 | 1106 | {
 | 
|---|
| [205] | 1107 | 
 | 
|---|
| [204] | 1108 |   if (sh_prochk_openvz == S_FALSE) {
 | 
|---|
 | 1109 |     return 0;
 | 
|---|
 | 1110 |   }
 | 
|---|
 | 1111 | 
 | 
|---|
 | 1112 |   i += 1024;
 | 
|---|
 | 1113 | 
 | 
|---|
 | 1114 |   if (i >= sh_prochk_size) {
 | 
|---|
 | 1115 |     return 0;
 | 
|---|
 | 1116 |   }
 | 
|---|
 | 1117 | 
 | 
|---|
 | 1118 |   if ( ((res[i] & SH_PR_PS) || (res[i] & SH_PR_PS2)) && (res[i] & SH_PR_ANY))
 | 
|---|
 | 1119 |     {
 | 
|---|
 | 1120 |       /* This is a system process corresponding to a 'virtual'
 | 
|---|
 | 1121 |        * process that has a PID offset by 1024
 | 
|---|
 | 1122 |        */
 | 
|---|
 | 1123 |       return 1;
 | 
|---|
 | 1124 |     }
 | 
|---|
 | 1125 | 
 | 
|---|
| [205] | 1126 |   if (openvz_hidden > 0)
 | 
|---|
| [204] | 1127 |     {
 | 
|---|
| [205] | 1128 |       p_store = i;
 | 
|---|
| [204] | 1129 |       --openvz_hidden;
 | 
|---|
 | 1130 |       return 1;
 | 
|---|
 | 1131 |     }
 | 
|---|
| [205] | 1132 |   else if (i == p_store)
 | 
|---|
 | 1133 |     {
 | 
|---|
 | 1134 |       return 1;
 | 
|---|
 | 1135 |     }
 | 
|---|
| [204] | 1136 | 
 | 
|---|
 | 1137 |   return 0;
 | 
|---|
 | 1138 | }
 | 
|---|
 | 1139 | 
 | 
|---|
| [67] | 1140 | static int sh_process_check_int (short * res)
 | 
|---|
 | 1141 | {
 | 
|---|
| [170] | 1142 |   volatile size_t i;
 | 
|---|
 | 1143 |   size_t j;
 | 
|---|
| [67] | 1144 |   char  tests[512];
 | 
|---|
| [170] | 1145 |   volatile int   retval;
 | 
|---|
| [67] | 1146 | 
 | 
|---|
 | 1147 |   pid_t this_pid;
 | 
|---|
 | 1148 | 
 | 
|---|
 | 1149 |   SL_ENTER(_("sh_process_check_int"));
 | 
|---|
 | 1150 | 
 | 
|---|
 | 1151 |   this_pid = getpid();
 | 
|---|
 | 1152 | 
 | 
|---|
 | 1153 |   if (!res)
 | 
|---|
 | 1154 |     {
 | 
|---|
| [143] | 1155 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 1156 |       sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
 | 
|---|
| [169] | 1157 |                       _("Internal error: NULL argument, switching off"), 
 | 
|---|
| [67] | 1158 |                       _("sh_process_check_int"));
 | 
|---|
| [143] | 1159 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 1160 |       SL_RETURN ((-1), _("sh_process_check_int"));
 | 
|---|
 | 1161 |     }
 | 
|---|
 | 1162 | 
 | 
|---|
| [143] | 1163 |   SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [169] | 1164 |   retval = sh_processes_runps (res, NULL, 0, SH_PR_PS, 0);
 | 
|---|
| [143] | 1165 |   SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 1166 |   for (i = sh_prochk_minpid; i != sh_prochk_maxpid; ++i)
 | 
|---|
 | 1167 |     {
 | 
|---|
 | 1168 |       j      = i - sh_prochk_minpid; 
 | 
|---|
 | 1169 |       res[j] = sh_processes_check ((pid_t) i, res[j]);
 | 
|---|
 | 1170 |     }
 | 
|---|
| [143] | 1171 |   SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [169] | 1172 |   retval += sh_processes_runps (res, NULL, 0, SH_PR_PS2, 0);
 | 
|---|
| [143] | 1173 |   SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 1174 | 
 | 
|---|
| [169] | 1175 |   if (retval != 0)
 | 
|---|
 | 1176 |     {
 | 
|---|
 | 1177 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
 | 1178 |       sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN, 
 | 
|---|
 | 1179 |                       _("Failed to run ps, switching off"), 
 | 
|---|
 | 1180 |                       _("sh_process_check_int"));
 | 
|---|
 | 1181 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
 | 1182 |       SL_RETURN ((-1), _("sh_process_check_int"));
 | 
|---|
 | 1183 |     }
 | 
|---|
 | 1184 | 
 | 
|---|
| [67] | 1185 |   /* Evaluate results
 | 
|---|
 | 1186 |    */
 | 
|---|
 | 1187 |   for (i = sh_prochk_minpid; i != sh_prochk_maxpid; ++i)
 | 
|---|
 | 1188 |     {
 | 
|---|
 | 1189 |       /* don't check the current process
 | 
|---|
 | 1190 |        */
 | 
|---|
 | 1191 |       if (i == (size_t) this_pid)
 | 
|---|
 | 1192 |         continue;
 | 
|---|
 | 1193 | 
 | 
|---|
 | 1194 |       j      = i - sh_prochk_minpid;
 | 
|---|
 | 1195 | 
 | 
|---|
 | 1196 |       if (((res[j] & SH_PR_PS) != 0) || ((res[j] & SH_PR_PS2) != 0))
 | 
|---|
 | 1197 |         {
 | 
|---|
 | 1198 |           res[j] |= SH_PR_PS_ANY;
 | 
|---|
 | 1199 |         }
 | 
|---|
 | 1200 |       else
 | 
|---|
 | 1201 |         {
 | 
|---|
 | 1202 |           res[j] &= ~SH_PR_PS_ANY;
 | 
|---|
 | 1203 |         }
 | 
|---|
 | 1204 | 
 | 
|---|
 | 1205 |       tests[0] = '\0';
 | 
|---|
 | 1206 | 
 | 
|---|
 | 1207 |       if ((res[j] & SH_PR_ANY) || (res[j] & SH_PR_PS_ANY))
 | 
|---|
 | 1208 |         {
 | 
|---|
| [102] | 1209 |           /* list all tests where the pid was found
 | 
|---|
 | 1210 |            */
 | 
|---|
| [67] | 1211 |           sh_processes_tlist (tests, sizeof(tests), res[j]);
 | 
|---|
| [102] | 1212 | 
 | 
|---|
| [67] | 1213 |           /* 
 | 
|---|
 | 1214 |            * case 1: in ps and found 
 | 
|---|
 | 1215 |            */
 | 
|---|
 | 1216 |           if ((res[j] & SH_PR_PS_ANY) && (res[j] & SH_PR_ANY))
 | 
|---|
 | 1217 |             {
 | 
|---|
| [143] | 1218 |               SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 1219 |               sh_error_handle((-1), FIL__, __LINE__, 0, MSG_PCK_OK, 
 | 
|---|
 | 1220 |                               (unsigned long) i, tests);
 | 
|---|
| [143] | 1221 |               SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 1222 |             }
 | 
|---|
 | 1223 | 
 | 
|---|
 | 1224 |           /* 
 | 
|---|
 | 1225 |            * case 2: not in ps and found
 | 
|---|
 | 1226 |            */
 | 
|---|
 | 1227 |           else if ((res[j] & SH_PR_PS_ANY) == 0) 
 | 
|---|
 | 1228 |             {
 | 
|---|
 | 1229 |               res[j] = sh_processes_check ((pid_t) i, 0);
 | 
|---|
 | 1230 |               /*
 | 
|---|
 | 1231 |                * if still there, it is real and hidden
 | 
|---|
 | 1232 |                */
 | 
|---|
| [204] | 1233 |               if ((res[j] & SH_PR_ANY) && !openvz_ok(res, j))
 | 
|---|
| [67] | 1234 |                 {
 | 
|---|
 | 1235 |                   if (S_FALSE == is_in_list(&list_hidden, NULL, i))
 | 
|---|
 | 1236 |                     {
 | 
|---|
| [78] | 1237 |                       char   user[16];
 | 
|---|
 | 1238 |                       char * aout;
 | 
|---|
 | 1239 |                       char * safe;
 | 
|---|
 | 1240 | 
 | 
|---|
| [143] | 1241 |                       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [78] | 1242 |                       aout = get_user_and_path ((pid_t) i, user, sizeof(user));
 | 
|---|
| [143] | 1243 |                       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [78] | 1244 | 
 | 
|---|
 | 1245 |                       if (aout)
 | 
|---|
 | 1246 |                         {
 | 
|---|
 | 1247 |                           safe = sh_util_safe_name (aout);
 | 
|---|
| [143] | 1248 |                           SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [78] | 1249 |                           sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
 | 
|---|
 | 1250 |                                           MSG_PCK_P_HIDDEN,
 | 
|---|
 | 1251 |                                           (unsigned long) i, tests, safe, user);
 | 
|---|
| [143] | 1252 |                           SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [78] | 1253 |                           SH_FREE(safe);
 | 
|---|
 | 1254 |                           SH_FREE(aout);
 | 
|---|
 | 1255 |                         }
 | 
|---|
 | 1256 |                       else
 | 
|---|
| [143] | 1257 |                         {
 | 
|---|
 | 1258 |                           SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
 | 1259 |                           sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
 | 
|---|
 | 1260 |                                           MSG_PCK_HIDDEN,
 | 
|---|
 | 1261 |                                           (unsigned long) i, tests);
 | 
|---|
 | 1262 |                           SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
 | 1263 |                         }
 | 
|---|
| [67] | 1264 |                     }
 | 
|---|
 | 1265 |                 }
 | 
|---|
 | 1266 |             }
 | 
|---|
 | 1267 | 
 | 
|---|
 | 1268 |           /*
 | 
|---|
 | 1269 |            * case 3: in ps, but not found
 | 
|---|
 | 1270 |            */
 | 
|---|
 | 1271 |           else
 | 
|---|
 | 1272 |             {
 | 
|---|
 | 1273 |               if (((res[j] & SH_PR_PS) != 0) && ((res[j] & SH_PR_PS2) != 0))
 | 
|---|
 | 1274 |                 {
 | 
|---|
 | 1275 |                   if (S_FALSE == is_in_list(&list_fake, NULL, i))
 | 
|---|
 | 1276 |                     {
 | 
|---|
| [143] | 1277 |                       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 1278 |                       sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0, 
 | 
|---|
 | 1279 |                                       MSG_PCK_FAKE, 
 | 
|---|
 | 1280 |                                       (unsigned long) i, tests);
 | 
|---|
| [143] | 1281 |                       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 1282 |                     }
 | 
|---|
 | 1283 |                 }
 | 
|---|
 | 1284 |             }
 | 
|---|
 | 1285 |         }
 | 
|---|
 | 1286 |     } /* loop end */
 | 
|---|
 | 1287 | 
 | 
|---|
 | 1288 |   check_watchlist (res);
 | 
|---|
 | 1289 | 
 | 
|---|
 | 1290 |   SL_RETURN (0, _("sh_process_check_int"));
 | 
|---|
 | 1291 | }
 | 
|---|
 | 1292 | 
 | 
|---|
 | 1293 | /* Initialise. 
 | 
|---|
 | 1294 |  */
 | 
|---|
| [170] | 1295 | static int sh_prochk_init_internal(void) 
 | 
|---|
| [67] | 1296 | {
 | 
|---|
 | 1297 |   SL_ENTER(_("sh_prochk_init"));
 | 
|---|
 | 1298 | 
 | 
|---|
 | 1299 |   (void) proc_max_pid (&sh_prochk_maxpid);
 | 
|---|
 | 1300 | 
 | 
|---|
 | 1301 |   if (sh_prochk_minpid > sh_prochk_maxpid)
 | 
|---|
 | 1302 |     ShProchkActive = S_FALSE;
 | 
|---|
 | 1303 | 
 | 
|---|
 | 1304 |   /* We need to free anything allocated by the configuration functions if
 | 
|---|
 | 1305 |    * we find that the module is to be left inactive - otherwise _reconf()
 | 
|---|
 | 1306 |    * won't quite work. 
 | 
|---|
 | 1307 |    */
 | 
|---|
 | 1308 |   if( ShProchkActive == S_FALSE ) 
 | 
|---|
 | 1309 |     {
 | 
|---|
 | 1310 |       sh_prochk_free_list(process_check);
 | 
|---|
 | 1311 |       process_check = NULL;
 | 
|---|
 | 1312 |       SL_RETURN(-1, _("sh_prochk_init"));
 | 
|---|
 | 1313 |     }
 | 
|---|
 | 1314 | 
 | 
|---|
 | 1315 |   sh_prochk_size = sh_prochk_maxpid - sh_prochk_minpid;
 | 
|---|
 | 1316 | 
 | 
|---|
| [338] | 1317 |   if (sh_prochk_res == NULL)
 | 
|---|
 | 1318 |     {
 | 
|---|
 | 1319 |       sh_prochk_res  = SH_ALLOC(sizeof(short) * sh_prochk_size);
 | 
|---|
 | 1320 |     }
 | 
|---|
| [67] | 1321 |   memset (sh_prochk_res, 0, sizeof(short) * sh_prochk_size);
 | 
|---|
 | 1322 |   
 | 
|---|
 | 1323 |   SL_RETURN(0, _("sh_prochk_init"));
 | 
|---|
 | 1324 | }
 | 
|---|
 | 1325 | 
 | 
|---|
| [143] | 1326 | int sh_prochk_init (struct mod_type * arg)
 | 
|---|
 | 1327 | {
 | 
|---|
| [210] | 1328 | #ifndef HAVE_PTHREAD
 | 
|---|
 | 1329 |   (void) arg;
 | 
|---|
 | 1330 | #endif
 | 
|---|
 | 1331 | 
 | 
|---|
| [143] | 1332 |   if (ShProchkActive == S_FALSE)
 | 
|---|
 | 1333 |     return SH_MOD_FAILED;
 | 
|---|
 | 1334 | #ifdef HAVE_PTHREAD
 | 
|---|
| [144] | 1335 |   if (arg != NULL && arg->initval < 0 &&
 | 
|---|
 | 1336 |       (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
 | 
|---|
| [143] | 1337 |     {
 | 
|---|
 | 1338 |       if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
 | 
|---|
 | 1339 |         return SH_MOD_THREAD;
 | 
|---|
 | 1340 |       else
 | 
|---|
 | 1341 |         return SH_MOD_FAILED;
 | 
|---|
 | 1342 |     }
 | 
|---|
| [335] | 1343 |   else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
 | 
|---|
 | 1344 |            (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
 | 
|---|
 | 1345 |     {
 | 
|---|
| [338] | 1346 |       sh_prochk_init_internal();
 | 
|---|
| [335] | 1347 |       return SH_MOD_THREAD;
 | 
|---|
 | 1348 |     }
 | 
|---|
| [143] | 1349 | #endif
 | 
|---|
 | 1350 |   return sh_prochk_init_internal();
 | 
|---|
 | 1351 | }
 | 
|---|
| [67] | 1352 | 
 | 
|---|
 | 1353 | int sh_prochk_timer(time_t tcurrent) 
 | 
|---|
 | 1354 | {
 | 
|---|
 | 1355 |   static time_t lastcheck = 0;
 | 
|---|
 | 1356 | 
 | 
|---|
 | 1357 |   SL_ENTER(_("sh_prochk_timer"));
 | 
|---|
 | 1358 |   if ((time_t) (tcurrent - lastcheck) >= sh_prochk_interval)
 | 
|---|
 | 1359 |     {
 | 
|---|
 | 1360 |       lastcheck  = tcurrent;
 | 
|---|
 | 1361 |       SL_RETURN((-1), _("sh_prochk_timer"));
 | 
|---|
 | 1362 |     }
 | 
|---|
 | 1363 |   SL_RETURN(0, _("sh_prochk_timer"));
 | 
|---|
 | 1364 | }
 | 
|---|
 | 1365 | 
 | 
|---|
 | 1366 | int sh_prochk_check(void) 
 | 
|---|
 | 1367 | {
 | 
|---|
| [170] | 1368 |   int status;
 | 
|---|
| [67] | 1369 | 
 | 
|---|
 | 1370 |   SL_ENTER(_("sh_prochk_check"));
 | 
|---|
 | 1371 | 
 | 
|---|
| [143] | 1372 |   SH_MUTEX_LOCK(mutex_proc_check);
 | 
|---|
| [170] | 1373 | 
 | 
|---|
 | 1374 |   status = 0;
 | 
|---|
 | 1375 | 
 | 
|---|
| [67] | 1376 |   if( ShProchkActive != S_FALSE )
 | 
|---|
 | 1377 |     {
 | 
|---|
| [143] | 1378 |       SH_MUTEX_LOCK(mutex_thread_nolog);
 | 
|---|
| [67] | 1379 |       sh_error_handle((-1), FIL__, __LINE__, 0, MSG_PCK_CHECK, 
 | 
|---|
 | 1380 |                       (unsigned long) sh_prochk_minpid, 
 | 
|---|
 | 1381 |                       (unsigned long) (sh_prochk_maxpid-1));
 | 
|---|
| [143] | 1382 |       SH_MUTEX_UNLOCK(mutex_thread_nolog);
 | 
|---|
| [103] | 1383 | 
 | 
|---|
 | 1384 |       if (sh_prochk_res) {
 | 
|---|
 | 1385 |         memset (sh_prochk_res, 0, sizeof(short) * sh_prochk_size);
 | 
|---|
 | 1386 |       }
 | 
|---|
| [67] | 1387 |       status = sh_process_check_int(sh_prochk_res);
 | 
|---|
| [103] | 1388 | 
 | 
|---|
| [67] | 1389 |       if (status != 0)
 | 
|---|
 | 1390 |         ShProchkActive = S_FALSE;
 | 
|---|
 | 1391 | 
 | 
|---|
 | 1392 |       /* clean out old entries which are not marked 
 | 
|---|
 | 1393 |        * as missing/hidden/fake anymore
 | 
|---|
 | 1394 |        */
 | 
|---|
 | 1395 |       clean_list (&list_missing);
 | 
|---|
 | 1396 |       clean_list (&list_hidden);
 | 
|---|
 | 1397 |       clean_list (&list_fake);
 | 
|---|
 | 1398 |     }
 | 
|---|
| [183] | 1399 | 
 | 
|---|
| [143] | 1400 |   SH_MUTEX_UNLOCK(mutex_proc_check);
 | 
|---|
| [67] | 1401 | 
 | 
|---|
 | 1402 |   SL_RETURN(status, _("sh_prochk_check"));
 | 
|---|
 | 1403 | }
 | 
|---|
 | 1404 | 
 | 
|---|
 | 1405 | /* Free our lists and the associated memory 
 | 
|---|
 | 1406 |  */
 | 
|---|
 | 1407 | int sh_prochk_cleanup(void) 
 | 
|---|
 | 1408 | {
 | 
|---|
 | 1409 |   SL_ENTER(_("sh_prochk_cleanup"));
 | 
|---|
 | 1410 | 
 | 
|---|
 | 1411 |   sh_prochk_reconf();
 | 
|---|
 | 1412 | 
 | 
|---|
 | 1413 |   if (list_missing) {
 | 
|---|
 | 1414 |     kill_list(list_missing);
 | 
|---|
 | 1415 |     list_missing = NULL;
 | 
|---|
 | 1416 |   }
 | 
|---|
 | 1417 |   if (list_hidden) {
 | 
|---|
 | 1418 |     kill_list(list_hidden);
 | 
|---|
 | 1419 |     list_hidden  = NULL;
 | 
|---|
 | 1420 |   }
 | 
|---|
 | 1421 |   if (list_fake) {
 | 
|---|
 | 1422 |     kill_list(list_fake);
 | 
|---|
 | 1423 |     list_fake    = NULL;
 | 
|---|
 | 1424 |   }
 | 
|---|
 | 1425 |   
 | 
|---|
 | 1426 |   SL_RETURN(0, _("sh_prochk_cleanup"));
 | 
|---|
 | 1427 | }
 | 
|---|
 | 1428 | 
 | 
|---|
 | 1429 | /* Free our lists and the associated memory 
 | 
|---|
 | 1430 |  */
 | 
|---|
 | 1431 | int sh_prochk_reconf(void) 
 | 
|---|
 | 1432 | {
 | 
|---|
 | 1433 |   SL_ENTER(_("sh_prochk_reconf"));
 | 
|---|
 | 1434 | 
 | 
|---|
| [143] | 1435 |   SH_MUTEX_LOCK(mutex_proc_check);
 | 
|---|
| [67] | 1436 |   userdef_maxpid     = 0;
 | 
|---|
 | 1437 |   sh_prochk_maxpid   = 0x8000;
 | 
|---|
| [144] | 1438 |   sh_prochk_minpid   = 0x0001;
 | 
|---|
| [67] | 1439 |   sh_prochk_interval = SH_PROCHK_INTERVAL;
 | 
|---|
| [204] | 1440 |   sh_prochk_openvz   = S_FALSE;
 | 
|---|
| [205] | 1441 |   p_store            = 0;
 | 
|---|
 | 1442 |   openvz_hidden      = 0;
 | 
|---|
| [67] | 1443 | 
 | 
|---|
 | 1444 |   sh_prochk_free_list(process_check);
 | 
|---|
 | 1445 |   process_check = NULL;
 | 
|---|
 | 1446 |   if (sh_prochk_res != NULL)
 | 
|---|
 | 1447 |     SH_FREE(sh_prochk_res);
 | 
|---|
 | 1448 |   sh_prochk_res = NULL;
 | 
|---|
 | 1449 | 
 | 
|---|
 | 1450 |   if (sh_prochk_psarg)
 | 
|---|
 | 1451 |     SH_FREE(sh_prochk_psarg);
 | 
|---|
 | 1452 |   sh_prochk_psarg = NULL;
 | 
|---|
 | 1453 |   if (sh_prochk_pspath)
 | 
|---|
 | 1454 |     SH_FREE(sh_prochk_pspath);
 | 
|---|
 | 1455 |   sh_prochk_pspath = NULL;
 | 
|---|
| [143] | 1456 |   SH_MUTEX_UNLOCK(mutex_proc_check);
 | 
|---|
| [67] | 1457 | 
 | 
|---|
 | 1458 |   SL_RETURN(0, _("sh_prochk_reconf"));
 | 
|---|
 | 1459 | }
 | 
|---|
 | 1460 | 
 | 
|---|
 | 1461 | /* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
 | 
|---|
 | 1462 | #endif
 | 
|---|
 | 1463 | 
 | 
|---|
 | 1464 | /* #ifdef SH_USE_PROCESSCHECK */
 | 
|---|
 | 1465 | #endif
 | 
|---|
 | 1466 | 
 | 
|---|
 | 1467 | 
 | 
|---|
 | 1468 | #ifdef SH_CUTEST
 | 
|---|
 | 1469 | #include "CuTest.h"
 | 
|---|
 | 1470 | 
 | 
|---|
 | 1471 | void Test_processcheck_watchlist_ok (CuTest *tc) {
 | 
|---|
 | 1472 | #if defined(SH_USE_PROCESSCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
 | 
|---|
 | 1473 |   CuAssertTrue(tc, 0 == sh_prochk_add_process("init"));
 | 
|---|
 | 1474 |   CuAssertTrue(tc, 
 | 
|---|
 | 1475 |                S_TRUE  == is_in_watchlist("    1 ?        00:00:00 init", 0));
 | 
|---|
 | 1476 |   CuAssertTrue(tc, 
 | 
|---|
 | 1477 |                S_FALSE == is_in_watchlist("    1 ?        00:00:00 flix", 0));
 | 
|---|
 | 1478 |   CuAssertTrue(tc, 
 | 
|---|
 | 1479 |                S_TRUE  == is_in_watchlist("25218 ?        SNs    0:01 /usr/sbin/init -k start -DSSL", 0));
 | 
|---|
 | 1480 |   CuAssertTrue(tc, 
 | 
|---|
 | 1481 |                S_FALSE  == is_in_watchlist("25218 ?        SNs    0:01 /usr/sbin/apache2 -k start -DSSL", 0));
 | 
|---|
 | 1482 | 
 | 
|---|
 | 1483 | 
 | 
|---|
 | 1484 |   sh_prochk_free_list(process_check);
 | 
|---|
 | 1485 |   process_check = NULL;
 | 
|---|
 | 1486 |   CuAssertTrue(tc, S_FALSE == is_in_watchlist("init", 0));
 | 
|---|
 | 1487 | 
 | 
|---|
 | 1488 |   CuAssertTrue(tc, 0 == sh_prochk_add_process("init"));
 | 
|---|
 | 1489 |   CuAssertTrue(tc, 0 == sh_prochk_add_process("ssh"));
 | 
|---|
 | 1490 |   CuAssertTrue(tc, 0 == sh_prochk_add_process("syslog"));
 | 
|---|
 | 1491 |   CuAssertTrue(tc, S_TRUE  == is_in_watchlist("init", 0));
 | 
|---|
 | 1492 |   CuAssertTrue(tc, S_TRUE  == is_in_watchlist("ssh", 0));
 | 
|---|
 | 1493 |   CuAssertTrue(tc, S_TRUE  == is_in_watchlist("syslog", 0));
 | 
|---|
 | 1494 | 
 | 
|---|
 | 1495 |   sh_prochk_free_list(process_check);
 | 
|---|
 | 1496 |   process_check = NULL;
 | 
|---|
 | 1497 |   CuAssertTrue(tc, S_FALSE == is_in_watchlist("init", 0));
 | 
|---|
 | 1498 |   CuAssertTrue(tc, S_FALSE == is_in_watchlist("ssh", 0));
 | 
|---|
 | 1499 |   CuAssertTrue(tc, S_FALSE == is_in_watchlist("syslog", 0));
 | 
|---|
 | 1500 | #else
 | 
|---|
 | 1501 |   (void) tc; /* fix compiler warning */
 | 
|---|
 | 1502 | #endif
 | 
|---|
 | 1503 |   return;
 | 
|---|
 | 1504 | }
 | 
|---|
 | 1505 | 
 | 
|---|
 | 1506 | void Test_processcheck_listhandle_ok (CuTest *tc) {
 | 
|---|
 | 1507 | #if defined(SH_USE_PROCESSCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
 | 
|---|
 | 1508 |   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "init", 0));
 | 
|---|
 | 1509 |   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
 | 
|---|
 | 1510 |   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "foobar", 0));
 | 
|---|
 | 1511 |   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
 | 
|---|
 | 1512 | 
 | 
|---|
 | 1513 |   if (list_missing)
 | 
|---|
 | 1514 |     kill_list(list_missing);
 | 
|---|
 | 1515 |   list_missing = NULL;
 | 
|---|
 | 1516 | 
 | 
|---|
 | 1517 |   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "init", 0));
 | 
|---|
 | 1518 |   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
 | 
|---|
 | 1519 |   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "foobar", 0));
 | 
|---|
 | 1520 |   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
 | 
|---|
 | 1521 | 
 | 
|---|
 | 1522 |   if (list_missing)
 | 
|---|
 | 1523 |     kill_list(list_missing);
 | 
|---|
 | 1524 |   list_missing = NULL;
 | 
|---|
 | 1525 | 
 | 
|---|
 | 1526 |   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "init", 0));
 | 
|---|
 | 1527 |   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
 | 
|---|
 | 1528 |   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "foobar", 0));
 | 
|---|
 | 1529 |   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
 | 
|---|
 | 1530 | 
 | 
|---|
 | 1531 |   CuAssertTrue(tc, 2  == clean_list(&list_missing));
 | 
|---|
 | 1532 |   CuAssertPtrNotNull(tc, list_missing);
 | 
|---|
 | 1533 | 
 | 
|---|
 | 1534 |   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
 | 
|---|
 | 1535 |   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
 | 
|---|
 | 1536 | 
 | 
|---|
 | 1537 |   CuAssertTrue(tc, 2  == clean_list(&list_missing));
 | 
|---|
 | 1538 |   CuAssertPtrNotNull(tc, list_missing);
 | 
|---|
 | 1539 | 
 | 
|---|
 | 1540 |   CuAssertTrue(tc, 0  == clean_list(&list_missing));
 | 
|---|
 | 1541 |   CuAssertTrue(tc, NULL == list_missing);
 | 
|---|
 | 1542 | #else
 | 
|---|
 | 1543 |   (void) tc; /* fix compiler warning */
 | 
|---|
 | 1544 | #endif
 | 
|---|
 | 1545 |   return;
 | 
|---|
 | 1546 | }
 | 
|---|
 | 1547 | 
 | 
|---|
 | 1548 | 
 | 
|---|
 | 1549 | /* #ifdef SH_CUTEST */
 | 
|---|
 | 1550 | #endif
 | 
|---|
 | 1551 | 
 | 
|---|