[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v1 2/5] xen/xsplice: Hypervisor implementation of XEN_XSPLICE_op
>>> On 16.09.15 at 23:01, <konrad.wilk@xxxxxxxxxx> wrote: > --- /dev/null > +++ b/xen/common/xsplice.c > @@ -0,0 +1,442 @@ > +/* > + * xSplice - Copyright Oracle Corp. Inc 2015. > + * > + * Author: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> > + */ > + > +#include <xen/smp.h> > +#include <xen/keyhandler.h> > +#include <xen/spinlock.h> > +#include <xen/mm.h> > +#include <xen/list.h> > +#include <xen/guest_access.h> > +#include <xen/stdbool.h> No. This header should only be used in a very limited set up cases (namely source code shared with the tools). Looks like we accumulated a few other violations. > +struct payload { > + char *id; /* Name of it. Past this structure. */ > + ssize_t id_len; /* Length of the name. */ > + > + uint8_t *raw; /* Pointer to Elf file. Past 'id'*/ > + ssize_t raw_len; /* Size of 'raw'. */ > + > + int32_t status; /* XSPLICE_STATUS_* or Exx type value. */ > + int32_t old_status; /* XSPLICE_STATUS_* or Exx type value. */ > + > + struct spinlock cmd_lock; /* Lock against the action. */ > + uint32_t cmd; /* Action request. XSPLICE_ACTION_* */ > + > + /* Boring things below: */ > + struct list_head list; /* Linked to 'payload_list'. */ > + ssize_t len; /* This structure + raw_len + id_len + 1. */ > + > + struct tasklet tasklet; char name[]; here would avoid some casting further down. > +static const char *status2str(int64_t status) > +{ > +#define STATUS(x) [XSPLICE_STATUS_##x] = #x > + static const char *const names[] = { > + STATUS(LOADED), > + STATUS(PROGRESS), > + STATUS(CHECKED), > + STATUS(APPLIED), > + STATUS(REVERTED), > + }; This array will grow unreasonably once we gain a few more XSPLICE_STATUS_* values (which are bits masks, not enum like values). > +int find_payload(xen_xsplice_id_t *id, bool_t need_lock, struct payload **f) static? > +{ > + struct payload *data; > + XEN_GUEST_HANDLE_PARAM(char) str; > + char name[XEN_XSPLICE_ID_SIZE]; /* 128 bytes on stack. Perhaps kzalloc? > */ I don't think 128 bytes are a significant problem, unless this could be run in the context of an interrupt. > +static int xsplice_upload(xen_sysctl_xsplice_upload_t *upload) > +{ > + struct payload *data = NULL; > + int rc; > + ssize_t len; > + > + rc = verify_payload(upload); > + if ( rc ) > + return rc; > + > + rc = find_payload(&upload->id, true, &data); > + if ( rc == 0 /* Found. */ ) > + return -EEXIST; > + > + if ( rc != -ENOENT ) > + return rc; > + > + /* > + * Compute the size of the structures which need to be verified. > + * The 1 is for the extra \0 in case name does not have it. > + */ > + len = sizeof(*data) + upload->id.size + 1 + upload->size; > + data = alloc_xenheap_pages(get_order_from_bytes(len), 0); > + if ( !data ) > + return -ENOMEM; > + > + memset(data, 0, len); > + data->len = len; > + > + /* At the end of structure we put the name. */ > + data->id = (char *)data + sizeof(*data); > + data->id_len = upload->id.size; > + /* And after the name + \0 we stick the raw ELF data. */ > + data->raw = (uint8_t *)data + sizeof(*data) + data->id_len + 1; Please use data->id here to shorten the expression. > +static int xsplice_list(xen_sysctl_xsplice_list_t *list) > +{ > + xen_xsplice_status_t status; > + struct payload *data; > + unsigned int idx = 0, i = 0; > + int rc = 0; > + unsigned int ver = payload_version; Is it correct to latch this before taking the lock? > + // TODO: Increase to a 64 or other value. Leave 4 for debug. > + if ( list->nr > 4 ) > + return -E2BIG; Command line driven? > + if ( list->_pad != 0 ) > + return -EINVAL; > + > + if ( guest_handle_is_null(list->status) || > + guest_handle_is_null(list->id) || > + guest_handle_is_null(list->len) ) > + return -EINVAL; Are these really useful? > + if ( !guest_handle_okay(list->status, sizeof(status) * list->nr) || > + !guest_handle_okay(list->id, XEN_XSPLICE_ID_SIZE * list->nr) || > + !guest_handle_okay(list->len, sizeof(uint32_t) * list->nr) ) > + return -EINVAL; > + > + spin_lock(&payload_list_lock); > + if ( list->idx > payload_cnt ) > + { > + spin_unlock(&payload_list_lock); > + return -EINVAL; > + } > + > + status._pad = 0; /* No stack leaking. */ > + list_for_each_entry( data, &payload_list, list ) > + { > + uint32_t len; > + > + if ( list->idx > i++ ) > + continue; > + > + status.status = data->status; > + len = data->id_len; > + > + /* N.B. 'idx' != 'i'. */ > + if ( copy_to_guest_offset(list->id, idx * XEN_XSPLICE_ID_SIZE, > + data->id, len) || > + copy_to_guest_offset(list->len, idx, &len, 1) || > + copy_to_guest_offset(list->status, idx, &status, 1) ) > + { > + rc = -EFAULT; > + break; > + } > + idx ++; > + if ( hypercall_preempt_check() || (idx + 1 > list->nr) ) > + { > + break; > + } Pointless braces. (I won't make specific note of the many other coding style issues.) > +static int xsplice_action(xen_sysctl_xsplice_action_t *action) > +{ > + struct payload *data; > + int rc; > + > + if ( action->_pad != 0 ) > + return -EINVAL; > + > + rc = verify_id(&action->id); > + if ( rc ) > + return rc; > + > + spin_lock(&payload_list_lock); > + rc = find_payload(&action->id, false /* we are holding the lock. */, > &data); > + if ( rc ) > + goto out; > + > + if ( action->cmd != XSPLICE_ACTION_UNLOAD ) > + spin_lock(&data->cmd_lock); Wouldn't it be better to drop the lock in the specific case below, after having done the ->status checks? > + switch ( action->cmd ) > + { > + case XSPLICE_ACTION_CHECK: > + if ( ( data->status == XSPLICE_STATUS_LOADED ) ) > + { > + data->old_status = data->status; > + data->status = XSPLICE_STATUS_PROGRESS; > + data->cmd = action->cmd; > + tasklet_schedule(&data->tasklet); > + rc = 0; > + } else if ( data->status == XSPLICE_STATUS_CHECKED ) > + { > + rc = 0; > + } > + break; > + case XSPLICE_ACTION_UNLOAD: > + if ( ( data->status == XSPLICE_STATUS_REVERTED ) || > + ( data->status == XSPLICE_STATUS_LOADED ) || > + ( data->status == XSPLICE_STATUS_CHECKED ) ) > + { > + __free_payload(data); > + /* No touching 'data' from here on! */ > + rc = 0; > + } > + break; > + case XSPLICE_ACTION_REVERT: > + if ( data->status == XSPLICE_STATUS_APPLIED ) > + { > + data->old_status = data->status; > + data->status = XSPLICE_STATUS_PROGRESS; > + data->cmd = action->cmd; > + rc = 0; > + /* TODO: Tasklet is not good for this. We need a different > vehicle. */ > + tasklet_schedule(&data->tasklet); > + } > + break; > + case XSPLICE_ACTION_APPLY: > + if ( ( data->status == XSPLICE_STATUS_CHECKED ) || > + ( data->status == XSPLICE_STATUS_REVERTED )) > + { > + data->old_status = data->status; > + data->status = XSPLICE_STATUS_PROGRESS; > + data->cmd = action->cmd; > + rc = 0; > + /* TODO: Tasklet is not good for this. We need a different > vehicle. */ > + tasklet_schedule(&data->tasklet); > + } > + break; Looking at all of these ->status checks - why do XSPLICE_STATUS_* need to be bit masks rather then enum like values? > + default: > + rc = -ENOSYS; EOPNOTSUPP or EINVAL or ..., but not ENOSYS. > +int xsplice_control(xen_sysctl_xsplice_op_t *xsplice) > +{ > + int rc; > + > + switch ( xsplice->cmd ) > + { > + case XEN_SYSCTL_XSPLICE_UPLOAD: > + rc = xsplice_upload(&xsplice->u.upload); > + break; > + case XEN_SYSCTL_XSPLICE_GET: > + rc = xsplice_get(&xsplice->u.get); > + break; > + case XEN_SYSCTL_XSPLICE_LIST: > + rc = xsplice_list(&xsplice->u.list); > + break; > + case XEN_SYSCTL_XSPLICE_ACTION: > + rc = xsplice_action(&xsplice->u.action); > + break; > + default: > + rc = -ENOSYS; Same here. Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |