/*
(C) Nelson Murilo - 2004/09/13
Version 0.10
C port from chkproc.pl code from Klaus Steding-Jessen <jessen@nic.br>
and Cristine Hoepers <cristine@nic.br> +little output changes.
2002/03/02 - Segmentation fault in ps for non ASCII user name, by RainbowHat
2002/06/13 Updated by Kostya Kortchinsky <kostya.kortchinsky@renater.fr>
- corrected the program return value ;
- added a verbose mode displaying information about the hidden process.
2002/08/08 - Value of MAX_PROCESSES was increased to 99999 (new versions
of FreeBSD, HP-UX and others), reported by Morohoshi Akihiko, Paul
and others.
2002/09/03 - Eliminate (?) false-positives. Original idea from Aaron Sherman.
2002/11/15 - Updated by Kostya Kortchinsky <kostya.kortchinsky@renater.fr>
- ported to SunOS.
2003/01/19 - Another Adore based lkm test. Original idea from Junichi Murakami
2003/02/02 - More little fixes - Nelson Murilo
2003/02/23 - Use of kill to eliminate false-positives abandonated, It is
preferable false-positives that false-negatives. Uncomment kill() functions
if you like it.
2003/06/07 - Fix for NPTL threading mechanisms - patch by Mike Griego
2003/09/01 - Fix for ps mode detect, patch by Bill Dupree and others
2004/04/03 - More fix for linux's threads - Nelson Murilo
2004/09/13 - More and more fix for linux's threads - Nelson Murilo
2005/02/23 - More and more and more fix for linux's threads - Nelson Murilo
2005/10/28 - Bug fix for FreeBSD: chkproc was sending a SIGXFSZ (kill -25)
to init, causing a reboot. Patch by Nelson Murilo.
Thanks to Luiz E. R. Cordeiro.
2005/11/15 - Add check for Enye LKM - Nelson Murilo
2005/11/25 - Fix for long lines in PS output - patch by Lantz Moore
2006/01/05 - Add getpriority to identify LKMs, ideas from Yjesus(unhide) and
Slider/Flimbo (skdet)
2006/01/11 - Fix signal 25 on parisc linux and return of kill() -
Thanks to Lantz Moore
2014/07/16 - MAX_PROCESSES now is 999999 -
Thanks to Nico Koenrades
2017/04/13 - MAX_PROCESSES now is 4194384 if linux64
Thanks to DS Store
*/
#if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__sun)
int main (){ return 0; }
#else
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#if defined(__sun)
#include <procfs.h>
#include <fcntl.h>
#endif
#include <sys/resource.h>
#define PS_SUN 0
#define PS_LOL 1
#define PS_COM 2
#define PS_LNX 3
#define PS_MAX 3
#define ENYELKM "/proc/12345"
// #define ENYELKM "/tmp/12345"
#if defined(__sun)
#define FIRST_PROCESS 0
#else
#define FIRST_PROCESS 1
#endif
#define MAX_PROCESSES 999999
#if (defined (__x86_64) > 0 || defined (__amd64) > 0)
#undef MAX_PROCESSES
#define MAX_PROCESSES 4194304
#endif
#define MAX_BUF 1024
#if !defined (SIGXFSZ)
#define SIGXFSZ 25
#endif
static char *ps_cmds[] = {
"ps -edf",
"ps auxw",
"ps mauxw 2>&1 ",
"ps auxw -T|tr -s ' '|cut -d' ' -f2-",
};
int psproc [MAX_PROCESSES+1];
int dirproc[MAX_PROCESSES+1];
#if defined(__linux__)
int isathread[MAX_PROCESSES+1];
#endif
/*
* read at most the first (size-1) chars into s and terminate with a '\0'.
* stops reading after a newline or EOF. if a newline is read, it will be
* the last char in the string. if no newline is found in the first
* (size-1) chars, then keep reading and discarding chars until a newline
* is found or EOF.
*/
char *readline(char *s, int size, FILE *stream)
{
char *rv = fgets(s, size, stream);
if (strlen(s) == (size-1) && s[size-1] != '\n')
{
char buf[MAX_BUF];
fgets(buf, MAX_BUF, stream);
while (strlen(buf) == (MAX_BUF-1) && buf[MAX_BUF-1] != '\n')
{
fgets(buf, MAX_BUF, stream);
}
}
return rv;
}
int main(int argc, char **argv)
{
char buf[MAX_BUF], *p, path[MAX_BUF];
char *pscmd = (char *)0;
FILE *ps;
DIR *proc = opendir("/proc");
struct dirent *dir;
struct stat sb;
int i, j, retps, retdir, pv, verbose;
long ret = 0L;
char * tmp_d_name;
#if defined(__linux__)
int maybeathread;
#endif
#if defined(__sun)
psinfo_t psbuf;
#endif
pv = verbose = 0;
if (!proc)
{
perror("proc");
exit (1);
}
for (i = 1; i < argc; i++)
{
if (!memcmp(argv[i], "-v", 2))
verbose++;
else if (!memcmp(argv[i], "-?", 2))
{
printf("Usage: %s [-v] [-v] -p <num>\n", argv[0]);
return 0;
}
#if defined(__linux__)
else if (!memcmp(argv[i], "-p", 2))
{
if (i+1 < argc)
pv = atoi(argv[++i]);
else
{
printf("Usage: %s [-v] [-v] [-p procps version]\n", argv[0]);
return 0;
}
}
#endif
}
#if defined(__sun)
pscmd = ps_cmds[PS_SUN];
#elif !defined (__linux__)
pscmd = ps_cmds[PS_COM];
#endif
#if defined(__linux__)
if (pv < 1 || pv > PS_MAX)
pv = 1;
pscmd = ps_cmds[pv];
/* printf("pv = %d\n\r", pv); /* -- DEBUG */
#endif
/* printf("pscmd = %s\n\r", pscmd); /* -- DEBUG */
if (!(ps = popen(pscmd, "r")))
{
perror("ps");
exit(errno);
}
*buf = 0;
readline(buf, MAX_BUF, ps); /* Skip header */
#if defined(__sun)
if (!isspace(*buf))
#else
if (!isalpha(*buf))
#endif
{
readline(buf, MAX_BUF, ps); /* Skip header */
if (!isalpha(*buf) && pv != PS_LNX)
{
if (pv != PS_LOL)
execlp(argv[0], argv[0], "-p 1", NULL);
fprintf(stderr, "OooPS!\n");
exit(2);
}
}
if (!memcmp(buf, "ps:", 3) && (pv != PS_LOL))
execlp(argv[0], argv[0], "-p 1", NULL);
for (i = FIRST_PROCESS; i <= MAX_PROCESSES; i++) { /* Init matrix */
psproc[i] = dirproc[i] = 0;
#if defined(__linux__)
isathread[i] = 0;
#endif
}
while (readline(buf, MAX_BUF, ps))
{
p = buf;
#if defined(__sun)
while (isspace(*p)) /* Skip spaces */
p++;
#endif
while (!isspace(*p)) /* Skip User */
p++;
while (isspace(*p)) /* Skip spaces */
p++;
/* printf(">>PS %s<<\n", p); /* -- DEBUG */
ret = atol(p);
if ( ret < 0 || ret > MAX_PROCESSES )
{
fprintf (stderr, " OooPS, not expected %ld value\n", ret);
exit (2);
}
psproc[ret] = 1;
}
pclose(ps);
while ((dir = readdir(proc)))
{
#if defined(__linux__)
maybeathread = 0;
#endif
tmp_d_name = dir->d_name;
if (!strcmp(tmp_d_name, ".") || !strcmp(tmp_d_name, ".."))
continue;
#if defined(__linux__)
if (*tmp_d_name == '.') { /* here we catch the new NTPL threads in linux. They are listed in /proc as PIDs with a period prepended */
tmp_d_name++;
maybeathread = 1;
}
#endif
if(!isdigit(*tmp_d_name))
continue;
#if defined(__linux__)
else if (maybeathread) {
isathread[atol(tmp_d_name)] = 1; /* mark it as a linux NTPL thread if it's in the form of "\.[0-9]*" */
if (verbose)
printf("%ld is a Linux Thread, marking as such...\n", atol(tmp_d_name));
}
#endif
/* printf("%s\n", tmp_d_name); /* -- DEBUG */
dirproc[atol(tmp_d_name)] = 1;
}
closedir(proc);
/* Brute force */
strcpy(buf, "/proc/");
retps = retdir = 0;
for (i = FIRST_PROCESS; i <= MAX_PROCESSES; i++)
{
// snprintf(&buf[6], 6, "%d", i);
snprintf(&buf[6], 8, "%d", i);
if (!chdir(buf))
{
if (!dirproc[i] && !psproc[i])
{
#if defined(__linux__)
if (!isathread[i]) {
#endif
retdir++;
if (verbose)
printf ("PID %5d(%s): not in readdir output\n", i, buf);
#if defined(__linux__)
}
#endif
}
if (!psproc[i] ) /* && !kill(i, 0)) */
{
#if defined(__linux__)
if(!isathread[i]) {
#endif
retps++;
if (verbose)
printf ("PID %5d: not in ps ou
评论1