]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Verify in ttyname() that the symlink is valid.
authorMiklos Szeredi <miklos@szeredi.hu>
Wed, 3 Nov 2010 04:25:45 +0000 (00:25 -0400)
committerAndreas Schwab <schwab@redhat.com>
Wed, 1 Dec 2010 14:35:06 +0000 (15:35 +0100)
(cherry picked from commit 0e516e0e14f2f9783a21cd1727bc53776341f857)

ChangeLog
sysdeps/unix/sysv/linux/ttyname.c
sysdeps/unix/sysv/linux/ttyname_r.c

index 7590fd59214ee10493b5e46e3b31e94f1a79fee9..77cd729ba7709bfe68081187fa1f3401f4a5e3a2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2010-11-03  Ulrich Drepper  <drepper@gmail.com>
+
+       [BZ #12167]
+       * sysdeps/unix/sysv/linux/ttyname.c (ttyname): Recognize new mangling
+       of inacessible symlinks.  Verify result of symlink before returning it.
+       * sysdeps/unix/sysv/linux/ttyname_r.c (__ttyname_r): Likewise.
+       Patch mostly by Miklos Szeredi <miklos@szeredi.hu>.
+
 2010-10-20  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
            Ulrich Drepper  <drepper@gmail.com>
 
index 69af6adc65126c1d0260fc6f68a0a4b59a63282a..6cec3a90130a60288acc5678281178664ab7c4a5 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991,92,93,1996-2002,2006,2009 Free Software Foundation, Inc.
+/* Copyright (C) 1991-1993,1996-2002,2006,2009,2010
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -131,6 +132,9 @@ ttyname (int fd)
   if (__builtin_expect (__tcgetattr (fd, &term) < 0, 0))
     return NULL;
 
+  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
+    return NULL;
+
   /* We try using the /proc filesystem.  */
   *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';
 
@@ -161,13 +165,32 @@ ttyname (int fd)
     {
       if ((size_t) len >= buflen)
        return NULL;
+
+#define UNREACHABLE_LEN strlen ("(unreachable)")
+      if (len > UNREACHABLE_LEN
+         && memcmp (ttyname_buf, "(unreachable)", UNREACHABLE_LEN) == 0)
+       {
+         memmove (ttyname_buf, ttyname_buf + UNREACHABLE_LEN,
+                  len - UNREACHABLE_LEN);
+         len -= UNREACHABLE_LEN;
+       }
+
       /* readlink need not terminate the string.  */
       ttyname_buf[len] = '\0';
-      return ttyname_buf;
-    }
 
-  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
-    return NULL;
+      /* Verify readlink result, fall back on iterating through devices.  */
+      if (ttyname_buf[0] == '/'
+         && __xstat64 (_STAT_VER, ttyname_buf, &st1) == 0
+#ifdef _STATBUF_ST_RDEV
+         && S_ISCHR (st1.st_mode)
+         && st1.st_rdev == st.st_rdev
+#else
+         && st1.st_ino == st.st_ino
+         && st1.st_dev == st.st_dev
+#endif
+         )
+       return ttyname_buf;
+    }
 
   if (__xstat64 (_STAT_VER, "/dev/pts", &st1) == 0 && S_ISDIR (st1.st_mode))
     {
index cef8624dc6920ef6a7babecaf94165591154e2ad..2fa7503471b0c7e04d222967f145045a970f5a8a 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1991,92,93,1995-2001,2003,2006 Free Software Foundation, Inc.
+/* Copyright (C) 1991-1993,1995-2001,2003,2006,2010
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -122,6 +123,9 @@ __ttyname_r (int fd, char *buf, size_t buflen)
   if (__builtin_expect (__tcgetattr (fd, &term) < 0, 0))
     return errno;
 
+  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
+    return errno;
+
   /* We try using the /proc filesystem.  */
   *_fitoa_word (fd, __stpcpy (procname, "/proc/self/fd/"), 10, 0) = '\0';
 
@@ -145,12 +149,30 @@ __ttyname_r (int fd, char *buf, size_t buflen)
 #endif
                        , 1))
     {
+#define UNREACHABLE_LEN strlen ("(unreachable)")
+      if (ret > UNREACHABLE_LEN
+         && memcmp (buf, "(unreachable)", UNREACHABLE_LEN) == 0)
+       {
+         memmove (buf, buf + UNREACHABLE_LEN, ret - UNREACHABLE_LEN);
+         ret -= UNREACHABLE_LEN;
+       }
+
+      /* readlink need not terminate the string.  */
       buf[ret] = '\0';
-      return 0;
-    }
 
-  if (__fxstat64 (_STAT_VER, fd, &st) < 0)
-    return errno;
+      /* Verify readlink result, fall back on iterating through devices.  */
+      if (buf[0] == '/'
+         && __xstat64 (_STAT_VER, buf, &st1) == 0
+#ifdef _STATBUF_ST_RDEV
+         && S_ISCHR (st1.st_mode)
+         && st1.st_rdev == st.st_rdev
+#else
+         && st1.st_ino == st.st_ino
+         && st1.st_dev == st.st_dev
+#endif
+         )
+       return 0;
+    }
 
   /* Prepare the result buffer.  */
   memcpy (buf, "/dev/pts/", sizeof ("/dev/pts/"));