forked from rpms/glibc
0e17ea22c1
The following commit removes the requirement for patches to be placed in 1000, 2000, or 3000 ID blocks depending on their upstream status. Instead upstream status is documented in the header of the patch with some semi-standard notation as described in template.patch. The patches are re-numbered and defined and applied in the same order. Verified that before and after the patch that the source tree does not change. The patch definition is resorted to match the patch application order.
62 lines
2.1 KiB
Diff
62 lines
2.1 KiB
Diff
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)
|