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