Bug 177965 - tcgetattr stores uninitialized values when E_NOTTY
Summary: tcgetattr stores uninitialized values when E_NOTTY
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: glibc
Version: 5
Hardware: i386
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Brian Brock
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2006-01-16 21:46 UTC by John Reiser
Modified: 2007-11-30 22:11 UTC (History)
1 user (show)

Fixed In Version: 2.4.90-7
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2006-05-12 09:03:08 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)

Description John Reiser 2006-01-16 21:46:50 UTC
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):
glibc-2.3.90-29

How reproducible:
Always

Steps to Reproduce:
1. Run internal testcase stdio-common/scanf4 and observe when __isatty() checks on a filedescriptor for /dev/null.
2.
3.
  

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 14:37:13 UTC
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 16:19:15 UTC
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 19:24:57 UTC
I changed the code upstream.

Comment 4 Jakub Jelinek 2006-05-12 09:03:08 UTC
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.