[PATCH v2 1/3] linux/termios: clear k_termios.c_cflag & CIBAUD for non-split speed [BZ 33340]

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Wed Sep 17 13:04:20 GMT 2025



On 10/09/25 18:36, H. Peter Anvin wrote:
> After getting more experience with the various broken direct-to-ioctl
> termios2 hacks using Fedora 43 beta, I have found a fair number of
> cases where the software would fail to set, or clear CIBAUD for
> non-split-speed operation.
> 
> Thus it seems will help improve compatibility to clear the kernel-side
> version of c_cflag & CIBAUD (having the same meaning to the Linux
> kernel as the speed 0 has for cfsetibaud(), i.e. force the input speed
> to equal the output speed) for non-split-speed operation, rather than
> having it explicitly equal the output speed in CBAUD.
> 
> When writing the code that went into glibc 2.42 I had considered this
> issue, and had to make an educated guess which way would be more
> likely to break fewer things.  Unfortunately, it appears I guessed
> wrong.
> 
> A third option would be to *always* set CIBAUD to __BOTHER, even for
> the standard baud rates.  However, that is an even bigger departure
> from legacy behavior, whereas this variant mostly preserves current
> behavior in terms of under what conditions buggy utilities will
> continue to work.
> 
> This change is in tcsetattr() rather than
> ___termios2_canonicalize_speeds(), as it should not be run for
> tcgetattr(); that would break split speed support for the legacy
> interface versions of cfgetispeed() and cfsetispeed().
> 
> [ v2: fixed comment style ]
> 
> Resolves: BZ #33340
> Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>


LGTM, but did we hear back from BZ 33340 that it actually fixes the reported
issues?

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
>  sysdeps/unix/sysv/linux/tcsetattr.c | 35 +++++++++++++++--------------
>  1 file changed, 18 insertions(+), 17 deletions(-)
> 
> diff --git a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcsetattr.c
> index 4f07a03e6657..cf12e15169e3 100644
> --- a/sysdeps/unix/sysv/linux/tcsetattr.c
> +++ b/sysdeps/unix/sysv/linux/tcsetattr.c
> @@ -41,16 +41,6 @@ __tcsetattr (int fd, int optional_actions, const struct termios *termios_p)
>  
>    copy_c_cc (k_termios.c_cc, _TERMIOS2_NCCS, termios_p->c_cc, NCCS);
>  
> -  /*
> -   * Choose the proper ioctl number to invoke.
> -   *
> -   * Alpha got TCSETS2 late (Linux 4.20), but has the same structure
> -   * format, and it only needs TCSETS2 if either it needs to use
> -   * __BOTHER or split speed.  All other architectures have TCSETS2 as
> -   * far back as the current glibc supports.  Calling TCSETS with
> -   * __BOTHER causes unpredictable results on old Alpha kernels and
> -   * could even crash them.
> -   */
>    static_assert_equal(TCSADRAIN, TCSANOW + 1);
>    static_assert_equal(TCSAFLUSH, TCSANOW + 2);
>    static_assert_equal(TCSETSW2,  TCSETS2 + 1);
> @@ -62,17 +52,28 @@ __tcsetattr (int fd, int optional_actions, const struct termios *termios_p)
>    if (cmd > 2)
>      return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
>  
> +  /* For compatibility with broken workaround hacks for the lack
> +     of arbitrary speed support in previous versions of glibc,
> +     clear CIBAUD if only one speed is used.
> +
> +     This is also necessary for the Alpha compatibility hack below. */
> +  if (k_termios.c_ospeed == k_termios.c_ispeed)
> +    k_termios.c_cflag &= ~CIBAUD;
> +
> +  /* Choose the proper ioctl number to invoke.
> +
> +     Alpha got TCSETS2 late (Linux 4.20), but has the same structure
> +     format, and it only needs TCSETS2 if either it needs to use
> +     __BOTHER or split speed.  All other architectures have TCSETS2 as
> +     far back as the current glibc supports.  Calling TCSETS with
> +     __BOTHER causes unpredictable results on old Alpha kernels and
> +     could even crash them. */
>    if (__ASSUME_TERMIOS2 ||
>        k_termios.c_ospeed != k_termios.c_ispeed ||
>        cbaud (k_termios.c_cflag) == __BOTHER)
> -    {
> -      cmd += TCSETS2;
> -    }
> +    cmd += TCSETS2;
>    else
> -    {
> -      cmd += TCSETS;
> -      k_termios.c_cflag &= ~CIBAUD;
> -    }
> +    cmd += TCSETS;
>  
>    return INLINE_SYSCALL_CALL (ioctl, fd, cmd, &k_termios);
>  }



More information about the Libc-alpha mailing list