I can offer a solution to this severe cause of compromised system integrity. The main problem lies in the calls to remove_me() and replace_me(), which in themselves are sufficient to corrupt /var/run/utmp.
My suggestion is to abondon utmp completely, where the clients of splitvt have no reason to be written anyway, instead moving all reporting into /var/log/wtmp via logwtmp() as the standard interface. The present patch works successfully against 1.6.6-9 and against the kfreebsd-patch I have suggested in the debian-bsd list. In the best of worlds, Joey Hess should be be brought in here, as he was responsible for so long time. Best regards, Mats Erik Andersson, DM
Description: Stop using utmp, migrate to wtmp. The old utmp-implementation is buggy since it corrupts /var/run/wtmp. A standardized use of logwtmp() is much securer and more common. . Built successfully against 1.6.6-9. Author: Mats Erik Andersson <deb...@gisladisker.se> Last-Update: 2011-03-23 Forwarded: no diff -Naurp splitvt-1.6.6.debian/config.c splitvt-1.6.6/config.c --- splitvt-1.6.6.debian/config.c 2011-03-23 15:43:33.000000000 +0100 +++ splitvt-1.6.6/config.c 2011-03-23 16:34:55.000000000 +0100 @@ -115,6 +115,7 @@ char *argv[]; /* Check for the ut_host field in the utmp file */ if ( grep(INCLUDE, "utmp.h", "ut_host") ) { strcat(cflags, " -DHAVE_UTHOST"); + strcat(ldflags, " -lutil"); VERBOSE_PRINT("\tYour utmp file uses the host field.\n"); } diff -Naurp splitvt-1.6.6.debian/splitvt.c splitvt-1.6.6/splitvt.c --- splitvt-1.6.6.debian/splitvt.c 2011-03-23 15:43:33.000000000 +0100 +++ splitvt-1.6.6/splitvt.c 2011-03-23 20:45:29.000000000 +0100 @@ -298,7 +298,6 @@ char *argv[]; signal(SIGCLD, SIG_IGN); #endif - (void) remove_me(); if ( (topfd=pty_open(upper_args, &toppid, UPPER)) < 0 ) { end_vt100(); @@ -638,8 +637,11 @@ static int isalive() if ( topok ) if ( kill(toppid, 0) < 0 ) { - if ( pw ) + if ( pw && upper_tty[0]) + { (void) delutmp(pw->pw_name, upper_tty); + upper_tty[0] = '\0'; + } if ( thisfd == topfd ) thisfd=bottomfd; (void) close(topfd); @@ -650,8 +652,11 @@ static int isalive() if ( bottomok ) if ( kill(bottompid, 0) < 0 ) { - if ( pw ) + if ( pw && lower_tty[0]) + { (void) delutmp(pw->pw_name, lower_tty); + lower_tty[0] = '\0'; + } if ( thisfd == bottomfd ) thisfd=topfd; (void) close(bottomfd); @@ -667,8 +672,11 @@ static int isalive() if ( topok ) if ( waitpid(toppid, &status, WNOHANG) != 0 ) { - if ( pw ) + if ( pw && upper_tty[0]) + { (void) delutmp(pw->pw_name, upper_tty); + upper_tty[0] = '\0'; + } if ( thisfd == topfd ) thisfd=bottomfd; (void) close(topfd); @@ -679,8 +687,11 @@ static int isalive() if ( bottomok ) if ( waitpid(bottompid, &status, WNOHANG) != 0 ) { - if ( pw ) + if ( pw && lower_tty[0]) + { (void) delutmp(pw->pw_name, lower_tty); + lower_tty[0] = '\0'; + } if ( thisfd == bottomfd ) thisfd=topfd; (void) close(bottomfd); @@ -712,7 +723,6 @@ int sig; (void) delutmp(pw->pw_name, upper_tty); if ( pw && bottomok && lower_tty[0] ) (void) delutmp(pw->pw_name, lower_tty); - (void) replace_me(); if ( sig ) printf("Exiting due to signal: %d\n", sig); diff -Naurp splitvt-1.6.6.debian/utmp.c splitvt-1.6.6/utmp.c --- splitvt-1.6.6.debian/utmp.c 2011-03-23 15:43:33.000000000 +0100 +++ splitvt-1.6.6/utmp.c 2011-03-23 21:20:45.000000000 +0100 @@ -172,7 +172,9 @@ char *tty; /* /dev/ttyxx */ /* Retrieve any existing utmp entry */ d_zero((char *)&ut, sizeof(ut)); +#if 0 /* Outdated */ (void) get_utmp(tty, &ut); +#endif /* Outdated */ /* Get the ttyxy form of the tty pathname if possible. */ if ( *tty == '/' ) { @@ -195,11 +197,15 @@ char *tty; /* /dev/ttyxx */ ut.ut_pid=getpid(); #endif #if defined(HAVE_UTHOST) +# if 0 /* Outdated */ /* remove_me() should be called before this function */ if ( utmp_saved ) { strncpy(ut.ut_host, saved_utmp.ut_host, sizeof(ut.ut_host)-1); ut.ut_host[sizeof(ut.ut_host)-1]='\0'; } +# else /* Portable and fun. */ + strncpy(ut.ut_host, "splitvt", 8); +# endif #endif (void) time(&ut.ut_time); @@ -212,7 +218,12 @@ char *tty; /* /dev/ttyxx */ } #endif +#if 0 /* Outdated */ return(set_utmp(tty, &ut)); +#else /* Only the safe use of /var/log/wtmp. */ + logwtmp(ttyptr, user, "splitvt"); + return 0; +#endif } @@ -226,6 +237,7 @@ char *tty; /* /dev/ttyxx */ struct utmp ut; int retval=0; +#if 0 /* Outdated manual manipulations. */ /* Retrieve any existing utmp entry */ d_zero((char *)&ut, sizeof(ut)); if ( get_utmp(tty, &ut) == 0 ) { @@ -240,6 +252,22 @@ char *tty; /* /dev/ttyxx */ (void) time(&ut.ut_time); retval=set_utmp(tty, &ut); } +#else /* Portable, half-way contemporary approach. */ + char *ttyptr; + + /* Get the ttyxy form of the tty pathname if possible. */ + if ( *tty == '/' ) { + for ( ttyptr=(tty+1); *ttyptr; ++ttyptr ) { + if ( *ttyptr == '/' ) + break; + } + if ( *ttyptr == '/' ) + ++ttyptr; + } else + ttyptr=tty; + + logwtmp(ttyptr, "", ""); +#endif #if !defined(SOLARIS) && !defined(IRIX) /* Solaris and Irix machines do this automatically */ diff -Naurp splitvt-1.6.6.debian/vttest.c splitvt-1.6.6/vttest.c --- splitvt-1.6.6.debian/vttest.c 2011-03-23 15:43:33.000000000 +0100 +++ splitvt-1.6.6/vttest.c 2011-03-23 18:11:49.000000000 +0100 @@ -14,6 +14,7 @@ #include <sys/types.h> #include <stdio.h> +#include <unistd.h> #include <fcntl.h> #ifdef HAVE_TERMIOS_H #include <termios.h>
signature.asc
Description: Digital signature