Commit 386d947e authored by Natanael Copa's avatar Natanael Copa

main/xen: fix xsa55 and xsa57 (CVE-2013-2194,CVE-2013-2195,CVE-2013-2196,CVE-2013-2211)

ref #2108
ref #2117

fixes #2111
fixes #2120
parent ab94a521
......@@ -3,7 +3,7 @@
# Maintainer: William Pitcock <nenolod@dereferenced.org>
pkgname=xen
pkgver=4.1.4
pkgrel=4
pkgrel=5
pkgdesc="Xen hypervisor"
url="http://www.xen.org/"
arch="x86 x86_64"
......@@ -27,7 +27,9 @@ source="http://bits.xensource.com/oss-xen/release/$pkgver/$pkgname-$pkgver.tar.g
xsa52-4.1.patch
xsa53-4.1.patch
xsa54.patch
xsa55-4.1.patch
xsa56.patch
xsa57-4.1.patch
xenstored.initd
xenstored.confd
......@@ -132,7 +134,9 @@ ce56f00762139cd611dfc3332b7571cf xsa41.patch
db1e5a92547c8c8ed2e1872efed99ab0 xsa52-4.1.patch
e11ae888997d11fcb91b431ebf609d4e xsa53-4.1.patch
a8393d1ec6b886ea72ffe624a04ee10a xsa54.patch
391d90e3851df0b42b2971e8b860e19a xsa55-4.1.patch
e70b9128ffc2175cea314a533a7d8457 xsa56.patch
a065178b8f5ed028b97fa51db97e41e2 xsa57-4.1.patch
6e5739dad7e2bd1b625e55ddc6c782b7 xenstored.initd
b017ccdd5e1c27bbf1513e3569d4ff07 xenstored.confd
ed262f15fb880badb53575539468646c xenconsoled.initd
......
This diff is collapsed.
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-XXXX-XXX / 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
diff --git a/extras/mini-os/console/xencons_ring.c b/extras/mini-os/console/xencons_ring.c
index 9ed3756..286c650 100644
--- a/extras/mini-os/console/xencons_ring.c
+++ b/extras/mini-os/console/xencons_ring.c
@@ -291,12 +291,6 @@ again:
goto abort_transaction;
}
- err = xenbus_printf(xbt, nodename, "type", "%s", "ioemu");
- if (err) {
- message = "writing type";
- goto abort_transaction;
- }
-
snprintf(path, sizeof(path), "%s/state", nodename);
err = xenbus_switch_state(xbt, path, XenbusStateConnected);
if (err) {
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 3c2e1b2..54f440c 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);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 7e8fcef..0628840 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -62,12 +62,13 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
}
int libxl__device_generic_add(libxl_ctx *ctx, libxl__device *device,
- char **bents, char **fents)
+ char **bents, char **fents, char **ro_fents)
{
libxl__gc gc = LIBXL_INIT_GC(ctx);
char *frontend_path, *backend_path;
xs_transaction_t t;
struct xs_permissions frontend_perms[2];
+ struct xs_permissions ro_frontend_perms[2];
struct xs_permissions backend_perms[2];
int rc;
@@ -84,21 +85,36 @@ int libxl__device_generic_add(libxl_ctx *ctx, libxl__device *device,
frontend_perms[1].id = device->backend_domid;
frontend_perms[1].perms = XS_PERM_READ;
- backend_perms[0].id = device->backend_domid;
- backend_perms[0].perms = XS_PERM_NONE;
- backend_perms[1].id = device->domid;
- backend_perms[1].perms = XS_PERM_READ;
+ ro_frontend_perms[0].id = backend_perms[0].id = device->backend_domid;
+ ro_frontend_perms[0].perms = backend_perms[0].perms = XS_PERM_NONE;
+ ro_frontend_perms[1].id = backend_perms[1].id = device->domid;
+ ro_frontend_perms[1].perms = backend_perms[1].perms = XS_PERM_READ;
retry_transaction:
t = xs_transaction_start(ctx->xsh);
/* FIXME: read frontend_path and check state before removing stuff */
- if (fents) {
+ if (fents || ro_fents) {
xs_rm(ctx->xsh, t, frontend_path);
xs_mkdir(ctx->xsh, t, frontend_path);
- xs_set_permissions(ctx->xsh, t, frontend_path, frontend_perms, ARRAY_SIZE(frontend_perms));
+ /* Console 0 is a special case. It doesn't use the regular PV
+ * state machine but also the frontend directory has
+ * historically contained other information, such as the
+ * vnc-port, which we don't want the guest fiddling with.
+ */
+ if (device->kind == DEVICE_CONSOLE && device->devid == 0)
+ xs_set_permissions(ctx->xsh, t, frontend_path,
+ ro_frontend_perms, ARRAY_SIZE(ro_frontend_perms));
+ else
+ xs_set_permissions(ctx->xsh, t, frontend_path,
+ frontend_perms, ARRAY_SIZE(frontend_perms));
xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/backend", frontend_path), backend_path, strlen(backend_path));
- libxl__xs_writev(&gc, t, frontend_path, fents);
+ if (fents)
+ libxl__xs_writev_perms(&gc, t, frontend_path, fents,
+ frontend_perms, ARRAY_SIZE(frontend_perms));
+ if (ro_fents)
+ libxl__xs_writev_perms(&gc, t, frontend_path, ro_fents,
+ ro_frontend_perms, ARRAY_SIZE(ro_frontend_perms));
}
if (bents) {
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 9cf503f..5ddd27b 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -143,6 +143,11 @@ _hidden char **libxl__xs_kvs_of_flexarray(libxl__gc *gc, flexarray_t *array, int
_hidden int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
char *dir, char **kvs);
+/* as writev but also sets the permissions on each path */
+_hidden int libxl__xs_writev_perms(libxl__gc *gc, xs_transaction_t t,
+ char *dir, char *kvs[],
+ struct xs_permissions *perms,
+ unsigned int num_perms);
_hidden int libxl__xs_write(libxl__gc *gc, xs_transaction_t t,
char *path, char *fmt, ...) PRINTF_ATTRIBUTE(4, 5);
/* Each fn returns 0 on success.
@@ -185,7 +190,7 @@ _hidden int libxl__device_physdisk_major_minor(const char *physpath, int *major,
_hidden int libxl__device_disk_dev_number(const char *virtpath);
_hidden int libxl__device_generic_add(libxl_ctx *ctx, libxl__device *device,
- char **bents, char **fents);
+ char **bents, char **fents, char **ro_fents);
_hidden char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device);
_hidden char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__device_del(libxl_ctx *ctx, libxl__device *dev, int wait);
diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
index b1d05d9..9c76bce 100644
--- a/tools/libxl/libxl_pci.c
+++ b/tools/libxl/libxl_pci.c
@@ -274,8 +274,9 @@ static int libxl_create_pci_backend(libxl__gc *gc, uint32_t domid, libxl_device_
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);
out:
if (back)
diff --git a/tools/libxl/libxl_xshelp.c b/tools/libxl/libxl_xshelp.c
index 3dc9239..06b95e0 100644
--- a/tools/libxl/libxl_xshelp.c
+++ b/tools/libxl/libxl_xshelp.c
@@ -48,8 +48,10 @@ char **libxl__xs_kvs_of_flexarray(libxl__gc *gc, flexarray_t *array, int length)
return kvs;
}
-int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
- char *dir, char *kvs[])
+int libxl__xs_writev_perms(libxl__gc *gc, xs_transaction_t t,
+ char *dir, char *kvs[],
+ struct xs_permissions *perms,
+ unsigned int num_perms)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
char *path;
@@ -63,11 +65,19 @@ int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
if (path && kvs[i + 1]) {
int length = strlen(kvs[i + 1]);
xs_write(ctx->xsh, t, path, kvs[i + 1], length);
+ if (perms)
+ xs_set_permissions(ctx->xsh, t, path, perms, num_perms);
}
}
return 0;
}
+int libxl__xs_writev(libxl__gc *gc, xs_transaction_t t,
+ char *dir, char *kvs[])
+{
+ return libxl__xs_writev_perms(gc, t, dir, kvs, NULL, 0);
+}
+
int libxl__xs_write(libxl__gc *gc, xs_transaction_t t,
char *path, char *fmt, ...)
{
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment