1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

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.
This commit is contained in:
Adhemerval Zanella
2019-01-16 18:10:56 +00:00
parent 6e8ba7fd57
commit 359653aaac
5 changed files with 66 additions and 54 deletions

View File

@ -1,5 +1,13 @@
2019-03-22 Adhemerval Zanella <adhemerval.zanella@linaro.org> 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. * include/libc-internal.h (__get_clockfreq): Remove prototype.
* rt/Makefile (clock-routines): Remove get_clockfreq. * rt/Makefile (clock-routines): Remove get_clockfreq.
* rt/get_clockfreq.c: Remove file. * rt/get_clockfreq.c: Remove file.

41
include/random-bits.h Normal file
View File

@ -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

View File

@ -82,6 +82,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/param.h> #include <sys/param.h>
#include <netinet/in.h> #include <netinet/in.h>
@ -92,12 +93,7 @@
#include <string.h> #include <string.h>
#include <sys/time.h> #include <sys/time.h>
#include <shlib-compat.h> #include <shlib-compat.h>
#include <random-bits.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
int int
__res_context_mkquery (struct resolv_context *ctx, int op, const char *dname, __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 /* We randomize the IDs every time. The old code just incremented
by one after the initial randomization which still predictable if by one after the initial randomization which still predictable if
the application does multiple requests. */ the application does multiple requests. */
int randombits; hp->id = random_bits ();
#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->opcode = op; hp->opcode = op;
hp->rd = (ctx->resp->options & RES_RECURSE) != 0; hp->rd = (ctx->resp->options & RES_RECURSE) != 0;
hp->rcode = NOERROR; hp->rcode = NOERROR;

View File

@ -109,7 +109,7 @@
#include <unistd.h> #include <unistd.h>
#include <kernel-features.h> #include <kernel-features.h>
#include <libc-diag.h> #include <libc-diag.h>
#include <hp-timing.h> #include <random-bits.h>
#if PACKETSZ > 65536 #if PACKETSZ > 65536
#define MAXPACKET PACKETSZ #define MAXPACKET PACKETSZ
@ -309,15 +309,7 @@ nameserver_offset (struct __res_state *statp)
if ((offset & 1) == 0) if ((offset & 1) == 0)
{ {
/* Initialization is required. */ /* Initialization is required. */
#if HP_TIMING_AVAIL offset = random_bits ();
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
/* The lowest bit is the most random. Preserve it. */ /* The lowest bit is the most random. Preserve it. */
offset <<= 1; offset <<= 1;

View File

@ -71,22 +71,15 @@
#endif #endif
#ifdef _LIBC #ifdef _LIBC
# include <hp-timing.h> # include <random-bits.h>
# if HP_TIMING_AVAIL # define RANDOM_BITS(Var) ((Var) = random_bits ())
# define RANDOM_BITS(Var) \ # else
if (__glibc_unlikely (value == UINT64_C (0))) \ # define RANDOM_BITS(Var) \
{ \ { \
/* If this is the first time this function is used initialize \ struct timeval tv; \
the variable we accumulate the value in to some somewhat \ __gettimeofday (&tv, NULL); \
random value. If we'd not do this programs at startup time \ (Var) = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \
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
#endif #endif
/* Use the widest available unsigned type if uint64_t is not /* 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; int len;
char *XXXXXX; char *XXXXXX;
static uint64_t value; uint64_t value;
uint64_t random_time_bits;
unsigned int count; unsigned int count;
int fd = -1; int fd = -1;
int save_errno = errno; int save_errno = errno;
@ -227,16 +219,8 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
XXXXXX = &tmpl[len - 6 - suffixlen]; XXXXXX = &tmpl[len - 6 - suffixlen];
/* Get some more or less random data. */ /* Get some more or less random data. */
#ifdef RANDOM_BITS RANDOM_BITS (value);
RANDOM_BITS (random_time_bits); value ^= (uint64_t)__getpid () << 32;
#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 ();
for (count = 0; count < attempts; value += 7777, ++count) for (count = 0; count < attempts; value += 7777, ++count)
{ {