]> xenbits.xensource.com Git - libvirt.git/commitdiff
Introduce new API for generating random numbers
authorDaniel P. Berrange <berrange@redhat.com>
Wed, 25 Jan 2012 15:17:46 +0000 (15:17 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 26 Jan 2012 14:03:14 +0000 (14:03 +0000)
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

13 files changed:
src/Makefile.am
src/libvirt.c
src/libvirt_private.syms
src/security/security_selinux.c
src/storage/storage_backend_iscsi.c
src/test/test_driver.c
src/util/iohelper.c
src/util/util.c
src/util/util.h
src/util/uuid.c
src/util/virrandom.c [new file with mode: 0644]
src/util/virrandom.h [new file with mode: 0644]
tests/testutils.c

index a44446f4d47240ef2829be0375ceb8386bae1c49..4629700a0daba002e5cc61cd428cb26f3367044b 100644 (file)
@@ -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
 
index 8be4e13cec9920e30191ed4c4ed2ebd0bf0bd19b..e9d638bc470d4e97ec21e5e27865dfe012ce5fa4 100644 (file)
@@ -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
index 924ec16c787c7bce46dbb34e38e41bda1b0fd89c..915a43f12e9c578c232747d9c38c9c2fbb58dd71 100644 (file)
@@ -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;
index c2dcecabe15a302e31ae7a9b31ae0e3ae9b2ab9d..cb41a17c52f12c06bac84fcc96e65f04469f777d 100644 (file)
@@ -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) {
index 354f99be9ad477d9c45ace9311aec06a5f735832..6ebc6e1631a55108a91cb2d3cf7a1436c5adc4ab 100644 (file)
@@ -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);
index 55b889b148002db3f8f287f4f69f791190a5f57a..bf6b14835b3155dd9269de0acb11165517cc70fb 100644 (file)
@@ -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;
     }
 
index 93154f89454c19f690a8ef3c8279a1a77d0be30e..079419312edc7a27c15a86cdf542d61641810ba4 100644 (file)
@@ -39,6 +39,7 @@
 #include "memory.h"
 #include "virterror_internal.h"
 #include "configmake.h"
+#include "virrandom.h"
 
 #define VIR_FROM_THIS VIR_FROM_STORAGE
 
index 33bcf29317652e47b312ccb2d1554ebc97eaf162..f1c3346765796b8670269d6b850a5106579c69da 100644 (file)
@@ -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,
index 94d92828f54f5b2cc31e82de5c78fcfb6ab6d8b9..91cae47ac16010cdcf4c9121500ba3219c13c161 100644 (file)
@@ -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);
index 15ba5af181e35cf6988b3cdf281a46b3e18bcf7b..23822ec8f6194b78ca608c783d12b1170d54214a 100644 (file)
@@ -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 (file)
index 0000000..0af94d5
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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@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;
+}
+
+/*
+ * virRandomBits:
+ * @nbits: Number of bits of randommess required
+ *
+ * Generate an evenly distributed random number between [0,2^nbits), where
+ * @nbits must be in the range (0,64].
+ *
+ * Return: a random number with @nbits entropy
+ */
+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 (file)
index 0000000..eede373
--- /dev/null
@@ -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@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__ */
index acdfdc1b409db64f42c9c8580cd05297b7481bce..fccea17cf21907e4cf1ba3f4df8768c004e69c38 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * testutils.c: basic test utils
  *
- * Copyright (C) 2005-2011 Red Hat, Inc.
+ * Copyright (C) 2005-2012 Red Hat, Inc.
  *
  * See COPYING.LIB for the License of this software
  *
@@ -34,6 +34,7 @@
 #include "buf.h"
 #include "logging.h"
 #include "command.h"
+#include "virrandom.h"
 
 #if TEST_OOM_TRACE
 # include <execinfo.h>