diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2019-01-16 18:10:56 +0000 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2019-03-22 17:30:39 -0300 |
commit | 359653aaacad463d916323f03c0ac3c47405aafa (patch) | |
tree | a7d4de0a3e520ad4d62a2ed11bb63b55607fb160 | |
parent | 6e8ba7fd574f530afb9681f21604475d5756d773 (diff) | |
download | glibc-359653aaacad463d916323f03c0ac3c47405aafa.tar.gz glibc-359653aaacad463d916323f03c0ac3c47405aafa.tar.xz glibc-359653aaacad463d916323f03c0ac3c47405aafa.zip |
Do not use HP_TIMING_NOW for random bits
This patch removes the HP_TIMING_BITS usage for fast random bits and replace with clock_gettime (CLOCK_MONOTONIC). It has unspecified starting time and nano-second accuracy, so its randomness is significantly better than gettimeofday. Althoug it should incur in more overhead (specially for architecture that support hp-timing), the symbol is also common implemented as a vDSO. Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu. I also checked on a i686-gnu build. * include/random-bits.h: New file. * resolv/res_mkquery.c [HP_TIMING_AVAIL] (RANDOM_BITS, (__res_context_mkquery): Remove usage hp-timing usage and replace with random_bits. * resolv/res_send.c [HP_TIMING_AVAIL] (nameserver_offset): Likewise. * sysdeps/posix/tempname.c [HP_TIMING_AVAIL] (__gen_tempname): Likewise.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | include/random-bits.h | 41 | ||||
-rw-r--r-- | resolv/res_mkquery.c | 19 | ||||
-rw-r--r-- | resolv/res_send.c | 12 | ||||
-rw-r--r-- | sysdeps/posix/tempname.c | 40 |
5 files changed, 66 insertions, 54 deletions
diff --git a/ChangeLog b/ChangeLog index 4c5fa54db3..378f9aaa65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2019-03-22 Adhemerval Zanella <adhemerval.zanella@linaro.org> + * include/random-bits.h: New file. + * resolv/res_mkquery.c [HP_TIMING_AVAIL] (RANDOM_BITS, + (__res_context_mkquery): Remove usage hp-timing usage and replace with + random_bits. + * resolv/res_send.c [HP_TIMING_AVAIL] (nameserver_offset): Likewise. + * sysdeps/posix/tempname.c [HP_TIMING_AVAIL] (__gen_tempname): + Likewise. + * include/libc-internal.h (__get_clockfreq): Remove prototype. * rt/Makefile (clock-routines): Remove get_clockfreq. * rt/get_clockfreq.c: Remove file. diff --git a/include/random-bits.h b/include/random-bits.h new file mode 100644 index 0000000000..a0651a5a34 --- /dev/null +++ b/include/random-bits.h @@ -0,0 +1,41 @@ +/* Fast pseudo-random bits based on clock_gettime. + Copyright (C) 2019 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 Lesser General Public + License as published by the Free Software Foundation; either + 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _RANDOM_BITS_H +# define _RANDOM_BITS_H + +#include <time.h> +#include <stdint.h> + +/* Provides fast pseudo-random bits through clock_gettime. It has unspecified + starting time, nano-second accuracy, its randomness is significantly better + than gettimeofday, and for mostly architectures it is implemented through + vDSO instead of a syscall. Since the source is a system clock, the upper + bits will have less entropy. */ +static inline uint32_t +random_bits (void) +{ + struct timespec tv; + __clock_gettime (CLOCK_MONOTONIC, &tv); + /* Shuffle the lower bits to minimize the clock bias. */ + uint32_t ret = tv.tv_nsec ^ tv.tv_sec; + ret ^= (ret << 24) | (ret >> 8); + return ret; +} + +#endif diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c index 19b8b402c4..dd43d347af 100644 --- a/resolv/res_mkquery.c +++ b/resolv/res_mkquery.c @@ -82,6 +82,7 @@ * SOFTWARE. */ +#include <stdint.h> #include <sys/types.h> #include <sys/param.h> #include <netinet/in.h> @@ -92,12 +93,7 @@ #include <string.h> #include <sys/time.h> #include <shlib-compat.h> - -#include <hp-timing.h> -#include <stdint.h> -#if HP_TIMING_AVAIL -# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; } -#endif +#include <random-bits.h> int __res_context_mkquery (struct resolv_context *ctx, int op, const char *dname, @@ -120,16 +116,7 @@ __res_context_mkquery (struct resolv_context *ctx, int op, const char *dname, /* We randomize the IDs every time. The old code just incremented by one after the initial randomization which still predictable if the application does multiple requests. */ - int randombits; -#ifdef RANDOM_BITS - RANDOM_BITS (randombits); -#else - struct timeval tv; - __gettimeofday (&tv, NULL); - randombits = (tv.tv_sec << 8) ^ tv.tv_usec; -#endif - - hp->id = randombits; + hp->id = random_bits (); hp->opcode = op; hp->rd = (ctx->resp->options & RES_RECURSE) != 0; hp->rcode = NOERROR; diff --git a/resolv/res_send.c b/resolv/res_send.c index 0f6ec83a7b..ca441c4ce1 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -109,7 +109,7 @@ #include <unistd.h> #include <kernel-features.h> #include <libc-diag.h> -#include <hp-timing.h> +#include <random-bits.h> #if PACKETSZ > 65536 #define MAXPACKET PACKETSZ @@ -309,15 +309,7 @@ nameserver_offset (struct __res_state *statp) if ((offset & 1) == 0) { /* Initialization is required. */ -#if HP_TIMING_AVAIL - uint64_t ticks; - HP_TIMING_NOW (ticks); - offset = ticks; -#else - struct timeval tv; - __gettimeofday (&tv, NULL); - offset = ((tv.tv_sec << 8) ^ tv.tv_usec); -#endif + offset = random_bits (); /* The lowest bit is the most random. Preserve it. */ offset <<= 1; diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c index 2ed39d1a42..de346949b2 100644 --- a/sysdeps/posix/tempname.c +++ b/sysdeps/posix/tempname.c @@ -71,22 +71,15 @@ #endif #ifdef _LIBC -# include <hp-timing.h> -# if HP_TIMING_AVAIL -# define RANDOM_BITS(Var) \ - if (__glibc_unlikely (value == UINT64_C (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 +# include <random-bits.h> +# define RANDOM_BITS(Var) ((Var) = random_bits ()) +# else +# define RANDOM_BITS(Var) \ + { \ + struct timeval tv; \ + __gettimeofday (&tv, NULL); \ + (Var) = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ + } #endif /* Use the widest available unsigned type if uint64_t is not @@ -193,8 +186,7 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) { int len; char *XXXXXX; - static uint64_t value; - uint64_t random_time_bits; + uint64_t value; unsigned int count; int fd = -1; int save_errno = errno; @@ -227,16 +219,8 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ -#ifdef RANDOM_BITS - RANDOM_BITS (random_time_bits); -#else - { - struct timeval tv; - __gettimeofday (&tv, NULL); - random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; - } -#endif - value += random_time_bits ^ __getpid (); + RANDOM_BITS (value); + value ^= (uint64_t)__getpid () << 32; for (count = 0; count < attempts; value += 7777, ++count) { |