All callers used the same initialization seed (well, the new
viratomictest forgot to look at getpid()); so we might as well
make this value automatic. And while it may feel like we are
giving up functionality, I documented how to get it back in the
unlikely case that you actually need to debug with a fixed
pseudo-random sequence. I left that crippled by default, so
that a stray environment variable doesn't cause a lack of
randomness to become a security issue.
* src/util/virrandom.c (virRandomInitialize): Rename...
(virRandomOnceInit): ...and make static, with one-shot call.
Document how to do fixed-seed debugging.
* src/util/virrandom.h (virRandomInitialize): Drop prototype.
* src/libvirt_private.syms (virrandom.h): Don't export it.
* src/libvirt.c (virInitialize): Adjust caller.
* src/lxc/lxc_controller.c (main): Likewise.
* src/security/virt-aa-helper.c (main): Likewise.
* src/util/iohelper.c (main): Likewise.
* tests/seclabeltest.c (main): Likewise.
* tests/testutils.c (virtTestMain): Likewise.
* tests/viratomictest.c (mymain): Likewise.
---
src/libvirt.c | 3 +--
src/libvirt_private.syms | 1 -
src/lxc/lxc_controller.c | 5 ++---
src/security/virt-aa-helper.c | 3 ---
src/util/iohelper.c | 5 ++---
src/util/virrandom.c | 25 ++++++++++++++++++++++++-
src/util/virrandom.h | 1 -
tests/seclabeltest.c | 3 +--
tests/testutils.c | 3 +--
tests/viratomictest.c | 2 --
10 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/src/libvirt.c b/src/libvirt.c
index 3c4bf8c..0a91d0f 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -408,8 +408,7 @@ virInitialize(void)
initialized = 1;
if (virThreadInitialize() < 0 ||
- virErrorInitialize() < 0 ||
- virRandomInitialize(time(NULL) ^ getpid()))
+ virErrorInitialize() < 0)
return -1;
gcry_control(GCRYCTL_SET_THREAD_CBS, &virTLSThreadImpl);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 44b6652..6b98c9c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1663,7 +1663,6 @@ virPidFileDeletePath;
# virrandom.h
virRandomBits;
virRandomGenerateWWN;
-virRandomInitialize;
# virsocketaddr.h
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 56ed7d3..8ff925e 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2010-2012 Red Hat, Inc.
* Copyright IBM Corp. 2008
*
* lxc_controller.c: linux container process controller
@@ -1480,8 +1480,7 @@ int main(int argc, char *argv[])
if (setlocale(LC_ALL, "") == NULL ||
bindtextdomain(PACKAGE, LOCALEDIR) == NULL ||
- textdomain(PACKAGE) == NULL ||
- virRandomInitialize(time(NULL) ^ getpid())) {
+ textdomain(PACKAGE) == NULL) {
fprintf(stderr, _("%s: initialization failed\n"), argv[0]);
exit(EXIT_FAILURE);
}
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 5352a4a..4c2f487 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -1199,9 +1199,6 @@ main(int argc, char **argv)
memset(ctl, 0, sizeof(vahControl));
- if (virRandomInitialize(time(NULL) ^ getpid()) < 0)
- vah_error(ctl, 1, _("could not initialize random generator"));
-
if (vahParseArgv(ctl, argc, argv) != 0)
vah_error(ctl, 1, _("could not parse arguments"));
diff --git a/src/util/iohelper.c b/src/util/iohelper.c
index 0732cac..4791234 100644
--- a/src/util/iohelper.c
+++ b/src/util/iohelper.c
@@ -1,7 +1,7 @@
/*
* iohelper.c: Helper program to perform I/O operations on files
*
- * Copyright (C) 2011 Red Hat, Inc.
+ * Copyright (C) 2011-2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -230,8 +230,7 @@ main(int argc, char **argv)
}
if (virThreadInitialize() < 0 ||
- virErrorInitialize() < 0 ||
- virRandomInitialize(time(NULL) ^ getpid())) {
+ virErrorInitialize() < 0) {
fprintf(stderr, _("%s: initialization failed\n"), program_name);
exit(EXIT_FAILURE);
}
diff --git a/src/util/virrandom.c b/src/util/virrandom.c
index b815ce2..50bed46 100644
--- a/src/util/virrandom.c
+++ b/src/util/virrandom.c
@@ -29,6 +29,7 @@
#include "count-one-bits.h"
#include "util.h"
#include "virterror_internal.h"
+#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -37,8 +38,21 @@ static struct random_data randomData;
static virMutex randomLock;
-int virRandomInitialize(uint32_t seed)
+static int
+virRandomOnceInit(void)
{
+ unsigned int seed = time(NULL) ^ getpid();
+
+#if 0
+ /* Normally we want a decent seed. But if reproducible debugging
+ * of a fixed pseudo-random sequence is ever required, uncomment
+ * this block to let an environment variable force the seed. */
+ const char *debug = getenv("VIR_DEBUG_RANDOM_SEED");
+
+ if (debug && virStrToLong_ui(debug, NULL, 0, &seed) < 0)
+ return -1;
+#endif
+
if (virMutexInit(&randomLock) < 0)
return -1;
@@ -51,6 +65,8 @@ int virRandomInitialize(uint32_t seed)
return 0;
}
+VIR_ONCE_GLOBAL_INIT(virRandom)
+
/* The algorithm of virRandomBits requires that RAND_MAX == 2^n-1 for
* some n; gnulib's random_r meets this property. */
verify(((RAND_MAX + 1U) & RAND_MAX) == 0);
@@ -70,6 +86,13 @@ uint64_t virRandomBits(int nbits)
uint64_t ret = 0;
int32_t bits;
+ if (virRandomInitialize() < 0) {
+ /* You're already hosed, so this particular non-random value
+ * isn't any worse. */
+ VIR_WARN("random number generation is broken");
+ return 0;
+ }
+
virMutexLock(&randomLock);
while (nbits > bits_per_iter) {
diff --git a/src/util/virrandom.h b/src/util/virrandom.h
index aa2c8b4..8d3cad7 100644
--- a/src/util/virrandom.h
+++ b/src/util/virrandom.h
@@ -25,7 +25,6 @@
# include "internal.h"
# include <stdint.h>
-int virRandomInitialize(uint32_t seed) ATTRIBUTE_RETURN_CHECK;
uint64_t virRandomBits(int nbits);
int virRandomGenerateWWN(char **wwn, const char *virt_type);
diff --git a/tests/seclabeltest.c b/tests/seclabeltest.c
index 45ab8e4..81ef323 100644
--- a/tests/seclabeltest.c
+++ b/tests/seclabeltest.c
@@ -14,8 +14,7 @@ main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
virSecurityManagerPtr mgr;
const char *doi, *model;
- if (virThreadInitialize() < 0 ||
- virRandomInitialize(time(NULL) ^ getpid()))
+ if (virThreadInitialize() < 0)
exit(EXIT_FAILURE);
mgr = virSecurityManagerNew(NULL, "QEMU", false, true, false);
diff --git a/tests/testutils.c b/tests/testutils.c
index 171321f..ecd3d2d 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -603,8 +603,7 @@ int virtTestMain(int argc,
fprintf(stderr, "TEST: %s\n", progname);
if (virThreadInitialize() < 0 ||
- virErrorInitialize() < 0 ||
- virRandomInitialize(time(NULL) ^ getpid()))
+ virErrorInitialize() < 0)
return 1;
virLogSetFromEnv();
diff --git a/tests/viratomictest.c b/tests/viratomictest.c
index 48f0d24..772fbfe 100644
--- a/tests/viratomictest.c
+++ b/tests/viratomictest.c
@@ -165,8 +165,6 @@ mymain(void)
{
int ret = 0;
- if (virRandomInitialize(time(NULL)) < 0)
- return -1;
if (virThreadInitialize() < 0)
return -1;
--
1.7.11.2