References: bsc#979620 CVE-2016-4962 XSA-175

From 57c13510f626dc46b568e07d47870f86acb5c9ad Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 17:01:56 +0100
Subject: [PATCH 11/12] libxl: Do not trust frontend for channel in list

libxl_device_channel_list should not trust frontend-provided data.

So it needs to iterate using the /libxl paths, and read the backend
path out of /libxl.

However, it also filters out pure "consoles", which are channels
without a "name".  But the name was stored only in the frontend
directory, which the frontend can delete.

So store the name in the backend too.  (Ideally we would store it in
/libxl, where the backend can't write to it either, but
libxl__device_console_add not currently have access to the xenstore
transaction used by libxl__device_generic_add.  Protection against the
backend will come later, in XSA-178.)

Because the libxl paths are defined to be in terms of the frontend
device types, not the backend device types, it is no longer correct
for libxl__append_channel_list to take a type argument.  Abolish this
(with no functional effect).

This is part of XSA-175.

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/libxl/libxl.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

Index: xen-4.5.3-testing/tools/libxl/libxl.c
===================================================================
--- xen-4.5.3-testing.orig/tools/libxl/libxl.c
+++ xen-4.5.3-testing/tools/libxl/libxl.c
@@ -3733,6 +3733,8 @@ int libxl__device_console_add(libxl__gc
     if (console->name) {
         flexarray_append(ro_front, "name");
         flexarray_append(ro_front, console->name);
+        flexarray_append(back, "name");
+        flexarray_append(back, console->name);
     }
     if (console->connection) {
         flexarray_append(back, "connection");
@@ -3871,34 +3873,35 @@ static int libxl__device_channel_from_xs
     return rc;
 }
 
-static int libxl__append_channel_list_of_type(libxl__gc *gc,
+static int libxl__append_channel_list(libxl__gc *gc,
                                               uint32_t domid,
-                                              const char *type,
                                               libxl_device_channel **channels,
                                               int *nchannels)
 {
-    char *fe_path = NULL, *be_path = NULL;
+    char *libxl_dir_path = NULL, *be_path = NULL;
     char **dir = NULL;
     unsigned int n = 0, devid = 0;
     libxl_device_channel *next = NULL;
     int rc = 0, i;
 
-    fe_path = GCSPRINTF("%s/device/%s",
-                        libxl__xs_get_dompath(gc, domid), type);
-    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &n);
+    libxl_dir_path = GCSPRINTF("%s/device/console",
+                               libxl__xs_libxl_path(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, libxl_dir_path, &n);
     if (!dir || !n)
       goto out;
 
     for (i = 0; i < n; i++) {
-        const char *p, *name;
+        const char *libxl_path, *name;
         libxl_device_channel *tmp;
 
-        p = libxl__sprintf(gc, "%s/%s", fe_path, dir[i]);
-        name = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/name", p));
+        libxl_path = GCSPRINTF("%s/%s", libxl_dir_path, dir[i]);
+        be_path = libxl__xs_read(gc, XBT_NULL,
+                                 GCSPRINTF("%s/backend", libxl_path));
+        if (!be_path) continue;
+        name = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/name", be_path));
         /* 'channels' are consoles with names, so ignore all consoles
            without names */
         if (!name) continue;
-        be_path = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend", p));
         tmp = realloc(*channels,
                       sizeof(libxl_device_channel) * (*nchannels + devid + 1));
         if (!tmp) {
@@ -3929,7 +3932,7 @@ libxl_device_channel *libxl_device_chann
 
     *num = 0;
 
-    rc = libxl__append_channel_list_of_type(gc, domid, "console", &channels, num);
+    rc = libxl__append_channel_list(gc, domid, &channels, num);
     if (rc) goto out_err;
 
     GC_FREE;
