Print this page
5375 utmpd(1M) core dumps when WTMPX_UPDATE_FREQ is zero
@@ -17,11 +17,11 @@
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
- * Copyright 2014 Shruti V Sampat <shrutisampat@gmail.com>
+ * Copyright 2014, 2015 Shruti V Sampat <shrutisampat@gmail.com>
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
@@ -76,10 +76,11 @@
#include <string.h>
#include <poll.h>
#include <deflt.h>
#include <procfs.h>
#include <sys/resource.h>
+#include <limits.h>
#define dprintf(x) if (Debug) (void) printf x
/*
* Memory allocation keyed off MAX_FDS
@@ -174,10 +175,13 @@
static void nonfatal(); /* Prints error message */
static void print_tables(); /* Prints out internal tables for Debug */
static int proc_is_alive(pid_t pid); /* Check if a process is alive */
static void warn_utmp(void);
+/* Validate defaults from file and assign */
+static int validate_default(char *defp, int *flag);
+
/*
* main() - Main does basic setup and calls wait_for_pids() to do the work
*/
int
@@ -185,10 +189,11 @@
{
char *defp;
struct rlimit rlim;
int i;
time_t curtime, now;
+ char msg[256];
prog_name = argv[0]; /* Save invocation name */
if (getuid() != 0) {
(void) fprintf(stderr,
@@ -208,32 +213,44 @@
exit(2);
}
}
/*
- * Read defaults file for poll timeout
+ * Read defaults file for poll timeout, WTMPX update frequency
+ * and maximum number of processes to monitor.
*/
if (defopen(UTMP_DEFAULT) == 0) {
- if ((defp = defread("SCAN_PERIOD=")) != NULL) {
- Poll_timeout = atol(defp);
- dprintf(("Poll timeout set to %d\n", Poll_timeout));
+ if ((defp = defread("SCAN_PERIOD=")) != NULL)
+ if (validate_default(defp, &Poll_timeout) == -1) {
+ (void) snprintf(msg, sizeof (msg), "SCAN_PERIOD"
+ " should be a positive integer, found %s",
+ defp);
+ nonfatal(msg);
}
+ dprintf(("Poll timeout set to %d\n", Poll_timeout));
- if ((defp = defread("WTMPX_UPDATE_FREQ=")) != NULL) {
- WTMPX_ufreq = atol(defp);
- dprintf(("WTMPX update frequency set to %d\n",
- WTMPX_ufreq));
+ if ((defp = defread("WTMPX_UPDATE_FREQ=")) != NULL)
+ if (validate_default(defp, &WTMPX_ufreq) == -1) {
+ (void) snprintf(msg, sizeof (msg),
+ "WTMPX_UPDATE_FREQ should be a positive "
+ "integer, found %s", defp);
+ nonfatal(msg);
}
+ dprintf(("WTMPX update frequency set to %d\n", WTMPX_ufreq));
/*
* Paranoia - if polling on large number of FDs is expensive /
* buggy the number can be set lower in the field.
*/
- if ((defp = defread("MAX_FDS=")) != NULL) {
- Max_fds = atol(defp);
- dprintf(("Max_fds set to %d\n", Max_fds));
+ if ((defp = defread("MAX_FDS=")) != NULL)
+ if (validate_default(defp, &Max_fds) == -1) {
+ (void) snprintf(msg, sizeof (msg), "MAX_FDS "
+ "should be a positive integer, found %s",
+ defp);
+ nonfatal(msg);
}
+ dprintf(("Max fds set to %d\n", Max_fds));
(void) defopen((char *)NULL);
}
if (Debug == 0) {
/*
@@ -279,11 +296,11 @@
fatal("getrlimit returned failure");
(void) enable_extended_FILE_stdio(-1, -1);
if ((WTMPXfd = open(WTMPX_FILE, O_RDONLY)) < 0)
- nonfatal("WARNING: unable to open " WTMPX_FILE "for update.");
+ nonfatal("WARNING: unable to open " WTMPX_FILE " for update.");
/*
* Loop here scanning the utmpx file and waiting for processes
* to terminate. Most of the activity is directed out of wait_for_pids.
* If wait_for_pids fails we reload the table and try again.
@@ -680,12 +697,11 @@
* add_pid - add a pid to the fd table and the pidtable.
* these tables are sorted tables for quick lookups.
*
*/
static void
-add_pid(pid)
- pid_t pid;
+add_pid(pid_t pid)
{
int fd = 0;
int i = 0, move_amt;
int j;
static int first_time = 1;
@@ -767,17 +783,20 @@
/*
* rem_pid - Remove an entry from the table and check to see if its
* not in the utmpx file.
* If i != -1 don't look up the pid, use i as index
+ *
+ * pid - Pid of process to clean or 0 if we don't know it
+ *
+ * i - Index into table or -1 if we need to look it up
+ *
+ * clean_it - Clean the entry, or just remove from table?
*/
static void
-rem_pid(pid, i, clean_it)
- pid_t pid; /* Pid of process to clean or 0 if we don't know it */
- int i; /* Index into table or -1 if we need to look it up */
- int clean_it; /* Clean the entry, or just remove from table? */
+rem_pid(pid_t pid, int i, int clean_it)
{
int move_amt;
dprintf((" rem_pid: pid = %d i = %d", (int)pid, i));
@@ -821,13 +840,11 @@
* find_pid - Returns an index into the pidtable of the specifed pid,
* else -1 if not found
*/
static int
-find_pid(pid, i)
- pid_t pid;
- int *i;
+find_pid(pid_t pid, int *i)
{
struct pidentry pe;
struct pidentry *p;
pe.pl_pid = pid;
@@ -845,12 +862,11 @@
/*
* Pidcmp - Used by besearch for sorting and finding process IDs.
*/
static int
-pidcmp(a, b)
- struct pidentry *a, *b;
+pidcmp(struct pidentry *a, struct pidentry *b)
{
if (b == NULL || a == NULL)
return (0);
return (a->pl_pid - b->pl_pid);
}
@@ -859,12 +875,11 @@
/*
* proc_to_fd - Take a process ID and return an open file descriptor to the
* /proc file for the specified process.
*/
static int
-proc_to_fd(pid)
- pid_t pid;
+proc_to_fd(pid_t pid)
{
char procname[64];
int fd, dfd;
(void) sprintf(procname, "/proc/%d/psinfo", (int)pid);
@@ -909,12 +924,11 @@
/*
* Clean_entry - Cleans the specified entry - where i is an index
* into the pid_table.
*/
static void
-clean_entry(i)
- int i;
+clean_entry(int i)
{
struct utmpx *u;
if (pidcnt == 0)
return;
@@ -923,11 +937,11 @@
/*
* Double check if the process is dead.
*/
if (proc_is_alive(pidtable[i].pl_pid)) {
- dprintf((" Bad attempt to clean %d\n", \
+ dprintf((" Bad attempt to clean %d\n",
(int)pidtable[i].pl_pid));
return;
}
/*
@@ -949,12 +963,11 @@
/*
* clean_utmpx_ent - Clean a utmpx entry
*/
static void
-clean_utmpx_ent(u)
- struct utmpx *u;
+clean_utmpx_ent(struct utmpx *u)
{
dprintf((" clean_utmpx_ent: %d\n", (int)u->ut_pid));
u->ut_type = DEAD_PROCESS;
(void) time(&u->ut_xtime);
(void) pututxline(u);
@@ -1031,12 +1044,11 @@
* not a zombie. Returns 1 if process is alive
* and zero if it is dead or a zombie.
*/
static int
-proc_is_alive(pid)
- pid_t pid;
+proc_is_alive(pid_t pid)
{
char psinfoname[64];
int fd;
psinfo_t psinfo;
@@ -1080,6 +1092,32 @@
if (lstat(UTMP_FILE, &s) == 0 &&
s.st_size % sizeof (struct utmp) == 0) {
nonfatal("WARNING: /var/adm/utmp exists!\nSee "
"utmp(4) for more information");
}
+}
+
+/*
+ * validate_default - validate and assign defaults.
+ */
+
+static int
+validate_default(char *defp, int *flag)
+{
+ long lval;
+ char *endptr;
+
+ errno = 0;
+ lval = strtol(defp, &endptr, 10);
+
+ if (errno != 0 || lval > INT_MAX || lval <= 0)
+ return (-1);
+
+ while (isspace(*endptr) != 0)
+ endptr++;
+
+ if (*endptr != '\0')
+ return (-1);
+
+ *flag = lval;
+ return (0);
}