--- xen-unstable.hg/tools/libxc/xc_acm.c | 94 ++++++++++++++- xen-unstable.hg/tools/python/xen/lowlevel/acm/acm.c | 2 xen-unstable.hg/tools/security/secpol_tool.c | 4 xen-unstable.hg/xen/common/acm_ops.c | 120 ++++++-------------- xen-unstable.hg/xen/include/public/acm_ops.h | 9 - xen-unstable.hg/xen/include/xen/hypercall.h | 2 6 files changed, 126 insertions(+), 105 deletions(-) Index: root/xen-unstable.hg/tools/libxc/xc_acm.c =================================================================== --- root.orig/xen-unstable.hg/tools/libxc/xc_acm.c +++ root/xen-unstable.hg/tools/libxc/xc_acm.c @@ -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; } Index: root/xen-unstable.hg/xen/include/xen/hypercall.h =================================================================== --- root.orig/xen-unstable.hg/xen/include/xen/hypercall.h +++ root/xen-unstable.hg/xen/include/xen/hypercall.h @@ -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( Index: root/xen-unstable.hg/xen/include/public/acm_ops.h =================================================================== --- root.orig/xen-unstable.hg/xen/include/public/acm_ops.h +++ root/xen-unstable.hg/xen/include/public/acm_ops.h @@ -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 */ Index: root/xen-unstable.hg/tools/security/secpol_tool.c =================================================================== --- root.orig/xen-unstable.hg/tools/security/secpol_tool.c +++ root/xen-unstable.hg/tools/security/secpol_tool.c @@ -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)); Index: root/xen-unstable.hg/tools/python/xen/lowlevel/acm/acm.c =================================================================== --- root.orig/xen-unstable.hg/tools/python/xen/lowlevel/acm/acm.c +++ root/xen-unstable.hg/tools/python/xen/lowlevel/acm/acm.c @@ -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; Index: root/xen-unstable.hg/xen/common/acm_ops.c =================================================================== --- root.orig/xen-unstable.hg/xen/common/acm_ops.c +++ root/xen-unstable.hg/xen/common/acm_ops.c @@ -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; + struct xen_acmctl curop, *op = &curop; - if ( acm_authorize_acm_ops(current->domain) ) + 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) + 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(getssid.id.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) + 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(getdecision.id1.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) + 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(getdecision.id2.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: