All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Roger Pau Monné" <roger.pau@citrix.com>
To: Marek Marczykowski <marmarek@invisiblethingslab.com>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>,
	Ian Campbell <Ian.Campbell@citrix.com>,
	"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Subject: Re: [PATCH v2 2/3] libxl: do not assume Dom0 backend while listing disks and nics
Date: Wed, 8 May 2013 12:22:43 +0200	[thread overview]
Message-ID: <518A2773.2080902@citrix.com> (raw)
In-Reply-To: <4a8ea9106b7700bdf37b8de1347343f8ade4b1fb.1367987733.git.marmarek@invisiblethingslab.com>

On 08/05/13 05:39, Marek Marczykowski wrote:
> 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@invisiblethingslab.com>
> ---
>  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;

It will be better to propagate the error returned from
libxl__xs_read_checked:

rc = libxl__xs_read_checked(gc, XBT_NULL,
               GCSPRINTF("%s/backend-id", fe_path), &be_domid_str);
if (rc) {
    LOG(ERROR, "Missing xenstore node %s/backend-id", fe_path);
    return rc;
}

Or better, have a fail label that could be used when an error is detected:

rc = libxl__xs_read_checked(gc, XBT_NULL,
               GCSPRINTF("%s/backend-id", fe_path), &be_domid_str);
if (rc) {
    LOG(ERROR, "Missing xenstore node %s/backend-id", fe_path);
    goto fail;
}

...

    return be_domid;

fail:
    assert(rc);
    return rc;

Also, the -1s below should be replaced with ERROR_FAIL or some more
appropriate error value.

> +    }
> +    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);

GCSPRINTF

>      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);

GCSPRINTF

> +    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);

GCSPRINTF

>      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);

GCSPRINTF

> +    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)
> 

  reply	other threads:[~2013-05-08 10:22 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-08  4:35 [PATCH v2 0/3] Get devices list from frontend xenstore entries Marek Marczykowski
2013-05-08  3:39 ` [PATCH v2 2/3] libxl: do not assume Dom0 backend while listing disks and nics Marek Marczykowski
2013-05-08 10:22   ` Roger Pau Monné [this message]
2013-05-08  3:39 ` [PATCH v2 1/3] libxl: add libxl__xs_get_permissions helper Marek Marczykowski
2013-05-08  9:32   ` Roger Pau Monné
2013-05-08  3:48 ` [PATCH v2 3/3] libxl: reduce code duplication in libxl_device_vtpm_list Marek Marczykowski
2013-05-08 11:49 ` [PATCH v2 0/3] Get devices list from frontend xenstore entries Ian Campbell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=518A2773.2080902@citrix.com \
    --to=roger.pau@citrix.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=Ian.Jackson@eu.citrix.com \
    --cc=marmarek@invisiblethingslab.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.