aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorKeir Fraser <keir@xensource.com>2007-10-03 14:04:51 +0100
committerKeir Fraser <keir@xensource.com>2007-10-03 14:04:51 +0100
commit8950f5c6ba8e2349de4162af6f09f36c80670cf7 (patch)
treec504141d5eb47e884c8c7e1e566b15ba0607606c /tools
parentac9ba8d39deffe57bf3068f365e8a079ac74b5e7 (diff)
downloadxen-8950f5c6ba8e2349de4162af6f09f36c80670cf7.tar.gz
xen-8950f5c6ba8e2349de4162af6f09f36c80670cf7.tar.bz2
xen-8950f5c6ba8e2349de4162af6f09f36c80670cf7.zip
Extend 'xm dumppolicy' to support Xen-API
I am extending 'xm dumppolicy' to be used via the Xen-API. For this there are two new functions in the ACM policy class: - get the currently enforced policy including statistical data from the hypervisor - get the ACM 'ssidref' of a Domain. Since this may be a ACM-specific variable or type (int) I put it into the ACM class. I extended the Xen-API documentation with the two new functions. Signed-off-by: Stefan Berger <Stefanb@us.ibm.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/libxen/include/xen/api/xen_acmpolicy.h17
-rw-r--r--tools/libxen/src/xen_acmpolicy.c35
-rw-r--r--tools/python/xen/lowlevel/acm/acm.c37
-rw-r--r--tools/python/xen/util/acmpolicy.py8
-rw-r--r--tools/python/xen/util/xsm/acm/acm.py30
-rw-r--r--tools/python/xen/xend/XendXSPolicy.py31
-rw-r--r--tools/python/xen/xend/XendXSPolicyAdmin.py5
-rw-r--r--tools/python/xen/xm/dumppolicy.py31
-rw-r--r--tools/security/secpol_tool.c136
9 files changed, 293 insertions, 37 deletions
diff --git a/tools/libxen/include/xen/api/xen_acmpolicy.h b/tools/libxen/include/xen/api/xen_acmpolicy.h
index 4ac1cfd8e8..d0b4a500ca 100644
--- a/tools/libxen/include/xen/api/xen_acmpolicy.h
+++ b/tools/libxen/include/xen/api/xen_acmpolicy.h
@@ -108,7 +108,22 @@ xen_acmpolicy_get_binary(xen_session *session, char **binary,
xen_xspolicy xspolicy);
/**
- * Get the UUID filed of the given policy.
+ * Get the binary representation (base64-encoded) of the currently
+ * enforced policy.
+ */
+extern bool
+xen_acmpolicy_get_enforced_binary(xen_session *session, char **binary,
+ xen_xspolicy xspolicy);
+
+/**
+ * Get the ACM ssidref of the given VM.
+ */
+bool
+xen_acmpolicy_get_VM_ssidref(xen_session *session, int64_t *result,
+ xen_vm vm);
+
+/**
+ * Get the UUID field of the given policy.
*/
bool
xen_acmpolicy_get_uuid(xen_session *session, char **result,
diff --git a/tools/libxen/src/xen_acmpolicy.c b/tools/libxen/src/xen_acmpolicy.c
index 1a6190bfee..f8d69195a4 100644
--- a/tools/libxen/src/xen_acmpolicy.c
+++ b/tools/libxen/src/xen_acmpolicy.c
@@ -217,6 +217,41 @@ xen_acmpolicy_get_binary(xen_session *session, char **result,
bool
+xen_acmpolicy_get_enforced_binary(xen_session *session, char **result,
+ xen_xspolicy xspolicy)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = xspolicy },
+ };
+
+ abstract_type result_type = abstract_type_string;
+
+ *result = NULL;
+ XEN_CALL_("ACMPolicy.get_enforced_binary");
+ return session->ok;
+}
+
+
+bool
+xen_acmpolicy_get_VM_ssidref(xen_session *session,
+ int64_t *result, xen_vm vm)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vm }
+ };
+
+ abstract_type result_type = abstract_type_int;
+
+ XEN_CALL_("ACMPolicy.get_VM_ssidref");
+ return session->ok;
+}
+
+
+bool
xen_acmpolicy_get_uuid(xen_session *session, char **result,
xen_xspolicy xspolicy)
{
diff --git a/tools/python/xen/lowlevel/acm/acm.c b/tools/python/xen/lowlevel/acm/acm.c
index 0a37ba3d92..1daa4e626a 100644
--- a/tools/python/xen/lowlevel/acm/acm.c
+++ b/tools/python/xen/lowlevel/acm/acm.c
@@ -26,6 +26,7 @@
#include <sys/mman.h>
#include <sys/types.h>
#include <stdlib.h>
+#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <xen/xsm/acm.h>
@@ -258,6 +259,41 @@ static PyObject *chgpolicy(PyObject *self, PyObject *args)
}
+static PyObject *getpolicy(PyObject *self, PyObject *args)
+{
+ struct acm_getpolicy getpolicy;
+ int xc_handle, rc;
+ uint8_t pull_buffer[8192];
+ PyObject *result;
+ uint32_t len = sizeof(pull_buffer);
+
+ memset(&getpolicy, 0x0, sizeof(getpolicy));
+ set_xen_guest_handle(getpolicy.pullcache, pull_buffer);
+ getpolicy.pullcache_size = sizeof(pull_buffer);
+
+ if ((xc_handle = xc_interface_open()) <= 0) {
+ PyErr_SetString(PyExc_IOError, ctrlif_op);
+ return NULL;
+ }
+
+ rc = xc_acm_op(xc_handle, ACMOP_getpolicy, &getpolicy, sizeof(getpolicy));
+
+ xc_interface_close(xc_handle);
+
+ if (rc == 0) {
+ struct acm_policy_buffer *header =
+ (struct acm_policy_buffer *)pull_buffer;
+ if (ntohl(header->len) < sizeof(pull_buffer))
+ len = ntohl(header->len);
+ } else {
+ len = 0;
+ }
+
+ result = Py_BuildValue("is#", rc, pull_buffer, len);
+ return result;
+}
+
+
static PyObject *relabel_domains(PyObject *self, PyObject *args)
{
struct acm_relabel_doms reldoms;
@@ -313,6 +349,7 @@ static PyMethodDef acmMethods[] = {
{"getssid", getssid, METH_VARARGS, "Retrieve label information and ssidref for a domain"},
{"getdecision", getdecision, METH_VARARGS, "Retrieve ACM access control decision"},
{"chgpolicy", chgpolicy, METH_VARARGS, "Change the policy in one step"},
+ {"getpolicy", getpolicy, METH_NOARGS , "Get the binary policy from the hypervisor"},
{"relabel_domains", relabel_domains, METH_VARARGS, "Relabel domains"},
/* end of list (extend list above this line) */
{NULL, NULL, 0, NULL}
diff --git a/tools/python/xen/util/acmpolicy.py b/tools/python/xen/util/acmpolicy.py
index 36aa88cbd3..d11b40dec0 100644
--- a/tools/python/xen/util/acmpolicy.py
+++ b/tools/python/xen/util/acmpolicy.py
@@ -1264,3 +1264,11 @@ class ACMPolicy(XSPolicy):
log.info("The following Ch. Wall types in labels were unknown:" \
" %s" % list(unknown_chw))
return rc, mapfile, all_bin.tostring()
+
+ def get_enforced_binary(self):
+ rc, binpol = security.hv_get_policy()
+ if rc != 0:
+ raise SecurityError(-xsconstants.XSERR_HV_OP_FAILED)
+ return binpol
+
+ get_enforced_binary = classmethod(get_enforced_binary)
diff --git a/tools/python/xen/util/xsm/acm/acm.py b/tools/python/xen/util/xsm/acm/acm.py
index d58652e06c..53081f0261 100644
--- a/tools/python/xen/util/xsm/acm/acm.py
+++ b/tools/python/xen/util/xsm/acm/acm.py
@@ -507,6 +507,22 @@ def hv_chg_policy(bin_pol, del_array, chg_array):
rc = -xsconstants.XSERR_HV_OP_FAILED
return rc, errors
+def hv_get_policy():
+ """
+ Gte the binary policy enforced in the hypervisor
+ """
+ rc = -xsconstants.XSERR_GENERAL_FAILURE
+ bin_pol = ""
+ if not on():
+ err("No policy active.")
+ try:
+ rc, bin_pol = acm.getpolicy()
+ except Exception, e:
+ pass
+ if len(bin_pol) == 0:
+ bin_pol = None
+ return rc, bin_pol
+
def make_policy(policy_name):
policy_file = string.join(string.split(policy_name, "."), "/")
@@ -546,10 +562,22 @@ def dump_policy():
(ret, output) = commands.getstatusoutput(xensec_tool + " getpolicy")
if ret:
- err("Dumping hypervisor policy failed:\n" + output)
+ err("Dumping hypervisor policy failed:\n" + output)
+
print output
+def dump_policy_file(filename, ssidref=None):
+ ssid = ""
+ if ssidref:
+ ssid = " " + str(ssidref)
+ (ret, output) = commands.getstatusoutput(xensec_tool + " dumppolicy " +
+ filename + ssid)
+ if ret:
+ err("Dumping policy failed:\n" + output)
+
+ print output
+
def list_labels(policy_name, condition):
if (not policy_name) and (active_policy) in ["NULL", "INACTIVE", "DEFAULT"]:
diff --git a/tools/python/xen/xend/XendXSPolicy.py b/tools/python/xen/xend/XendXSPolicy.py
index de30fd7caa..11c1a1b63f 100644
--- a/tools/python/xen/xend/XendXSPolicy.py
+++ b/tools/python/xen/xend/XendXSPolicy.py
@@ -16,13 +16,15 @@
# Copyright (c) 2006 Xensource
#============================================================================
+import base64
import logging
+from xen.xend import XendDomain
from xen.xend.XendBase import XendBase
from xen.xend.XendError import *
+from xen.xend.XendAPIConstants import *
from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
from xen.util import xsconstants
import xen.util.xsm.xsm as security
-import base64
log = logging.getLogger("xend.XendXSPolicy")
log.setLevel(logging.TRACE)
@@ -184,8 +186,13 @@ class XendACMPolicy(XendXSPolicy):
'header' ]
return XendXSPolicy.getAttrRO() + attrRO
+ def getFuncs(self):
+ funcs = [ 'get_enforced_binary', 'get_VM_ssidref' ]
+ return XendBase.getFuncs() + funcs
+
getClass = classmethod(getClass)
getAttrRO = classmethod(getAttrRO)
+ getFuncs = classmethod(getFuncs)
def __init__(self, acmpol, record, uuid):
""" acmpol = actual ACMPolicy object """
@@ -221,3 +228,25 @@ class XendACMPolicy(XendXSPolicy):
def get_binary(self):
polbin = self.acmpol.get_bin()
return base64.b64encode(polbin)
+
+ def get_VM_ssidref(self, vm_ref):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ if not dom:
+ raise InvalidHandleError("VM", vm_ref)
+ if dom._stateGet() not in [ XEN_API_VM_POWER_STATE_RUNNING, \
+ XEN_API_VM_POWER_STATE_PAUSED ]:
+ raise VMBadState("Domain is not running or paused.")
+ ssid = security.get_ssid(dom.getDomid())
+ if not ssid:
+ raise SecurityError(-xsconstants.XSERR_GENERAL_FAILURE)
+ return ssid[3]
+
+ def get_enforced_binary(self):
+ polbin = XSPolicyAdminInstance(). \
+ get_enforced_binary(xsconstants.XS_POLICY_ACM)
+ if polbin:
+ return base64.b64encode(polbin)
+ return None
+
+ get_enforced_binary = classmethod(get_enforced_binary)
+ get_VM_ssidref = classmethod(get_VM_ssidref)
diff --git a/tools/python/xen/xend/XendXSPolicyAdmin.py b/tools/python/xen/xend/XendXSPolicyAdmin.py
index c97e085dd0..c8f70b9242 100644
--- a/tools/python/xen/xend/XendXSPolicyAdmin.py
+++ b/tools/python/xen/xend/XendXSPolicyAdmin.py
@@ -324,6 +324,11 @@ class XSPolicyAdmin:
stes = loadedpol.policy_get_stes_of_vmlabel(tmp[2])
return stes
+ def get_enforced_binary(self, xstype):
+ res = None
+ if xstype == xsconstants.XS_POLICY_ACM:
+ res = ACMPolicy.get_enforced_binary()
+ return res
poladmin = None
diff --git a/tools/python/xen/xm/dumppolicy.py b/tools/python/xen/xm/dumppolicy.py
index 77c4151beb..7bd2ba15de 100644
--- a/tools/python/xen/xm/dumppolicy.py
+++ b/tools/python/xen/xm/dumppolicy.py
@@ -17,9 +17,18 @@
#============================================================================
"""Display currently enforced policy (low-level hypervisor representation).
"""
+import os
import sys
-from xen.util.xsm.xsm import XSMError, err, dump_policy
+import base64
+import tempfile
+import commands
+from xen.util.xsm.xsm import XSMError, err, dump_policy, dump_policy_file
from xen.xm.opts import OptionError
+from xen.xm import main as xm_main
+from xen.xm.main import server
+from xen.util import xsconstants
+
+DOM0_UUID = "00000000-0000-0000-0000-000000000000"
def help():
return """
@@ -30,7 +39,25 @@ def main(argv):
if len(argv) != 1:
raise OptionError("No arguments expected.")
- dump_policy()
+ if xm_main.serverType == xm_main.SERVER_XEN_API:
+ try:
+ bin_pol = server.xenapi.ACMPolicy.get_enforced_binary()
+ if bin_pol:
+ dom0_ssid = server.xenapi.ACMPolicy.get_VM_ssidref(DOM0_UUID)
+ bin = base64.b64decode(bin_pol)
+ try:
+ fd, filename = tempfile.mkstemp(suffix=".bin")
+ os.write(fd, bin)
+ os.close(fd)
+ dump_policy_file(filename, dom0_ssid)
+ finally:
+ os.unlink(filename)
+ else:
+ err("No policy is installed.")
+ except Exception, e:
+ err("An error occurred getting the running policy: %s" % str(e))
+ else:
+ dump_policy()
if __name__ == '__main__':
try:
diff --git a/tools/security/secpol_tool.c b/tools/security/secpol_tool.c
index 14b4bcc73d..e9da8e4827 100644
--- a/tools/security/secpol_tool.c
+++ b/tools/security/secpol_tool.c
@@ -49,7 +49,9 @@ void usage(char *progname)
"ACTION is one of:\n"
"\t getpolicy\n"
"\t dumpstats\n"
- "\t loadpolicy <binary policy file>\n", progname);
+ "\t loadpolicy <binary policy file>\n"
+ "\t dumppolicy <binary policy file> [Dom-0 ssidref]\n",
+ progname);
exit(-1);
}
@@ -288,53 +290,93 @@ int acm_domain_getpolicy(int xc_handle)
return ret;
}
-/************************ load binary policy ******************************/
+/************************ dump binary policy ******************************/
-int acm_domain_loadpolicy(int xc_handle, const char *filename)
+static int load_file(const char *filename,
+ uint8_t **buffer, off_t *len)
{
struct stat mystat;
- int ret, fd;
- off_t len;
- uint8_t *buffer;
- uint16_t chwall_ssidref, ste_ssidref;
+ int ret = 0;
+ int fd;
- if ((ret = stat(filename, &mystat))) {
+ if ((ret = stat(filename, &mystat)) != 0) {
printf("File %s not found.\n", filename);
+ ret = errno;
goto out;
}
- len = mystat.st_size;
- if ((buffer = malloc(len)) == NULL) {
+ *len = mystat.st_size;
+
+ if ((*buffer = malloc(*len)) == NULL) {
ret = -ENOMEM;
goto out;
}
+
if ((fd = open(filename, O_RDONLY)) <= 0) {
ret = -ENOENT;
printf("File %s not found.\n", filename);
goto free_out;
}
- ret =acm_get_ssidref(xc_handle, 0, &chwall_ssidref, &ste_ssidref);
- if (ret < 0) {
- goto free_out;
- }
- if (len == read(fd, buffer, len)) {
- struct acm_setpolicy setpolicy;
- /* dump it and then push it down into xen/acm */
+
+ if (*len == read(fd, *buffer, *len))
+ return 0;
+
+free_out:
+ free(*buffer);
+ *buffer = NULL;
+ *len = 0;
+out:
+ return ret;
+}
+
+static int acm_domain_dumppolicy(const char *filename, uint32_t ssidref)
+{
+ uint8_t *buffer = NULL;
+ off_t len;
+ int ret = 0;
+ uint16_t chwall_ssidref, ste_ssidref;
+
+ chwall_ssidref = (ssidref ) & 0xffff;
+ ste_ssidref = (ssidref >> 16) & 0xffff;
+
+ if ((ret = load_file(filename, &buffer, &len)) == 0) {
acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref);
- set_xen_guest_handle(setpolicy.pushcache, buffer);
- setpolicy.pushcache_size = len;
- ret = xc_acm_op(xc_handle, ACMOP_setpolicy, &setpolicy, sizeof(setpolicy));
+ free(buffer);
+ }
- if (ret)
- printf
- ("ERROR setting policy.\n");
- else
- printf("Successfully changed policy.\n");
+ return ret;
+}
+
+/************************ load binary policy ******************************/
+int acm_domain_loadpolicy(int xc_handle, const char *filename)
+{
+ int ret;
+ off_t len;
+ uint8_t *buffer;
+ uint16_t chwall_ssidref, ste_ssidref;
+ struct acm_setpolicy setpolicy;
+
+ ret = load_file(filename, &buffer, &len);
+ if (ret != 0)
+ goto out;
+
+ ret = acm_get_ssidref(xc_handle, 0, &chwall_ssidref, &ste_ssidref);
+ if (ret < 0)
+ goto free_out;
+
+ /* dump it and then push it down into xen/acm */
+ acm_dump_policy_buffer(buffer, len, chwall_ssidref, ste_ssidref);
+ set_xen_guest_handle(setpolicy.pushcache, buffer);
+ setpolicy.pushcache_size = len;
+ ret = xc_acm_op(xc_handle, ACMOP_setpolicy, &setpolicy, sizeof(setpolicy));
+
+ if (ret) {
+ printf("ERROR setting policy.\n");
} else {
- ret = -1;
+ printf("Successfully changed policy.\n");
}
- close(fd);
+
free_out:
free(buffer);
out:
@@ -435,26 +477,56 @@ int main(int argc, char **argv)
if (argc < 2)
usage(argv[0]);
- if ((xc_handle = xc_interface_open()) <= 0) {
- printf("ERROR: Could not open xen privcmd device!\n");
- exit(-1);
- }
if (!strcmp(argv[1], "getpolicy")) {
if (argc != 2)
usage(argv[0]);
+
+ if ((xc_handle = xc_interface_open()) <= 0) {
+ printf("ERROR: Could not open xen privcmd device!\n");
+ exit(-1);
+ }
+
ret = acm_domain_getpolicy(xc_handle);
+
+ xc_interface_close(xc_handle);
} else if (!strcmp(argv[1], "loadpolicy")) {
if (argc != 3)
usage(argv[0]);
+
+ if ((xc_handle = xc_interface_open()) <= 0) {
+ printf("ERROR: Could not open xen privcmd device!\n");
+ exit(-1);
+ }
+
ret = acm_domain_loadpolicy(xc_handle, argv[2]);
+
+ xc_interface_close(xc_handle);
} else if (!strcmp(argv[1], "dumpstats")) {
if (argc != 2)
usage(argv[0]);
+
+ if ((xc_handle = xc_interface_open()) <= 0) {
+ printf("ERROR: Could not open xen privcmd device!\n");
+ exit(-1);
+ }
+
ret = acm_domain_dumpstats(xc_handle);
+
+ xc_interface_close(xc_handle);
+ } else if (!strcmp(argv[1], "dumppolicy")) {
+ uint32_t ssidref = 0xffffffff;
+ if (argc < 3 || argc > 4)
+ usage(argv[0]);
+ if (argc == 4) {
+ if (!sscanf(argv[3], "%i", &ssidref)) {
+ printf("Error: Could not parse ssidref.\n");
+ exit(-1);
+ }
+ }
+ ret = acm_domain_dumppolicy(argv[2], ssidref);
} else
usage(argv[0]);
- xc_interface_close(xc_handle);
return ret;
}