[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#729746: MAXLOGNAME increased (17 -> 32)



On 25/11/2013 14:56, Petr Salinger wrote:
> The getlogin_r is not thread safe, as it uses the same buffer as getlogin.

This should fix it, I think. It still updates the buffer (for the sake
of getlogin) but doesn't rely on it.

Also, I think the ERANGE check can be removed when we drop support for
pre-9.2.

-- 
Robert Millan
Index: getlogin_r.c
===================================================================
--- getlogin_r.c	(revision 5163)
+++ getlogin_r.c	(working copy)
@@ -25,11 +25,9 @@
 #include <sys/param.h>
 #include <sysdep.h>
 
-/* Cache the system call's return value.  */
-char *__getlogin_cache;
-/* The kernel never returns more than MAXLOGNAME bytes, therefore we don't
-   need more than that either.  */
-char __getlogin_cache_room[MAXLOGNAME];
+/* Defined in getlogin.c.  */
+extern char *__getlogin_cache;
+extern char __getlogin_cache_room[MAXLOGNAME];
 
 extern int __syscall_getlogin (char *__name, size_t __name_len);
 libc_hidden_proto (__syscall_getlogin)
@@ -45,20 +43,28 @@
 {
   size_t len;
 
-  if (__getlogin_cache == NULL)
-    {
-      if (INLINE_SYSCALL (getlogin, 2, __getlogin_cache_room, MAXLOGNAME) < 0)
+      if (INLINE_SYSCALL (getlogin, 2, name, name_len) < 0)
 	return errno;
       /* The system call should return a NULL terminated name.  */
-      if (__memchr (__getlogin_cache_room, '\0', MAXLOGNAME) == NULL)
+      if (__memchr (name, '\0', name_len) == NULL)
 	abort ();
-      __getlogin_cache = __getlogin_cache_room;
-    }
 
-  len = strlen (__getlogin_cache);
+  len = strlen (name);
+
+  /* FIXME: recent kernels (r243021) already check this (and set ERANGE). */
   if (__builtin_expect (len < name_len, 1))
     {
-      memcpy (name, __getlogin_cache, len + 1);
+      /* We update the cache only for the sake of getlogin.c.  We can't use it
+	 ourselves since it would break thread-safety. */
+
+      /* Upstream has increased MAXLOGNAME in the kernel before (r243023).
+	 Be safe rather than sorry. */
+      if (len + 1 <= sizeof (__getlogin_cache_room))
+	{
+	  /* Not thread-safe, but the only consumer (getlogin.c) doesn't care. */
+	  memcpy (__getlogin_cache, name, len + 1);
+	  __getlogin_cache = __getlogin_cache_room;
+	}
       return 0;
     }
   else
Index: getlogin.c
===================================================================
--- getlogin.c	(revision 5151)
+++ getlogin.c	(working copy)
@@ -24,9 +24,11 @@
 #include <sys/param.h>
 #include <sysdep.h>
 
-/* Defined in getlogin_r.c.  */
-extern char *__getlogin_cache;
-extern char __getlogin_cache_room[MAXLOGNAME];
+/* Cache the system call's return value.  */
+char *__getlogin_cache;
+/* The kernel never returns more than MAXLOGNAME bytes, therefore we don't
+   need more than that either.  */
+char __getlogin_cache_room[MAXLOGNAME];
 
 extern int __syscall_getlogin (char *__name, size_t __name_len);
 libc_hidden_proto (__syscall_getlogin)

Reply to: