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
[-- Attachment #1 --]
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
===================================================================
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
===================================================================
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();
/*
* If a change has occured, store the new terminal control
@@ -205,7 +204,8 @@
slcptr += 2;
len = 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
===================================================================
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;
- DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
+ DIAG(TD_OPTIONS, {while ((nfrontp - nbackp) > 0) netflush();
+ printsub('<', subpointer, SB_LEN()+2);});
subchar = SB_GET();
switch (subchar) {
@@ -1532,7 +1534,8 @@
ncp = statusbuf;
- netflush(); /* get rid of anything waiting to go out */
+ while ((nfrontp - nbackp) > 0)
+ netflush(); /* get rid of anything waiting to go out */
ADD(IAC);
ADD(SB);
@@ -1607,48 +1610,79 @@
ADD(SE);
output_datalen(statusbuf, ncp - statusbuf);
- netflush(); /* Send it on its way */
+ while ((nfrontp - nbackp) > 0)
+ netflush(); /* Send it on its way */
DIAG(TD_OPTIONS,
- {printsub('>', statusbuf, ncp - statusbuf); netflush();});
+ {printsub('>', statusbuf, ncp - statusbuf);
+ while ((nfrontp - nbackp) > 0) netflush();});
}
/*
* 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).
*/
int
output_data(const char *format, ...)
{
va_list args;
- size_t remaining, ret;
+ size_t remaining, copied;
+ int bufremain;
+ char *buf, *bufp;
va_start(args, format);
+ /* calculate free space to play with */
remaining = BUFSIZ - (nfrontp - netobuf);
- /* try a netflush() if the room is too low */
- if (strlen(format) > remaining || BUFSIZ / 4 > remaining) {
- netflush();
- remaining = BUFSIZ - (nfrontp - netobuf);
+
+ if ((bufremain = vasprintf(&buf, format, args)) == -1)
+ return -1;
+ bufp = buf;
+
+ while (bufremain > 0) {
+ /* Free up enough space if the room is too low */
+ while ((bufremain > BUFSIZ ? BUFSIZ : bufremain) > remaining)
+ remaining += netflush();
+
+ /* Copy out as much as will fit */
+ copied = remaining > bufremain ? bufremain : remaining;
+ memmove(nfrontp, bufp, copied);
+ nfrontp += copied;
+ bufremain -= copied;
+ remaining -= copied;
+ bufp += copied;
}
- ret = vsnprintf(nfrontp, remaining, format, args);
- nfrontp += (ret < remaining) ? ret : remaining;
va_end(args);
- return ret;
+ bufremain = strlen(buf);
+ free(buf);
+ return bufremain;
}
int
output_datalen(const char *buf, size_t len)
{
size_t remaining;
-
+ int bufremain, copied;
+ const char *bufp;
+
remaining = BUFSIZ - (nfrontp - netobuf);
- if (remaining < len) {
- netflush();
- remaining = BUFSIZ - (nfrontp - netobuf);
- if (remaining < len)
- return -1;
+ bufremain = len;
+ bufp = buf;
+
+ while (bufremain > 0) {
+ /* Free up enough space if the room is too low*/
+ while((bufremain > BUFSIZ ? BUFSIZ : bufremain) > remaining)
+ remaining += netflush();
+
+ /* Copy out as much as will fit */
+ copied = remaining > bufremain ? bufremain : remaining;
+ memmove(nfrontp, bufp, copied);
+ nfrontp += copied;
+ bufremain -= copied;
+ remaining -= copied;
+ bufp += copied;
}
- memmove(nfrontp, buf, len);
- nfrontp += len;
+
return (len);
}
Index: telnetd.c
===================================================================
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;
/*
@@ -1420,8 +1419,9 @@
}
#endif /* defined(CRAY2) && defined(UNICOS5) */
- 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
===================================================================
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 = 0;
#if defined(CRAY2) && defined(UNICOS5)
@@ -404,7 +403,6 @@
clientstat(code, parm1, parm2)
register int code, parm1, parm2;
{
- void netflush();
/*
* Get a copy of terminal characteristics.
Index: utility.c
===================================================================
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();
DIAG(TD_REPORT, output_data("td: ttloop\r\n"));
- if (nfrontp-nbackp) {
+ while ((nfrontp - nbackp) > 0) {
netflush();
}
ncc = 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;
if ((n = nfrontp - nbackp) > 0) {
+#if 0
+ /* XXX This causes output_data() to recurse and die */
DIAG(TD_REPORT, {
n += output_data("td: netflush %d chars\r\n", n);
});
+#endif
#ifdef ENCRYPTION
if (encrypt_output) {
char *s = nclearto ? nclearto : nbackp;
@@ -296,7 +299,7 @@
}
if (n < 0) {
if (errno == EWOULDBLOCK || errno == EINTR)
- return;
+ return 0;
cleanup(0);
}
nbackp += n;
@@ -313,7 +316,7 @@
nclearto = 0;
#endif /* ENCRYPTION */
}
- return;
+ return (n);
} /* end of netflush */
@@ -1082,7 +1085,7 @@
while (cnt) {
/* flush net output buffer if no room for new data) */
- if ((&netobuf[BUFSIZ] - nfrontp) < 80) {
+ while ((&netobuf[BUFSIZ] - nfrontp) < 80) {
netflush();
}
[-- Attachment #2 --]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (FreeBSD)
Comment: For info see http://www.gnupg.org
iD8DBQE7W7KlWry0BWjoQKURAt/7AJ0ahHx2P4erlF66H7PvjUyikErkUwCg706O
M81Bq7cl29EHaBtQDK7TlEs=
=1gGv
-----END PGP SIGNATURE-----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010722221413.A95414>
