Red Hat Bugzilla – Bug 177965
tcgetattr stores uninitialized values when E_NOTTY
Last modified: 2007-11-30 17:11:21 EST
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.12) Gecko/20050922 Fedora/1.0.7-1.1.fc4 Firefox/1.0.7
Description of problem:
When the filedescriptor first argument to tcgetattr() is not a tty, then tcgetattr stores uninitialized values into the structure pointed to by the second argument.
Version-Release number of selected component (if applicable):
Steps to Reproduce:
1. Run internal testcase stdio-common/scanf4 and observe when __isatty() checks on a filedescriptor for /dev/null.
Actual Results: Uninitialized values from the local stack frame of __tcgetattr are copied to *termios_p.
Expected Results: Do not store uninitialized values into *termios_p. Either don't store into *termios_p when the ioctl fails, or clear the local k_termios struct before making the call (so that the values will be initialized in case the ioctl() fails.)
-----sysdeps/unix/sysv/linux/tcgetattr.c line 34
__tcgetattr (fd, termios_p)
struct termios *termios_p;
struct __kernel_termios k_termios;
retval = INLINE_SYSCALL (ioctl, 3, fd, TCGETS, &k_termios);
termios_p->c_iflag = k_termios.c_iflag; /* <<<<< here, and following */
termios_p->c_oflag = k_termios.c_oflag;
termios_p->c_cflag = k_termios.c_cflag;
termios_p->c_lflag = k_termios.c_lflag;
termios_p->c_line = k_termios.c_line;
Why is that a problem? To my knowledge the content of the struct pointed by
the termios_p argument is undefined after failed call.
It is a problem because tcgetattr itself is introducing more undefinedness than
is already given by the OS kernel. Namely, the returned values are pieces of
the uninitialized local stack frame of tcgetattr, not the values (whether
defined or undefined) left by the kernel.
Although it is a good idea for the kernel to avoid storing anything if the
system call fails, for tcgetattr I cannot find a specification that requires
this. Also, the manual page for tcgetattr does not say that the structure is
"output only." So the kernel could read some of the members before deciding to
return an error, then write some subset of the members, leaving other members
with original user-mode values. The current tcgetattr fails if *termios_p is
not output only.
In order to guarantee that tcgetattr does not introduce any new undefinedness,
then tcgetattr must first copy in the values from *termios_p to k_termios,
perform the system call, then copy out the values from k_termios to *termios_p.
If a specification were to rquire that *termios_p be output only, then tcgetattr
still should minimize the introduction of new undefinedness. This helps glibc
clients that are trying to be robust in the face of runtime errors, and improves
maintainability and supportability, by reducing the uncontrolled fanout from
I changed the code upstream.
Should be fixed in glibc-2.4.90-7 in rawhide.