[comp.sys.hp] Beware of serial port programs run by users

garvey@cmic.UUCP (Joe Garvey) (02/03/90)

I was doing a little program to read/write from a serial interface on my
HP 9000/370 running HP-UX 6.5. To my dismay, a small little software bug
screwed the interface to a fair-thee-well. This program can be run by any
user with access to the port. There should *not* be a getty running on this
port, and a getty running on the other ports. It does not seem to affect the
internal serial port (other than to give it a temporarily ridiculous set of
settings).

The response center considers this a feature. I consider it a bug. You decide
for yourself.

I call this program wedge.c... because of the effect it has. Consider yourself
warned. After all forwarned is forarmed (four armed might actually be better
:-) ).

-------------------------- cut here ------------------------------------------
/*
 * This little demo program will cause a 4-port mux in a series 300 computer
 * to permenantly go out to lunch. In fact, in my case I used it on port 2
 * and ports 0, 1, and 2 ceased to function. (You could see the getty issue
 * a prompt, but could not respond.) /dev/tty13.2 has no getty running on it.
 *
 * The only way out of this is to reset (turn the power off) the computer!!!
 * Any user can do this. Take heed a protect your serial ports accordingly.
 *
 * Modification History:
 * Joe Garvey, Jan 1990: Created to show HP what happened when I made a simple
 *    mistake.
 *
 */

#include <stdio.h>
#include <termio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

static int RAU_fd;                            /* file descriptor for RAU line */

main ()

{

/***** Definitions *****/

struct termio RAU_Line_Settings;


/***** Code *****/

if ((RAU_fd = open("/dev/tty13.2", O_RDWR)) < 0)
   {
   fprintf(stderr, "%s: ", "wedge");
   fprintf(stderr, "Couldn't open RAU line \"%s\"\n", "/dev/tty13.2");
   exit(1);
   }

RAU_Line_Settings.c_iflag = IGNBRK | PARMRK | INPCK | IXANY;
RAU_Line_Settings.c_oflag = ONOCR;

                     /* use of CSTOP instead of CSTOPB screws a 4-port mux up */
                     /* even the ports you're not using!!!                    */
/* right */
RAU_Line_Settings.c_cflag = B2400 | CSTOPB | CREAD | CS8 | PARENB | PARODD
                                                                        | HUPCL;
*/
/* wrong */
RAU_Line_Settings.c_cflag = B2400 | CSTOP | CREAD | CS8 | PARENB | PARODD
                                                                        | HUPCL;
RAU_Line_Settings.c_lflag = 0;
RAU_Line_Settings.c_line = 0;
RAU_Line_Settings.c_cc[VTIME] = 1;
RAU_Line_Settings.c_cc[VMIN] = 0;

if (ioctl(RAU_fd, TCSETA, &RAU_Line_Settings) < 0)
   {
   fprintf(stderr, "%s: ", "wedge");
   fprintf(stderr, "Couldn't configure RAU line\n");
   exit(1);
   }

sleep(1000);        /* use this delay to check settings of line using stty(1) */
                    /* stty -a < /dev/tty13.2                                 */

return;

}

-------------------------- cut here, too -------------------------------------


Joe Garvey                       UUCP: {apple,backbone}!versatc!mips!cmic!garvey
California Microwave             Internet: garvey%cmic@mips.com
990 Almanor Ave                  HP Desk: xxx ("mips!cmic!garvey")/hp1900/ux
Sunnyvale, Ca, 94086             800-831-3104 (outside CA)
408-720-6439 (let it ring)       800-824-7814 (inside CA)

rer@hpfcdc.HP.COM (Rob Robason) (02/06/90)

> The response center considers this a feature.  I consider it a bug.  You
> decide for yourself.
> /* use of CSTOP instead of CSTOPB screws a 4-port mux up */
> /* even the ports you're not using!!!                    */
> /* right */
> RAU_Line_Settings.c_cflag = B2400 | CSTOPB | CREAD | CS8 | PARENB | PARODD
> /* wrong */
> RAU_Line_Settings.c_cflag = B2400 | CSTOP | CREAD | CS8 | PARENB | PARODD

CSTOP is a flow control character definition (^S, get it:  Cntl-STOP)
and part of a set of predefined default characters in <termio.h>.  It
has nothing to do with CSTOPB which is a Control operation to set the
number of STOP Bits on characters transmitted, totally unrelated to flow
control.  In the example you cited above, you obviously made a
typographical error and should not expect the application to work.

Just out of curiosity, and for fun, I tried to disect what you were
REALLY doing, from definitions in termio.h:

/* default control chars */
#  define	CSTOP	023	/* cntl s */

/* Control Modes */
#  define CSTOPB	0000200		/* Send two stop bits, else one */

/* Baud Rate Values */
#  define _CBAUD	0000037
#  define B0		0 		/* Hang up */
#  define B50		0000001		/* 50 baud */
#  define B75		0000002		/* 75 baud */
[middle of sequential list deleted...]
#  define B38400	0000022		/* 38400 baud */

I note that the 023 value you're tring to impose as a command is, in
fact, within the masked value of speed control values but is not even a
currently defined speed.  I would expect such use to result in
unpredictable behavior.  You are telling the interface to do something
we haven't defined.  One could argue that some sort of error checking
could be invoked.  Such error checking would be costly in terms of
performance, and would certainly not be consistent with the typical
low-level expectations of ioctl() operations.  While we take
responsibility for our defects, we can't fix the UNIX* out of UNIX.

This is one of those elusive bugs like I see so often with programs that
get lost in malloc()/free() operations:  it is definitely a coding
defect and could have resulted from hundreds of potential typos.

*UNIX is a trademark of AT&T in the U.S.A.  and in other countries.

Rob "blame the inventor" Robason

rer@hpfcdc.HP.COM (Rob Robason) (02/07/90)

> Such error checking would be costly in terms of
> performance, and would certainly not be consistent with the typical
> low-level expectations of ioctl() operations.

Sorry, I meant to say "inconsistent", not "consistent".  Kind of takes
the umph out of my point.  Boy, I wish notes had some sort of error
checking so it could understand what I MEANT to say :-).

Rob "Irony is my middle name" Robason

perry@hpfcdc.HP.COM (Perry Scott) (02/10/90)

Rob explains the externals pretty well.  I've worked with the MUX
firmware, so I can guess what really happens to your MUX.


from /usr/include/sys/termio.h:

#  define       CSTOP   023     /* cntl s */
#  define _CBAUD        0000037
#  define B2400         0000014         /* 2400 baud */
#  define B38400        0000022         /* 38400 baud */

> RAU_Line_Settings.c_cflag = B2400 | CSTOP | CREAD | CS8 | PARENB | PARODD

This sends (023|014 = 037), which is still a baud rate, and gives it to
the MUX.  The MUX firmware uses this as an index into a table of values
which it uses to poke its SIO.  Apparently, the SIO gets poked with
something that is not-your-usual-baudrate, depending on the whim of the
Zilog link editor.

The problem is exacerbated by an old firmware bug that uses only one
configuration byte instead of four.  This causes all the ports to be set
to the never-never-land baud rate, in addition to the victim's.  I'll
bet the EPROM on the MUX says 98642-90001.  If so, there is a (free?)
upgrade to the latest revision.

So, I have to agree with the Response Center that you are using an
"unsupported" baud rate. :-)  Nasty typo you have there.

Perry Scott