[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH]: xl: introduce xlu_cfg_get_(string|long)_default



The function init_dm_info() in xl_cmdimpl.c is used to initialise a
libxl_device_model_info structure with some default values. After being
called, some of those values are overridden. For the string values which
are not overwritten we either end up with a double free or attempt to
free a string literal resulting in a segfault. This type of usage model
would be complex to fix by adding strdup()'s in the init function and
then checking and freeing when over-writing.

My proposed solution is to add default versions of xlu_cfg_get_string
and xlu_cfg_get_long. This way both double-free's and leaks are avoided
and arguably the intention of the code is clearer.

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

diff -r d323c34ec982 -r aa90461b1d04 tools/libxl/libxlu_cfg.c
--- a/tools/libxl/libxlu_cfg.c  Tue Aug 31 13:30:21 2010 +0100
+++ b/tools/libxl/libxlu_cfg.c  Tue Aug 31 14:01:07 2010 +0100
@@ -151,7 +151,23 @@ int xlu_cfg_get_string(const XLU_Config 
     *value_r= set->values[0];
     return 0;
 }
-        
+
+int xlu_cfg_get_string_default(const XLU_Config *cfg, const char *n,
+                       const char **value_r, const char *def) {
+    XLU_ConfigSetting *set;
+    int e;
+
+    e= find_atom(cfg,n,&set);
+    if (e) {
+        *value_r = strdup(def);
+        if ( def && NULL == *value_r )
+            return ENOMEM;
+        return 0;
+    }
+    *value_r= set->values[0];
+    return 0;
+}
+
 int xlu_cfg_get_long(const XLU_Config *cfg, const char *n,
                      long *value_r) {
     long l;
@@ -181,6 +197,35 @@ int xlu_cfg_get_long(const XLU_Config *c
     return 0;
 }
         
+int xlu_cfg_get_long_default(const XLU_Config *cfg, const char *n,
+                     long *value_r, long def) {
+    long l;
+    XLU_ConfigSetting *set;
+    int e;
+    char *ep;
+
+    e= find_atom(cfg,n,&set);  if (e) { *value_r = def; return 0; }
+    errno= 0; l= strtol(set->values[0], &ep, 0);
+    e= errno;
+    if (errno) {
+        e= errno;
+        assert(e==EINVAL || e==ERANGE);
+        fprintf(cfg->report,
+                "%s:%d: warning: parameter `%s' could not be parsed"
+                " as a number: %s\n",
+                cfg->filename, set->lineno, n, strerror(e));
+        *value_r = def;
+        return e;
+    }
+    if (*ep || ep==set->values[0]) {
+        fprintf(cfg->report,
+                "%s:%d: warning: parameter `%s' is not a valid number\n",
+                cfg->filename, set->lineno, n);
+        return EINVAL;
+    }
+    *value_r= l;
+    return 0;
+}
 
 int xlu_cfg_get_list(const XLU_Config *cfg, const char *n,
                      XLU_ConfigList **list_r, int *entries_r) {
diff -r d323c34ec982 -r aa90461b1d04 tools/libxl/libxlutil.h
--- a/tools/libxl/libxlutil.h   Tue Aug 31 13:30:21 2010 +0100
+++ b/tools/libxl/libxlutil.h   Tue Aug 31 14:01:07 2010 +0100
@@ -46,7 +46,10 @@ void xlu_cfg_destroy(XLU_Config*);
  */
 
 int xlu_cfg_get_string(const XLU_Config*, const char *n, const char **value_r);
+int xlu_cfg_get_string_default(const XLU_Config *cfg, const char *n,
+                                const char **value_r, const char *def);
 int xlu_cfg_get_long(const XLU_Config*, const char *n, long *value_r);
+int xlu_cfg_get_long_default(const XLU_Config*, const char *n, long *value_r, 
long def);
 
 int xlu_cfg_get_list(const XLU_Config*, const char *n,
                      XLU_ConfigList **list_r /* may be 0 */,
diff -r d323c34ec982 -r aa90461b1d04 tools/libxl/xl_cmdimpl.c
--- a/tools/libxl/xl_cmdimpl.c  Tue Aug 31 13:30:21 2010 +0100
+++ b/tools/libxl/xl_cmdimpl.c  Tue Aug 31 14:01:07 2010 +0100
@@ -286,36 +286,6 @@ static void init_build_info(libxl_domain
     }
 }
 
-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));
-
-    libxl_uuid_generate(&dm_info->uuid);
-
-    dm_info->dom_name = c_info->name;
-    dm_info->device_model = "qemu-dm";
-    dm_info->videoram = b_info->video_memkb / 1024;
-    dm_info->apic = b_info->u.hvm.apic;
-    dm_info->vcpus = b_info->max_vcpus;
-    dm_info->vcpu_avail = b_info->cur_vcpus;
-
-    dm_info->stdvga = 0;
-    dm_info->vnc = 1;
-    dm_info->vnclisten = "127.0.0.1";
-    dm_info->vncdisplay = 0;
-    dm_info->vncunused = 1;
-    dm_info->keymap = NULL;
-    dm_info->sdl = 0;
-    dm_info->opengl = 0;
-    dm_info->nographic = 0;
-    dm_info->serial = NULL;
-    dm_info->boot = "cda";
-    dm_info->usb = 0;
-    dm_info->usbdevice = NULL;
-    dm_info->xen_platform_pci = 1;
-}
-
 static void init_nic_info(libxl_device_nic *nic_info, int devnum)
 {
     const uint8_t *r;
@@ -1008,22 +978,31 @@ skip_vfb:
 
     if (c_info->hvm == 1) {
         /* init dm from c and b */
-        init_dm_info(dm_info, c_info, b_info);
+        memset(dm_info, '\0', sizeof(*dm_info));
+
+        libxl_uuid_generate(&dm_info->uuid);
+        dm_info->dom_name = strdup(c_info->name);
+
+        dm_info->videoram = b_info->video_memkb / 1024;
+        dm_info->apic = b_info->u.hvm.apic;
+        dm_info->vcpus = b_info->max_vcpus;
+        dm_info->vcpu_avail = b_info->cur_vcpus;
 
         /* then process config related to dm */
-        if (!xlu_cfg_get_string (config, "device_model", &buf))
+        if (!xlu_cfg_get_string_default (config, "device_model", &buf, 
"qemu-dm"))
             dm_info->device_model = strdup(buf);
+
         if (!xlu_cfg_get_long (config, "stdvga", &l))
             dm_info->stdvga = l;
-        if (!xlu_cfg_get_long (config, "vnc", &l))
+        if (!xlu_cfg_get_long_default (config, "vnc", &l, 1))
             dm_info->vnc = l;
-        if (!xlu_cfg_get_string (config, "vnclisten", &buf))
+        if (!xlu_cfg_get_string_default (config, "vnclisten", &buf, 
"127.0.0.1"))
             dm_info->vnclisten = strdup(buf);
         if (!xlu_cfg_get_string (config, "vncpasswd", &buf))
             dm_info->vncpasswd = strdup(buf);
         if (!xlu_cfg_get_long (config, "vncdisplay", &l))
             dm_info->vncdisplay = l;
-        if (!xlu_cfg_get_long (config, "vncunused", &l))
+        if (!xlu_cfg_get_long_default (config, "vncunused", &l, 1))
             dm_info->vncunused = l;
         if (!xlu_cfg_get_string (config, "keymap", &buf))
             dm_info->keymap = strdup(buf);
@@ -1035,7 +1014,7 @@ skip_vfb:
             dm_info->nographic = l;
         if (!xlu_cfg_get_string (config, "serial", &buf))
             dm_info->serial = strdup(buf);
-        if (!xlu_cfg_get_string (config, "boot", &buf))
+        if (!xlu_cfg_get_string_default (config, "boot", &buf, "cda"))
             dm_info->boot = strdup(buf);
         if (!xlu_cfg_get_long (config, "usb", &l))
             dm_info->usb = l;
@@ -1043,7 +1022,7 @@ skip_vfb:
             dm_info->usbdevice = strdup(buf);
         if (!xlu_cfg_get_string (config, "soundhw", &buf))
             dm_info->soundhw = strdup(buf);
-        if (!xlu_cfg_get_long (config, "xen_platform_pci", &l))
+        if (!xlu_cfg_get_long_default (config, "xen_platform_pci", &l, 1))
             dm_info->xen_platform_pci = l;
     }
 



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.