summaryrefslogtreecommitdiff
path: root/lib/tempname.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2020-09-09 23:59:18 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2020-09-10 00:03:04 -0700
commit44358d4d165bcc96ceacb2c7e903053b87ab339c (patch)
tree9293c88386ec23c9d472d4a9d8ce029e656f6d68 /lib/tempname.c
parent976b5cb15ef4972c3700f1b151fddd4a4c6eb3ba (diff)
downloadgnulib-44358d4d165bcc96ceacb2c7e903053b87ab339c.tar.gz
tempname: help merge with glibc
Inspired by draft patches by Adhemerval Zanella in: https://sourceware.org/pipermail/libc-alpha/2020-September/117501.html https://sourceware.org/pipermail/libc-alpha/2020-September/117502.html * lib/tempname.c: Include stdalign.h, time.h. If _LIBC, do not include random-bits.h. (__getrandom, __clock_gettime64, __timespec64) [!_LIBC]: New macros. (RANDOM_BITS): Remove, replacing with ... (random_bits): ... this new static function. All uses changed. Add entropy each time if getrandom is not supported. (RANDOM_VALUE, BASE_62_DIGITS, BASE_62_POWER): Assume 64-bit support a la C99. (try_tempname_len): Take advantage of ASLR when initializing random value. * modules/tempname (Depends-on): Add clock-time, stdalign, time.
Diffstat (limited to 'lib/tempname.c')
-rw-r--r--lib/tempname.c49
1 files changed, 30 insertions, 19 deletions
diff --git a/lib/tempname.c b/lib/tempname.c
index 9219ee66af..03426c23cf 100644
--- a/lib/tempname.c
+++ b/lib/tempname.c
@@ -47,9 +47,11 @@
#include <string.h>
#include <fcntl.h>
+#include <stdalign.h>
#include <stdint.h>
#include <sys/random.h>
#include <sys/stat.h>
+#include <time.h>
#if _LIBC
# define struct_stat64 struct stat64
@@ -60,27 +62,33 @@
# define __mkdir mkdir
# define __open open
# define __lxstat64(version, file, buf) lstat (file, buf)
+# define __getrandom getrandom
+# define __clock_gettime64 clock_gettime
+# define __timespec64 timespec
#endif
-#ifdef _LIBC
-# include <random-bits.h>
-# define RANDOM_BITS(Var) ((Var) = random_bits ())
-typedef uint32_t random_value;
-# define RANDOM_VALUE_MAX UINT32_MAX
-# define BASE_62_DIGITS 5 /* 62**5 < UINT32_MAX */
-# define BASE_62_POWER (62 * 62 * 62 * 62 * 62) /* 2**BASE_62_DIGITS */
-#else
/* Use getrandom if it works, falling back on a 64-bit linear
- congruential generator that starts with whatever Var's value
- happens to be. */
-# define RANDOM_BITS(Var) \
- ((void) (getrandom (&(Var), sizeof (Var), 0) == sizeof (Var) \
- || ((Var) = 2862933555777941757 * (Var) + 3037000493)))
+ congruential generator that starts with Var's value
+ mixed in with a clock's low-order bits if available. */
typedef uint_fast64_t random_value;
-# define RANDOM_VALUE_MAX UINT_FAST64_MAX
-# define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */
-# define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62)
+#define RANDOM_VALUE_MAX UINT_FAST64_MAX
+#define BASE_62_DIGITS 10 /* 62**10 < UINT_FAST64_MAX */
+#define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62)
+
+static random_value
+random_bits (random_value var)
+{
+ random_value r;
+ if (__getrandom (&r, sizeof r, 0) == sizeof r)
+ return r;
+#if _LIBC || (defined CLOCK_MONOTONIC && HAVE_CLOCK_GETTIME)
+ /* Add entropy if getrandom is not supported. */
+ struct __timespec64 tv;
+ __clock_gettime64 (CLOCK_MONOTONIC, &tv);
+ var ^= tv.tv_nsec;
#endif
+ return 2862933555777941757 * var + 3037000493;
+}
#if _LIBC
/* Return nonzero if DIR is an existent directory. */
@@ -250,8 +258,11 @@ try_tempname_len (char *tmpl, int suffixlen, void *args,
unsigned int attempts = ATTEMPTS_MIN;
#endif
- /* A random variable. */
- random_value v;
+ /* A random variable. The initial value is used only the for fallback path
+ on 'random_bits' on 'getrandom' failure. Its initial value tries to use
+ some entropy from the ASLR and ignore possible bits from the stack
+ alignment. */
+ random_value v = ((uintptr_t) &v) / alignof (max_align_t);
/* How many random base-62 digits can currently be extracted from V. */
int vdigits = 0;
@@ -279,7 +290,7 @@ try_tempname_len (char *tmpl, int suffixlen, void *args,
if (vdigits == 0)
{
do
- RANDOM_BITS (v);
+ v = random_bits (v);
while (unfair_min <= v);
vdigits = BASE_62_DIGITS;