Date: Mon, 23 Jul 2001 18:22:04 +0300 From: Ruslan Ermilov <ru@FreeBSD.ORG> To: Assar Westerlund <assar@sics.se> Cc: Kris Kennaway <kris@obsecurity.org>, Matt Dillon <dillon@earth.backplane.com>, audit@FreeBSD.ORG Subject: Re: [PATCH] Re: FreeBSD remote root exploit ? Message-ID: <20010723182204.C17788@sunbay.com> In-Reply-To: <5lr8v7x3bl.fsf@assaris.sics.se>; from assar@sics.se on Mon, Jul 23, 2001 at 02:00:46PM %2B0200 References: <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> <20010722221413.A95414@xor.obsecurity.org> <20010723133609.A88343@sunbay.com> <5lr8v7x3bl.fsf@assaris.sics.se>
next in thread | previous in thread | raw e-mail | index | archive | help
--0F1p//8PRICkK4MW Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Mon, Jul 23, 2001 at 02:00:46PM +0200, Assar Westerlund wrote: > Ruslan Ermilov <ru@FreeBSD.ORG> writes: > > output_datalen() always returns `len', make it `void'? > > Or leave it as it is for symmetry with output_data? > > > How about the attached? It mostly the same, except: > > > > - netflush() now flushes the entire buffer rather than > > callers ensure this. We should probably sleep until > > `net' is ready for output using select(2) but I have > > not found code that would set non-blocking I/O mode > > on the socket. > > There should not be any code in telnetd that set the socket non-blocking. > > > - output_data() uses output_datalen() internally to > > avoid unnecessary duplication of the code. > > Good. > > > + /* Free up enough space if the room is too low*/ > > + if ((len > BUFSIZ ? BUFSIZ : len) > remaining) { > > I don't understand this. Isn't BUFSIZ always going to be larger than > (or equal) than remaining? So just doing 'if (len > remaining)' > woul call netflush() unnecessarily if len > remaining == BUFSIZ ? > > I think it's clearer: > if (len > remaining) > This sucks if (len > BUFSIZ) and buffer is empty (remaining == BUFSIZ)? We would unnecessarily call netflush(). > > @@ -293,25 +295,24 @@ netflush() > > n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ > > } > > } > > - } > > - if (n < 0) { > > - if (errno == EWOULDBLOCK || errno == EINTR) > > - return; > > - cleanup(0); > > - } > > - nbackp += n; > > + if (n == -1 && errno != EWOULDBLOCK && errno != EINTR) { > > + cleanup(0); > > + /* NOTREACHED */ > > + } > > + nbackp += n; > > Is this good? Doesn't it mean that if we get EWOULDBLOCK or EINTR, we > will subtract one from nbackp? > Doh, this is not what was planned, sorry. The last minute bug. An updated patch follows. Cheers, -- Ruslan Ermilov Oracle Developer/DBA, ru@sunbay.com Sunbay Software AG, ru@FreeBSD.org FreeBSD committer, +380.652.512.251 Simferopol, Ukraine http://www.FreeBSD.org The Power To Serve http://www.oracle.com Enabling The Information Age --0F1p//8PRICkK4MW Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=p2 Index: ext.h =================================================================== RCS file: /home/ncvs/src/crypto/telnet/telnetd/ext.h,v retrieving revision 1.2.8.2 diff -u -p -r1.2.8.2 ext.h --- ext.h 2001/07/20 15:16:52 1.2.8.2 +++ ext.h 2001/07/23 15:18:43 @@ -190,7 +190,7 @@ extern void wontoption P((int)); int output_data __P((const char *, ...)) __printflike(1, 2); -int output_datalen __P((const char *, size_t)); +void output_datalen __P((const char *, int)); #ifdef ENCRYPTION extern void (*encrypt_output) P((unsigned char *, int)); Index: slc.c =================================================================== RCS file: /home/ncvs/src/crypto/telnet/telnetd/slc.c,v retrieving revision 1.4.2.1 diff -u -p -r1.4.2.1 slc.c --- slc.c 2001/07/20 15:16:52 1.4.2.1 +++ slc.c 2001/07/23 15:18:54 @@ -176,7 +176,6 @@ end_slc(bufp) register unsigned char **bufp; { register int len; - void netflush(); /* * If a change has occured, store the new terminal control Index: state.c =================================================================== RCS file: /home/ncvs/src/crypto/telnet/telnetd/state.c,v retrieving revision 1.4.2.1 diff -u -p -r1.4.2.1 state.c --- state.c 2001/07/20 15:16:52 1.4.2.1 +++ state.c 2001/07/23 15:19:06 @@ -1615,40 +1615,46 @@ send_status() /* * 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; + int len; + char *buf; va_start(args, format); - 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); - } - ret = vsnprintf(nfrontp, remaining, format, args); - nfrontp += (ret < remaining) ? ret : remaining; + if ((len = vasprintf(&buf, format, args)) == -1) + return -1; + output_datalen(buf, len); va_end(args); - return ret; + free(buf); + return (len); } -int -output_datalen(const char *buf, size_t len) +void +output_datalen(const char *buf, int len) { - size_t remaining; - + int remaining, copied; + remaining = BUFSIZ - (nfrontp - netobuf); - if (remaining < len) { - netflush(); - remaining = BUFSIZ - (nfrontp - netobuf); - if (remaining < len) - return -1; + while (len > 0) { + /* Free up enough space if the room is too low*/ + if ((len > BUFSIZ ? BUFSIZ : len) > remaining) { + netflush(); + remaining = BUFSIZ - (nfrontp - netobuf); + } + + /* Copy out as much as will fit */ + copied = remaining > len ? len : remaining; + memmove(nfrontp, buf, copied); + nfrontp += copied; + len -= copied; + remaining -= copied; + buf += copied; } - memmove(nfrontp, buf, len); - nfrontp += len; - return (len); + return; } Index: telnetd.c =================================================================== RCS file: /home/ncvs/src/crypto/telnet/telnetd/telnetd.c,v retrieving revision 1.11.2.3 diff -u -p -r1.11.2.3 telnetd.c --- telnetd.c 2001/07/20 15:16:52 1.11.2.3 +++ telnetd.c 2001/07/23 15:19:38 @@ -952,7 +952,6 @@ telnet(f, p, host) char *HE; char *HN; char *IM; - void netflush(); int nfd; /* Index: termstat.c =================================================================== RCS file: /home/ncvs/src/crypto/telnet/telnetd/termstat.c,v retrieving revision 1.4.2.2 diff -u -p -r1.4.2.2 termstat.c --- termstat.c 2001/07/20 15:16:52 1.4.2.2 +++ termstat.c 2001/07/23 15:19:43 @@ -140,7 +140,6 @@ int newmap = 1; /* nonzero if \n maps to void localstat() { - void netflush(); int need_will_echo = 0; #if defined(CRAY2) && defined(UNICOS5) @@ -404,7 +403,6 @@ flowstat() clientstat(code, parm1, parm2) register int code, parm1, parm2; { - void netflush(); /* * Get a copy of terminal characteristics. Index: utility.c =================================================================== RCS file: /home/ncvs/src/crypto/telnet/telnetd/utility.c,v retrieving revision 1.5.2.2 diff -u -p -r1.5.2.2 utility.c --- utility.c 2001/07/20 15:16:52 1.5.2.2 +++ utility.c 2001/07/23 15:19:50 @@ -69,10 +69,9 @@ static const char rcsid[] = void ttloop() { - void netflush(); DIAG(TD_REPORT, output_data("td: ttloop\r\n")); - if (nfrontp-nbackp) { + if (nfrontp - nbackp > 0) { netflush(); } ncc = read(net, netibuf, sizeof netibuf); @@ -257,10 +256,13 @@ netflush() int n; extern int not42; - if ((n = nfrontp - nbackp) > 0) { + while ((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; @@ -293,25 +295,26 @@ netflush() n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ } } - } - if (n < 0) { - if (errno == EWOULDBLOCK || errno == EINTR) - return; - cleanup(0); - } - nbackp += n; + if (n == -1) { + if (errno == EWOULDBLOCK || errno == EINTR) + continue; + cleanup(0); + /* NOTREACHED */ + } + nbackp += n; #ifdef ENCRYPTION - if (nbackp > nclearto) - nclearto = 0; + if (nbackp > nclearto) + nclearto = 0; #endif /* ENCRYPTION */ - if (nbackp >= neturg) { - neturg = 0; - } - if (nbackp == nfrontp) { - nbackp = nfrontp = netobuf; + if (nbackp >= neturg) { + neturg = 0; + } + if (nbackp == nfrontp) { + nbackp = nfrontp = netobuf; #ifdef ENCRYPTION - nclearto = 0; + nclearto = 0; #endif /* ENCRYPTION */ + } } return; } /* end of netflush */ --0F1p//8PRICkK4MW-- 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?20010723182204.C17788>