diff --git a/src/Makefile.am b/src/Makefile.am index a44446f4d47240ef2829be0375ceb8386bae1c49..4629700a0daba002e5cc61cd428cb26f3367044b 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 8be4e13cec9920e30191ed4c4ed2ebd0bf0bd19b..e9d638bc470d4e97ec21e5e27865dfe012ce5fa4 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 924ec16c787c7bce46dbb34e38e41bda1b0fd89c..915a43f12e9c578c232747d9c38c9c2fbb58dd71 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 c2dcecabe15a302e31ae7a9b31ae0e3ae9b2ab9d..cb41a17c52f12c06bac84fcc96e65f04469f777d 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 354f99be9ad477d9c45ace9311aec06a5f735832..6ebc6e1631a55108a91cb2d3cf7a1436c5adc4ab 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 55b889b148002db3f8f287f4f69f791190a5f57a..bf6b14835b3155dd9269de0acb11165517cc70fb 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 93154f89454c19f690a8ef3c8279a1a77d0be30e..079419312edc7a27c15a86cdf542d61641810ba4 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 33bcf29317652e47b312ccb2d1554ebc97eaf162..f1c3346765796b8670269d6b850a5106579c69da 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 94d92828f54f5b2cc31e82de5c78fcfb6ab6d8b9..91cae47ac16010cdcf4c9121500ba3219c13c161 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 15ba5af181e35cf6988b3cdf281a46b3e18bcf7b..23822ec8f6194b78ca608c783d12b1170d54214a 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 0000000000000000000000000000000000000000..0af94d5da8b5540a254a8963bf4849cea57d7797 --- /dev/null +++ b/src/util/virrandom.c @@ -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 + */ + +#include + +#include + +#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 index 0000000000000000000000000000000000000000..eede3731c2cdd45f40c0ee34350231cb1b288245 --- /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 + */ + +#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__ */ diff --git a/tests/testutils.c b/tests/testutils.c index acdfdc1b409db64f42c9c8580cd05297b7481bce..fccea17cf21907e4cf1ba3f4df8768c004e69c38 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -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