b1dca6
commit 359653aaacad463d916323f03c0ac3c47405aafa
b1dca6
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
b1dca6
Date:   Wed Jan 16 18:10:56 2019 +0000
b1dca6
b1dca6
    Do not use HP_TIMING_NOW for random bits
b1dca6
    
b1dca6
    This patch removes the HP_TIMING_BITS usage for fast random bits and replace
b1dca6
    with clock_gettime (CLOCK_MONOTONIC).  It has unspecified starting time and
b1dca6
    nano-second accuracy, so its randomness is significantly better than
b1dca6
    gettimeofday.
b1dca6
    
b1dca6
    Althoug it should incur in more overhead (specially for architecture that
b1dca6
    support hp-timing), the symbol is also common implemented as a vDSO.
b1dca6
    
b1dca6
    Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu. I also
b1dca6
    checked on a i686-gnu build.
b1dca6
    
b1dca6
            * include/random-bits.h: New file.
b1dca6
            * resolv/res_mkquery.c [HP_TIMING_AVAIL] (RANDOM_BITS,
b1dca6
            (__res_context_mkquery): Remove usage hp-timing usage and replace with
b1dca6
            random_bits.
b1dca6
            * resolv/res_send.c [HP_TIMING_AVAIL] (nameserver_offset): Likewise.
b1dca6
            * sysdeps/posix/tempname.c [HP_TIMING_AVAIL] (__gen_tempname):
b1dca6
            Likewise.
b1dca6
b1dca6
diff --git a/include/random-bits.h b/include/random-bits.h
b1dca6
new file mode 100644
b1dca6
index 0000000000000000..a0651a5a34f80a8d
b1dca6
--- /dev/null
b1dca6
+++ b/include/random-bits.h
b1dca6
@@ -0,0 +1,41 @@
b1dca6
+/* Fast pseudo-random bits based on clock_gettime.
b1dca6
+   Copyright (C) 2019 Free Software Foundation, Inc.
b1dca6
+   This file is part of the GNU C Library.
b1dca6
+
b1dca6
+   The GNU C Library is free software; you can redistribute it and/or
b1dca6
+   modify it under the terms of the GNU Lesser General Public
b1dca6
+   License as published by the Free Software Foundation; either
b1dca6
+   version 2.1 of the License, or (at your option) any later version.
b1dca6
+
b1dca6
+   The GNU C Library is distributed in the hope that it will be useful,
b1dca6
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
b1dca6
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
b1dca6
+   Lesser General Public License for more details.
b1dca6
+
b1dca6
+   You should have received a copy of the GNU Lesser General Public
b1dca6
+   License along with the GNU C Library; if not, see
b1dca6
+   <http://www.gnu.org/licenses/>.  */
b1dca6
+
b1dca6
+#ifndef _RANDOM_BITS_H
b1dca6
+# define _RANDOM_BITS_H
b1dca6
+
b1dca6
+#include <time.h>
b1dca6
+#include <stdint.h>
b1dca6
+
b1dca6
+/* Provides fast pseudo-random bits through clock_gettime.  It has unspecified
b1dca6
+   starting time, nano-second accuracy, its randomness is significantly better
b1dca6
+   than gettimeofday, and for mostly architectures it is implemented through
b1dca6
+   vDSO instead of a syscall.  Since the source is a system clock, the upper
b1dca6
+   bits will have less entropy. */
b1dca6
+static inline uint32_t
b1dca6
+random_bits (void)
b1dca6
+{
b1dca6
+  struct timespec tv;
b1dca6
+  __clock_gettime (CLOCK_MONOTONIC, &tv;;
b1dca6
+  /* Shuffle the lower bits to minimize the clock bias.  */
b1dca6
+  uint32_t ret = tv.tv_nsec ^ tv.tv_sec;
b1dca6
+  ret ^= (ret << 24) | (ret >> 8);
b1dca6
+  return ret;
b1dca6
+}
b1dca6
+
b1dca6
+#endif
b1dca6
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
b1dca6
index 213abeefadf7ece5..4471a8838b1de7ee 100644
b1dca6
--- a/resolv/res_mkquery.c
b1dca6
+++ b/resolv/res_mkquery.c
b1dca6
@@ -82,6 +82,7 @@
b1dca6
  * SOFTWARE.
b1dca6
  */
b1dca6
 
b1dca6
+#include <stdint.h>
b1dca6
 #include <sys/types.h>
b1dca6
 #include <sys/param.h>
b1dca6
 #include <netinet/in.h>
b1dca6
@@ -92,12 +93,7 @@
b1dca6
 #include <string.h>
b1dca6
 #include <sys/time.h>
b1dca6
 #include <shlib-compat.h>
b1dca6
-
b1dca6
-#include <hp-timing.h>
b1dca6
-#include <stdint.h>
b1dca6
-#if HP_TIMING_AVAIL
b1dca6
-# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; }
b1dca6
-#endif
b1dca6
+#include <random-bits.h>
b1dca6
 
b1dca6
 int
b1dca6
 __res_context_mkquery (struct resolv_context *ctx, int op, const char *dname,
b1dca6
@@ -120,16 +116,7 @@ __res_context_mkquery (struct resolv_context *ctx, int op, const char *dname,
b1dca6
   /* We randomize the IDs every time.  The old code just incremented
b1dca6
      by one after the initial randomization which still predictable if
b1dca6
      the application does multiple requests.  */
b1dca6
-  int randombits;
b1dca6
-#ifdef RANDOM_BITS
b1dca6
-  RANDOM_BITS (randombits);
b1dca6
-#else
b1dca6
-  struct timeval tv;
b1dca6
-  __gettimeofday (&tv, NULL);
b1dca6
-  randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
b1dca6
-#endif
b1dca6
-
b1dca6
-  hp->id = randombits;
b1dca6
+  hp->id = random_bits ();
b1dca6
   hp->opcode = op;
b1dca6
   hp->rd = (ctx->resp->options & RES_RECURSE) != 0;
b1dca6
   hp->rcode = NOERROR;
b1dca6
diff --git a/resolv/res_send.c b/resolv/res_send.c
b1dca6
index ac19627634281c2f..55e7fa438e7baac1 100644
b1dca6
--- a/resolv/res_send.c
b1dca6
+++ b/resolv/res_send.c
b1dca6
@@ -109,7 +109,7 @@
b1dca6
 #include <unistd.h>
b1dca6
 #include <kernel-features.h>
b1dca6
 #include <libc-diag.h>
b1dca6
-#include <hp-timing.h>
b1dca6
+#include <random-bits.h>
b1dca6
 
b1dca6
 #if PACKETSZ > 65536
b1dca6
 #define MAXPACKET       PACKETSZ
b1dca6
@@ -309,15 +309,7 @@ nameserver_offset (struct __res_state *statp)
b1dca6
   if ((offset & 1) == 0)
b1dca6
     {
b1dca6
       /* Initialization is required.  */
b1dca6
-#if HP_TIMING_AVAIL
b1dca6
-      uint64_t ticks;
b1dca6
-      HP_TIMING_NOW (ticks);
b1dca6
-      offset = ticks;
b1dca6
-#else
b1dca6
-      struct timeval tv;
b1dca6
-      __gettimeofday (&tv, NULL);
b1dca6
-      offset = ((tv.tv_sec << 8) ^ tv.tv_usec);
b1dca6
-#endif
b1dca6
+      offset = random_bits ();
b1dca6
       /* The lowest bit is the most random.  Preserve it.  */
b1dca6
       offset <<= 1;
b1dca6
 
b1dca6
diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c
b1dca6
index 432262a03b6ecc23..3d26f378021680ae 100644
b1dca6
--- a/sysdeps/posix/tempname.c
b1dca6
+++ b/sysdeps/posix/tempname.c
b1dca6
@@ -71,22 +71,15 @@
b1dca6
 #endif
b1dca6
 
b1dca6
 #ifdef _LIBC
b1dca6
-# include <hp-timing.h>
b1dca6
-# if HP_TIMING_AVAIL
b1dca6
-#  define RANDOM_BITS(Var) \
b1dca6
-  if (__glibc_unlikely (value == UINT64_C (0)))				      \
b1dca6
-    {									      \
b1dca6
-      /* If this is the first time this function is used initialize	      \
b1dca6
-	 the variable we accumulate the value in to some somewhat	      \
b1dca6
-	 random value.  If we'd not do this programs at startup time	      \
b1dca6
-	 might have a reduced set of possible names, at least on slow	      \
b1dca6
-	 machines.  */							      \
b1dca6
-      struct timeval tv;						      \
b1dca6
-      __gettimeofday (&tv, NULL);					      \
b1dca6
-      value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;		      \
b1dca6
-    }									      \
b1dca6
-  HP_TIMING_NOW (Var)
b1dca6
-# endif
b1dca6
+# include <random-bits.h>
b1dca6
+# define RANDOM_BITS(Var) ((Var) = random_bits ())
b1dca6
+# else
b1dca6
+# define RANDOM_BITS(Var) \
b1dca6
+    {                                                                         \
b1dca6
+      struct timeval tv;                                                      \
b1dca6
+      __gettimeofday (&tv, NULL);                                             \
b1dca6
+      (Var) = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;                      \
b1dca6
+    }
b1dca6
 #endif
b1dca6
 
b1dca6
 /* Use the widest available unsigned type if uint64_t is not
b1dca6
@@ -193,8 +186,7 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
b1dca6
 {
b1dca6
   int len;
b1dca6
   char *XXXXXX;
b1dca6
-  static uint64_t value;
b1dca6
-  uint64_t random_time_bits;
b1dca6
+  uint64_t value;
b1dca6
   unsigned int count;
b1dca6
   int fd = -1;
b1dca6
   int save_errno = errno;
b1dca6
@@ -227,16 +219,8 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
b1dca6
   XXXXXX = &tmpl[len - 6 - suffixlen];
b1dca6
 
b1dca6
   /* Get some more or less random data.  */
b1dca6
-#ifdef RANDOM_BITS
b1dca6
-  RANDOM_BITS (random_time_bits);
b1dca6
-#else
b1dca6
-  {
b1dca6
-    struct timeval tv;
b1dca6
-    __gettimeofday (&tv, NULL);
b1dca6
-    random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
b1dca6
-  }
b1dca6
-#endif
b1dca6
-  value += random_time_bits ^ __getpid ();
b1dca6
+  RANDOM_BITS (value);
b1dca6
+  value ^= (uint64_t)__getpid () << 32;
b1dca6
 
b1dca6
   for (count = 0; count < attempts; value += 7777, ++count)
b1dca6
     {