From patchwork Wed Sep 9 17:53:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 40388 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 460113857837; Wed, 9 Sep 2020 17:54:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 460113857837 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1599674045; bh=uEP9bqv4qoUL/pdQBNptxknFRP2aPeEVwsYcWa18Mvo=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=nkBbzTOW48DPL4oyCnNMwQ1R22OzCDQ9V0MFUi8v3YmyJZ9xvER584U493eiq8/bj OEceWBHFLwqXbPjFmXL6KxAKNmw5vkaoh6LD4cse+BnZofUsx5BwDyaU1HDc4T5Nl/ omxsGI+6S6RbmT9s5VrPf0d3/HVqS9vP8yTYtg3s= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x743.google.com (mail-qk1-x743.google.com [IPv6:2607:f8b0:4864:20::743]) by sourceware.org (Postfix) with ESMTPS id CB2A83857C59 for ; Wed, 9 Sep 2020 17:54:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org CB2A83857C59 Received: by mail-qk1-x743.google.com with SMTP id o16so3256607qkj.10 for ; Wed, 09 Sep 2020 10:54:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=uEP9bqv4qoUL/pdQBNptxknFRP2aPeEVwsYcWa18Mvo=; b=DuYeDUXHJKJDRv4BTQG4MCX8YWr2nO4WEnMZJks7Sl12xNsATjY2AwxlOHPhjt5uIM QnjuusBAeiVqSLVEiKWPFGN6EQFj6f5VkTf/MKN5kyIr5XkGFZ9K8MpJnuI27rWZgYWD uQEGxhfAFA/Z5MeIkPpuX2x2EG6SvnHeCToZa5vdQx/1eLGZFs9/G8FGBylF6lQNIb9C Qlfn6x6Tg6/IYoF1G0rWkZal9ZQsu0Pg07i5N9w1Faz0XoaoMMmw+XytYCWQMae9Kw+b qzLp19mHoKVVPjRFmppUEmBtVEFD7xjaPC1hRjJEuUXm8oDd4asUn9bwwCqZ8iwTJ4Ah xZQQ== X-Gm-Message-State: AOAM5331KP71s2oykvNS0w1I77CdPE0wf4MjraJC2hBlEIF3ITLxsHJY oVBC75qbLiJyU52FICR5oErW1CMKyP7hdw== X-Google-Smtp-Source: ABdhPJzmPSOAvwGtiAdErKpV+zLhDCF+NyoVtOzfiT3b91V1oUWC9bki7sCit3Znh1Uquzzg05mu6Q== X-Received: by 2002:a05:620a:20db:: with SMTP id f27mr4566121qka.11.1599674040883; Wed, 09 Sep 2020 10:54:00 -0700 (PDT) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id x126sm3509639qka.91.2020.09.09.10.53.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2020 10:54:00 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 1/2] Sync tempname with gnulib Date: Wed, 9 Sep 2020 14:53:54 -0300 Message-Id: <20200909175355.2594189-1-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 X-Spam-Status: No, score=-13.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Cc: Jakub Jelinek Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" It sync with commit b58bf6ee39a6a114550a6bb68e7db5262c17f8bf. --- sysdeps/posix/tempname.c | 260 ++++++++++++++++++++++----------------- 1 file changed, 147 insertions(+), 113 deletions(-) diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index cd48385a40..9219ee66af 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -16,7 +16,7 @@ . */ #if !_LIBC -# include +# include # include "tempname.h" #endif @@ -24,9 +24,6 @@ #include #include -#ifndef __set_errno -# define __set_errno(Val) errno = (Val) -#endif #include #ifndef P_tmpdir @@ -36,12 +33,12 @@ # define TMP_MAX 238328 #endif #ifndef __GT_FILE -# define __GT_FILE 0 -# define __GT_DIR 1 -# define __GT_NOCREATE 2 +# define __GT_FILE 0 +# define __GT_DIR 1 +# define __GT_NOCREATE 2 #endif -#if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR \ - || GT_NOCREATE != __GT_NOCREATE) +#if !_LIBC && (GT_FILE != __GT_FILE || GT_DIR != __GT_DIR \ + || GT_NOCREATE != __GT_NOCREATE) # error report this to bug-gnulib@gnu.org #endif @@ -50,10 +47,8 @@ #include #include -#include #include -#include - +#include #include #if _LIBC @@ -62,32 +57,29 @@ #else # define struct_stat64 struct stat # define __gen_tempname gen_tempname -# define __getpid getpid # define __mkdir mkdir # define __open open # define __lxstat64(version, file, buf) lstat (file, buf) -# define __secure_getenv secure_getenv #endif #ifdef _LIBC # include # define RANDOM_BITS(Var) ((Var) = random_bits ()) -# else +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) \ - { \ - struct timespec ts; \ - clock_gettime (CLOCK_REALTIME, &ts); \ - (Var) = ((uint64_t) tv.tv_nsec << 16) ^ tv.tv_sec; \ - } -#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 - uintmax_t is only 32 bits lose about 3.725 bits of randomness, - which is better than not having mkstemp at all. */ -#if !defined UINT64_MAX && !defined uint64_t -# define uint64_t uintmax_t + ((void) (getrandom (&(Var), sizeof (Var), 0) == sizeof (Var) \ + || ((Var) = 2862933555777941757 * (Var) + 3037000493))) +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) #endif #if _LIBC @@ -107,7 +99,7 @@ direxists (const char *dir) enough space in TMPL. */ int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir) + int try_tmpdir) { const char *d; size_t dlen, plen; @@ -121,35 +113,35 @@ __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, { plen = strlen (pfx); if (plen > 5) - plen = 5; + plen = 5; } if (try_tmpdir) { d = __secure_getenv ("TMPDIR"); if (d != NULL && direxists (d)) - dir = d; + dir = d; else if (dir != NULL && direxists (dir)) - /* nothing */ ; + /* nothing */ ; else - dir = NULL; + dir = NULL; } if (dir == NULL) { if (direxists (P_tmpdir)) - dir = P_tmpdir; + dir = P_tmpdir; else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) - dir = "/tmp"; + dir = "/tmp"; else - { - __set_errno (ENOENT); - return -1; - } + { + __set_errno (ENOENT); + return -1; + } } dlen = strlen (dir); while (dlen > 1 && dir[dlen - 1] == '/') - dlen--; /* remove trailing slashes */ + dlen--; /* remove trailing slashes */ /* check we have room for "${dir}/${pfx}XXXXXX\0" */ if (tmpl_len < dlen + 1 + plen + 6 + 1) @@ -163,39 +155,91 @@ __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, } #endif /* _LIBC */ +#if _LIBC +static int try_tempname_len (char *, int, void *, int (*) (char *, void *), + size_t); +#endif + +static int +try_file (char *tmpl, void *flags) +{ + int *openflags = flags; + return __open (tmpl, + (*openflags & ~O_ACCMODE) + | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); +} + +static int +try_dir (char *tmpl, void *flags _GL_UNUSED) +{ + return __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); +} + +static int +try_nocreate (char *tmpl, void *flags _GL_UNUSED) +{ + struct_stat64 st; + + if (__lxstat64 (_STAT_VER, tmpl, &st) == 0 || errno == EOVERFLOW) + __set_errno (EEXIST); + return errno == ENOENT ? 0 : -1; +} + /* These are the characters used in temporary file names. */ static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; /* Generate a temporary file name based on TMPL. TMPL must match the - rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix). + rules for mk[s]temp (i.e., end in at least X_SUFFIX_LEN "X"s, + possibly with a suffix). The name constructed does not exist at the time of the call to - __gen_tempname. TMPL is overwritten with the result. + this function. TMPL is overwritten with the result. KIND may be one of: - __GT_NOCREATE: simply verify that the name does not exist - at the time of the call. - __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. + __GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + __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. */ +#ifdef _LIBC +static +#endif int -__gen_tempname (char *tmpl, int suffixlen, int flags, int kind) +gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind, + size_t x_suffix_len) +{ + static int (*const tryfunc[]) (char *, void *) = + { + [__GT_FILE] = try_file, + [__GT_DIR] = try_dir, + [__GT_NOCREATE] = try_nocreate + }; + return try_tempname_len (tmpl, suffixlen, &flags, tryfunc[kind], + x_suffix_len); +} + +#ifdef _LIBC +static +#endif +int +try_tempname_len (char *tmpl, int suffixlen, void *args, + int (*tryfunc) (char *, void *), size_t x_suffix_len) { - int len; + size_t len; char *XXXXXX; unsigned int count; int fd = -1; int save_errno = errno; - struct_stat64 st; /* A lower bound on the number of temporary files to attempt to generate. The maximum total number of temporary file names that can exist for a given template is 62**6. It should never be necessary to try all of these combinations. Instead if a reasonable number of names is tried (we define reasonable as 62**3) fail to - give the system administrator the chance to remove the problems. */ + give the system administrator the chance to remove the problems. + This value requires that X_SUFFIX_LEN be at least 3. */ #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary file. To @@ -206,82 +250,72 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) unsigned int attempts = ATTEMPTS_MIN; #endif + /* A random variable. */ + random_value v; + + /* How many random base-62 digits can currently be extracted from V. */ + int vdigits = 0; + + /* 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 + = RANDOM_VALUE_MAX - RANDOM_VALUE_MAX % BASE_62_POWER; + len = strlen (tmpl); - if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) + if (len < x_suffix_len + suffixlen + || strspn (&tmpl[len - x_suffix_len - suffixlen], "X") < x_suffix_len) { __set_errno (EINVAL); return -1; } /* This is where the Xs start. */ - XXXXXX = &tmpl[len - 6 - suffixlen]; + XXXXXX = &tmpl[len - x_suffix_len - suffixlen]; - uint64_t pid = (uint64_t) __getpid () << 32; for (count = 0; count < attempts; ++count) { - uint64_t v; - /* Get some more or less random data. */ - RANDOM_BITS (v); - v ^= pid; - - /* 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: - fd = __open (tmpl, - (flags & ~O_ACCMODE) - | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - break; - - case __GT_DIR: - fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); - break; - - case __GT_NOCREATE: - /* This case is backward from the other three. __gen_tempname - succeeds if __xstat fails because the name does not exist. - Note the continue to bypass the common logic at the bottom - of the loop. */ - if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) - { - if (errno == ENOENT) - { - __set_errno (save_errno); - return 0; - } - else - /* Give up now. */ - return -1; - } - continue; - - default: - assert (! "invalid KIND in __gen_tempname"); - abort (); - } - + for (size_t i = 0; i < x_suffix_len; i++) + { + if (vdigits == 0) + { + do + RANDOM_BITS (v); + while (unfair_min <= v); + + vdigits = BASE_62_DIGITS; + } + + XXXXXX[i] = letters[v % 62]; + v /= 62; + vdigits--; + } + + fd = tryfunc (tmpl, args); if (fd >= 0) - { - __set_errno (save_errno); - return fd; - } + { + __set_errno (save_errno); + return fd; + } else if (errno != EEXIST) - return -1; + return -1; } /* We got out of the loop because we ran out of combinations to try. */ __set_errno (EEXIST); return -1; } + +int +__gen_tempname (char *tmpl, int suffixlen, int flags, int kind) +{ + return gen_tempname_len (tmpl, suffixlen, flags, kind, 6); +} + +#if !_LIBC +int +try_tempname (char *tmpl, int suffixlen, void *args, + int (*tryfunc) (char *, void *)) +{ + return try_tempname_len (tmpl, suffixlen, args, tryfunc, 6); +} +#endif From patchwork Wed Sep 9 17:53:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 40389 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id CB5553860C35; Wed, 9 Sep 2020 17:54:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CB5553860C35 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1599674045; bh=JhVtb4kHtmqWGY9ers4QgwGLImiZRuYKSsKD1MFCMCI=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=JoDjLgsjses7U4x+XyPOYIYYxYEOKv1g/UW72bjBihwCMvyQcG7nJX0q39pp2QN9U lToqhyymjJ6M/lzUPSHp5y6totYQH5RfsyRvmoxyhsgZ5O0iLRwgN2IBM8pGGKYVg8 u7ZHoAXdrpSZeEWKGwcsV2YiYEOraohTl+L3LGkQ= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-qk1-x732.google.com (mail-qk1-x732.google.com [IPv6:2607:f8b0:4864:20::732]) by sourceware.org (Postfix) with ESMTPS id 35470385782B for ; Wed, 9 Sep 2020 17:54:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 35470385782B Received: by mail-qk1-x732.google.com with SMTP id v123so3258740qkd.9 for ; Wed, 09 Sep 2020 10:54:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JhVtb4kHtmqWGY9ers4QgwGLImiZRuYKSsKD1MFCMCI=; b=Z7AHdhEDXYJfGBSsha0346gEu+dALquD/IEtbERWTc1CHxersBKXQB+9m2DOmNa7n9 b5dzmKCdKSGtL4uc09qnJHSK/0ryxF7iEjHORB1tLE2Fadsid2/KJUrg0FqY0Yevhuq2 rVY4XEZ+WW47nOvbcmAyNc/YR+NQd2/5AK3ls1at60canF//qSQHiOEAKS4VKPO/BM5A gB4CH/AJfyo8z9N485eJh5Vz3eKdPyjNOm/xhR0Fo20acdjcjbWVtusN0xthVyEPRZ3q 9RGR4gz3Eq4T2GPeL7e1yQudG/XrJEB7/5EutpIcBq4Z5nugz+hqR7wA00SniXKFj41D jolA== X-Gm-Message-State: AOAM533bMP7+E8vFDkKuFNngzVjOE6xUcj6JKBx0NyQHbPkzbmjkxb/u 69qeaQ+4mZDt23QYeONnLVzQcuXwDOX+wQ== X-Google-Smtp-Source: ABdhPJwTtZaHR6aVvIyxBnhaZwwunmWqewoIdWM4Hp7gbb7faqvnYok5/HANKEILC/0XYT4GBovySQ== X-Received: by 2002:a05:620a:101a:: with SMTP id z26mr4336307qkj.300.1599674042454; Wed, 09 Sep 2020 10:54:02 -0700 (PDT) Received: from localhost.localdomain ([177.194.48.209]) by smtp.googlemail.com with ESMTPSA id x126sm3509639qka.91.2020.09.09.10.54.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 09 Sep 2020 10:54:02 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH 2/2] Use getrandom on try_tempname_len [BZ #15813] Date: Wed, 9 Sep 2020 14:53:55 -0300 Message-Id: <20200909175355.2594189-2-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200909175355.2594189-1-adhemerval.zanella@linaro.org> References: <20200909175355.2594189-1-adhemerval.zanella@linaro.org> MIME-Version: 1.0 X-Spam-Status: No, score=-13.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Adhemerval Zanella via Libc-alpha From: Adhemerval Zanella Netto Reply-To: Adhemerval Zanella Cc: Jakub Jelinek Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Remove the usage of random-bits.h for _LIBC and use getrandom instead. Also, the fallback relies on UB (the LCG might use unitialized value from the stack variable) so initialize the initial state using some ASLR entropy. The fallback will be always used on Linux with kernels older than 3.17, so it also adds some extra entropy based on the clock for the linear congruential generator (LCG). Checked on x86_64-linux-gnu. --- sysdeps/posix/tempname.c | 41 +++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index 9219ee66af..1ef5536814 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -60,27 +60,31 @@ # define __mkdir mkdir # define __open open # define __lxstat64(version, file, buf) lstat (file, buf) +# define __getrandom getrandom #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))) 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 + /* Add some more entropy if getrandom is not supported. */ + struct __timespec64 tv; + __clock_gettime64 (CLOCK_MONOTONIC, &tv); + var = var ^ tv.tv_nsec; #endif + return 2862933555777941757 * var + 3037000493; +} #if _LIBC /* Return nonzero if DIR is an existent directory. */ @@ -250,8 +254,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) / 16; /* How many random base-62 digits can currently be extracted from V. */ int vdigits = 0; @@ -279,7 +286,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;