Bug 177965 - tcgetattr stores uninitialized values when E_NOTTY
tcgetattr stores uninitialized values when E_NOTTY
Product: Fedora
Classification: Fedora
Component: glibc (Show other bugs)
i386 Linux
medium Severity medium
: ---
: ---
Assigned To: Jakub Jelinek
Brian Brock
Depends On:
  Show dependency treegraph
Reported: 2006-01-16 16:46 EST by John Reiser
Modified: 2007-11-30 17:11 EST (History)
1 user (show)

See Also:
Fixed In Version: 2.4.90-7
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2006-05-12 05:03:08 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

  None (edit)
Description John Reiser 2006-01-16 16:46:50 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):

How reproducible:

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.)

Additional info:

-----sysdeps/unix/sysv/linux/tcgetattr.c line 34
__tcgetattr (fd, termios_p)
      int fd;
      struct termios *termios_p;
  struct __kernel_termios k_termios;
  int retval;

  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;
Comment 1 Jakub Jelinek 2006-01-17 09:37:13 EST
Why is that a problem?  To my knowledge the content of the struct pointed by
the termios_p argument is undefined after failed call.
Comment 2 John Reiser 2006-01-17 11:19:15 EST
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
unexpected situations.
Comment 3 Ulrich Drepper 2006-05-10 15:24:57 EDT
I changed the code upstream.
Comment 4 Jakub Jelinek 2006-05-12 05:03:08 EDT
Should be fixed in glibc-2.4.90-7 in rawhide.

Note You need to log in before you can comment on or make changes to this bug.