* Xen Security Advisory 175 (CVE-2016-4962) - Unsanitised guest input in libxl device handling code
@ 2016-06-02 12:52 Xen.org security team
0 siblings, 0 replies; 2+ messages in thread
From: Xen.org security team @ 2016-06-02 12:52 UTC (permalink / raw)
To: xen-announce, xen-devel, xen-users, oss-security; +Cc: Xen.org security team
[-- Attachment #1: Type: text/plain, Size: 13531 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Xen Security Advisory CVE-2016-4962 / XSA-175
version 5
Unsanitised guest input in libxl device handling code
UPDATES IN VERSION 5
====================
Public release.
ISSUE DESCRIPTION
=================
Various parts of libxl device-handling code inappropriately use
information from (partially) guest controlled areas of xenstore
(principally the frontend directory
/local/domain/GUEST/device/TYPE/DEVID,
henceforth referred to as FE). The problems vary by device type:
For almost all device types (all devices except consoles and
channels), the guest has the ability to completely remove FE. This
will normally result in the virtual device no longer functioning
(which is bad for the guest and an outcome the guest could achieve
anyway). But it will also cause the device not to appear in lists of
devices, and prevent the device being properly torn down during domain
destruction (including guest reboot and migration). When such a
malicious domain is shut down, the host resources associated with the
manipulated devices may remain in use: for example, disk and nic
hotplug teardown scripts will not be run. For resources allocated in
an manner which excludes some other accesses, this can prevent the
operation of that other software on the host (for example, it can
prevent management operations on the underlying objects); for
resources are allocated in a nonexclusive manner, the guest can
consume new resources with each successive guest boot, eventually
exhausting capacity.
For all devices other than the main PV console, the guest can write
FE/backend to point to the backend of a device belonging to a
different guest. On subsequent domain removal (for example, by guest
reboot or migration) libxl uses this value with insufficient checks,
allowing libxl to be tricked into failing to tear down the device
properly.
For almost all device types the backend xenstore path and domid
returned to libxl's caller during query functions servicing the domain
are read from a guest-controlled part of xenstore. This means that a
guest can cause incorrect displays in tools like xl, and possibly
cause maloperation by higher-level domain management systems.
For all device types, libxl would read the guest-writeable FE/backend
node to find the xenstore path to the backend. A guest could write a
bad value, which would (mostly) be detected by libxl but would cause
libxl operations (including informational functions) to fail.
For consoles, vtpm and channel devices, libxl would use FE/backend
without checking, to discover important information about the device.
For vtpm devices, this means guest can manipulate the
apparently-configured uuid. For channel devices, the guest can
manipulate the apparently-configured channel name.
For channel devices, the guest can trick console attachment tools in
the backend domain into connecting to arbitrary wrong paths on the
backend domain filesystem.
IMPACT
======
A malicious guest administrator can cause denial of service by
resource exhaustion.
A malicious guest administrator can confuse and/or deny service to
management facilities.
A malicious guest administrator of a guest configured with channel
devices may be able to escalate their privilege to that of the backend
domain (i.e., normally, to that of the host).
VULNERABLE SYSTEMS
==================
Xen systems using libxl based toolstacks (for example xl or libvirt
with the libxl driver) are vulnerable to denial of service to guests
and administrators.
Xen systems with guests configured with channel devices are possibly
vulnerable to privilege escalation by those guests.
(Channel devices are be configured with "channel=" in the xl domain
configuration file. See
http://xenbits.xen.org/docs/4.6-testing/misc/channel.txt
for more information.)
MITIGATION
==========
Disabling channel devices in applicable guests will reduce the
impact of the vulnerability.
Limiting the frequency with which a guest is able to reboot, or
limiting or eliminating a guest's ability to be granted exclusive
access to host resources, will reduce the resource exhaustion impact.
CREDITS
=======
This issue was discovered by Wei Liu from Citrix.
RESOLUTION
==========
Applying the appropriate attached patch resolves this issue.
xsa175-unstable/*.patch xen-unstable
xsa175-4.6/*.patch xen-4.6
xsa175-4.5/*.patch xen-4.5
xsa175-4.4/*.patch xen-4.4
$ sha256sum xsa175-*/*
473fdf33f6f26c0655b504e2cc384c20904bcdd713fbacc4236f499a0a6f8ac3 xsa175-unstable/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch
531b2233581d847f26eeffc5fa7c1428a2f42336aed7943165da881003d4be90 xsa175-unstable/0002-libxl-Provide-libxl__backendpath_parse_domid.patch
cfb45654444a95e80a2b9608448b1092f407b9a9d52436ce49c45978e5e8c310 xsa175-unstable/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch
361cc95707bba9b1801e4972016ca61ab6d8103f93b0141758112eaa61d9113d xsa175-unstable/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch
f21e63a17728e638d4e33e074e5a35fa9eb18f13c0051d9bef0d7849b60de649 xsa175-unstable/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch
0fe8d5e65103a9fc2b54692726ab66ddf4004a641e5b6730ee97c7b1621d6543 xsa175-unstable/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch
dd06e96c10c51829d7489c72d2560a9bbd12dbd727a0bb492810b334d0623296 xsa175-unstable/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch
64e56d387e418082dbd0088a012e263abda0d452a77ff7c2273cb7425d45fc60 xsa175-unstable/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch
6e3b59ac930d5210032bf1015782c14bc94881e8734e451e3d5f0c3e794f4d34 xsa175-unstable/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch
2c9a23f859bf8ecd1800089ca7f9032b24311a90c4cfe38f2a26f5ee6a8443c6 xsa175-unstable/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch
43d39d6544893c76a91c056543d46a0bfa32cf2891d234815b6a3d43d87fa5ef xsa175-unstable/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch
82da838f3daff7f225426b6572e7f7577e821f3546bb1d2ddafd72fbc8839a0d xsa175-unstable/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch
e732be8fae0d7c7de487a6a7ab919f2b91005067ce2dcf7083195fb74e2943de xsa175-unstable/0013-libxl-Do-not-trust-frontend-for-vusb.patch
c44dcbf52358b8747c922257cad3d03cc056ecc03ecd396e50f6b3f6d1cea798 xsa175-4.6/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch
fd11a983dc1f125901daaa9c9019edb46c3d16a9371399a6e9c9ef4a23b54276 xsa175-4.6/0002-libxl-Provide-libxl__backendpath_parse_domid.patch
f50f7156dc5595d1d1839c225ac8c4bd767511bc6ce4aec5f60b9ab207ea7631 xsa175-4.6/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch
09b2faa98ec3db11142c17fd4d9e055505f4552ff43e48da4d30ebcbf6b929f4 xsa175-4.6/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch
4fa05ee839da5bae49e4b403a2d13da802e10f7aa586007da89e73c6fd6719b7 xsa175-4.6/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch
92f423b541e9447f0bf37a83bbece2cfe198b1db33ca02cd3f6ca17bad203f2f xsa175-4.6/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch
97fb68eda21ab0151e6e240ddde34da0da0e8f11ea448f4603d7ef2326acda70 xsa175-4.6/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch
9cde88602e13c2964307fa1bc5b1601dc6796d4b9d9b9e49898e1d13470c71ab xsa175-4.6/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch
69a19ee15ad266e391b4356a2f6ad3442a905cd06441921ae4e2c2778823f8ae xsa175-4.6/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch
51fadcafa1549201d6dd4eda9c3f8b9d2c7cad6851f2aafe3569ec3980c5a256 xsa175-4.6/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch
dc925af06451392d87f8750b3be2ad60b95be107f2534391063732f1e1b5109a xsa175-4.6/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch
57211890bf71f7648f5b3f7a88f79fddb7d3077eb3a1bc3cbd6f910fa324dfd1 xsa175-4.6/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch
a262c85f9145f71df512338ef1a4b77c05086a894d58ba3d911ea6984bbeaed5 xsa175-4.5/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch
676806c5713a60f113264298c48c3ac34e3370a6bfb8628d5b8700edfe2415e3 xsa175-4.5/0002-libxl-Provide-libxl__backendpath_parse_domid.patch
50518f86aedf7857ca3644a2f073745017d12263880990cb7f0d4b3b9e264ac5 xsa175-4.5/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch
e9207a4a35c13061b502935a31ad09cf4ca8048804f1a62d1c1ccfde5ff3432c xsa175-4.5/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch
78baa5268af36baa546e4cd8e7f62d830c860ee3051bba5273266ca0f95627ae xsa175-4.5/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch
c59be732bbf602d7d3b5dcbf3a0ca86d6f624585ba2e29f8d0f82c74f7bd33a3 xsa175-4.5/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch
5c1aa2cc37240cdc4dce5c5067f18c36466d9271ab81c6a7a38d8674b534cd86 xsa175-4.5/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch
020287ae99d9c049c12087d828ea2d898686ab8600c0f9f8f2042b297ebc968e xsa175-4.5/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch
4781d673403b3bb0f43196af1aec52f8769bcf7352afd239d874f381a1d0e9cc xsa175-4.5/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch
c6a0fb210488794188924a90df4450e42782f99651b7a016e072a7df7d26d3d6 xsa175-4.5/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch
3f3eec4f45925a9de39fcfd14e7709b3fc8245425b8ae45213afee1ede2b09a0 xsa175-4.5/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch
084b0054f223addeab3ff951ac1362b7d48379ddf0556eae9971f1a87507c2d4 xsa175-4.5/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch
cefe2c82a30227b6538c6924d7d939192be3c481e48ac94c82f4c51f60388570 xsa175-4.4/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch
f24b26891fac4e8bf8a0939a5b64fc7ad096ef699f1882aad6e96cf81b85fc3e xsa175-4.4/0002-libxl-Provide-libxl__backendpath_parse_domid.patch
748ea9d369b1f8372d1a4c420e6a9d90f881b7142e7913ed5d72b99c07ac11a0 xsa175-4.4/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch
9f4011a48b01a36087e019f2c4bcdea91c8f2dabce5bd6b9a4cb7fd70f343c50 xsa175-4.4/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch
012c86146bbb67c2bb9424ba76294e6c6eca033d932d543e0e58f83e91d79e7b xsa175-4.4/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch
be5665c91b0dfd79c8c4bb35d5adfb719ab23a547479a14aacac9d5f46d77a0f xsa175-4.4/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch
9068b9025ad079d1ec1cacc399a72b5dc1836894683b2545274e8b19b795cd60 xsa175-4.4/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch
b57f96af3c1cac5f56a684afe223b4a977c144daf8d5f2a1e184697cd29fdbe2 xsa175-4.4/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch
c8941fcf41edae75fa5a1b417d9b457fdd67a5531b6cf75dc16da9d63697c61f xsa175-4.4/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch
0641b38b7718d5fa84a8ce12a2bf034273caeb1e372f48b73170b3fd085f169c xsa175-4.4/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch
$
NOTE REGARDING EMBARGO LENGTH
=============================
Due to the complexity and centrality of the set of patches, the
security team suggested a three-week embargo rather than the normal
two-week embargo, and the discoverer agreed.
Please do your best to test these patches as thoroughly and as early
as possible, and report any problems.
DEPLOYMENT DURING EMBARGO
=========================
Deployment of patches or mitigations not explicitly allowed below is
NOT permitted (except where all the affected systems and VMs are
administered and used only by organisations which are members of the
Xen Project Security Issues Predisclosure List). Specifically,
deployment on public cloud systems is NOT permitted.
This is because the patches and mitigations result in guest-visible
changes in the information recorded in xenstore, which might lead a
guest administrator to understand the nature of the vulnerability.
Deployment is permitted only AFTER the embargo ends.
HOWEVER, deployment of the following IS is permitted during the
embargo, even on public-facing systems with untrusted guest users and
administrators:
* The patches for XSA-175 EXCEPT for the one patch
libxl: Do not trust frontend for channel in list
* The mitigation of limiting reboot frequency
In any case: Distribution of updated software is prohibited (except to
other members of the predisclosure list).
Predisclosure list members who wish to deploy significantly different
patches and/or mitigations, please contact the Xen Project Security
Team.
(Note: this during-embargo deployment notice is retained in
post-embargo publicly released Xen Project advisories, even though it
is then no longer applicable. This is to enable the community to have
oversight of the Xen Project Security Team's decisionmaking.)
For more information about permissible uses of embargoed information,
consult the Xen Project community's agreed Security Policy:
http://www.xenproject.org/security-policy.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)
iQEcBAEBAgAGBQJXUCvtAAoJEIP+FMlX6CvZS7QIAMAUfcPHE/j8eqXCjoToYAfq
/VjLuEaUgHwSeWcsXhJ78p74uCuKty17VUeNQ2A9JZIISiAVbai51Ms4RZsCxYeK
G3XVf8bHZDiLhCS/AaFjS2AMrE/ulV+m5LRd4U0YTykf392s/hT9VKQkdkZh6ryu
S206cu2rDgmABI9mvzDQlhTfgS3Efe7SFmHq63swYzN4CwuKKbdd7EdFuHUio3Qq
QewtQ1UNORTR84vKfiNY/4Bd6Fhwl/0JU5kYKlPskzuM1ItN8wa5E3aou/0S7Cv4
vE0c7oXfIJKyf5zcxBI6T/VJXN3zyM+pAj3i0Hdn6LczRR2kAEnkp60MMr17ICE=
=GCRC
-----END PGP SIGNATURE-----
[-- Attachment #2: xsa175-unstable/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch --]
[-- Type: application/octet-stream, Size: 7592 bytes --]
From c4fa93745a68a8f6bdf8959cda4802907b3cfdcd Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 15:50:01 +0100
Subject: [PATCH 01/34] libxl: Record backend/frontend paths in /libxl/$DOMID
This gives us a record of all the backends we have set up for a
domain, which is separate from the frontends in
/local/domain/$DOMID/device.
In particular:
1. A guest has write permission for the frontend path:
/local/domain/$DOMID/device/$KIND/$DEVID
which means that the guest can completely delete the frontend.
(They can't recreate it because they don't have write permission
on the containing directory.)
2. A guest has write permission for the backend path recorded in the
frontend, ie, it can write to
/local/domain/$DOMID/device/$KIND/$DEVID/backend
which means that the guest can break the association between
frontend and backend.
So we can't rely on iterating over the frontends to find all the
backends, or examining a frontend to discover how a device is
configured.
So, have libxl__device_generic_add record the frontend and backend
paths in /libxl/$DOMID/device, and have libxl__device_destroy remove
them again.
Create the containing directory /libxl/GUEST/device in
libxl__domain_make. The already existing xs_rm in devices_destroy_cb
will take care of removing it.
This is part of XSA-175.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v2: Correct actual path computation (!)
v3: Correct actual path computation - really this time (!)
---
docs/misc/xenstore-paths.markdown | 15 +++++++++++++++
tools/libxl/libxl_create.c | 2 ++
tools/libxl/libxl_device.c | 36 ++++++++++++++++++++++++++++++++++--
tools/libxl/libxl_internal.h | 1 +
4 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index 2a37dae..2f545c1 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -534,6 +534,21 @@ The guest's virtual time offset from UTC in seconds.
### libxl Specific Paths
+#### /libxl/$DOMID/device/$KIND/$DEVID
+
+Created by libxl for every frontend/backend pair created for $DOMID.
+Used by libxl for enumeration and management of the device.
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/frontend
+
+Path in xenstore to the frontend, normally
+/local/domain/$DOMID/device/$KIND/$DEVID
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/backend
+
+Path in xenstore to the backend, normally
+/local/domain/$BACKEND_DOMID/backend/$KIND/$DOMID/$DEVID
+
#### /libxl/$DOMID/dm-version ("qemu\_xen"|"qemu\_xen\_traditional") = [n,INTERNAL]
The device model version for a domain.
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 5000bd0..703b4ea 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -617,6 +617,8 @@ retry_transaction:
xs_rm(ctx->xsh, t, libxl_path);
libxl__xs_mknod(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));
+ libxl__xs_mknod(gc, t, GCSPRINTF("%s/device", libxl_path),
+ noperm, ARRAY_SIZE(noperm));
xs_write(ctx->xsh, t, GCSPRINTF("%s/vm", dom_path), vm_path, strlen(vm_path));
rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index f79e536..b4bd005 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -40,6 +40,15 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
device->domid, device->devid);
}
+char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device)
+{
+ char *libxl_dom_path = libxl__xs_libxl_path(gc, device->domid);
+
+ return GCSPRINTF("%s/device/%s/%d", libxl_dom_path,
+ libxl__device_kind_to_string(device->kind),
+ device->devid);
+}
+
/* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
libxl__device *device)
@@ -105,14 +114,16 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- char *frontend_path, *backend_path;
+ char *frontend_path, *backend_path, *libxl_path;
struct xs_permissions frontend_perms[2];
struct xs_permissions ro_frontend_perms[2];
struct xs_permissions backend_perms[2];
int create_transaction = t == XBT_NULL;
+ int rc;
frontend_path = libxl__device_frontend_path(gc, device);
backend_path = libxl__device_backend_path(gc, device);
+ libxl_path = libxl__device_libxl_path(gc, device);
frontend_perms[0].id = device->domid;
frontend_perms[0].perms = XS_PERM_NONE;
@@ -127,8 +138,22 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
retry_transaction:
if (create_transaction)
t = xs_transaction_start(ctx->xsh);
+
/* FIXME: read frontend_path and check state before removing stuff */
+ rc = libxl__xs_rm_checked(gc, t, libxl_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/frontend",libxl_path),
+ frontend_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/backend",libxl_path),
+ backend_path);
+ if (rc) goto out;
+
+ /* xxx much of this function lacks error checks! */
+
if (fents || ro_fents) {
xs_rm(ctx->xsh, t, frontend_path);
xs_mkdir(ctx->xsh, t, frontend_path);
@@ -174,6 +199,11 @@ retry_transaction:
}
}
return 0;
+
+ out:
+ if (create_transaction && t)
+ libxl__xs_transaction_abort(gc, &t);
+ return rc;
}
typedef struct {
@@ -649,6 +679,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
{
const char *be_path = libxl__device_backend_path(gc, dev);
const char *fe_path = libxl__device_frontend_path(gc, dev);
+ const char *libxl_path = libxl__device_libxl_path(gc, dev);
const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params");
const char *tapdisk_params;
xs_transaction_t t = 0;
@@ -669,9 +700,10 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
if (domid == LIBXL_TOOLSTACK_DOMID) {
/*
* The toolstack domain is in charge of removing the
- * frontend path.
+ * frontend and libxl paths.
*/
libxl__xs_path_cleanup(gc, t, fe_path);
+ libxl__xs_path_cleanup(gc, t, libxl_path);
}
if (dev->backend_domid == domid) {
/*
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index c791418..2cb8133 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1182,6 +1182,7 @@ _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, 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 char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
--
2.1.4
[-- Attachment #3: xsa175-unstable/0002-libxl-Provide-libxl__backendpath_parse_domid.patch --]
[-- Type: application/octet-stream, Size: 2228 bytes --]
From 0612cda6977ac22cc8c71d3e624a86d3cfcaf019 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:34:19 +0100
Subject: [PATCH 02/34] libxl: Provide libxl__backendpath_parse_domid
Multiple places in libxl need to figure out the backend domid of a
device. This can be discovered easily by looking at the backend path,
which always starts /local/domain/$backend_domid/.
There are no call sites yet.
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_device.c | 15 +++++++++++++++
tools/libxl/libxl_internal.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index b4bd005..9f115c6 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -298,6 +298,21 @@ static int disk_try_backend(disk_try_backend_args *a,
return 0;
}
+int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out) {
+ int r;
+ unsigned int domid_sc;
+ char delim_sc;
+
+ r = sscanf(be_path, "/local/domain/%u%c", &domid_sc, &delim_sc);
+ if (!(r==2 && delim_sc=='/')) {
+ LOG(ERROR, "internal error: backend path %s unparseable!", be_path);
+ return ERROR_FAIL;
+ }
+ *domid_out = domid_sc;
+ return 0;
+}
+
int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
libxl_disk_backend ok;
disk_try_backend_args a;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 2cb8133..9f381fb 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -702,6 +702,8 @@ _hidden char **libxl__xs_directory(libxl__gc *gc, xs_transaction_t t,
/* On error: returns NULL, sets errno (no logging) */
_hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid);
+_hidden int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out);
/*----- "checked" xenstore access functions -----*/
/* Each of these functions will check that it succeeded; if it
--
2.1.4
[-- Attachment #4: xsa175-unstable/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]
From 092c134ab57de7a1eb6bb6032c3de89c1d5e790a Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 18:39:36 +0100
Subject: [PATCH 03/34] libxl: Do not trust frontend in libxl__devices_destroy
We need to enumerate the devices we have provided to a domain, without
trusting the guest-writeable (or, at least, guest-deletable) frontend
paths.
Instead, enumerate via, and read the backend path from, /libxl.
The console /libxl path is regular, so the special case for console 0
is not relevant any more: /libxl/GUEST/device/console/0 will be found,
and then libxl__device_destroy will DTRT to the right frontend path.
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_device.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 9f115c6..16384f8 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -762,7 +762,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
libxl__multidev_begin(ao, multidev);
multidev->callback = devices_remove_callback;
- path = GCSPRINTF("/local/domain/%d/device", domid);
+ path = GCSPRINTF("/libxl/%d/device", domid);
kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
if (!kinds) {
if (errno != ENOENT) {
@@ -775,12 +775,12 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
if (libxl__device_kind_from_string(kinds[i], &kind))
continue;
- path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]);
+ path = GCSPRINTF("/libxl/%d/device/%s", domid, kinds[i]);
devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries);
if (!devs)
continue;
for (j = 0; j < num_dev_xsentries; j++) {
- path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend",
+ path = GCSPRINTF("/libxl/%d/device/%s/%s/backend",
domid, kinds[i], devs[j]);
path = libxl__xs_read(gc, XBT_NULL, path);
GCNEW(dev);
@@ -809,22 +809,6 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
}
}
- /* console 0 frontend directory is not under /local/domain/<domid>/device */
- path = GCSPRINTF("/local/domain/%d/console/backend", domid);
- path = libxl__xs_read(gc, XBT_NULL, path);
- GCNEW(dev);
- if (path && strcmp(path, "") &&
- libxl__parse_backend_path(gc, path, dev) == 0) {
- dev->domid = domid;
- dev->kind = LIBXL__DEVICE_KIND_CONSOLE;
- dev->devid = 0;
-
- /* Currently console devices can be destroyed synchronously by just
- * removing xenstore entries, this is what libxl__device_destroy does.
- */
- libxl__device_destroy(gc, dev);
- }
-
out:
libxl__multidev_prepared(egc, multidev, rc);
}
--
2.1.4
[-- Attachment #5: xsa175-unstable/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch --]
[-- Type: application/octet-stream, Size: 1388 bytes --]
From b23d6cd8fe57c1753bfed3fc1305bca7a9c645f0 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 4 May 2016 15:30:32 +0100
Subject: [PATCH 04/34] libxl: Do not trust frontend in libxl__device_nextid
When selecting the devid for a new device, we should look in
/libxl/device for existing devices, not in the frontend area.
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 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index c39d745..1e538c3 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1986,15 +1986,16 @@ out:
/* common function to get next device id */
int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
{
- char *dompath, **l;
+ char *libxl_dom_path, **l;
unsigned int nb;
int nextid = -1;
- if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
return nextid;
l = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/device/%s", dompath, device), &nb);
+ GCSPRINTF("%s/device/%s", libxl_dom_path, device),
+ &nb);
if (l == NULL || nb == 0)
nextid = 0;
else
--
2.1.4
[-- Attachment #6: xsa175-unstable/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch --]
[-- Type: application/octet-stream, Size: 3817 bytes --]
From b2b5150f0a90103c6df34b47eca7bb92bc3d2b87 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:08:49 +0100
Subject: [PATCH 05/34] libxl: Do not trust frontend for disk eject event
Use the /libxl path for interpreting disk eject watch events: do not
read the backend path out of the frontend. Instead, use the version
in /libxl. That avoids us relying on the guest-modifiable
$frontend/backend pointer.
To implement this we store the path
/libxl/$guest/device/vbd/$devid/backend
in the evgen structure.
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 | 26 +++++++++++++++++++++-----
tools/libxl/libxl_internal.h | 2 +-
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 1e538c3..2dc82f8 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1312,9 +1312,10 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
const char *wpath, const char *epath) {
EGC_GC;
libxl_evgen_disk_eject *evg = (void*)w;
- char *backend;
+ const char *backend;
char *value;
char backend_type[BACKEND_STRING_SIZE+1];
+ int rc;
value = libxl__xs_read(gc, XBT_NULL, wpath);
@@ -1330,9 +1331,16 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
libxl_device_disk *disk = &ev->u.disk_eject.disk;
- backend = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%.*s/backend", (int)strlen(wpath)-6,
- wpath));
+ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
+ if (rc) {
+ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+ if (!backend) {
+ /* device has been removed, not simply ejected */
+ return;
+ }
sscanf(backend,
"/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
@@ -1381,11 +1389,18 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
if (!domid)
domid = guest_domid;
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+
path = GCSPRINTF("%s/device/vbd/%d/eject",
libxl__xs_get_dompath(gc, domid),
- libxl__device_disk_dev_number(vdev, NULL, NULL));
+ devid);
if (!path) { rc = ERROR_NOMEM; goto out; }
+ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid),
+ devid);
+ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
+
rc = libxl__ev_xswatch_register(gc, &evg->watch,
disk_eject_xswatch_callback, path);
if (rc) goto out;
@@ -1412,6 +1427,7 @@ void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
libxl__ev_xswatch_deregister(gc, &evg->watch);
free(evg->vdev);
+ free(evg->be_ptr_path);
free(evg);
CTX_UNLOCK;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 9f381fb..7dc702c 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -360,7 +360,7 @@ struct libxl__evgen_disk_eject {
uint32_t domid;
LIBXL_LIST_ENTRY(libxl_evgen_disk_eject) entry;
libxl_ev_user user;
- char *vdev;
+ char *vdev, *be_ptr_path;
};
_hidden void
libxl__evdisable_disk_eject(libxl__gc*, libxl_evgen_disk_eject*);
--
2.1.4
[-- Attachment #7: xsa175-unstable/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 3315 bytes --]
From d90149b39f8cdcfe0ddfc73148ece38ba6ab0f05 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Fri, 29 Apr 2016 19:21:51 +0100
Subject: [PATCH 06/34] libxl: Do not trust frontend for disk in getinfo
* Rename the frontend variable to `fe_path' to check we caught them all
* Read the backend path from /libxl, rather than from the frontend
* Parse the backend domid from the backend path, rather than reading it
from the frontend (and add the appropriate error path and initialisation)
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 | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 2dc82f8..191c939 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2849,27 +2849,34 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk, libxl_diskinfo *diskinfo)
{
GC_INIT(ctx);
- char *dompath, *diskpath;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
+
+ diskinfo->backend = NULL;
dompath = libxl__xs_get_dompath(gc, domid);
diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
/* tap devices entries in xenstore are written as vbd devices. */
- diskpath = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid), diskinfo->devid);
diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", diskpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!diskinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", diskpath));
- diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", diskpath));
+ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
+ &diskinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
GCSPRINTF("%s/frontend", diskinfo->backend), NULL);
@@ -2878,6 +2885,10 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
GC_FREE;
return 0;
+
+ out:
+ free(diskinfo->backend);
+ return rc;
}
int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
--
2.1.4
[-- Attachment #8: xsa175-unstable/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch --]
[-- Type: application/octet-stream, Size: 2378 bytes --]
From 33194a0226ecd1db19cfb54bb635774e5934cff9 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:58:32 +0100
Subject: [PATCH 07/34] libxl: Do not trust frontend for vtpm list
libxl_device_vtpm_list needs to enumerate and identify devices without
trusting frontend-controlled data. So
* Use the /libxl path to enumerate vtpms.
* Use the /libxl path to find the corresponding backends.
* Parse the backend path to find the backend domid.
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 | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 191c939..07a0fec 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2176,14 +2176,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
GC_INIT(ctx);
libxl_device_vtpm* vtpms = NULL;
- char* fe_path = NULL;
+ char *libxl_path;
char** dir = NULL;
unsigned int ndirs = 0;
+ int rc;
*num = 0;
- fe_path = GCSPRINTF("%s/device/vtpm", libxl__xs_get_dompath(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+ libxl_path = GCSPRINTF("%s/device/vtpm", libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);
if (dir && ndirs) {
vtpms = malloc(sizeof(*vtpms) * ndirs);
libxl_device_vtpm* vtpm;
@@ -2192,16 +2193,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
char* tmp;
const char* be_path = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/%s/backend",
- fe_path, *dir));
+ libxl_path, *dir));
libxl_device_vtpm_init(vtpm);
vtpm->devid = atoi(*dir);
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/%s/backend-id",
- fe_path, *dir));
- vtpm->backend_domid = atoi(tmp);
+ rc = libxl__backendpath_parse_domid(gc, be_path,
+ &vtpm->backend_domid);
+ if (rc) return NULL;
tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
if (tmp) {
--
2.1.4
[-- Attachment #9: xsa175-unstable/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2100 bytes --]
From af52263d7077950b070af6d83e9c47594a0e1267 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:00:20 +0100
Subject: [PATCH 08/34] libxl: Do not trust frontend for vtpm in getinfo
libxl_device_vtpm_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 07a0fec..8c9cab1 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2225,7 +2225,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
libxl_vtpminfo *vtpminfo)
{
GC_INIT(ctx);
- char *dompath, *vtpmpath;
+ char *libxl_path, *dompath, *vtpmpath;
char *val;
int rc = 0;
@@ -2234,8 +2234,10 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
vtpminfo->devid = vtpm->devid;
vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vtpm/%d",
+ libxl__xs_libxl_path(gc, domid), vtpminfo->devid);
vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", vtpmpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!vtpminfo->backend) {
goto err;
}
@@ -2243,9 +2245,9 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
goto err;
}
- val = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/backend-id", vtpmpath));
- vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
+ &vtpminfo->backend_id);
+ if (rc) goto exit;
val = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/state", vtpmpath));
--
2.1.4
[-- Attachment #10: xsa175-unstable/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch --]
[-- Type: application/octet-stream, Size: 1440 bytes --]
From 9e703fd22bec87b54b5408c8c5559276b36eda61 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:52:53 +0100
Subject: [PATCH 09/34] libxl: Do not trust frontend for nic in
libxl_devid_to_device_nic
Find the backend by reading the pointer in /libxl rather than in the
guest's frontend area.
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 | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 8c9cab1..1ad4536 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3628,16 +3628,16 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_nic *nic)
{
GC_INIT(ctx);
- char *dompath, *path;
+ char *libxl_dom_path, *path;
int rc = ERROR_FAIL;
libxl_device_nic_init(nic);
- dompath = libxl__xs_get_dompath(gc, domid);
- if (!dompath)
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ if (!libxl_dom_path)
goto out;
path = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/device/vif/%d/backend", dompath,
+ GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path,
devid));
if (!path)
goto out;
--
2.1.4
[-- Attachment #11: xsa175-unstable/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2553 bytes --]
From 2cf4309a404d6ccd4d7df91ad43eb16b3b6ce1d8 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:31:07 +0100
Subject: [PATCH 10/34] libxl: Do not trust frontend for nic in getinfo
libxl_device_nic_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 1ad4536..9aa9aa9 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3717,21 +3717,26 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic, libxl_nicinfo *nicinfo)
{
GC_INIT(ctx);
- char *dompath, *nicpath;
+ char *dompath, *nicpath, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
nicinfo->devid = nic->devid;
nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vif/%d",
+ libxl__xs_libxl_path(gc, domid), nicinfo->devid);
nicinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", nicpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!nicinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", nicpath));
- nicinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, nicinfo->backend,
+ &nicinfo->backend_id);
+ if (rc) goto out;
+
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath));
nicinfo->state = val ? strtoul(val, NULL, 10) : -1;
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", nicpath));
@@ -3745,8 +3750,10 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/frontend-id", nicinfo->backend));
nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
const char *libxl__device_nic_devname(libxl__gc *gc,
--
2.1.4
[-- Attachment #12: xsa175-unstable/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch --]
[-- Type: application/octet-stream, Size: 4154 bytes --]
From 96db81f1f16fdcf132055141ad8d17aa608a2a15 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/34] 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(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 9aa9aa9..b16a097 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3814,6 +3814,8 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
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");
@@ -3952,34 +3954,35 @@ static int libxl__device_channel_from_xs_be(libxl__gc *gc,
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 = GCSPRINTF("%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) {
@@ -4010,7 +4013,7 @@ libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
*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;
--
2.1.4
[-- Attachment #13: xsa175-unstable/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 4791 bytes --]
From 7ff4b30568f6202e1b505b49120bbced3cfafac7 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 17:24:32 +0100
Subject: [PATCH 12/34] libxl: Do not trust frontend for channel in getinfo
libxl_device_channel_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
* Tolerate FRONTEND/tty vanishing.
Note that there is a strange off-by-one error in the computation of
both fe_path and libxl_path in libxl_device_channel_getinfo: the
incoming channel->devid, which is copied to channelinfo->devid, has +1
applied to calculate the frontend path (and, after this patch, the
libxl path). I.e., the devid passed to libxl_device_channel_getinfo
must be one less than the actual devid for the device being asked
about.
This is actually a bug which mirrors a bug in
libxl__append_channel_list, which fills in the devids of the channel
devices it finds with sequentially increasing numbers starting at 0.
In the usual case channels have real devids starting at 1 (because
there is the console, which is devid 0, but not a channel). So these
bugs usually cancel out.
We do not address this problem at this time. This bug does not have
any security implications.
This patch 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 | 39 ++++++++++++++++++++++++++++++++++-----
1 file changed, 34 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b16a097..75539e9 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -4034,22 +4034,28 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_channelinfo *channelinfo)
{
GC_INIT(ctx);
- char *dompath, *fe_path;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
channelinfo->devid = channel->devid;
fe_path = GCSPRINTF("%s/device/console/%d", dompath,
channelinfo->devid + 1);
+ libxl_path = GCSPRINTF("%s/device/console/%d",
+ libxl__xs_libxl_path(gc, domid),
+ channelinfo->devid + 1);
channelinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", fe_path), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!channelinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", fe_path));
- channelinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, channelinfo->backend,
+ &channelinfo->backend_id);
+ if (rc) goto out;
+
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
channelinfo->state = val ? strtoul(val, NULL, 10) : -1;
channelinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
@@ -4067,13 +4073,36 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
switch (channel->connection) {
case LIBXL_CHANNEL_CONNECTION_PTY:
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path));
+ /*
+ * It is obviously very wrong for this value to be in the
+ * frontend. But in XSA-175 we don't want to re-engineer
+ * this because other xenconsole code elsewhere (some
+ * even out of tree, perhaps) expects this node to be
+ * here.
+ *
+ * FE/pty is readonly for the guest. It always exists if
+ * FE does because libxl__device_console_add
+ * unconditionally creates it and nothing deletes it.
+ *
+ * The guest can delete the whole FE (which it has write
+ * privilege on) but the containing directories
+ * /local/GUEST[/device[/console]] are also RO for the
+ * guest. So if the guest deletes FE it cannot recreate
+ * it.
+ *
+ * Therefore the guest cannot cause FE/pty to contain bad
+ * data, although it can cause it to not exist.
+ */
+ if (!val) val = "/NO-SUCH-PATH";
channelinfo->u.pty.path = strdup(val);
break;
default:
break;
}
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
/******************************************************************************/
--
2.1.4
[-- Attachment #14: xsa175-unstable/0013-libxl-Do-not-trust-frontend-for-vusb.patch --]
[-- Type: application/octet-stream, Size: 9181 bytes --]
From d3390df239984972a3468fcf1f66eaaff19daeaa Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Thu, 5 May 2016 16:17:18 +0100
Subject: [PATCH 13/34] libxl: Do not trust frontend for vusb
Do not use the frontend directory for enumerating the vusb devices;
since the frontend could delete them, this could result in devices
being lost and not torn down, etc. Instead, use the /libxl directory
for enumeration. So:
* Replace vusb_be_from_xs_fe with vusb_be_from_xs_libxl
* Change the call sites
* Change various places that use the dompath to use libxl_dom_path
* Rename some `path' variables appropriate (to spot any missed updates)
* Parse backend domid out of backend path rather than reading it from
the frontend (several places)
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v3: Whitespace adjustment to parameter list indentation
v2: New patch, following rebase
---
tools/libxl/libxl_pvusb.c | 84 ++++++++++++++++++++++-------------------------
1 file changed, 40 insertions(+), 44 deletions(-)
diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c
index 9f1e842..7af7e4d 100644
--- a/tools/libxl/libxl_pvusb.c
+++ b/tools/libxl/libxl_pvusb.c
@@ -336,28 +336,16 @@ out:
return;
}
-static const char *vusb_be_from_xs_fe(libxl__gc *gc, const char *fe_path,
- uint32_t tgt_domid)
+static const char *vusb_be_from_xs_libxl(libxl__gc *gc, const char *libxl_path)
{
const char *be_path;
int r;
- uint32_t be_domid, fe_domid;
- char be_type[16];
- r = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/backend", fe_path),
+ r = libxl__xs_read_checked(gc, XBT_NULL,
+ GCSPRINTF("%s/backend", libxl_path),
&be_path);
if (r || !be_path) return NULL;
- /* Check to see that it has the proper form, and that fe_domid ==
- * target domid */
- r = sscanf(be_path, "/local/domain/%u/backend/%15[^/]/%u",
- &be_domid, be_type, &fe_domid);
-
- if (r != 3 || fe_domid != tgt_domid) {
- LOG(ERROR, "Malformed backend, refusing to use");
- return NULL;
- }
-
return be_path;
}
@@ -366,15 +354,15 @@ libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
{
GC_INIT(ctx);
libxl_device_usbctrl *usbctrls = NULL;
- char *path = NULL;
+ char *libxl_vusbs_path = NULL;
char **entry = NULL;
unsigned int nentries = 0;
*num = 0;
- path = GCSPRINTF("%s/device/vusb",
- libxl__xs_get_dompath(gc, domid));
- entry = libxl__xs_directory(gc, XBT_NULL, path, &nentries);
+ libxl_vusbs_path = GCSPRINTF("%s/device/vusb",
+ libxl__xs_libxl_path(gc, domid));
+ entry = libxl__xs_directory(gc, XBT_NULL, libxl_vusbs_path, &nentries);
if (entry && nentries) {
usbctrls = libxl__zalloc(NOGC, sizeof(*usbctrls) * nentries);
@@ -383,7 +371,7 @@ libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
for (usbctrl = usbctrls;
usbctrl < end;
usbctrl++, entry++, (*num)++) {
- const char *tmp, *be_path, *fe_path;
+ const char *tmp, *be_path, *libxl_path;
int ret;
libxl_device_usbctrl_init(usbctrl);
@@ -405,10 +393,12 @@ libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
tmp ? atoi(tmp) : -1; \
})
- fe_path = GCSPRINTF("%s/%s", path, *entry);
- be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
+ libxl_path = GCSPRINTF("%s/%s", libxl_vusbs_path, *entry);
+ be_path = READ_SUBPATH(libxl_path, "backend");
if (!be_path) goto out;
- usbctrl->backend_domid = READ_SUBPATH_INT(fe_path, "backend-id");
+ ret = libxl__backendpath_parse_domid(gc, be_path,
+ &usbctrl->backend_domid);
+ if (ret) goto out;
usbctrl->version = READ_SUBPATH_INT(be_path, "usb-ver");
usbctrl->ports = READ_SUBPATH_INT(be_path, "num-ports");
libxl_usbctrl_type_from_string(READ_SUBPATH(be_path, "type"),
@@ -436,6 +426,7 @@ int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
{
GC_INIT(ctx);
const char *dompath, *fe_path, *be_path, *tmp;
+ const char *libxl_dom_path, *libxl_path;
int rc;
usbctrlinfo->devid = usbctrl->devid;
@@ -458,9 +449,12 @@ int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
dompath = libxl__xs_get_dompath(gc, domid);
fe_path = GCSPRINTF("%s/device/vusb/%d", dompath, usbctrl->devid);
- be_path = READ_SUBPATH(fe_path, "backend");
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ libxl_path = GCSPRINTF("%s/device/vusb/%d", libxl_dom_path, usbctrl->devid);
+ be_path = READ_SUBPATH(libxl_path, "backend");
usbctrlinfo->backend = libxl__strdup(NOGC, be_path);
- usbctrlinfo->backend_id = READ_SUBPATH_INT(fe_path, "backend-id");
+ rc = libxl__backendpath_parse_domid(gc, be_path, &usbctrl->backend_domid);
+ if (rc) goto out;
usbctrlinfo->state = READ_SUBPATH_INT(fe_path, "state");
usbctrlinfo->evtch = READ_SUBPATH_INT(fe_path, "event-channel");
usbctrlinfo->ref_urb = READ_SUBPATH_INT(fe_path, "urb-ring-ref");
@@ -605,13 +599,15 @@ static int get_assigned_devices(libxl__gc *gc,
domlist = libxl__xs_directory(gc, XBT_NULL, "/local/domain", &ndom);
for (i = 0; i < ndom; i++) {
- char *path;
+ char *libxl_vusbs_path;
char **usbctrls;
unsigned int nc = 0;
uint32_t domid = atoi(domlist[i]);
- path = GCSPRINTF("%s/device/vusb", libxl__xs_get_dompath(gc, domid));
- usbctrls = libxl__xs_directory(gc, XBT_NULL, path, &nc);
+ libxl_vusbs_path = GCSPRINTF("%s/device/vusb",
+ libxl__xs_libxl_path(gc, domid));
+ usbctrls = libxl__xs_directory(gc, XBT_NULL,
+ libxl_vusbs_path, &nc);
for (j = 0; j < nc; j++) {
libxl_device_usbdev *tmp = NULL;
@@ -681,16 +677,16 @@ libxl__device_usbdev_list_for_usbctrl(libxl__gc *gc,
libxl_device_usbdev **usbdevs,
int *num)
{
- const char *fe_path, *be_path, *num_devs;
+ const char *libxl_path, *be_path, *num_devs;
int n, i, rc;
*usbdevs = NULL;
*num = 0;
- fe_path = GCSPRINTF("%s/device/vusb/%d",
- libxl__xs_get_dompath(gc, domid), usbctrl);
+ libxl_path = GCSPRINTF("%s/device/vusb/%d",
+ libxl__xs_libxl_path(gc, domid), usbctrl);
- be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
+ be_path = vusb_be_from_xs_libxl(gc, libxl_path);
if (!be_path) {
rc = ERROR_FAIL;
goto out;
@@ -739,16 +735,16 @@ libxl_device_usbdev_list(libxl_ctx *ctx, uint32_t domid, int *num)
{
GC_INIT(ctx);
libxl_device_usbdev *usbdevs = NULL;
- const char *path;
+ const char *libxl_vusbs_path;
char **usbctrls;
unsigned int nc = 0;
int i, j;
*num = 0;
- path = GCSPRINTF("%s/device/vusb",
- libxl__xs_get_dompath(gc, domid));
- usbctrls = libxl__xs_directory(gc, XBT_NULL, path, &nc);
+ libxl_vusbs_path = GCSPRINTF("%s/device/vusb",
+ libxl__xs_libxl_path(gc, !domid));
+ usbctrls = libxl__xs_directory(gc, XBT_NULL, libxl_vusbs_path, &nc);
for (i = 0; i < nc; i++) {
int rc, nd = 0;
@@ -878,13 +874,13 @@ static int libxl__device_usbdev_setdefault(libxl__gc *gc,
}
} else {
/* A controller was specified; look it up */
- const char *fe_path, *be_path, *tmp;
+ const char *libxl_path, *be_path, *tmp;
- fe_path = GCSPRINTF("%s/device/vusb/%d",
- libxl__xs_get_dompath(gc, domid),
+ libxl_path = GCSPRINTF("%s/device/vusb/%d",
+ libxl__xs_libxl_path(gc, domid),
usbdev->ctrl);
- be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
+ be_path = vusb_be_from_xs_libxl(gc, libxl_path);
if (!be_path) {
rc = ERROR_FAIL;
goto out;
@@ -1651,13 +1647,13 @@ int libxl_ctrlport_to_device_usbdev(libxl_ctx *ctx,
libxl_device_usbdev *usbdev)
{
GC_INIT(ctx);
- const char *dompath, *fe_path, *be_path, *busid;
+ const char *libxl_dom_path, *libxl_path, *be_path, *busid;
int rc;
- dompath = libxl__xs_get_dompath(gc, domid);
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
- fe_path = GCSPRINTF("%s/device/vusb/%d", dompath, ctrl);
- be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
+ libxl_path = GCSPRINTF("%s/device/vusb/%d", libxl_dom_path, ctrl);
+ be_path = vusb_be_from_xs_libxl(gc, libxl_path);
if (!be_path) {
rc = ERROR_FAIL;
goto out;
--
2.1.4
[-- Attachment #15: xsa175-4.6/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch --]
[-- Type: application/octet-stream, Size: 7641 bytes --]
From cf6264a8144850a1cbf78709e41d0fcc657be0f3 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 15:50:01 +0100
Subject: [PATCH 01/12] libxl: Record backend/frontend paths in /libxl/$DOMID
This gives us a record of all the backends we have set up for a
domain, which is separate from the frontends in
/local/domain/$DOMID/device.
In particular:
1. A guest has write permission for the frontend path:
/local/domain/$DOMID/device/$KIND/$DEVID
which means that the guest can completely delete the frontend.
(They can't recreate it because they don't have write permission
on the containing directory.)
2. A guest has write permission for the backend path recorded in the
frontend, ie, it can write to
/local/domain/$DOMID/device/$KIND/$DEVID/backend
which means that the guest can break the association between
frontend and backend.
So we can't rely on iterating over the frontends to find all the
backends, or examining a frontend to discover how a device is
configured.
So, have libxl__device_generic_add record the frontend and backend
paths in /libxl/$DOMID/device, and have libxl__device_destroy remove
them again.
Create the containing directory /libxl/GUEST/device in
libxl__domain_make. The already existing xs_rm in devices_destroy_cb
will take care of removing it.
This is part of XSA-175.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v2: Correct actual path computation (!)
v3: Correct actual path computation - really this time (!)
Conflicts:
tools/libxl/libxl_create.c
---
docs/misc/xenstore-paths.markdown | 15 +++++++++++++++
tools/libxl/libxl_create.c | 2 ++
tools/libxl/libxl_device.c | 36 ++++++++++++++++++++++++++++++++++--
tools/libxl/libxl_internal.h | 1 +
4 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index d94ea9d..276273d 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -389,6 +389,21 @@ The guest's virtual time offset from UTC in seconds.
### libxl Specific Paths
+#### /libxl/$DOMID/device/$KIND/$DEVID
+
+Created by libxl for every frontend/backend pair created for $DOMID.
+Used by libxl for enumeration and management of the device.
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/frontend
+
+Path in xenstore to the frontend, normally
+/local/domain/$DOMID/device/$KIND/$DEVID
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/backend
+
+Path in xenstore to the backend, normally
+/local/domain/$BACKEND_DOMID/backend/$KIND/$DOMID/$DEVID
+
#### /libxl/$DOMID/dm-version ("qemu\_xen"|"qemu\_xen\_traditional") = [n,INTERNAL]
The device model version for a domain.
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 350e274..c6862b8 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -591,6 +591,8 @@ retry_transaction:
xs_rm(ctx->xsh, t, libxl_path);
libxl__xs_mkdir(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));
+ libxl__xs_mkdir(gc, t, GCSPRINTF("%s/device", libxl_path),
+ noperm, ARRAY_SIZE(noperm));
xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 8bb5e93..f1af411 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -40,6 +40,15 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
device->domid, device->devid);
}
+char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device)
+{
+ char *libxl_dom_path = libxl__xs_libxl_path(gc, device->domid);
+
+ return GCSPRINTF("%s/device/%s/%d", libxl_dom_path,
+ libxl__device_kind_to_string(device->kind),
+ device->devid);
+}
+
/* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
libxl__device *device)
@@ -105,14 +114,16 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- char *frontend_path, *backend_path;
+ char *frontend_path, *backend_path, *libxl_path;
struct xs_permissions frontend_perms[2];
struct xs_permissions ro_frontend_perms[2];
struct xs_permissions backend_perms[2];
int create_transaction = t == XBT_NULL;
+ int rc;
frontend_path = libxl__device_frontend_path(gc, device);
backend_path = libxl__device_backend_path(gc, device);
+ libxl_path = libxl__device_libxl_path(gc, device);
frontend_perms[0].id = device->domid;
frontend_perms[0].perms = XS_PERM_NONE;
@@ -127,8 +138,22 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
retry_transaction:
if (create_transaction)
t = xs_transaction_start(ctx->xsh);
+
/* FIXME: read frontend_path and check state before removing stuff */
+ rc = libxl__xs_rm_checked(gc, t, libxl_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/frontend",libxl_path),
+ frontend_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/backend",libxl_path),
+ backend_path);
+ if (rc) goto out;
+
+ /* xxx much of this function lacks error checks! */
+
if (fents || ro_fents) {
xs_rm(ctx->xsh, t, frontend_path);
xs_mkdir(ctx->xsh, t, frontend_path);
@@ -174,6 +199,11 @@ retry_transaction:
}
}
return 0;
+
+ out:
+ if (create_transaction && t)
+ libxl__xs_transaction_abort(gc, &t);
+ return rc;
}
typedef struct {
@@ -572,6 +602,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
{
const char *be_path = libxl__device_backend_path(gc, dev);
const char *fe_path = libxl__device_frontend_path(gc, dev);
+ const char *libxl_path = libxl__device_libxl_path(gc, dev);
const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params");
const char *tapdisk_params;
xs_transaction_t t = 0;
@@ -592,9 +623,10 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
if (domid == LIBXL_TOOLSTACK_DOMID) {
/*
* The toolstack domain is in charge of removing the
- * frontend path.
+ * frontend and libxl paths.
*/
libxl__xs_path_cleanup(gc, t, fe_path);
+ libxl__xs_path_cleanup(gc, t, libxl_path);
}
if (dev->backend_domid == domid) {
/*
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 1699f32..38af3ac 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1152,6 +1152,7 @@ _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, 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 char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
--
2.1.4
[-- Attachment #16: xsa175-4.6/0002-libxl-Provide-libxl__backendpath_parse_domid.patch --]
[-- Type: application/octet-stream, Size: 2166 bytes --]
From fd2317e415eab76f20d11c6518fca9042fe117bc Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:34:19 +0100
Subject: [PATCH 02/12] libxl: Provide libxl__backendpath_parse_domid
Multiple places in libxl need to figure out the backend domid of a
device. This can be discovered easily by looking at the backend path,
which always starts /local/domain/$backend_domid/.
There are no call sites yet.
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_device.c | 15 +++++++++++++++
tools/libxl/libxl_internal.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index f1af411..bfd4bdd 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -288,6 +288,21 @@ static int disk_try_backend(disk_try_backend_args *a,
return 0;
}
+int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out) {
+ int r;
+ unsigned int domid_sc;
+ char delim_sc;
+
+ r = sscanf(be_path, "/local/domain/%u%c", &domid_sc, &delim_sc);
+ if (!(r==2 && delim_sc=='/')) {
+ LOG(ERROR, "internal error: backend path %s unparseable!", be_path);
+ return ERROR_FAIL;
+ }
+ *domid_out = domid_sc;
+ return 0;
+}
+
int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
libxl_disk_backend ok;
disk_try_backend_args a;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 38af3ac..f034f63 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -683,6 +683,8 @@ _hidden bool libxl__xs_mkdir(libxl__gc *gc, xs_transaction_t t,
_hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid);
+_hidden int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out);
/*----- "checked" xenstore access functions -----*/
/* Each of these functions will check that it succeeded; if it
--
2.1.4
[-- Attachment #17: xsa175-4.6/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]
From 5214e86aec5cce54f6c3621f487df3f1ecb32c52 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 18:39:36 +0100
Subject: [PATCH 03/12] libxl: Do not trust frontend in libxl__devices_destroy
We need to enumerate the devices we have provided to a domain, without
trusting the guest-writeable (or, at least, guest-deletable) frontend
paths.
Instead, enumerate via, and read the backend path from, /libxl.
The console /libxl path is regular, so the special case for console 0
is not relevant any more: /libxl/GUEST/device/console/0 will be found,
and then libxl__device_destroy will DTRT to the right frontend path.
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_device.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index bfd4bdd..f4e907f 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -685,7 +685,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
libxl__multidev_begin(ao, multidev);
multidev->callback = devices_remove_callback;
- path = GCSPRINTF("/local/domain/%d/device", domid);
+ path = GCSPRINTF("/libxl/%d/device", domid);
kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
if (!kinds) {
if (errno != ENOENT) {
@@ -698,12 +698,12 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
if (libxl__device_kind_from_string(kinds[i], &kind))
continue;
- path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]);
+ path = GCSPRINTF("/libxl/%d/device/%s", domid, kinds[i]);
devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries);
if (!devs)
continue;
for (j = 0; j < num_dev_xsentries; j++) {
- path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend",
+ path = GCSPRINTF("/libxl/%d/device/%s/%s/backend",
domid, kinds[i], devs[j]);
path = libxl__xs_read(gc, XBT_NULL, path);
GCNEW(dev);
@@ -728,22 +728,6 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
}
}
- /* console 0 frontend directory is not under /local/domain/<domid>/device */
- path = GCSPRINTF("/local/domain/%d/console/backend", domid);
- path = libxl__xs_read(gc, XBT_NULL, path);
- GCNEW(dev);
- if (path && strcmp(path, "") &&
- libxl__parse_backend_path(gc, path, dev) == 0) {
- dev->domid = domid;
- dev->kind = LIBXL__DEVICE_KIND_CONSOLE;
- dev->devid = 0;
-
- /* Currently console devices can be destroyed synchronously by just
- * removing xenstore entries, this is what libxl__device_destroy does.
- */
- libxl__device_destroy(gc, dev);
- }
-
out:
libxl__multidev_prepared(egc, multidev, rc);
}
--
2.1.4
[-- Attachment #18: xsa175-4.6/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch --]
[-- Type: application/octet-stream, Size: 1395 bytes --]
From 31c78e76bdeb450ce0e0b32e9f5b0e284d4b9958 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 4 May 2016 15:30:32 +0100
Subject: [PATCH 04/12] libxl: Do not trust frontend in libxl__device_nextid
When selecting the devid for a new device, we should look in
/libxl/device for existing devices, not in the frontend area.
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 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 1366177..96f68dc 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2008,15 +2008,16 @@ out:
/* common function to get next device id */
static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
{
- char *dompath, **l;
+ char *libxl_dom_path, **l;
unsigned int nb;
int nextid = -1;
- if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
return nextid;
l = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/device/%s", dompath, device), &nb);
+ GCSPRINTF("%s/device/%s", libxl_dom_path, device),
+ &nb);
if (l == NULL || nb == 0)
nextid = 0;
else
--
2.1.4
[-- Attachment #19: xsa175-4.6/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch --]
[-- Type: application/octet-stream, Size: 3890 bytes --]
From f02320d65226f722bf8eaaa6bf6e0148d633965a Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:08:49 +0100
Subject: [PATCH 05/12] libxl: Do not trust frontend for disk eject event
Use the /libxl path for interpreting disk eject watch events: do not
read the backend path out of the frontend. Instead, use the version
in /libxl. That avoids us relying on the guest-modifiable
$frontend/backend pointer.
To implement this we store the path
/libxl/$guest/device/vbd/$devid/backend
in the evgen structure.
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 | 28 ++++++++++++++++++++++------
tools/libxl/libxl_internal.h | 2 +-
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 96f68dc..831b80c 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1336,9 +1336,10 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
const char *wpath, const char *epath) {
EGC_GC;
libxl_evgen_disk_eject *evg = (void*)w;
- char *backend;
+ const char *backend;
char *value;
char backend_type[BACKEND_STRING_SIZE+1];
+ int rc;
value = libxl__xs_read(gc, XBT_NULL, wpath);
@@ -1354,9 +1355,16 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
libxl_device_disk *disk = &ev->u.disk_eject.disk;
- backend = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%.*s/backend",
- (int)strlen(wpath)-6, wpath));
+ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
+ if (rc) {
+ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+ if (!backend) {
+ /* device has been removed, not simply ejected */
+ return;
+ }
sscanf(backend,
"/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
@@ -1405,11 +1413,18 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
if (!domid)
domid = guest_domid;
- path = libxl__sprintf(gc, "%s/device/vbd/%d/eject",
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+
+ path = GCSPRINTF("%s/device/vbd/%d/eject",
libxl__xs_get_dompath(gc, domid),
- libxl__device_disk_dev_number(vdev, NULL, NULL));
+ devid);
if (!path) { rc = ERROR_NOMEM; goto out; }
+ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid),
+ devid);
+ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
+
rc = libxl__ev_xswatch_register(gc, &evg->watch,
disk_eject_xswatch_callback, path);
if (rc) goto out;
@@ -1436,6 +1451,7 @@ void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
libxl__ev_xswatch_deregister(gc, &evg->watch);
free(evg->vdev);
+ free(evg->be_ptr_path);
free(evg);
CTX_UNLOCK;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index f034f63..1f11b1a 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -337,7 +337,7 @@ struct libxl__evgen_disk_eject {
uint32_t domid;
LIBXL_LIST_ENTRY(libxl_evgen_disk_eject) entry;
libxl_ev_user user;
- char *vdev;
+ char *vdev, *be_ptr_path;
};
_hidden void
libxl__evdisable_disk_eject(libxl__gc*, libxl_evgen_disk_eject*);
--
2.1.4
[-- Attachment #20: xsa175-4.6/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 3378 bytes --]
From d3e1c77a8ae7820e0906f324254b551995624ab5 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Fri, 29 Apr 2016 19:21:51 +0100
Subject: [PATCH 06/12] libxl: Do not trust frontend for disk in getinfo
* Rename the frontend variable to `fe_path' to check we caught them all
* Read the backend path from /libxl, rather than from the frontend
* Parse the backend domid from the backend path, rather than reading it
from the frontend (and add the appropriate error path and initialisation)
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 | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 831b80c..b418564 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2821,27 +2821,34 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk, libxl_diskinfo *diskinfo)
{
GC_INIT(ctx);
- char *dompath, *diskpath;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
+
+ diskinfo->backend = NULL;
dompath = libxl__xs_get_dompath(gc, domid);
diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
/* tap devices entries in xenstore are written as vbd devices. */
- diskpath = libxl__sprintf(gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
+ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid), diskinfo->devid);
diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", diskpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!diskinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", diskpath));
- diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", diskpath));
+ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
+ &diskinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/ring-ref", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
libxl__sprintf(gc, "%s/frontend", diskinfo->backend), NULL);
@@ -2850,6 +2857,10 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
GC_FREE;
return 0;
+
+ out:
+ free(diskinfo->backend);
+ return rc;
}
int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
--
2.1.4
[-- Attachment #21: xsa175-4.6/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch --]
[-- Type: application/octet-stream, Size: 2387 bytes --]
From c277f046e8d5c8413d6436685dbda75c5626d577 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:58:32 +0100
Subject: [PATCH 07/12] libxl: Do not trust frontend for vtpm list
libxl_device_vtpm_list needs to enumerate and identify devices without
trusting frontend-controlled data. So
* Use the /libxl path to enumerate vtpms.
* Use the /libxl path to find the corresponding backends.
* Parse the backend path to find the backend domid.
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 | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b418564..6590157 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2196,14 +2196,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
GC_INIT(ctx);
libxl_device_vtpm* vtpms = NULL;
- char* fe_path = NULL;
+ char *libxl_path;
char** dir = NULL;
unsigned int ndirs = 0;
+ int rc;
*num = 0;
- fe_path = libxl__sprintf(gc, "%s/device/vtpm", libxl__xs_get_dompath(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+ libxl_path = GCSPRINTF("%s/device/vtpm", libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);
if (dir && ndirs) {
vtpms = malloc(sizeof(*vtpms) * ndirs);
libxl_device_vtpm* vtpm;
@@ -2212,16 +2213,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
char* tmp;
const char* be_path = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/%s/backend",
- fe_path, *dir));
+ libxl_path, *dir));
libxl_device_vtpm_init(vtpm);
vtpm->devid = atoi(*dir);
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/%s/backend-id",
- fe_path, *dir));
- vtpm->backend_domid = atoi(tmp);
+ rc = libxl__backendpath_parse_domid(gc, be_path,
+ &vtpm->backend_domid);
+ if (rc) return NULL;
tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
if (tmp) {
--
2.1.4
[-- Attachment #22: xsa175-4.6/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2100 bytes --]
From d36cdc6238506f65ca9ce2bb008c61e45dbcb9d0 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:00:20 +0100
Subject: [PATCH 08/12] libxl: Do not trust frontend for vtpm in getinfo
libxl_device_vtpm_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 6590157..a424832 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2245,7 +2245,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
libxl_vtpminfo *vtpminfo)
{
GC_INIT(ctx);
- char *dompath, *vtpmpath;
+ char *libxl_path, *dompath, *vtpmpath;
char *val;
int rc = 0;
@@ -2254,8 +2254,10 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
vtpminfo->devid = vtpm->devid;
vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vtpm/%d",
+ libxl__xs_libxl_path(gc, domid), vtpminfo->devid);
vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", vtpmpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!vtpminfo->backend) {
goto err;
}
@@ -2263,9 +2265,9 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
goto err;
}
- val = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/backend-id", vtpmpath));
- vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
+ &vtpminfo->backend_id);
+ if (rc) goto exit;
val = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/state", vtpmpath));
--
2.1.4
[-- Attachment #23: xsa175-4.6/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch --]
[-- Type: application/octet-stream, Size: 1505 bytes --]
From 3e1e9ff62717f4c9b231e82a299e960bd4da4506 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:52:53 +0100
Subject: [PATCH 09/12] libxl: Do not trust frontend for nic in
libxl_devid_to_device_nic
Find the backend by reading the pointer in /libxl rather than in the
guest's frontend area.
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 | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index a424832..225e659 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3512,17 +3512,17 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_nic *nic)
{
GC_INIT(ctx);
- char *dompath, *path;
+ char *libxl_dom_path, *path;
int rc = ERROR_FAIL;
libxl_device_nic_init(nic);
- dompath = libxl__xs_get_dompath(gc, domid);
- if (!dompath)
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ if (!libxl_dom_path)
goto out;
path = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%s/device/vif/%d/backend",
- dompath, devid));
+ GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path,
+ devid));
if (!path)
goto out;
--
2.1.4
[-- Attachment #24: xsa175-4.6/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2812 bytes --]
From 4bb4bb97faacc6135fb0640be9da10c9f2dc5592 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:31:07 +0100
Subject: [PATCH 10/12] libxl: Do not trust frontend for nic in getinfo
libxl_device_nic_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 225e659..105a9cc 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3601,22 +3601,27 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic, libxl_nicinfo *nicinfo)
{
GC_INIT(ctx);
- char *dompath, *nicpath;
+ char *dompath, *nicpath, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
nicinfo->devid = nic->devid;
- nicpath = libxl__sprintf(gc, "%s/device/vif/%d", dompath, nicinfo->devid);
+ nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vif/%d",
+ libxl__xs_libxl_path(gc, domid), nicinfo->devid);
nicinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", nicpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!nicinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", nicpath));
- nicinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", nicpath));
+ rc = libxl__backendpath_parse_domid(gc, nicinfo->backend,
+ &nicinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath));
nicinfo->state = val ? strtoul(val, NULL, 10) : -1;
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", nicpath));
nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
@@ -3629,8 +3634,10 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend-id", nicinfo->backend));
nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
const char *libxl__device_nic_devname(libxl__gc *gc,
--
2.1.4
[-- Attachment #25: xsa175-4.6/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch --]
[-- Type: application/octet-stream, Size: 4163 bytes --]
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(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 105a9cc..48d491f 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3698,6 +3698,8 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
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");
@@ -3836,34 +3838,35 @@ static int libxl__device_channel_from_xs_be(libxl__gc *gc,
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) {
@@ -3894,7 +3897,7 @@ libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
*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;
--
2.1.4
[-- Attachment #26: xsa175-4.6/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 4963 bytes --]
From 1a83149ba5f2a7faed29d45b5d6dddfff78459bc Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 17:24:32 +0100
Subject: [PATCH 12/12] libxl: Do not trust frontend for channel in getinfo
libxl_device_channel_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
* Tolerate FRONTEND/tty vanishing.
Note that there is a strange off-by-one error in the computation of
both fe_path and libxl_path in libxl_device_channel_getinfo: the
incoming channel->devid, which is copied to channelinfo->devid, has +1
applied to calculate the frontend path (and, after this patch, the
libxl path). I.e., the devid passed to libxl_device_channel_getinfo
must be one less than the actual devid for the device being asked
about.
This is actually a bug which mirrors a bug in
libxl__append_channel_list, which fills in the devids of the channel
devices it finds with sequentially increasing numbers starting at 0.
In the usual case channels have real devids starting at 1 (because
there is the console, which is devid 0, but not a channel). So these
bugs usually cancel out.
We do not address this problem at this time. This bug does not have
any security implications.
This patch 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 | 44 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 36 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 48d491f..db92fae 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3918,23 +3918,28 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_channelinfo *channelinfo)
{
GC_INIT(ctx);
- char *dompath, *fe_path;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
channelinfo->devid = channel->devid;
- fe_path = libxl__sprintf(gc, "%s/device/console/%d", dompath,
- channelinfo->devid + 1);
+ fe_path = GCSPRINTF("%s/device/console/%d", dompath,
+ channelinfo->devid + 1);
+ libxl_path = GCSPRINTF("%s/device/console/%d",
+ libxl__xs_libxl_path(gc, domid),
+ channelinfo->devid + 1);
channelinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend",
- fe_path), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!channelinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", fe_path));
- channelinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, channelinfo->backend,
+ &channelinfo->backend_id);
+ if (rc) goto out;
+
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
channelinfo->state = val ? strtoul(val, NULL, 10) : -1;
channelinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
@@ -3952,13 +3957,36 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
switch (channel->connection) {
case LIBXL_CHANNEL_CONNECTION_PTY:
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path));
+ /*
+ * It is obviously very wrong for this value to be in the
+ * frontend. But in XSA-175 we don't want to re-engineer
+ * this because other xenconsole code elsewhere (some
+ * even out of tree, perhaps) expects this node to be
+ * here.
+ *
+ * FE/pty is readonly for the guest. It always exists if
+ * FE does because libxl__device_console_add
+ * unconditionally creates it and nothing deletes it.
+ *
+ * The guest can delete the whole FE (which it has write
+ * privilege on) but the containing directories
+ * /local/GUEST[/device[/console]] are also RO for the
+ * guest. So if the guest deletes FE it cannot recreate
+ * it.
+ *
+ * Therefore the guest cannot cause FE/pty to contain bad
+ * data, although it can cause it to not exist.
+ */
+ if (!val) val = "/NO-SUCH-PATH";
channelinfo->u.pty.path = strdup(val);
break;
default:
break;
}
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
/******************************************************************************/
--
2.1.4
[-- Attachment #27: xsa175-4.5/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch --]
[-- Type: application/octet-stream, Size: 7602 bytes --]
From 3a4091efe0b4bcae46371491d74c15bba6f93275 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Mon, 16 May 2016 14:56:57 +0100
Subject: [PATCH 01/12] libxl: Record backend/frontend paths in /libxl/$DOMID
This gives us a record of all the backends we have set up for a
domain, which is separate from the frontends in
/local/domain/$DOMID/device.
In particular:
1. A guest has write permission for the frontend path:
/local/domain/$DOMID/device/$KIND/$DEVID
which means that the guest can completely delete the frontend.
(They can't recreate it because they don't have write permission
on the containing directory.)
2. A guest has write permission for the backend path recorded in the
frontend, ie, it can write to
/local/domain/$DOMID/device/$KIND/$DEVID/backend
which means that the guest can break the association between
frontend and backend.
So we can't rely on iterating over the frontends to find all the
backends, or examining a frontend to discover how a device is
configured.
So, have libxl__device_generic_add record the frontend and backend
paths in /libxl/$DOMID/device, and have libxl__device_destroy remove
them again.
Create the containing directory /libxl/GUEST/device in
libxl__domain_make. The already existing xs_rm in devices_destroy_cb
will take care of removing it.
This is part of XSA-175.
Backport note: Backported over 7472ced, which fixes a bug in driver
domain teardown.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v2: Correct actual path computation (!)
v3: Correct actual path computation - really this time (!)
---
docs/misc/xenstore-paths.markdown | 15 +++++++++++++++
tools/libxl/libxl_create.c | 2 ++
tools/libxl/libxl_device.c | 34 +++++++++++++++++++++++++++++++++-
tools/libxl/libxl_internal.h | 1 +
4 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index d94ea9d..276273d 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -389,6 +389,21 @@ The guest's virtual time offset from UTC in seconds.
### libxl Specific Paths
+#### /libxl/$DOMID/device/$KIND/$DEVID
+
+Created by libxl for every frontend/backend pair created for $DOMID.
+Used by libxl for enumeration and management of the device.
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/frontend
+
+Path in xenstore to the frontend, normally
+/local/domain/$DOMID/device/$KIND/$DEVID
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/backend
+
+Path in xenstore to the backend, normally
+/local/domain/$BACKEND_DOMID/backend/$KIND/$DOMID/$DEVID
+
#### /libxl/$DOMID/dm-version ("qemu\_xen"|"qemu\_xen\_traditional") = [n,INTERNAL]
The device model version for a domain.
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 152fdbc..a4d4d4c 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -586,6 +586,8 @@ retry_transaction:
xs_rm(ctx->xsh, t, libxl_path);
libxl__xs_mkdir(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));
+ libxl__xs_mkdir(gc, t, GCSPRINTF("%s/device", libxl_path),
+ noperm, ARRAY_SIZE(noperm));
xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 4b51ded..a8b97a3 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -40,6 +40,15 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
device->domid, device->devid);
}
+char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device)
+{
+ char *libxl_dom_path = libxl__xs_libxl_path(gc, device->domid);
+
+ return GCSPRINTF("%s/device/%s/%d", libxl_dom_path,
+ libxl__device_kind_to_string(device->kind),
+ device->devid);
+}
+
/* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
libxl__device *device)
@@ -105,14 +114,16 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- char *frontend_path, *backend_path;
+ char *frontend_path, *backend_path, *libxl_path;
struct xs_permissions frontend_perms[2];
struct xs_permissions ro_frontend_perms[2];
struct xs_permissions backend_perms[2];
int create_transaction = t == XBT_NULL;
+ int rc;
frontend_path = libxl__device_frontend_path(gc, device);
backend_path = libxl__device_backend_path(gc, device);
+ libxl_path = libxl__device_libxl_path(gc, device);
frontend_perms[0].id = device->domid;
frontend_perms[0].perms = XS_PERM_NONE;
@@ -127,8 +138,22 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
retry_transaction:
if (create_transaction)
t = xs_transaction_start(ctx->xsh);
+
/* FIXME: read frontend_path and check state before removing stuff */
+ rc = libxl__xs_rm_checked(gc, t, libxl_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/frontend",libxl_path),
+ frontend_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/backend",libxl_path),
+ backend_path);
+ if (rc) goto out;
+
+ /* xxx much of this function lacks error checks! */
+
if (fents || ro_fents) {
xs_rm(ctx->xsh, t, frontend_path);
xs_mkdir(ctx->xsh, t, frontend_path);
@@ -174,6 +199,11 @@ retry_transaction:
}
}
return 0;
+
+ out:
+ if (create_transaction && t)
+ libxl__xs_transaction_abort(gc, &t);
+ return rc;
}
typedef struct {
@@ -570,6 +600,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
{
const char *be_path = libxl__device_backend_path(gc, dev);
const char *fe_path = libxl__device_frontend_path(gc, dev);
+ const char *libxl_path = libxl__device_libxl_path(gc, dev);
const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params");
const char *tapdisk_params;
xs_transaction_t t = 0;
@@ -594,6 +625,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
*/
libxl__xs_path_cleanup(gc, t, fe_path);
libxl__xs_path_cleanup(gc, t, be_path);
+ libxl__xs_path_cleanup(gc, t, libxl_path);
} else if (dev->backend_domid == domid) {
/*
* The driver domain is in charge for removing what it can
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index ff88f3d..55b19d9 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1061,6 +1061,7 @@ _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, 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 char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
--
2.1.4
[-- Attachment #28: xsa175-4.5/0002-libxl-Provide-libxl__backendpath_parse_domid.patch --]
[-- Type: application/octet-stream, Size: 2166 bytes --]
From c689a6c9471761b59e6d08dee1667834e0b7fc34 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:34:19 +0100
Subject: [PATCH 02/12] libxl: Provide libxl__backendpath_parse_domid
Multiple places in libxl need to figure out the backend domid of a
device. This can be discovered easily by looking at the backend path,
which always starts /local/domain/$backend_domid/.
There are no call sites yet.
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_device.c | 15 +++++++++++++++
tools/libxl/libxl_internal.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index a8b97a3..9136b26 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -288,6 +288,21 @@ static int disk_try_backend(disk_try_backend_args *a,
return 0;
}
+int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out) {
+ int r;
+ unsigned int domid_sc;
+ char delim_sc;
+
+ r = sscanf(be_path, "/local/domain/%u%c", &domid_sc, &delim_sc);
+ if (!(r==2 && delim_sc=='/')) {
+ LOG(ERROR, "internal error: backend path %s unparseable!", be_path);
+ return ERROR_FAIL;
+ }
+ *domid_out = domid_sc;
+ return 0;
+}
+
int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
libxl_disk_backend ok;
disk_try_backend_args a;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 55b19d9..bfe06bd 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -594,6 +594,8 @@ _hidden bool libxl__xs_mkdir(libxl__gc *gc, xs_transaction_t t,
_hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid);
+_hidden int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out);
/*----- "checked" xenstore access functions -----*/
/* Each of these functions will check that it succeeded; if it
--
2.1.4
[-- Attachment #29: xsa175-4.5/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]
From 924ac76cba810c3c8d594f78f96fbf7c792c3f54 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 18:39:36 +0100
Subject: [PATCH 03/12] libxl: Do not trust frontend in libxl__devices_destroy
We need to enumerate the devices we have provided to a domain, without
trusting the guest-writeable (or, at least, guest-deletable) frontend
paths.
Instead, enumerate via, and read the backend path from, /libxl.
The console /libxl path is regular, so the special case for console 0
is not relevant any more: /libxl/GUEST/device/console/0 will be found,
and then libxl__device_destroy will DTRT to the right frontend path.
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_device.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 9136b26..38ab393 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -683,7 +683,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
libxl__multidev_begin(ao, multidev);
multidev->callback = devices_remove_callback;
- path = GCSPRINTF("/local/domain/%d/device", domid);
+ path = GCSPRINTF("/libxl/%d/device", domid);
kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
if (!kinds) {
if (errno != ENOENT) {
@@ -696,12 +696,12 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
if (libxl__device_kind_from_string(kinds[i], &kind))
continue;
- path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]);
+ path = GCSPRINTF("/libxl/%d/device/%s", domid, kinds[i]);
devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries);
if (!devs)
continue;
for (j = 0; j < num_dev_xsentries; j++) {
- path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend",
+ path = GCSPRINTF("/libxl/%d/device/%s/%s/backend",
domid, kinds[i], devs[j]);
path = libxl__xs_read(gc, XBT_NULL, path);
GCNEW(dev);
@@ -726,22 +726,6 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
}
}
- /* console 0 frontend directory is not under /local/domain/<domid>/device */
- path = GCSPRINTF("/local/domain/%d/console/backend", domid);
- path = libxl__xs_read(gc, XBT_NULL, path);
- GCNEW(dev);
- if (path && strcmp(path, "") &&
- libxl__parse_backend_path(gc, path, dev) == 0) {
- dev->domid = domid;
- dev->kind = LIBXL__DEVICE_KIND_CONSOLE;
- dev->devid = 0;
-
- /* Currently console devices can be destroyed synchronously by just
- * removing xenstore entries, this is what libxl__device_destroy does.
- */
- libxl__device_destroy(gc, dev);
- }
-
out:
libxl__multidev_prepared(egc, multidev, rc);
}
--
2.1.4
[-- Attachment #30: xsa175-4.5/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch --]
[-- Type: application/octet-stream, Size: 1395 bytes --]
From 1070d8daa6a73a66ceabd9cd6c89ce712b69bafe Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 4 May 2016 15:30:32 +0100
Subject: [PATCH 04/12] libxl: Do not trust frontend in libxl__device_nextid
When selecting the devid for a new device, we should look in
/libxl/device for existing devices, not in the frontend area.
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 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 312a371..170dd45 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1985,15 +1985,16 @@ out:
/* common function to get next device id */
static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
{
- char *dompath, **l;
+ char *libxl_dom_path, **l;
unsigned int nb;
int nextid = -1;
- if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
return nextid;
l = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/device/%s", dompath, device), &nb);
+ GCSPRINTF("%s/device/%s", libxl_dom_path, device),
+ &nb);
if (l == NULL || nb == 0)
nextid = 0;
else
--
2.1.4
[-- Attachment #31: xsa175-4.5/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch --]
[-- Type: application/octet-stream, Size: 3890 bytes --]
From 1d70543c4e53c2fc283e520d098069ac41583469 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:08:49 +0100
Subject: [PATCH 05/12] libxl: Do not trust frontend for disk eject event
Use the /libxl path for interpreting disk eject watch events: do not
read the backend path out of the frontend. Instead, use the version
in /libxl. That avoids us relying on the guest-modifiable
$frontend/backend pointer.
To implement this we store the path
/libxl/$guest/device/vbd/$devid/backend
in the evgen structure.
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 | 28 ++++++++++++++++++++++------
tools/libxl/libxl_internal.h | 2 +-
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 170dd45..9c0fed4 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1323,9 +1323,10 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
const char *wpath, const char *epath) {
EGC_GC;
libxl_evgen_disk_eject *evg = (void*)w;
- char *backend;
+ const char *backend;
char *value;
char backend_type[BACKEND_STRING_SIZE+1];
+ int rc;
value = libxl__xs_read(gc, XBT_NULL, wpath);
@@ -1341,9 +1342,16 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
libxl_device_disk *disk = &ev->u.disk_eject.disk;
- backend = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%.*s/backend",
- (int)strlen(wpath)-6, wpath));
+ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
+ if (rc) {
+ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+ if (!backend) {
+ /* device has been removed, not simply ejected */
+ return;
+ }
sscanf(backend,
"/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
@@ -1392,11 +1400,18 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
if (!domid)
domid = guest_domid;
- path = libxl__sprintf(gc, "%s/device/vbd/%d/eject",
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+
+ path = GCSPRINTF("%s/device/vbd/%d/eject",
libxl__xs_get_dompath(gc, domid),
- libxl__device_disk_dev_number(vdev, NULL, NULL));
+ devid);
if (!path) { rc = ERROR_NOMEM; goto out; }
+ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid),
+ devid);
+ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
+
rc = libxl__ev_xswatch_register(gc, &evg->watch,
disk_eject_xswatch_callback, path);
if (rc) goto out;
@@ -1423,6 +1438,7 @@ void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
libxl__ev_xswatch_deregister(gc, &evg->watch);
free(evg->vdev);
+ free(evg->be_ptr_path);
free(evg);
CTX_UNLOCK;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index bfe06bd..302585c 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -271,7 +271,7 @@ struct libxl__evgen_disk_eject {
uint32_t domid;
LIBXL_LIST_ENTRY(libxl_evgen_disk_eject) entry;
libxl_ev_user user;
- char *vdev;
+ char *vdev, *be_ptr_path;
};
_hidden void
libxl__evdisable_disk_eject(libxl__gc*, libxl_evgen_disk_eject*);
--
2.1.4
[-- Attachment #32: xsa175-4.5/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 3378 bytes --]
From 11770db72bc644c322ad9044dbf86f9c6cb3a780 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Fri, 29 Apr 2016 19:21:51 +0100
Subject: [PATCH 06/12] libxl: Do not trust frontend for disk in getinfo
* Rename the frontend variable to `fe_path' to check we caught them all
* Read the backend path from /libxl, rather than from the frontend
* Parse the backend domid from the backend path, rather than reading it
from the frontend (and add the appropriate error path and initialisation)
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 | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 9c0fed4..69b7da7 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2796,27 +2796,34 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk, libxl_diskinfo *diskinfo)
{
GC_INIT(ctx);
- char *dompath, *diskpath;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
+
+ diskinfo->backend = NULL;
dompath = libxl__xs_get_dompath(gc, domid);
diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
/* tap devices entries in xenstore are written as vbd devices. */
- diskpath = libxl__sprintf(gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
+ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid), diskinfo->devid);
diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", diskpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!diskinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", diskpath));
- diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", diskpath));
+ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
+ &diskinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/ring-ref", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
libxl__sprintf(gc, "%s/frontend", diskinfo->backend), NULL);
@@ -2825,6 +2832,10 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
GC_FREE;
return 0;
+
+ out:
+ free(diskinfo->backend);
+ return rc;
}
int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
--
2.1.4
[-- Attachment #33: xsa175-4.5/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch --]
[-- Type: application/octet-stream, Size: 2387 bytes --]
From 54a34ac83f0826cd0213a6ebdb0c414cb5051ed2 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:58:32 +0100
Subject: [PATCH 07/12] libxl: Do not trust frontend for vtpm list
libxl_device_vtpm_list needs to enumerate and identify devices without
trusting frontend-controlled data. So
* Use the /libxl path to enumerate vtpms.
* Use the /libxl path to find the corresponding backends.
* Parse the backend path to find the backend domid.
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 | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 69b7da7..b91eee8 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2173,14 +2173,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
GC_INIT(ctx);
libxl_device_vtpm* vtpms = NULL;
- char* fe_path = NULL;
+ char *libxl_path;
char** dir = NULL;
unsigned int ndirs = 0;
+ int rc;
*num = 0;
- fe_path = libxl__sprintf(gc, "%s/device/vtpm", libxl__xs_get_dompath(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+ libxl_path = GCSPRINTF("%s/device/vtpm", libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);
if (dir && ndirs) {
vtpms = malloc(sizeof(*vtpms) * ndirs);
libxl_device_vtpm* vtpm;
@@ -2189,16 +2190,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
char* tmp;
const char* be_path = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/%s/backend",
- fe_path, *dir));
+ libxl_path, *dir));
libxl_device_vtpm_init(vtpm);
vtpm->devid = atoi(*dir);
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/%s/backend-id",
- fe_path, *dir));
- vtpm->backend_domid = atoi(tmp);
+ rc = libxl__backendpath_parse_domid(gc, be_path,
+ &vtpm->backend_domid);
+ if (rc) return NULL;
tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
if (tmp) {
--
2.1.4
[-- Attachment #34: xsa175-4.5/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2100 bytes --]
From b83d66dfb3905dfd627f5e4833d74be274771e43 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:00:20 +0100
Subject: [PATCH 08/12] libxl: Do not trust frontend for vtpm in getinfo
libxl_device_vtpm_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b91eee8..65b9953 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2222,7 +2222,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
libxl_vtpminfo *vtpminfo)
{
GC_INIT(ctx);
- char *dompath, *vtpmpath;
+ char *libxl_path, *dompath, *vtpmpath;
char *val;
int rc = 0;
@@ -2231,8 +2231,10 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
vtpminfo->devid = vtpm->devid;
vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vtpm/%d",
+ libxl__xs_libxl_path(gc, domid), vtpminfo->devid);
vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", vtpmpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!vtpminfo->backend) {
goto err;
}
@@ -2240,9 +2242,9 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
goto err;
}
- val = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/backend-id", vtpmpath));
- vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
+ &vtpminfo->backend_id);
+ if (rc) goto exit;
val = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/state", vtpmpath));
--
2.1.4
[-- Attachment #35: xsa175-4.5/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch --]
[-- Type: application/octet-stream, Size: 1505 bytes --]
From c626ea4768294b73ef24fafe7af9ad1221c1c48d Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:52:53 +0100
Subject: [PATCH 09/12] libxl: Do not trust frontend for nic in
libxl_devid_to_device_nic
Find the backend by reading the pointer in /libxl rather than in the
guest's frontend area.
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 | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 65b9953..4c45269 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3540,17 +3540,17 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_nic *nic)
{
GC_INIT(ctx);
- char *dompath, *path;
+ char *libxl_dom_path, *path;
int rc = ERROR_FAIL;
libxl_device_nic_init(nic);
- dompath = libxl__xs_get_dompath(gc, domid);
- if (!dompath)
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ if (!libxl_dom_path)
goto out;
path = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%s/device/vif/%d/backend",
- dompath, devid));
+ GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path,
+ devid));
if (!path)
goto out;
--
2.1.4
[-- Attachment #36: xsa175-4.5/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2812 bytes --]
From 9d1982995e8d5645ae149bce670bea82fda31421 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:31:07 +0100
Subject: [PATCH 10/12] libxl: Do not trust frontend for nic in getinfo
libxl_device_nic_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 4c45269..34853f8 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3629,22 +3629,27 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic, libxl_nicinfo *nicinfo)
{
GC_INIT(ctx);
- char *dompath, *nicpath;
+ char *dompath, *nicpath, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
nicinfo->devid = nic->devid;
- nicpath = libxl__sprintf(gc, "%s/device/vif/%d", dompath, nicinfo->devid);
+ nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vif/%d",
+ libxl__xs_libxl_path(gc, domid), nicinfo->devid);
nicinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", nicpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!nicinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", nicpath));
- nicinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", nicpath));
+ rc = libxl__backendpath_parse_domid(gc, nicinfo->backend,
+ &nicinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath));
nicinfo->state = val ? strtoul(val, NULL, 10) : -1;
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", nicpath));
nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
@@ -3657,8 +3662,10 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend-id", nicinfo->backend));
nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
const char *libxl__device_nic_devname(libxl__gc *gc,
--
2.1.4
[-- Attachment #37: xsa175-4.5/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch --]
[-- Type: application/octet-stream, Size: 4163 bytes --]
From 55fcc20fa75d9458805bf8130ce257cddd8db71f 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(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 34853f8..6ffb173 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3726,6 +3726,8 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
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");
@@ -3864,34 +3866,35 @@ static int libxl__device_channel_from_xs_be(libxl__gc *gc,
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) {
@@ -3922,7 +3925,7 @@ libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
*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;
--
2.1.4
[-- Attachment #38: xsa175-4.5/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 4963 bytes --]
From 0333ec931e023a66dc03392c9bcb1040018b00e8 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 17:24:32 +0100
Subject: [PATCH 12/12] libxl: Do not trust frontend for channel in getinfo
libxl_device_channel_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
* Tolerate FRONTEND/tty vanishing.
Note that there is a strange off-by-one error in the computation of
both fe_path and libxl_path in libxl_device_channel_getinfo: the
incoming channel->devid, which is copied to channelinfo->devid, has +1
applied to calculate the frontend path (and, after this patch, the
libxl path). I.e., the devid passed to libxl_device_channel_getinfo
must be one less than the actual devid for the device being asked
about.
This is actually a bug which mirrors a bug in
libxl__append_channel_list, which fills in the devids of the channel
devices it finds with sequentially increasing numbers starting at 0.
In the usual case channels have real devids starting at 1 (because
there is the console, which is devid 0, but not a channel). So these
bugs usually cancel out.
We do not address this problem at this time. This bug does not have
any security implications.
This patch 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 | 44 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 36 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 6ffb173..2dd2467 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3946,23 +3946,28 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_channelinfo *channelinfo)
{
GC_INIT(ctx);
- char *dompath, *fe_path;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
channelinfo->devid = channel->devid;
- fe_path = libxl__sprintf(gc, "%s/device/console/%d", dompath,
- channelinfo->devid + 1);
+ fe_path = GCSPRINTF("%s/device/console/%d", dompath,
+ channelinfo->devid + 1);
+ libxl_path = GCSPRINTF("%s/device/console/%d",
+ libxl__xs_libxl_path(gc, domid),
+ channelinfo->devid + 1);
channelinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend",
- fe_path), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!channelinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", fe_path));
- channelinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, channelinfo->backend,
+ &channelinfo->backend_id);
+ if (rc) goto out;
+
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
channelinfo->state = val ? strtoul(val, NULL, 10) : -1;
channelinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
@@ -3980,13 +3985,36 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
switch (channel->connection) {
case LIBXL_CHANNEL_CONNECTION_PTY:
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path));
+ /*
+ * It is obviously very wrong for this value to be in the
+ * frontend. But in XSA-175 we don't want to re-engineer
+ * this because other xenconsole code elsewhere (some
+ * even out of tree, perhaps) expects this node to be
+ * here.
+ *
+ * FE/pty is readonly for the guest. It always exists if
+ * FE does because libxl__device_console_add
+ * unconditionally creates it and nothing deletes it.
+ *
+ * The guest can delete the whole FE (which it has write
+ * privilege on) but the containing directories
+ * /local/GUEST[/device[/console]] are also RO for the
+ * guest. So if the guest deletes FE it cannot recreate
+ * it.
+ *
+ * Therefore the guest cannot cause FE/pty to contain bad
+ * data, although it can cause it to not exist.
+ */
+ if (!val) val = "/NO-SUCH-PATH";
channelinfo->u.pty.path = strdup(val);
break;
default:
break;
}
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
/******************************************************************************/
--
2.1.4
[-- Attachment #39: xsa175-4.4/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch --]
[-- Type: application/octet-stream, Size: 7566 bytes --]
From 9a5ccbd7b599c75b3a95c52bf128e362c0ae9e45 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Mon, 16 May 2016 16:44:31 +0100
Subject: [PATCH 01/10] libxl: Record backend/frontend paths in /libxl/$DOMID
This gives us a record of all the backends we have set up for a
domain, which is separate from the frontends in
/local/domain/$DOMID/device.
In particular:
1. A guest has write permission for the frontend path:
/local/domain/$DOMID/device/$KIND/$DEVID
which means that the guest can completely delete the frontend.
(They can't recreate it because they don't have write permission
on the containing directory.)
2. A guest has write permission for the backend path recorded in the
frontend, ie, it can write to
/local/domain/$DOMID/device/$KIND/$DEVID/backend
which means that the guest can break the association between
frontend and backend.
So we can't rely on iterating over the frontends to find all the
backends, or examining a frontend to discover how a device is
configured.
So, have libxl__device_generic_add record the frontend and backend
paths in /libxl/$DOMID/device, and have libxl__device_destroy remove
them again.
Create the containing directory /libxl/GUEST/device in
libxl__domain_make. The already existing xs_rm in devices_destroy_cb
will take care of removing it.
This is part of XSA-175.
Backport note: Backported over 7472ced, which fixes a bug in driver
domain teardown.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v2: Correct actual path computation (!)
v3: Correct actual path computation - really this time (!)
---
docs/misc/xenstore-paths.markdown | 15 +++++++++++++++
tools/libxl/libxl_create.c | 2 ++
tools/libxl/libxl_device.c | 34 +++++++++++++++++++++++++++++++++-
tools/libxl/libxl_internal.h | 1 +
4 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index 70ab7f4..e018b55 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -381,6 +381,21 @@ The guest's virtual time offset from UTC in seconds.
### libxl Specific Paths
+#### /libxl/$DOMID/device/$KIND/$DEVID
+
+Created by libxl for every frontend/backend pair created for $DOMID.
+Used by libxl for enumeration and management of the device.
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/frontend
+
+Path in xenstore to the frontend, normally
+/local/domain/$DOMID/device/$KIND/$DEVID
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/backend
+
+Path in xenstore to the backend, normally
+/local/domain/$BACKEND_DOMID/backend/$KIND/$DOMID/$DEVID
+
#### /libxl/$DOMID/dm-version ("qemu\_xen"|"qemu\_xen\_traditional") = [n,INTERNAL]
The device model version for a domain.
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 5292c15..0e26666 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -528,6 +528,8 @@ retry_transaction:
xs_rm(ctx->xsh, t, libxl_path);
libxl__xs_mkdir(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));
+ libxl__xs_mkdir(gc, t, GCSPRINTF("%s/device", libxl_path),
+ noperm, ARRAY_SIZE(noperm));
xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 29ed547..e9d2424 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -40,6 +40,15 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
device->domid, device->devid);
}
+char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device)
+{
+ char *libxl_dom_path = libxl__xs_libxl_path(gc, device->domid);
+
+ return GCSPRINTF("%s/device/%s/%d", libxl_dom_path,
+ libxl__device_kind_to_string(device->kind),
+ device->devid);
+}
+
int libxl__parse_backend_path(libxl__gc *gc,
const char *path,
libxl__device *dev)
@@ -87,14 +96,16 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- char *frontend_path, *backend_path;
+ char *frontend_path, *backend_path, *libxl_path;
struct xs_permissions frontend_perms[2];
struct xs_permissions ro_frontend_perms[2];
struct xs_permissions backend_perms[2];
int create_transaction = t == XBT_NULL;
+ int rc;
frontend_path = libxl__device_frontend_path(gc, device);
backend_path = libxl__device_backend_path(gc, device);
+ libxl_path = libxl__device_libxl_path(gc, device);
frontend_perms[0].id = device->domid;
frontend_perms[0].perms = XS_PERM_NONE;
@@ -109,8 +120,22 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
retry_transaction:
if (create_transaction)
t = xs_transaction_start(ctx->xsh);
+
/* FIXME: read frontend_path and check state before removing stuff */
+ rc = libxl__xs_rm_checked(gc, t, libxl_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/frontend",libxl_path),
+ frontend_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/backend",libxl_path),
+ backend_path);
+ if (rc) goto out;
+
+ /* xxx much of this function lacks error checks! */
+
if (fents || ro_fents) {
xs_rm(ctx->xsh, t, frontend_path);
xs_mkdir(ctx->xsh, t, frontend_path);
@@ -156,6 +181,11 @@ retry_transaction:
}
}
return 0;
+
+ out:
+ if (create_transaction && t)
+ libxl__xs_transaction_abort(gc, &t);
+ return rc;
}
typedef struct {
@@ -552,6 +582,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
{
const char *be_path = libxl__device_backend_path(gc, dev);
const char *fe_path = libxl__device_frontend_path(gc, dev);
+ const char *libxl_path = libxl__device_libxl_path(gc, dev);
const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params");
const char *tapdisk_params;
xs_transaction_t t = 0;
@@ -576,6 +607,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
*/
libxl__xs_path_cleanup(gc, t, fe_path);
libxl__xs_path_cleanup(gc, t, be_path);
+ libxl__xs_path_cleanup(gc, t, libxl_path);
} else if (dev->backend_domid == domid) {
/*
* The driver domain is in charge for removing what it can
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index f6d469b..801e95d 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -968,6 +968,7 @@ _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, 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 char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
--
2.1.4
[-- Attachment #40: xsa175-4.4/0002-libxl-Provide-libxl__backendpath_parse_domid.patch --]
[-- Type: application/octet-stream, Size: 2166 bytes --]
From 35a740847bea0a2aede72de7b2b8b49eef36e4eb Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:34:19 +0100
Subject: [PATCH 02/10] libxl: Provide libxl__backendpath_parse_domid
Multiple places in libxl need to figure out the backend domid of a
device. This can be discovered easily by looking at the backend path,
which always starts /local/domain/$backend_domid/.
There are no call sites yet.
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_device.c | 15 +++++++++++++++
tools/libxl/libxl_internal.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index e9d2424..b500264 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -270,6 +270,21 @@ static int disk_try_backend(disk_try_backend_args *a,
return 0;
}
+int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out) {
+ int r;
+ unsigned int domid_sc;
+ char delim_sc;
+
+ r = sscanf(be_path, "/local/domain/%u%c", &domid_sc, &delim_sc);
+ if (!(r==2 && delim_sc=='/')) {
+ LOG(ERROR, "internal error: backend path %s unparseable!", be_path);
+ return ERROR_FAIL;
+ }
+ *domid_out = domid_sc;
+ return 0;
+}
+
int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
libxl_disk_backend ok;
disk_try_backend_args a;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 801e95d..3fc9997 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -574,6 +574,8 @@ _hidden bool libxl__xs_mkdir(libxl__gc *gc, xs_transaction_t t,
_hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid);
+_hidden int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out);
/*----- "checked" xenstore access functions -----*/
/* Each of these functions will check that it succeeded; if it
--
2.1.4
[-- Attachment #41: xsa175-4.4/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]
From ef216637a72ce30661d28a47ccc7464869baa398 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 18:39:36 +0100
Subject: [PATCH 03/10] libxl: Do not trust frontend in libxl__devices_destroy
We need to enumerate the devices we have provided to a domain, without
trusting the guest-writeable (or, at least, guest-deletable) frontend
paths.
Instead, enumerate via, and read the backend path from, /libxl.
The console /libxl path is regular, so the special case for console 0
is not relevant any more: /libxl/GUEST/device/console/0 will be found,
and then libxl__device_destroy will DTRT to the right frontend path.
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_device.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index b500264..e7650d0 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -665,7 +665,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
libxl__multidev_begin(ao, multidev);
multidev->callback = devices_remove_callback;
- path = GCSPRINTF("/local/domain/%d/device", domid);
+ path = GCSPRINTF("/libxl/%d/device", domid);
kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
if (!kinds) {
if (errno != ENOENT) {
@@ -678,12 +678,12 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
if (libxl__device_kind_from_string(kinds[i], &kind))
continue;
- path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]);
+ path = GCSPRINTF("/libxl/%d/device/%s", domid, kinds[i]);
devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries);
if (!devs)
continue;
for (j = 0; j < num_dev_xsentries; j++) {
- path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend",
+ path = GCSPRINTF("/libxl/%d/device/%s/%s/backend",
domid, kinds[i], devs[j]);
path = libxl__xs_read(gc, XBT_NULL, path);
GCNEW(dev);
@@ -708,22 +708,6 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
}
}
- /* console 0 frontend directory is not under /local/domain/<domid>/device */
- path = GCSPRINTF("/local/domain/%d/console/backend", domid);
- path = libxl__xs_read(gc, XBT_NULL, path);
- GCNEW(dev);
- if (path && strcmp(path, "") &&
- libxl__parse_backend_path(gc, path, dev) == 0) {
- dev->domid = domid;
- dev->kind = LIBXL__DEVICE_KIND_CONSOLE;
- dev->devid = 0;
-
- /* Currently console devices can be destroyed synchronously by just
- * removing xenstore entries, this is what libxl__device_destroy does.
- */
- libxl__device_destroy(gc, dev);
- }
-
out:
libxl__multidev_prepared(egc, multidev, rc);
}
--
2.1.4
[-- Attachment #42: xsa175-4.4/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch --]
[-- Type: application/octet-stream, Size: 1395 bytes --]
From 90f14dc5c68f52baeef9722090695a166c7e083d Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 4 May 2016 15:30:32 +0100
Subject: [PATCH 04/10] libxl: Do not trust frontend in libxl__device_nextid
When selecting the devid for a new device, we should look in
/libxl/device for existing devices, not in the frontend area.
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 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index e2a5be3..b52e63e 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1743,15 +1743,16 @@ out:
/* common function to get next device id */
static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
{
- char *dompath, **l;
+ char *libxl_dom_path, **l;
unsigned int nb;
int nextid = -1;
- if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
return nextid;
l = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/device/%s", dompath, device), &nb);
+ GCSPRINTF("%s/device/%s", libxl_dom_path, device),
+ &nb);
if (l == NULL || nb == 0)
nextid = 0;
else
--
2.1.4
[-- Attachment #43: xsa175-4.4/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch --]
[-- Type: application/octet-stream, Size: 3890 bytes --]
From d84e538d96525f75fc0aa7d0ebe3cd194186d0d4 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:08:49 +0100
Subject: [PATCH 05/10] libxl: Do not trust frontend for disk eject event
Use the /libxl path for interpreting disk eject watch events: do not
read the backend path out of the frontend. Instead, use the version
in /libxl. That avoids us relying on the guest-modifiable
$frontend/backend pointer.
To implement this we store the path
/libxl/$guest/device/vbd/$devid/backend
in the evgen structure.
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 | 28 ++++++++++++++++++++++------
tools/libxl/libxl_internal.h | 2 +-
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b52e63e..f101334 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1141,9 +1141,10 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
const char *wpath, const char *epath) {
EGC_GC;
libxl_evgen_disk_eject *evg = (void*)w;
- char *backend;
+ const char *backend;
char *value;
char backend_type[BACKEND_STRING_SIZE+1];
+ int rc;
value = libxl__xs_read(gc, XBT_NULL, wpath);
@@ -1159,9 +1160,16 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
libxl_device_disk *disk = &ev->u.disk_eject.disk;
- backend = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%.*s/backend",
- (int)strlen(wpath)-6, wpath));
+ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
+ if (rc) {
+ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+ if (!backend) {
+ /* device has been removed, not simply ejected */
+ return;
+ }
sscanf(backend,
"/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
@@ -1210,11 +1218,18 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
if (!domid)
domid = guest_domid;
- path = libxl__sprintf(gc, "%s/device/vbd/%d/eject",
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+
+ path = GCSPRINTF("%s/device/vbd/%d/eject",
libxl__xs_get_dompath(gc, domid),
- libxl__device_disk_dev_number(vdev, NULL, NULL));
+ devid);
if (!path) { rc = ERROR_NOMEM; goto out; }
+ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid),
+ devid);
+ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
+
rc = libxl__ev_xswatch_register(gc, &evg->watch,
disk_eject_xswatch_callback, path);
if (rc) goto out;
@@ -1241,6 +1256,7 @@ void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
libxl__ev_xswatch_deregister(gc, &evg->watch);
free(evg->vdev);
+ free(evg->be_ptr_path);
free(evg);
CTX_UNLOCK;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 3fc9997..8128e76 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -257,7 +257,7 @@ struct libxl__evgen_disk_eject {
uint32_t domid;
LIBXL_LIST_ENTRY(libxl_evgen_disk_eject) entry;
libxl_ev_user user;
- char *vdev;
+ char *vdev, *be_ptr_path;
};
_hidden void
libxl__evdisable_disk_eject(libxl__gc*, libxl_evgen_disk_eject*);
--
2.1.4
[-- Attachment #44: xsa175-4.4/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 3378 bytes --]
From 3d1d7473c756d79e464600cee370c8759bd20f89 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Fri, 29 Apr 2016 19:21:51 +0100
Subject: [PATCH 06/10] libxl: Do not trust frontend for disk in getinfo
* Rename the frontend variable to `fe_path' to check we caught them all
* Read the backend path from /libxl, rather than from the frontend
* Parse the backend domid from the backend path, rather than reading it
from the frontend (and add the appropriate error path and initialisation)
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 | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index f101334..18f9f0a 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2449,27 +2449,34 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk, libxl_diskinfo *diskinfo)
{
GC_INIT(ctx);
- char *dompath, *diskpath;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
+
+ diskinfo->backend = NULL;
dompath = libxl__xs_get_dompath(gc, domid);
diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
/* tap devices entries in xenstore are written as vbd devices. */
- diskpath = libxl__sprintf(gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
+ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid), diskinfo->devid);
diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", diskpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!diskinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", diskpath));
- diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", diskpath));
+ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
+ &diskinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/ring-ref", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
libxl__sprintf(gc, "%s/frontend", diskinfo->backend), NULL);
@@ -2478,6 +2485,10 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
GC_FREE;
return 0;
+
+ out:
+ free(diskinfo->backend);
+ return rc;
}
int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
--
2.1.4
[-- Attachment #45: xsa175-4.4/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch --]
[-- Type: application/octet-stream, Size: 2387 bytes --]
From 44aadb912061fc75e41fceb00c67b8d222a2c7c4 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:58:32 +0100
Subject: [PATCH 07/10] libxl: Do not trust frontend for vtpm list
libxl_device_vtpm_list needs to enumerate and identify devices without
trusting frontend-controlled data. So
* Use the /libxl path to enumerate vtpms.
* Use the /libxl path to find the corresponding backends.
* Parse the backend path to find the backend domid.
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 | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 18f9f0a..0886d92 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1879,14 +1879,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
GC_INIT(ctx);
libxl_device_vtpm* vtpms = NULL;
- char* fe_path = NULL;
+ char *libxl_path;
char** dir = NULL;
unsigned int ndirs = 0;
+ int rc;
*num = 0;
- fe_path = libxl__sprintf(gc, "%s/device/vtpm", libxl__xs_get_dompath(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+ libxl_path = GCSPRINTF("%s/device/vtpm", libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);
if (dir && ndirs) {
vtpms = malloc(sizeof(*vtpms) * ndirs);
libxl_device_vtpm* vtpm;
@@ -1895,16 +1896,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
char* tmp;
const char* be_path = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/%s/backend",
- fe_path, *dir));
+ libxl_path, *dir));
libxl_device_vtpm_init(vtpm);
vtpm->devid = atoi(*dir);
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/%s/backend-id",
- fe_path, *dir));
- vtpm->backend_domid = atoi(tmp);
+ rc = libxl__backendpath_parse_domid(gc, be_path,
+ &vtpm->backend_domid);
+ if (rc) return NULL;
tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
if (tmp) {
--
2.1.4
[-- Attachment #46: xsa175-4.4/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2100 bytes --]
From 593d796c753fea1c4cdc365273de777aff798fe9 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:00:20 +0100
Subject: [PATCH 08/10] libxl: Do not trust frontend for vtpm in getinfo
libxl_device_vtpm_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 0886d92..a0aeb50 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1928,7 +1928,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
libxl_vtpminfo *vtpminfo)
{
GC_INIT(ctx);
- char *dompath, *vtpmpath;
+ char *libxl_path, *dompath, *vtpmpath;
char *val;
int rc = 0;
@@ -1937,8 +1937,10 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
vtpminfo->devid = vtpm->devid;
vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vtpm/%d",
+ libxl__xs_libxl_path(gc, domid), vtpminfo->devid);
vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", vtpmpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!vtpminfo->backend) {
goto err;
}
@@ -1946,9 +1948,9 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
goto err;
}
- val = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/backend-id", vtpmpath));
- vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
+ &vtpminfo->backend_id);
+ if (rc) goto exit;
val = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/state", vtpmpath));
--
2.1.4
[-- Attachment #47: xsa175-4.4/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch --]
[-- Type: application/octet-stream, Size: 1505 bytes --]
From a7fb7be6b7a14e8ca5ab0609c49b06545d6772bf Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:52:53 +0100
Subject: [PATCH 09/10] libxl: Do not trust frontend for nic in
libxl_devid_to_device_nic
Find the backend by reading the pointer in /libxl rather than in the
guest's frontend area.
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 | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index a0aeb50..7a8faba 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3066,17 +3066,17 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_nic *nic)
{
GC_INIT(ctx);
- char *dompath, *path;
+ char *libxl_dom_path, *path;
int rc = ERROR_FAIL;
libxl_device_nic_init(nic);
- dompath = libxl__xs_get_dompath(gc, domid);
- if (!dompath)
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ if (!libxl_dom_path)
goto out;
path = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%s/device/vif/%d/backend",
- dompath, devid));
+ GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path,
+ devid));
if (!path)
goto out;
--
2.1.4
[-- Attachment #48: xsa175-4.4/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2812 bytes --]
From e4c0f9b55819194a501e3ecae6b12188a2db1d01 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:31:07 +0100
Subject: [PATCH 10/10] libxl: Do not trust frontend for nic in getinfo
libxl_device_nic_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 7a8faba..c794d3a 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3155,22 +3155,27 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic, libxl_nicinfo *nicinfo)
{
GC_INIT(ctx);
- char *dompath, *nicpath;
+ char *dompath, *nicpath, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
nicinfo->devid = nic->devid;
- nicpath = libxl__sprintf(gc, "%s/device/vif/%d", dompath, nicinfo->devid);
+ nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vif/%d",
+ libxl__xs_libxl_path(gc, domid), nicinfo->devid);
nicinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", nicpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!nicinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", nicpath));
- nicinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", nicpath));
+ rc = libxl__backendpath_parse_domid(gc, nicinfo->backend,
+ &nicinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath));
nicinfo->state = val ? strtoul(val, NULL, 10) : -1;
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", nicpath));
nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
@@ -3183,8 +3188,10 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend-id", nicinfo->backend));
nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
const char *libxl__device_nic_devname(libxl__gc *gc,
--
2.1.4
[-- Attachment #49: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 2+ messages in thread* Xen Security Advisory 175 (CVE-2016-4962) - Unsanitised guest input in libxl device handling code
@ 2016-06-06 16:56 Xen.org security team
0 siblings, 0 replies; 2+ messages in thread
From: Xen.org security team @ 2016-06-06 16:56 UTC (permalink / raw)
To: xen-announce, xen-devel, xen-users, oss-security; +Cc: Xen.org security team
[-- Attachment #1: Type: text/plain, Size: 13873 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Xen Security Advisory CVE-2016-4962 / XSA-175
version 6
Unsanitised guest input in libxl device handling code
UPDATES IN VERSION 6
====================
Mention backports to Xen 4.3.
ISSUE DESCRIPTION
=================
Various parts of libxl device-handling code inappropriately use
information from (partially) guest controlled areas of xenstore
(principally the frontend directory
/local/domain/GUEST/device/TYPE/DEVID,
henceforth referred to as FE). The problems vary by device type:
For almost all device types (all devices except consoles and
channels), the guest has the ability to completely remove FE. This
will normally result in the virtual device no longer functioning
(which is bad for the guest and an outcome the guest could achieve
anyway). But it will also cause the device not to appear in lists of
devices, and prevent the device being properly torn down during domain
destruction (including guest reboot and migration). When such a
malicious domain is shut down, the host resources associated with the
manipulated devices may remain in use: for example, disk and nic
hotplug teardown scripts will not be run. For resources allocated in
an manner which excludes some other accesses, this can prevent the
operation of that other software on the host (for example, it can
prevent management operations on the underlying objects); for
resources are allocated in a nonexclusive manner, the guest can
consume new resources with each successive guest boot, eventually
exhausting capacity.
For all devices other than the main PV console, the guest can write
FE/backend to point to the backend of a device belonging to a
different guest. On subsequent domain removal (for example, by guest
reboot or migration) libxl uses this value with insufficient checks,
allowing libxl to be tricked into failing to tear down the device
properly.
For almost all device types the backend xenstore path and domid
returned to libxl's caller during query functions servicing the domain
are read from a guest-controlled part of xenstore. This means that a
guest can cause incorrect displays in tools like xl, and possibly
cause maloperation by higher-level domain management systems.
For all device types, libxl would read the guest-writeable FE/backend
node to find the xenstore path to the backend. A guest could write a
bad value, which would (mostly) be detected by libxl but would cause
libxl operations (including informational functions) to fail.
For consoles, vtpm and channel devices, libxl would use FE/backend
without checking, to discover important information about the device.
For vtpm devices, this means guest can manipulate the
apparently-configured uuid. For channel devices, the guest can
manipulate the apparently-configured channel name.
For channel devices, the guest can trick console attachment tools in
the backend domain into connecting to arbitrary wrong paths on the
backend domain filesystem.
IMPACT
======
A malicious guest administrator can cause denial of service by
resource exhaustion.
A malicious guest administrator can confuse and/or deny service to
management facilities.
A malicious guest administrator of a guest configured with channel
devices may be able to escalate their privilege to that of the backend
domain (i.e., normally, to that of the host).
VULNERABLE SYSTEMS
==================
Xen systems using libxl based toolstacks (for example xl or libvirt
with the libxl driver) are vulnerable to denial of service to guests
and administrators.
Xen systems with guests configured with channel devices are possibly
vulnerable to privilege escalation by those guests.
(Channel devices are be configured with "channel=" in the xl domain
configuration file. See
http://xenbits.xen.org/docs/4.6-testing/misc/channel.txt
for more information.)
MITIGATION
==========
Disabling channel devices in applicable guests will reduce the
impact of the vulnerability.
Limiting the frequency with which a guest is able to reboot, or
limiting or eliminating a guest's ability to be granted exclusive
access to host resources, will reduce the resource exhaustion impact.
CREDITS
=======
This issue was discovered by Wei Liu from Citrix.
RESOLUTION
==========
Applying the appropriate attached patch resolves this issue.
xsa175-unstable/*.patch xen-unstable
xsa175-4.6/*.patch xen-4.6
xsa175-4.5/*.patch xen-4.5
xsa175-4.4/*.patch xen-4.4
For Xen 4.3, patches are available in xen.git#staging-4.3. They are
currently undergoing testing by the Xen Project CI system, osstest:
xen.git commits 0376b6bb2a89..5811d6bdf5bb Xen 4.3
See:
http://xenbits.xen.org/gitweb/?p=xen.git;a=summary
git://xenbits.xen.org/xen.git
http://xenbits.xen.org/git-http/xen.git
$ sha256sum xsa175-*/*
473fdf33f6f26c0655b504e2cc384c20904bcdd713fbacc4236f499a0a6f8ac3 xsa175-unstable/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch
531b2233581d847f26eeffc5fa7c1428a2f42336aed7943165da881003d4be90 xsa175-unstable/0002-libxl-Provide-libxl__backendpath_parse_domid.patch
cfb45654444a95e80a2b9608448b1092f407b9a9d52436ce49c45978e5e8c310 xsa175-unstable/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch
361cc95707bba9b1801e4972016ca61ab6d8103f93b0141758112eaa61d9113d xsa175-unstable/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch
f21e63a17728e638d4e33e074e5a35fa9eb18f13c0051d9bef0d7849b60de649 xsa175-unstable/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch
0fe8d5e65103a9fc2b54692726ab66ddf4004a641e5b6730ee97c7b1621d6543 xsa175-unstable/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch
dd06e96c10c51829d7489c72d2560a9bbd12dbd727a0bb492810b334d0623296 xsa175-unstable/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch
64e56d387e418082dbd0088a012e263abda0d452a77ff7c2273cb7425d45fc60 xsa175-unstable/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch
6e3b59ac930d5210032bf1015782c14bc94881e8734e451e3d5f0c3e794f4d34 xsa175-unstable/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch
2c9a23f859bf8ecd1800089ca7f9032b24311a90c4cfe38f2a26f5ee6a8443c6 xsa175-unstable/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch
43d39d6544893c76a91c056543d46a0bfa32cf2891d234815b6a3d43d87fa5ef xsa175-unstable/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch
82da838f3daff7f225426b6572e7f7577e821f3546bb1d2ddafd72fbc8839a0d xsa175-unstable/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch
e732be8fae0d7c7de487a6a7ab919f2b91005067ce2dcf7083195fb74e2943de xsa175-unstable/0013-libxl-Do-not-trust-frontend-for-vusb.patch
c44dcbf52358b8747c922257cad3d03cc056ecc03ecd396e50f6b3f6d1cea798 xsa175-4.6/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch
fd11a983dc1f125901daaa9c9019edb46c3d16a9371399a6e9c9ef4a23b54276 xsa175-4.6/0002-libxl-Provide-libxl__backendpath_parse_domid.patch
f50f7156dc5595d1d1839c225ac8c4bd767511bc6ce4aec5f60b9ab207ea7631 xsa175-4.6/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch
09b2faa98ec3db11142c17fd4d9e055505f4552ff43e48da4d30ebcbf6b929f4 xsa175-4.6/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch
4fa05ee839da5bae49e4b403a2d13da802e10f7aa586007da89e73c6fd6719b7 xsa175-4.6/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch
92f423b541e9447f0bf37a83bbece2cfe198b1db33ca02cd3f6ca17bad203f2f xsa175-4.6/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch
97fb68eda21ab0151e6e240ddde34da0da0e8f11ea448f4603d7ef2326acda70 xsa175-4.6/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch
9cde88602e13c2964307fa1bc5b1601dc6796d4b9d9b9e49898e1d13470c71ab xsa175-4.6/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch
69a19ee15ad266e391b4356a2f6ad3442a905cd06441921ae4e2c2778823f8ae xsa175-4.6/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch
51fadcafa1549201d6dd4eda9c3f8b9d2c7cad6851f2aafe3569ec3980c5a256 xsa175-4.6/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch
dc925af06451392d87f8750b3be2ad60b95be107f2534391063732f1e1b5109a xsa175-4.6/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch
57211890bf71f7648f5b3f7a88f79fddb7d3077eb3a1bc3cbd6f910fa324dfd1 xsa175-4.6/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch
a262c85f9145f71df512338ef1a4b77c05086a894d58ba3d911ea6984bbeaed5 xsa175-4.5/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch
676806c5713a60f113264298c48c3ac34e3370a6bfb8628d5b8700edfe2415e3 xsa175-4.5/0002-libxl-Provide-libxl__backendpath_parse_domid.patch
50518f86aedf7857ca3644a2f073745017d12263880990cb7f0d4b3b9e264ac5 xsa175-4.5/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch
e9207a4a35c13061b502935a31ad09cf4ca8048804f1a62d1c1ccfde5ff3432c xsa175-4.5/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch
78baa5268af36baa546e4cd8e7f62d830c860ee3051bba5273266ca0f95627ae xsa175-4.5/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch
c59be732bbf602d7d3b5dcbf3a0ca86d6f624585ba2e29f8d0f82c74f7bd33a3 xsa175-4.5/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch
5c1aa2cc37240cdc4dce5c5067f18c36466d9271ab81c6a7a38d8674b534cd86 xsa175-4.5/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch
020287ae99d9c049c12087d828ea2d898686ab8600c0f9f8f2042b297ebc968e xsa175-4.5/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch
4781d673403b3bb0f43196af1aec52f8769bcf7352afd239d874f381a1d0e9cc xsa175-4.5/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch
c6a0fb210488794188924a90df4450e42782f99651b7a016e072a7df7d26d3d6 xsa175-4.5/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch
3f3eec4f45925a9de39fcfd14e7709b3fc8245425b8ae45213afee1ede2b09a0 xsa175-4.5/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch
084b0054f223addeab3ff951ac1362b7d48379ddf0556eae9971f1a87507c2d4 xsa175-4.5/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch
cefe2c82a30227b6538c6924d7d939192be3c481e48ac94c82f4c51f60388570 xsa175-4.4/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch
f24b26891fac4e8bf8a0939a5b64fc7ad096ef699f1882aad6e96cf81b85fc3e xsa175-4.4/0002-libxl-Provide-libxl__backendpath_parse_domid.patch
748ea9d369b1f8372d1a4c420e6a9d90f881b7142e7913ed5d72b99c07ac11a0 xsa175-4.4/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch
9f4011a48b01a36087e019f2c4bcdea91c8f2dabce5bd6b9a4cb7fd70f343c50 xsa175-4.4/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch
012c86146bbb67c2bb9424ba76294e6c6eca033d932d543e0e58f83e91d79e7b xsa175-4.4/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch
be5665c91b0dfd79c8c4bb35d5adfb719ab23a547479a14aacac9d5f46d77a0f xsa175-4.4/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch
9068b9025ad079d1ec1cacc399a72b5dc1836894683b2545274e8b19b795cd60 xsa175-4.4/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch
b57f96af3c1cac5f56a684afe223b4a977c144daf8d5f2a1e184697cd29fdbe2 xsa175-4.4/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch
c8941fcf41edae75fa5a1b417d9b457fdd67a5531b6cf75dc16da9d63697c61f xsa175-4.4/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch
0641b38b7718d5fa84a8ce12a2bf034273caeb1e372f48b73170b3fd085f169c xsa175-4.4/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch
$
NOTE REGARDING EMBARGO LENGTH
=============================
Due to the complexity and centrality of the set of patches, the
security team suggested a three-week embargo rather than the normal
two-week embargo, and the discoverer agreed.
Please do your best to test these patches as thoroughly and as early
as possible, and report any problems.
DEPLOYMENT DURING EMBARGO
=========================
Deployment of patches or mitigations not explicitly allowed below is
NOT permitted (except where all the affected systems and VMs are
administered and used only by organisations which are members of the
Xen Project Security Issues Predisclosure List). Specifically,
deployment on public cloud systems is NOT permitted.
This is because the patches and mitigations result in guest-visible
changes in the information recorded in xenstore, which might lead a
guest administrator to understand the nature of the vulnerability.
Deployment is permitted only AFTER the embargo ends.
HOWEVER, deployment of the following IS is permitted during the
embargo, even on public-facing systems with untrusted guest users and
administrators:
* The patches for XSA-175 EXCEPT for the one patch
libxl: Do not trust frontend for channel in list
* The mitigation of limiting reboot frequency
In any case: Distribution of updated software is prohibited (except to
other members of the predisclosure list).
Predisclosure list members who wish to deploy significantly different
patches and/or mitigations, please contact the Xen Project Security
Team.
(Note: this during-embargo deployment notice is retained in
post-embargo publicly released Xen Project advisories, even though it
is then no longer applicable. This is to enable the community to have
oversight of the Xen Project Security Team's decisionmaking.)
For more information about permissible uses of embargoed information,
consult the Xen Project community's agreed Security Policy:
http://www.xenproject.org/security-policy.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)
iQEcBAEBAgAGBQJXVasOAAoJEIP+FMlX6CvZ83MIAMzwIsqiPv/NkojKD0YKW/0u
OvwwUeV3ZcsZAGGX1JzGodf2ifr4Jfhrm+K4PcaGyohKlt3adC3d+ffgJnyxAocd
R+PWXZGvOcDVaYqqp4PTeOx0AsQhvGJN+gmIt+mr5E6GgGfAH4O7aX3X/jlShR/L
3EDRtE8dg46xFillttUrHHgcvpIJfOB4kdV2G0FhlYIdlUt6EgFUvg4V+I4l28/v
EawBtmaunm2YL/U2fsBK5dj52JxiSNStmwe/heaubH50idHCWZSRI8O9rrXP+ijC
8ruOpPFUKt0XtlxqvqDEPhhrkB1gAYc82g451p3SpjdDbco/TyTqpbOmavhWo9M=
=0dH3
-----END PGP SIGNATURE-----
[-- Attachment #2: xsa175-unstable/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch --]
[-- Type: application/octet-stream, Size: 7592 bytes --]
From c4fa93745a68a8f6bdf8959cda4802907b3cfdcd Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 15:50:01 +0100
Subject: [PATCH 01/34] libxl: Record backend/frontend paths in /libxl/$DOMID
This gives us a record of all the backends we have set up for a
domain, which is separate from the frontends in
/local/domain/$DOMID/device.
In particular:
1. A guest has write permission for the frontend path:
/local/domain/$DOMID/device/$KIND/$DEVID
which means that the guest can completely delete the frontend.
(They can't recreate it because they don't have write permission
on the containing directory.)
2. A guest has write permission for the backend path recorded in the
frontend, ie, it can write to
/local/domain/$DOMID/device/$KIND/$DEVID/backend
which means that the guest can break the association between
frontend and backend.
So we can't rely on iterating over the frontends to find all the
backends, or examining a frontend to discover how a device is
configured.
So, have libxl__device_generic_add record the frontend and backend
paths in /libxl/$DOMID/device, and have libxl__device_destroy remove
them again.
Create the containing directory /libxl/GUEST/device in
libxl__domain_make. The already existing xs_rm in devices_destroy_cb
will take care of removing it.
This is part of XSA-175.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v2: Correct actual path computation (!)
v3: Correct actual path computation - really this time (!)
---
docs/misc/xenstore-paths.markdown | 15 +++++++++++++++
tools/libxl/libxl_create.c | 2 ++
tools/libxl/libxl_device.c | 36 ++++++++++++++++++++++++++++++++++--
tools/libxl/libxl_internal.h | 1 +
4 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index 2a37dae..2f545c1 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -534,6 +534,21 @@ The guest's virtual time offset from UTC in seconds.
### libxl Specific Paths
+#### /libxl/$DOMID/device/$KIND/$DEVID
+
+Created by libxl for every frontend/backend pair created for $DOMID.
+Used by libxl for enumeration and management of the device.
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/frontend
+
+Path in xenstore to the frontend, normally
+/local/domain/$DOMID/device/$KIND/$DEVID
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/backend
+
+Path in xenstore to the backend, normally
+/local/domain/$BACKEND_DOMID/backend/$KIND/$DOMID/$DEVID
+
#### /libxl/$DOMID/dm-version ("qemu\_xen"|"qemu\_xen\_traditional") = [n,INTERNAL]
The device model version for a domain.
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 5000bd0..703b4ea 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -617,6 +617,8 @@ retry_transaction:
xs_rm(ctx->xsh, t, libxl_path);
libxl__xs_mknod(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));
+ libxl__xs_mknod(gc, t, GCSPRINTF("%s/device", libxl_path),
+ noperm, ARRAY_SIZE(noperm));
xs_write(ctx->xsh, t, GCSPRINTF("%s/vm", dom_path), vm_path, strlen(vm_path));
rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index f79e536..b4bd005 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -40,6 +40,15 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
device->domid, device->devid);
}
+char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device)
+{
+ char *libxl_dom_path = libxl__xs_libxl_path(gc, device->domid);
+
+ return GCSPRINTF("%s/device/%s/%d", libxl_dom_path,
+ libxl__device_kind_to_string(device->kind),
+ device->devid);
+}
+
/* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
libxl__device *device)
@@ -105,14 +114,16 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- char *frontend_path, *backend_path;
+ char *frontend_path, *backend_path, *libxl_path;
struct xs_permissions frontend_perms[2];
struct xs_permissions ro_frontend_perms[2];
struct xs_permissions backend_perms[2];
int create_transaction = t == XBT_NULL;
+ int rc;
frontend_path = libxl__device_frontend_path(gc, device);
backend_path = libxl__device_backend_path(gc, device);
+ libxl_path = libxl__device_libxl_path(gc, device);
frontend_perms[0].id = device->domid;
frontend_perms[0].perms = XS_PERM_NONE;
@@ -127,8 +138,22 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
retry_transaction:
if (create_transaction)
t = xs_transaction_start(ctx->xsh);
+
/* FIXME: read frontend_path and check state before removing stuff */
+ rc = libxl__xs_rm_checked(gc, t, libxl_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/frontend",libxl_path),
+ frontend_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/backend",libxl_path),
+ backend_path);
+ if (rc) goto out;
+
+ /* xxx much of this function lacks error checks! */
+
if (fents || ro_fents) {
xs_rm(ctx->xsh, t, frontend_path);
xs_mkdir(ctx->xsh, t, frontend_path);
@@ -174,6 +199,11 @@ retry_transaction:
}
}
return 0;
+
+ out:
+ if (create_transaction && t)
+ libxl__xs_transaction_abort(gc, &t);
+ return rc;
}
typedef struct {
@@ -649,6 +679,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
{
const char *be_path = libxl__device_backend_path(gc, dev);
const char *fe_path = libxl__device_frontend_path(gc, dev);
+ const char *libxl_path = libxl__device_libxl_path(gc, dev);
const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params");
const char *tapdisk_params;
xs_transaction_t t = 0;
@@ -669,9 +700,10 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
if (domid == LIBXL_TOOLSTACK_DOMID) {
/*
* The toolstack domain is in charge of removing the
- * frontend path.
+ * frontend and libxl paths.
*/
libxl__xs_path_cleanup(gc, t, fe_path);
+ libxl__xs_path_cleanup(gc, t, libxl_path);
}
if (dev->backend_domid == domid) {
/*
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index c791418..2cb8133 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1182,6 +1182,7 @@ _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, 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 char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
--
2.1.4
[-- Attachment #3: xsa175-unstable/0002-libxl-Provide-libxl__backendpath_parse_domid.patch --]
[-- Type: application/octet-stream, Size: 2228 bytes --]
From 0612cda6977ac22cc8c71d3e624a86d3cfcaf019 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:34:19 +0100
Subject: [PATCH 02/34] libxl: Provide libxl__backendpath_parse_domid
Multiple places in libxl need to figure out the backend domid of a
device. This can be discovered easily by looking at the backend path,
which always starts /local/domain/$backend_domid/.
There are no call sites yet.
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_device.c | 15 +++++++++++++++
tools/libxl/libxl_internal.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index b4bd005..9f115c6 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -298,6 +298,21 @@ static int disk_try_backend(disk_try_backend_args *a,
return 0;
}
+int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out) {
+ int r;
+ unsigned int domid_sc;
+ char delim_sc;
+
+ r = sscanf(be_path, "/local/domain/%u%c", &domid_sc, &delim_sc);
+ if (!(r==2 && delim_sc=='/')) {
+ LOG(ERROR, "internal error: backend path %s unparseable!", be_path);
+ return ERROR_FAIL;
+ }
+ *domid_out = domid_sc;
+ return 0;
+}
+
int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
libxl_disk_backend ok;
disk_try_backend_args a;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 2cb8133..9f381fb 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -702,6 +702,8 @@ _hidden char **libxl__xs_directory(libxl__gc *gc, xs_transaction_t t,
/* On error: returns NULL, sets errno (no logging) */
_hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid);
+_hidden int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out);
/*----- "checked" xenstore access functions -----*/
/* Each of these functions will check that it succeeded; if it
--
2.1.4
[-- Attachment #4: xsa175-unstable/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]
From 092c134ab57de7a1eb6bb6032c3de89c1d5e790a Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 18:39:36 +0100
Subject: [PATCH 03/34] libxl: Do not trust frontend in libxl__devices_destroy
We need to enumerate the devices we have provided to a domain, without
trusting the guest-writeable (or, at least, guest-deletable) frontend
paths.
Instead, enumerate via, and read the backend path from, /libxl.
The console /libxl path is regular, so the special case for console 0
is not relevant any more: /libxl/GUEST/device/console/0 will be found,
and then libxl__device_destroy will DTRT to the right frontend path.
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_device.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 9f115c6..16384f8 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -762,7 +762,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
libxl__multidev_begin(ao, multidev);
multidev->callback = devices_remove_callback;
- path = GCSPRINTF("/local/domain/%d/device", domid);
+ path = GCSPRINTF("/libxl/%d/device", domid);
kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
if (!kinds) {
if (errno != ENOENT) {
@@ -775,12 +775,12 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
if (libxl__device_kind_from_string(kinds[i], &kind))
continue;
- path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]);
+ path = GCSPRINTF("/libxl/%d/device/%s", domid, kinds[i]);
devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries);
if (!devs)
continue;
for (j = 0; j < num_dev_xsentries; j++) {
- path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend",
+ path = GCSPRINTF("/libxl/%d/device/%s/%s/backend",
domid, kinds[i], devs[j]);
path = libxl__xs_read(gc, XBT_NULL, path);
GCNEW(dev);
@@ -809,22 +809,6 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
}
}
- /* console 0 frontend directory is not under /local/domain/<domid>/device */
- path = GCSPRINTF("/local/domain/%d/console/backend", domid);
- path = libxl__xs_read(gc, XBT_NULL, path);
- GCNEW(dev);
- if (path && strcmp(path, "") &&
- libxl__parse_backend_path(gc, path, dev) == 0) {
- dev->domid = domid;
- dev->kind = LIBXL__DEVICE_KIND_CONSOLE;
- dev->devid = 0;
-
- /* Currently console devices can be destroyed synchronously by just
- * removing xenstore entries, this is what libxl__device_destroy does.
- */
- libxl__device_destroy(gc, dev);
- }
-
out:
libxl__multidev_prepared(egc, multidev, rc);
}
--
2.1.4
[-- Attachment #5: xsa175-unstable/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch --]
[-- Type: application/octet-stream, Size: 1388 bytes --]
From b23d6cd8fe57c1753bfed3fc1305bca7a9c645f0 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 4 May 2016 15:30:32 +0100
Subject: [PATCH 04/34] libxl: Do not trust frontend in libxl__device_nextid
When selecting the devid for a new device, we should look in
/libxl/device for existing devices, not in the frontend area.
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 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index c39d745..1e538c3 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1986,15 +1986,16 @@ out:
/* common function to get next device id */
int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
{
- char *dompath, **l;
+ char *libxl_dom_path, **l;
unsigned int nb;
int nextid = -1;
- if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
return nextid;
l = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/device/%s", dompath, device), &nb);
+ GCSPRINTF("%s/device/%s", libxl_dom_path, device),
+ &nb);
if (l == NULL || nb == 0)
nextid = 0;
else
--
2.1.4
[-- Attachment #6: xsa175-unstable/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch --]
[-- Type: application/octet-stream, Size: 3817 bytes --]
From b2b5150f0a90103c6df34b47eca7bb92bc3d2b87 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:08:49 +0100
Subject: [PATCH 05/34] libxl: Do not trust frontend for disk eject event
Use the /libxl path for interpreting disk eject watch events: do not
read the backend path out of the frontend. Instead, use the version
in /libxl. That avoids us relying on the guest-modifiable
$frontend/backend pointer.
To implement this we store the path
/libxl/$guest/device/vbd/$devid/backend
in the evgen structure.
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 | 26 +++++++++++++++++++++-----
tools/libxl/libxl_internal.h | 2 +-
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 1e538c3..2dc82f8 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1312,9 +1312,10 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
const char *wpath, const char *epath) {
EGC_GC;
libxl_evgen_disk_eject *evg = (void*)w;
- char *backend;
+ const char *backend;
char *value;
char backend_type[BACKEND_STRING_SIZE+1];
+ int rc;
value = libxl__xs_read(gc, XBT_NULL, wpath);
@@ -1330,9 +1331,16 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
libxl_device_disk *disk = &ev->u.disk_eject.disk;
- backend = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%.*s/backend", (int)strlen(wpath)-6,
- wpath));
+ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
+ if (rc) {
+ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+ if (!backend) {
+ /* device has been removed, not simply ejected */
+ return;
+ }
sscanf(backend,
"/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
@@ -1381,11 +1389,18 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
if (!domid)
domid = guest_domid;
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+
path = GCSPRINTF("%s/device/vbd/%d/eject",
libxl__xs_get_dompath(gc, domid),
- libxl__device_disk_dev_number(vdev, NULL, NULL));
+ devid);
if (!path) { rc = ERROR_NOMEM; goto out; }
+ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid),
+ devid);
+ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
+
rc = libxl__ev_xswatch_register(gc, &evg->watch,
disk_eject_xswatch_callback, path);
if (rc) goto out;
@@ -1412,6 +1427,7 @@ void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
libxl__ev_xswatch_deregister(gc, &evg->watch);
free(evg->vdev);
+ free(evg->be_ptr_path);
free(evg);
CTX_UNLOCK;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 9f381fb..7dc702c 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -360,7 +360,7 @@ struct libxl__evgen_disk_eject {
uint32_t domid;
LIBXL_LIST_ENTRY(libxl_evgen_disk_eject) entry;
libxl_ev_user user;
- char *vdev;
+ char *vdev, *be_ptr_path;
};
_hidden void
libxl__evdisable_disk_eject(libxl__gc*, libxl_evgen_disk_eject*);
--
2.1.4
[-- Attachment #7: xsa175-unstable/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 3315 bytes --]
From d90149b39f8cdcfe0ddfc73148ece38ba6ab0f05 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Fri, 29 Apr 2016 19:21:51 +0100
Subject: [PATCH 06/34] libxl: Do not trust frontend for disk in getinfo
* Rename the frontend variable to `fe_path' to check we caught them all
* Read the backend path from /libxl, rather than from the frontend
* Parse the backend domid from the backend path, rather than reading it
from the frontend (and add the appropriate error path and initialisation)
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 | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 2dc82f8..191c939 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2849,27 +2849,34 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk, libxl_diskinfo *diskinfo)
{
GC_INIT(ctx);
- char *dompath, *diskpath;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
+
+ diskinfo->backend = NULL;
dompath = libxl__xs_get_dompath(gc, domid);
diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
/* tap devices entries in xenstore are written as vbd devices. */
- diskpath = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid), diskinfo->devid);
diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", diskpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!diskinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", diskpath));
- diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", diskpath));
+ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
+ &diskinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
GCSPRINTF("%s/frontend", diskinfo->backend), NULL);
@@ -2878,6 +2885,10 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
GC_FREE;
return 0;
+
+ out:
+ free(diskinfo->backend);
+ return rc;
}
int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
--
2.1.4
[-- Attachment #8: xsa175-unstable/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch --]
[-- Type: application/octet-stream, Size: 2378 bytes --]
From 33194a0226ecd1db19cfb54bb635774e5934cff9 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:58:32 +0100
Subject: [PATCH 07/34] libxl: Do not trust frontend for vtpm list
libxl_device_vtpm_list needs to enumerate and identify devices without
trusting frontend-controlled data. So
* Use the /libxl path to enumerate vtpms.
* Use the /libxl path to find the corresponding backends.
* Parse the backend path to find the backend domid.
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 | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 191c939..07a0fec 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2176,14 +2176,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
GC_INIT(ctx);
libxl_device_vtpm* vtpms = NULL;
- char* fe_path = NULL;
+ char *libxl_path;
char** dir = NULL;
unsigned int ndirs = 0;
+ int rc;
*num = 0;
- fe_path = GCSPRINTF("%s/device/vtpm", libxl__xs_get_dompath(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+ libxl_path = GCSPRINTF("%s/device/vtpm", libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);
if (dir && ndirs) {
vtpms = malloc(sizeof(*vtpms) * ndirs);
libxl_device_vtpm* vtpm;
@@ -2192,16 +2193,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
char* tmp;
const char* be_path = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/%s/backend",
- fe_path, *dir));
+ libxl_path, *dir));
libxl_device_vtpm_init(vtpm);
vtpm->devid = atoi(*dir);
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/%s/backend-id",
- fe_path, *dir));
- vtpm->backend_domid = atoi(tmp);
+ rc = libxl__backendpath_parse_domid(gc, be_path,
+ &vtpm->backend_domid);
+ if (rc) return NULL;
tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
if (tmp) {
--
2.1.4
[-- Attachment #9: xsa175-unstable/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2100 bytes --]
From af52263d7077950b070af6d83e9c47594a0e1267 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:00:20 +0100
Subject: [PATCH 08/34] libxl: Do not trust frontend for vtpm in getinfo
libxl_device_vtpm_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 07a0fec..8c9cab1 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2225,7 +2225,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
libxl_vtpminfo *vtpminfo)
{
GC_INIT(ctx);
- char *dompath, *vtpmpath;
+ char *libxl_path, *dompath, *vtpmpath;
char *val;
int rc = 0;
@@ -2234,8 +2234,10 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
vtpminfo->devid = vtpm->devid;
vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vtpm/%d",
+ libxl__xs_libxl_path(gc, domid), vtpminfo->devid);
vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", vtpmpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!vtpminfo->backend) {
goto err;
}
@@ -2243,9 +2245,9 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
goto err;
}
- val = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/backend-id", vtpmpath));
- vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
+ &vtpminfo->backend_id);
+ if (rc) goto exit;
val = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/state", vtpmpath));
--
2.1.4
[-- Attachment #10: xsa175-unstable/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch --]
[-- Type: application/octet-stream, Size: 1440 bytes --]
From 9e703fd22bec87b54b5408c8c5559276b36eda61 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:52:53 +0100
Subject: [PATCH 09/34] libxl: Do not trust frontend for nic in
libxl_devid_to_device_nic
Find the backend by reading the pointer in /libxl rather than in the
guest's frontend area.
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 | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 8c9cab1..1ad4536 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3628,16 +3628,16 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_nic *nic)
{
GC_INIT(ctx);
- char *dompath, *path;
+ char *libxl_dom_path, *path;
int rc = ERROR_FAIL;
libxl_device_nic_init(nic);
- dompath = libxl__xs_get_dompath(gc, domid);
- if (!dompath)
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ if (!libxl_dom_path)
goto out;
path = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/device/vif/%d/backend", dompath,
+ GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path,
devid));
if (!path)
goto out;
--
2.1.4
[-- Attachment #11: xsa175-unstable/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2553 bytes --]
From 2cf4309a404d6ccd4d7df91ad43eb16b3b6ce1d8 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:31:07 +0100
Subject: [PATCH 10/34] libxl: Do not trust frontend for nic in getinfo
libxl_device_nic_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 1ad4536..9aa9aa9 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3717,21 +3717,26 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic, libxl_nicinfo *nicinfo)
{
GC_INIT(ctx);
- char *dompath, *nicpath;
+ char *dompath, *nicpath, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
nicinfo->devid = nic->devid;
nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vif/%d",
+ libxl__xs_libxl_path(gc, domid), nicinfo->devid);
nicinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", nicpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!nicinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", nicpath));
- nicinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, nicinfo->backend,
+ &nicinfo->backend_id);
+ if (rc) goto out;
+
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath));
nicinfo->state = val ? strtoul(val, NULL, 10) : -1;
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", nicpath));
@@ -3745,8 +3750,10 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/frontend-id", nicinfo->backend));
nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
const char *libxl__device_nic_devname(libxl__gc *gc,
--
2.1.4
[-- Attachment #12: xsa175-unstable/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch --]
[-- Type: application/octet-stream, Size: 4154 bytes --]
From 96db81f1f16fdcf132055141ad8d17aa608a2a15 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/34] 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(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 9aa9aa9..b16a097 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3814,6 +3814,8 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
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");
@@ -3952,34 +3954,35 @@ static int libxl__device_channel_from_xs_be(libxl__gc *gc,
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 = GCSPRINTF("%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) {
@@ -4010,7 +4013,7 @@ libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
*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;
--
2.1.4
[-- Attachment #13: xsa175-unstable/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 4791 bytes --]
From 7ff4b30568f6202e1b505b49120bbced3cfafac7 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 17:24:32 +0100
Subject: [PATCH 12/34] libxl: Do not trust frontend for channel in getinfo
libxl_device_channel_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
* Tolerate FRONTEND/tty vanishing.
Note that there is a strange off-by-one error in the computation of
both fe_path and libxl_path in libxl_device_channel_getinfo: the
incoming channel->devid, which is copied to channelinfo->devid, has +1
applied to calculate the frontend path (and, after this patch, the
libxl path). I.e., the devid passed to libxl_device_channel_getinfo
must be one less than the actual devid for the device being asked
about.
This is actually a bug which mirrors a bug in
libxl__append_channel_list, which fills in the devids of the channel
devices it finds with sequentially increasing numbers starting at 0.
In the usual case channels have real devids starting at 1 (because
there is the console, which is devid 0, but not a channel). So these
bugs usually cancel out.
We do not address this problem at this time. This bug does not have
any security implications.
This patch 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 | 39 ++++++++++++++++++++++++++++++++++-----
1 file changed, 34 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b16a097..75539e9 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -4034,22 +4034,28 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_channelinfo *channelinfo)
{
GC_INIT(ctx);
- char *dompath, *fe_path;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
channelinfo->devid = channel->devid;
fe_path = GCSPRINTF("%s/device/console/%d", dompath,
channelinfo->devid + 1);
+ libxl_path = GCSPRINTF("%s/device/console/%d",
+ libxl__xs_libxl_path(gc, domid),
+ channelinfo->devid + 1);
channelinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", fe_path), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!channelinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", fe_path));
- channelinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, channelinfo->backend,
+ &channelinfo->backend_id);
+ if (rc) goto out;
+
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
channelinfo->state = val ? strtoul(val, NULL, 10) : -1;
channelinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
@@ -4067,13 +4073,36 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
switch (channel->connection) {
case LIBXL_CHANNEL_CONNECTION_PTY:
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path));
+ /*
+ * It is obviously very wrong for this value to be in the
+ * frontend. But in XSA-175 we don't want to re-engineer
+ * this because other xenconsole code elsewhere (some
+ * even out of tree, perhaps) expects this node to be
+ * here.
+ *
+ * FE/pty is readonly for the guest. It always exists if
+ * FE does because libxl__device_console_add
+ * unconditionally creates it and nothing deletes it.
+ *
+ * The guest can delete the whole FE (which it has write
+ * privilege on) but the containing directories
+ * /local/GUEST[/device[/console]] are also RO for the
+ * guest. So if the guest deletes FE it cannot recreate
+ * it.
+ *
+ * Therefore the guest cannot cause FE/pty to contain bad
+ * data, although it can cause it to not exist.
+ */
+ if (!val) val = "/NO-SUCH-PATH";
channelinfo->u.pty.path = strdup(val);
break;
default:
break;
}
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
/******************************************************************************/
--
2.1.4
[-- Attachment #14: xsa175-unstable/0013-libxl-Do-not-trust-frontend-for-vusb.patch --]
[-- Type: application/octet-stream, Size: 9181 bytes --]
From d3390df239984972a3468fcf1f66eaaff19daeaa Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Thu, 5 May 2016 16:17:18 +0100
Subject: [PATCH 13/34] libxl: Do not trust frontend for vusb
Do not use the frontend directory for enumerating the vusb devices;
since the frontend could delete them, this could result in devices
being lost and not torn down, etc. Instead, use the /libxl directory
for enumeration. So:
* Replace vusb_be_from_xs_fe with vusb_be_from_xs_libxl
* Change the call sites
* Change various places that use the dompath to use libxl_dom_path
* Rename some `path' variables appropriate (to spot any missed updates)
* Parse backend domid out of backend path rather than reading it from
the frontend (several places)
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v3: Whitespace adjustment to parameter list indentation
v2: New patch, following rebase
---
tools/libxl/libxl_pvusb.c | 84 ++++++++++++++++++++++-------------------------
1 file changed, 40 insertions(+), 44 deletions(-)
diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c
index 9f1e842..7af7e4d 100644
--- a/tools/libxl/libxl_pvusb.c
+++ b/tools/libxl/libxl_pvusb.c
@@ -336,28 +336,16 @@ out:
return;
}
-static const char *vusb_be_from_xs_fe(libxl__gc *gc, const char *fe_path,
- uint32_t tgt_domid)
+static const char *vusb_be_from_xs_libxl(libxl__gc *gc, const char *libxl_path)
{
const char *be_path;
int r;
- uint32_t be_domid, fe_domid;
- char be_type[16];
- r = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/backend", fe_path),
+ r = libxl__xs_read_checked(gc, XBT_NULL,
+ GCSPRINTF("%s/backend", libxl_path),
&be_path);
if (r || !be_path) return NULL;
- /* Check to see that it has the proper form, and that fe_domid ==
- * target domid */
- r = sscanf(be_path, "/local/domain/%u/backend/%15[^/]/%u",
- &be_domid, be_type, &fe_domid);
-
- if (r != 3 || fe_domid != tgt_domid) {
- LOG(ERROR, "Malformed backend, refusing to use");
- return NULL;
- }
-
return be_path;
}
@@ -366,15 +354,15 @@ libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
{
GC_INIT(ctx);
libxl_device_usbctrl *usbctrls = NULL;
- char *path = NULL;
+ char *libxl_vusbs_path = NULL;
char **entry = NULL;
unsigned int nentries = 0;
*num = 0;
- path = GCSPRINTF("%s/device/vusb",
- libxl__xs_get_dompath(gc, domid));
- entry = libxl__xs_directory(gc, XBT_NULL, path, &nentries);
+ libxl_vusbs_path = GCSPRINTF("%s/device/vusb",
+ libxl__xs_libxl_path(gc, domid));
+ entry = libxl__xs_directory(gc, XBT_NULL, libxl_vusbs_path, &nentries);
if (entry && nentries) {
usbctrls = libxl__zalloc(NOGC, sizeof(*usbctrls) * nentries);
@@ -383,7 +371,7 @@ libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
for (usbctrl = usbctrls;
usbctrl < end;
usbctrl++, entry++, (*num)++) {
- const char *tmp, *be_path, *fe_path;
+ const char *tmp, *be_path, *libxl_path;
int ret;
libxl_device_usbctrl_init(usbctrl);
@@ -405,10 +393,12 @@ libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
tmp ? atoi(tmp) : -1; \
})
- fe_path = GCSPRINTF("%s/%s", path, *entry);
- be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
+ libxl_path = GCSPRINTF("%s/%s", libxl_vusbs_path, *entry);
+ be_path = READ_SUBPATH(libxl_path, "backend");
if (!be_path) goto out;
- usbctrl->backend_domid = READ_SUBPATH_INT(fe_path, "backend-id");
+ ret = libxl__backendpath_parse_domid(gc, be_path,
+ &usbctrl->backend_domid);
+ if (ret) goto out;
usbctrl->version = READ_SUBPATH_INT(be_path, "usb-ver");
usbctrl->ports = READ_SUBPATH_INT(be_path, "num-ports");
libxl_usbctrl_type_from_string(READ_SUBPATH(be_path, "type"),
@@ -436,6 +426,7 @@ int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
{
GC_INIT(ctx);
const char *dompath, *fe_path, *be_path, *tmp;
+ const char *libxl_dom_path, *libxl_path;
int rc;
usbctrlinfo->devid = usbctrl->devid;
@@ -458,9 +449,12 @@ int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
dompath = libxl__xs_get_dompath(gc, domid);
fe_path = GCSPRINTF("%s/device/vusb/%d", dompath, usbctrl->devid);
- be_path = READ_SUBPATH(fe_path, "backend");
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ libxl_path = GCSPRINTF("%s/device/vusb/%d", libxl_dom_path, usbctrl->devid);
+ be_path = READ_SUBPATH(libxl_path, "backend");
usbctrlinfo->backend = libxl__strdup(NOGC, be_path);
- usbctrlinfo->backend_id = READ_SUBPATH_INT(fe_path, "backend-id");
+ rc = libxl__backendpath_parse_domid(gc, be_path, &usbctrl->backend_domid);
+ if (rc) goto out;
usbctrlinfo->state = READ_SUBPATH_INT(fe_path, "state");
usbctrlinfo->evtch = READ_SUBPATH_INT(fe_path, "event-channel");
usbctrlinfo->ref_urb = READ_SUBPATH_INT(fe_path, "urb-ring-ref");
@@ -605,13 +599,15 @@ static int get_assigned_devices(libxl__gc *gc,
domlist = libxl__xs_directory(gc, XBT_NULL, "/local/domain", &ndom);
for (i = 0; i < ndom; i++) {
- char *path;
+ char *libxl_vusbs_path;
char **usbctrls;
unsigned int nc = 0;
uint32_t domid = atoi(domlist[i]);
- path = GCSPRINTF("%s/device/vusb", libxl__xs_get_dompath(gc, domid));
- usbctrls = libxl__xs_directory(gc, XBT_NULL, path, &nc);
+ libxl_vusbs_path = GCSPRINTF("%s/device/vusb",
+ libxl__xs_libxl_path(gc, domid));
+ usbctrls = libxl__xs_directory(gc, XBT_NULL,
+ libxl_vusbs_path, &nc);
for (j = 0; j < nc; j++) {
libxl_device_usbdev *tmp = NULL;
@@ -681,16 +677,16 @@ libxl__device_usbdev_list_for_usbctrl(libxl__gc *gc,
libxl_device_usbdev **usbdevs,
int *num)
{
- const char *fe_path, *be_path, *num_devs;
+ const char *libxl_path, *be_path, *num_devs;
int n, i, rc;
*usbdevs = NULL;
*num = 0;
- fe_path = GCSPRINTF("%s/device/vusb/%d",
- libxl__xs_get_dompath(gc, domid), usbctrl);
+ libxl_path = GCSPRINTF("%s/device/vusb/%d",
+ libxl__xs_libxl_path(gc, domid), usbctrl);
- be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
+ be_path = vusb_be_from_xs_libxl(gc, libxl_path);
if (!be_path) {
rc = ERROR_FAIL;
goto out;
@@ -739,16 +735,16 @@ libxl_device_usbdev_list(libxl_ctx *ctx, uint32_t domid, int *num)
{
GC_INIT(ctx);
libxl_device_usbdev *usbdevs = NULL;
- const char *path;
+ const char *libxl_vusbs_path;
char **usbctrls;
unsigned int nc = 0;
int i, j;
*num = 0;
- path = GCSPRINTF("%s/device/vusb",
- libxl__xs_get_dompath(gc, domid));
- usbctrls = libxl__xs_directory(gc, XBT_NULL, path, &nc);
+ libxl_vusbs_path = GCSPRINTF("%s/device/vusb",
+ libxl__xs_libxl_path(gc, !domid));
+ usbctrls = libxl__xs_directory(gc, XBT_NULL, libxl_vusbs_path, &nc);
for (i = 0; i < nc; i++) {
int rc, nd = 0;
@@ -878,13 +874,13 @@ static int libxl__device_usbdev_setdefault(libxl__gc *gc,
}
} else {
/* A controller was specified; look it up */
- const char *fe_path, *be_path, *tmp;
+ const char *libxl_path, *be_path, *tmp;
- fe_path = GCSPRINTF("%s/device/vusb/%d",
- libxl__xs_get_dompath(gc, domid),
+ libxl_path = GCSPRINTF("%s/device/vusb/%d",
+ libxl__xs_libxl_path(gc, domid),
usbdev->ctrl);
- be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
+ be_path = vusb_be_from_xs_libxl(gc, libxl_path);
if (!be_path) {
rc = ERROR_FAIL;
goto out;
@@ -1651,13 +1647,13 @@ int libxl_ctrlport_to_device_usbdev(libxl_ctx *ctx,
libxl_device_usbdev *usbdev)
{
GC_INIT(ctx);
- const char *dompath, *fe_path, *be_path, *busid;
+ const char *libxl_dom_path, *libxl_path, *be_path, *busid;
int rc;
- dompath = libxl__xs_get_dompath(gc, domid);
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
- fe_path = GCSPRINTF("%s/device/vusb/%d", dompath, ctrl);
- be_path = vusb_be_from_xs_fe(gc, fe_path, domid);
+ libxl_path = GCSPRINTF("%s/device/vusb/%d", libxl_dom_path, ctrl);
+ be_path = vusb_be_from_xs_libxl(gc, libxl_path);
if (!be_path) {
rc = ERROR_FAIL;
goto out;
--
2.1.4
[-- Attachment #15: xsa175-4.6/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch --]
[-- Type: application/octet-stream, Size: 7641 bytes --]
From cf6264a8144850a1cbf78709e41d0fcc657be0f3 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 15:50:01 +0100
Subject: [PATCH 01/12] libxl: Record backend/frontend paths in /libxl/$DOMID
This gives us a record of all the backends we have set up for a
domain, which is separate from the frontends in
/local/domain/$DOMID/device.
In particular:
1. A guest has write permission for the frontend path:
/local/domain/$DOMID/device/$KIND/$DEVID
which means that the guest can completely delete the frontend.
(They can't recreate it because they don't have write permission
on the containing directory.)
2. A guest has write permission for the backend path recorded in the
frontend, ie, it can write to
/local/domain/$DOMID/device/$KIND/$DEVID/backend
which means that the guest can break the association between
frontend and backend.
So we can't rely on iterating over the frontends to find all the
backends, or examining a frontend to discover how a device is
configured.
So, have libxl__device_generic_add record the frontend and backend
paths in /libxl/$DOMID/device, and have libxl__device_destroy remove
them again.
Create the containing directory /libxl/GUEST/device in
libxl__domain_make. The already existing xs_rm in devices_destroy_cb
will take care of removing it.
This is part of XSA-175.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v2: Correct actual path computation (!)
v3: Correct actual path computation - really this time (!)
Conflicts:
tools/libxl/libxl_create.c
---
docs/misc/xenstore-paths.markdown | 15 +++++++++++++++
tools/libxl/libxl_create.c | 2 ++
tools/libxl/libxl_device.c | 36 ++++++++++++++++++++++++++++++++++--
tools/libxl/libxl_internal.h | 1 +
4 files changed, 52 insertions(+), 2 deletions(-)
diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index d94ea9d..276273d 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -389,6 +389,21 @@ The guest's virtual time offset from UTC in seconds.
### libxl Specific Paths
+#### /libxl/$DOMID/device/$KIND/$DEVID
+
+Created by libxl for every frontend/backend pair created for $DOMID.
+Used by libxl for enumeration and management of the device.
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/frontend
+
+Path in xenstore to the frontend, normally
+/local/domain/$DOMID/device/$KIND/$DEVID
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/backend
+
+Path in xenstore to the backend, normally
+/local/domain/$BACKEND_DOMID/backend/$KIND/$DOMID/$DEVID
+
#### /libxl/$DOMID/dm-version ("qemu\_xen"|"qemu\_xen\_traditional") = [n,INTERNAL]
The device model version for a domain.
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 350e274..c6862b8 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -591,6 +591,8 @@ retry_transaction:
xs_rm(ctx->xsh, t, libxl_path);
libxl__xs_mkdir(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));
+ libxl__xs_mkdir(gc, t, GCSPRINTF("%s/device", libxl_path),
+ noperm, ARRAY_SIZE(noperm));
xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 8bb5e93..f1af411 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -40,6 +40,15 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
device->domid, device->devid);
}
+char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device)
+{
+ char *libxl_dom_path = libxl__xs_libxl_path(gc, device->domid);
+
+ return GCSPRINTF("%s/device/%s/%d", libxl_dom_path,
+ libxl__device_kind_to_string(device->kind),
+ device->devid);
+}
+
/* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
libxl__device *device)
@@ -105,14 +114,16 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- char *frontend_path, *backend_path;
+ char *frontend_path, *backend_path, *libxl_path;
struct xs_permissions frontend_perms[2];
struct xs_permissions ro_frontend_perms[2];
struct xs_permissions backend_perms[2];
int create_transaction = t == XBT_NULL;
+ int rc;
frontend_path = libxl__device_frontend_path(gc, device);
backend_path = libxl__device_backend_path(gc, device);
+ libxl_path = libxl__device_libxl_path(gc, device);
frontend_perms[0].id = device->domid;
frontend_perms[0].perms = XS_PERM_NONE;
@@ -127,8 +138,22 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
retry_transaction:
if (create_transaction)
t = xs_transaction_start(ctx->xsh);
+
/* FIXME: read frontend_path and check state before removing stuff */
+ rc = libxl__xs_rm_checked(gc, t, libxl_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/frontend",libxl_path),
+ frontend_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/backend",libxl_path),
+ backend_path);
+ if (rc) goto out;
+
+ /* xxx much of this function lacks error checks! */
+
if (fents || ro_fents) {
xs_rm(ctx->xsh, t, frontend_path);
xs_mkdir(ctx->xsh, t, frontend_path);
@@ -174,6 +199,11 @@ retry_transaction:
}
}
return 0;
+
+ out:
+ if (create_transaction && t)
+ libxl__xs_transaction_abort(gc, &t);
+ return rc;
}
typedef struct {
@@ -572,6 +602,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
{
const char *be_path = libxl__device_backend_path(gc, dev);
const char *fe_path = libxl__device_frontend_path(gc, dev);
+ const char *libxl_path = libxl__device_libxl_path(gc, dev);
const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params");
const char *tapdisk_params;
xs_transaction_t t = 0;
@@ -592,9 +623,10 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
if (domid == LIBXL_TOOLSTACK_DOMID) {
/*
* The toolstack domain is in charge of removing the
- * frontend path.
+ * frontend and libxl paths.
*/
libxl__xs_path_cleanup(gc, t, fe_path);
+ libxl__xs_path_cleanup(gc, t, libxl_path);
}
if (dev->backend_domid == domid) {
/*
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 1699f32..38af3ac 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1152,6 +1152,7 @@ _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, 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 char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
--
2.1.4
[-- Attachment #16: xsa175-4.6/0002-libxl-Provide-libxl__backendpath_parse_domid.patch --]
[-- Type: application/octet-stream, Size: 2166 bytes --]
From fd2317e415eab76f20d11c6518fca9042fe117bc Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:34:19 +0100
Subject: [PATCH 02/12] libxl: Provide libxl__backendpath_parse_domid
Multiple places in libxl need to figure out the backend domid of a
device. This can be discovered easily by looking at the backend path,
which always starts /local/domain/$backend_domid/.
There are no call sites yet.
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_device.c | 15 +++++++++++++++
tools/libxl/libxl_internal.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index f1af411..bfd4bdd 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -288,6 +288,21 @@ static int disk_try_backend(disk_try_backend_args *a,
return 0;
}
+int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out) {
+ int r;
+ unsigned int domid_sc;
+ char delim_sc;
+
+ r = sscanf(be_path, "/local/domain/%u%c", &domid_sc, &delim_sc);
+ if (!(r==2 && delim_sc=='/')) {
+ LOG(ERROR, "internal error: backend path %s unparseable!", be_path);
+ return ERROR_FAIL;
+ }
+ *domid_out = domid_sc;
+ return 0;
+}
+
int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
libxl_disk_backend ok;
disk_try_backend_args a;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 38af3ac..f034f63 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -683,6 +683,8 @@ _hidden bool libxl__xs_mkdir(libxl__gc *gc, xs_transaction_t t,
_hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid);
+_hidden int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out);
/*----- "checked" xenstore access functions -----*/
/* Each of these functions will check that it succeeded; if it
--
2.1.4
[-- Attachment #17: xsa175-4.6/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]
From 5214e86aec5cce54f6c3621f487df3f1ecb32c52 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 18:39:36 +0100
Subject: [PATCH 03/12] libxl: Do not trust frontend in libxl__devices_destroy
We need to enumerate the devices we have provided to a domain, without
trusting the guest-writeable (or, at least, guest-deletable) frontend
paths.
Instead, enumerate via, and read the backend path from, /libxl.
The console /libxl path is regular, so the special case for console 0
is not relevant any more: /libxl/GUEST/device/console/0 will be found,
and then libxl__device_destroy will DTRT to the right frontend path.
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_device.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index bfd4bdd..f4e907f 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -685,7 +685,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
libxl__multidev_begin(ao, multidev);
multidev->callback = devices_remove_callback;
- path = GCSPRINTF("/local/domain/%d/device", domid);
+ path = GCSPRINTF("/libxl/%d/device", domid);
kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
if (!kinds) {
if (errno != ENOENT) {
@@ -698,12 +698,12 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
if (libxl__device_kind_from_string(kinds[i], &kind))
continue;
- path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]);
+ path = GCSPRINTF("/libxl/%d/device/%s", domid, kinds[i]);
devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries);
if (!devs)
continue;
for (j = 0; j < num_dev_xsentries; j++) {
- path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend",
+ path = GCSPRINTF("/libxl/%d/device/%s/%s/backend",
domid, kinds[i], devs[j]);
path = libxl__xs_read(gc, XBT_NULL, path);
GCNEW(dev);
@@ -728,22 +728,6 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
}
}
- /* console 0 frontend directory is not under /local/domain/<domid>/device */
- path = GCSPRINTF("/local/domain/%d/console/backend", domid);
- path = libxl__xs_read(gc, XBT_NULL, path);
- GCNEW(dev);
- if (path && strcmp(path, "") &&
- libxl__parse_backend_path(gc, path, dev) == 0) {
- dev->domid = domid;
- dev->kind = LIBXL__DEVICE_KIND_CONSOLE;
- dev->devid = 0;
-
- /* Currently console devices can be destroyed synchronously by just
- * removing xenstore entries, this is what libxl__device_destroy does.
- */
- libxl__device_destroy(gc, dev);
- }
-
out:
libxl__multidev_prepared(egc, multidev, rc);
}
--
2.1.4
[-- Attachment #18: xsa175-4.6/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch --]
[-- Type: application/octet-stream, Size: 1395 bytes --]
From 31c78e76bdeb450ce0e0b32e9f5b0e284d4b9958 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 4 May 2016 15:30:32 +0100
Subject: [PATCH 04/12] libxl: Do not trust frontend in libxl__device_nextid
When selecting the devid for a new device, we should look in
/libxl/device for existing devices, not in the frontend area.
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 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 1366177..96f68dc 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2008,15 +2008,16 @@ out:
/* common function to get next device id */
static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
{
- char *dompath, **l;
+ char *libxl_dom_path, **l;
unsigned int nb;
int nextid = -1;
- if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
return nextid;
l = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/device/%s", dompath, device), &nb);
+ GCSPRINTF("%s/device/%s", libxl_dom_path, device),
+ &nb);
if (l == NULL || nb == 0)
nextid = 0;
else
--
2.1.4
[-- Attachment #19: xsa175-4.6/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch --]
[-- Type: application/octet-stream, Size: 3890 bytes --]
From f02320d65226f722bf8eaaa6bf6e0148d633965a Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:08:49 +0100
Subject: [PATCH 05/12] libxl: Do not trust frontend for disk eject event
Use the /libxl path for interpreting disk eject watch events: do not
read the backend path out of the frontend. Instead, use the version
in /libxl. That avoids us relying on the guest-modifiable
$frontend/backend pointer.
To implement this we store the path
/libxl/$guest/device/vbd/$devid/backend
in the evgen structure.
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 | 28 ++++++++++++++++++++++------
tools/libxl/libxl_internal.h | 2 +-
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 96f68dc..831b80c 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1336,9 +1336,10 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
const char *wpath, const char *epath) {
EGC_GC;
libxl_evgen_disk_eject *evg = (void*)w;
- char *backend;
+ const char *backend;
char *value;
char backend_type[BACKEND_STRING_SIZE+1];
+ int rc;
value = libxl__xs_read(gc, XBT_NULL, wpath);
@@ -1354,9 +1355,16 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
libxl_device_disk *disk = &ev->u.disk_eject.disk;
- backend = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%.*s/backend",
- (int)strlen(wpath)-6, wpath));
+ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
+ if (rc) {
+ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+ if (!backend) {
+ /* device has been removed, not simply ejected */
+ return;
+ }
sscanf(backend,
"/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
@@ -1405,11 +1413,18 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
if (!domid)
domid = guest_domid;
- path = libxl__sprintf(gc, "%s/device/vbd/%d/eject",
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+
+ path = GCSPRINTF("%s/device/vbd/%d/eject",
libxl__xs_get_dompath(gc, domid),
- libxl__device_disk_dev_number(vdev, NULL, NULL));
+ devid);
if (!path) { rc = ERROR_NOMEM; goto out; }
+ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid),
+ devid);
+ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
+
rc = libxl__ev_xswatch_register(gc, &evg->watch,
disk_eject_xswatch_callback, path);
if (rc) goto out;
@@ -1436,6 +1451,7 @@ void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
libxl__ev_xswatch_deregister(gc, &evg->watch);
free(evg->vdev);
+ free(evg->be_ptr_path);
free(evg);
CTX_UNLOCK;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index f034f63..1f11b1a 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -337,7 +337,7 @@ struct libxl__evgen_disk_eject {
uint32_t domid;
LIBXL_LIST_ENTRY(libxl_evgen_disk_eject) entry;
libxl_ev_user user;
- char *vdev;
+ char *vdev, *be_ptr_path;
};
_hidden void
libxl__evdisable_disk_eject(libxl__gc*, libxl_evgen_disk_eject*);
--
2.1.4
[-- Attachment #20: xsa175-4.6/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 3378 bytes --]
From d3e1c77a8ae7820e0906f324254b551995624ab5 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Fri, 29 Apr 2016 19:21:51 +0100
Subject: [PATCH 06/12] libxl: Do not trust frontend for disk in getinfo
* Rename the frontend variable to `fe_path' to check we caught them all
* Read the backend path from /libxl, rather than from the frontend
* Parse the backend domid from the backend path, rather than reading it
from the frontend (and add the appropriate error path and initialisation)
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 | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 831b80c..b418564 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2821,27 +2821,34 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk, libxl_diskinfo *diskinfo)
{
GC_INIT(ctx);
- char *dompath, *diskpath;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
+
+ diskinfo->backend = NULL;
dompath = libxl__xs_get_dompath(gc, domid);
diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
/* tap devices entries in xenstore are written as vbd devices. */
- diskpath = libxl__sprintf(gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
+ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid), diskinfo->devid);
diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", diskpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!diskinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", diskpath));
- diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", diskpath));
+ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
+ &diskinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/ring-ref", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
libxl__sprintf(gc, "%s/frontend", diskinfo->backend), NULL);
@@ -2850,6 +2857,10 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
GC_FREE;
return 0;
+
+ out:
+ free(diskinfo->backend);
+ return rc;
}
int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
--
2.1.4
[-- Attachment #21: xsa175-4.6/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch --]
[-- Type: application/octet-stream, Size: 2387 bytes --]
From c277f046e8d5c8413d6436685dbda75c5626d577 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:58:32 +0100
Subject: [PATCH 07/12] libxl: Do not trust frontend for vtpm list
libxl_device_vtpm_list needs to enumerate and identify devices without
trusting frontend-controlled data. So
* Use the /libxl path to enumerate vtpms.
* Use the /libxl path to find the corresponding backends.
* Parse the backend path to find the backend domid.
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 | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b418564..6590157 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2196,14 +2196,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
GC_INIT(ctx);
libxl_device_vtpm* vtpms = NULL;
- char* fe_path = NULL;
+ char *libxl_path;
char** dir = NULL;
unsigned int ndirs = 0;
+ int rc;
*num = 0;
- fe_path = libxl__sprintf(gc, "%s/device/vtpm", libxl__xs_get_dompath(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+ libxl_path = GCSPRINTF("%s/device/vtpm", libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);
if (dir && ndirs) {
vtpms = malloc(sizeof(*vtpms) * ndirs);
libxl_device_vtpm* vtpm;
@@ -2212,16 +2213,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
char* tmp;
const char* be_path = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/%s/backend",
- fe_path, *dir));
+ libxl_path, *dir));
libxl_device_vtpm_init(vtpm);
vtpm->devid = atoi(*dir);
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/%s/backend-id",
- fe_path, *dir));
- vtpm->backend_domid = atoi(tmp);
+ rc = libxl__backendpath_parse_domid(gc, be_path,
+ &vtpm->backend_domid);
+ if (rc) return NULL;
tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
if (tmp) {
--
2.1.4
[-- Attachment #22: xsa175-4.6/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2100 bytes --]
From d36cdc6238506f65ca9ce2bb008c61e45dbcb9d0 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:00:20 +0100
Subject: [PATCH 08/12] libxl: Do not trust frontend for vtpm in getinfo
libxl_device_vtpm_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 6590157..a424832 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2245,7 +2245,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
libxl_vtpminfo *vtpminfo)
{
GC_INIT(ctx);
- char *dompath, *vtpmpath;
+ char *libxl_path, *dompath, *vtpmpath;
char *val;
int rc = 0;
@@ -2254,8 +2254,10 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
vtpminfo->devid = vtpm->devid;
vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vtpm/%d",
+ libxl__xs_libxl_path(gc, domid), vtpminfo->devid);
vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", vtpmpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!vtpminfo->backend) {
goto err;
}
@@ -2263,9 +2265,9 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
goto err;
}
- val = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/backend-id", vtpmpath));
- vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
+ &vtpminfo->backend_id);
+ if (rc) goto exit;
val = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/state", vtpmpath));
--
2.1.4
[-- Attachment #23: xsa175-4.6/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch --]
[-- Type: application/octet-stream, Size: 1505 bytes --]
From 3e1e9ff62717f4c9b231e82a299e960bd4da4506 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:52:53 +0100
Subject: [PATCH 09/12] libxl: Do not trust frontend for nic in
libxl_devid_to_device_nic
Find the backend by reading the pointer in /libxl rather than in the
guest's frontend area.
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 | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index a424832..225e659 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3512,17 +3512,17 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_nic *nic)
{
GC_INIT(ctx);
- char *dompath, *path;
+ char *libxl_dom_path, *path;
int rc = ERROR_FAIL;
libxl_device_nic_init(nic);
- dompath = libxl__xs_get_dompath(gc, domid);
- if (!dompath)
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ if (!libxl_dom_path)
goto out;
path = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%s/device/vif/%d/backend",
- dompath, devid));
+ GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path,
+ devid));
if (!path)
goto out;
--
2.1.4
[-- Attachment #24: xsa175-4.6/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2812 bytes --]
From 4bb4bb97faacc6135fb0640be9da10c9f2dc5592 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:31:07 +0100
Subject: [PATCH 10/12] libxl: Do not trust frontend for nic in getinfo
libxl_device_nic_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 225e659..105a9cc 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3601,22 +3601,27 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic, libxl_nicinfo *nicinfo)
{
GC_INIT(ctx);
- char *dompath, *nicpath;
+ char *dompath, *nicpath, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
nicinfo->devid = nic->devid;
- nicpath = libxl__sprintf(gc, "%s/device/vif/%d", dompath, nicinfo->devid);
+ nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vif/%d",
+ libxl__xs_libxl_path(gc, domid), nicinfo->devid);
nicinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", nicpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!nicinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", nicpath));
- nicinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", nicpath));
+ rc = libxl__backendpath_parse_domid(gc, nicinfo->backend,
+ &nicinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath));
nicinfo->state = val ? strtoul(val, NULL, 10) : -1;
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", nicpath));
nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
@@ -3629,8 +3634,10 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend-id", nicinfo->backend));
nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
const char *libxl__device_nic_devname(libxl__gc *gc,
--
2.1.4
[-- Attachment #25: xsa175-4.6/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch --]
[-- Type: application/octet-stream, Size: 4163 bytes --]
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(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 105a9cc..48d491f 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3698,6 +3698,8 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
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");
@@ -3836,34 +3838,35 @@ static int libxl__device_channel_from_xs_be(libxl__gc *gc,
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) {
@@ -3894,7 +3897,7 @@ libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
*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;
--
2.1.4
[-- Attachment #26: xsa175-4.6/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 4963 bytes --]
From 1a83149ba5f2a7faed29d45b5d6dddfff78459bc Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 17:24:32 +0100
Subject: [PATCH 12/12] libxl: Do not trust frontend for channel in getinfo
libxl_device_channel_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
* Tolerate FRONTEND/tty vanishing.
Note that there is a strange off-by-one error in the computation of
both fe_path and libxl_path in libxl_device_channel_getinfo: the
incoming channel->devid, which is copied to channelinfo->devid, has +1
applied to calculate the frontend path (and, after this patch, the
libxl path). I.e., the devid passed to libxl_device_channel_getinfo
must be one less than the actual devid for the device being asked
about.
This is actually a bug which mirrors a bug in
libxl__append_channel_list, which fills in the devids of the channel
devices it finds with sequentially increasing numbers starting at 0.
In the usual case channels have real devids starting at 1 (because
there is the console, which is devid 0, but not a channel). So these
bugs usually cancel out.
We do not address this problem at this time. This bug does not have
any security implications.
This patch 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 | 44 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 36 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 48d491f..db92fae 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3918,23 +3918,28 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_channelinfo *channelinfo)
{
GC_INIT(ctx);
- char *dompath, *fe_path;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
channelinfo->devid = channel->devid;
- fe_path = libxl__sprintf(gc, "%s/device/console/%d", dompath,
- channelinfo->devid + 1);
+ fe_path = GCSPRINTF("%s/device/console/%d", dompath,
+ channelinfo->devid + 1);
+ libxl_path = GCSPRINTF("%s/device/console/%d",
+ libxl__xs_libxl_path(gc, domid),
+ channelinfo->devid + 1);
channelinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend",
- fe_path), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!channelinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", fe_path));
- channelinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, channelinfo->backend,
+ &channelinfo->backend_id);
+ if (rc) goto out;
+
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
channelinfo->state = val ? strtoul(val, NULL, 10) : -1;
channelinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
@@ -3952,13 +3957,36 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
switch (channel->connection) {
case LIBXL_CHANNEL_CONNECTION_PTY:
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path));
+ /*
+ * It is obviously very wrong for this value to be in the
+ * frontend. But in XSA-175 we don't want to re-engineer
+ * this because other xenconsole code elsewhere (some
+ * even out of tree, perhaps) expects this node to be
+ * here.
+ *
+ * FE/pty is readonly for the guest. It always exists if
+ * FE does because libxl__device_console_add
+ * unconditionally creates it and nothing deletes it.
+ *
+ * The guest can delete the whole FE (which it has write
+ * privilege on) but the containing directories
+ * /local/GUEST[/device[/console]] are also RO for the
+ * guest. So if the guest deletes FE it cannot recreate
+ * it.
+ *
+ * Therefore the guest cannot cause FE/pty to contain bad
+ * data, although it can cause it to not exist.
+ */
+ if (!val) val = "/NO-SUCH-PATH";
channelinfo->u.pty.path = strdup(val);
break;
default:
break;
}
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
/******************************************************************************/
--
2.1.4
[-- Attachment #27: xsa175-4.5/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch --]
[-- Type: application/octet-stream, Size: 7602 bytes --]
From 3a4091efe0b4bcae46371491d74c15bba6f93275 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Mon, 16 May 2016 14:56:57 +0100
Subject: [PATCH 01/12] libxl: Record backend/frontend paths in /libxl/$DOMID
This gives us a record of all the backends we have set up for a
domain, which is separate from the frontends in
/local/domain/$DOMID/device.
In particular:
1. A guest has write permission for the frontend path:
/local/domain/$DOMID/device/$KIND/$DEVID
which means that the guest can completely delete the frontend.
(They can't recreate it because they don't have write permission
on the containing directory.)
2. A guest has write permission for the backend path recorded in the
frontend, ie, it can write to
/local/domain/$DOMID/device/$KIND/$DEVID/backend
which means that the guest can break the association between
frontend and backend.
So we can't rely on iterating over the frontends to find all the
backends, or examining a frontend to discover how a device is
configured.
So, have libxl__device_generic_add record the frontend and backend
paths in /libxl/$DOMID/device, and have libxl__device_destroy remove
them again.
Create the containing directory /libxl/GUEST/device in
libxl__domain_make. The already existing xs_rm in devices_destroy_cb
will take care of removing it.
This is part of XSA-175.
Backport note: Backported over 7472ced, which fixes a bug in driver
domain teardown.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v2: Correct actual path computation (!)
v3: Correct actual path computation - really this time (!)
---
docs/misc/xenstore-paths.markdown | 15 +++++++++++++++
tools/libxl/libxl_create.c | 2 ++
tools/libxl/libxl_device.c | 34 +++++++++++++++++++++++++++++++++-
tools/libxl/libxl_internal.h | 1 +
4 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index d94ea9d..276273d 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -389,6 +389,21 @@ The guest's virtual time offset from UTC in seconds.
### libxl Specific Paths
+#### /libxl/$DOMID/device/$KIND/$DEVID
+
+Created by libxl for every frontend/backend pair created for $DOMID.
+Used by libxl for enumeration and management of the device.
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/frontend
+
+Path in xenstore to the frontend, normally
+/local/domain/$DOMID/device/$KIND/$DEVID
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/backend
+
+Path in xenstore to the backend, normally
+/local/domain/$BACKEND_DOMID/backend/$KIND/$DOMID/$DEVID
+
#### /libxl/$DOMID/dm-version ("qemu\_xen"|"qemu\_xen\_traditional") = [n,INTERNAL]
The device model version for a domain.
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 152fdbc..a4d4d4c 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -586,6 +586,8 @@ retry_transaction:
xs_rm(ctx->xsh, t, libxl_path);
libxl__xs_mkdir(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));
+ libxl__xs_mkdir(gc, t, GCSPRINTF("%s/device", libxl_path),
+ noperm, ARRAY_SIZE(noperm));
xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 4b51ded..a8b97a3 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -40,6 +40,15 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
device->domid, device->devid);
}
+char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device)
+{
+ char *libxl_dom_path = libxl__xs_libxl_path(gc, device->domid);
+
+ return GCSPRINTF("%s/device/%s/%d", libxl_dom_path,
+ libxl__device_kind_to_string(device->kind),
+ device->devid);
+}
+
/* Returns 1 if device exists, 0 if not, ERROR_* (<0) on error. */
int libxl__device_exists(libxl__gc *gc, xs_transaction_t t,
libxl__device *device)
@@ -105,14 +114,16 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- char *frontend_path, *backend_path;
+ char *frontend_path, *backend_path, *libxl_path;
struct xs_permissions frontend_perms[2];
struct xs_permissions ro_frontend_perms[2];
struct xs_permissions backend_perms[2];
int create_transaction = t == XBT_NULL;
+ int rc;
frontend_path = libxl__device_frontend_path(gc, device);
backend_path = libxl__device_backend_path(gc, device);
+ libxl_path = libxl__device_libxl_path(gc, device);
frontend_perms[0].id = device->domid;
frontend_perms[0].perms = XS_PERM_NONE;
@@ -127,8 +138,22 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
retry_transaction:
if (create_transaction)
t = xs_transaction_start(ctx->xsh);
+
/* FIXME: read frontend_path and check state before removing stuff */
+ rc = libxl__xs_rm_checked(gc, t, libxl_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/frontend",libxl_path),
+ frontend_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/backend",libxl_path),
+ backend_path);
+ if (rc) goto out;
+
+ /* xxx much of this function lacks error checks! */
+
if (fents || ro_fents) {
xs_rm(ctx->xsh, t, frontend_path);
xs_mkdir(ctx->xsh, t, frontend_path);
@@ -174,6 +199,11 @@ retry_transaction:
}
}
return 0;
+
+ out:
+ if (create_transaction && t)
+ libxl__xs_transaction_abort(gc, &t);
+ return rc;
}
typedef struct {
@@ -570,6 +600,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
{
const char *be_path = libxl__device_backend_path(gc, dev);
const char *fe_path = libxl__device_frontend_path(gc, dev);
+ const char *libxl_path = libxl__device_libxl_path(gc, dev);
const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params");
const char *tapdisk_params;
xs_transaction_t t = 0;
@@ -594,6 +625,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
*/
libxl__xs_path_cleanup(gc, t, fe_path);
libxl__xs_path_cleanup(gc, t, be_path);
+ libxl__xs_path_cleanup(gc, t, libxl_path);
} else if (dev->backend_domid == domid) {
/*
* The driver domain is in charge for removing what it can
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index ff88f3d..55b19d9 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1061,6 +1061,7 @@ _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, 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 char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
--
2.1.4
[-- Attachment #28: xsa175-4.5/0002-libxl-Provide-libxl__backendpath_parse_domid.patch --]
[-- Type: application/octet-stream, Size: 2166 bytes --]
From c689a6c9471761b59e6d08dee1667834e0b7fc34 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:34:19 +0100
Subject: [PATCH 02/12] libxl: Provide libxl__backendpath_parse_domid
Multiple places in libxl need to figure out the backend domid of a
device. This can be discovered easily by looking at the backend path,
which always starts /local/domain/$backend_domid/.
There are no call sites yet.
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_device.c | 15 +++++++++++++++
tools/libxl/libxl_internal.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index a8b97a3..9136b26 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -288,6 +288,21 @@ static int disk_try_backend(disk_try_backend_args *a,
return 0;
}
+int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out) {
+ int r;
+ unsigned int domid_sc;
+ char delim_sc;
+
+ r = sscanf(be_path, "/local/domain/%u%c", &domid_sc, &delim_sc);
+ if (!(r==2 && delim_sc=='/')) {
+ LOG(ERROR, "internal error: backend path %s unparseable!", be_path);
+ return ERROR_FAIL;
+ }
+ *domid_out = domid_sc;
+ return 0;
+}
+
int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
libxl_disk_backend ok;
disk_try_backend_args a;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 55b19d9..bfe06bd 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -594,6 +594,8 @@ _hidden bool libxl__xs_mkdir(libxl__gc *gc, xs_transaction_t t,
_hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid);
+_hidden int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out);
/*----- "checked" xenstore access functions -----*/
/* Each of these functions will check that it succeeded; if it
--
2.1.4
[-- Attachment #29: xsa175-4.5/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]
From 924ac76cba810c3c8d594f78f96fbf7c792c3f54 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 18:39:36 +0100
Subject: [PATCH 03/12] libxl: Do not trust frontend in libxl__devices_destroy
We need to enumerate the devices we have provided to a domain, without
trusting the guest-writeable (or, at least, guest-deletable) frontend
paths.
Instead, enumerate via, and read the backend path from, /libxl.
The console /libxl path is regular, so the special case for console 0
is not relevant any more: /libxl/GUEST/device/console/0 will be found,
and then libxl__device_destroy will DTRT to the right frontend path.
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_device.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 9136b26..38ab393 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -683,7 +683,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
libxl__multidev_begin(ao, multidev);
multidev->callback = devices_remove_callback;
- path = GCSPRINTF("/local/domain/%d/device", domid);
+ path = GCSPRINTF("/libxl/%d/device", domid);
kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
if (!kinds) {
if (errno != ENOENT) {
@@ -696,12 +696,12 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
if (libxl__device_kind_from_string(kinds[i], &kind))
continue;
- path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]);
+ path = GCSPRINTF("/libxl/%d/device/%s", domid, kinds[i]);
devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries);
if (!devs)
continue;
for (j = 0; j < num_dev_xsentries; j++) {
- path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend",
+ path = GCSPRINTF("/libxl/%d/device/%s/%s/backend",
domid, kinds[i], devs[j]);
path = libxl__xs_read(gc, XBT_NULL, path);
GCNEW(dev);
@@ -726,22 +726,6 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
}
}
- /* console 0 frontend directory is not under /local/domain/<domid>/device */
- path = GCSPRINTF("/local/domain/%d/console/backend", domid);
- path = libxl__xs_read(gc, XBT_NULL, path);
- GCNEW(dev);
- if (path && strcmp(path, "") &&
- libxl__parse_backend_path(gc, path, dev) == 0) {
- dev->domid = domid;
- dev->kind = LIBXL__DEVICE_KIND_CONSOLE;
- dev->devid = 0;
-
- /* Currently console devices can be destroyed synchronously by just
- * removing xenstore entries, this is what libxl__device_destroy does.
- */
- libxl__device_destroy(gc, dev);
- }
-
out:
libxl__multidev_prepared(egc, multidev, rc);
}
--
2.1.4
[-- Attachment #30: xsa175-4.5/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch --]
[-- Type: application/octet-stream, Size: 1395 bytes --]
From 1070d8daa6a73a66ceabd9cd6c89ce712b69bafe Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 4 May 2016 15:30:32 +0100
Subject: [PATCH 04/12] libxl: Do not trust frontend in libxl__device_nextid
When selecting the devid for a new device, we should look in
/libxl/device for existing devices, not in the frontend area.
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 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 312a371..170dd45 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1985,15 +1985,16 @@ out:
/* common function to get next device id */
static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
{
- char *dompath, **l;
+ char *libxl_dom_path, **l;
unsigned int nb;
int nextid = -1;
- if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
return nextid;
l = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/device/%s", dompath, device), &nb);
+ GCSPRINTF("%s/device/%s", libxl_dom_path, device),
+ &nb);
if (l == NULL || nb == 0)
nextid = 0;
else
--
2.1.4
[-- Attachment #31: xsa175-4.5/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch --]
[-- Type: application/octet-stream, Size: 3890 bytes --]
From 1d70543c4e53c2fc283e520d098069ac41583469 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:08:49 +0100
Subject: [PATCH 05/12] libxl: Do not trust frontend for disk eject event
Use the /libxl path for interpreting disk eject watch events: do not
read the backend path out of the frontend. Instead, use the version
in /libxl. That avoids us relying on the guest-modifiable
$frontend/backend pointer.
To implement this we store the path
/libxl/$guest/device/vbd/$devid/backend
in the evgen structure.
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 | 28 ++++++++++++++++++++++------
tools/libxl/libxl_internal.h | 2 +-
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 170dd45..9c0fed4 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1323,9 +1323,10 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
const char *wpath, const char *epath) {
EGC_GC;
libxl_evgen_disk_eject *evg = (void*)w;
- char *backend;
+ const char *backend;
char *value;
char backend_type[BACKEND_STRING_SIZE+1];
+ int rc;
value = libxl__xs_read(gc, XBT_NULL, wpath);
@@ -1341,9 +1342,16 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
libxl_device_disk *disk = &ev->u.disk_eject.disk;
- backend = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%.*s/backend",
- (int)strlen(wpath)-6, wpath));
+ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
+ if (rc) {
+ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+ if (!backend) {
+ /* device has been removed, not simply ejected */
+ return;
+ }
sscanf(backend,
"/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
@@ -1392,11 +1400,18 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
if (!domid)
domid = guest_domid;
- path = libxl__sprintf(gc, "%s/device/vbd/%d/eject",
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+
+ path = GCSPRINTF("%s/device/vbd/%d/eject",
libxl__xs_get_dompath(gc, domid),
- libxl__device_disk_dev_number(vdev, NULL, NULL));
+ devid);
if (!path) { rc = ERROR_NOMEM; goto out; }
+ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid),
+ devid);
+ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
+
rc = libxl__ev_xswatch_register(gc, &evg->watch,
disk_eject_xswatch_callback, path);
if (rc) goto out;
@@ -1423,6 +1438,7 @@ void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
libxl__ev_xswatch_deregister(gc, &evg->watch);
free(evg->vdev);
+ free(evg->be_ptr_path);
free(evg);
CTX_UNLOCK;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index bfe06bd..302585c 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -271,7 +271,7 @@ struct libxl__evgen_disk_eject {
uint32_t domid;
LIBXL_LIST_ENTRY(libxl_evgen_disk_eject) entry;
libxl_ev_user user;
- char *vdev;
+ char *vdev, *be_ptr_path;
};
_hidden void
libxl__evdisable_disk_eject(libxl__gc*, libxl_evgen_disk_eject*);
--
2.1.4
[-- Attachment #32: xsa175-4.5/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 3378 bytes --]
From 11770db72bc644c322ad9044dbf86f9c6cb3a780 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Fri, 29 Apr 2016 19:21:51 +0100
Subject: [PATCH 06/12] libxl: Do not trust frontend for disk in getinfo
* Rename the frontend variable to `fe_path' to check we caught them all
* Read the backend path from /libxl, rather than from the frontend
* Parse the backend domid from the backend path, rather than reading it
from the frontend (and add the appropriate error path and initialisation)
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 | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 9c0fed4..69b7da7 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2796,27 +2796,34 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk, libxl_diskinfo *diskinfo)
{
GC_INIT(ctx);
- char *dompath, *diskpath;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
+
+ diskinfo->backend = NULL;
dompath = libxl__xs_get_dompath(gc, domid);
diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
/* tap devices entries in xenstore are written as vbd devices. */
- diskpath = libxl__sprintf(gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
+ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid), diskinfo->devid);
diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", diskpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!diskinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", diskpath));
- diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", diskpath));
+ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
+ &diskinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/ring-ref", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
libxl__sprintf(gc, "%s/frontend", diskinfo->backend), NULL);
@@ -2825,6 +2832,10 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
GC_FREE;
return 0;
+
+ out:
+ free(diskinfo->backend);
+ return rc;
}
int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
--
2.1.4
[-- Attachment #33: xsa175-4.5/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch --]
[-- Type: application/octet-stream, Size: 2387 bytes --]
From 54a34ac83f0826cd0213a6ebdb0c414cb5051ed2 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:58:32 +0100
Subject: [PATCH 07/12] libxl: Do not trust frontend for vtpm list
libxl_device_vtpm_list needs to enumerate and identify devices without
trusting frontend-controlled data. So
* Use the /libxl path to enumerate vtpms.
* Use the /libxl path to find the corresponding backends.
* Parse the backend path to find the backend domid.
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 | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 69b7da7..b91eee8 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2173,14 +2173,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
GC_INIT(ctx);
libxl_device_vtpm* vtpms = NULL;
- char* fe_path = NULL;
+ char *libxl_path;
char** dir = NULL;
unsigned int ndirs = 0;
+ int rc;
*num = 0;
- fe_path = libxl__sprintf(gc, "%s/device/vtpm", libxl__xs_get_dompath(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+ libxl_path = GCSPRINTF("%s/device/vtpm", libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);
if (dir && ndirs) {
vtpms = malloc(sizeof(*vtpms) * ndirs);
libxl_device_vtpm* vtpm;
@@ -2189,16 +2190,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
char* tmp;
const char* be_path = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/%s/backend",
- fe_path, *dir));
+ libxl_path, *dir));
libxl_device_vtpm_init(vtpm);
vtpm->devid = atoi(*dir);
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/%s/backend-id",
- fe_path, *dir));
- vtpm->backend_domid = atoi(tmp);
+ rc = libxl__backendpath_parse_domid(gc, be_path,
+ &vtpm->backend_domid);
+ if (rc) return NULL;
tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
if (tmp) {
--
2.1.4
[-- Attachment #34: xsa175-4.5/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2100 bytes --]
From b83d66dfb3905dfd627f5e4833d74be274771e43 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:00:20 +0100
Subject: [PATCH 08/12] libxl: Do not trust frontend for vtpm in getinfo
libxl_device_vtpm_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b91eee8..65b9953 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2222,7 +2222,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
libxl_vtpminfo *vtpminfo)
{
GC_INIT(ctx);
- char *dompath, *vtpmpath;
+ char *libxl_path, *dompath, *vtpmpath;
char *val;
int rc = 0;
@@ -2231,8 +2231,10 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
vtpminfo->devid = vtpm->devid;
vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vtpm/%d",
+ libxl__xs_libxl_path(gc, domid), vtpminfo->devid);
vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", vtpmpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!vtpminfo->backend) {
goto err;
}
@@ -2240,9 +2242,9 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
goto err;
}
- val = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/backend-id", vtpmpath));
- vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
+ &vtpminfo->backend_id);
+ if (rc) goto exit;
val = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/state", vtpmpath));
--
2.1.4
[-- Attachment #35: xsa175-4.5/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch --]
[-- Type: application/octet-stream, Size: 1505 bytes --]
From c626ea4768294b73ef24fafe7af9ad1221c1c48d Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:52:53 +0100
Subject: [PATCH 09/12] libxl: Do not trust frontend for nic in
libxl_devid_to_device_nic
Find the backend by reading the pointer in /libxl rather than in the
guest's frontend area.
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 | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 65b9953..4c45269 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3540,17 +3540,17 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_nic *nic)
{
GC_INIT(ctx);
- char *dompath, *path;
+ char *libxl_dom_path, *path;
int rc = ERROR_FAIL;
libxl_device_nic_init(nic);
- dompath = libxl__xs_get_dompath(gc, domid);
- if (!dompath)
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ if (!libxl_dom_path)
goto out;
path = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%s/device/vif/%d/backend",
- dompath, devid));
+ GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path,
+ devid));
if (!path)
goto out;
--
2.1.4
[-- Attachment #36: xsa175-4.5/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2812 bytes --]
From 9d1982995e8d5645ae149bce670bea82fda31421 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:31:07 +0100
Subject: [PATCH 10/12] libxl: Do not trust frontend for nic in getinfo
libxl_device_nic_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 4c45269..34853f8 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3629,22 +3629,27 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic, libxl_nicinfo *nicinfo)
{
GC_INIT(ctx);
- char *dompath, *nicpath;
+ char *dompath, *nicpath, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
nicinfo->devid = nic->devid;
- nicpath = libxl__sprintf(gc, "%s/device/vif/%d", dompath, nicinfo->devid);
+ nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vif/%d",
+ libxl__xs_libxl_path(gc, domid), nicinfo->devid);
nicinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", nicpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!nicinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", nicpath));
- nicinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", nicpath));
+ rc = libxl__backendpath_parse_domid(gc, nicinfo->backend,
+ &nicinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath));
nicinfo->state = val ? strtoul(val, NULL, 10) : -1;
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", nicpath));
nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
@@ -3657,8 +3662,10 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend-id", nicinfo->backend));
nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
const char *libxl__device_nic_devname(libxl__gc *gc,
--
2.1.4
[-- Attachment #37: xsa175-4.5/0011-libxl-Do-not-trust-frontend-for-channel-in-list.patch --]
[-- Type: application/octet-stream, Size: 4163 bytes --]
From 55fcc20fa75d9458805bf8130ce257cddd8db71f 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(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 34853f8..6ffb173 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3726,6 +3726,8 @@ int libxl__device_console_add(libxl__gc *gc, uint32_t domid,
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");
@@ -3864,34 +3866,35 @@ static int libxl__device_channel_from_xs_be(libxl__gc *gc,
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) {
@@ -3922,7 +3925,7 @@ libxl_device_channel *libxl_device_channel_list(libxl_ctx *ctx,
*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;
--
2.1.4
[-- Attachment #38: xsa175-4.5/0012-libxl-Do-not-trust-frontend-for-channel-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 4963 bytes --]
From 0333ec931e023a66dc03392c9bcb1040018b00e8 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 17:24:32 +0100
Subject: [PATCH 12/12] libxl: Do not trust frontend for channel in getinfo
libxl_device_channel_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
* Tolerate FRONTEND/tty vanishing.
Note that there is a strange off-by-one error in the computation of
both fe_path and libxl_path in libxl_device_channel_getinfo: the
incoming channel->devid, which is copied to channelinfo->devid, has +1
applied to calculate the frontend path (and, after this patch, the
libxl path). I.e., the devid passed to libxl_device_channel_getinfo
must be one less than the actual devid for the device being asked
about.
This is actually a bug which mirrors a bug in
libxl__append_channel_list, which fills in the devids of the channel
devices it finds with sequentially increasing numbers starting at 0.
In the usual case channels have real devids starting at 1 (because
there is the console, which is devid 0, but not a channel). So these
bugs usually cancel out.
We do not address this problem at this time. This bug does not have
any security implications.
This patch 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 | 44 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 36 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 6ffb173..2dd2467 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3946,23 +3946,28 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_channelinfo *channelinfo)
{
GC_INIT(ctx);
- char *dompath, *fe_path;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
channelinfo->devid = channel->devid;
- fe_path = libxl__sprintf(gc, "%s/device/console/%d", dompath,
- channelinfo->devid + 1);
+ fe_path = GCSPRINTF("%s/device/console/%d", dompath,
+ channelinfo->devid + 1);
+ libxl_path = GCSPRINTF("%s/device/console/%d",
+ libxl__xs_libxl_path(gc, domid),
+ channelinfo->devid + 1);
channelinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend",
- fe_path), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!channelinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/backend-id", fe_path));
- channelinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, channelinfo->backend,
+ &channelinfo->backend_id);
+ if (rc) goto out;
+
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
channelinfo->state = val ? strtoul(val, NULL, 10) : -1;
channelinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
@@ -3980,13 +3985,36 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, uint32_t domid,
switch (channel->connection) {
case LIBXL_CHANNEL_CONNECTION_PTY:
val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/tty", fe_path));
+ /*
+ * It is obviously very wrong for this value to be in the
+ * frontend. But in XSA-175 we don't want to re-engineer
+ * this because other xenconsole code elsewhere (some
+ * even out of tree, perhaps) expects this node to be
+ * here.
+ *
+ * FE/pty is readonly for the guest. It always exists if
+ * FE does because libxl__device_console_add
+ * unconditionally creates it and nothing deletes it.
+ *
+ * The guest can delete the whole FE (which it has write
+ * privilege on) but the containing directories
+ * /local/GUEST[/device[/console]] are also RO for the
+ * guest. So if the guest deletes FE it cannot recreate
+ * it.
+ *
+ * Therefore the guest cannot cause FE/pty to contain bad
+ * data, although it can cause it to not exist.
+ */
+ if (!val) val = "/NO-SUCH-PATH";
channelinfo->u.pty.path = strdup(val);
break;
default:
break;
}
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
/******************************************************************************/
--
2.1.4
[-- Attachment #39: xsa175-4.4/0001-libxl-Record-backend-frontend-paths-in-libxl-DOMID.patch --]
[-- Type: application/octet-stream, Size: 7566 bytes --]
From 9a5ccbd7b599c75b3a95c52bf128e362c0ae9e45 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Mon, 16 May 2016 16:44:31 +0100
Subject: [PATCH 01/10] libxl: Record backend/frontend paths in /libxl/$DOMID
This gives us a record of all the backends we have set up for a
domain, which is separate from the frontends in
/local/domain/$DOMID/device.
In particular:
1. A guest has write permission for the frontend path:
/local/domain/$DOMID/device/$KIND/$DEVID
which means that the guest can completely delete the frontend.
(They can't recreate it because they don't have write permission
on the containing directory.)
2. A guest has write permission for the backend path recorded in the
frontend, ie, it can write to
/local/domain/$DOMID/device/$KIND/$DEVID/backend
which means that the guest can break the association between
frontend and backend.
So we can't rely on iterating over the frontends to find all the
backends, or examining a frontend to discover how a device is
configured.
So, have libxl__device_generic_add record the frontend and backend
paths in /libxl/$DOMID/device, and have libxl__device_destroy remove
them again.
Create the containing directory /libxl/GUEST/device in
libxl__domain_make. The already existing xs_rm in devices_destroy_cb
will take care of removing it.
This is part of XSA-175.
Backport note: Backported over 7472ced, which fixes a bug in driver
domain teardown.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
v2: Correct actual path computation (!)
v3: Correct actual path computation - really this time (!)
---
docs/misc/xenstore-paths.markdown | 15 +++++++++++++++
tools/libxl/libxl_create.c | 2 ++
tools/libxl/libxl_device.c | 34 +++++++++++++++++++++++++++++++++-
tools/libxl/libxl_internal.h | 1 +
4 files changed, 51 insertions(+), 1 deletion(-)
diff --git a/docs/misc/xenstore-paths.markdown b/docs/misc/xenstore-paths.markdown
index 70ab7f4..e018b55 100644
--- a/docs/misc/xenstore-paths.markdown
+++ b/docs/misc/xenstore-paths.markdown
@@ -381,6 +381,21 @@ The guest's virtual time offset from UTC in seconds.
### libxl Specific Paths
+#### /libxl/$DOMID/device/$KIND/$DEVID
+
+Created by libxl for every frontend/backend pair created for $DOMID.
+Used by libxl for enumeration and management of the device.
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/frontend
+
+Path in xenstore to the frontend, normally
+/local/domain/$DOMID/device/$KIND/$DEVID
+
+#### /libxl/$DOMID/device/$KIND/$DEVID/backend
+
+Path in xenstore to the backend, normally
+/local/domain/$BACKEND_DOMID/backend/$KIND/$DOMID/$DEVID
+
#### /libxl/$DOMID/dm-version ("qemu\_xen"|"qemu\_xen\_traditional") = [n,INTERNAL]
The device model version for a domain.
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 5292c15..0e26666 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -528,6 +528,8 @@ retry_transaction:
xs_rm(ctx->xsh, t, libxl_path);
libxl__xs_mkdir(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));
+ libxl__xs_mkdir(gc, t, GCSPRINTF("%s/device", libxl_path),
+ noperm, ARRAY_SIZE(noperm));
xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 29ed547..e9d2424 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -40,6 +40,15 @@ char *libxl__device_backend_path(libxl__gc *gc, libxl__device *device)
device->domid, device->devid);
}
+char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device)
+{
+ char *libxl_dom_path = libxl__xs_libxl_path(gc, device->domid);
+
+ return GCSPRINTF("%s/device/%s/%d", libxl_dom_path,
+ libxl__device_kind_to_string(device->kind),
+ device->devid);
+}
+
int libxl__parse_backend_path(libxl__gc *gc,
const char *path,
libxl__device *dev)
@@ -87,14 +96,16 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, char **bents, char **fents, char **ro_fents)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
- char *frontend_path, *backend_path;
+ char *frontend_path, *backend_path, *libxl_path;
struct xs_permissions frontend_perms[2];
struct xs_permissions ro_frontend_perms[2];
struct xs_permissions backend_perms[2];
int create_transaction = t == XBT_NULL;
+ int rc;
frontend_path = libxl__device_frontend_path(gc, device);
backend_path = libxl__device_backend_path(gc, device);
+ libxl_path = libxl__device_libxl_path(gc, device);
frontend_perms[0].id = device->domid;
frontend_perms[0].perms = XS_PERM_NONE;
@@ -109,8 +120,22 @@ int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
retry_transaction:
if (create_transaction)
t = xs_transaction_start(ctx->xsh);
+
/* FIXME: read frontend_path and check state before removing stuff */
+ rc = libxl__xs_rm_checked(gc, t, libxl_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/frontend",libxl_path),
+ frontend_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, GCSPRINTF("%s/backend",libxl_path),
+ backend_path);
+ if (rc) goto out;
+
+ /* xxx much of this function lacks error checks! */
+
if (fents || ro_fents) {
xs_rm(ctx->xsh, t, frontend_path);
xs_mkdir(ctx->xsh, t, frontend_path);
@@ -156,6 +181,11 @@ retry_transaction:
}
}
return 0;
+
+ out:
+ if (create_transaction && t)
+ libxl__xs_transaction_abort(gc, &t);
+ return rc;
}
typedef struct {
@@ -552,6 +582,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
{
const char *be_path = libxl__device_backend_path(gc, dev);
const char *fe_path = libxl__device_frontend_path(gc, dev);
+ const char *libxl_path = libxl__device_libxl_path(gc, dev);
const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params");
const char *tapdisk_params;
xs_transaction_t t = 0;
@@ -576,6 +607,7 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
*/
libxl__xs_path_cleanup(gc, t, fe_path);
libxl__xs_path_cleanup(gc, t, be_path);
+ libxl__xs_path_cleanup(gc, t, libxl_path);
} else if (dev->backend_domid == domid) {
/*
* The driver domain is in charge for removing what it can
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index f6d469b..801e95d 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -968,6 +968,7 @@ _hidden int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
libxl__device *device, 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 char *libxl__device_libxl_path(libxl__gc *gc, libxl__device *device);
_hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
libxl__device *dev);
_hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
--
2.1.4
[-- Attachment #40: xsa175-4.4/0002-libxl-Provide-libxl__backendpath_parse_domid.patch --]
[-- Type: application/octet-stream, Size: 2166 bytes --]
From 35a740847bea0a2aede72de7b2b8b49eef36e4eb Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:34:19 +0100
Subject: [PATCH 02/10] libxl: Provide libxl__backendpath_parse_domid
Multiple places in libxl need to figure out the backend domid of a
device. This can be discovered easily by looking at the backend path,
which always starts /local/domain/$backend_domid/.
There are no call sites yet.
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_device.c | 15 +++++++++++++++
tools/libxl/libxl_internal.h | 2 ++
2 files changed, 17 insertions(+)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index e9d2424..b500264 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -270,6 +270,21 @@ static int disk_try_backend(disk_try_backend_args *a,
return 0;
}
+int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out) {
+ int r;
+ unsigned int domid_sc;
+ char delim_sc;
+
+ r = sscanf(be_path, "/local/domain/%u%c", &domid_sc, &delim_sc);
+ if (!(r==2 && delim_sc=='/')) {
+ LOG(ERROR, "internal error: backend path %s unparseable!", be_path);
+ return ERROR_FAIL;
+ }
+ *domid_out = domid_sc;
+ return 0;
+}
+
int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
libxl_disk_backend ok;
disk_try_backend_args a;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 801e95d..3fc9997 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -574,6 +574,8 @@ _hidden bool libxl__xs_mkdir(libxl__gc *gc, xs_transaction_t t,
_hidden char *libxl__xs_libxl_path(libxl__gc *gc, uint32_t domid);
+_hidden int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
+ libxl_domid *domid_out);
/*----- "checked" xenstore access functions -----*/
/* Each of these functions will check that it succeeded; if it
--
2.1.4
[-- Attachment #41: xsa175-4.4/0003-libxl-Do-not-trust-frontend-in-libxl__devices_destro.patch --]
[-- Type: application/octet-stream, Size: 3072 bytes --]
From ef216637a72ce30661d28a47ccc7464869baa398 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 18:39:36 +0100
Subject: [PATCH 03/10] libxl: Do not trust frontend in libxl__devices_destroy
We need to enumerate the devices we have provided to a domain, without
trusting the guest-writeable (or, at least, guest-deletable) frontend
paths.
Instead, enumerate via, and read the backend path from, /libxl.
The console /libxl path is regular, so the special case for console 0
is not relevant any more: /libxl/GUEST/device/console/0 will be found,
and then libxl__device_destroy will DTRT to the right frontend path.
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_device.c | 22 +++-------------------
1 file changed, 3 insertions(+), 19 deletions(-)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index b500264..e7650d0 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -665,7 +665,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
libxl__multidev_begin(ao, multidev);
multidev->callback = devices_remove_callback;
- path = GCSPRINTF("/local/domain/%d/device", domid);
+ path = GCSPRINTF("/libxl/%d/device", domid);
kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
if (!kinds) {
if (errno != ENOENT) {
@@ -678,12 +678,12 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
if (libxl__device_kind_from_string(kinds[i], &kind))
continue;
- path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]);
+ path = GCSPRINTF("/libxl/%d/device/%s", domid, kinds[i]);
devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries);
if (!devs)
continue;
for (j = 0; j < num_dev_xsentries; j++) {
- path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend",
+ path = GCSPRINTF("/libxl/%d/device/%s/%s/backend",
domid, kinds[i], devs[j]);
path = libxl__xs_read(gc, XBT_NULL, path);
GCNEW(dev);
@@ -708,22 +708,6 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
}
}
- /* console 0 frontend directory is not under /local/domain/<domid>/device */
- path = GCSPRINTF("/local/domain/%d/console/backend", domid);
- path = libxl__xs_read(gc, XBT_NULL, path);
- GCNEW(dev);
- if (path && strcmp(path, "") &&
- libxl__parse_backend_path(gc, path, dev) == 0) {
- dev->domid = domid;
- dev->kind = LIBXL__DEVICE_KIND_CONSOLE;
- dev->devid = 0;
-
- /* Currently console devices can be destroyed synchronously by just
- * removing xenstore entries, this is what libxl__device_destroy does.
- */
- libxl__device_destroy(gc, dev);
- }
-
out:
libxl__multidev_prepared(egc, multidev, rc);
}
--
2.1.4
[-- Attachment #42: xsa175-4.4/0004-libxl-Do-not-trust-frontend-in-libxl__device_nextid.patch --]
[-- Type: application/octet-stream, Size: 1395 bytes --]
From 90f14dc5c68f52baeef9722090695a166c7e083d Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 4 May 2016 15:30:32 +0100
Subject: [PATCH 04/10] libxl: Do not trust frontend in libxl__device_nextid
When selecting the devid for a new device, we should look in
/libxl/device for existing devices, not in the frontend area.
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 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index e2a5be3..b52e63e 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1743,15 +1743,16 @@ out:
/* common function to get next device id */
static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
{
- char *dompath, **l;
+ char *libxl_dom_path, **l;
unsigned int nb;
int nextid = -1;
- if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+ if (!(libxl_dom_path = libxl__xs_libxl_path(gc, domid)))
return nextid;
l = libxl__xs_directory(gc, XBT_NULL,
- GCSPRINTF("%s/device/%s", dompath, device), &nb);
+ GCSPRINTF("%s/device/%s", libxl_dom_path, device),
+ &nb);
if (l == NULL || nb == 0)
nextid = 0;
else
--
2.1.4
[-- Attachment #43: xsa175-4.4/0005-libxl-Do-not-trust-frontend-for-disk-eject-event.patch --]
[-- Type: application/octet-stream, Size: 3890 bytes --]
From d84e538d96525f75fc0aa7d0ebe3cd194186d0d4 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Wed, 27 Apr 2016 16:08:49 +0100
Subject: [PATCH 05/10] libxl: Do not trust frontend for disk eject event
Use the /libxl path for interpreting disk eject watch events: do not
read the backend path out of the frontend. Instead, use the version
in /libxl. That avoids us relying on the guest-modifiable
$frontend/backend pointer.
To implement this we store the path
/libxl/$guest/device/vbd/$devid/backend
in the evgen structure.
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 | 28 ++++++++++++++++++++++------
tools/libxl/libxl_internal.h | 2 +-
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b52e63e..f101334 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1141,9 +1141,10 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
const char *wpath, const char *epath) {
EGC_GC;
libxl_evgen_disk_eject *evg = (void*)w;
- char *backend;
+ const char *backend;
char *value;
char backend_type[BACKEND_STRING_SIZE+1];
+ int rc;
value = libxl__xs_read(gc, XBT_NULL, wpath);
@@ -1159,9 +1160,16 @@ static void disk_eject_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *w,
libxl_event *ev = NEW_EVENT(egc, DISK_EJECT, evg->domid, evg->user);
libxl_device_disk *disk = &ev->u.disk_eject.disk;
- backend = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%.*s/backend",
- (int)strlen(wpath)-6, wpath));
+ rc = libxl__xs_read_checked(gc, XBT_NULL, evg->be_ptr_path, &backend);
+ if (rc) {
+ LIBXL__EVENT_DISASTER(egc, "xs_read failed reading be_ptr_path",
+ errno, LIBXL_EVENT_TYPE_DISK_EJECT);
+ return;
+ }
+ if (!backend) {
+ /* device has been removed, not simply ejected */
+ return;
+ }
sscanf(backend,
"/local/domain/%d/backend/%" TOSTRING(BACKEND_STRING_SIZE)
@@ -1210,11 +1218,18 @@ int libxl_evenable_disk_eject(libxl_ctx *ctx, uint32_t guest_domid,
if (!domid)
domid = guest_domid;
- path = libxl__sprintf(gc, "%s/device/vbd/%d/eject",
+ int devid = libxl__device_disk_dev_number(vdev, NULL, NULL);
+
+ path = GCSPRINTF("%s/device/vbd/%d/eject",
libxl__xs_get_dompath(gc, domid),
- libxl__device_disk_dev_number(vdev, NULL, NULL));
+ devid);
if (!path) { rc = ERROR_NOMEM; goto out; }
+ const char *libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid),
+ devid);
+ evg->be_ptr_path = libxl__sprintf(NOGC, "%s/backend", libxl_path);
+
rc = libxl__ev_xswatch_register(gc, &evg->watch,
disk_eject_xswatch_callback, path);
if (rc) goto out;
@@ -1241,6 +1256,7 @@ void libxl__evdisable_disk_eject(libxl__gc *gc, libxl_evgen_disk_eject *evg) {
libxl__ev_xswatch_deregister(gc, &evg->watch);
free(evg->vdev);
+ free(evg->be_ptr_path);
free(evg);
CTX_UNLOCK;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 3fc9997..8128e76 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -257,7 +257,7 @@ struct libxl__evgen_disk_eject {
uint32_t domid;
LIBXL_LIST_ENTRY(libxl_evgen_disk_eject) entry;
libxl_ev_user user;
- char *vdev;
+ char *vdev, *be_ptr_path;
};
_hidden void
libxl__evdisable_disk_eject(libxl__gc*, libxl_evgen_disk_eject*);
--
2.1.4
[-- Attachment #44: xsa175-4.4/0006-libxl-Do-not-trust-frontend-for-disk-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 3378 bytes --]
From 3d1d7473c756d79e464600cee370c8759bd20f89 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Fri, 29 Apr 2016 19:21:51 +0100
Subject: [PATCH 06/10] libxl: Do not trust frontend for disk in getinfo
* Rename the frontend variable to `fe_path' to check we caught them all
* Read the backend path from /libxl, rather than from the frontend
* Parse the backend domid from the backend path, rather than reading it
from the frontend (and add the appropriate error path and initialisation)
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 | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index f101334..18f9f0a 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2449,27 +2449,34 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_disk *disk, libxl_diskinfo *diskinfo)
{
GC_INIT(ctx);
- char *dompath, *diskpath;
+ char *dompath, *fe_path, *libxl_path;
char *val;
+ int rc;
+
+ diskinfo->backend = NULL;
dompath = libxl__xs_get_dompath(gc, domid);
diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
/* tap devices entries in xenstore are written as vbd devices. */
- diskpath = libxl__sprintf(gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
+ fe_path = GCSPRINTF("%s/device/vbd/%d", dompath, diskinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vbd/%d",
+ libxl__xs_libxl_path(gc, domid), diskinfo->devid);
diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", diskpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!diskinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", diskpath));
- diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", diskpath));
+ rc = libxl__backendpath_parse_domid(gc, diskinfo->backend,
+ &diskinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", fe_path));
diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/event-channel", fe_path));
diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/ring-ref", diskpath));
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/ring-ref", fe_path));
diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
libxl__sprintf(gc, "%s/frontend", diskinfo->backend), NULL);
@@ -2478,6 +2485,10 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
GC_FREE;
return 0;
+
+ out:
+ free(diskinfo->backend);
+ return rc;
}
int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
--
2.1.4
[-- Attachment #45: xsa175-4.4/0007-libxl-Do-not-trust-frontend-for-vtpm-list.patch --]
[-- Type: application/octet-stream, Size: 2387 bytes --]
From 44aadb912061fc75e41fceb00c67b8d222a2c7c4 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:58:32 +0100
Subject: [PATCH 07/10] libxl: Do not trust frontend for vtpm list
libxl_device_vtpm_list needs to enumerate and identify devices without
trusting frontend-controlled data. So
* Use the /libxl path to enumerate vtpms.
* Use the /libxl path to find the corresponding backends.
* Parse the backend path to find the backend domid.
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 | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 18f9f0a..0886d92 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1879,14 +1879,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
GC_INIT(ctx);
libxl_device_vtpm* vtpms = NULL;
- char* fe_path = NULL;
+ char *libxl_path;
char** dir = NULL;
unsigned int ndirs = 0;
+ int rc;
*num = 0;
- fe_path = libxl__sprintf(gc, "%s/device/vtpm", libxl__xs_get_dompath(gc, domid));
- dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+ libxl_path = GCSPRINTF("%s/device/vtpm", libxl__xs_libxl_path(gc, domid));
+ dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);
if (dir && ndirs) {
vtpms = malloc(sizeof(*vtpms) * ndirs);
libxl_device_vtpm* vtpm;
@@ -1895,16 +1896,15 @@ libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
char* tmp;
const char* be_path = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/%s/backend",
- fe_path, *dir));
+ libxl_path, *dir));
libxl_device_vtpm_init(vtpm);
vtpm->devid = atoi(*dir);
- tmp = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/%s/backend-id",
- fe_path, *dir));
- vtpm->backend_domid = atoi(tmp);
+ rc = libxl__backendpath_parse_domid(gc, be_path,
+ &vtpm->backend_domid);
+ if (rc) return NULL;
tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path));
if (tmp) {
--
2.1.4
[-- Attachment #46: xsa175-4.4/0008-libxl-Do-not-trust-frontend-for-vtpm-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2100 bytes --]
From 593d796c753fea1c4cdc365273de777aff798fe9 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:00:20 +0100
Subject: [PATCH 08/10] libxl: Do not trust frontend for vtpm in getinfo
libxl_device_vtpm_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 0886d92..a0aeb50 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1928,7 +1928,7 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
libxl_vtpminfo *vtpminfo)
{
GC_INIT(ctx);
- char *dompath, *vtpmpath;
+ char *libxl_path, *dompath, *vtpmpath;
char *val;
int rc = 0;
@@ -1937,8 +1937,10 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
vtpminfo->devid = vtpm->devid;
vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vtpm/%d",
+ libxl__xs_libxl_path(gc, domid), vtpminfo->devid);
vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
- GCSPRINTF("%s/backend", vtpmpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!vtpminfo->backend) {
goto err;
}
@@ -1946,9 +1948,9 @@ int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
goto err;
}
- val = libxl__xs_read(gc, XBT_NULL,
- GCSPRINTF("%s/backend-id", vtpmpath));
- vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = libxl__backendpath_parse_domid(gc, vtpminfo->backend,
+ &vtpminfo->backend_id);
+ if (rc) goto exit;
val = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/state", vtpmpath));
--
2.1.4
[-- Attachment #47: xsa175-4.4/0009-libxl-Do-not-trust-frontend-for-nic-in-libxl_devid_t.patch --]
[-- Type: application/octet-stream, Size: 1505 bytes --]
From a7fb7be6b7a14e8ca5ab0609c49b06545d6772bf Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 15:52:53 +0100
Subject: [PATCH 09/10] libxl: Do not trust frontend for nic in
libxl_devid_to_device_nic
Find the backend by reading the pointer in /libxl rather than in the
guest's frontend area.
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 | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index a0aeb50..7a8faba 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3066,17 +3066,17 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
int devid, libxl_device_nic *nic)
{
GC_INIT(ctx);
- char *dompath, *path;
+ char *libxl_dom_path, *path;
int rc = ERROR_FAIL;
libxl_device_nic_init(nic);
- dompath = libxl__xs_get_dompath(gc, domid);
- if (!dompath)
+ libxl_dom_path = libxl__xs_libxl_path(gc, domid);
+ if (!libxl_dom_path)
goto out;
path = libxl__xs_read(gc, XBT_NULL,
- libxl__sprintf(gc, "%s/device/vif/%d/backend",
- dompath, devid));
+ GCSPRINTF("%s/device/vif/%d/backend", libxl_dom_path,
+ devid));
if (!path)
goto out;
--
2.1.4
[-- Attachment #48: xsa175-4.4/0010-libxl-Do-not-trust-frontend-for-nic-in-getinfo.patch --]
[-- Type: application/octet-stream, Size: 2812 bytes --]
From e4c0f9b55819194a501e3ecae6b12188a2db1d01 Mon Sep 17 00:00:00 2001
From: Ian Jackson <ian.jackson@eu.citrix.com>
Date: Tue, 3 May 2016 16:31:07 +0100
Subject: [PATCH 10/10] libxl: Do not trust frontend for nic in getinfo
libxl_device_nic_getinfo needs to examine devices without trusting
frontend-controlled data. So:
* Use /libxl to find the backend path.
* Parse the backend path to find the backend domid, rather than
reading it from the frontend.
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 | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 7a8faba..c794d3a 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -3155,22 +3155,27 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
libxl_device_nic *nic, libxl_nicinfo *nicinfo)
{
GC_INIT(ctx);
- char *dompath, *nicpath;
+ char *dompath, *nicpath, *libxl_path;
char *val;
+ int rc;
dompath = libxl__xs_get_dompath(gc, domid);
nicinfo->devid = nic->devid;
- nicpath = libxl__sprintf(gc, "%s/device/vif/%d", dompath, nicinfo->devid);
+ nicpath = GCSPRINTF("%s/device/vif/%d", dompath, nicinfo->devid);
+ libxl_path = GCSPRINTF("%s/device/vif/%d",
+ libxl__xs_libxl_path(gc, domid), nicinfo->devid);
nicinfo->backend = xs_read(ctx->xsh, XBT_NULL,
- libxl__sprintf(gc, "%s/backend", nicpath), NULL);
+ GCSPRINTF("%s/backend", libxl_path), NULL);
if (!nicinfo->backend) {
GC_FREE;
return ERROR_FAIL;
}
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/backend-id", nicpath));
- nicinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
- val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/state", nicpath));
+ rc = libxl__backendpath_parse_domid(gc, nicinfo->backend,
+ &nicinfo->backend_id);
+ if (rc) goto out;
+
+ val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/state", nicpath));
nicinfo->state = val ? strtoul(val, NULL, 10) : -1;
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/event-channel", nicpath));
nicinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
@@ -3183,8 +3188,10 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
val = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "%s/frontend-id", nicinfo->backend));
nicinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+ rc = 0;
+ out:
GC_FREE;
- return 0;
+ return rc;
}
const char *libxl__device_nic_devname(libxl__gc *gc,
--
2.1.4
[-- Attachment #49: Type: text/plain, Size: 126 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-06-06 16:56 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-02 12:52 Xen Security Advisory 175 (CVE-2016-4962) - Unsanitised guest input in libxl device handling code Xen.org security team
-- strict thread matches above, loose matches on Subject: below --
2016-06-06 16:56 Xen.org security team
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).