[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [ACM] Simpler interface to hypercalls



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1179998335 -3600
# Node ID 96915ca8d5f239062f889970279c5d90296a8a96
# Parent  46095d5a59a9d268c247b2b1bf747024759b1f8e
[ACM] Simpler interface to hypercalls

Implement a simpler interface for the hypercalls to ACM. I put the
parameters to all hypercalls into a union. On top of this I have
implemented a shim layer for enabling ACM hypercalls on PPC.

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
---
 tools/libxc/xc_acm.c                |   94 +++++++++++++++++++++++---
 tools/python/xen/lowlevel/acm/acm.c |    2 
 tools/security/secpol_tool.c        |    4 -
 xen/common/acm_ops.c                |  128 ++++++++++++------------------------
 xen/include/public/acm_ops.h        |    9 --
 xen/include/xen/hypercall.h         |    2 
 6 files changed, 130 insertions(+), 109 deletions(-)

diff -r 46095d5a59a9 -r 96915ca8d5f2 tools/libxc/xc_acm.c
--- a/tools/libxc/xc_acm.c      Thu May 24 10:14:05 2007 +0100
+++ b/tools/libxc/xc_acm.c      Thu May 24 10:18:55 2007 +0100
@@ -16,20 +16,96 @@
 
 int xc_acm_op(int xc_handle, int cmd, void *arg, unsigned long arg_size)
 {
-    int ret = -1;
+    int ret;
     DECLARE_HYPERCALL;
+    struct xen_acmctl acmctl;
+
+    switch (cmd) {
+        case ACMOP_setpolicy: {
+            struct acm_setpolicy *setpolicy = (struct acm_setpolicy *)arg;
+            memcpy(&acmctl.u.setpolicy,
+                   setpolicy,
+                   sizeof(struct acm_setpolicy));
+        }
+        break;
+
+        case ACMOP_getpolicy: {
+            struct acm_getpolicy *getpolicy = (struct acm_getpolicy *)arg;
+            memcpy(&acmctl.u.getpolicy,
+                   getpolicy,
+                   sizeof(struct acm_getpolicy));
+        }
+        break;
+
+        case ACMOP_dumpstats: {
+            struct acm_dumpstats *dumpstats = (struct acm_dumpstats *)arg;
+            memcpy(&acmctl.u.dumpstats,
+                   dumpstats,
+                   sizeof(struct acm_dumpstats));
+        }
+        break;
+
+        case ACMOP_getssid: {
+            struct acm_getssid *getssid = (struct acm_getssid *)arg;
+            memcpy(&acmctl.u.getssid,
+                   getssid,
+                   sizeof(struct acm_getssid));
+        }
+        break;
+
+        case ACMOP_getdecision: {
+            struct acm_getdecision *getdecision = (struct acm_getdecision 
*)arg;
+            memcpy(&acmctl.u.getdecision,
+                   getdecision,
+                   sizeof(struct acm_getdecision));
+        }
+        break;
+
+        case ACMOP_chgpolicy: {
+            struct acm_change_policy *change_policy = (struct 
acm_change_policy *)arg;
+            memcpy(&acmctl.u.change_policy,
+                   change_policy,
+                   sizeof(struct acm_change_policy));
+        }
+        break;
+
+        case ACMOP_relabeldoms: {
+            struct acm_relabel_doms *relabel_doms = (struct acm_relabel_doms 
*)arg;
+            memcpy(&acmctl.u.relabel_doms,
+                   relabel_doms,
+                   sizeof(struct acm_relabel_doms));
+        }
+        break;
+    }
+
+    acmctl.cmd = cmd;
+    acmctl.interface_version = ACM_INTERFACE_VERSION;
 
     hypercall.op = __HYPERVISOR_acm_op;
-    hypercall.arg[0] = cmd;
-    hypercall.arg[1] = (unsigned long) arg;
+    hypercall.arg[0] = (unsigned long)&acmctl;
+    if ( lock_pages(&acmctl, sizeof(acmctl)) != 0)
+    {
+        PERROR("Could not lock memory for Xen hypercall");
+        return -EFAULT;
+    }
+    if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0)
+    {
+        if ( errno == EACCES )
+            DPRINTF("acmctl operation failed -- need to"
+                    " rebuild the user-space tool set?\n");
+    }
+    unlock_pages(&acmctl, sizeof(acmctl));
 
-    if (lock_pages(arg, arg_size) != 0) {
-        PERROR("xc_acm_op: arg lock failed");
-        goto out;
+    switch (cmd) {
+        case ACMOP_getdecision: {
+            struct acm_getdecision *getdecision = (struct acm_getdecision 
*)arg;
+            memcpy(getdecision,
+                   &acmctl.u.getdecision,
+                   sizeof(struct acm_getdecision));
+            break;
+        }
     }
-    ret = do_xen_hypercall(xc_handle, &hypercall);
-    unlock_pages(arg, arg_size);
- out:
+
     return ret;
 }
 
diff -r 46095d5a59a9 -r 96915ca8d5f2 tools/python/xen/lowlevel/acm/acm.c
--- a/tools/python/xen/lowlevel/acm/acm.c       Thu May 24 10:14:05 2007 +0100
+++ b/tools/python/xen/lowlevel/acm/acm.c       Thu May 24 10:18:55 2007 +0100
@@ -53,7 +53,6 @@ void * __getssid(int domid, uint32_t *bu
         goto out2;
     }
     memset(buf, 0, SSID_BUFFER_SIZE);
-    getssid.interface_version = ACM_INTERFACE_VERSION;
     set_xen_guest_handle(getssid.ssidbuf, buf);
     getssid.ssidbuf_size = SSID_BUFFER_SIZE;
     getssid.get_ssid_by = ACM_GETBY_domainid;
@@ -163,7 +162,6 @@ static PyObject *getdecision(PyObject * 
     (strcmp(arg2_name, "domid") && strcmp(arg2_name, "ssidref")))
         return NULL;
 
-    getdecision.interface_version = ACM_INTERFACE_VERSION;
     getdecision.hook = ACMHOOK_sharing;
     if (!strcmp(arg1_name, "domid")) {
         getdecision.get_decision_by1 = ACM_GETBY_domainid;
diff -r 46095d5a59a9 -r 96915ca8d5f2 tools/security/secpol_tool.c
--- a/tools/security/secpol_tool.c      Thu May 24 10:14:05 2007 +0100
+++ b/tools/security/secpol_tool.c      Thu May 24 10:18:55 2007 +0100
@@ -243,7 +243,6 @@ int acm_get_ssidref(int xc_handle, int d
     struct acm_getssid getssid;
     char buf[4096];
     struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)buf;
-    getssid.interface_version = ACM_INTERFACE_VERSION;
     set_xen_guest_handle(getssid.ssidbuf, buf);
     getssid.ssidbuf_size = sizeof(buf);
     getssid.get_ssid_by = ACM_GETBY_domainid;
@@ -268,7 +267,6 @@ int acm_domain_getpolicy(int xc_handle)
     uint16_t chwall_ref, ste_ref;
 
     memset(pull_buffer, 0x00, sizeof(pull_buffer));
-    getpolicy.interface_version = ACM_INTERFACE_VERSION;
     set_xen_guest_handle(getpolicy.pullcache, pull_buffer);
     getpolicy.pullcache_size = sizeof(pull_buffer);
     ret = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy));
@@ -323,7 +321,6 @@ int acm_domain_loadpolicy(int xc_handle,
         struct acm_setpolicy setpolicy;
         /* dump it and then push it down into xen/acm */
         acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref);
-        setpolicy.interface_version = ACM_INTERFACE_VERSION;
         set_xen_guest_handle(setpolicy.pushcache, buffer);
         setpolicy.pushcache_size = len;
         ret = xc_acm_op(xc_handle, ACMOP_setpolicy, &setpolicy, 
sizeof(setpolicy));
@@ -372,7 +369,6 @@ int acm_domain_dumpstats(int xc_handle)
     struct acm_stats_buffer *stats;
 
     memset(stats_buffer, 0x00, sizeof(stats_buffer));
-    dumpstats.interface_version = ACM_INTERFACE_VERSION;
     set_xen_guest_handle(dumpstats.pullcache, stats_buffer);
     dumpstats.pullcache_size = sizeof(stats_buffer);
     ret = xc_acm_op(xc_handle, ACMOP_dumpstats, &dumpstats, sizeof(dumpstats));
diff -r 46095d5a59a9 -r 96915ca8d5f2 xen/common/acm_ops.c
--- a/xen/common/acm_ops.c      Thu May 24 10:14:05 2007 +0100
+++ b/xen/common/acm_ops.c      Thu May 24 10:18:55 2007 +0100
@@ -38,69 +38,54 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
 
 int acm_authorize_acm_ops(struct domain *d)
 {
+    /* currently, policy management functions are restricted to privileged 
domains */
     return (IS_PRIV(d) ? 0 : -EPERM);
 }
 
-long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg)
+
+long do_acm_op(XEN_GUEST_HANDLE(xen_acmctl_t) u_acmctl)
 {
     long rc = -EFAULT;
-
-    if ( acm_authorize_acm_ops(current->domain) )
+    struct xen_acmctl curop, *op = &curop;
+
+    if (acm_authorize_acm_ops(current->domain))
         return -EPERM;
 
-    switch ( cmd )
+    if ( copy_from_guest(op, u_acmctl, 1) )
+        return -EFAULT;
+
+    if (op->interface_version != ACM_INTERFACE_VERSION)
+        return -EACCES;
+
+    switch ( op->cmd )
     {
 
     case ACMOP_setpolicy: {
-        struct acm_setpolicy setpolicy;
-        if (copy_from_guest(&setpolicy, arg, 1) != 0)
-            return -EFAULT;
-        if (setpolicy.interface_version != ACM_INTERFACE_VERSION)
-            return -EACCES;
-
-        rc = acm_set_policy(setpolicy.pushcache,
-                            setpolicy.pushcache_size);
+        rc = acm_set_policy(op->u.setpolicy.pushcache,
+                            op->u.setpolicy.pushcache_size);
         break;
     }
 
     case ACMOP_getpolicy: {
-        struct acm_getpolicy getpolicy;
-        if (copy_from_guest(&getpolicy, arg, 1) != 0)
-            return -EFAULT;
-        if (getpolicy.interface_version != ACM_INTERFACE_VERSION)
-            return -EACCES;
-
-        rc = acm_get_policy(getpolicy.pullcache,
-                            getpolicy.pullcache_size);
+        rc = acm_get_policy(op->u.getpolicy.pullcache,
+                            op->u.getpolicy.pullcache_size);
         break;
     }
 
     case ACMOP_dumpstats: {
-        struct acm_dumpstats dumpstats;
-        if (copy_from_guest(&dumpstats, arg, 1) != 0)
-            return -EFAULT;
-        if (dumpstats.interface_version != ACM_INTERFACE_VERSION)
-            return -EACCES;
-
-        rc = acm_dump_statistics(dumpstats.pullcache,
-                                 dumpstats.pullcache_size);
+        rc = acm_dump_statistics(op->u.dumpstats.pullcache,
+                                 op->u.dumpstats.pullcache_size);
         break;
     }
 
     case ACMOP_getssid: {
-        struct acm_getssid getssid;
         ssidref_t ssidref;
 
-        if (copy_from_guest(&getssid, arg, 1) != 0)
-            return -EFAULT;
-        if (getssid.interface_version != ACM_INTERFACE_VERSION)
-            return -EACCES;
-
-        if (getssid.get_ssid_by == ACM_GETBY_ssidref)
-            ssidref = getssid.id.ssidref;
-        else if (getssid.get_ssid_by == ACM_GETBY_domainid)
-        {
-            struct domain *subj = rcu_lock_domain_by_id(getssid.id.domainid);
+        if (op->u.getssid.get_ssid_by == ACM_GETBY_ssidref)
+            ssidref = op->u.getssid.id.ssidref;
+        else if (op->u.getssid.get_ssid_by == ACM_GETBY_domainid)
+        {
+            struct domain *subj = 
rcu_lock_domain_by_id(op->u.getssid.id.domainid);
             if (!subj)
             {
                 rc = -ESRCH; /* domain not found */
@@ -120,24 +105,19 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
             rc = -ESRCH;
             break;
         }
-        rc = acm_get_ssid(ssidref, getssid.ssidbuf, getssid.ssidbuf_size);
+        rc = acm_get_ssid(ssidref, op->u.getssid.ssidbuf,
+                          op->u.getssid.ssidbuf_size);
         break;
     }
 
     case ACMOP_getdecision: {
-        struct acm_getdecision getdecision;
         ssidref_t ssidref1, ssidref2;
 
-        if (copy_from_guest(&getdecision, arg, 1) != 0)
-            return -EFAULT;
-        if (getdecision.interface_version != ACM_INTERFACE_VERSION)
-            return -EACCES;
-
-        if (getdecision.get_decision_by1 == ACM_GETBY_ssidref)
-            ssidref1 = getdecision.id1.ssidref;
-        else if (getdecision.get_decision_by1 == ACM_GETBY_domainid)
-        {
-            struct domain *subj = 
rcu_lock_domain_by_id(getdecision.id1.domainid);
+        if (op->u.getdecision.get_decision_by1 == ACM_GETBY_ssidref)
+            ssidref1 = op->u.getdecision.id1.ssidref;
+        else if (op->u.getdecision.get_decision_by1 == ACM_GETBY_domainid)
+        {
+            struct domain *subj = 
rcu_lock_domain_by_id(op->u.getdecision.id1.domainid);
             if (!subj)
             {
                 rc = -ESRCH; /* domain not found */
@@ -157,11 +137,11 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
             rc = -ESRCH;
             break;
         }
-        if (getdecision.get_decision_by2 == ACM_GETBY_ssidref)
-            ssidref2 = getdecision.id2.ssidref;
-        else if (getdecision.get_decision_by2 == ACM_GETBY_domainid)
-        {
-            struct domain *subj = 
rcu_lock_domain_by_id(getdecision.id2.domainid);
+        if (op->u.getdecision.get_decision_by2 == ACM_GETBY_ssidref)
+            ssidref2 = op->u.getdecision.id2.ssidref;
+        else if (op->u.getdecision.get_decision_by2 == ACM_GETBY_domainid)
+        {
+            struct domain *subj = 
rcu_lock_domain_by_id(op->u.getdecision.id2.domainid);
             if (!subj)
             {
                 rc = -ESRCH; /* domain not found */
@@ -181,55 +161,33 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
             rc = -ESRCH;
             break;
         }
-        rc = acm_get_decision(ssidref1, ssidref2, getdecision.hook);
+        rc = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook);
 
         if (rc == ACM_ACCESS_PERMITTED)
         {
-            getdecision.acm_decision = ACM_ACCESS_PERMITTED;
+            op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED;
             rc = 0;
         }
         else if  (rc == ACM_ACCESS_DENIED)
         {
-            getdecision.acm_decision = ACM_ACCESS_DENIED;
+            op->u.getdecision.acm_decision = ACM_ACCESS_DENIED;
             rc = 0;
         }
         else
             rc = -ESRCH;
 
-        if ( (rc == 0) && (copy_to_guest(arg, &getdecision, 1) != 0) )
+        if ( (rc == 0) && (copy_to_guest(u_acmctl, op, 1) != 0) )
             rc = -EFAULT;
         break;
     }
 
     case ACMOP_chgpolicy: {
-        struct acm_change_policy chgpolicy;
-
-        if (copy_from_guest(&chgpolicy, arg, 1) != 0)
-            return -EFAULT;
-        if (chgpolicy.interface_version != ACM_INTERFACE_VERSION)
-            return -EACCES;
-
-        rc = acm_change_policy(&chgpolicy);
-
-        if (rc == 0)
-            if (copy_to_guest(arg, &chgpolicy, 1) != 0)
-                rc = -EFAULT;
+        rc = acm_change_policy(&op->u.change_policy);
         break;
     }
 
     case ACMOP_relabeldoms: {
-        struct acm_relabel_doms relabeldoms;
-
-        if (copy_from_guest(&relabeldoms, arg, 1) != 0)
-            return -EFAULT;
-        if (relabeldoms.interface_version != ACM_INTERFACE_VERSION)
-            return -EACCES;
-
-        rc = acm_relabel_domains(&relabeldoms);
-
-        if (rc == 0)
-            if (copy_to_guest(arg, &relabeldoms, 1) != 0)
-                rc = -EFAULT;
+        rc = acm_relabel_domains(&op->u.relabel_doms);
         break;
     }
 
@@ -241,7 +199,7 @@ long do_acm_op(int cmd, XEN_GUEST_HANDLE
     return rc;
 }
 
-#endif /* defined(ACM_SECURITY) */
+#endif
 
 /*
  * Local variables:
diff -r 46095d5a59a9 -r 96915ca8d5f2 xen/include/public/acm_ops.h
--- a/xen/include/public/acm_ops.h      Thu May 24 10:14:05 2007 +0100
+++ b/xen/include/public/acm_ops.h      Thu May 24 10:18:55 2007 +0100
@@ -34,7 +34,7 @@
  * This makes sure that old versions of acm tools will stop working in a
  * well-defined way (rather than crashing the machine, for instance).
  */
-#define ACM_INTERFACE_VERSION   0xAAAA0009
+#define ACM_INTERFACE_VERSION   0xAAAA000A
 
 /************************************************************************/
 
@@ -49,7 +49,6 @@
 #define ACMOP_setpolicy         1
 struct acm_setpolicy {
     /* IN */
-    uint32_t interface_version;
     XEN_GUEST_HANDLE_64(void) pushcache;
     uint32_t pushcache_size;
 };
@@ -58,7 +57,6 @@ struct acm_setpolicy {
 #define ACMOP_getpolicy         2
 struct acm_getpolicy {
     /* IN */
-    uint32_t interface_version;
     XEN_GUEST_HANDLE_64(void) pullcache;
     uint32_t pullcache_size;
 };
@@ -67,7 +65,6 @@ struct acm_getpolicy {
 #define ACMOP_dumpstats         3
 struct acm_dumpstats {
     /* IN */
-    uint32_t interface_version;
     XEN_GUEST_HANDLE_64(void) pullcache;
     uint32_t pullcache_size;
 };
@@ -78,7 +75,6 @@ struct acm_dumpstats {
 #define ACM_GETBY_domainid 2
 struct acm_getssid {
     /* IN */
-    uint32_t interface_version;
     uint32_t get_ssid_by; /* ACM_GETBY_* */
     union {
         domaintype_t domainid;
@@ -91,7 +87,6 @@ struct acm_getssid {
 #define ACMOP_getdecision      5
 struct acm_getdecision {
     /* IN */
-    uint32_t interface_version;
     uint32_t get_decision_by1; /* ACM_GETBY_* */
     uint32_t get_decision_by2; /* ACM_GETBY_* */
     union {
@@ -111,7 +106,6 @@ struct acm_getdecision {
 #define ACMOP_chgpolicy        6
 struct acm_change_policy {
     /* IN */
-    uint32_t interface_version;
     XEN_GUEST_HANDLE_64(void) policy_pushcache;
     uint32_t policy_pushcache_size;
     XEN_GUEST_HANDLE_64(void) del_array;
@@ -127,7 +121,6 @@ struct acm_change_policy {
 #define ACMOP_relabeldoms       7
 struct acm_relabel_doms {
     /* IN */
-    uint32_t interface_version;
     XEN_GUEST_HANDLE_64(void) relabel_map;
     uint32_t relabel_map_size;
     /* OUT */
diff -r 46095d5a59a9 -r 96915ca8d5f2 xen/include/xen/hypercall.h
--- a/xen/include/xen/hypercall.h       Thu May 24 10:14:05 2007 +0100
+++ b/xen/include/xen/hypercall.h       Thu May 24 10:18:55 2007 +0100
@@ -98,7 +98,7 @@ do_vcpu_op(
 
 extern long
 do_acm_op(
-    int cmd, XEN_GUEST_HANDLE(void) arg);
+    XEN_GUEST_HANDLE(xen_acmctl_t) arg);
 
 extern long
 do_nmi_op(

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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