sysvinit/sysvinit-2.90-no-kill.patch

236 lines
6.2 KiB
Diff
Raw Normal View History

---
src/killall5.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 132 insertions(+), 13 deletions(-)
--- src/killall5.c
+++ src/killall5.c 2023-05-02 14:14:02.198263058 +0000
@@ -67,6 +67,9 @@
#endif
#define STATNAMELEN 15
+#define DO_NETFS 2
+#define DO_STAT 1
+#define NO_STAT 0
/* Info about a process. */
typedef struct proc {
@@ -76,6 +79,8 @@ typedef struct proc {
char *argv1; /* Name as found out from argv[1] */
char *argv1base; /* `basename argv[1]` */
char *statname; /* the statname without braces */
+ ino_t ino; /* Inode number */
+ dev_t dev; /* Device it is on */
pid_t pid; /* Process ID. */
pid_t sid; /* Session ID. */
char kernel; /* Kernel thread or zombie. */
@@ -473,20 +478,54 @@ int readarg(FILE *fp, char *buf, int sz)
}
/*
+ * Scan the filedescriptors of pid for /dev/fuse
+ */
+int is_fuse(const char *pid) {
+ DIR *dir;
+ char path[256];
+ char buf[256];
+ struct dirent *d;
+ ssize_t len;
+
+ /* Open /proc/pid/fd/ */
+ snprintf(path, sizeof(path), "/proc/%s/fd", pid);
+ if ((dir = opendir(path)) != NULL) {
+ int dfd = dirfd(dir);
+ /* Walk through the directory. */
+ while ((d = readdir(dir)) != NULL) {
+ if (*d->d_name == '.')
+ continue;
+ /* check for /dev/fuse */
+ if ((len = readlinkat(dfd, d->d_name, buf, sizeof(buf))) > 0) {
+ buf[len] = '\0';
+ if (strcmp("/dev/fuse", buf) == 0)
+ return 1; /* Fuse filesystem */
+ }
+ }
+ closedir(dir);
+ }
+
+ /* Not a fuse filesystem */
+ return 0;
+}
+
+/*
* Read the proc filesystem.
* CWD must be /proc to avoid problems if / is affected by the killing (ie depend on fuse).
*/
-int readproc()
+int readproc(int do_stat)
{
DIR *dir;
FILE *fp;
PROC *p, *n;
struct dirent *d;
+ struct stat st;
char path[PATH_MAX+1];
char buf[PATH_MAX+1];
char *s, *q;
unsigned long startcode, endcode;
int pid, f;
+ ssize_t len;
char process_status[11];
/* Open the /proc directory. */
@@ -593,8 +632,12 @@ int readproc()
p->kernel = 1;
fclose(fp);
if ( (! list_dz_processes) &&
- (strchr(process_status, 'Z') != NULL) ) {
- /* Ignore zombie processes */
+ ( (strchr(process_status, 'D') != NULL) ||
+ (strchr(process_status, 'Z') != NULL) ) ){
+ /* Ignore zombie processes or processes in
+ disk sleep, as attempts
+ to access the stats of these will
+ sometimes fail. */
if (p->argv0) free(p->argv0);
if (p->argv1) free(p->argv1);
if (p->statname) free(p->statname);
@@ -661,11 +704,76 @@ int readproc()
/* Try to stat the executable. */
snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name);
- p->pathname = (char *)xmalloc(PATH_MAX);
- memset(p->pathname, 0, PATH_MAX);
- if (readlink(path, p->pathname, PATH_MAX) == -1) {
- p->pathname = NULL;
- }
+
+ p->nfs = 0;
+
+ switch (do_stat) {
+ case NO_STAT:
+ if ((len = readlink(path, buf, PATH_MAX)) < 0)
+ break;
+ buf[len] = '\0';
+
+ /* Check for uevent handler, mdmon, and for providers
+ of FUSE filesystems */
+ if ((strncmp(buf, "/usr/sbin/mdmon", 15) == 0) ||
+ (strncmp(buf, "/sbin/mdmon", 11) == 0) ||
+ (strncmp(buf, "/usr/lib/systemd/systemd-udevd", 30) == 0) ||
+ (is_fuse(d->d_name))) {
+ OMIT *restrict optr;
+
+ xmemalign((void*)&optr, sizeof(void*), alignof(OMIT));
+ optr->next = omit;
+ optr->prev = (OMIT*)0;
+ optr->pid = pid;
+ omit = optr;
+ }
+
+ break;
+ case DO_NETFS:
+ if ((p->nfs = check4nfs(path, buf)))
+ goto link;
+ /* else fall through */
+ case DO_STAT:
+ if (stat(path, &st) != 0) {
+ char * ptr;
+
+ len = readlink(path, buf, PATH_MAX);
+ if (len <= 0)
+ break;
+ buf[len] = '\0';
+
+ ptr = strstr(buf, " (deleted)");
+ if (!ptr)
+ break;
+ *ptr = '\0';
+ len -= strlen(" (deleted)");
+
+ if (stat(buf, &st) != 0)
+ break;
+ p->dev = st.st_dev;
+ p->ino = st.st_ino;
+ p->pathname = (char *)xmalloc(len + 1);
+ memcpy(p->pathname, buf, len);
+ p->pathname[len] = '\0';
+
+ /* All done */
+ break;
+ }
+
+ p->dev = st.st_dev;
+ p->ino = st.st_ino;
+
+ /* Fall through */
+ default:
+ link:
+ len = readlink(path, buf, PATH_MAX);
+ if (len > 0) {
+ p->pathname = (char *)xmalloc(len + 1);
+ memcpy(p->pathname, buf, len);
+ p->pathname[len] = '\0';
+ }
+ break;
+ }
/* Link it into the list. */
p->next = plist;
@@ -728,6 +836,7 @@ PIDQ_HEAD *pidof(char *prog)
{
PROC *p;
PIDQ_HEAD *q;
+ struct stat st;
char *s;
int nfs = 0;
int dostat = 0;
@@ -742,7 +851,15 @@ PIDQ_HEAD *pidof(char *prog)
/* Try to stat the executable. */
memset(real_path, 0, sizeof(real_path));
if ( (prog[0] == '/') && ( realpath(prog, real_path) ) ) {
- dostat++;
+
+ if (check4nfs(prog, real_path))
+ nfs++;
+
+ if (real_path[0] != '\0')
+ prog = &real_path[0]; /* Binary located on network FS. */
+
+ if ((nfs == 0) && (stat(prog, &st) == 0))
+ dostat++; /* Binary located on a local FS. */
}
/* Get basename of program. */
@@ -758,9 +875,11 @@ PIDQ_HEAD *pidof(char *prog)
q = init_pid_q(q);
/* First try to find a match based on dev/ino pair. */
- if (dostat) {
+ if (dostat && !nfs) {
for (p = plist; p; p = p->next) {
- if (p->pathname && strcmp(real_path, p->pathname) == 0) {
+ if (p->nfs)
+ continue;
+ if (p->dev == st.st_dev && p->ino == st.st_ino) {
add_pid_to_q(q, p);
foundone++;
}
@@ -1026,7 +1145,7 @@ int main_pidof(int argc, char **argv)
init_nfs(); /* Which network based FS are online? */
/* Print out process-ID's one by one. */
- readproc();
+ readproc((flags & PIDOF_NETFS) ? DO_NETFS : DO_STAT);
for(f = 0; f < argc; f++) {
if ((q = pidof(argv[f])) != NULL) {
@@ -1171,7 +1290,7 @@ int main(int argc, char **argv)
}
/* Read /proc filesystem */
- if (readproc() < 0) {
+ if (readproc(NO_STAT) < 0) {
if (sent_sigstop)
kill(-1, SIGCONT);
return(1);