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 
29 /* changed from 500 to 600 b/o FreeBSD (see sys/cdefs.h)
30  * which needs _POSIX_C_SOURCE >= 200112 for lstat()
31  */
32 #if defined(__sun) || defined(__sun__) || defined(sun)
33 #define _XOPEN_SOURCE 500
34 #else
35 #define _XOPEN_SOURCE 600
36 #endif
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <ctype.h>
41 #include <string.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
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 
57 #ifdef HAVE_SYS_STATVFS_H
58 #include <sys/statvfs.h>
59 #endif
60 
61 
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"
72 #include "sh_calls.h"
73 #include "sh_pthread.h"
74 
75 #ifdef SH_USE_PROCESSCHECK
76 
77 #define FIL__  _("sh_processcheck.c")
78 
79 #ifdef __linux__
80 #define PS_THREADS
81 #endif
82 
83 /* We won't want to build this into yule
84  */
85 #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
86 
87 SH_MUTEX_STATIC(mutex_proc_check, PTHREAD_MUTEX_INITIALIZER);
88 
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;
104 static int      sh_prochk_openvz   = S_FALSE;
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);
114 static int sh_prochk_set_openvz  (const char *str);
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     {
150         N_("processcheckisopenvz"),
151         sh_prochk_set_openvz,
152     },
153     {
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 
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 
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;
188 static const short SH_PR_STATVSF  = 0x0200;
189 
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;
194 
195 /* /proc:
196  *        linux:     /proc/pid/exe
197  *        freebsd:   /proc/pid/file
198  *        solaris10: /proc/pid/path/a.out
199  */
get_user_and_path(pid_t pid,char * user,size_t usrlen)200 static char * get_user_and_path (pid_t pid, char * user, size_t usrlen)
201 {
202   extern char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
203 
204   char        path[128];
205   char *      buf;
206   struct stat sbuf;
207   int         len;
208   char *      tmp;
209 
210   sl_snprintf (path, sizeof(path), _("/proc/%ld/exe"), (unsigned long) pid);
211 
212   if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
213     {
214       goto linkread;
215     }
216 
217   sl_snprintf (path, sizeof(path), _("/proc/%ld/file"), (unsigned long) pid);
218 
219   if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
220     {
221       goto linkread;
222     }
223 
224   sl_snprintf (path, sizeof(path), _("/proc/%ld/path/a.out"), (unsigned long) pid);
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 
249   tmp = sh_unix_getUIDname (SH_ERR_ALL, sbuf.st_uid, user, usrlen);
250 
251   if (!tmp)
252     sl_snprintf (user, usrlen, "%ld", (unsigned long) sbuf.st_uid);
253 
254   return buf;
255 }
256 
257 
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  */
kill_list(struct watchlist * head)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  */
clean_list(struct watchlist ** head_ptr)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  */
is_in_list(struct watchlist ** head_ptr,char * str,unsigned long pid)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 
is_in_watchlist(const char * str,unsigned long num)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 
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 void * sh_dummy_413_watchlist = NULL;
414 
check_watchlist(short * res)415 static void check_watchlist (short * res)
416 {
417   struct watchlist * list = process_check;
418   char * tmp;
419   size_t indx;
420 
421   /* Take the address to keep gcc from putting them into registers.
422    * Avoids the 'clobbered by longjmp' warning.
423    */
424   sh_dummy_413_watchlist = (void*) &list;
425 
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 	    {
434 	      SH_MUTEX_LOCK(mutex_thread_nolog);
435 	      tmp = sh_util_safe_name (list->str);
436 	      sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0,
437 			      MSG_PCK_MISS,
438 			      tmp);
439 	      SH_FREE(tmp);
440 	      SH_MUTEX_UNLOCK(mutex_thread_nolog);
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 		{
456 		  SH_MUTEX_LOCK(mutex_thread_nolog);
457 		  tmp = sh_util_safe_name (list->str);
458 		  sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0,
459 				  MSG_PCK_MISS,
460 				  tmp);
461 		  SH_FREE(tmp);
462 		  SH_MUTEX_UNLOCK(mutex_thread_nolog);
463 		}
464 	    }
465 	  list->seen = S_FALSE;
466 	}
467       list = list->next;
468     }
469 
470   sh_dummy_413_watchlist = NULL;
471   return;
472 }
473 
474 /* Add 'str' to the list of watched processes for which
475  * existence should be checked.
476  */
sh_prochk_add_process(const char * str)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));
496       SH_MUTEX_LOCK(mutex_thread_nolog);
497       sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
498 		      errbuf, _("sh_processes_add_process"));
499       SH_MUTEX_UNLOCK(mutex_thread_nolog);
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  */
sh_prochk_set_severity(const char * c)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  */
sh_prochk_set_pspath(const char * str)526 int sh_prochk_set_pspath(const char *str)
527 {
528   SL_ENTER(_("sh_prochk_set_pspath"));
529 
530   if (!str || ('/' != str[0]))
531     SL_RETURN((-1), _("sh_prochk_set_pspath"));
532   if (sh_prochk_pspath)
533     SH_FREE(sh_prochk_pspath);
534 #ifdef SH_EVAL_SHELL
535   sh_prochk_pspath = sh_util_strdup (str);
536   SL_RETURN((0), _("sh_prochk_set_pspath"));
537 #else
538   sh_prochk_pspath = NULL;
539   SL_RETURN((-1), _("sh_prochk_set_pspath"));
540 #endif
541 }
542 
543 /* argument for ps
544  */
sh_prochk_set_psarg(const char * str)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);
551 #ifdef SH_EVAL_SHELL
552   sh_prochk_psarg = sh_util_strdup (str);
553   SL_RETURN((0), _("sh_prochk_set_psarg"));
554 #else
555   (void) str;
556   sh_prochk_psarg = NULL;
557   SL_RETURN((-1), _("sh_prochk_set_psarg"));
558 #endif
559 }
560 
561 
562 /* Decide if we're active.
563  */
sh_prochk_set_active(const char * str)564 int sh_prochk_set_active(const char *str)
565 {
566   int value;
567 
568   SL_ENTER(_("sh_prochk_set_active"));
569 
570   value = sh_util_flagval(str, &ShProchkActive);
571 
572   SL_RETURN((value), _("sh_prochk_set_active"));
573 }
574 
575 /* Are we on openvz.
576  */
577 static int openvz_hidden = 0;
578 
sh_prochk_set_openvz(const char * str)579 int sh_prochk_set_openvz(const char *str)
580 {
581   int value;
582 
583   SL_ENTER(_("sh_prochk_set_openvz"));
584 
585   value = sh_util_flagval(str, &sh_prochk_openvz);
586 
587   if (sh_prochk_openvz != S_FALSE) {
588     openvz_hidden = 1;
589   }
590 
591   SL_RETURN((value), _("sh_prochk_set_openvz"));
592 }
593 
594 /* Minimum PID
595  */
sh_prochk_set_minpid(const char * str)596 int sh_prochk_set_minpid(const char * str)
597 {
598   size_t  value;
599   char * foo;
600   int    retval = 0;
601 
602   SL_ENTER(_("sh_prochk_set_minpid"));
603 
604   value = (size_t) strtoul(str, &foo, 0);
605   if (*foo != '\0')
606     retval = -1;
607   else
608     sh_prochk_minpid = value;
609 
610   SL_RETURN((retval), _("sh_prochk_set_minpid"));
611 }
612 
613 /* Maximum PID
614  */
615 static int userdef_maxpid = 0;
616 
sh_prochk_set_maxpid(const char * str)617 int sh_prochk_set_maxpid(const char * str)
618 {
619   size_t  value;
620   char * foo;
621   int    retval = -1;
622 
623   SL_ENTER(_("sh_prochk_set_maxpid"));
624 
625   value = (size_t) strtoul(str, &foo, 0);
626 
627   if (*foo == '\0' && S_TRUE == sl_ok_adds(value, 1)) {
628     sh_prochk_maxpid = value + 1;
629     userdef_maxpid   = 1;
630     retval = 0;
631   }
632 
633   SL_RETURN((retval), _("sh_prochk_set_maxpid"));
634 }
635 
sh_prochk_set_interval(const char * c)636 int sh_prochk_set_interval (const char * c)
637 {
638   int retval = 0;
639   long val;
640 
641   SL_ENTER(_("sh_prochk_set_interval"));
642   val = strtol (c, (char **)NULL, 10);
643   if (val <= 0)
644     {
645       SH_MUTEX_LOCK(mutex_thread_nolog);
646       sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
647 		       _("process check interval"), c);
648       SH_MUTEX_UNLOCK(mutex_thread_nolog);
649       retval = -1;
650     }
651   else
652     {
653       sh_prochk_interval = (time_t) val;
654     }
655   SL_RETURN(retval, _("sh_prochk_set_interval"));
656 }
657 
658 
659 
660 /* Recurse to the end of the list and then free the data as we return
661  * back up towards the start, making sure to free any strdupped strings
662  */
sh_prochk_free_list(struct watchlist * head)663 static void sh_prochk_free_list(struct watchlist *head)
664 {
665   if ( head != NULL )
666     {
667       sh_prochk_free_list(head->next);
668       if (head->str)
669 	SH_FREE(head->str);
670 #ifdef HAVE_REGEX_H
671       regfree(&(head->preg));
672 #endif
673       SH_FREE(head);
674     }
675   return;
676 }
677 
678 #if defined(__linux__)
679 #define PROC_PID_MAX _("/proc/sys/kernel/pid_max")
680 
proc_max_pid(size_t * procpid)681 static int proc_max_pid (size_t * procpid)
682 {
683   char * ret;
684   unsigned long  pid;
685   FILE * fd;
686   char   str[128];
687   char * ptr;
688 
689   SL_ENTER(_("proc_max_pid"));
690 
691   if (userdef_maxpid != 0)
692     SL_RETURN((-1), _("proc_max_pid"));
693 
694   if (0 == access(PROC_PID_MAX, R_OK)) /* flawfinder: ignore */
695     {
696       if (NULL != (fd = fopen(PROC_PID_MAX, "r")))
697 	{
698 	  str[0] = '\0';
699 	  ret = fgets(str, 128, fd);
700 	  if (ret && *str != '\0')
701 	    {
702 	      pid = strtoul(str, &ptr, 0);
703 	      if (*ptr == '\0' || *ptr == '\n')
704 		{
705 		  sl_fclose(FIL__, __LINE__, fd);
706 		  *procpid = (size_t) pid;
707 		  SL_RETURN(0, _("proc_max_pid"));
708 		}
709 	    }
710 	  sl_fclose(FIL__, __LINE__, fd);
711 	}
712     }
713   SL_RETURN((-1), _("proc_max_pid"));
714 }
715 #else
proc_max_pid(size_t * dummy)716 static int proc_max_pid(size_t * dummy)
717 {
718   (void) dummy;
719   return -1;
720 }
721 #endif
722 
sh_processes_tlist(char * list,size_t len,short res)723 static void sh_processes_tlist (char * list, size_t len, short res)
724 {
725   if (res & SH_PR_PS)       sl_strlcat(list, _(" ps(initial)"), len);
726   if (res & SH_PR_CHDIR)    sl_strlcat(list, _(" chdir"), len);
727   if (res & SH_PR_OPENDIR)  sl_strlcat(list, _(" opendir"), len);
728   if (res & SH_PR_LSTAT)    sl_strlcat(list, _(" lstat"), len);
729   if (res & SH_PR_PRIORITY) sl_strlcat(list, _(" getpriority"), len);
730   if (res & SH_PR_SCHED)    sl_strlcat(list, _(" sched_getparam"), len);
731   if (res & SH_PR_GETSID)   sl_strlcat(list, _(" getsid"), len);
732   if (res & SH_PR_GETPGID)  sl_strlcat(list, _(" getpgid"), len);
733   if (res & SH_PR_KILL)     sl_strlcat(list, _(" kill"), len);
734   if (res & SH_PR_STATVSF)  sl_strlcat(list, _(" statvfs"), len);
735   if (res & SH_PR_PS2)      sl_strlcat(list, _(" ps(final)"), len);
736   return;
737 }
738 
739 
sh_processes_check(pid_t pid,short res)740 static short sh_processes_check (pid_t pid, short res)
741 {
742   int  have_checks = 0;
743   int  need_checks = 0;
744 #ifdef HAVE_PROCFS
745   char path[128];
746   struct stat buf;
747   DIR * dir;
748   int  retval;
749 #if defined(HAVE_STATVFS) && !defined(__FreeBSD__)
750   struct statvfs vfsbuf;
751 #endif
752 #endif
753 
754 #if !defined(sun) && !defined(__sun) && !defined(__sun__)
755 #ifdef _POSIX_PRIORITY_SCHEDULING
756   struct sched_param p;
757 #endif
758 #endif
759 
760   if (0 == kill(pid, 0))
761     {
762       res |= SH_PR_KILL;    res |= SH_PR_ANY; ++have_checks;
763       ++need_checks;
764     }
765   else if (errno != EPERM)
766     {
767       ++need_checks;
768     }
769 
770 
771 #ifdef HAVE_GETPGID
772   if ((pid_t)-1 != getpgid(pid))
773     {
774       res |= SH_PR_GETPGID; res |= SH_PR_ANY; ++have_checks;
775     }
776   ++need_checks;
777 #endif
778 
779 #ifdef HAVE_GETSID
780   if ((pid_t)-1 != getsid(pid))
781     {
782       res |= SH_PR_GETSID;  res |= SH_PR_ANY; ++have_checks;
783     }
784   ++need_checks;
785 #endif
786 
787   /* sched_getparam() is broken on solaris 10, may segfault in librt
788    */
789 #if !defined(sun) && !defined(__sun) && !defined(__sun__) && !defined(__OpenBSD__)
790 #ifdef _POSIX_PRIORITY_SCHEDULING
791   if (0 == sched_getparam (pid, &p))
792     {
793       res |= SH_PR_SCHED;   res |= SH_PR_ANY; ++have_checks;
794     }
795   ++need_checks;
796 #endif
797 #endif
798 
799 #ifdef HAVE_GETPRIORITY
800   errno = 0;
801   if (((-1) == getpriority (PRIO_PROCESS, (int) pid)) && (errno == ESRCH));
802   else
803     {
804       res |= SH_PR_PRIORITY; res |= SH_PR_ANY; ++have_checks;
805     }
806   ++need_checks;
807 #endif
808 
809 #ifdef HAVE_PROCFS
810   sl_snprintf (path, sizeof(path), "/proc/%ld", (unsigned long) pid);
811 
812   do {
813     retval = lstat (path, &buf);
814   } while (retval < 0 && errno == EINTR);
815 
816   if (0 == retval)
817     {
818       res |= SH_PR_LSTAT;   res |= SH_PR_ANY; ++have_checks;
819     }
820   ++need_checks;
821 
822   if (NULL != (dir = opendir(path)))
823     {
824       res |= SH_PR_OPENDIR; res |= SH_PR_ANY; ++have_checks;
825       closedir(dir);
826     }
827   ++need_checks;
828 
829 #if defined(HAVE_STATVFS) && !defined(__FreeBSD__)
830   do {
831     retval = statvfs (path, &vfsbuf);
832   } while (retval < 0 && errno == EINTR);
833 
834   if (0 == retval)
835     {
836       res |= SH_PR_STATVSF;   res |= SH_PR_ANY; ++have_checks;
837     }
838   ++need_checks;
839 #endif
840 
841 #if !defined(SH_PROFILE)
842   if (0 == chdir(path))
843     {
844       res |= SH_PR_CHDIR;   res |= SH_PR_ANY; ++have_checks;
845       do {
846 	retval = chdir ("/");
847       } while (retval < 0 && errno == EINTR);
848     }
849   ++need_checks;
850 #endif
851 #endif
852 
853   if (have_checks == need_checks)
854     {
855       res |= SH_PR_ALL;
856     }
857   return res;
858 }
859 
860 extern int flag_err_debug;
861 
sh_processes_readps(FILE * in,short * res,char * str,size_t len,short flag,pid_t pid)862 static int sh_processes_readps (FILE * in, short * res,
863 				char * str, size_t len,
864 				short flag, pid_t pid)
865 {
866   int  cc;
867   volatile unsigned int  lnum   = 0;
868   volatile unsigned long num    = 0;
869   char c;
870   unsigned int  pos = 0;
871 #define SH_TWAIT_MAX 60
872   volatile unsigned int  twait = 0;
873   char tstr[256];
874   enum { SKIP_TO_WS, SKIP_WS, SKIP_TO_WS2, SKIP_WS2, GET_NUM, SKIP_END, GET_NUM2 } line;
875 
876   SL_ENTER(_("sh_processes_readps"));
877 
878   if (!in) {
879     SL_RETURN((-1), _("sh_processes_readps"));
880   }
881 
882   tstr[(sizeof(tstr)-1)] = '\0';
883   tstr[0]                = '\0';
884   line = SKIP_END;		/* Skip 1st line */
885 
886   do
887     {
888       cc = fgetc(in);
889 
890       if (EOF == cc)
891 	{
892 	  if (feof(in))
893 	    {
894 	      break;
895 	    }
896 	  else if ((errno == EAGAIN) && (twait < SH_TWAIT_MAX))
897 	    {
898 	      clearerr(in);
899 	      retry_msleep(1, 0);
900 	      ++twait;
901 	      continue;
902 	    }
903 #ifdef HOST_IS_OPENBSD
904 	  else if (errno == ENODEV)
905 	    {
906 	      clearerr(in);
907 	      continue;
908 	    }
909 #endif
910 	  else
911 	    {
912 	      char errbuf[SH_ERRBUF_SIZE];
913 
914 	      SH_MUTEX_LOCK(mutex_thread_nolog);
915 	      sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, errno, MSG_E_SUBGEN,
916 			      sh_error_message(errno, errbuf, sizeof(errbuf)),
917 			      _("sh_processes_readps"));
918 	      SH_MUTEX_UNLOCK(mutex_thread_nolog);
919 	      break;
920 	    }
921 	}
922 
923       c = (char) cc;
924 
925       if (pos < (sizeof(tstr)-1))
926 	{
927 	  tstr[pos] = c; ++pos;
928 	}
929 
930       switch(line)
931 	{
932 	case SKIP_END:
933 	  if (c == '\n')
934 	    {
935 	      tstr[pos-1] = '\0';
936 	      if (flag_err_debug == S_TRUE)
937 		{
938 		  SH_MUTEX_LOCK(mutex_thread_nolog);
939 		  sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, num,
940 				  MSG_E_SUBGEN,
941 				  tstr,
942 				  _("sh_processes_readps"));
943 		  SH_MUTEX_UNLOCK(mutex_thread_nolog);
944 		}
945 	      /* fprintf(stderr, "<%ld> %s\n", num, tstr); */
946 	      line = SKIP_WS; pos = 0;
947 	      if (str != NULL && num == (unsigned long) pid)
948 		sl_strlcpy(str, tstr, len);
949 	      if (lnum != 0)
950 		is_in_watchlist (tstr, num);
951 	      ++lnum;
952 	    }
953 	  break;
954 	case SKIP_TO_WS:
955 	  if (!isspace(cc))
956 	    break;
957 	  line = SKIP_WS;
958 	  /* fallthrough */
959 	case SKIP_WS:
960 	  if (isspace(cc))
961 	    break;
962 	  num  = 0;
963 	  line = GET_NUM;
964 	  /* fallthrough */
965 	case GET_NUM:
966 	  if (isdigit(cc))
967 	    {
968 	      num = num * 10 + (c - '0');
969 	      break;
970 	    }
971 	  else if (isspace(cc))
972 	    {
973 #ifdef PS_THREADS
974 	      num  = 0;
975 	      line = SKIP_WS2;
976 #else
977 	      if (num < sh_prochk_maxpid && num >= sh_prochk_minpid)
978 		{
979 		  res[num - sh_prochk_minpid] |= flag;
980 		}
981 	      line = SKIP_END;
982 #endif
983 	      break;
984 	    }
985 	  else
986 	    {
987 	      line = SKIP_TO_WS;
988 	      break;
989 	    }
990 	case SKIP_TO_WS2:
991 	  if (!isspace(cc))
992 	    break;
993 	  line = SKIP_WS2;
994 	  /* fallthrough */
995 	case SKIP_WS2:
996 	  if (isspace(cc))
997 	    break;
998 	  num  = 0;
999 	  line = GET_NUM2;
1000 	  /* fallthrough */
1001 	case GET_NUM2:
1002 	  if (isdigit(cc))
1003 	    {
1004 	      num = num * 10 + (c - '0');
1005 	      break;
1006 	    }
1007 	  else if (isspace(cc))
1008 	    {
1009 	      if (num < sh_prochk_maxpid && num >= sh_prochk_minpid)
1010 		{
1011 		  res[num - sh_prochk_minpid] |= flag;
1012 		}
1013 	      line = SKIP_END;
1014 	      break;
1015 	    }
1016 	  else
1017 	    {
1018 	      line = SKIP_TO_WS2;
1019 	      break;
1020 	    }
1021 	default:
1022 	  SL_RETURN ((-1), _("sh_processes_readps"));
1023 	}
1024     } while (1);
1025 
1026   if (ferror(in))
1027     {
1028       SL_RETURN ((-1), _("sh_processes_readps"));
1029     }
1030 
1031   SL_RETURN ((0), _("sh_processes_readps"));
1032 }
1033 
sh_processes_runps(short * res,char * str,size_t len,short flag,pid_t pid)1034 static int sh_processes_runps (short * res, char * str, size_t len,
1035 			       short flag, pid_t pid)
1036 {
1037   sh_tas_t task;
1038 
1039   int    status = 0;
1040   char * p;
1041   int retval = 0;
1042   char  dir[SH_PATHBUF];
1043 
1044   SL_ENTER(_("sh_processes_runps"));
1045 
1046   sh_ext_tas_init(&task);
1047   p = sh_unix_getUIDdir (SH_ERR_ERR, task.run_user_uid, dir, sizeof(dir));
1048   if (p)
1049     {
1050       (void) sh_ext_tas_add_envv (&task, _("HOME"), p);
1051     }
1052   (void) sh_ext_tas_add_envv (&task, _("SHELL"),
1053 			      _("/bin/sh"));
1054   (void) sh_ext_tas_add_envv (&task, _("PATH"),
1055 			      _("/sbin:/usr/sbin:/bin:/usr/bin"));
1056   if (sh.timezone != NULL)
1057     {
1058       (void) sh_ext_tas_add_envv(&task,  "TZ", sh.timezone);
1059     }
1060 
1061   if (!sh_prochk_pspath)
1062     sh_ext_tas_command(&task,  PSPATH);
1063   else
1064     sh_ext_tas_command(&task,  sh_prochk_pspath);
1065 
1066   (void) sh_ext_tas_add_argv(&task,  _("ps"));
1067 
1068   if (!sh_prochk_psarg)
1069     {
1070 #ifdef PS_THREADS
1071       (void) sh_ext_tas_add_argv(&task,  _("-eT"));
1072 #else
1073       (void) sh_ext_tas_add_argv(&task,  PSARG);
1074 #endif
1075     }
1076   else
1077     {
1078       (void) sh_ext_tas_add_argv(&task,  sh_prochk_psarg);
1079     }
1080 
1081   task.rw = 'r';
1082   task.fork_twice = S_FALSE;
1083 
1084   status = sh_ext_popen(&task);
1085   if (status != 0)
1086     {
1087       SH_MUTEX_LOCK(mutex_thread_nolog);
1088       sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
1089 		      _("Could not open pipe"), _("sh_processes_runps"));
1090       SH_MUTEX_UNLOCK(mutex_thread_nolog);
1091       SL_RETURN ((-1), _("sh_processes_runps"));
1092     }
1093 
1094   /* read from the open pipe
1095    */
1096   if (task.pipe != NULL)
1097     {
1098       retval = sh_processes_readps (task.pipe, res, str, len, flag, pid);
1099     }
1100 
1101   /* close pipe and return exit status
1102    */
1103   (void) sh_ext_pclose(&task);
1104   sh_ext_tas_free (&task);
1105   SL_RETURN ((retval), _("sh_processes_runps"));
1106 }
1107 
1108 /* Check whether there is a visible process
1109  * with PID = i + 1024
1110  */
1111 static size_t p_store = 0;
1112 
openvz_ok(short * res,size_t i)1113 static int openvz_ok(short * res, size_t i)
1114 {
1115 
1116   if (sh_prochk_openvz == S_FALSE) {
1117     return 0;
1118   }
1119 
1120   i += 1024;
1121 
1122   if (i >= sh_prochk_size) {
1123     return 0;
1124   }
1125 
1126   if ( ((res[i] & SH_PR_PS) || (res[i] & SH_PR_PS2)) && (res[i] & SH_PR_ANY))
1127     {
1128       /* This is a system process corresponding to a 'virtual'
1129        * process that has a PID offset by 1024
1130        */
1131       return 1;
1132     }
1133 
1134   if (openvz_hidden > 0)
1135     {
1136       p_store = i;
1137       --openvz_hidden;
1138       return 1;
1139     }
1140   else if (i == p_store)
1141     {
1142       return 1;
1143     }
1144 
1145   return 0;
1146 }
1147 
sh_process_check_int(short * res)1148 static int sh_process_check_int (short * res)
1149 {
1150   volatile size_t i;
1151   size_t j;
1152   char  tests[512];
1153   volatile int   retval;
1154 
1155   pid_t this_pid;
1156 
1157   SL_ENTER(_("sh_process_check_int"));
1158 
1159   this_pid = getpid();
1160 
1161   if (!res)
1162     {
1163       SH_MUTEX_LOCK(mutex_thread_nolog);
1164       sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
1165 		      _("Internal error: NULL argument, switching off"),
1166 		      _("sh_process_check_int"));
1167       SH_MUTEX_UNLOCK(mutex_thread_nolog);
1168       SL_RETURN ((-1), _("sh_process_check_int"));
1169     }
1170 
1171   retval = sh_processes_runps (res, NULL, 0, SH_PR_PS, 0);
1172 
1173   for (i = sh_prochk_minpid; i != sh_prochk_maxpid; ++i)
1174     {
1175       j      = i - sh_prochk_minpid;
1176       res[j] = sh_processes_check ((pid_t) i, res[j]);
1177     }
1178 
1179   retval += sh_processes_runps (res, NULL, 0, SH_PR_PS2, 0);
1180 
1181   if (retval != 0)
1182     {
1183       SH_MUTEX_LOCK(mutex_thread_nolog);
1184       sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
1185 		      _("Failed to run ps, switching off"),
1186 		      _("sh_process_check_int"));
1187       SH_MUTEX_UNLOCK(mutex_thread_nolog);
1188       SL_RETURN ((-1), _("sh_process_check_int"));
1189     }
1190 
1191   /* Evaluate results
1192    */
1193   for (i = sh_prochk_minpid; i != sh_prochk_maxpid; ++i)
1194     {
1195       /* don't check the current process
1196        */
1197       if (i == (size_t) this_pid)
1198 	continue;
1199 
1200       j      = i - sh_prochk_minpid;
1201 
1202       if (((res[j] & SH_PR_PS) != 0) || ((res[j] & SH_PR_PS2) != 0))
1203 	{
1204 	  res[j] |= SH_PR_PS_ANY;
1205 	}
1206       else
1207 	{
1208 	  res[j] &= ~SH_PR_PS_ANY;
1209 	}
1210 
1211       tests[0] = '\0';
1212 
1213       if ((res[j] & SH_PR_ANY) || (res[j] & SH_PR_PS_ANY))
1214 	{
1215 	  /* list all tests where the pid was found
1216 	   */
1217 	  sh_processes_tlist (tests, sizeof(tests), res[j]);
1218 
1219 	  /*
1220 	   * case 1: in ps and found
1221 	   */
1222 	  if ((res[j] & SH_PR_PS_ANY) && (res[j] & SH_PR_ANY))
1223 	    {
1224 	      SH_MUTEX_LOCK(mutex_thread_nolog);
1225 	      sh_error_handle((-1), FIL__, __LINE__, 0, MSG_PCK_OK,
1226 			      (unsigned long) i, tests);
1227 	      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1228 	    }
1229 
1230 	  /*
1231 	   * case 2: not in ps and found
1232 	   */
1233 	  else if ((res[j] & SH_PR_PS_ANY) == 0)
1234 	    {
1235 	      res[j] = sh_processes_check ((pid_t) i, 0);
1236 	      /*
1237 	       * if still there, it is real and hidden
1238 	       */
1239 	      if ((res[j] & SH_PR_ANY) && !openvz_ok(res, j))
1240 		{
1241 		  if (S_FALSE == is_in_list(&list_hidden, NULL, i))
1242 		    {
1243 		      char   user[16];
1244 		      char * aout;
1245 		      char * safe;
1246 
1247 		      SH_MUTEX_LOCK(mutex_thread_nolog);
1248 		      aout = get_user_and_path ((pid_t) i, user, sizeof(user));
1249 		      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1250 
1251 		      if (aout)
1252 			{
1253 			  safe = sh_util_safe_name (aout);
1254 			  SH_MUTEX_LOCK(mutex_thread_nolog);
1255 			  sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0,
1256 					  MSG_PCK_P_HIDDEN,
1257 					  (unsigned long) i, tests, safe, user);
1258 			  SH_MUTEX_UNLOCK(mutex_thread_nolog);
1259 			  SH_FREE(safe);
1260 			  SH_FREE(aout);
1261 			}
1262 		      else
1263 			{
1264 			  SH_MUTEX_LOCK(mutex_thread_nolog);
1265 			  sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0,
1266 					  MSG_PCK_HIDDEN,
1267 					  (unsigned long) i, tests);
1268 			  SH_MUTEX_UNLOCK(mutex_thread_nolog);
1269 			}
1270 		    }
1271 		}
1272 	    }
1273 
1274 	  /*
1275 	   * case 3: in ps, but not found
1276 	   */
1277 	  else
1278 	    {
1279 	      if (((res[j] & SH_PR_PS) != 0) && ((res[j] & SH_PR_PS2) != 0))
1280 		{
1281 		  if (S_FALSE == is_in_list(&list_fake, NULL, i))
1282 		    {
1283 		      SH_MUTEX_LOCK(mutex_thread_nolog);
1284 		      sh_error_handle(sh_prochk_severity, FIL__, __LINE__, 0,
1285 				      MSG_PCK_FAKE,
1286 				      (unsigned long) i, tests);
1287 		      SH_MUTEX_UNLOCK(mutex_thread_nolog);
1288 		    }
1289 		}
1290 	    }
1291 	}
1292     } /* loop end */
1293 
1294   check_watchlist (res);
1295 
1296   SL_RETURN (0, _("sh_process_check_int"));
1297 }
1298 
1299 /* Initialise.
1300  */
sh_prochk_init_internal(void)1301 static int sh_prochk_init_internal(void)
1302 {
1303   SL_ENTER(_("sh_prochk_init"));
1304 
1305   (void) proc_max_pid (&sh_prochk_maxpid);
1306 
1307   if (sh_prochk_minpid > sh_prochk_maxpid)
1308     ShProchkActive = S_FALSE;
1309 
1310   /* We need to free anything allocated by the configuration functions if
1311    * we find that the module is to be left inactive - otherwise _reconf()
1312    * won't quite work.
1313    */
1314   if( ShProchkActive == S_FALSE )
1315     {
1316       sh_prochk_free_list(process_check);
1317       process_check = NULL;
1318       SL_RETURN(-1, _("sh_prochk_init"));
1319     }
1320 
1321   sh_prochk_size = sh_prochk_maxpid - sh_prochk_minpid;
1322 
1323   if (sh_prochk_res == NULL)
1324     {
1325       sh_prochk_res  = SH_ALLOC(sizeof(short) * sh_prochk_size);
1326     }
1327   memset (sh_prochk_res, 0, sizeof(short) * sh_prochk_size);
1328 
1329   SL_RETURN(0, _("sh_prochk_init"));
1330 }
1331 
sh_prochk_init(struct mod_type * arg)1332 int sh_prochk_init (struct mod_type * arg)
1333 {
1334 #ifndef HAVE_PTHREAD
1335   (void) arg;
1336 #endif
1337 
1338   if (ShProchkActive == S_FALSE)
1339     return SH_MOD_FAILED;
1340 #ifdef HAVE_PTHREAD
1341   if (arg != NULL && arg->initval < 0 &&
1342       (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1343     {
1344       if (0 == sh_pthread_create(sh_threaded_module_run, (void *)arg))
1345 	return SH_MOD_THREAD;
1346       else
1347 	return SH_MOD_FAILED;
1348     }
1349   else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
1350 	   (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
1351     {
1352       sh_prochk_init_internal();
1353       return SH_MOD_THREAD;
1354     }
1355 #endif
1356   return sh_prochk_init_internal();
1357 }
1358 
sh_prochk_timer(time_t tcurrent)1359 int sh_prochk_timer(time_t tcurrent)
1360 {
1361   static time_t lastcheck = 0;
1362 
1363   SL_ENTER(_("sh_prochk_timer"));
1364   if ((time_t) (tcurrent - lastcheck) >= sh_prochk_interval)
1365     {
1366       lastcheck  = tcurrent;
1367       SL_RETURN((-1), _("sh_prochk_timer"));
1368     }
1369   SL_RETURN(0, _("sh_prochk_timer"));
1370 }
1371 
sh_prochk_check(void)1372 int sh_prochk_check(void)
1373 {
1374   int status;
1375 
1376   SL_ENTER(_("sh_prochk_check"));
1377 
1378   SH_MUTEX_LOCK(mutex_proc_check);
1379 
1380   status = 0;
1381 
1382   if( ShProchkActive != S_FALSE )
1383     {
1384       SH_MUTEX_LOCK(mutex_thread_nolog);
1385       sh_error_handle((-1), FIL__, __LINE__, 0, MSG_PCK_CHECK,
1386 		      (unsigned long) sh_prochk_minpid,
1387 		      (unsigned long) (sh_prochk_maxpid-1));
1388       SH_MUTEX_UNLOCK(mutex_thread_nolog);
1389 
1390       if (sh_prochk_res) {
1391 	memset (sh_prochk_res, 0, sizeof(short) * sh_prochk_size);
1392       }
1393       status = sh_process_check_int(sh_prochk_res);
1394 
1395       if (status != 0)
1396 	ShProchkActive = S_FALSE;
1397 
1398       /* clean out old entries which are not marked
1399        * as missing/hidden/fake anymore
1400        */
1401       clean_list (&list_missing);
1402       clean_list (&list_hidden);
1403       clean_list (&list_fake);
1404     }
1405 
1406   SH_MUTEX_UNLOCK(mutex_proc_check);
1407 
1408   SL_RETURN(status, _("sh_prochk_check"));
1409 }
1410 
1411 /* Free our lists and the associated memory
1412  */
sh_prochk_cleanup(void)1413 int sh_prochk_cleanup(void)
1414 {
1415   SL_ENTER(_("sh_prochk_cleanup"));
1416 
1417   sh_prochk_reconf();
1418 
1419   if (list_missing) {
1420     kill_list(list_missing);
1421     list_missing = NULL;
1422   }
1423   if (list_hidden) {
1424     kill_list(list_hidden);
1425     list_hidden  = NULL;
1426   }
1427   if (list_fake) {
1428     kill_list(list_fake);
1429     list_fake    = NULL;
1430   }
1431 
1432   SL_RETURN(0, _("sh_prochk_cleanup"));
1433 }
1434 
1435 /* Free our lists and the associated memory
1436  */
sh_prochk_reconf(void)1437 int sh_prochk_reconf(void)
1438 {
1439   SL_ENTER(_("sh_prochk_reconf"));
1440 
1441   SH_MUTEX_LOCK(mutex_proc_check);
1442   userdef_maxpid     = 0;
1443   sh_prochk_maxpid   = 0x8000;
1444   sh_prochk_minpid   = 0x0001;
1445   sh_prochk_interval = SH_PROCHK_INTERVAL;
1446   sh_prochk_openvz   = S_FALSE;
1447   p_store            = 0;
1448   openvz_hidden      = 0;
1449 
1450   sh_prochk_free_list(process_check);
1451   process_check = NULL;
1452   if (sh_prochk_res != NULL)
1453     SH_FREE(sh_prochk_res);
1454   sh_prochk_res = NULL;
1455 
1456   if (sh_prochk_psarg)
1457     SH_FREE(sh_prochk_psarg);
1458   sh_prochk_psarg = NULL;
1459   if (sh_prochk_pspath)
1460     SH_FREE(sh_prochk_pspath);
1461   sh_prochk_pspath = NULL;
1462   SH_MUTEX_UNLOCK(mutex_proc_check);
1463 
1464   SL_RETURN(0, _("sh_prochk_reconf"));
1465 }
1466 
1467 /* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
1468 #endif
1469 
1470 /* #ifdef SH_USE_PROCESSCHECK */
1471 #endif
1472 
1473 
1474 #ifdef SH_CUTEST
1475 #include "CuTest.h"
1476 
Test_processcheck_watchlist_ok(CuTest * tc)1477 void Test_processcheck_watchlist_ok (CuTest *tc) {
1478 #if defined(SH_USE_PROCESSCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
1479   CuAssertTrue(tc, 0 == sh_prochk_add_process("init"));
1480   CuAssertTrue(tc,
1481 	       S_TRUE  == is_in_watchlist("    1 ?        00:00:00 init", 0));
1482   CuAssertTrue(tc,
1483 	       S_FALSE == is_in_watchlist("    1 ?        00:00:00 flix", 0));
1484   CuAssertTrue(tc,
1485 	       S_TRUE  == is_in_watchlist("25218 ?        SNs    0:01 /usr/sbin/init -k start -DSSL", 0));
1486   CuAssertTrue(tc,
1487 	       S_FALSE  == is_in_watchlist("25218 ?        SNs    0:01 /usr/sbin/apache2 -k start -DSSL", 0));
1488 
1489 
1490   sh_prochk_free_list(process_check);
1491   process_check = NULL;
1492   CuAssertTrue(tc, S_FALSE == is_in_watchlist("init", 0));
1493 
1494   CuAssertTrue(tc, 0 == sh_prochk_add_process("init"));
1495   CuAssertTrue(tc, 0 == sh_prochk_add_process("ssh"));
1496   CuAssertTrue(tc, 0 == sh_prochk_add_process("syslog"));
1497   CuAssertTrue(tc, S_TRUE  == is_in_watchlist("init", 0));
1498   CuAssertTrue(tc, S_TRUE  == is_in_watchlist("ssh", 0));
1499   CuAssertTrue(tc, S_TRUE  == is_in_watchlist("syslog", 0));
1500 
1501   sh_prochk_free_list(process_check);
1502   process_check = NULL;
1503   CuAssertTrue(tc, S_FALSE == is_in_watchlist("init", 0));
1504   CuAssertTrue(tc, S_FALSE == is_in_watchlist("ssh", 0));
1505   CuAssertTrue(tc, S_FALSE == is_in_watchlist("syslog", 0));
1506 #else
1507   (void) tc; /* fix compiler warning */
1508 #endif
1509   return;
1510 }
1511 
Test_processcheck_listhandle_ok(CuTest * tc)1512 void Test_processcheck_listhandle_ok (CuTest *tc) {
1513 #if defined(SH_USE_PROCESSCHECK) && (defined(SH_WITH_CLIENT) || defined(SH_STANDALONE))
1514   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "init", 0));
1515   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
1516   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "foobar", 0));
1517   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
1518 
1519   if (list_missing)
1520     kill_list(list_missing);
1521   list_missing = NULL;
1522 
1523   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "init", 0));
1524   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
1525   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "foobar", 0));
1526   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
1527 
1528   if (list_missing)
1529     kill_list(list_missing);
1530   list_missing = NULL;
1531 
1532   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "init", 0));
1533   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "init", 0));
1534   CuAssertTrue(tc, S_FALSE == is_in_list(&list_missing, "foobar", 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, S_TRUE  == is_in_list(&list_missing, "init", 0));
1541   CuAssertTrue(tc, S_TRUE  == is_in_list(&list_missing, "foobar", 0));
1542 
1543   CuAssertTrue(tc, 2  == clean_list(&list_missing));
1544   CuAssertPtrNotNull(tc, list_missing);
1545 
1546   CuAssertTrue(tc, 0  == clean_list(&list_missing));
1547   CuAssertTrue(tc, NULL == list_missing);
1548 #else
1549   (void) tc; /* fix compiler warning */
1550 #endif
1551   return;
1552 }
1553 
1554 
1555 /* #ifdef SH_CUTEST */
1556 #endif
1557 
1558