aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl/libxl.c
diff options
context:
space:
mode:
authorIan Jackson <ian.jackson@eu.citrix.com>2013-06-27 17:27:04 +0100
committerIan Jackson <Ian.Jackson@eu.citrix.com>2013-06-27 17:27:04 +0100
commit8e49bda945b85050a3583d8a6f3831b5f14cca16 (patch)
tree85e9a42cbe34c59e3f77f32f55be1b19389acf2c /tools/libxl/libxl.c
parenta04ad70f7598336e08119f47a9b478e7adc5d529 (diff)
downloadxen-8e49bda945b85050a3583d8a6f3831b5f14cca16.tar.gz
xen-8e49bda945b85050a3583d8a6f3831b5f14cca16.tar.bz2
xen-8e49bda945b85050a3583d8a6f3831b5f14cca16.zip
libxl: Restrict permissions on PV console device xenstore nodes
Matthew Daley has observed that the PV console protocol places sensitive host state into a guest writeable xenstore locations, this includes: - The pty used to communicate between the console backend daemon and its client, allowing the guest administrator to read and write arbitrary host files. - The output file, allowing the guest administrator to write arbitrary host files or to target arbitrary qemu chardevs which include sockets, udp, ptr, pipes etc (see -chardev in qemu(1) for a more complete list). - The maximum buffer size, allowing the guest administrator to consume more resources than the host administrator has configured. - The backend to use (qemu vs xenconsoled), potentially allowing the guest administrator to confuse host software. So we arrange to make the sensitive keys in the xenstore frontend directory read only for the guest. This is safe since the xenstore permissions model, unlike POSIX directory permissions, does not allow the guest to remove and recreate a node if it has write access to the containing directory. There are a few associated wrinkles: - The primary PV console is "special". It's xenstore node is not under the usual /devices/ subtree and it does not use the customary xenstore state machine protocol. Unfortunately its directory is used for other things, including the vnc-port node, which we do not want the guest to be able to write to. Rather than trying to track down all the possible secondary uses of this directory just make it r/o to the guest. All newly created subdirectories inherit these permissions and so are now safe by default. - The other serial consoles do use the customary xenstore state machine and therefore need write access to at least the "protocol" and "state" nodes, however they may also want to use arbitrary "feature-foo" nodes (although I'm not aware of any) and therefore we cannot simply lock down the entire frontend directory. Instead we add support to libxl__device_generic_add for frontend keys which are explicitly read only and use that to lock down the sensitive keys. - Minios' console frontend wants to write the "type" node, which it has no business doing since this is a host/toolstack level decision. This fails now that the node has become read only to the PV guest. Since the toolstack already writes this node just remove the attempt to set it. This is CVE-2013-2211 / XSA-57 Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Conflicts (4.2 backport): tools/libxl/libxl.c (no vtpm, free front_ro on error in libxl__device_console_add) Conflicts (4.1 backport): extras/mini-os/console/xenbus.c tools/libxl/libxl.c tools/libxl/libxl_device.c tools/libxl/libxl_internal.h tools/libxl/libxl_pci.c tools/libxl/libxl_xshelp.c - minios code was in xencons_ring.c - many places need &gc not just gc - libxl__xs_writev path is not const - varios minor context fixups
Diffstat (limited to 'tools/libxl/libxl.c')
-rw-r--r--tools/libxl/libxl.c62
1 files changed, 38 insertions, 24 deletions
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 3c2e1b2175..54f440c749 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1036,8 +1036,9 @@ int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *dis
}
libxl__device_generic_add(ctx, &device,
- libxl__xs_kvs_of_flexarray(&gc, back, back->count),
- libxl__xs_kvs_of_flexarray(&gc, front, front->count));
+ libxl__xs_kvs_of_flexarray(&gc, back, back->count),
+ libxl__xs_kvs_of_flexarray(&gc, front, front->count),
+ NULL);
rc = 0;
@@ -1266,8 +1267,9 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
}
libxl__device_generic_add(ctx, &device,
- libxl__xs_kvs_of_flexarray(&gc, back, back->count),
- libxl__xs_kvs_of_flexarray(&gc, front, front->count));
+ libxl__xs_kvs_of_flexarray(&gc, back, back->count),
+ libxl__xs_kvs_of_flexarray(&gc, front, front->count),
+ NULL);
/* FIXME: wait for plug */
rc = 0;
@@ -1478,8 +1480,9 @@ int libxl_device_net2_add(libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net
flexarray_append(front, "1");
libxl__device_generic_add(ctx, &device,
- libxl__xs_kvs_of_flexarray(&gc, back, back->count),
- libxl__xs_kvs_of_flexarray(&gc, front, front->count));
+ libxl__xs_kvs_of_flexarray(&gc, back, back->count),
+ libxl__xs_kvs_of_flexarray(&gc, front, front->count),
+ NULL);
/* FIXME: wait for plug */
rc = 0;
@@ -1571,7 +1574,7 @@ int libxl_device_net2_del(libxl_ctx *ctx, libxl_device_net2 *net2, int wait)
int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
{
libxl__gc gc = LIBXL_INIT_GC(ctx);
- flexarray_t *front;
+ flexarray_t *front, *ro_front;
flexarray_t *back;
libxl__device device;
int rc;
@@ -1581,6 +1584,11 @@ int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_consol
rc = ERROR_NOMEM;
goto out;
}
+ ro_front = flexarray_make(16, 1);
+ if (!ro_front) {
+ rc = ERROR_NOMEM;
+ goto out;
+ }
back = flexarray_make(16, 1);
if (!back) {
rc = ERROR_NOMEM;
@@ -1607,25 +1615,27 @@ int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_consol
flexarray_append(front, "backend-id");
flexarray_append(front, libxl__sprintf(&gc, "%d", console->backend_domid));
- flexarray_append(front, "limit");
- flexarray_append(front, libxl__sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT));
- flexarray_append(front, "type");
+ flexarray_append(ro_front, "limit");
+ flexarray_append(ro_front, libxl__sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT));
+ flexarray_append(ro_front, "type");
if (console->consback == LIBXL_CONSBACK_XENCONSOLED)
- flexarray_append(front, "xenconsoled");
+ flexarray_append(ro_front, "xenconsoled");
else
- flexarray_append(front, "ioemu");
- flexarray_append(front, "output");
- flexarray_append(front, console->output);
+ flexarray_append(ro_front, "ioemu");
+ flexarray_append(ro_front, "output");
+ flexarray_append(ro_front, console->output);
+ flexarray_append(ro_front, "tty");
+ flexarray_append(ro_front, "");
if (device.devid == 0) {
if (console->build_state == NULL) {
rc = ERROR_INVAL;
goto out_free;
}
- flexarray_append(front, "port");
- flexarray_append(front, libxl__sprintf(&gc, "%"PRIu32, console->build_state->console_port));
- flexarray_append(front, "ring-ref");
- flexarray_append(front, libxl__sprintf(&gc, "%lu", console->build_state->console_mfn));
+ flexarray_append(ro_front, "port");
+ flexarray_append(ro_front, libxl__sprintf(&gc, "%"PRIu32, console->build_state->console_port));
+ flexarray_append(ro_front, "ring-ref");
+ flexarray_append(ro_front, libxl__sprintf(&gc, "%lu", console->build_state->console_mfn));
} else {
flexarray_append(front, "state");
flexarray_append(front, libxl__sprintf(&gc, "%d", 1));
@@ -1634,11 +1644,13 @@ int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_consol
}
libxl__device_generic_add(ctx, &device,
- libxl__xs_kvs_of_flexarray(&gc, back, back->count),
- libxl__xs_kvs_of_flexarray(&gc, front, front->count));
+ libxl__xs_kvs_of_flexarray(&gc, back, back->count),
+ libxl__xs_kvs_of_flexarray(&gc, front, front->count),
+ libxl__xs_kvs_of_flexarray(&gc, ro_front, ro_front->count));
rc = 0;
out_free:
flexarray_free(back);
+ flexarray_free(ro_front);
flexarray_free(front);
out:
libxl__free_all(&gc);
@@ -1693,8 +1705,9 @@ int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
flexarray_append(front, libxl__sprintf(&gc, "%d", 1));
libxl__device_generic_add(ctx, &device,
- libxl__xs_kvs_of_flexarray(&gc, back, back->count),
- libxl__xs_kvs_of_flexarray(&gc, front, front->count));
+ libxl__xs_kvs_of_flexarray(&gc, back, back->count),
+ libxl__xs_kvs_of_flexarray(&gc, front, front->count),
+ NULL);
rc = 0;
out_free:
flexarray_free(back);
@@ -1921,8 +1934,9 @@ int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
flexarray_append_pair(front, "state", libxl__sprintf(&gc, "%d", 1));
libxl__device_generic_add(ctx, &device,
- libxl__xs_kvs_of_flexarray(&gc, back, back->count),
- libxl__xs_kvs_of_flexarray(&gc, front, front->count));
+ libxl__xs_kvs_of_flexarray(&gc, back, back->count),
+ libxl__xs_kvs_of_flexarray(&gc, front, front->count),
+ NULL);
rc = 0;
out_free:
flexarray_free(front);