[Xen-devel] [PATCH, v4]: xl: randomly generate UUID''s

Gianni Tedesco
Fri, 27 Aug 2010 17:34:00 -0000

Changes since v3:
 - Fix LIBXL_UUID_BYTES on NetBSD. Note that the code assumes
   uint8_t[16] to always be interchangeable with libxl_uuid_t.
 - Return error messages when uuid_parse fails, spotted by Owen Smith
 - Implement "uuid" parameter in xl and exit with an error if parse
   fails
Changes since v2:
 - Re-based to remove orthogonal concern of UUID string formatting fixed
   in 22001:0b6f82eaaea9 "xl: make libxl_uuid2string internal to
libxenlight"
 - Incorporated Christoph Egger''s suggestions

8<---------------------------------------------------------------
This patch converts xl to randomly generate UUID''s rather than using a
dodgy time-seeded PRNG. I have ignored various suggestions so far on
auto-generation of MAC addresses and left it as a topic for a future
patch to solve. In other words the behaviour stays the same it''s just
using a true random source. This patch also implements the "uuid"
config
file parameter in xl.

Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com>

diff -r 3c4c3d48a835 tools/libxl/Makefile
--- a/tools/libxl/Makefile	Thu Aug 26 11:16:56 2010 +0100
+++ b/tools/libxl/Makefile	Fri Aug 27 18:27:27 2010 +0100
@@ -16,6 +16,9 @@ CFLAGS += -I. -fPIC
 CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest) $(CFLAGS_libxenstore)
$(CFLAGS_libblktapctl)

 LIBS = $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxenstore)
$(LDLIBS_libblktapctl) $(UTIL_LIBS)
+ifeq ($(CONFIG_Linux),y)
+LIBS += -luuid
+endif

 LIBXL_OBJS-y = osdeps.o libxl_paths.o libxl_bootloader.o
 ifeq ($(LIBXL_BLKTAP),y)
diff -r 3c4c3d48a835 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c	Thu Aug 26 11:16:56 2010 +0100
+++ b/tools/libxl/libxl.c	Fri Aug 27 18:27:27 2010 +0100
@@ -127,7 +127,7 @@ int libxl_domain_make(libxl_ctx *ctx, li
     *domid = -1;

     /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
-    memcpy(handle, info->uuid, sizeof(xen_domain_handle_t));
+    libxl_uuid_copy((libxl_uuid *)handle, &info->uuid);

     ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags,
domid);
     if (ret < 0) {
@@ -1502,8 +1502,8 @@ static int libxl_create_stubdom(libxl_ct
     memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
     c_info.hvm = 0;
     c_info.name = libxl_sprintf(&gc, "%s-dm",
_libxl_domid_to_name(&gc, info->domid));
-    for (i = 0; i < 16; i++)
-        c_info.uuid[i] = info->uuid[i];
+
+    libxl_uuid_copy(&c_info.uuid, &info->uuid);

     memset(&b_info, 0x00, sizeof(libxl_domain_build_info));
     b_info.max_vcpus = 1;
diff -r 3c4c3d48a835 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h	Thu Aug 26 11:16:56 2010 +0100
+++ b/tools/libxl/libxl.h	Fri Aug 27 18:27:27 2010 +0100
@@ -131,13 +131,7 @@
 #include <xs.h>
 #include <sys/wait.h> /* for pid_t */

-typedef uint8_t libxl_uuid[16];
-#define LIBXL_UUID_FMT
"%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
-#define LIBXL_UUID_BYTES(uuid) uuid[0], uuid[1], uuid[2], uuid[3], \
-            uuid[4], uuid[5], uuid[6], uuid[7], \
-            uuid[8], uuid[9], uuid[10], uuid[11], \
-            uuid[12], uuid[13], uuid[14], uuid[15] \
-
+#include "libxl_uuid.h"

 typedef uint8_t libxl_mac[6];

diff -r 3c4c3d48a835 tools/libxl/libxl_uuid.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxl/libxl_uuid.h	Fri Aug 27 18:27:27 2010 +0100
@@ -0,0 +1,156 @@
+/* Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *     * Neither the name of XenSource Inc. nor the names of its contributors
+ *     may be used to endorse or promote products derived from this software
+ *     without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __LIBXL_UUID_H__
+#define __LIBXL_UUID_H__
+
+#define LIBXL_UUID_FMT
"%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
+
+#if defined(__linux__)
+
+#include <uuid/uuid.h>
+
+typedef struct {
+    uuid_t uuid;
+} libxl_uuid;
+
+#define LIBXL__UUID_BYTES(uuid) uuid[0], uuid[1], uuid[2], uuid[3], \
+                                uuid[4], uuid[5], uuid[6], uuid[7], \
+                                uuid[8], uuid[9], uuid[10], uuid[11], \
+                                uuid[12], uuid[13], uuid[14], uuid[15]
+#define LIBXL_UUID_BYTES(arg) LIBXL__UUID_BYTES(((uint8_t *)arg.uuid))
+
+static inline int libxl_uuid_is_nil(libxl_uuid *uuid)
+{
+     return uuid_is_null(uuid->uuid);
+}
+
+static inline void libxl_uuid_generate(libxl_uuid *uuid)
+{
+     uuid_generate(uuid->uuid);
+}
+
+static inline void libxl_uuido_string(libxl_uuid *uuid, char *out, size_t size)
+{
+     uuid_unparse(uuid->uuid, out);
+}
+
+static inline int libxl_uuid_from_string(libxl_uuid *uuid, const char *in)
+{
+     return uuid_parse(in, uuid->uuid);
+}
+
+static inline void libxl_uuid_copy(libxl_uuid *dst, libxl_uuid *src)
+{
+     uuid_copy(dst->uuid, src->uuid);
+}
+
+static inline void libxl_uuid_clear(libxl_uuid *uuid)
+{
+     uuid_clear(uuid->uuid);
+}
+
+static inline int libxl_uuid_compare(libxl_uuid *uuid1, libxl_uuid *uuid2)
+{
+     return uuid_compare(uuid1->uuid, uuid2->uuid);
+}
+
+static inline const uint8_t *libxl_uuid_bytearray(libxl_uuid *uuid)
+{
+    return uuid->uuid;
+}
+
+#elif defined(__NetBSD__)
+
+#include <uuid.h>
+#include <string.h>
+#include <stdlib.h>
+
+typedef uuid_t libxl_uuid;
+#define LIBXL__UUID_BYTES(uuid) uuid[0], uuid[1], uuid[2], uuid[3], \
+                                uuid[4], uuid[5], uuid[6], uuid[7], \
+                                uuid[8], uuid[9], uuid[10], uuid[11], \
+                                uuid[12], uuid[13], uuid[14], uuid[15]
+#define LIBXL_UUID_BYTES(uuid) LIBXL__UUID_BYTES(((uint8_t *)uuid))
+
+static inline int libxl_uuid_is_nil(libxl_uuid *uuid)
+{
+     uint32_t status;
+     return uuid_is_nil((uuid_t *)uuid, &status);
+}
+
+static inline void libxl_uuid_generate(libxl_uuid *uuid)
+{
+     uint32_t status;
+     uuid_create((uuid_t *)uuid, &status);
+}
+
+static inline void libxl_uuido_string(libxl_uuid *uuid, char *out, size_t size)
+{
+     uint32_t status;
+     char *_out = NULL;
+     uuid_to_string((uuid_t *)uuid, &_out, &status);
+     strlcpy(out, _out, size);
+     free(_out);
+}
+
+static inline int libxl_uuid_from_string(libxl_uuid *uuid, const char *in)
+{
+    uint32_t status;
+    uuid_from_string(in, (uuid_t *)uuid, &status);
+    if ( status != uuid_s_ok )
+        return -1;
+    return 0;
+}
+
+static inline void libxl_uuid_copy(libxl_uuid *dst, libxl_uuid *src)
+{
+     memcpy((uuid_t *)dst, (uuid_t *)src, sizeof(uuid_t));
+}
+
+static inline void libxl_uuid_clear(libxl_uuid *uuid)
+{
+     memset((uuid_t *)uuid, 0, sizeof(uuid_t));
+}
+
+static inline int libxl_uuid_compare(libxl_uuid *uuid1, libxl_uuid *uuid2)
+{
+     uint32_t status;
+     return uuid_compare((uuid_t *)uuid1, (uuid_t *)uuid2, &status);
+}
+
+static inline const uint8_t *libxl_uuid_bytearray(libxl_uuid *uuid)
+{
+    return uuid;
+}
+
+#else
+
+#error "Please update libxl_uuid.h for your OS"
+
+#endif
+
+#endif /* __LIBXL_UUID_H__ */
diff -r 3c4c3d48a835 tools/libxl/xl.c
--- a/tools/libxl/xl.c	Thu Aug 26 11:16:56 2010 +0100
+++ b/tools/libxl/xl.c	Fri Aug 27 18:27:27 2010 +0100
@@ -74,8 +74,6 @@ int main(int argc, char **argv)
     argc -= optind;
     optind = 1;

-    srand(time(0));
-
     cspec = cmdtable_lookup(cmd);
     if (cspec)
         ret = cspec->cmd_impl(argc, argv);
diff -r 3c4c3d48a835 tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c	Thu Aug 26 11:16:56 2010 +0100
+++ b/tools/libxl/xl_cmdimpl.c	Fri Aug 27 18:27:27 2010 +0100
@@ -286,19 +286,12 @@ static void init_build_info(libxl_domain
     }
 }

-static void random_uuid(libxl_uuid *uuid)
-{
-    int i;
-    for (i = 0; i < 16; i++)
-        (*uuid)[i] = rand();
-}
-
 static void init_dm_info(libxl_device_model_info *dm_info,
         libxl_domain_create_info *c_info, libxl_domain_build_info *b_info)
 {
     memset(dm_info, ''\0'', sizeof(*dm_info));

-    random_uuid(&dm_info->uuid);
+    libxl_uuid_generate(&dm_info->uuid);

     dm_info->dom_name = c_info->name;
     dm_info->device_model = "qemu-dm";
@@ -325,6 +318,11 @@ static void init_dm_info(libxl_device_mo

 static void init_nic_info(libxl_device_nic *nic_info, int devnum)
 {
+    const uint8_t *r;
+    libxl_uuid uuid;
+
+    libxl_uuid_generate(&uuid);
+    r = libxl_uuid_bytearray(&uuid);
     memset(nic_info, ''\0'', sizeof(*nic_info));

     nic_info->backend_domid = 0;
@@ -335,9 +333,9 @@ static void init_nic_info(libxl_device_n
     nic_info->mac[0] = 0x00;
     nic_info->mac[1] = 0x16;
     nic_info->mac[2] = 0x3e;
-    nic_info->mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
-    nic_info->mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
-    nic_info->mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    nic_info->mac[3] = r[0] & 0x7f;
+    nic_info->mac[4] = r[1];
+    nic_info->mac[5] = r[2];
     nic_info->ifname = NULL;
     nic_info->bridge = strdup("xenbr0");
     CHK_ERRNO( asprintf(&nic_info->script, "%s/vif-bridge",
@@ -347,21 +345,26 @@ static void init_nic_info(libxl_device_n

 static void init_net2_info(libxl_device_net2 *net2_info, int devnum)
 {
+    const uint8_t *r;
+    libxl_uuid uuid;
+
+    libxl_uuid_generate(&uuid);
+    r = libxl_uuid_bytearray(&uuid);
     memset(net2_info, ''\0'', sizeof(*net2_info));

     net2_info->devid = devnum;
     net2_info->front_mac[0] = 0x00;
     net2_info->front_mac[1] = 0x16;
     net2_info->front_mac[2] = 0x3e;;
-    net2_info->front_mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX +
1.0)));
-    net2_info->front_mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX +
1.0)));
-    net2_info->front_mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX +
1.0)));
+    net2_info->front_mac[3] = 0x7f & r[0];
+    net2_info->front_mac[4] = r[1];
+    net2_info->front_mac[5] = r[2];
     net2_info->back_mac[0] = 0x00;
     net2_info->back_mac[1] = 0x16;
     net2_info->back_mac[2] = 0x3e;
-    net2_info->back_mac[3] = 1 + (int) (0x7f * (rand() / (RAND_MAX + 1.0)));
-    net2_info->back_mac[4] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
-    net2_info->back_mac[5] = 1 + (int) (0xff * (rand() / (RAND_MAX + 1.0)));
+    net2_info->back_mac[3] = 0x7f & r[3];
+    net2_info->back_mac[4] = r[4];
+    net2_info->back_mac[5] = r[5];
     net2_info->back_trusted = 1;
     net2_info->filter_mac = 1;
     net2_info->max_bypasses = 5;
@@ -604,7 +607,10 @@ static void parse_config_data(const char
         c_info->name = strdup(buf);
     else
         c_info->name = "test";
-    random_uuid(&c_info->uuid);
+
+    if (!xlu_cfg_get_string (config, "uuid", &buf) ||
+        libxl_uuid_from_string(&c_info->uuid, buf) )
+        libxl_uuid_generate(&c_info->uuid);

     if (!xlu_cfg_get_long(config, "oos", &l))
         c_info->oos = l;
@@ -1206,7 +1212,7 @@ static int preserve_domain(libxl_ctx *ct
         return 0;
     }

-    random_uuid(&new_uuid);
+    libxl_uuid_generate(&new_uuid);

     LOG("Preserving domain %d %s with suffix%s", domid,
d_config->c_info.name, stime);
     rc = libxl_domain_preserve(ctx, domid, &d_config->c_info, stime,
new_uuid);