[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |