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>

Attachment: signature.asc
Description: Digital signature

Reply via email to