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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list