[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


 


Rackspace

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