[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 2/5] xen/common/domctl: introduce XEN_DOMCTL_get/setdomaincontext



On 07.04.2020 19:38, Paul Durrant wrote:
> @@ -358,6 +359,113 @@ static struct vnuma_info *vnuma_init(const struct 
> xen_domctl_vnuma *uinfo,
>      return ERR_PTR(ret);
>  }
>  
> +struct domctl_context
> +{
> +    void *buffer;
> +    size_t len;
> +    size_t cur;
> +};
> +
> +static int accumulate_size(void *priv, const void *data, size_t len)
> +{
> +    struct domctl_context *c = priv;
> +
> +    if ( c->len + len < c->len )
> +        return -EOVERFLOW;
> +
> +    c->len += len;
> +
> +    return 0;
> +}
> +
> +static int save_data(void *priv, const void *data, size_t len)
> +{
> +    struct domctl_context *c = priv;
> +
> +    if ( c->len - c->cur < len )
> +        return -ENOSPC;
> +
> +    memcpy(c->buffer + c->cur, data, len);
> +    c->cur += len;
> +
> +    return 0;
> +}
> +
> +static int getdomaincontext(struct domain *d,
> +                            struct xen_domctl_getdomaincontext *gdc)
> +{
> +    struct domctl_context c = { };

Please can you use ZERO_BLOCK_PTR or some such for the buffer
field, such that errnoeous use of the field would not end up
as a (PV-controllable) NULL deref. (Yes, it's a domctl, but
still.) This being common code you also want to get things
right for Arm, irrespective of whether the code will be dead
there for now.

> +    int rc;
> +
> +    if ( d == current->domain )
> +        return -EPERM;
> +
> +    if ( guest_handle_is_null(gdc->buffer) ) /* query for buffer size */
> +    {
> +        if ( gdc->size )
> +            return -EINVAL;
> +
> +        /* dry run to acquire buffer size */
> +        rc = domain_save(d, accumulate_size, &c, true);
> +        if ( rc )
> +            return rc;
> +
> +        gdc->size = c.len;
> +        return 0;
> +    }
> +
> +    c.len = gdc->size;
> +    c.buffer = xmalloc_bytes(c.len);

What sizes are we looking at here? It may be better to use vmalloc()
right from the start. If not, I'd like to advocate for using
xmalloc_array() instead of xmalloc_bytes() - see the almost-XSA
commit cf38b4926e2b.

> +    if ( !c.buffer )
> +        return -ENOMEM;
> +
> +    rc = domain_save(d, save_data, &c, false);
> +
> +    gdc->size = c.cur;
> +    if ( !rc && copy_to_guest(gdc->buffer, c.buffer, gdc->size) )

As to my remark in patch 1 on the size field, applying to this size
field too - copy_to_user{,_hvm}() don't support a 64-bit value (on
y86 at least).

> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -38,7 +38,7 @@
>  #include "hvm/save.h"
>  #include "memory.h"
>  
> -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000012
> +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000013

I don't see you making any change making the interface backwards
incompatible, hence no need for the bump.

> @@ -1129,6 +1129,44 @@ struct xen_domctl_vuart_op {
>                                   */
>  };
>  
> +/*
> + * Get/Set domain PV context. The same struct xen_domctl_domaincontext
> + * is used for both commands but with slightly different field semantics
> + * as follows:
> + *
> + * XEN_DOMCTL_getdomaincontext
> + * ---------------------------
> + *
> + * buffer (IN):   The buffer into which the context data should be
> + *                copied, or NULL to query the buffer size that should
> + *                be allocated.
> + * size (IN/OUT): If 'buffer' is NULL then the value passed in must be
> + *                zero, and the value passed out will be the size of the
> + *                buffer to allocate.
> + *                If 'buffer' is non-NULL then the value passed in must
> + *                be the size of the buffer into which data may be copied.

This leaves open whether the size also gets updated in this latter
case.

> + */
> +struct xen_domctl_getdomaincontext {
> +    uint64_t size;

If this is to remain 64-bits (with too large values suitably taken
care of for all cases - see above), uint64_aligned_t please for
consistency, if nothing else.

Jan



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.