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>
This commit is contained in:
Ian Jackson authored and Ian Jackson committed 2016-06-06 15:31:24 +01:00
1 parent 8c4b40337b
commit 2978e1ae3d
4 files changed
+51 -1

No files matched your search

+15
View File
@@ -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.
+2
View File
@@ -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);
+33 -1
View File
@@ -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
+1
View File
@@ -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);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.