xsm: add device tree labeling support

This adds support in the hypervisor and policy build toolchain for
Xen/Flask policy version 30, 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@tycho.nsa.gov>
Tested-by: Julien Grall <julien.grall@linaro.org>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
Daniel De Graaf authored and Jan Beulich committed 2015-03-17 10:58:40 +01:00
1 parent 55d8c9c082
commit 525ee49e2c
7 files changed
+287 -42

No files matched your search

+14 -6
View File
@@ -20,21 +20,21 @@ MLS_CATS ?= 256
CHECKPOLICY ?= checkpolicy
M4 ?= m4
# Output security policy version. Leave unset to autodetect.
OUTPUT_POLICY ?= $(BEST_POLICY_VER)
########################################
#
# End of configuration options
#
########################################
# 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
# List of policy versions supported by the hypervisor
POLICY_VER_LIST_HV = 24 30
# policy source layout
POLDIR := policy
MODDIR := $(POLDIR)/modules
@@ -63,6 +63,14 @@ MOD_CONF := $(POLDIR)/modules.conf
# checkpolicy can use the #line directives provided by -s for error reporting:
M4PARAM := -D self_contained_policy -s
# The output of checkpolicy -V is "30 (compatibility range 30-15)", and the
# first word of the output is the maximum policy version supported.
CHECKPOLICY_VER_MAX := $(firstword $(shell $(CHECKPOLICY) -V))
# Find the highest version supported by both the hypervisor and checkpolicy
BEST_POLICY_VER := $(shell best=24; for ver in $(POLICY_VER_LIST_HV); do if test $$ver -le $(CHECKPOLICY_VER_MAX); then best=$$ver; fi; done; echo $$best)
CHECKPOLICY_PARAM := -t Xen -c $(OUTPUT_POLICY)
# enable MLS if requested.
+9
View File
@@ -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;
+28
View File
@@ -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
+12 -2
View File
@@ -30,10 +30,16 @@
#define POLICYDB_VERSION_POLCAP 22
#define POLICYDB_VERSION_PERMISSIVE 23
#define POLICYDB_VERSION_BOUNDARY 24
#define POLICYDB_VERSION_FILENAME_TRANS 25
#define POLICYDB_VERSION_ROLETRANS 26
#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27
#define POLICYDB_VERSION_DEFAULT_TYPE 28
#define POLICYDB_VERSION_CONSTRAINT_NAMES 29
#define POLICYDB_VERSION_XEN_DEVICETREE 30
/* 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_XEN_DEVICETREE
enum flask_bootparam_t {
FLASK_BOOTPARAM_PERMISSIVE,
@@ -82,6 +88,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 +104,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_ */
+112 -21
View File
@@ -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_XEN_DEVICETREE,
.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);
}
@@ -1040,8 +1046,8 @@ bad:
goto out;
}
static int read_cons_helper(struct constraint_node **nodep, int ncons,
int allowxtarget, void *fp)
static int read_cons_helper(struct policydb *p, struct constraint_node **nodep,
int ncons, int allowxtarget, void *fp)
{
struct constraint_node *c, *lc;
struct constraint_expr *e, *le;
@@ -1115,6 +1121,23 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
depth++;
if ( ebitmap_read(&e->names, fp) )
return -EINVAL;
if ( p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES )
{
struct ebitmap dummy;
ebitmap_init(&dummy);
if ( ebitmap_read(&dummy, fp) )
return -EINVAL;
ebitmap_destroy(&dummy);
ebitmap_init(&dummy);
if ( ebitmap_read(&dummy, fp) )
return -EINVAL;
ebitmap_destroy(&dummy);
rc = next_entry(buf, fp, sizeof(u32));
if ( rc < 0 )
return rc;
}
break;
default:
return -EINVAL;
@@ -1184,7 +1207,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
goto bad;
}
rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
rc = read_cons_helper(p, &cladatum->constraints, ncons, 0, fp);
if ( rc )
goto bad;
@@ -1195,11 +1218,27 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
if ( rc < 0 )
goto bad;
ncons = le32_to_cpu(buf[0]);
rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
rc = read_cons_helper(p, &cladatum->validatetrans, ncons, 1, fp);
if ( rc )
goto bad;
}
if ( p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS )
{
rc = next_entry(buf, fp, sizeof(u32) * 3);
if ( rc )
goto bad;
/* these values are ignored by Xen */
}
if ( p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE )
{
rc = next_entry(buf, fp, sizeof(u32) * 1);
if ( rc )
goto bad;
/* ignored by Xen */
}
rc = hashtab_insert(h, key, cladatum);
if ( rc )
goto bad;
@@ -1874,7 +1913,10 @@ int policydb_read(struct policydb *p, void *fp)
ltr->next = tr;
else
p->role_tr = tr;
rc = next_entry(buf, fp, sizeof(u32)*3);
if ( p->policyvers >= POLICYDB_VERSION_ROLETRANS )
rc = next_entry(buf, fp, sizeof(u32)*4);
else
rc = next_entry(buf, fp, sizeof(u32)*3);
if ( rc < 0 )
goto bad;
tr->role = le32_to_cpu(buf[0]);
@@ -1921,6 +1963,20 @@ int policydb_read(struct policydb *p, void *fp)
lra = ra;
}
if ( p->policyvers >= POLICYDB_VERSION_FILENAME_TRANS )
{
rc = next_entry(buf, fp, sizeof(u32));
if ( rc )
goto bad;
nel = le32_to_cpu(buf[0]);
if ( nel )
{
printk(KERN_ERR "Flask: unsupported genfs config data\n");
rc = -EINVAL;
goto bad;
}
}
rc = policydb_index_classes(p);
if ( rc )
goto bad;
@@ -1999,11 +2055,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_XEN_DEVICETREE )
{
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 +2091,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");
+4 -3
View File
@@ -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 */
+108 -10
View File
@@ -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,9 +2166,8 @@ 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",
__FUNCTION__, c->u.iomem.low_iomem,
c->u.iomem.high_iomem);
printk("%s: IO Memory overlap with entry %#"PRIx64" - %#"PRIx64"\n",
__FUNCTION__, c->u.iomem.low_iomem, c->u.iomem.high_iomem);
ret = -EEXIST;
break;
}
@@ -2188,7 +2222,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 +2251,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,8 +2277,8 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high )
}
}
printk("%s: ocontext not found: ioport %#x - %#x\n", __FUNCTION__,
low, high);
printk("%s: ocontext not found: ioport %#lx - %#lx\n",
__FUNCTION__, low, high);
ret = -ENOENT;
break;
@@ -2270,8 +2304,8 @@ int security_ocontext_del( u32 ocon, unsigned int low, unsigned int high )
}
}
printk("%s: ocontext not found: iomem %#x - %#x\n", __FUNCTION__,
low, high);
printk("%s: ocontext not found: iomem %#lx - %#lx\n",
__FUNCTION__, low, high);
ret = -ENOENT;
break;
@@ -2296,7 +2330,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 +2342,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;
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.