[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] xsm: add device tree labeling support
This adds support in the hypervisor and policy build toolchain for Xen/Flask policy version 25, which adds the ability to label ARM device tree nodes and expands the IOMEM ocontext entries to 64 bits. Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> --- Note: Actually using the features added in this patch requires a patch to the SELinux toolchain (checkpolicy) which has just been sent to that upstream and xen-devel. tools/flask/policy/Makefile | 22 +++++--- xen/include/public/xsm/flask_op.h | 9 ++++ xen/xsm/flask/flask_op.c | 28 ++++++++++ xen/xsm/flask/include/security.h | 9 +++- xen/xsm/flask/ss/policydb.c | 73 +++++++++++++++++++------ xen/xsm/flask/ss/policydb.h | 7 +-- xen/xsm/flask/ss/services.c | 111 +++++++++++++++++++++++++++++++++++--- 7 files changed, 226 insertions(+), 33 deletions(-) diff --git a/tools/flask/policy/Makefile b/tools/flask/policy/Makefile index e564396..3220f6b 100644 --- a/tools/flask/policy/Makefile +++ b/tools/flask/policy/Makefile @@ -26,15 +26,13 @@ M4 ?= m4 # ######################################## -# Policy version -# By default, checkpolicy creates the highest version policy it supports. Force -# the use of version 24 which is the highest that Xen supports, and the first to -# include the Xen policy type (needed for static device policy). -OUTPUT_POLICY = 24 - POLICY_FILENAME = xenpolicy-$(shell $(MAKE) -C $(XEN_ROOT)/xen xenversion --no-print-directory) POLICY_LOADPATH = /boot +# Minimum and maximum policy versions supported by the hypervisor +POLICY_VER_MIN = 24 +POLICY_VER_MAX = 25 + # policy source layout POLDIR := policy MODDIR := $(POLDIR)/modules @@ -64,6 +62,18 @@ MOD_CONF := $(POLDIR)/modules.conf # checkpolicy can use the #line directives provided by -s for error reporting: M4PARAM := -D self_contained_policy -s + +# If checkpolicy supports Xen policy versions other than 24 (the first version +# with support for the Xen policy), it will report them in the output of +# "checkpolicy -t Xen -V", such as "Xen policy compatibility range: 24 25". +# Otherwise, the maximum version supported by checkpolicy is 24. +CHECKPOLICY_VERS_TXT := $(shell $(CHECKPOLICY) -t Xen -V) +CHECKPOLICY_XEN_MAX = $(if $(findstring Xen,$(CHECKPOLICY_VERS_TXT)),$(lastword $(CHECKPOLICY_VERS_TXT)),24) + +# The output policy version used will be the highest supported by both the +# hypervisor and the checkpolicy binary +OUTPUT_POLICY := $(shell if test $(CHECKPOLICY_XEN_MAX) -gt $(POLICY_VER_MAX); then echo $(POLICY_VER_MAX); else echo $(CHECKPOLICY_XEN_MAX); fi) + CHECKPOLICY_PARAM := -t Xen -c $(OUTPUT_POLICY) # enable MLS if requested. diff --git a/xen/include/public/xsm/flask_op.h b/xen/include/public/xsm/flask_op.h index f874589..c76359c 100644 --- a/xen/include/public/xsm/flask_op.h +++ b/xen/include/public/xsm/flask_op.h @@ -150,6 +150,13 @@ struct xen_flask_relabel { uint32_t sid; }; +struct xen_flask_devicetree_label { + /* IN */ + uint32_t sid; + uint32_t length; + XEN_GUEST_HANDLE(char) path; +}; + struct xen_flask_op { uint32_t cmd; #define FLASK_LOAD 1 @@ -176,6 +183,7 @@ struct xen_flask_op { #define FLASK_DEL_OCONTEXT 22 #define FLASK_GET_PEER_SID 23 #define FLASK_RELABEL_DOMAIN 24 +#define FLASK_DEVICETREE_LABEL 25 uint32_t interface_version; /* XEN_FLASK_INTERFACE_VERSION */ union { struct xen_flask_load load; @@ -195,6 +203,7 @@ struct xen_flask_op { struct xen_flask_ocontext ocontext; struct xen_flask_peersid peersid; struct xen_flask_relabel relabel; + struct xen_flask_devicetree_label devicetree_label; } u; }; typedef struct xen_flask_op xen_flask_op_t; diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c index 84c7fec..47aacc1 100644 --- a/xen/xsm/flask/flask_op.c +++ b/xen/xsm/flask/flask_op.c @@ -563,6 +563,27 @@ static int flask_security_load(struct xen_flask_load *load) return ret; } +static int flask_devicetree_label(struct xen_flask_devicetree_label *arg) +{ + int rv; + char *buf; + u32 sid = arg->sid; + u32 perm = sid ? SECURITY__ADD_OCONTEXT : SECURITY__DEL_OCONTEXT; + + rv = domain_has_security(current->domain, perm); + if ( rv ) + return rv; + + rv = flask_copyin_string(arg->path, &buf, arg->length, PAGE_SIZE); + if ( rv ) + return rv; + + /* buf is consumed or freed by this function */ + rv = security_devicetree_setlabel(buf, sid); + + return rv; +} + #ifndef COMPAT static int flask_ocontext_del(struct xen_flask_ocontext *arg) @@ -790,6 +811,10 @@ ret_t do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op) rv = flask_relabel_domain(&op.u.relabel); break; + case FLASK_DEVICETREE_LABEL: + rv = flask_devicetree_label(&op.u.devicetree_label); + break; + default: rv = -ENOSYS; } @@ -848,6 +873,9 @@ CHECK_flask_transition; #define flask_security_get_bool compat_security_get_bool #define flask_security_set_bool compat_security_set_bool +#define xen_flask_devicetree_label compat_flask_devicetree_label +#define flask_devicetree_label compat_devicetree_label + #define xen_flask_op_t compat_flask_op_t #undef ret_t #define ret_t int diff --git a/xen/xsm/flask/include/security.h b/xen/xsm/flask/include/security.h index d07bae0..9590dd3 100644 --- a/xen/xsm/flask/include/security.h +++ b/xen/xsm/flask/include/security.h @@ -30,10 +30,11 @@ #define POLICYDB_VERSION_POLCAP 22 #define POLICYDB_VERSION_PERMISSIVE 23 #define POLICYDB_VERSION_BOUNDARY 24 +#define POLICYDB_VERSION_AARCH 25 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AARCH enum flask_bootparam_t { FLASK_BOOTPARAM_PERMISSIVE, @@ -82,6 +83,8 @@ int security_ioport_sid(u32 ioport, u32 *out_sid); int security_device_sid(u32 device, u32 *out_sid); +int security_devicetree_sid(const char *path, u32 *out_sid); + int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, u16 tclass); @@ -96,5 +99,7 @@ int security_iterate_ioport_sids(u32 start, u32 end, int security_ocontext_add(u32 ocontext, unsigned long low, unsigned long high, u32 sid); -int security_ocontext_del(u32 ocontext, unsigned int low, unsigned int high); +int security_ocontext_del(u32 ocontext, unsigned long low, unsigned long high); + +int security_devicetree_setlabel(char *path, u32 sid); #endif /* _FLASK_SECURITY_H_ */ diff --git a/xen/xsm/flask/ss/policydb.c b/xen/xsm/flask/ss/policydb.c index b88ea56..c7d29bd 100644 --- a/xen/xsm/flask/ss/policydb.c +++ b/xen/xsm/flask/ss/policydb.c @@ -74,55 +74,55 @@ static struct policydb_compat_info policydb_compat[] = { { .version = POLICYDB_VERSION_BASE, .sym_num = SYM_NUM - 3, - .ocon_num = OCON_NUM - 1, + .ocon_num = 4, .target_type = TARGET_XEN_OLD, }, { .version = POLICYDB_VERSION_BOOL, .sym_num = SYM_NUM - 2, - .ocon_num = OCON_NUM - 1, + .ocon_num = 4, .target_type = TARGET_XEN_OLD, }, { .version = POLICYDB_VERSION_IPV6, .sym_num = SYM_NUM - 2, - .ocon_num = OCON_NUM, + .ocon_num = 5, .target_type = TARGET_XEN_OLD, }, { .version = POLICYDB_VERSION_NLCLASS, .sym_num = SYM_NUM - 2, - .ocon_num = OCON_NUM, + .ocon_num = 5, .target_type = TARGET_XEN_OLD, }, { .version = POLICYDB_VERSION_MLS, .sym_num = SYM_NUM, - .ocon_num = OCON_NUM, + .ocon_num = 5, .target_type = TARGET_XEN_OLD, }, { .version = POLICYDB_VERSION_AVTAB, .sym_num = SYM_NUM, - .ocon_num = OCON_NUM, + .ocon_num = 5, .target_type = TARGET_XEN_OLD, }, { .version = POLICYDB_VERSION_RANGETRANS, .sym_num = SYM_NUM, - .ocon_num = OCON_NUM, + .ocon_num = 5, .target_type = TARGET_XEN_OLD, }, { .version = POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, - .ocon_num = OCON_NUM, + .ocon_num = 5, .target_type = TARGET_XEN_OLD, }, { .version = POLICYDB_VERSION_PERMISSIVE, .sym_num = SYM_NUM, - .ocon_num = OCON_NUM, + .ocon_num = 5, .target_type = TARGET_XEN_OLD, }, { @@ -134,7 +134,13 @@ static struct policydb_compat_info policydb_compat[] = { { .version = POLICYDB_VERSION_BOUNDARY, .sym_num = SYM_NUM, - .ocon_num = OCON_NUM, + .ocon_num = OCON_DEVICE + 1, + .target_type = TARGET_XEN, + }, + { + .version = POLICYDB_VERSION_AARCH, + .sym_num = SYM_NUM, + .ocon_num = OCON_DTREE + 1, .target_type = TARGET_XEN, }, }; @@ -634,7 +640,7 @@ static void ocontext_destroy(struct ocontext *c, int i) { context_destroy(&c->context[0]); context_destroy(&c->context[1]); - if ( i == OCON_ISID ) + if ( i == OCON_ISID || i == OCON_DTREE ) xfree(c->u.name); xfree(c); } @@ -1999,11 +2005,23 @@ int policydb_read(struct policydb *p, void *fp) "Old xen policy does not support iomemcon"); goto bad; } - rc = next_entry(buf, fp, sizeof(u32) *2); - if ( rc < 0 ) - goto bad; - c->u.iomem.low_iomem = le32_to_cpu(buf[0]); - c->u.iomem.high_iomem = le32_to_cpu(buf[1]); + if ( p->policyvers >= POLICYDB_VERSION_AARCH ) + { + u64 b64[2]; + rc = next_entry(b64, fp, sizeof(u64) *2); + if ( rc < 0 ) + goto bad; + c->u.iomem.low_iomem = le64_to_cpu(b64[0]); + c->u.iomem.high_iomem = le64_to_cpu(b64[1]); + } + else + { + rc = next_entry(buf, fp, sizeof(u32) *2); + if ( rc < 0 ) + goto bad; + c->u.iomem.low_iomem = le32_to_cpu(buf[0]); + c->u.iomem.high_iomem = le32_to_cpu(buf[1]); + } rc = context_read_and_validate(&c->context[0], p, fp); if ( rc ) goto bad; @@ -2023,6 +2041,29 @@ int policydb_read(struct policydb *p, void *fp) if ( rc ) goto bad; break; + case OCON_DTREE: + if ( p->target_type != TARGET_XEN ) + { + printk(KERN_ERR + "Old xen policy does not support devicetreecon"); + goto bad; + } + rc = next_entry(buf, fp, sizeof(u32)); + if ( rc < 0 ) + goto bad; + len = le32_to_cpu(buf[0]); + rc = -ENOMEM; + c->u.name = xmalloc_array(char, len + 1); + if (!c->u.name) + goto bad; + rc = next_entry(c->u.name, fp, len); + if ( rc < 0 ) + goto bad; + c->u.name[len] = 0; + rc = context_read_and_validate(&c->context[0], p, fp); + if ( rc ) + goto bad; + break; default: printk(KERN_ERR "Flask: unsupported object context config data\n"); diff --git a/xen/xsm/flask/ss/policydb.h b/xen/xsm/flask/ss/policydb.h index b176300..30be71a 100644 --- a/xen/xsm/flask/ss/policydb.h +++ b/xen/xsm/flask/ss/policydb.h @@ -154,8 +154,8 @@ struct ocontext { u32 high_ioport; } ioport; struct { - u32 low_iomem; - u32 high_iomem; + u64 low_iomem; + u64 high_iomem; } iomem; } u; struct context context[2]; /* security context(s) */ @@ -180,7 +180,8 @@ struct ocontext { #define OCON_IOPORT 2 /* io ports */ #define OCON_IOMEM 3 /* io memory */ #define OCON_DEVICE 4 /* pci devices */ -#define OCON_NUM 5 +#define OCON_DTREE 5 /* device tree nodes */ +#define OCON_NUM 6 #define OCON_NUM_OLD 7 /* The policy database */ diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c index f0e459a..ba2336e 100644 --- a/xen/xsm/flask/ss/services.c +++ b/xen/xsm/flask/ss/services.c @@ -1831,6 +1831,41 @@ out: return rc; } +int security_devicetree_sid(const char *path, u32 *out_sid) +{ + struct ocontext *c; + int rc = 0; + + POLICY_RDLOCK; + + c = policydb.ocontexts[OCON_DTREE]; + while ( c ) + { + if ( strcmp(c->u.name, path) == 0 ) + break; + c = c->next; + } + + if ( c ) + { + if ( !c->sid[0] ) + { + rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]); + if ( rc ) + goto out; + } + *out_sid = c->sid[0]; + } + else + { + *out_sid = SECINITSID_DEVICE; + } + +out: + POLICY_RDUNLOCK; + return rc; +} + int security_find_bool(const char *name) { int i, rv = -ENOENT; @@ -2131,7 +2166,7 @@ int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high c->u.iomem.high_iomem == high && c->sid[0] == sid) break; - printk("%s: IO Memory overlap with entry %#x - %#x\n", + printk("%s: IO Memory overlap with entry %#lx - %#lx\n", __FUNCTION__, c->u.iomem.low_iomem, c->u.iomem.high_iomem); ret = -EEXIST; @@ -2188,7 +2223,7 @@ int security_ocontext_add( u32 ocon, unsigned long low, unsigned long high return ret; } -int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high ) +int security_ocontext_del( u32 ocon, unsigned long low, unsigned long high ) { int ret = 0; struct ocontext *c, *before_c; @@ -2217,7 +2252,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high ) } } - printk("%s: ocontext not found: pirq %d\n", __FUNCTION__, low); + printk("%s: ocontext not found: pirq %ld\n", __FUNCTION__, low); ret = -ENOENT; break; @@ -2243,7 +2278,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high ) } } - printk("%s: ocontext not found: ioport %#x - %#x\n", __FUNCTION__, + printk("%s: ocontext not found: ioport %#lx - %#lx\n", __FUNCTION__, low, high); ret = -ENOENT; break; @@ -2270,7 +2305,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high ) } } - printk("%s: ocontext not found: iomem %#x - %#x\n", __FUNCTION__, + printk("%s: ocontext not found: iomem %#lx - %#lx\n", __FUNCTION__, low, high); ret = -ENOENT; break; @@ -2296,7 +2331,7 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high ) } } - printk("%s: ocontext not found: pcidevice %#x\n", __FUNCTION__, low); + printk("%s: ocontext not found: pcidevice %#lx\n", __FUNCTION__, low); ret = -ENOENT; break; @@ -2308,3 +2343,67 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high ) POLICY_WRUNLOCK; return ret; } + +int security_devicetree_setlabel(char *path, u32 sid) +{ + int ret = 0; + struct ocontext *c; + struct ocontext **pcurr; + struct ocontext *add = NULL; + + if ( sid ) + { + add = xzalloc(struct ocontext); + if ( add == NULL ) + { + xfree(path); + return -ENOMEM; + } + add->sid[0] = sid; + add->u.name = path; + } + else + { + ret = -ENOENT; + } + + POLICY_WRLOCK; + + pcurr = &policydb.ocontexts[OCON_DTREE]; + c = *pcurr; + while ( c ) + { + if ( strcmp(c->u.name, path) == 0 ) + { + if ( sid ) + { + ret = -EEXIST; + break; + } + else + { + *pcurr = c->next; + xfree(c->u.name); + xfree(c); + ret = 0; + break; + } + } + pcurr = &c->next; + c = *pcurr; + } + + if ( add && ret == 0 ) + { + add->next = policydb.ocontexts[OCON_DTREE]; + policydb.ocontexts[OCON_DTREE] = add; + add = NULL; + path = NULL; + } + + POLICY_WRUNLOCK; + + xfree(add); + xfree(path); + return ret; +} -- 2.1.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |