Print this page
5375 utmpd(1M) core dumps when WTMPX_UPDATE_FREQ is zero
*** 17,27 ****
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
! * Copyright 2014 Shruti V Sampat <shrutisampat@gmail.com>
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
--- 17,27 ----
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
! * Copyright 2014, 2015 Shruti V Sampat <shrutisampat@gmail.com>
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*** 76,85 ****
--- 76,86 ----
#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,183 ****
--- 175,187 ----
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,194 ****
--- 189,199 ----
{
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,239 ****
exit(2);
}
}
/*
! * Read defaults file for poll timeout
*/
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("WTMPX_UPDATE_FREQ=")) != NULL) {
! WTMPX_ufreq = atol(defp);
! 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));
}
(void) defopen((char *)NULL);
}
if (Debug == 0) {
/*
--- 213,256 ----
exit(2);
}
}
/*
! * 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)
! 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)
! 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)
! 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,289 ****
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.");
/*
* 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.
--- 296,306 ----
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.");
/*
* 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,691 ****
* 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;
{
int fd = 0;
int i = 0, move_amt;
int j;
static int first_time = 1;
--- 697,707 ----
* 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_t pid)
{
int fd = 0;
int i = 0, move_amt;
int j;
static int first_time = 1;
*** 767,783 ****
/*
* 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
*/
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? */
{
int move_amt;
dprintf((" rem_pid: pid = %d i = %d", (int)pid, i));
--- 783,802 ----
/*
* 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_t pid, int i, int clean_it)
{
int move_amt;
dprintf((" rem_pid: pid = %d i = %d", (int)pid, i));
*** 821,833 ****
* 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;
{
struct pidentry pe;
struct pidentry *p;
pe.pl_pid = pid;
--- 840,850 ----
* find_pid - Returns an index into the pidtable of the specifed pid,
* else -1 if not found
*/
static int
! find_pid(pid_t pid, int *i)
{
struct pidentry pe;
struct pidentry *p;
pe.pl_pid = pid;
*** 845,856 ****
/*
* Pidcmp - Used by besearch for sorting and finding process IDs.
*/
static int
! pidcmp(a, b)
! struct pidentry *a, *b;
{
if (b == NULL || a == NULL)
return (0);
return (a->pl_pid - b->pl_pid);
}
--- 862,872 ----
/*
* Pidcmp - Used by besearch for sorting and finding process IDs.
*/
static int
! pidcmp(struct pidentry *a, struct pidentry *b)
{
if (b == NULL || a == NULL)
return (0);
return (a->pl_pid - b->pl_pid);
}
*** 859,870 ****
/*
* 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;
{
char procname[64];
int fd, dfd;
(void) sprintf(procname, "/proc/%d/psinfo", (int)pid);
--- 875,885 ----
/*
* 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_t pid)
{
char procname[64];
int fd, dfd;
(void) sprintf(procname, "/proc/%d/psinfo", (int)pid);
*** 909,920 ****
/*
* Clean_entry - Cleans the specified entry - where i is an index
* into the pid_table.
*/
static void
! clean_entry(i)
! int i;
{
struct utmpx *u;
if (pidcnt == 0)
return;
--- 924,934 ----
/*
* Clean_entry - Cleans the specified entry - where i is an index
* into the pid_table.
*/
static void
! clean_entry(int i)
{
struct utmpx *u;
if (pidcnt == 0)
return;
*** 923,933 ****
/*
* Double check if the process is dead.
*/
if (proc_is_alive(pidtable[i].pl_pid)) {
! dprintf((" Bad attempt to clean %d\n", \
(int)pidtable[i].pl_pid));
return;
}
/*
--- 937,947 ----
/*
* Double check if the process is dead.
*/
if (proc_is_alive(pidtable[i].pl_pid)) {
! dprintf((" Bad attempt to clean %d\n",
(int)pidtable[i].pl_pid));
return;
}
/*
*** 949,960 ****
/*
* clean_utmpx_ent - Clean a utmpx entry
*/
static void
! clean_utmpx_ent(u)
! 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);
--- 963,973 ----
/*
* clean_utmpx_ent - Clean a utmpx entry
*/
static void
! 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,1042 ****
* 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;
{
char psinfoname[64];
int fd;
psinfo_t psinfo;
--- 1044,1054 ----
* not a zombie. Returns 1 if process is alive
* and zero if it is dead or a zombie.
*/
static int
! proc_is_alive(pid_t pid)
{
char psinfoname[64];
int fd;
psinfo_t psinfo;
*** 1080,1085 ****
--- 1092,1123 ----
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);
}