[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [ACM] Replace the union structure parameter of the ACM hypercalls
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 0f16f0871dc950fe85ece7e7a2e154383ae7c345 # Parent e999878433361d25bd0755163491fd401073ad55 [ACM] Replace the union structure parameter of the ACM hypercalls with command-specific request structures. It aligns the ACM hypercalls with the way parameters are passed in the event channel hypercalls. Advantages include backward-compatibility regarding old guests when new calls are added and clarity of the code. Signed-off by: Reiner Sailer <sailer@xxxxxxxxxx> --- tools/libxc/xc_acm.c | 33 +--- tools/libxc/xenctrl.h | 2 tools/python/xen/lowlevel/acm/acm.c | 54 +++--- tools/security/secpol_tool.c | 32 ++-- xen/common/acm_ops.c | 282 +++++++++++++++++------------------- xen/include/public/acm_ops.h | 55 +++---- xen/include/xen/hypercall.h | 2 7 files changed, 223 insertions(+), 237 deletions(-) diff -r e99987843336 -r 0f16f0871dc9 tools/libxc/xc_acm.c --- a/tools/libxc/xc_acm.c Sun May 21 18:57:42 2006 +0100 +++ b/tools/libxc/xc_acm.c Sun May 21 19:05:31 2006 +0100 @@ -1,13 +1,10 @@ /****************************************************************************** + * xc_acm.c * - * Copyright (C) 2005 IBM Corporation + * Copyright (C) 2005, 2006 IBM Corporation, R Sailer * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * - * Authors: - * Reiner Sailer <sailer@xxxxxxxxxxxxxx> - * Stefan Berger <stefanb@xxxxxxxxxxxxxx> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -17,29 +14,23 @@ #include "xc_private.h" -int xc_acm_op(int xc_handle, struct acm_op *op) + +int xc_acm_op(int xc_handle, int cmd, void *arg, size_t arg_size) { int ret = -1; DECLARE_HYPERCALL; - op->interface_version = ACM_INTERFACE_VERSION; + hypercall.op = __HYPERVISOR_acm_op; + hypercall.arg[0] = cmd; + hypercall.arg[1] = (unsigned long) arg; - hypercall.op = __HYPERVISOR_acm_op; - hypercall.arg[0] = (unsigned long) op; - - if (mlock(op, sizeof(*op)) != 0) { - PERROR("Could not lock memory for Xen policy hypercall"); - goto out1; + if (mlock(arg, arg_size) != 0) { + PERROR("xc_acm_op: arg mlock failed"); + goto out; } - ret = do_xen_hypercall(xc_handle, &hypercall); - ret = ioctl(xc_handle, IOCTL_PRIVCMD_HYPERCALL, &hypercall); - if (ret < 0) { - goto out2; - } - out2: - safe_munlock(op, sizeof(*op)); - out1: + safe_munlock(arg, arg_size); + out: return ret; } diff -r e99987843336 -r 0f16f0871dc9 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Sun May 21 18:57:42 2006 +0100 +++ b/tools/libxc/xenctrl.h Sun May 21 19:05:31 2006 +0100 @@ -594,6 +594,6 @@ int xc_add_mmu_update(int xc_handle, xc_ unsigned long long ptr, unsigned long long val); int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu); -int xc_acm_op(int xc_handle, struct acm_op *op); +int xc_acm_op(int xc_handle, int cmd, void *arg, size_t arg_size); #endif diff -r e99987843336 -r 0f16f0871dc9 tools/python/xen/lowlevel/acm/acm.c --- a/tools/python/xen/lowlevel/acm/acm.c Sun May 21 18:57:42 2006 +0100 +++ b/tools/python/xen/lowlevel/acm/acm.c Sun May 21 19:05:31 2006 +0100 @@ -38,7 +38,7 @@ fprintf(stderr, "ERROR: " _m " (%d = %s) /* generic shared function */ void * __getssid(int domid, uint32_t *buflen) { - struct acm_op op; + struct acm_getssid getssid; int xc_handle; #define SSID_BUFFER_SIZE 4096 void *buf = NULL; @@ -51,14 +51,13 @@ void * __getssid(int domid, uint32_t *bu goto out2; } memset(buf, 0, SSID_BUFFER_SIZE); - op.cmd = ACM_GETSSID; - op.interface_version = ACM_INTERFACE_VERSION; - op.u.getssid.ssidbuf = buf; - op.u.getssid.ssidbuf_size = SSID_BUFFER_SIZE; - op.u.getssid.get_ssid_by = DOMAINID; - op.u.getssid.id.domainid = domid; - - if (xc_acm_op(xc_handle, &op) < 0) { + getssid.interface_version = ACM_INTERFACE_VERSION; + getssid.ssidbuf = buf; + getssid.ssidbuf_size = SSID_BUFFER_SIZE; + getssid.get_ssid_by = DOMAINID; + getssid.id.domainid = domid; + + if (xc_acm_op(xc_handle, ACMOP_getssid, &getssid, sizeof(getssid)) < 0) { if (errno == EACCES) PERROR("ACM operation failed."); free(buf); @@ -147,7 +146,7 @@ static PyObject *getdecision(PyObject * static PyObject *getdecision(PyObject * self, PyObject * args) { char *arg1_name, *arg1, *arg2_name, *arg2, *decision = NULL; - struct acm_op op; + struct acm_getdecision getdecision; int xc_handle; if (!PyArg_ParseTuple(args, "ssss", &arg1_name, &arg1, &arg2_name, &arg2)) { @@ -163,34 +162,33 @@ static PyObject *getdecision(PyObject * (strcmp(arg2_name, "domid") && strcmp(arg2_name, "ssidref"))) return NULL; - op.cmd = ACM_GETDECISION; - op.interface_version = ACM_INTERFACE_VERSION; - op.u.getdecision.hook = SHARING; + getdecision.interface_version = ACM_INTERFACE_VERSION; + getdecision.hook = SHARING; if (!strcmp(arg1_name, "domid")) { - op.u.getdecision.get_decision_by1 = DOMAINID; - op.u.getdecision.id1.domainid = atoi(arg1); - } else { - op.u.getdecision.get_decision_by1 = SSIDREF; - op.u.getdecision.id1.ssidref = atol(arg1); + getdecision.get_decision_by1 = DOMAINID; + getdecision.id1.domainid = atoi(arg1); + } else { + getdecision.get_decision_by1 = SSIDREF; + getdecision.id1.ssidref = atol(arg1); } if (!strcmp(arg2_name, "domid")) { - op.u.getdecision.get_decision_by2 = DOMAINID; - op.u.getdecision.id2.domainid = atoi(arg2); - } else { - op.u.getdecision.get_decision_by2 = SSIDREF; - op.u.getdecision.id2.ssidref = atol(arg2); - } - - if (xc_acm_op(xc_handle, &op) < 0) { + getdecision.get_decision_by2 = DOMAINID; + getdecision.id2.domainid = atoi(arg2); + } else { + getdecision.get_decision_by2 = SSIDREF; + getdecision.id2.ssidref = atol(arg2); + } + + if (xc_acm_op(xc_handle, ACMOP_getdecision, &getdecision, sizeof(getdecision)) < 0) { if (errno == EACCES) PERROR("ACM operation failed."); } xc_interface_close(xc_handle); - if (op.u.getdecision.acm_decision == ACM_ACCESS_PERMITTED) + if (getdecision.acm_decision == ACM_ACCESS_PERMITTED) decision = "PERMITTED"; - else if (op.u.getdecision.acm_decision == ACM_ACCESS_DENIED) + else if (getdecision.acm_decision == ACM_ACCESS_DENIED) decision = "DENIED"; return Py_BuildValue("s", decision); diff -r e99987843336 -r 0f16f0871dc9 tools/security/secpol_tool.c --- a/tools/security/secpol_tool.c Sun May 21 18:57:42 2006 +0100 +++ b/tools/security/secpol_tool.c Sun May 21 19:05:31 2006 +0100 @@ -231,14 +231,16 @@ uint8_t pull_buffer[PULL_CACHE_SIZE]; uint8_t pull_buffer[PULL_CACHE_SIZE]; int acm_domain_getpolicy(int xc_handle) { - struct acm_op op; + struct acm_getpolicy getpolicy; int ret; memset(pull_buffer, 0x00, sizeof(pull_buffer)); - op.cmd = ACM_GETPOLICY; - op.u.getpolicy.pullcache = (void *) pull_buffer; - op.u.getpolicy.pullcache_size = sizeof(pull_buffer); - if ((ret = xc_acm_op(xc_handle, &op)) < 0) { + getpolicy.interface_version = ACM_INTERFACE_VERSION; + getpolicy.pullcache = (void *) pull_buffer; + getpolicy.pullcache_size = sizeof(pull_buffer); + ret = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy)); + + if (ret < 0) { printf("ACM operation failed: errno=%d\n", errno); if (errno == EACCES) fprintf(stderr, "ACM operation failed -- need to" @@ -275,13 +277,13 @@ int acm_domain_loadpolicy(int xc_handle, goto free_out; } if (len == read(fd, buffer, len)) { - struct acm_op op; + struct acm_setpolicy setpolicy; /* dump it and then push it down into xen/acm */ acm_dump_policy_buffer(buffer, len); - op.cmd = ACM_SETPOLICY; - op.u.setpolicy.pushcache = (void *) buffer; - op.u.setpolicy.pushcache_size = len; - ret = xc_acm_op(xc_handle, &op); + setpolicy.interface_version = ACM_INTERFACE_VERSION; + setpolicy.pushcache = (void *) buffer; + setpolicy.pushcache_size = len; + ret = xc_acm_op(xc_handle, ACMOP_setpolicy, &setpolicy, sizeof(setpolicy)); if (ret) printf @@ -322,15 +324,15 @@ int acm_domain_dumpstats(int xc_handle) int acm_domain_dumpstats(int xc_handle) { uint8_t stats_buffer[PULL_STATS_SIZE]; - struct acm_op op; + struct acm_dumpstats dumpstats; int ret; struct acm_stats_buffer *stats; memset(stats_buffer, 0x00, sizeof(stats_buffer)); - op.cmd = ACM_DUMPSTATS; - op.u.dumpstats.pullcache = (void *) stats_buffer; - op.u.dumpstats.pullcache_size = sizeof(stats_buffer); - ret = xc_acm_op(xc_handle, &op); + dumpstats.interface_version = ACM_INTERFACE_VERSION; + dumpstats.pullcache = (void *) stats_buffer; + dumpstats.pullcache_size = sizeof(stats_buffer); + ret = xc_acm_op(xc_handle, ACMOP_dumpstats, &dumpstats, sizeof(dumpstats)); if (ret < 0) { printf diff -r e99987843336 -r 0f16f0871dc9 xen/common/acm_ops.c --- a/xen/common/acm_ops.c Sun May 21 18:57:42 2006 +0100 +++ b/xen/common/acm_ops.c Sun May 21 19:05:31 2006 +0100 @@ -32,100 +32,94 @@ #ifndef ACM_SECURITY -long do_acm_op(XEN_GUEST_HANDLE(acm_op_t) u_acm_op) + +long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg) { return -ENOSYS; } + #else -enum acm_operation { - POLICY, /* access to policy interface (early drop) */ - GETPOLICY, /* dump policy cache */ - SETPOLICY, /* set policy cache (controls security) */ - DUMPSTATS, /* dump policy statistics */ - GETSSID, /* retrieve ssidref for domain id (decide inside authorized domains) */ - GETDECISION /* retrieve ACM decision from authorized domains */ -}; - -int acm_authorize_acm_ops(struct domain *d, enum acm_operation pops) + +int acm_authorize_acm_ops(struct domain *d) { /* currently, policy management functions are restricted to privileged domains */ if (!IS_PRIV(d)) return -EPERM; - return 0; } -long do_acm_op(XEN_GUEST_HANDLE(acm_op_t) u_acm_op) -{ - long ret = 0; - struct acm_op curop, *op = &curop; - - if (acm_authorize_acm_ops(current->domain, POLICY)) + +long do_acm_op(int cmd, XEN_GUEST_HANDLE(void) arg) +{ + long rc = -EFAULT; + + if (acm_authorize_acm_ops(current->domain)) return -EPERM; - if (copy_from_guest(op, u_acm_op, 1)) - return -EFAULT; - - if (op->interface_version != ACM_INTERFACE_VERSION) - return -EACCES; - - switch (op->cmd) + switch ( cmd ) { - case ACM_SETPOLICY: - { - ret = acm_authorize_acm_ops(current->domain, SETPOLICY); - if (!ret) - ret = acm_set_policy(op->u.setpolicy.pushcache, - op->u.setpolicy.pushcache_size, 1); - } - break; - - case ACM_GETPOLICY: - { - ret = acm_authorize_acm_ops(current->domain, GETPOLICY); - if (!ret) - ret = acm_get_policy(op->u.getpolicy.pullcache, - op->u.getpolicy.pullcache_size); - if (!ret) - copy_to_guest(u_acm_op, op, 1); - } - break; - - case ACM_DUMPSTATS: - { - ret = acm_authorize_acm_ops(current->domain, DUMPSTATS); - if (!ret) - ret = acm_dump_statistics(op->u.dumpstats.pullcache, - op->u.dumpstats.pullcache_size); - if (!ret) - copy_to_guest(u_acm_op, op, 1); - } - break; - - case ACM_GETSSID: - { + + 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, 1); + 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); + 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); + break; + } + + case ACMOP_getssid: { + struct acm_getssid getssid; ssidref_t ssidref; - ret = acm_authorize_acm_ops(current->domain, GETSSID); - if (ret) - break; - - if (op->u.getssid.get_ssid_by == SSIDREF) - ssidref = op->u.getssid.id.ssidref; - else if (op->u.getssid.get_ssid_by == DOMAINID) - { - struct domain *subj = find_domain_by_id(op->u.getssid.id.domainid); - if (!subj) - { - ret = -ESRCH; /* domain not found */ - break; - } - if (subj->ssid == NULL) - { - put_domain(subj); - ret = -ESRCH; + if (copy_from_guest(&getssid, arg, 1) != 0) + return -EFAULT; + if (getssid.interface_version != ACM_INTERFACE_VERSION) + return -EACCES; + + if (getssid.get_ssid_by == SSIDREF) + ssidref = getssid.id.ssidref; + else if (getssid.get_ssid_by == DOMAINID) + { + struct domain *subj = find_domain_by_id(getssid.id.domainid); + if (!subj) + { + rc = -ESRCH; /* domain not found */ + break; + } + if (subj->ssid == NULL) + { + put_domain(subj); + rc = -ESRCH; break; } ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; @@ -133,39 +127,36 @@ long do_acm_op(XEN_GUEST_HANDLE(acm_op_t } else { - ret = -ESRCH; - break; - } - ret = acm_get_ssid(ssidref, - op->u.getssid.ssidbuf, - op->u.getssid.ssidbuf_size); - if (!ret) - copy_to_guest(u_acm_op, op, 1); - } - break; - - case ACM_GETDECISION: - { + rc = -ESRCH; + break; + } + rc = acm_get_ssid(ssidref, getssid.ssidbuf, getssid.ssidbuf_size); + break; + } + + case ACMOP_getdecision: { + struct acm_getdecision getdecision; ssidref_t ssidref1, ssidref2; - ret = acm_authorize_acm_ops(current->domain, GETDECISION); - if (ret) - break; - - if (op->u.getdecision.get_decision_by1 == SSIDREF) - ssidref1 = op->u.getdecision.id1.ssidref; - else if (op->u.getdecision.get_decision_by1 == DOMAINID) - { - struct domain *subj = find_domain_by_id(op->u.getdecision.id1.domainid); - if (!subj) - { - ret = -ESRCH; /* domain not found */ - break; - } - if (subj->ssid == NULL) - { - put_domain(subj); - ret = -ESRCH; + if (copy_from_guest(&getdecision, arg, 1) != 0) + return -EFAULT; + if (getdecision.interface_version != ACM_INTERFACE_VERSION) + return -EACCES; + + if (getdecision.get_decision_by1 == SSIDREF) + ssidref1 = getdecision.id1.ssidref; + else if (getdecision.get_decision_by1 == DOMAINID) + { + struct domain *subj = find_domain_by_id(getdecision.id1.domainid); + if (!subj) + { + rc = -ESRCH; /* domain not found */ + break; + } + if (subj->ssid == NULL) + { + put_domain(subj); + rc = -ESRCH; break; } ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; @@ -173,23 +164,23 @@ long do_acm_op(XEN_GUEST_HANDLE(acm_op_t } else { - ret = -ESRCH; - break; - } - if (op->u.getdecision.get_decision_by2 == SSIDREF) - ssidref2 = op->u.getdecision.id2.ssidref; - else if (op->u.getdecision.get_decision_by2 == DOMAINID) - { - struct domain *subj = find_domain_by_id(op->u.getdecision.id2.domainid); - if (!subj) - { - ret = -ESRCH; /* domain not found */ + rc = -ESRCH; + break; + } + if (getdecision.get_decision_by2 == SSIDREF) + ssidref2 = getdecision.id2.ssidref; + else if (getdecision.get_decision_by2 == DOMAINID) + { + struct domain *subj = find_domain_by_id(getdecision.id2.domainid); + if (!subj) + { + rc = -ESRCH; /* domain not found */ break;; } if (subj->ssid == NULL) { put_domain(subj); - ret = -ESRCH; + rc = -ESRCH; break; } ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref; @@ -197,34 +188,35 @@ long do_acm_op(XEN_GUEST_HANDLE(acm_op_t } else { - ret = -ESRCH; - break; - } - ret = acm_get_decision(ssidref1, ssidref2, op->u.getdecision.hook); - - if (ret == ACM_ACCESS_PERMITTED) - { - op->u.getdecision.acm_decision = ACM_ACCESS_PERMITTED; - ret = 0; - } - else if (ret == ACM_ACCESS_DENIED) - { - op->u.getdecision.acm_decision = ACM_ACCESS_DENIED; - ret = 0; - } - else - ret = -ESRCH; - - if (!ret) - copy_to_guest(u_acm_op, op, 1); - } - break; + rc = -ESRCH; + break; + } + rc = acm_get_decision(ssidref1, ssidref2, getdecision.hook); + + if (rc == ACM_ACCESS_PERMITTED) + { + getdecision.acm_decision = ACM_ACCESS_PERMITTED; + rc = 0; + } + else if (rc == ACM_ACCESS_DENIED) + { + getdecision.acm_decision = ACM_ACCESS_DENIED; + rc = 0; + } + else + rc = -ESRCH; + + if ( (rc == 0) && (copy_to_guest(arg, &getdecision, 1) != 0) ) + rc = -EFAULT; + break; + } default: - ret = -ESRCH; - } - - return ret; + rc = -ENOSYS; + break; + } + + return rc; } #endif diff -r e99987843336 -r 0f16f0871dc9 xen/include/public/acm_ops.h --- a/xen/include/public/acm_ops.h Sun May 21 18:57:42 2006 +0100 +++ b/xen/include/public/acm_ops.h Sun May 21 19:05:31 2006 +0100 @@ -2,7 +2,7 @@ * acm_ops.h: Xen access control module hypervisor commands * * Reiner Sailer <sailer@xxxxxxxxxxxxxx> - * Copyright (c) 2005, International Business Machines Corporation. + * Copyright (c) 2005,2006 International Business Machines Corporation. */ #ifndef __XEN_PUBLIC_ACM_OPS_H__ @@ -17,36 +17,50 @@ * 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 0xAAAA0006 +#define ACM_INTERFACE_VERSION 0xAAAA0007 /************************************************************************/ -#define ACM_SETPOLICY 4 +/* + * Prototype for this hypercall is: + * int acm_op(int cmd, void *args) + * @cmd == ACMOP_??? (access control module operation). + * @args == Operation-specific extra arguments (NULL if none). + */ + + +#define ACMOP_setpolicy 1 struct acm_setpolicy { - /* OUT variables */ + /* IN */ + uint32_t interface_version; void *pushcache; uint32_t pushcache_size; }; -#define ACM_GETPOLICY 5 +#define ACMOP_getpolicy 2 struct acm_getpolicy { - /* OUT variables */ + /* IN */ + uint32_t interface_version; void *pullcache; uint32_t pullcache_size; }; -#define ACM_DUMPSTATS 6 +#define ACMOP_dumpstats 3 struct acm_dumpstats { + /* IN */ + uint32_t interface_version; void *pullcache; uint32_t pullcache_size; }; -#define ACM_GETSSID 7 +#define ACMOP_getssid 4 enum get_type {UNSET=0, SSIDREF, DOMAINID}; struct acm_getssid { + /* IN */ + uint32_t interface_version; enum get_type get_ssid_by; union { domaintype_t domainid; @@ -56,9 +70,11 @@ struct acm_getssid { uint32_t ssidbuf_size; }; -#define ACM_GETDECISION 8 +#define ACMOP_getdecision 5 struct acm_getdecision { - enum get_type get_decision_by1; /* in */ + /* IN */ + uint32_t interface_version; + enum get_type get_decision_by1; enum get_type get_decision_by2; union { domaintype_t domainid; @@ -69,24 +85,11 @@ struct acm_getdecision { ssidref_t ssidref; } id2; enum acm_hook_type hook; - int acm_decision; /* out */ + /* OUT */ + int acm_decision; }; -struct acm_op { - uint32_t cmd; - uint32_t interface_version; /* ACM_INTERFACE_VERSION */ - union { - struct acm_setpolicy setpolicy; - struct acm_getpolicy getpolicy; - struct acm_dumpstats dumpstats; - struct acm_getssid getssid; - struct acm_getdecision getdecision; - } u; -}; -typedef struct acm_op acm_op_t; -DEFINE_XEN_GUEST_HANDLE(acm_op_t); - -#endif /* __XEN_PUBLIC_ACM_OPS_H__ */ +#endif /* __XEN_PUBLIC_ACM_OPS_H__ */ /* * Local variables: diff -r e99987843336 -r 0f16f0871dc9 xen/include/xen/hypercall.h --- a/xen/include/xen/hypercall.h Sun May 21 18:57:42 2006 +0100 +++ b/xen/include/xen/hypercall.h Sun May 21 19:05:31 2006 +0100 @@ -80,7 +80,7 @@ do_vcpu_op( extern long do_acm_op( - XEN_GUEST_HANDLE(acm_op_t) u_acm_op); + int cmd, XEN_GUEST_HANDLE(void) arg); extern long do_nmi_op( _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |