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