|
[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
> -----Original Message-----
> From: Jan Beulich <jbeulich@xxxxxxxx>
> Sent: 29 April 2020 15:51
> To: Paul Durrant <paul@xxxxxxx>
> Cc: xen-devel@xxxxxxxxxxxxxxxxxxxx; Paul Durrant <pdurrant@xxxxxxxxxx>;
> Daniel De Graaf
> <dgdegra@xxxxxxxxxxxxx>; Ian Jackson <ian.jackson@xxxxxxxxxxxxx>; Wei Liu
> <wl@xxxxxxx>; Andrew Cooper
> <andrew.cooper3@xxxxxxxxxx>; George Dunlap <george.dunlap@xxxxxxxxxx>; Julien
> Grall <julien@xxxxxxx>;
> Stefano Stabellini <sstabellini@xxxxxxxxxx>
> Subject: 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.
>
Ok.
> > + 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.
Could be quite big so that seems reasonable.
> 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).
Ok.
>
> > --- 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.
>
Ok.
> > @@ -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.
I'll clarify.
>
> > + */
> > +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.
I've changed to uint32_t.
Paul
>
> Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |