[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v1 2/5] xen/xsplice: Hypervisor implementation of XEN_XSPLICE_op
The implementation does not actually do any patching. It just adds the framework for doing the hypercalls, keeping track of ELF payloads, and the basic operations: - query which payloads exist, - query for specific payloads, - check*1, apply*1, and unload payloads. *1: Which of course in this patch are nops. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> --- xen/common/Makefile | 1 + xen/common/keyhandler.c | 8 +- xen/common/sysctl.c | 6 + xen/common/xsplice.c | 442 ++++++++++++++++++++++++++++++++++++ xen/include/public/sysctl.h | 156 +++++++++++++ xen/include/xen/xsplice.h | 9 + xen/xsm/flask/hooks.c | 3 + xen/xsm/flask/policy/access_vectors | 2 + 8 files changed, 626 insertions(+), 1 deletion(-) create mode 100644 xen/common/xsplice.c create mode 100644 xen/include/xen/xsplice.h diff --git a/xen/common/Makefile b/xen/common/Makefile index 1726fac..7d53234 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -55,6 +55,7 @@ obj-y += vmap.o obj-y += vsprintf.o obj-y += wait.o obj-y += xmalloc_tlsf.o +obj-y += xsplice.o obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c index 5d21e48..1d4574a 100644 --- a/xen/common/keyhandler.c +++ b/xen/common/keyhandler.c @@ -18,6 +18,7 @@ #include <xen/mm.h> #include <xen/watchdog.h> #include <xen/init.h> +#include <xen/xsplice.h> #include <asm/debugger.h> #include <asm/div64.h> @@ -455,6 +456,11 @@ static struct keyhandler spinlock_reset_keyhandler = { .desc = "reset lock profile info" }; #endif +static struct keyhandler xsplice_printall_keyhandler = { + .diagnostic = 1, + .u.fn = xsplice_printall, + .desc = "print splicing information" +}; static void run_all_nonirq_keyhandlers(unsigned long unused) { @@ -567,7 +573,7 @@ void __init initialize_keytable(void) register_keyhandler('l', &spinlock_printall_keyhandler); register_keyhandler('L', &spinlock_reset_keyhandler); #endif - + register_keyhandler('x', &xsplice_printall_keyhandler); } /* diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c index 85e853f..517d684 100644 --- a/xen/common/sysctl.c +++ b/xen/common/sysctl.c @@ -28,6 +28,7 @@ #include <xsm/xsm.h> #include <xen/pmstat.h> #include <xen/gcov.h> +#include <xen/xsplice.h> long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl) { @@ -460,6 +461,11 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl) ret = tmem_control(&op->u.tmem_op); break; + case XEN_SYSCTL_xsplice_op: + ret = xsplice_control(&op->u.xsplice); + copyback = 1; + break; + default: ret = arch_do_sysctl(op, u_sysctl); copyback = 0; diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c new file mode 100644 index 0000000..d330efe --- /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> +#include <xen/sched.h> +#include <xen/lib.h> +#include <xen/xsplice.h> +#include <public/sysctl.h> + +#include <asm/event.h> + +static DEFINE_SPINLOCK(payload_list_lock); +static LIST_HEAD(payload_list); + +static unsigned int payload_cnt; +static unsigned int payload_version = 1; + +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; +}; + +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), + }; +#undef STATUS + + if (status >= ARRAY_SIZE(names)) + return "unknown"; + + if (status < 0) + return "-EXX"; + + if (!names[status]) + return "unknown"; + + return names[status]; +} + +void xsplice_printall(unsigned char key) +{ + struct payload *data; + + spin_lock(&payload_list_lock); + + list_for_each_entry ( data, &payload_list, list ) + { + printk(" id=%s status=%s(%d,old=%d): \n", data->id, + status2str(data->status), data->status, data->old_status); + } + spin_unlock(&payload_list_lock); +} + +static int verify_id(xen_xsplice_id_t *id) +{ + if ( id->size == 0 || id->size > XEN_XSPLICE_ID_SIZE ) + return -EINVAL; + + if ( id->_pad != 0 ) + return -EINVAL; + + if ( !guest_handle_okay(id->name, id->size) ) + return -EINVAL; + + return 0; +} + +int find_payload(xen_xsplice_id_t *id, bool_t need_lock, struct payload **f) +{ + struct payload *data; + XEN_GUEST_HANDLE_PARAM(char) str; + char name[XEN_XSPLICE_ID_SIZE]; /* 128 bytes on stack. Perhaps kzalloc? */ + int rc = -EINVAL; + + rc = verify_id(id); + if ( rc ) + return rc; + + str = guest_handle_cast(id->name, char); + if ( copy_from_guest(name, str, id->size) ) + return -EFAULT; + + if ( need_lock ) + spin_lock(&payload_list_lock); + + rc = -ENOENT; + list_for_each_entry ( data, &payload_list, list ) + { + if ( !strncmp(data->id, name, data->id_len) ) + { + *f = data; + rc = 0; + break; + } + } + + if ( need_lock ) + spin_unlock(&payload_list_lock); + + return rc; +} + + +static int verify_payload(xen_sysctl_xsplice_upload_t *upload) +{ + if ( verify_id(&upload->id) ) + return -EINVAL; + + if ( upload->size == 0 ) + return -EINVAL; + + if ( !guest_handle_okay(upload->payload, upload->size) ) + return -EFAULT; + + return 0; +} + +/* + * We MUST be holding the spinlock. + */ +static void __free_payload(struct payload *data) +{ + list_del(&data->list); + payload_cnt --; + payload_version ++; + tasklet_kill(&data->tasklet); + free_xenheap_pages(data, get_order_from_bytes(data->len)); +} + +static void xsplice_tasklet(unsigned long _data) +{ + struct payload *data = (struct payload *)_data; + + spin_lock(&data->cmd_lock); + switch ( data->cmd ) { + case XSPLICE_ACTION_CHECK: + /* TODO: Do the operation here. */ + data->status = XSPLICE_STATUS_CHECKED; + break; + case XSPLICE_ACTION_APPLY: + /* TODO: Well, do the work :-) */ + data->status = XSPLICE_STATUS_APPLIED; + break; + case XSPLICE_ACTION_REVERT: + /* TODO: Well, do the work :-) */ + data->status = XSPLICE_STATUS_REVERTED; + break; + default: + data->status = -EINVAL; + } + spin_unlock(&data->cmd_lock); +} + +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; + data->raw_len = upload->size; + + rc = -EFAULT; + if ( copy_from_guest(data->raw, upload->payload, upload->size) ) + goto err_out; + + if ( copy_from_guest(data->id, upload->id.name, upload->id.size) ) + goto err_out; + + data->status = XSPLICE_STATUS_LOADED; + INIT_LIST_HEAD(&data->list); + spin_lock_init(&data->cmd_lock); + data->cmd = 0; + tasklet_init(&data->tasklet, xsplice_tasklet, (unsigned long)data); + + spin_lock(&payload_list_lock); + list_add_tail(&data->list, &payload_list); + payload_cnt ++; + payload_version ++; + spin_unlock(&payload_list_lock); + + return 0; + + err_out: + free_xenheap_pages(data, get_order_from_bytes(len)); + return rc; +} + +static int xsplice_get(xen_sysctl_xsplice_summary_t *summary) +{ + struct payload *data; + int rc; + + if ( summary->status.status ) + return -EINVAL; + + if ( summary->status._pad != 0 ) + return -EINVAL; + + rc = verify_id(&summary->id ); + if ( rc ) + return rc; + + rc = find_payload(&summary->id, true, &data); + if ( rc ) + return rc; + + summary->status.status = data->status; + + return 0; +} + +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; + + // TODO: Increase to a 64 or other value. Leave 4 for debug. + if ( list->nr > 4 ) + return -E2BIG; + + 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; + + 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; + } + } + list->nr = payload_cnt - i; /* Remaining amount. */ + spin_unlock(&payload_list_lock); + list->version = ver; + + /* And how many we have processed. */ + return rc ? rc : idx; +} + +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); + + 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; + default: + rc = -ENOSYS; + break; + } + + if ( action->cmd != XSPLICE_ACTION_UNLOAD ) + spin_unlock(&data->cmd_lock); + out: + spin_unlock(&payload_list_lock); + + return rc; +} + +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; + break; + } + + return rc; +} diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 0cacacc..08952de 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -764,6 +764,160 @@ struct xen_sysctl_tmem_op { typedef struct xen_sysctl_tmem_op xen_sysctl_tmem_op_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tmem_op_t); +/* + * XEN_SYSCTL_XSPLICE_op + * + * Refer to the docs/misc/xsplice.markdown for the design details + * of this hypercall. + */ + +/* + * Structure describing an ELF payload. Uniquely identifies the + * payload. Should be human readable. + * Recommended length is XEN_XSPLICE_ID_SIZE. + */ +#define XEN_XSPLICE_ID_SIZE 128 +struct xen_xsplice_id { + XEN_GUEST_HANDLE_64(char) name; /* IN, pointer to name. */ + uint32_t size; /* IN, size of name. May be upto + XEN_XSPLICE_ID_SIZE. */ + uint32_t _pad; +}; +typedef struct xen_xsplice_id xen_xsplice_id_t; +DEFINE_XEN_GUEST_HANDLE(xen_xsplice_id_t); + +/* + * Upload a payload to the hypervisor. The payload is verified + * against basic checks and if there are any issues the proper return code + * will be returned. The payload is not applied at this time - that is + * controlled by XEN_SYSCTL_XSPLICE_ACTION. + * + * The return value is zero if the payload was succesfully uploaded. + * Otherwise an EXX return value is provided. Duplicate `id` are not supported. + * The payload at this point is verified against the basic checks. + * + * The `payload` is the ELF payload as mentioned in the `Payload format` + * section in the xSplice design document. + */ +#define XEN_SYSCTL_XSPLICE_UPLOAD 0 +struct xen_sysctl_xsplice_upload { + xen_xsplice_id_t id; /* IN, name of the patch. */ + uint64_t size; /* IN, size of the ELF file. */ + XEN_GUEST_HANDLE_64(uint8) payload; /* IN, the ELF file. */ +}; +typedef struct xen_sysctl_xsplice_upload xen_sysctl_xsplice_upload_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_xsplice_upload_t); + +/* + * Retrieve an status of an specific payload. + * + * Upon completion the `struct xen_xsplice_status` is updated. + * + * The return value is zero on success and EXX on failure. This operation + * is synchronous and does not require preemption. + */ +#define XEN_SYSCTL_XSPLICE_GET 1 + +struct xen_xsplice_status { +#define XSPLICE_STATUS_LOADED 0x01 +#define XSPLICE_STATUS_PROGRESS 0x02 +#define XSPLICE_STATUS_CHECKED 0x04 +#define XSPLICE_STATUS_APPLIED 0x08 +#define XSPLICE_STATUS_REVERTED 0x10 + /* Any negative value is an error. The error would be in -EXX format. */ + int32_t status; /* OUT, On IN has to be zero. */ + uint32_t _pad; /* IN, Must be zero. */ +}; +typedef struct xen_xsplice_status xen_xsplice_status_t; +DEFINE_XEN_GUEST_HANDLE(xen_xsplice_status_t); + +struct xen_sysctl_xsplice_summary { + xen_xsplice_id_t id; /* IN, name of the payload. */ + xen_xsplice_status_t status; /* IN/OUT, status of it. */ +}; +typedef struct xen_sysctl_xsplice_summary xen_sysctl_xsplice_summary_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_xsplice_summary_t); + +/* + * Retrieve an array of abbreviated status and names of payloads that are + * loaded in the hypervisor. + * + * If the hypercall returns an positive number, it is the number (up to `nr`) + * of the payloads returned, along with `nr` updated with the number of remaining + * payloads, `version` updated (it may be the same across hypercalls. If it + * varies the data is stale and further calls could fail). The `status`, + * `id`, and `len`' are updated at their designed index value (`idx`) with + * the returned value of data. + * + * If the hypercall returns E2BIG the `count` is too big and should be + * lowered. + * + * This operation can be preempted by the hypercall returning EAGAIN. + * Retry. + * + * Note that due to the asynchronous nature of hypercalls the domain might have + * added or removed the number of payloads making this information stale. It is + * the responsibility of the toolstack to use the `version` field to check + * between each invocation. if the version differs it should discard the stale + * data and start from scratch. It is OK for the toolstack to use the new + * `version` field. + */ +#define XEN_SYSCTL_XSPLICE_LIST 2 +struct xen_sysctl_xsplice_list { + uint32_t version; /* IN/OUT: Initially *MUST* be zero. + On subsequent calls reuse value. + If varies between calls, we are + * getting stale data. */ + uint32_t idx; /* IN/OUT: Index into array. */ + uint32_t nr; /* IN: How many status, id, and len + should populate. + OUT: How many payloads left. */ + uint32_t _pad; /* IN: Must be zero. */ + XEN_GUEST_HANDLE_64(xen_xsplice_status_t) status; /* OUT. Must have enough + space allocate for n of them. */ + XEN_GUEST_HANDLE_64(char) id; /* OUT: Array of ids. Each member + MUST XEN_XSPLICE_ID_SIZE in size. + Must have n of them. */ + XEN_GUEST_HANDLE_64(uint32) len; /* OUT: Array of lengths of ids. + Must have n of them. */ +}; +typedef struct xen_sysctl_xsplice_list xen_sysctl_xsplice_list_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_xsplice_list_t); + +/* + * Perform an operation on the payload structure referenced by the `id` field. + * The operation request is asynchronous and the status should be retrieved + * by using either XEN_SYSCTL_XSPLICE_GET or XEN_SYSCTL_XSPLICE_LIST hypercall. + * If the operation fails more details on the operation can be retrieved via + * XEN_SYSCTL_XSPLICE_INFO hypercall. + */ +#define XEN_SYSCTL_XSPLICE_ACTION 3 +struct xen_sysctl_xsplice_action { + xen_xsplice_id_t id; /* IN, name of the patch. */ +#define XSPLICE_ACTION_CHECK 1 +#define XSPLICE_ACTION_UNLOAD 2 +#define XSPLICE_ACTION_REVERT 3 +#define XSPLICE_ACTION_APPLY 4 + uint32_t cmd; /* IN: XSPLICE_ACTION_*. */ + uint32_t _pad; /* IN: Always zero. */ + uint64_aligned_t time; /* IN: Zero if no timeout. */ +}; +typedef struct xen_sysctl_xsplice_action xen_sysctl_xsplice_action_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_xsplice_action_t); + +struct xen_sysctl_xsplice_op { + uint32_t cmd; /* IN: XEN_SYSCTL_XSPLICE_* */ + uint32_t _pad; /* IN: Always zero. */ + union { + xen_sysctl_xsplice_upload_t upload; + xen_sysctl_xsplice_list_t list; + xen_sysctl_xsplice_summary_t get; + xen_sysctl_xsplice_action_t action; + } u; +}; +typedef struct xen_sysctl_xsplice_op xen_sysctl_xsplice_op_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_xsplice_op_t); + struct xen_sysctl { uint32_t cmd; #define XEN_SYSCTL_readconsole 1 @@ -789,6 +943,7 @@ struct xen_sysctl { #define XEN_SYSCTL_pcitopoinfo 22 #define XEN_SYSCTL_psr_cat_op 23 #define XEN_SYSCTL_tmem_op 24 +#define XEN_SYSCTL_xsplice_op 25 uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ union { struct xen_sysctl_readconsole readconsole; @@ -814,6 +969,7 @@ struct xen_sysctl { struct xen_sysctl_psr_cmt_op psr_cmt_op; struct xen_sysctl_psr_cat_op psr_cat_op; struct xen_sysctl_tmem_op tmem_op; + struct xen_sysctl_xsplice_op xsplice; uint8_t pad[128]; } u; }; diff --git a/xen/include/xen/xsplice.h b/xen/include/xen/xsplice.h new file mode 100644 index 0000000..41e28da --- /dev/null +++ b/xen/include/xen/xsplice.h @@ -0,0 +1,9 @@ +#ifndef __XEN_XSPLICE_H__ +#define __XEN_XSPLICE_H__ + +struct xen_sysctl_xsplice_op; +int xsplice_control(struct xen_sysctl_xsplice_op *); + +extern void xsplice_printall(unsigned char key); + +#endif /* __XEN_XSPLICE_H__ */ diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 4180f3b..053f083 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -807,6 +807,9 @@ static int flask_sysctl(int cmd) case XEN_SYSCTL_tmem_op: return domain_has_xen(current->domain, XEN__TMEM_CONTROL); + case XEN_SYSCTL_xsplice_op: + return domain_has_xen(current->domain, XEN2__XSPLICE_OP); + default: printk("flask_sysctl: Unknown op %d\n", cmd); return -EPERM; diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors index effb59f..5f08d05 100644 --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -93,6 +93,8 @@ class xen2 pmu_ctrl # PMU use (domains, including unprivileged ones, will be using this operation) pmu_use +# XEN_SYSCTL_xsplice_op + xsplice_op } # Classes domain and domain2 consist of operations that a domain performs on -- 2.1.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |