mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-27 03:33:33 +08: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:
parent
6e8ba7fd57
commit
359653aaac
@ -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.
|
||||
|
41
include/random-bits.h
Normal file
41
include/random-bits.h
Normal 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
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user