Home page logo
/

bugtraq logo Bugtraq mailing list archives

Re: Linux libc5.4.33 dumbness w/ mk[s]temp()
From: zack () RABI PHYS COLUMBIA EDU (Zack Weinberg)
Date: Mon, 13 Apr 1998 07:29:40 -0400


On Sat, 11 Apr 1998 16:46:56 -0500, Greg Alexander wrote:
       Linux libc5.4.33's mk[s]temp() functions require 6 X's at the end of
a filename (the BSD versions I've seen are a bit more flexible).  This alone
is enough to break any claims to real BSD compatability,

Six X's at the end of the string are required by the Unix98 standard.

but wait, there's
more:
       Only 1 of those 6 X's are really unique.  The rest are simply pid.
So you can create exactly 62 temp files using mk[s]temp() in one pid.  When
using mkstemp(), a EEXIST error is returned, and you get no fd, so you're
unlikely to do anything dumb, so it's just a really annoying DoS.

This bug exists also in glibc 2.0.  It has been fixed in the 2.1
development sources, but the fix is somewhat experimental so it will
not be backported to 2.0.  However, I've appended the change in case
anyone wants to test it.  It can probably be applied to 2.0 with
minimal effort and to libc5 with some work.  It almost certainly won't
work with either as is.

I monitor this list pretty closely for libc-related bugs, but if you
want to be sure they get addressed, please use the 'glibcbug' script
that came with the library to send a formal report.

zw

Index: sysdeps/posix/mkstemp.c
===================================================================
RCS file: /egcs/carton/cvsfiles/libc/sysdeps/posix/mkstemp.c,v
retrieving revision 1.5
retrieving revision 1.7
diff -u -r1.5 -r1.7
--- sysdeps/posix/mkstemp.c     1998/03/10 10:44:45     1.5
+++ sysdeps/posix/mkstemp.c     1998/04/07 12:52:50     1.7
@@ -19,9 +19,11 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <sys/time.h>

 /* Generate a unique temporary file name from TEMPLATE.
    The last six characters of TEMPLATE must be "XXXXXX";
@@ -33,8 +35,11 @@
 {
   static const char letters[]
     = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+  static uint32_t value;
+  struct timeval tv;
+  char *XXXXXX;
   size_t len;
-  size_t i;
+  int count;

   len = strlen (template);
   if (len < 6 || strcmp (&template[len - 6], "XXXXXX"))
@@ -43,20 +48,40 @@
       return -1;
     }

-  if (sprintf (&template[len - 5], "%.5u",
-              (unsigned int) getpid () % 100000) != 5)
-    /* Inconceivable lossage.  */
-    return -1;
+  /* This is where the Xs start.  */
+  XXXXXX = &template[len - 6];

-  for (i = 0; i < sizeof (letters); ++i)
+  /* Get some more or less random data.  */
+  __gettimeofday (&tv, NULL);
+  value += tv.tv_usec | getpid ();
+
+  for (count = 0; count < TMP_MAX; ++count)
     {
+      uint32_t v = value;
       int fd;

-      template[len - 6] = letters[i];
+      /* Fill in the random bits.  */
+      XXXXXX[0] = letters[v % 62];
+      v /= 62;
+      XXXXXX[1] = letters[v % 62];
+      v /= 62;
+      XXXXXX[2] = letters[v % 62];
+      v /= 62;
+      XXXXXX[3] = letters[v % 62];
+      v /= 62;
+      XXXXXX[4] = letters[v % 62];
+      v /= 62;
+      XXXXXX[5] = letters[v % 62];

       fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0600);
       if (fd >= 0)
+       /* The file does not exist.  */
        return fd;
+
+      /* This is a random value.  It is only necessary that the next
+        TMP_MAX values generated by adding 7777 to VALUE are different
+        with (module 2^32).  */
+      value += 7777;
     }

   /* We return the null string if we can't find a unique file name.  */
Index: sysdeps/posix/mktemp.c
===================================================================
RCS file: /egcs/carton/cvsfiles/libc/sysdeps/posix/mktemp.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- sysdeps/posix/mktemp.c      1996/11/06 04:24:39     1.8
+++ sysdeps/posix/mktemp.c      1998/04/07 09:08:11     1.9
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1993, 1996, 1998 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
@@ -16,13 +16,15 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */

+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <unistd.h>
-#include <stdio.h>
-#include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>

 /* Generate a unique temporary file name from TEMPLATE.
    The last six characters of TEMPLATE must be "XXXXXX";
@@ -33,8 +35,11 @@
 {
   static const char letters[]
     = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+  static uint32_t value;
+  struct timeval tv;
+  char *XXXXXX;
   size_t len;
-  size_t i;
+  int count;

   len = strlen (template);
   if (len < 6 || strcmp (&template[len - 6], "XXXXXX"))
@@ -43,20 +48,39 @@
       return NULL;
     }

-  if (sprintf (&template[len - 5], "%.5u",
-              (unsigned int) getpid () % 100000) != 5)
-    /* Inconceivable lossage.  */
-    return NULL;
+  /* This is where the Xs start.  */
+  XXXXXX = &template[len - 6];

-  for (i = 0; i < sizeof (letters); ++i)
+  /* Get some more or less random data.  */
+  __gettimeofday (&tv, NULL);
+  value += tv.tv_usec | getpid ();
+
+  for (count = 0; count < TMP_MAX; ++count)
     {
       struct stat ignored;
+      uint32_t v = value;

-      template[len - 6] = letters[i];
+      /* Fill in the random bits.  */
+      XXXXXX[0] = letters[v % 62];
+      v /= 62;
+      XXXXXX[1] = letters[v % 62];
+      v /= 62;
+      XXXXXX[2] = letters[v % 62];
+      v /= 62;
+      XXXXXX[3] = letters[v % 62];
+      v /= 62;
+      XXXXXX[4] = letters[v % 62];
+      v /= 62;
+      XXXXXX[5] = letters[v % 62];

       if (stat (template, &ignored) < 0 && errno == ENOENT)
        /* The file does not exist.  So return this name.  */
        return template;
+
+      /* This is a random value.  It is only necessary that the next
+        TMP_MAX values generated by adding 7777 to VALUE are different
+        with (module 2^32).  */
+      value += 7777;
     }

   /* We return the null string if we can't find a unique file name.  */



  By Date           By Thread  

Current thread:
[ Nmap | Sec Tools | Mailing Lists | Site News | About/Contact | Advertising | Privacy ]
AlienVault