Skip to content

Commit

Permalink
common: make seeding pseudo-random number generator easy
Browse files Browse the repository at this point in the history
Unify how srand() calls are done, with some care to try avoiding bad
seeding with hope pseudo-random numbers are unpredictable.

Acked-by: Petr Vorel <petr.vorel@gmail.com>
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
  • Loading branch information
kerolasa committed Sep 10, 2019
1 parent ec821e5 commit ad0256f
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 26 deletions.
40 changes: 40 additions & 0 deletions iputils_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#if HAVE_GETRANDOM
# include <sys/random.h>
#endif

#ifdef HAVE_ERROR_H
# include <error.h>
#else
Expand Down Expand Up @@ -79,3 +84,38 @@ long strtol_or_err(char const *const str, char const *const errmesg,
error(EXIT_FAILURE, errno, "%s: '%s'", errmesg, str);
abort();
}

static unsigned int iputil_srand_fallback(void)
{
struct timespec ts;

clock_gettime(CLOCK_REALTIME, &ts);
return ((getpid() << 16) ^ getuid() ^ ts.tv_sec ^ ts.tv_nsec);
}

void iputils_srand(void)
{
unsigned int i;
#if HAVE_GETRANDOM
ssize_t ret;

while ((ret = getrandom(&i, sizeof(i), GRND_NONBLOCK)) != sizeof(i)) {
switch(errno) {
case EINTR:
continue;
default:
i = iputil_srand_fallback();
break;
}
}
#else
i = iputil_srand_fallback();
#endif
srand(i);
/* Consume up to 31 random numbers */
i = rand() & 0x1F;
while (0 < i) {
rand();
i--;
}
}
1 change: 1 addition & 0 deletions iputils_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,6 @@ extern int close_stream(FILE *stream);
extern void close_stdout(void);
extern long strtol_or_err(char const *const str, char const *const errmesg,
const long min, const long max);
extern void iputils_srand(void);

#endif /* IPUTILS_COMMON_H */
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ conf.set('_GNU_SOURCE', 1, description : 'Enable GNU extensions on systems that
# Check functions.
foreach f : '''
__fpending
getrandom
nanosleep
'''.split()
if cc.has_function(f, args : '-D_GNU_SOURCE')
Expand Down
16 changes: 1 addition & 15 deletions ninfod/ninfod_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,21 +305,7 @@ void init_core(int forced)
DEBUG(LOG_DEBUG, "%s()\n", __func__);

if (!initialized || forced) {
struct timeval tv;
unsigned int seed = 0;
pid_t pid;

if (gettimeofday(&tv, NULL) < 0) {
DEBUG(LOG_WARNING, "%s(): failed to gettimeofday()\n", __func__);
} else {
seed = (tv.tv_usec & 0xffffffff);
}

pid = getpid();
seed ^= (((unsigned long)pid) & 0xffffffff);

srand(seed);

iputils_srand();
#if ENABLE_THREADS
if (initialized)
pthread_attr_destroy(&pattr);
Expand Down
9 changes: 1 addition & 8 deletions ping6_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,7 @@ struct {
static void niquery_init_nonce(void)
{
#if PING6_NONCE_MEMORY
struct timeval tv;
unsigned long seed;

seed = (unsigned long)getpid();
if (!gettimeofday(&tv, NULL))
seed ^= tv.tv_usec;
srand(seed);

iputils_srand();
ni_nonce_ptr = calloc(NI_NONCE_SIZE, MAX_DUP_CHK);
if (!ni_nonce_ptr)
error(2, errno, "calloc");
Expand Down
6 changes: 3 additions & 3 deletions rdisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ int main(int argc, char **argv)

#ifdef RDISC_SERVER
if (responder)
srandom((int)gethostid());
iputils_srand();
#endif

if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
Expand Down Expand Up @@ -503,7 +503,7 @@ void timer()
else
left_until_advertise = min_adv_int +
((max_adv_int - min_adv_int) *
(random() % 1000)/1000);
(rand() % 1000)/1000);
} else
#endif
if (solicit && left_until_solicit <= 0) {
Expand Down Expand Up @@ -873,7 +873,7 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from)
/* Restart the timer when we broadcast */
left_until_advertise = min_adv_int +
((max_adv_int - min_adv_int)
* (random() % 1000)/1000);
* (rand() % 1000)/1000);
} else {
sin.sin_addr.s_addr = ip->saddr;
if (!is_directly_connected(sin.sin_addr)) {
Expand Down

0 comments on commit ad0256f

Please sign in to comment.