sysvinit/killproc-2.20.dif

380 lines
11 KiB
Plaintext
Raw Blame History

--- 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 */