Blame SOURCES/glibc-fedora-linux-tcsetattr.patch

0b26f7
Short description: Fedora-specific workaround for kernel pty bug.
0b26f7
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
0b26f7
Origin: PATCH
0b26f7
Upstream status: not-submitted
0b26f7
0b26f7
This is a Fedora-specific workaround for a kernel bug where calling
0b26f7
ioctl on a pty will silently ignore the invalid c_cflag. The
0b26f7
workaround is to use TCGETS to verify the setting matches. This is
0b26f7
not upstream and needs to either be removed or submitted upstream
0b26f7
after analysis.
0b26f7
0b26f7
Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
0b26f7
===================================================================
0b26f7
--- a/sysdeps/unix/sysv/linux/tcsetattr.c
0b26f7
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c
0b26f7
@@ -45,6 +45,7 @@ __tcsetattr (int fd, int optional_action
0b26f7
 {
0b26f7
   struct __kernel_termios k_termios;
0b26f7
   unsigned long int cmd;
0b26f7
+  int retval;
0b26f7
 
0b26f7
   switch (optional_actions)
0b26f7
     {
0b26f7
@@ -75,7 +76,36 @@ __tcsetattr (int fd, int optional_action
0b26f7
   memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0],
0b26f7
 	  __KERNEL_NCCS * sizeof (cc_t));
0b26f7
 
0b26f7
-  return INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios);
0b26f7
+  retval = INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios);
0b26f7
+
0b26f7
+  if (retval == 0 && cmd == TCSETS)
0b26f7
+    {
0b26f7
+      /* The Linux kernel has a bug which silently ignore the invalid
0b26f7
+        c_cflag on pty. We have to check it here. */
0b26f7
+      int save = errno;
0b26f7
+      retval = INLINE_SYSCALL (ioctl, 3, fd, TCGETS, &k_termios);
0b26f7
+      if (retval)
0b26f7
+       {
0b26f7
+         /* We cannot verify if the setting is ok. We don't return
0b26f7
+            an error (?). */
0b26f7
+         __set_errno (save);
0b26f7
+         retval = 0;
0b26f7
+       }
0b26f7
+      else if ((termios_p->c_cflag & (PARENB | CREAD))
0b26f7
+              != (k_termios.c_cflag & (PARENB | CREAD))
0b26f7
+              || ((termios_p->c_cflag & CSIZE)
0b26f7
+                  && ((termios_p->c_cflag & CSIZE)
0b26f7
+                      != (k_termios.c_cflag & CSIZE))))
0b26f7
+       {
0b26f7
+         /* It looks like the Linux kernel silently changed the
0b26f7
+            PARENB/CREAD/CSIZE bits in c_cflag. Report it as an
0b26f7
+            error. */
0b26f7
+         __set_errno (EINVAL);
0b26f7
+         retval = -1;
0b26f7
+       }
0b26f7
+    }
0b26f7
+
0b26f7
+  return retval;
0b26f7
 }
0b26f7
 weak_alias (__tcsetattr, tcsetattr)
0b26f7
 libc_hidden_def (tcsetattr)