diff options
Diffstat (limited to 'gnulib/import/tempname.c')
-rw-r--r-- | gnulib/import/tempname.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/gnulib/import/tempname.c b/gnulib/import/tempname.c index 3d91dee..5fc5efe 100644 --- a/gnulib/import/tempname.c +++ b/gnulib/import/tempname.c @@ -1,17 +1,17 @@ -/* Copyright (C) 1991-2021 Free Software Foundation, Inc. +/* Copyright (C) 1991-2022 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 - modify it under the terms of the GNU General Public + modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. + version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public + You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see <https://www.gnu.org/licenses/>. */ @@ -22,6 +22,7 @@ #include <sys/types.h> #include <assert.h> +#include <stdbool.h> #include <errno.h> @@ -61,7 +62,8 @@ # define __gen_tempname gen_tempname # define __mkdir mkdir # define __open open -# define __lxstat64(version, file, buf) lstat (file, buf) +# define __lstat64(file, buf) lstat (file, buf) +# define __stat64(file, buf) stat (file, buf) # define __getrandom getrandom # define __clock_gettime64 clock_gettime # define __timespec64 timespec @@ -76,13 +78,14 @@ typedef uint_fast64_t random_value; #define BASE_62_POWER (62LL * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62 * 62) static random_value -random_bits (random_value var) +random_bits (random_value var, bool use_getrandom) { random_value r; - if (__getrandom (&r, sizeof r, 0) == sizeof r) + /* Without GRND_NONBLOCK it can be blocked for minutes on some systems. */ + if (use_getrandom && __getrandom (&r, sizeof r, GRND_NONBLOCK) == sizeof r) return r; #if _LIBC || (defined CLOCK_MONOTONIC && HAVE_CLOCK_GETTIME) - /* Add entropy if getrandom is not supported. */ + /* Add entropy if getrandom did not work. */ struct __timespec64 tv; __clock_gettime64 (CLOCK_MONOTONIC, &tv); var ^= tv.tv_nsec; @@ -96,7 +99,7 @@ static int direxists (const char *dir) { struct_stat64 buf; - return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); + return __stat64 (dir, &buf) == 0 && S_ISDIR (buf.st_mode); } /* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is @@ -178,17 +181,17 @@ try_file (char *tmpl, void *flags) } static int -try_dir (char *tmpl, void *flags _GL_UNUSED) +try_dir (char *tmpl, _GL_UNUSED void *flags) { return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); } static int -try_nocreate (char *tmpl, void *flags _GL_UNUSED) +try_nocreate (char *tmpl, _GL_UNUSED void *flags) { struct_stat64 st; - if (__lxstat64 (_STAT_VER, tmpl, &st) == 0 || errno == EOVERFLOW) + if (__lstat64 (tmpl, &st) == 0 || errno == EOVERFLOW) __set_errno (EEXIST); return errno == ENOENT ? 0 : -1; } @@ -267,6 +270,13 @@ try_tempname_len (char *tmpl, int suffixlen, void *args, /* How many random base-62 digits can currently be extracted from V. */ int vdigits = 0; + /* Whether to consume entropy when acquiring random bits. On the + first try it's worth the entropy cost with __GT_NOCREATE, which + is inherently insecure and can use the entropy to make it a bit + less secure. On the (rare) second and later attempts it might + help against DoS attacks. */ + bool use_getrandom = tryfunc == try_nocreate; + /* Least unfair value for V. If V is less than this, V can generate BASE_62_DIGITS digits fairly. Otherwise it might be biased. */ random_value const unfair_min @@ -290,7 +300,10 @@ try_tempname_len (char *tmpl, int suffixlen, void *args, if (vdigits == 0) { do - v = random_bits (v); + { + v = random_bits (v, use_getrandom); + use_getrandom = true; + } while (unfair_min <= v); vdigits = BASE_62_DIGITS; |