380 lines
11 KiB
Plaintext
380 lines
11 KiB
Plaintext
--- checkproc.8
|
||
+++ checkproc.8 2011-10-18 09:29:16.195166916 +0000
|
||
@@ -17,6 +17,7 @@ Pidofproc \- Checks for a process by exe
|
||
.HP
|
||
.B checkproc
|
||
.RB [ \-vLkNz ]
|
||
+.RB [ \-x ]
|
||
.RB [ \-p\ \fIpid_file\fP ]
|
||
.RB [ \-i\ \fIingnore_file\fP ]
|
||
.RB [ \-c\ \fIroot\fP ]
|
||
@@ -30,10 +31,12 @@ Pidofproc \- Checks for a process by exe
|
||
.B checkproc
|
||
.B \ \
|
||
.RB [ \-vk ]
|
||
+.RB [ \-x ]
|
||
.I basename_of_executable
|
||
.HP
|
||
.B pidofproc
|
||
.RB [ \-LkNz ]
|
||
+.RB [ \-x ]
|
||
.RB [ \-p\ \fIpid_file\fP ]
|
||
.RB [ \-i\ \fIingnore_file\fP ]
|
||
.RB [ \-c\ \fIroot\fP ]
|
||
@@ -47,6 +50,7 @@ Pidofproc \- Checks for a process by exe
|
||
.B pidofproc
|
||
.B \ \
|
||
.RB [ \-k ]
|
||
+.RB [ \-x ]
|
||
.I basename_of_executable
|
||
.SH SYNOPSIS LSB 3.1
|
||
.HP
|
||
@@ -250,6 +254,15 @@ are in the zombie state. Without this o
|
||
handled as not existent because such a process isn't
|
||
alive but listed in the process table and waits on its
|
||
parent process.
|
||
+.TP
|
||
+.B \-x
|
||
+Tells
|
||
+.B checkproc
|
||
+as well as
|
||
+.B pidofproc
|
||
+to use the upto 15 byte long filename name found in
|
||
+.I /proc/<pid>/stat
|
||
+to be able to identify scripts overwriting their command line.
|
||
.PP
|
||
.\"
|
||
.SH EXAMPLE
|
||
--- checkproc.c
|
||
+++ checkproc.c 2011-10-17 15:41:46.671646382 +0000
|
||
@@ -60,7 +60,7 @@ int main(int argc, char **argv)
|
||
posixa = getenv("_POSIX_OPTION_ORDER"); unsetenv("_POSIX_OPTION_ORDER");
|
||
posixb = getenv("POSIXLY_CORRECT"); unsetenv("POSIXLY_CORRECT");
|
||
opterr = 0;
|
||
- while ((c = getopt(argc, argv, "c:kp:nNhqvzLi:")) != -1) {
|
||
+ while ((c = getopt(argc, argv, "c:kp:nNhqvzLi:x")) != -1) {
|
||
switch (c) {
|
||
case 'c':
|
||
if (optarg && optarg[0] != '-' && !root) {
|
||
@@ -86,6 +86,9 @@ int main(int argc, char **argv)
|
||
case 'N':
|
||
init_nfs();
|
||
break;
|
||
+ case 'x':
|
||
+ flags |= STSCRPT;
|
||
+ break;
|
||
case 'z':
|
||
flags &= ~NZOMBIE;
|
||
break;
|
||
--- killproc.8
|
||
+++ killproc.8 2011-10-18 09:27:22.403146549 +0000
|
||
@@ -16,6 +16,7 @@ Killproc \- Send signals to processes by
|
||
.B killproc
|
||
.RB [ \-vqLN ]
|
||
.RB [ \-g | -G ]
|
||
+.RB [ \-x ]
|
||
.RB [ \-p\ \fIpid_file\fP ]
|
||
.RB [ \-i\ \fIingnore_file\fP ]
|
||
.RB [ \-c\ \fIroot\fP ]
|
||
@@ -269,6 +270,13 @@ Be more verbose.
|
||
This option list all available signals and some of their
|
||
synonyms by their number and signal names to standard out.
|
||
and exits.
|
||
+.TP
|
||
+.B \-x
|
||
+Tells
|
||
+.B killproc
|
||
+to use the upto 15 byte long filename name found in
|
||
+.I /proc/<pid>/stat
|
||
+to be able to identify scripts overwriting their command line.
|
||
.\"
|
||
.SH EXAMPLES
|
||
.TP
|
||
--- killproc.c
|
||
+++ killproc.c 2011-10-17 15:42:52.871147146 +0000
|
||
@@ -96,7 +96,7 @@ int main(int argc, char **argv)
|
||
posixa = getenv("_POSIX_OPTION_ORDER"); unsetenv("_POSIX_OPTION_ORDER");
|
||
posixb = getenv("POSIXLY_CORRECT"); unsetenv("POSIXLY_CORRECT");
|
||
opterr = 0;
|
||
- while ((c = getopt(argc, argv, "c:p:gGnNhlvqt:Li:")) != -1) {
|
||
+ while ((c = getopt(argc, argv, "c:p:gGnNhlvqt:Li:x")) != -1) {
|
||
switch (c) {
|
||
case 'c':
|
||
if (optarg && optarg[0] != '-' && !root) {
|
||
@@ -135,6 +135,9 @@ int main(int argc, char **argv)
|
||
case 'N':
|
||
init_nfs();
|
||
break;
|
||
+ case 'x':
|
||
+ flags |= STSCRPT;
|
||
+ break;
|
||
case 'p': /* Changed from -f to -p to fit startproc and LSB */
|
||
/* Allocate here: address optarg (current *argv) isn't freeable */
|
||
if (optarg && !pid_file) {
|
||
--- libinit.c
|
||
+++ libinit.c 2011-10-18 09:06:23.471646253 +0000
|
||
@@ -570,13 +570,12 @@ static const char * checkscripts(char* e
|
||
*/
|
||
scrpt = (char *)memchr(scrpt, 0, cnt);
|
||
if (!scrpt || (cnt = len - (++scrpt - ent)) <= 0)
|
||
- goto out;
|
||
+ break;
|
||
if (*scrpt == '/') {
|
||
ret = scrpt;
|
||
goto out;
|
||
}
|
||
} while (scrpt && cnt > 0);
|
||
-
|
||
out:
|
||
if (scrpt && root) {
|
||
char *ptr = strdupa(scrpt);
|
||
@@ -877,8 +876,11 @@ int pidof (const char * inname, const ch
|
||
continue;
|
||
|
||
/* Seek for a script not for a binary */
|
||
- if (!(scrpt = checkscripts(entry, root, len, d->d_name)))
|
||
+ if (!(scrpt = checkscripts(entry, root, len, d->d_name))) {
|
||
+ if (flags & STSCRPT)
|
||
+ goto risky;
|
||
continue;
|
||
+ }
|
||
|
||
/* Don't blame our boot scripts having the same name */
|
||
if ( (flags & (KILL|DAEMON))
|
||
@@ -1128,7 +1130,7 @@ risky:
|
||
return -1;
|
||
}
|
||
|
||
- if (!(flags & (KTHREAD|KSHORT))&& isscrpt &&
|
||
+ if (!(flags & (KTHREAD|KSHORT)) && isscrpt &&
|
||
(fp = open(proc(buf, "cmdline"), O_PROCMODE)) != -1) {
|
||
|
||
char entry[PATH_MAX+1];
|
||
@@ -1142,15 +1144,18 @@ risky:
|
||
goto out;
|
||
|
||
/* Seek for a script not for a binary */
|
||
- if (!(scrpt = checkscripts(entry, root, len, buf)))
|
||
+ if (!(scrpt = checkscripts(entry, root, len, buf))) {
|
||
+ if (flags & STSCRPT)
|
||
+ goto nameonly;
|
||
goto out; /* Nothing found */
|
||
+ }
|
||
|
||
if (scrpt && strcmp(scrpt,fullname) == 0) {
|
||
do_list(pid,getsession(pid),ignore);
|
||
goto out; /* Done */
|
||
}
|
||
}
|
||
-
|
||
+nameonly:
|
||
if ((fp = open(proc(buf, "stat"), O_PROCMODE)) != -1) {
|
||
|
||
char entry[PATH_MAX+1];
|
||
@@ -1313,7 +1318,7 @@ int check_pids (const char * inname, con
|
||
|
||
skip = true; /* No stat entry check needed */
|
||
}
|
||
-risky:
|
||
+ risky:
|
||
|
||
if (!(flags & (KTHREAD|KSHORT)) && isscrpt &&
|
||
(fp = open(proc(pid, "cmdline"), O_PROCMODE)) != -1) {
|
||
@@ -1332,7 +1337,8 @@ risky:
|
||
if ((scrpt = checkscripts(entry, root, len, pid))) {
|
||
if (strcmp(scrpt,fullname) == 0)
|
||
continue; /* Found */
|
||
- skip = true; /* No stat entry check needed */
|
||
+ if (!(flags & STSCRPT))
|
||
+ skip = true; /* No stat entry check needed */
|
||
}
|
||
}
|
||
|
||
--- libinit.h
|
||
+++ libinit.h 2011-10-18 09:13:36.923145552 +0000
|
||
@@ -106,6 +106,7 @@
|
||
#define FLWLINK 0x0040
|
||
#define KSTOP 0x0080
|
||
#define KBASE 0x0100
|
||
+#define STSCRPT 0x0200
|
||
|
||
#define MAXENV 20
|
||
#define CMDLLEN MAXNAMLEN /* The string length of /proc/12345/cmdline\0\0 + 1 */
|
||
@@ -116,6 +117,7 @@
|
||
#endif
|
||
#define DEFPIDEXT ".pid"
|
||
#define DEFPIDLEN 14 /* The string length of /var/run/.pid + 1 */
|
||
+#define COMM_LEN 15 /* The lenght of the task command name in /proc/<pid>/stat */
|
||
|
||
extern char **environ;
|
||
extern char * newenvp[];
|
||
@@ -216,10 +218,12 @@ static inline char * base_name ( const c
|
||
|
||
static inline char * swap_name ( const char * base )
|
||
{
|
||
- size_t len = strlen(base) + 2 + 1;
|
||
- char *swap = (char*)xmalloc(len);
|
||
-
|
||
- return strcat(strcat(strcpy(swap,"("),base),")");
|
||
+ size_t len = strlen(base);
|
||
+ char *swap;
|
||
+ if (len > COMM_LEN)
|
||
+ len = COMM_LEN;
|
||
+ swap = (char*)xmalloc(len + 2 + 1);
|
||
+ return strcat(strncat(strcpy(swap,"("),base, COMM_LEN),")");
|
||
}
|
||
|
||
extern void addnewenv ( const char * name, const char * entry );
|
||
--- startproc.8
|
||
+++ startproc.8 2011-10-18 09:28:45.875646247 +0000
|
||
@@ -18,6 +18,7 @@ Start_daemon \- Start processes identifi
|
||
.HP
|
||
.B startproc
|
||
.RB [ \-fLves ]
|
||
+.RB [ \-x ]
|
||
.RB [[ \-n\ ] \fI+/\-<prio>\fP ]
|
||
.RB [ \- ( t | T )\ \fI<sec>\fP ]
|
||
.RB [ \-u\ \fIuser\fP ]
|
||
@@ -32,6 +33,7 @@ Start_daemon \- Start processes identifi
|
||
.HP
|
||
.B start_daemon
|
||
.RB [ \-fLve ]
|
||
+.RB [ \-x ]
|
||
.RB [ \-n\ \fI+/\-<prio>\fP ]
|
||
.RB [ \-u\ \fIuser\fP ]
|
||
.RB [ \-g\ \fIgroup\fP ]
|
||
@@ -249,6 +251,15 @@ Sets the user ID of the process to
|
||
.TP
|
||
.B \-v
|
||
Verbose output.
|
||
+.TP
|
||
+.B \-x
|
||
+Tells
|
||
+.B startproc
|
||
+as well as
|
||
+.B start_daemon
|
||
+to use the upto 15 byte long filename name found in
|
||
+.I /proc/<pid>/stat
|
||
+to be able to identify scripts overwriting their command line.
|
||
.\"
|
||
.SH EXAMPLE
|
||
.TP
|
||
--- startproc.c
|
||
+++ startproc.c 2011-10-20 12:19:33.523206609 +0000
|
||
@@ -109,7 +109,7 @@ int main(int argc, char **argv)
|
||
}
|
||
|
||
opterr = 0;
|
||
- while ((c = getopt(argc, argv, "+c:edp:l:hqvsu:g:t:n:fLi:T:wW:")) != -1) { /* `+' is POSIX correct */
|
||
+ while ((c = getopt(argc, argv, "+c:edp:l:hqvsu:g:t:n:fLi:T:wW:x")) != -1) { /* `+' is POSIX correct */
|
||
switch (c) {
|
||
case 'v':
|
||
quiet = 0;
|
||
@@ -127,6 +127,9 @@ int main(int argc, char **argv)
|
||
dialog = true;
|
||
seconds = 15;
|
||
break;
|
||
+ case 'x':
|
||
+ flags |= STSCRPT;
|
||
+ break;
|
||
case 'p': /* Former option -f */
|
||
if (force)
|
||
warn("option -p does not work in force mode\n");
|
||
@@ -412,6 +415,8 @@ static int do_start(const char *inname,
|
||
const char * fullname;
|
||
char proc_exe[6+9+4+1];
|
||
static struct stat itsme;
|
||
+ sigset_t newset, oldset;
|
||
+ int pipe[2];
|
||
|
||
if ((n = snprintf(proc_exe, sizeof(proc_exe) - 1, "/proc/%d/exe", getpid())) > 0) {
|
||
proc_exe[n] = '\0';
|
||
@@ -445,11 +450,17 @@ static int do_start(const char *inname,
|
||
if (sdaemon)
|
||
pid = 0;
|
||
else {
|
||
+ sigemptyset(&newset);
|
||
+ sigaddset(&newset, SIGQUIT);
|
||
+ sigaddset(&newset, SIGCHLD);
|
||
+ sigprocmask(SIG_UNBLOCK, &newset, &oldset);
|
||
save_sigquit = signal(SIGQUIT, sig_quit);
|
||
if (sigchld)
|
||
(void)signal(SIGCHLD, sig_chld);
|
||
else
|
||
(void)signal(SIGCHLD, SIG_DFL);
|
||
+ if (pipe2(pipe, O_CLOEXEC) < 0)
|
||
+ error(100, "cannot open a pipe: %m\n");
|
||
if ((pid = fork()) == 0) {
|
||
/* Update again to point to the child pid */
|
||
fwd_sd_listen_pid();
|
||
@@ -459,10 +470,15 @@ static int do_start(const char *inname,
|
||
switch (pid) {
|
||
case 0:
|
||
if (!sdaemon) {
|
||
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||
(void)signal(SIGINT, SIG_DFL);
|
||
(void)signal(SIGQUIT, SIG_DFL);
|
||
(void)signal(SIGSEGV, SIG_DFL);
|
||
(void)signal(SIGTERM, SIG_DFL);
|
||
+
|
||
+ close(pipe[1]);
|
||
+ read(pipe[0], proc_exe, 1); /* Wait on parent with the pipe here */
|
||
+ close(pipe[0]);
|
||
}
|
||
|
||
if (root) {
|
||
@@ -615,8 +631,8 @@ static int do_start(const char *inname,
|
||
fclose(tmp);
|
||
fflush(stdout);
|
||
fflush(stderr); /* flush stdout and especially stderr */
|
||
- usleep(1); /* Force the kernel to run the scheduler and update
|
||
- the environment of the current processes */
|
||
+
|
||
+ close(pipe[0]);
|
||
|
||
if ((n = snprintf(proc_exe, sizeof(proc_exe) - 1, "/proc/%d/exe", pid)) > 0) {
|
||
proc_exe[n] = '\0';
|
||
@@ -628,17 +644,21 @@ static int do_start(const char *inname,
|
||
* pid but before the execve() is done by the kernel, in later
|
||
* case be sure not to run on our own binary.
|
||
*/
|
||
+ n = 0;
|
||
do {
|
||
struct stat serv;
|
||
|
||
errno = 0;
|
||
if (stat(proc_exe, &serv) < 0) {
|
||
if (errno == ENOENT)
|
||
- break; /* Seems to be a fast system */
|
||
-
|
||
+ break; /* Seems to be a very fast system
|
||
+ * should not happen due to the pipe */
|
||
error(100, "cannot stat %s: %s\n", proc_exe, strerror(errno));
|
||
}
|
||
|
||
+ if (n++ == 0)
|
||
+ close(pipe[1]); /* Sync child over the pipe */
|
||
+
|
||
if (itsme.st_dev != serv.st_dev || itsme.st_ino != serv.st_ino)
|
||
break; /* Seems to be a slow system */
|
||
|
||
@@ -647,6 +667,9 @@ static int do_start(const char *inname,
|
||
} while (true);
|
||
|
||
} else {
|
||
+
|
||
+ close(pipe[1]); /* Sync child over the pipe */
|
||
+
|
||
warn("error in snprintf: %s\n", strerror(errno));
|
||
usleep(100*1000);
|
||
}
|
||
@@ -657,7 +680,7 @@ retry:
|
||
case -1: /* WNOHANG and hopefully no child but daemon */
|
||
if (errno == EINTR)
|
||
goto retry;
|
||
- if (errno != ECHILD) /* ECHILD shouldn<64>t happen, should it? (it does) */
|
||
+ if (errno != ECHILD) /* ECHILD should not happen, should it? (it does) */
|
||
error(LSB_PROOFE," waitpid on %s: %s\n", fullname, strerror(errno));
|
||
break;
|
||
case 0: /* WNOHANG and no status available */
|