[PATCH v8 06/15] linux/termios: clear padding bytes in struct termios

H. Peter Anvin hpa@zytor.com
Tue Jun 10 19:02:17 GMT 2025


There is a 3-byte padding field (1 byte on m68k) in struct termios due
to NCCS being set to 32 and there being one more byte-sized variable
next to it (c_line).

Make sure these padding bytes are zero by explicitly setting the
structure to zero before populating it in tcgetattr() and
__old_tcsetattr(). This may make future extensions easier, plus, it is
bad practice to leave bytes uninitialized by an ABI.

This patch leaves the actual field implicit, because of it having
different size on m68k and others; m68k having a standard ABI
alignment of only 2 bytes; this seems simpler than having to do
something different on m68k -- especially if someone decides to build
an m68k distribution with natural alignment enabled (-malign-int.)

Even so, there is at least one byte on every architecture, which could
be pressed into service in the future, e.g. as a flag field or to
provide positive identification of a future extended termios format.

Moral of the story: when designing a structure for an ABI, make sure
all your members are naturally aligned without implict
padding. However, fixing this would require adding m68k to the set of
architectures which require a new struct termios, and that does not
seem like a worthwhile engineering tradeoff at this time.

Thanks to Adhemerval Zanella Netto for catching the m68k issue.

Signed-off-by: "H. Peter Anvin" (Intel) <hpa@zytor.com>
---
 sysdeps/unix/sysv/linux/tcgetattr.c | 1 +
 sysdeps/unix/sysv/linux/tcsetattr.c | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/tcgetattr.c b/sysdeps/unix/sysv/linux/tcgetattr.c
index dbeae739cc31..7eed18b74b7d 100644
--- a/sysdeps/unix/sysv/linux/tcgetattr.c
+++ b/sysdeps/unix/sysv/linux/tcgetattr.c
@@ -28,6 +28,7 @@ __tcgetattr (int fd, struct termios *termios_p)
     {
       ___termios2_canonicalize_speeds (&k_termios);
 
+      memset (termios_p, 0, sizeof (*termios_p));
       termios_p->c_iflag  = k_termios.c_iflag;
       termios_p->c_oflag  = k_termios.c_oflag;
       termios_p->c_cflag  = k_termios.c_cflag;
diff --git a/sysdeps/unix/sysv/linux/tcsetattr.c b/sysdeps/unix/sysv/linux/tcsetattr.c
index 7ec53e41937f..ae4361a22bd3 100644
--- a/sysdeps/unix/sysv/linux/tcsetattr.c
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c
@@ -88,13 +88,13 @@ attribute_compat_text_section
 __old_tcsetattr (int fd, int optional_actions, const old_termios_t *termios_p)
 {
   struct termios new_termios;
+
+  memset (&new_termios, 0, sizeof (new_termios));
   new_termios.c_iflag  = termios_p->c_iflag;
   new_termios.c_oflag  = termios_p->c_oflag;
   new_termios.c_cflag  = termios_p->c_cflag;
   new_termios.c_lflag  = termios_p->c_lflag;
   new_termios.c_line   = termios_p->c_line;
-  new_termios.c_ispeed = 0;
-  new_termios.c_ospeed = 0;
   copy_c_cc(new_termios.c_cc, NCCS, termios_p->c_cc, OLD_NCCS);
 
   return __tcsetattr (fd, optional_actions, &new_termios);
-- 
2.49.0



More information about the Libc-alpha mailing list