Example #1
0
static inline void xmemalign(void **memptr, size_t alignment, size_t size)
{
	if ((posix_memalign(memptr, alignment, size)) < 0) {
		if (sent_sigstop) kill(-1, SIGCONT);
		nsyslog(LOG_ERR, "out of memory");
		exit(1);
	}
}
Example #2
0
/*
 *	See if the proc filesystem is there. Mount if needed.
 */
int mount_proc(void)
{
	struct stat	st;
	char		*args[] = { "mount", "-t", "proc", "proc", "/proc", 0 };
	pid_t		pid, rc;
	int		wst;
	int		did_mount = 0;

	/* Stat /proc/version to see if /proc is mounted. */
	if (stat("/proc/version", &st) < 0 && errno == ENOENT) {

		/* It's not there, so mount it. */
		if ((pid = fork()) < 0) {
			nsyslog(LOG_ERR, "cannot fork");
			exit(1);
		}
		if (pid == 0) {
			/* Try a few mount binaries. */
			execv("/sbin/mount", args);
			execv("/bin/mount", args);

			/* Okay, I give up. */
			nsyslog(LOG_ERR, "cannot execute mount");
			exit(1);
		}
		/* Wait for child. */
		while ((rc = wait(&wst)) != pid)
			if (rc < 0 && errno == ECHILD)
				break;
		if (rc != pid || WEXITSTATUS(wst) != 0)
			nsyslog(LOG_ERR, "mount returned non-zero exit status");

		did_mount = 1;
	}

	/* See if mount succeeded. */
	if (stat("/proc/version", &st) < 0) {
		if (errno == ENOENT)
			nsyslog(LOG_ERR, "/proc not mounted, failed to mount.");
		else
			nsyslog(LOG_ERR, "/proc unavailable.");
		exit(1);
	}

	return did_mount;
}
Example #3
0
static void *xmalloc(size_t bytes)
{
	void *p;

	if ((p = malloc(bytes)) == NULL) {
		if (sent_sigstop) kill(-1, SIGCONT);
		nsyslog(LOG_ERR, "out of memory");
		exit(1);
	}
	return p;
}
Example #4
0
/* Main for either killall or pidof. */
int main(int argc, char **argv)
{
	PROC		*p;
	int		pid, sid = -1;
	pid_t		opid[KILLALL_OMITSZ];
	int		i, oind, omit = 0;
	int		sig = SIGKILL;

	/* return non-zero if no process was killed */
	int		retval = 2;

	/* Get program name. */
	if ((progname = strrchr(argv[0], '/')) == NULL)
		progname = argv[0];
	else
		progname++;

	/* Now connect to syslog. */
	openlog(progname, LOG_CONS|LOG_PID, LOG_DAEMON);

	/* Were we called as 'pidof' ? */
	if (strcmp(progname, "pidof") == 0)
		return main_pidof(argc, argv);

	/* Right, so we are "killall". */
	for (oind = KILLALL_OMITSZ-1; oind > 0; oind--)
		opid[oind] = 0;

	if (argc > 1) {
		for (i = 1; i < argc; i++) {
			if (argv[i][0] == '-') (argv[i])++;
			if (argv[i][0] == 'o') {
				if (++i >= argc) usage();
				if (oind >= KILLALL_OMITSZ -1) {
					nsyslog(LOG_ERR,"omit pid buffer size "
						"%d exceeded!\n",
						KILLALL_OMITSZ);
					closelog();
					exit(1);
				}
				if ((opid[oind] = atoi(argv[i])) < 1) {
					nsyslog(LOG_ERR,
						"illegal omit pid value "
						"(%s)!\n", argv[i]);
					closelog();
					exit(1);
				}
				oind++;
				omit = 1;
			}
			else if ((sig = atoi(argv[1])) <= 0 || sig > 31)
				usage();
		}
	}

	/* First get the /proc filesystem online. */
	mount_proc();

	/*
	 *	Ignoring SIGKILL and SIGSTOP do not make sense, but
	 *	someday kill(-1, sig) might kill ourself if we don't
	 *	do this. This certainly is a valid concern for SIGTERM-
	 *	Linux 2.1 might send the calling process the signal too.
	 */
	signal(SIGTERM, SIG_IGN);
	signal(SIGSTOP, SIG_IGN);
	signal(SIGKILL, SIG_IGN);

	/* lock us into memory */
	mlockall(MCL_CURRENT | MCL_FUTURE);

	/* Now stop all processes. */
	kill(-1, SIGSTOP);
	sent_sigstop = 1;

	/* Read /proc filesystem */
	if (readproc(NO_STAT) < 0) {
		kill(-1, SIGCONT);
		return(1);
	}

	/* Now kill all processes except init (pid 1) and our session. */
	sid = (int)getsid(0);
	pid = (int)getpid();
	for (p = plist; p; p = p->next) {
		if (p->pid == 1 || p->pid == pid || p->sid == sid || p->kernel)
			continue;
		if (omit) {
			for (i = 0; i < oind; i++)
				if (opid[i] == p->pid)
					break;
			/* On a match, continue with the for loop above. */
			if (i < oind)
				continue;
		}
		kill(p->pid, sig);
		retval = 0;
	}

	/* And let them continue. */
	kill(-1, SIGCONT);

	/* Done. */
	closelog();

	/* Force the kernel to run the scheduler */
	usleep(1);

	return retval;
}
Example #5
0
/*
 *	Pidof functionality.
 */
int main_pidof(int argc, char **argv)
{
	PIDQ_HEAD	*q;
	PROC		*p;
	pid_t		opid[PIDOF_OMITSZ], spid;
	int		f;
	int		first = 1;
	int		i, oind, opt, flags = 0;
	int		chroot_check = 0;
	struct stat	st;
	char		tmp[512];

	for (oind = PIDOF_OMITSZ-1; oind > 0; oind--)
		opid[oind] = 0;
	opterr = 0;

	while ((opt = getopt(argc,argv,"hco:sx")) != EOF) switch (opt) {
		case '?':
			nsyslog(LOG_ERR,"invalid options on command line!\n");
			closelog();
			exit(1);
		case 'c':
			if (geteuid() == 0) chroot_check = 1;
			break;
		case 'o':
			if (oind >= PIDOF_OMITSZ -1) {
				nsyslog(LOG_ERR,"omit pid buffer size %d "
					"exceeded!\n", PIDOF_OMITSZ);
				closelog();
				exit(1);
			}
			if (strcmp("%PPID",optarg) == 0)
				opid[oind] = getppid();
			else if ((opid[oind] = atoi(optarg)) < 1) {
				nsyslog(LOG_ERR,
					"illegal omit pid value (%s)!\n",
					optarg);
				closelog();
				exit(1);
			}
			oind++;
			flags |= PIDOF_OMIT;
			break;
		case 's':
			flags |= PIDOF_SINGLE;
			break;
		case 'x':
			scripts_too++;
			break;
		default:
			/* Nothing */
			break;
	}
	argc -= optind;
	argv += optind;

	/* Check if we are in a chroot */
	if (chroot_check) {
		snprintf(tmp, 512, "/proc/%d/root", getpid());
		if (stat(tmp, &st) < 0) {
			nsyslog(LOG_ERR, "stat failed for %s!\n", tmp);
			closelog();
			exit(1);
		}
	}

	/* Print out process-ID's one by one. */
	readproc(DO_STAT);
	for(f = 0; f < argc; f++) {
		if ((q = pidof(argv[f])) != NULL) {
			spid = 0;
			while ((p = get_next_from_pid_q(q))) {
				if (flags & PIDOF_OMIT) {
					for (i = 0; i < oind; i++)
						if (opid[i] == p->pid)
							break;
					/*
					 *	On a match, continue with
					 *	the for loop above.
					 */
					if (i < oind)
						continue;
				}
				if (flags & PIDOF_SINGLE) {
					if (spid)
						continue;
					else
						spid = 1;
				}
				if (chroot_check) {
					struct stat st2;
					snprintf(tmp, 512, "/proc/%d/root",
						 p->pid);
					if (stat(tmp, &st2) < 0 ||
					    st.st_dev != st2.st_dev ||
					    st.st_ino != st2.st_ino) {
						continue;
					}
				}
				if (!first)
					printf(" ");
				printf("%d", p->pid);
				first = 0;
			}
		}
	}
	if (!first)
		printf("\n");
	closelog();
	return(first ? 1 : 0);
}
Example #6
0
/* Give usage message and exit. */
void usage(void)
{
	nsyslog(LOG_ERR, "only one argument, a signal number, allowed");
	closelog();
	exit(1);
}
Example #7
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 do_stat)
{
	DIR		*dir;
	FILE		*fp;
	PROC		*p, *n;
	struct dirent	*d;
	struct stat	st;
	char		path[256];
	char		buf[256];
	char		*s, *q;
	unsigned long	startcode, endcode;
	int		pid, f;

	/* Open the /proc directory. */
	if (chdir("/proc") == -1) {
		nsyslog(LOG_ERR, "chdir /proc failed");
		return -1;
	}
	if ((dir = opendir(".")) == NULL) {
		nsyslog(LOG_ERR, "cannot opendir(/proc)");
		return -1;
	}

	/* Free the already existing process list. */
	n = plist;
	for (p = plist; n; p = n) {
		n = p->next;
		if (p->argv0) free(p->argv0);
		if (p->argv1) free(p->argv1);
		free(p);
	}
	plist = NULL;

	/* Walk through the directory. */
	while ((d = readdir(dir)) != NULL) {

		/* See if this is a process */
		if ((pid = atoi(d->d_name)) == 0) continue;

		/* Get a PROC struct . */
		p = (PROC *)xmalloc(sizeof(PROC));
		memset(p, 0, sizeof(PROC));

		/* Open the status file. */
		snprintf(path, sizeof(path), "%s/stat", d->d_name);

		/* Read SID & statname from it. */
		if ((fp = fopen(path, "r")) != NULL) {
			buf[0] = 0;
			fgets(buf, sizeof(buf), fp);

			/* See if name starts with '(' */
			s = buf;
			while (*s != ' ') s++;
			s++;
			if (*s == '(') {
				/* Read program name. */
				q = strrchr(buf, ')');
				if (q == NULL) {
					p->sid = 0;
					nsyslog(LOG_ERR,
					"can't get program name from /proc/%s\n",
						path);
					free(p);
					continue;
				}
				s++;
			} else {
				q = s;
				while (*q != ' ') q++;
			}
			*q++ = 0;
			while (*q == ' ') q++;
			p->statname = (char *)xmalloc(strlen(s)+1);
			strcpy(p->statname, s);

			/* Get session, startcode, endcode. */
			startcode = endcode = 0;
			if (sscanf(q, 	"%*c %*d %*d %d %*d %*d %*u %*u "
					"%*u %*u %*u %*u %*u %*d %*d "
					"%*d %*d %*d %*d %*u %*u %*d "
					"%*u %lu %lu",
					&p->sid, &startcode, &endcode) != 3) {
				p->sid = 0;
				nsyslog(LOG_ERR, "can't read sid from %s\n",
					path);
				free(p);
				continue;
			}
			if (startcode == 0 && endcode == 0)
				p->kernel = 1;
			fclose(fp);
		} else {
			/* Process disappeared.. */
			free(p);
			continue;
		}

		snprintf(path, sizeof(path), "%s/cmdline", d->d_name);
		if ((fp = fopen(path, "r")) != NULL) {

			/* Now read argv[0] */
			f = readarg(fp, buf, sizeof(buf));

			if (buf[0]) {
				/* Store the name into malloced memory. */
				p->argv0 = (char *)xmalloc(f + 1);
				strcpy(p->argv0, buf);

				/* Get a pointer to the basename. */
				p->argv0base = strrchr(p->argv0, '/');
				if (p->argv0base != NULL)
					p->argv0base++;
				else
					p->argv0base = p->argv0;
			}

			/* And read argv[1] */
			while ((f = readarg(fp, buf, sizeof(buf))) != EOF)
				if (buf[0] != '-') break;

			if (buf[0]) {
				/* Store the name into malloced memory. */
				p->argv1 = (char *)xmalloc(f + 1);
				strcpy(p->argv1, buf);

				/* Get a pointer to the basename. */
				p->argv1base = strrchr(p->argv1, '/');
				if (p->argv1base != NULL)
					p->argv1base++;
				else
					p->argv1base = p->argv1;
			}

			fclose(fp);

		} else {
			/* Process disappeared.. */
			free(p);
			continue;
		}

		/* Try to stat the executable. */
		snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name);
		if (do_stat && stat(path, &st) == 0) {
			p->dev = st.st_dev;
			p->ino = st.st_ino;
		}

		/* Link it into the list. */
		p->next = plist;
		plist = p;
		p->pid = pid;
	}
	closedir(dir);

	/* Done. */
	return 0;
}