Based on: http://www.uclibc.org/cgi-bin/viewcvs.cgi/trunk/uClibc/libc/misc/\ internals/tempname.c?rev=8887&r1=5747&r2=8887 Use /dev/urandom exclusively with __gen_tempname(), for the mktemp/tmpnam family, instead of hp-timing, gettimeofday(), or getpid(). diff -Naur glibc-2.8-20080929.orig/sysdeps/posix/tempname.c glibc-2.8-20080929/sysdeps/posix/tempname.c --- glibc-2.8-20080929.orig/sysdeps/posix/tempname.c 2008-03-30 03:30:25.000000000 +0000 +++ glibc-2.8-20080929/sysdeps/posix/tempname.c 2008-10-15 20:24:16.000000000 +0000 @@ -51,10 +51,6 @@ # include #endif -#if HAVE_SYS_TIME_H || _LIBC -# include -#endif - #if HAVE_STDINT_H || _LIBC # include #endif @@ -93,11 +89,11 @@ # define struct_stat64 struct stat64 #else # define struct_stat64 struct stat -# define __getpid getpid -# define __gettimeofday gettimeofday # define __mkdir mkdir # define __open open # define __open64 open +# define __close close +# define __read read # define __lxstat64(version, path, buf) lstat (path, buf) # define __xstat64(version, path, buf) stat (path, buf) #endif @@ -106,25 +102,6 @@ # define __secure_getenv getenv #endif -#ifdef _LIBC -# include -# if HP_TIMING_AVAIL -# define RANDOM_BITS(Var) \ - if (__builtin_expect (value == UINT64_C (0), 0)) \ - { \ - /* If this is the first time this function is used initialize \ - the variable we accumulate the value in to some somewhat \ - random value. If we'd not do this programs at startup time \ - might have a reduced set of possible names, at least on slow \ - machines. */ \ - struct timeval tv; \ - __gettimeofday (&tv, NULL); \ - value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ - } \ - HP_TIMING_NOW (Var) -# endif -#endif - /* Use the widest available unsigned type if uint64_t is not available. The algorithm below extracts a number less than 62**6 (approximately 2**35.725) from uint64_t, so ancient hosts where @@ -209,6 +186,19 @@ static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; +static unsigned int fillrand(unsigned char *buf, unsigned int len) +{ + int fd; + unsigned int result = -1; + fd = __open("/dev/urandom", O_RDONLY); + if (fd >= 0) + { + result = __read(fd, buf, len); + __close(fd); + } + return result; +} + /* Generate a temporary file name based on TMPL. TMPL must match the rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed does not exist at the time of the call to __gen_tempname. TMPL is @@ -220,19 +210,19 @@ __GT_FILE: create the file using open(O_CREAT|O_EXCL) and return a read-write fd. The file is mode 0600. __GT_DIR: create a directory, which will be mode 0700. - - We use a clever algorithm to get hard-to-predict names. */ +*/ int __gen_tempname (char *tmpl, int flags, int kind) { - int len; + int len, i; char *XXXXXX; static uint64_t value; - uint64_t random_time_bits; unsigned int count; int fd = -1; int save_errno = errno; struct_stat64 st; + unsigned char randomness[6]; + unsigned int k; /* A lower bound on the number of temporary files to attempt to generate. The maximum total number of temporary file names that @@ -260,39 +250,19 @@ /* This is where the Xs start. */ XXXXXX = &tmpl[len - 6]; - /* Get some more or less random data. */ -#ifdef RANDOM_BITS - RANDOM_BITS (random_time_bits); -#else -# if HAVE_GETTIMEOFDAY || _LIBC - { - struct timeval tv; - __gettimeofday (&tv, NULL); - random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; - } -# else - random_time_bits = time (NULL); -# endif -#endif - value += random_time_bits ^ __getpid (); + /* Get some random data. */ + if (fillrand(randomness, sizeof(randomness)) != sizeof(randomness)) + { + goto all_done; + } + for (i = 0 ; i < sizeof(randomness) ; i++) + { + k = ((randomness[i]) % 62); + XXXXXX[i] = letters[k]; + } for (count = 0; count < attempts; value += 7777, ++count) { - uint64_t v = value; - - /* 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]; - switch (kind) { case __GT_FILE: @@ -337,6 +307,7 @@ } /* We got out of the loop because we ran out of combinations to try. */ +all_done: __set_errno (EEXIST); return -1; }