[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 2/3] libxl: do not assume Dom0 backend while listing disks and nics
One more place where code assumed that all backends are in dom0. List devices in domain device/ tree, instead of backend/ of dom0. Additionally fix libxl_devid_to_device_{nic,disk} to fill backend_domid properly. Changes in v2: - restructure *_from_xs_be to *_from_xs_fe, which take care of getting backend path and backend domid (with libxl__get_backend_from_xs_fe helper) - sanity checks on frontend-controlled entries Signed-off-by: Marek Marczykowski <marmarek@xxxxxxxxxxxxxxxxxxxxxx> --- tools/libxl/libxl.c | 162 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 127 insertions(+), 35 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 5b9a3df..cb4a2a8 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -1739,6 +1739,83 @@ static int libxl__resolve_domid(libxl__gc *gc, const char *name, return libxl_domain_qualifier_to_domid(CTX, name, domid); } +/* Get backend path from frontend, with some sanity checks: + * - if both points to each other + * - if backend is owned by backend domid + * + * Returns backend domid or -1 on error. If no error reported, be_path will be + * filled with backend path. + */ +static int libxl__get_backend_from_xs_fe(libxl__gc *gc, const char *fe_path, + const char **be_path_out) +{ + int be_domid; + const char *be_domid_str; + const char *be_path; + const char *fe_path_from_be; + char *be_dompath; + char *be_base_path; + struct xs_permissions *be_perms; + unsigned int be_perms_count; + + if (libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/backend-id", fe_path), &be_domid_str)) { + LOG(ERROR, "Missing xenstore node %s/backend-id", fe_path); + return -1; + } + be_domid = strtoul(be_domid_str, NULL, 10); + + if (libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/backend", fe_path), &be_path)) { + LOG(ERROR, "Missing xenstore node %s/backend", fe_path); + return -1; + } + + if (!(be_dompath = libxl__xs_get_dompath(gc, be_domid))) { + LOG(ERROR, "Failed to get dompath for domain %d", be_domid); + return -1; + } + + be_base_path = GCSPRINTF("%s/backend/", be_dompath); + if (strncmp(be_path, be_base_path, strlen(be_base_path))) { + /* possible malicious frontend action */ + LOG(ERROR, "Backend xenstore path %s not withing %s", + be_path, + be_base_path); + return -1; + } + + be_perms = libxl__xs_get_permissions(gc, XBT_NULL, be_path, &be_perms_count); + if (!be_perms) { + LOG(ERROR, "Failed to get %s path permissions", be_path); + return -1; + } + + if (be_perms[0].id != be_domid) { + /* possible malicious frontend action */ + /* perhaps LIBXL_TOOLSTACK_DOMID should be also allowed? */ + LOG(ERROR, "Backend path %s not owned by backend domain (owner: %d)", be_path, be_perms[0].id); + return -1; + } + + if (libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/frontend", be_path), &fe_path_from_be)) { + LOG(ERROR, "Missing xenstore node %s/frontend", be_path); + return -1; + } + + if (strcmp(fe_path, fe_path_from_be)) { + /* possible malicious frontend action */ + LOG(ERROR, "Frontend path from backend (%s) doesn't match original " + "frontend path (%s)", fe_path_from_be, fe_path); + return -1; + } + + *be_path_out = be_path; + + return be_domid; +} + /******************************************************************************/ int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm) { @@ -2235,16 +2312,24 @@ void libxl__device_disk_add(libxl__egc *egc, uint32_t domid, device_disk_add(egc, domid, disk, aodev, NULL, NULL); } -static int libxl__device_disk_from_xs_be(libxl__gc *gc, - const char *be_path, +static int libxl__device_disk_from_xs_fe(libxl__gc *gc, + const char *fe_path, libxl_device_disk *disk) { libxl_ctx *ctx = libxl__gc_owner(gc); unsigned int len; + const char *be_path; + int be_domid; char *tmp; libxl_device_disk_init(disk); + be_domid = libxl__get_backend_from_xs_fe(gc, fe_path, &be_path); + if (be_domid < 0) + goto cleanup; + + disk->backend_domid = be_domid; + /* "params" may not be present; but everything else must be. */ tmp = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(gc, "%s/params", be_path), &len); @@ -2322,13 +2407,13 @@ int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid, if (!dompath) { goto out; } - path = libxl__xs_read(gc, XBT_NULL, - libxl__sprintf(gc, "%s/device/vbd/%d/backend", - dompath, devid)); + path = libxl__sprintf(gc, "%s/device/vbd/%d", + dompath, devid); if (!path) goto out; - rc = libxl__device_disk_from_xs_be(gc, path, disk); + rc = libxl__device_disk_from_xs_fe(gc, path, disk); + out: GC_FREE; return rc; @@ -2341,17 +2426,17 @@ static int libxl__append_disk_list_of_type(libxl__gc *gc, libxl_device_disk **disks, int *ndisks) { - char *be_path = NULL; + char *fe_path = NULL; char **dir = NULL; unsigned int n = 0; libxl_device_disk *pdisk = NULL, *pdisk_end = NULL; int rc=0; int initial_disks = *ndisks; - be_path = libxl__sprintf(gc, "%s/backend/%s/%d", - libxl__xs_get_dompath(gc, 0), type, domid); - dir = libxl__xs_directory(gc, XBT_NULL, be_path, &n); - if (dir) { + fe_path = libxl__sprintf(gc, "%s/device/%s", + libxl__xs_get_dompath(gc, domid), type); + dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &n); + if (dir && n) { libxl_device_disk *tmp; tmp = realloc(*disks, sizeof (libxl_device_disk) * (*ndisks + n)); if (tmp == NULL) @@ -2360,11 +2445,10 @@ static int libxl__append_disk_list_of_type(libxl__gc *gc, pdisk = *disks + initial_disks; pdisk_end = *disks + initial_disks + n; for (; pdisk < pdisk_end; pdisk++, dir++) { - const char *p; - p = libxl__sprintf(gc, "%s/%s", be_path, *dir); - if ((rc=libxl__device_disk_from_xs_be(gc, p, pdisk))) + rc = libxl__device_disk_from_xs_fe(gc, + GCSPRINTF("%s/%s", fe_path, *dir), pdisk); + if (rc) goto out; - pdisk->backend_domid = 0; *ndisks += 1; } } @@ -2949,17 +3033,25 @@ out: return; } -static void libxl__device_nic_from_xs_be(libxl__gc *gc, - const char *be_path, +static int libxl__device_nic_from_xs_fe(libxl__gc *gc, + const char *fe_path, libxl_device_nic *nic) { libxl_ctx *ctx = libxl__gc_owner(gc); unsigned int len; + const char *be_path; + int be_domid; char *tmp; int rc; + be_domid = libxl__get_backend_from_xs_fe(gc, fe_path, &be_path); + if (be_domid < 0) + return ERROR_FAIL; + libxl_device_nic_init(nic); + nic->backend_domid = be_domid; + tmp = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(gc, "%s/handle", be_path), &len); if ( tmp ) @@ -2988,6 +3080,8 @@ static void libxl__device_nic_from_xs_be(libxl__gc *gc, nic->nictype = LIBXL_NIC_TYPE_VIF; nic->model = NULL; /* XXX Only for TYPE_IOEMU */ nic->ifname = NULL; /* XXX Only for TYPE_IOEMU */ + + return 0; } int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid, @@ -3002,15 +3096,11 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid, if (!dompath) goto out; - path = libxl__xs_read(gc, XBT_NULL, - libxl__sprintf(gc, "%s/device/vif/%d/backend", - dompath, devid)); + path = libxl__sprintf(gc, "%s/device/vif/%d", dompath, devid); if (!path) goto out; - libxl__device_nic_from_xs_be(gc, path, nic); - - rc = 0; + rc = libxl__device_nic_from_xs_fe(gc, path, nic); out: GC_FREE; return rc; @@ -3022,31 +3112,33 @@ static int libxl__append_nic_list_of_type(libxl__gc *gc, libxl_device_nic **nics, int *nnics) { - char *be_path = NULL; + char *fe_path = NULL; char **dir = NULL; unsigned int n = 0; libxl_device_nic *pnic = NULL, *pnic_end = NULL; + int rc = 0; - be_path = libxl__sprintf(gc, "%s/backend/%s/%d", - libxl__xs_get_dompath(gc, 0), type, domid); - dir = libxl__xs_directory(gc, XBT_NULL, be_path, &n); - if (dir) { + fe_path = libxl__sprintf(gc, "%s/device/%s", + libxl__xs_get_dompath(gc, domid), type); + dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &n); + if (dir && n) { libxl_device_nic *tmp; tmp = realloc(*nics, sizeof (libxl_device_nic) * (*nnics + n)); if (tmp == NULL) return ERROR_NOMEM; *nics = tmp; pnic = *nics + *nnics; - *nnics += n; - pnic_end = *nics + *nnics; + pnic_end = *nics + *nnics + n; for (; pnic < pnic_end; pnic++, dir++) { - const char *p; - p = libxl__sprintf(gc, "%s/%s", be_path, *dir); - libxl__device_nic_from_xs_be(gc, p, pnic); - pnic->backend_domid = 0; + rc = libxl__device_nic_from_xs_fe(gc, + GCSPRINTF("%s/%s", fe_path, *dir), pnic); + if (rc) + goto out; + *nnics += 1; } } - return 0; +out: + return rc; } libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num) -- 1.8.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |