Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Jul 2001 22:14:14 -0700
From:      Kris Kennaway <kris@obsecurity.org>
To:        Kris Kennaway <kris@obsecurity.org>
Cc:        Assar Westerlund <assar@FreeBSD.ORG>, Matt Dillon <dillon@earth.backplane.com>, Ruslan Ermilov <ru@FreeBSD.ORG>, audit@FreeBSD.ORG
Subject:   Re: [PATCH] Re: FreeBSD remote root exploit ?
Message-ID:  <20010722221413.A95414@xor.obsecurity.org>
In-Reply-To: <20010722215619.A94874@xor.obsecurity.org>; from kris@obsecurity.org on Sun, Jul 22, 2001 at 09:56:20PM -0700
References:  <200107191817.f6JIHSJ76262@earth.backplane.com> <20010719215957.A74024@sunbay.com> <200107191917.f6JJHwV77405@earth.backplane.com> <20010720100029.A30828@sunbay.com> <200107200932.f6K9WgZ88552@earth.backplane.com> <20010720143742.E65677@sunbay.com> <200107201717.f6KHHGa91142@earth.backplane.com> <20010722194031.A92249@jail-3.5> <5l66ck9wm7.fsf@assaris.sics.se> <20010722215619.A94874@xor.obsecurity.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--qDbXVdCdHGoSgWSk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Sun, Jul 22, 2001 at 09:56:20PM -0700, Kris Kennaway wrote:

> * Some places which called netflush() conditionally (e.g. if there is
>   insufficient free space for the operation they're about to do) now
>   use while() to guarantee this; previously they could overflow if the
>   netflush() failed.  Some of the netflush() calls seemed to only be
>   'advisory' and nothing depends on the flush actually taking place
>   immediately.  I've left these alone for now; perhaps they should be
>   changed to flush the entire buffer.

After thinking about this a bit further, I've decided to make the
standalone netflush() calls flush the entire buffer.  This seems like
a better thing to do than to potentially do nothing at all.

I'm also not sure if I diffed the last patch against the correct CVS
versions.  Updated patch follows.

Kris

Index: ext.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/crypto/telnet/telnetd/ext.h,v
retrieving revision 1.2.8.2
diff -u -r1.2.8.2 ext.h
--- ext.h	2001/07/20 15:16:52	1.2.8.2
+++ ext.h	2001/07/23 05:05:23
@@ -120,7 +120,6 @@
 	localstat P((void)),
 	flowstat P((void)),
 	netclear P((void)),
-	netflush P((void)),
 #ifdef DIAGNOSTICS
 	printoption P((char *, int)),
 	printdata P((char *, char *, int)),
@@ -159,6 +158,7 @@
 	getpty P((int *)),
 #endif
 	login_tty P((int)),
+	netflush P((void)),
 	spcset P((int, cc_t *, cc_t **)),
 	stilloob P((int)),
 	terminit P((void)),
Index: slc.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/crypto/telnet/telnetd/slc.c,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 slc.c
--- slc.c	2001/07/20 15:16:52	1.4.2.1
+++ slc.c	2001/07/23 05:09:10
@@ -176,7 +176,6 @@
 	register unsigned char **bufp;
 {
 	register int len;
-	void netflush();
=20
 	/*
 	 * If a change has occured, store the new terminal control
@@ -205,7 +204,8 @@
 			slcptr +=3D 2;
 			len =3D slcptr - slcbuf;
 			output_datalen(slcbuf, len);
-			netflush();  /* force it out immediately */
+			while ((nfrontp - nbackp) > 0)
+			    netflush();  /* force it out immediately */
 			DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2););
 		}
 	}
Index: state.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/crypto/telnet/telnetd/state.c,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 state.c
--- state.c	2001/07/20 15:16:52	1.4.2.1
+++ state.c	2001/07/23 05:11:24
@@ -938,7 +938,8 @@
 			set_my_want_state_will(TELOPT_LOGOUT);
 			send_will(TELOPT_LOGOUT, 0);
 			set_my_state_will(TELOPT_LOGOUT);
-			(void)netflush();
+			while ((nfrontp - nbackp) > 0)
+				netflush();
 			cleanup(0);
 			/* NOT REACHED */
 			break;
@@ -1100,7 +1101,8 @@
 {
     register int subchar;
=20
-    DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
+    DIAG(TD_OPTIONS, {while ((nfrontp - nbackp) > 0) netflush();
+    	printsub('<', subpointer, SB_LEN()+2);});
=20
     subchar =3D SB_GET();
     switch (subchar) {
@@ -1532,7 +1534,8 @@
=20
 	ncp =3D statusbuf;
=20
-	netflush();	/* get rid of anything waiting to go out */
+	while ((nfrontp - nbackp) > 0)
+		netflush();	/* get rid of anything waiting to go out */
=20
 	ADD(IAC);
 	ADD(SB);
@@ -1607,48 +1610,79 @@
 	ADD(SE);
=20
 	output_datalen(statusbuf, ncp - statusbuf);
-	netflush();	/* Send it on its way */
+	while ((nfrontp - nbackp) > 0)
+		netflush();	/* Send it on its way */
=20
 	DIAG(TD_OPTIONS,
-		{printsub('>', statusbuf, ncp - statusbuf); netflush();});
+		{printsub('>', statusbuf, ncp - statusbuf);
+		while ((nfrontp - nbackp) > 0) netflush();});
 }
=20
 /*
  * This function appends data to nfrontp and advances nfrontp.
+ * Returns the number of characters written altogether (the buffer may have
+ * been flushed in the process).
  */
=20
 int
 output_data(const char *format, ...)
 {
 	va_list args;
-	size_t remaining, ret;
+	size_t remaining, copied;
+	int bufremain;
+	char *buf, *bufp;
=20
 	va_start(args, format);
+	/* calculate free space to play with */
 	remaining =3D BUFSIZ - (nfrontp - netobuf);
-	/* try a netflush() if the room is too low */
-	if (strlen(format) > remaining || BUFSIZ / 4 > remaining) {
-		netflush();
-		remaining =3D BUFSIZ - (nfrontp - netobuf);
+
+	if ((bufremain =3D vasprintf(&buf, format, args)) =3D=3D -1)
+		return -1;
+	bufp =3D buf;
+
+	while (bufremain > 0) {
+		/* Free up enough space if the room is too low */
+		while ((bufremain > BUFSIZ ? BUFSIZ : bufremain) > remaining)
+			remaining +=3D netflush();
+
+		/* Copy out as much as will fit */
+		copied =3D remaining > bufremain ? bufremain : remaining;
+		memmove(nfrontp, bufp, copied);
+		nfrontp +=3D copied;
+		bufremain -=3D copied;
+		remaining -=3D copied;
+		bufp +=3D copied;
 	}
-	ret =3D vsnprintf(nfrontp, remaining, format, args);
-	nfrontp +=3D (ret < remaining) ? ret : remaining;
 	va_end(args);
-	return ret;
+	bufremain =3D strlen(buf);
+	free(buf);
+	return bufremain;
 }
=20
 int
 output_datalen(const char *buf, size_t len)
 {
 	size_t remaining;
-
+	int bufremain, copied;
+	const char *bufp;
+=09
 	remaining =3D BUFSIZ - (nfrontp - netobuf);
-	if (remaining < len) {
-		netflush();
-		remaining =3D BUFSIZ - (nfrontp - netobuf);
-		if (remaining < len)
-			return -1;
+	bufremain =3D len;
+	bufp =3D buf;
+
+	while (bufremain > 0) {
+		/* Free up enough space if the room is too low*/
+		while((bufremain > BUFSIZ ? BUFSIZ : bufremain) > remaining)
+			remaining +=3D netflush();
+
+		/* Copy out as much as will fit */
+		copied =3D remaining > bufremain ? bufremain : remaining;
+		memmove(nfrontp, bufp, copied);
+		nfrontp +=3D copied;
+		bufremain -=3D copied;
+		remaining -=3D copied;
+		bufp +=3D copied;
 	}
-	memmove(nfrontp, buf, len);
-	nfrontp +=3D len;
+
 	return (len);
 }
Index: telnetd.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/crypto/telnet/telnetd/telnetd.c,v
retrieving revision 1.11.2.3
diff -u -r1.11.2.3 telnetd.c
--- telnetd.c	2001/07/20 15:16:52	1.11.2.3
+++ telnetd.c	2001/07/23 05:05:23
@@ -952,7 +952,6 @@
 	char *HE;
 	char *HN;
 	char *IM;
-	void netflush();
 	int nfd;
=20
 	/*
@@ -1420,8 +1419,9 @@
 		}
 #endif	/* defined(CRAY2) && defined(UNICOS5) */
=20
-		if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
-			netflush();
+		if (FD_ISSET(f, &obits))
+			while ((nfrontp - nbackp) > 0)
+				netflush();
 		if (ncc > 0)
 			telrcv();
 		if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
Index: termstat.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/crypto/telnet/telnetd/termstat.c,v
retrieving revision 1.4.2.2
diff -u -r1.4.2.2 termstat.c
--- termstat.c	2001/07/20 15:16:52	1.4.2.2
+++ termstat.c	2001/07/23 05:05:24
@@ -140,7 +140,6 @@
 	void
 localstat()
 {
-	void netflush();
 	int need_will_echo =3D 0;
=20
 #if	defined(CRAY2) && defined(UNICOS5)
@@ -404,7 +403,6 @@
 clientstat(code, parm1, parm2)
 	register int code, parm1, parm2;
 {
-	void netflush();
=20
 	/*
 	 * Get a copy of terminal characteristics.
Index: utility.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /mnt/ncvs/src/crypto/telnet/telnetd/utility.c,v
retrieving revision 1.5.2.2
diff -u -r1.5.2.2 utility.c
--- utility.c	2001/07/20 15:16:52	1.5.2.2
+++ utility.c	2001/07/23 05:05:24
@@ -69,10 +69,9 @@
     void
 ttloop()
 {
-    void netflush();
=20
     DIAG(TD_REPORT, output_data("td: ttloop\r\n"));
-    if (nfrontp-nbackp) {
+    while ((nfrontp - nbackp) > 0) {
 	netflush();
     }
     ncc =3D read(net, netibuf, sizeof netibuf);
@@ -249,18 +248,22 @@
 /*
  *  netflush
  *		Send as much data as possible to the network,
- *	handling requests for urgent data.
+ *	handling requests for urgent data.  Not all data in the
+ *	buffer may be sent.
  */
-    void
+    int
 netflush()
 {
     int n;
     extern int not42;
=20
     if ((n =3D nfrontp - nbackp) > 0) {
+#if 0
+	/* XXX This causes output_data() to recurse and die */
 	DIAG(TD_REPORT, {
 	    n +=3D output_data("td: netflush %d chars\r\n", n);
 	});
+#endif
 #ifdef	ENCRYPTION
 	if (encrypt_output) {
 		char *s =3D nclearto ? nclearto : nbackp;
@@ -296,7 +299,7 @@
     }
     if (n < 0) {
 	if (errno =3D=3D EWOULDBLOCK || errno =3D=3D EINTR)
-		return;
+		return 0;
 	cleanup(0);
     }
     nbackp +=3D n;
@@ -313,7 +316,7 @@
 	nclearto =3D 0;
 #endif	/* ENCRYPTION */
     }
-    return;
+    return (n);
 }  /* end of netflush */
=20
=20
@@ -1082,7 +1085,7 @@
=20
 	while (cnt) {
 		/* flush net output buffer if no room for new data) */
-		if ((&netobuf[BUFSIZ] - nfrontp) < 80) {
+		while ((&netobuf[BUFSIZ] - nfrontp) < 80) {
 			netflush();
 		}
=20

--qDbXVdCdHGoSgWSk
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (FreeBSD)
Comment: For info see http://www.gnupg.org

iD8DBQE7W7KlWry0BWjoQKURAt/7AJ0ahHx2P4erlF66H7PvjUyikErkUwCg706O
M81Bq7cl29EHaBtQDK7TlEs=
=1gGv
-----END PGP SIGNATURE-----

--qDbXVdCdHGoSgWSk--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010722221413.A95414>