We had discussed whether login fails often due to left-over utmp entries. I guess that depends on how likely it is that processes die without cleanup; and how important it is that login should "work".
I now see that there is the possibility for a DoS attack, by filling up utmp with left-over entries to cover all PIDs (or a significant proportion of PID space). For example, we can cause one left-over entry with run xterm and within that xterm use "kill -9 $PPID" and might try that repeatedly to exhaust PID space; except xterm reuses ptys and re-writes utmp entries, and the pty space is smaller than PID space... Until this is fixed, utmp should be sanitized regularly to remove unused entries. I now use the following, often (i.e. nightly). Cheers, Paul Szabo [email protected] http://www.maths.usyd.edu.au/u/psz/ School of Mathematics and Statistics University of Sydney Australia --- #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdio.h> #include <utmp.h> #include <time.h> /* #include <signal.h> #include <errno.h> */ int main( int argc, char *argv[]) { char *usage = "Usage:\n\n\ clear-dead-utmp-entries [-quiet] [-really]\n\n\ to clear left-over utmp entries.\n\n"; int debug = 0; int quiet = 0; int really = 0; int cleared = 0; int clearable = 0; int header = 0; int i; struct utmp *utmpp; struct tm *tmmp; #define buflen 256 char buf[buflen]; struct stat strst; for (i=1; i<argc; i++) { if (!strcmp(argv[i], "-debug")) { debug++; } else if (!strcmp(argv[i], "-quiet")) { quiet++; } else if (!strcmp(argv[i], "-really")) { really++; } else { printf ("\nBad option %s. %s", argv[i], usage); return 1; } } setutent(); while (utmpp = getutent()) { if (utmpp->ut_type != INIT_PROCESS && utmpp->ut_type != LOGIN_PROCESS && utmpp->ut_type != USER_PROCESS) continue; if (utmpp->ut_pid == 0) continue; /* Is this PID "alive"? */ /* Seems that /usr/bin/who uses if (kill(utmpp->ut_pid, 0) < 0 && errno == ESRCH) continue; but "plain" psz gets EPERM, while root gets success with ENOENT. */ sprintf(buf, "/proc/%d", (int)utmpp->ut_pid); if (!stat(buf, &strst)) continue; tmmp = localtime(&utmpp->ut_time); strftime(buf, buflen, "%b %d %H:%M", tmmp); if (debug) { printf ("\nutmp line:\n"); printf (" ut_user: %.*s\n", sizeof(utmpp->ut_user), utmpp->ut_user); printf (" ut_id: %.*s\n", sizeof(utmpp->ut_id), utmpp->ut_id); printf (" ut_line: %.*s\n", sizeof(utmpp->ut_line), utmpp->ut_line); printf (" ut_type: %d\n", (int)utmpp->ut_type); printf (" ut_pid: %d\n", (int)utmpp->ut_pid); printf (" e_term: %d\n", (int)utmpp->ut_exit.e_termination); printf (" e_exit: %d\n", (int)utmpp->ut_exit.e_exit); printf (" ut_time: %s\n", buf); printf (" ut_host: %.*s\n", sizeof(utmpp->ut_host), utmpp->ut_host); printf ("\n"); } if (!header) { printf ("T PID Name Line Time Hostname\n"); header++; } printf ("%-2d%-6d%-10.10s%-8.8s%-13.13s%.40s\n", (int)utmpp->ut_type, (int)utmpp->ut_pid, utmpp->ut_user, utmpp->ut_line, buf, utmpp->ut_host); if (!really) { clearable++; continue; } utmpp->ut_type = DEAD_PROCESS; if (! pututline(utmpp)) { printf ("\nERROR: Cannot clear utmp entry above\n\n"); break; }; cleared++; } if (cleared==1) { printf ("Cleared one utmp entry shown above\n"); } else if (cleared>1) { printf ("Cleared %d utmp entries shown above\n", cleared); } else { if (clearable) printf ("No utmp entries cleared, need '-really' option for that\n"); else if (!quiet) printf ("No utmp entries cleared\n"); } } -- To UNSUBSCRIBE, email to [email protected] with a subject of "unsubscribe". Trouble? Contact [email protected]

