From: Paul Eggert Date: Thu, 10 Sep 2020 06:59:18 +0000 (-0700) Subject: tempname: help merge with glibc X-Git-Tag: v1.0~3644 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=44358d4d165bcc96ceacb2c7e903053b87ab339c;p=gnulib.git 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. --- diff --git a/ChangeLog b/ChangeLog index c554e5672c..8b6f62bb12 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 2020-09-09 Paul Eggert + 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. + getcwd: merge recent glibc changes * lib/getcwd.c (GETCWD_RETURN_TYPE) [!_LIBC]: New macro. (__getcwd, getcwd) [_LIBC && !GETCWD_RETURN_TYPE]: Add aliases. 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 #include +#include #include #include #include +#include #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 -# 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; diff --git a/modules/tempname b/modules/tempname index d55f4ce1a3..385c65a6ee 100644 --- a/modules/tempname +++ b/modules/tempname @@ -9,14 +9,17 @@ m4/tempname.m4 Depends-on: c99 +clock-time extensions fcntl-h getrandom libc-config lstat mkdir +stdalign stdint sys_stat +time configure.ac: gl_FUNC_GEN_TEMPNAME