From: "Daniel P. Berrange" <berrange(a)redhat.com>
The old virRandom() API was not generating good random numbers.
Replace it with a new API virRandomBits which instead of being
told the upper limit, gets told the number of bits of randomness
required.
* src/util/virrandom.c, src/util/virrandom.h: Add virRandomBits,
and move virRandomInitialize
* src/util/util.h, src/util/util.c: Delete virRandom and
virRandomInitialize
* src/libvirt.c, src/security/security_selinux.c,
src/test/test_driver.c, src/util/iohelper.c: Update for
changes from virRandom to virRandomBits
* src/storage/storage_backend_iscsi.c: Remove bogus call
to virRandomInitialize & convert to virRandomBits
---
src/Makefile.am | 1 +
src/libvirt.c | 2 +-
src/libvirt_private.syms | 7 ++-
src/security/security_selinux.c | 5 +-
src/storage/storage_backend_iscsi.c | 12 +----
src/test/test_driver.c | 3 +-
src/util/iohelper.c | 1 +
src/util/util.c | 37 ++----------------
src/util/util.h | 3 -
src/util/uuid.c | 3 +-
src/util/virrandom.c | 73 +++++++++++++++++++++++++++++++++++
src/util/virrandom.h | 30 ++++++++++++++
12 files changed, 125 insertions(+), 52 deletions(-)
create mode 100644 src/util/virrandom.c
create mode 100644 src/util/virrandom.h
diff --git a/src/Makefile.am b/src/Makefile.am
index a44446f..4629700 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -99,6 +99,7 @@ UTIL_SOURCES = \
util/virnetdevtap.h util/virnetdevtap.c \
util/virnetdevveth.h util/virnetdevveth.c \
util/virnetdevvportprofile.h util/virnetdevvportprofile.c \
+ util/virrandom.h util/virrandom.c \
util/virsocketaddr.h util/virsocketaddr.c \
util/virtime.h util/virtime.c
diff --git a/src/libvirt.c b/src/libvirt.c
index 722a2e2..68eec2e 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -36,7 +36,6 @@
#include "driver.h"
#include "uuid.h"
-#include "util.h"
#include "memory.h"
#include "configmake.h"
#include "intprops.h"
@@ -44,6 +43,7 @@
#include "rpc/virnettlscontext.h"
#include "command.h"
#include "virnodesuspend.h"
+#include "virrandom.h"
#ifndef WITH_DRIVER_MODULES
# ifdef WITH_TEST
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 924ec16..915a43f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1126,8 +1126,6 @@ virParseMacAddr;
virParseNumber;
virParseVersionString;
virPipeReadUntilEOF;
-virRandom;
-virRandomInitialize;
virSetBlocking;
virSetCloseExec;
virSetInherit;
@@ -1369,6 +1367,11 @@ virPidFileDelete;
virPidFileDeletePath;
+# virrandom.h
+virRandomBits;
+virRandomInitialize;
+
+
# virsocketaddr.h
virSocketAddrBroadcast;
virSocketAddrBroadcastByPrefix;
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index c2dceca..cb41a17 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -32,6 +32,7 @@
#include "hostusb.h"
#include "storage_file.h"
#include "virfile.h"
+#include "virrandom.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
@@ -216,8 +217,8 @@ SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
}
} else {
do {
- c1 = virRandom(1024);
- c2 = virRandom(1024);
+ c1 = virRandomBits(10);
+ c2 = virRandomBits(10);
if ( c1 == c2 ) {
if (virAsprintf(&mcs, "s0:c%d", c1) < 0) {
diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c
index 354f99b..6ebc6e1 100644
--- a/src/storage/storage_backend_iscsi.c
+++ b/src/storage/storage_backend_iscsi.c
@@ -42,6 +42,7 @@
#include "logging.h"
#include "virfile.h"
#include "command.h"
+#include "virrandom.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
@@ -283,15 +284,8 @@ virStorageBackendCreateIfaceIQN(const char *initiatoriqn,
initiatoriqn, NULL
};
- if (virRandomInitialize(time(NULL) ^ getpid()) == -1) {
- virStorageReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Failed to initialize random generator "
- "when creating iscsi interface"));
- goto out;
- }
-
- snprintf(temp_ifacename, sizeof(temp_ifacename), "libvirt-iface-%08x",
- virRandom(1024 * 1024 * 1024));
+ snprintf(temp_ifacename, sizeof(temp_ifacename), "libvirt-iface-%08llx",
+ (unsigned long long)virRandomBits(30));
VIR_DEBUG("Attempting to create interface '%s' with IQN
'%s'",
&temp_ifacename[0], initiatoriqn);
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index 55b889b..bf6b148 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -51,6 +51,7 @@
#include "logging.h"
#include "virfile.h"
#include "virtypedparam.h"
+#include "virrandom.h"
#define VIR_FROM_THIS VIR_FROM_TEST
@@ -5316,7 +5317,7 @@ testNodeDeviceCreateXML(virConnectPtr conn,
if (caps->type != VIR_NODE_DEV_CAP_SCSI_HOST)
continue;
- caps->data.scsi_host.host = virRandom(1024);
+ caps->data.scsi_host.host = virRandomBits(10);
caps = caps->next;
}
diff --git a/src/util/iohelper.c b/src/util/iohelper.c
index 93154f8..0794193 100644
--- a/src/util/iohelper.c
+++ b/src/util/iohelper.c
@@ -39,6 +39,7 @@
#include "memory.h"
#include "virterror_internal.h"
#include "configmake.h"
+#include "virrandom.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
diff --git a/src/util/util.c b/src/util/util.c
index c00c2f9..ada423b 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -77,6 +77,7 @@
#include "command.h"
#include "nonblocking.h"
#include "passfd.h"
+#include "virrandom.h"
#ifndef NSIG
# define NSIG 32
@@ -1853,9 +1854,9 @@ void virGenerateMacAddr(const unsigned char *prefix,
addr[0] = prefix[0];
addr[1] = prefix[1];
addr[2] = prefix[2];
- addr[3] = virRandom(256);
- addr[4] = virRandom(256);
- addr[5] = virRandom(256);
+ addr[3] = virRandomBits(8);
+ addr[4] = virRandomBits(8);
+ addr[5] = virRandomBits(8);
}
@@ -2097,36 +2098,6 @@ int virKillProcess(pid_t pid, int sig)
}
-static char randomState[128];
-static struct random_data randomData;
-static virMutex randomLock;
-
-int virRandomInitialize(unsigned int seed)
-{
- if (virMutexInit(&randomLock) < 0)
- return -1;
-
- if (initstate_r(seed,
- randomState,
- sizeof(randomState),
- &randomData) < 0)
- return -1;
-
- return 0;
-}
-
-int virRandom(int max)
-{
- int32_t ret;
-
- virMutexLock(&randomLock);
- random_r(&randomData, &ret);
- virMutexUnlock(&randomLock);
-
- return (int) ((double)max * ((double)ret / (double)RAND_MAX));
-}
-
-
#ifdef HAVE_GETPWUID_R
enum {
VIR_USER_ENT_DIRECTORY,
diff --git a/src/util/util.h b/src/util/util.h
index 94d9282..91cae47 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -242,9 +242,6 @@ int virGetUserID(const char *name,
int virGetGroupID(const char *name,
gid_t *gid) ATTRIBUTE_RETURN_CHECK;
-int virRandomInitialize(unsigned int seed) ATTRIBUTE_RETURN_CHECK;
-int virRandom(int max);
-
char *virFileFindMountPoint(const char *type);
void virFileWaitForDevices(void);
diff --git a/src/util/uuid.c b/src/util/uuid.c
index 15ba5af..23822ec 100644
--- a/src/util/uuid.c
+++ b/src/util/uuid.c
@@ -40,6 +40,7 @@
#include "logging.h"
#include "memory.h"
#include "virfile.h"
+#include "virrandom.h"
#ifndef ENODATA
# define ENODATA EIO
@@ -80,7 +81,7 @@ virUUIDGeneratePseudoRandomBytes(unsigned char *buf,
int buflen)
{
while (buflen > 0) {
- *buf++ = virRandom(256);
+ *buf++ = virRandomBits(8);
buflen--;
}
diff --git a/src/util/virrandom.c b/src/util/virrandom.c
new file mode 100644
index 0000000..b35b1f4
--- /dev/null
+++ b/src/util/virrandom.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include "virrandom.h"
+#include "threads.h"
+#include "count-one-bits.h"
+
+static char randomState[128];
+static struct random_data randomData;
+static virMutex randomLock;
+
+
+int virRandomInitialize(uint32_t seed)
+{
+ if (virMutexInit(&randomLock) < 0)
+ return -1;
+
+ if (initstate_r(seed,
+ randomState,
+ sizeof(randomState),
+ &randomData) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+uint64_t virRandomBits(int nbits)
+{
+ int bits_per_iter = count_one_bits(RAND_MAX);
+ uint64_t ret = 0;
+ int32_t bits;
+
+ /* This algorithm requires that RAND_MAX == 2^n-1 for some n;
+ gnulib's random_r meets this property. */
+ verify(((RAND_MAX + 1U) & RAND_MAX) == 0);
+
+ virMutexLock(&randomLock);
+
+ while (nbits > bits_per_iter) {
+ random_r(&randomData, &bits);
+ ret = (ret << bits_per_iter) | (bits & RAND_MAX);
+ nbits -= bits_per_iter;
+ }
+
+ random_r(&randomData, &bits);
+ ret = (ret << nbits) | (bits & ((1 << nbits) - 1));
+
+ virMutexUnlock(&randomLock);
+ return ret;
+}
diff --git a/src/util/virrandom.h b/src/util/virrandom.h
new file mode 100644
index 0000000..eede373
--- /dev/null
+++ b/src/util/virrandom.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Authors:
+ * Daniel P. Berrange <berrange(a)redhat.com>
+ */
+
+#ifndef __VIR_RANDOM_H__
+# define __VIR_RANDOM_H__
+
+# include "internal.h"
+
+int virRandomInitialize(uint32_t seed) ATTRIBUTE_RETURN_CHECK;
+uint64_t virRandomBits(int nbits);
+
+#endif /* __VIR_RANDOM_H__ */
--
1.7.7.5