|
[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 |