Bug 6488 - telnet client sometimes prints garbage due to missing byte from the telnet data stream
Summary: telnet client sometimes prints garbage due to missing byte from the telnet da...
Status: RESOLVED FIXED
Alias: None
Product: Busybox
Classification: Unclassified
Component: Networking (show other bugs)
Version: unspecified
Hardware: All Linux
: P5 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-09-16 23:32 UTC by Corey Ashford
Modified: 2017-10-05 15:44 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Corey Ashford 2013-09-16 23:32:54 UTC
We recently ran into a problem where busybox, on an embedded system, was displaying a Chinese character in the place of the "l" in "login".

After much tracing and debugging, we determined that what was happening is that the telnet client appears to be behaving properly if we look at the data coming in from the read() call, but that data is missing the Telnet protocol IAC (255) byte that should tell the client that the following byte is a control code.

This doesn't happen every time, but about one in three times.  Here's a copy/paste from my screen:

% sudo /usr/sbin/in.telnetd -h -debug 10016 &
% ./telnet localhost 10016

Entering character mode
Escape character is '^]'.

�cjashfor-w510 login: 

You can see the extra character in this example preceding the "cjashfor".

After we ran into this problem, we suspected a number of things, including the telnet daemon, but the telnet daemon from the standard telnet package on Fedora never encounters this error.

After doing some stracing, and tcpdump'ing, we discovered that in both cases, using the standard telnet and the busybox telnet, tcpdump was showing the escape code in the telnet datastream, but in the case of busybox telnet, the read() call sometimes doesn't return that byte, and only sends the byte following the escape code, a 242 (decimal) byte, which is a Telnet Data Mark command (see RFC 854).  Because there is no escape code received, this byte is treated as a printable character by the telnet daemon, and printed to the screen.

In the case of the standard telnet, it doesn't used read(), and instead uses recv(), and for whatever reason never misses this byte.

As a result, I am not certain that there is a bug in telnet or in the stack somewhere between the read() call and the TCP/IP socket.  Or perhaps there's an error in the busybox telnet daemon that it isn't properly conditioning the socket to receive every byte. 

Note that our original problem was on an embedded system using a PowerPC processor and 2.6.32-ish kernel, but I have replicated this problem in Fedora 18 using a 3.10 kernel on x86_64.  So the error is quite easy to reproduce.
Comment 1 Corey Ashford 2013-09-16 23:34:33 UTC
I want to also note that I reproduced the problem using a busybox built today from the the master branch of the git tree.
Comment 2 Corey Ashford 2013-09-16 23:36:35 UTC
Sorry, one more correction:  I said this, "Or perhaps there's an
error in the busybox telnet daemon that it isn't properly conditioning the
socket to receive every byte."

but I meant to type this:

"Or perhaps there's an
error in the busybox telnet *client* that it isn't properly conditioning the
socket to receive every byte."
Comment 3 Corey Ashford 2013-09-17 00:01:27 UTC
Ok, I found several more errors in my report.  Please allow me to re-phrase it:

...
You can see the extra character in this example preceding the "cjashfor".

After we ran into this problem, we suspected a number of things, including the
telnet daemon, but the telnet client from the standard telnet package on Fedora
never encounters this error.

After doing some stracing, and tcpdump'ing, we discovered that in both cases,
using the standard telnet client and the busybox telnet client, tcpdump was showing the IAC code in the telnet datastream, but in the case of busybox telnet, the read() call sometimes doesn't return that byte, and only reads the byte following the IAC, a 242 (decimal) byte, which is a Telnet Data Mark command (see RFC 854).  Because there is no IAC received, this byte is
treated by the telnet client as a printable character, and is printed to
the screen.

In the case of the standard telnet client, it doesn't use read(); instead it
uses recv(), and for whatever reason it never misses this IAC byte.

As a result, I am not certain that there is a bug in the telnet client or in
the stack somewhere between the read() call and the TCP/IP socket.  Perhaps
there's an error in the busybox telnet client that it isn't properly
conditioning the socket to receive every byte. 

Note that our original problem was on an embedded system using a PowerPC
processor and 2.6.32-ish kernel, but I have replicated this problem in Fedora
18 using a 3.10 kernel on x86_64.  So the error is quite easy to reproduce.
Comment 4 Denys Vlasenko 2017-10-05 15:44:51 UTC
There were some fixes for IACs n 2016, hopefully fixing problems in this report as well.