forked from Minki/linux
selinux: allow MLS->non-MLS and vice versa upon policy reload
Allow runtime switching between different policy types (e.g. from a MLS/MCS policy to a non-MLS/non-MCS policy or viceversa). Signed-off-by: Guido Trentalancia <guido@trentalancia.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
42596eafdd
commit
0719aaf5ea
@ -57,7 +57,6 @@
|
||||
struct netlbl_lsm_secattr;
|
||||
|
||||
extern int selinux_enabled;
|
||||
extern int selinux_mls_enabled;
|
||||
|
||||
/* Policy capabilities */
|
||||
enum {
|
||||
@ -80,6 +79,8 @@ extern int selinux_policycap_openperm;
|
||||
/* limitation of boundary depth */
|
||||
#define POLICYDB_BOUNDS_MAXDEPTH 4
|
||||
|
||||
int security_mls_enabled(void);
|
||||
|
||||
int security_load_policy(void *data, size_t len);
|
||||
|
||||
int security_policycap_supported(unsigned int req_cap);
|
||||
|
@ -282,7 +282,8 @@ static ssize_t sel_read_mls(struct file *filp, char __user *buf,
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled);
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
|
||||
security_mls_enabled());
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
}
|
||||
|
||||
|
@ -41,9 +41,6 @@ static inline int mls_context_cpy(struct context *dst, struct context *src)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
return 0;
|
||||
|
||||
dst->range.level[0].sens = src->range.level[0].sens;
|
||||
rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
|
||||
if (rc)
|
||||
@ -64,9 +61,6 @@ static inline int mls_context_cpy_low(struct context *dst, struct context *src)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
return 0;
|
||||
|
||||
dst->range.level[0].sens = src->range.level[0].sens;
|
||||
rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
|
||||
if (rc)
|
||||
@ -82,9 +76,6 @@ out:
|
||||
|
||||
static inline int mls_context_cmp(struct context *c1, struct context *c2)
|
||||
{
|
||||
if (!selinux_mls_enabled)
|
||||
return 1;
|
||||
|
||||
return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
|
||||
ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
|
||||
(c1->range.level[1].sens == c2->range.level[1].sens) &&
|
||||
@ -93,9 +84,6 @@ static inline int mls_context_cmp(struct context *c1, struct context *c2)
|
||||
|
||||
static inline void mls_context_destroy(struct context *c)
|
||||
{
|
||||
if (!selinux_mls_enabled)
|
||||
return;
|
||||
|
||||
ebitmap_destroy(&c->range.level[0].cat);
|
||||
ebitmap_destroy(&c->range.level[1].cat);
|
||||
mls_context_init(c);
|
||||
|
@ -39,7 +39,7 @@ int mls_compute_context_len(struct context *context)
|
||||
struct ebitmap *e;
|
||||
struct ebitmap_node *node;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
if (!policydb.mls_enabled)
|
||||
return 0;
|
||||
|
||||
len = 1; /* for the beginning ":" */
|
||||
@ -93,7 +93,7 @@ void mls_sid_to_context(struct context *context,
|
||||
struct ebitmap *e;
|
||||
struct ebitmap_node *node;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
if (!policydb.mls_enabled)
|
||||
return;
|
||||
|
||||
scontextp = *scontext;
|
||||
@ -200,7 +200,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
|
||||
{
|
||||
struct user_datum *usrdatum;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
if (!p->mls_enabled)
|
||||
return 1;
|
||||
|
||||
if (!mls_range_isvalid(p, &c->range))
|
||||
@ -253,7 +253,7 @@ int mls_context_to_sid(struct policydb *pol,
|
||||
struct cat_datum *catdatum, *rngdatum;
|
||||
int l, rc = -EINVAL;
|
||||
|
||||
if (!selinux_mls_enabled) {
|
||||
if (!pol->mls_enabled) {
|
||||
if (def_sid != SECSID_NULL && oldc)
|
||||
*scontext += strlen(*scontext)+1;
|
||||
return 0;
|
||||
@ -387,7 +387,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
|
||||
char *tmpstr, *freestr;
|
||||
int rc;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
if (!policydb.mls_enabled)
|
||||
return -EINVAL;
|
||||
|
||||
/* we need freestr because mls_context_to_sid will change
|
||||
@ -407,7 +407,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
|
||||
/*
|
||||
* Copies the MLS range `range' into `context'.
|
||||
*/
|
||||
static inline int mls_range_set(struct context *context,
|
||||
int mls_range_set(struct context *context,
|
||||
struct mls_range *range)
|
||||
{
|
||||
int l, rc = 0;
|
||||
@ -427,7 +427,7 @@ static inline int mls_range_set(struct context *context,
|
||||
int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
|
||||
struct context *usercon)
|
||||
{
|
||||
if (selinux_mls_enabled) {
|
||||
if (policydb.mls_enabled) {
|
||||
struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
|
||||
struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
|
||||
struct mls_level *user_low = &(user->range.level[0]);
|
||||
@ -477,7 +477,7 @@ int mls_convert_context(struct policydb *oldp,
|
||||
struct ebitmap_node *node;
|
||||
int l, i;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
if (!policydb.mls_enabled)
|
||||
return 0;
|
||||
|
||||
for (l = 0; l < 2; l++) {
|
||||
@ -516,7 +516,7 @@ int mls_compute_sid(struct context *scontext,
|
||||
struct range_trans rtr;
|
||||
struct mls_range *r;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
if (!policydb.mls_enabled)
|
||||
return 0;
|
||||
|
||||
switch (specified) {
|
||||
@ -559,7 +559,7 @@ int mls_compute_sid(struct context *scontext,
|
||||
void mls_export_netlbl_lvl(struct context *context,
|
||||
struct netlbl_lsm_secattr *secattr)
|
||||
{
|
||||
if (!selinux_mls_enabled)
|
||||
if (!policydb.mls_enabled)
|
||||
return;
|
||||
|
||||
secattr->attr.mls.lvl = context->range.level[0].sens - 1;
|
||||
@ -579,7 +579,7 @@ void mls_export_netlbl_lvl(struct context *context,
|
||||
void mls_import_netlbl_lvl(struct context *context,
|
||||
struct netlbl_lsm_secattr *secattr)
|
||||
{
|
||||
if (!selinux_mls_enabled)
|
||||
if (!policydb.mls_enabled)
|
||||
return;
|
||||
|
||||
context->range.level[0].sens = secattr->attr.mls.lvl + 1;
|
||||
@ -601,7 +601,7 @@ int mls_export_netlbl_cat(struct context *context,
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
if (!policydb.mls_enabled)
|
||||
return 0;
|
||||
|
||||
rc = ebitmap_netlbl_export(&context->range.level[0].cat,
|
||||
@ -629,7 +629,7 @@ int mls_import_netlbl_cat(struct context *context,
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!selinux_mls_enabled)
|
||||
if (!policydb.mls_enabled)
|
||||
return 0;
|
||||
|
||||
rc = ebitmap_netlbl_import(&context->range.level[0].cat,
|
||||
|
@ -39,6 +39,8 @@ int mls_context_to_sid(struct policydb *p,
|
||||
|
||||
int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);
|
||||
|
||||
int mls_range_set(struct context *context, struct mls_range *range);
|
||||
|
||||
int mls_convert_context(struct policydb *oldp,
|
||||
struct policydb *newp,
|
||||
struct context *context);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define _SS_MLS_TYPES_H_
|
||||
|
||||
#include "security.h"
|
||||
#include "ebitmap.h"
|
||||
|
||||
struct mls_level {
|
||||
u32 sens; /* sensitivity */
|
||||
@ -27,18 +28,12 @@ struct mls_range {
|
||||
|
||||
static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
|
||||
{
|
||||
if (!selinux_mls_enabled)
|
||||
return 1;
|
||||
|
||||
return ((l1->sens == l2->sens) &&
|
||||
ebitmap_cmp(&l1->cat, &l2->cat));
|
||||
}
|
||||
|
||||
static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
|
||||
{
|
||||
if (!selinux_mls_enabled)
|
||||
return 1;
|
||||
|
||||
return ((l1->sens >= l2->sens) &&
|
||||
ebitmap_contains(&l1->cat, &l2->cat));
|
||||
}
|
||||
|
@ -52,8 +52,6 @@ static char *symtab_name[SYM_NUM] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
int selinux_mls_enabled;
|
||||
|
||||
static unsigned int symtab_sizes[SYM_NUM] = {
|
||||
2,
|
||||
32,
|
||||
@ -455,7 +453,7 @@ static int policydb_index_others(struct policydb *p)
|
||||
|
||||
printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
|
||||
p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
|
||||
if (selinux_mls_enabled)
|
||||
if (p->mls_enabled)
|
||||
printk(", %d sens, %d cats", p->p_levels.nprim,
|
||||
p->p_cats.nprim);
|
||||
printk("\n");
|
||||
@ -1717,14 +1715,12 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
int i, j, rc;
|
||||
__le32 buf[4];
|
||||
u32 nodebuf[8];
|
||||
u32 len, len2, config, nprim, nel, nel2;
|
||||
u32 len, len2, nprim, nel, nel2;
|
||||
char *policydb_str;
|
||||
struct policydb_compat_info *info;
|
||||
struct range_trans *rt;
|
||||
struct mls_range *r;
|
||||
|
||||
config = 0;
|
||||
|
||||
rc = policydb_init(p);
|
||||
if (rc)
|
||||
goto out;
|
||||
@ -1772,7 +1768,7 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
kfree(policydb_str);
|
||||
policydb_str = NULL;
|
||||
|
||||
/* Read the version, config, and table sizes. */
|
||||
/* Read the version and table sizes. */
|
||||
rc = next_entry(buf, fp, sizeof(u32)*4);
|
||||
if (rc < 0)
|
||||
goto bad;
|
||||
@ -1787,13 +1783,7 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
}
|
||||
|
||||
if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
|
||||
if (ss_initialized && !selinux_mls_enabled) {
|
||||
printk(KERN_ERR "SELinux: Cannot switch between non-MLS"
|
||||
" and MLS policies\n");
|
||||
goto bad;
|
||||
}
|
||||
selinux_mls_enabled = 1;
|
||||
config |= POLICYDB_CONFIG_MLS;
|
||||
p->mls_enabled = 1;
|
||||
|
||||
if (p->policyvers < POLICYDB_VERSION_MLS) {
|
||||
printk(KERN_ERR "SELinux: security policydb version %d "
|
||||
@ -1801,12 +1791,6 @@ int policydb_read(struct policydb *p, void *fp)
|
||||
p->policyvers);
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
if (ss_initialized && selinux_mls_enabled) {
|
||||
printk(KERN_ERR "SELinux: Cannot switch between MLS and"
|
||||
" non-MLS policies\n");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
|
||||
p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "symtab.h"
|
||||
#include "avtab.h"
|
||||
#include "sidtab.h"
|
||||
#include "ebitmap.h"
|
||||
#include "mls_types.h"
|
||||
#include "context.h"
|
||||
#include "constraint.h"
|
||||
|
||||
@ -185,6 +187,8 @@ struct genfs {
|
||||
|
||||
/* The policy database */
|
||||
struct policydb {
|
||||
int mls_enabled;
|
||||
|
||||
/* symbol tables */
|
||||
struct symtab symtab[SYM_NUM];
|
||||
#define p_commons symtab[SYM_COMMONS]
|
||||
|
@ -26,6 +26,10 @@
|
||||
*
|
||||
* Added support for bounds domain and audit messaged on masked permissions
|
||||
*
|
||||
* Updated: Guido Trentalancia <guido@trentalancia.com>
|
||||
*
|
||||
* Added support for runtime switching of the policy type
|
||||
*
|
||||
* Copyright (C) 2008, 2009 NEC Corporation
|
||||
* Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
|
||||
* Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
|
||||
@ -232,6 +236,10 @@ static void map_decision(u16 tclass, struct av_decision *avd,
|
||||
}
|
||||
}
|
||||
|
||||
int security_mls_enabled(void)
|
||||
{
|
||||
return policydb.mls_enabled;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the boolean value of a constraint expression
|
||||
@ -1550,6 +1558,8 @@ static int convert_context(u32 key,
|
||||
{
|
||||
struct convert_context_args *args;
|
||||
struct context oldc;
|
||||
struct ocontext *oc;
|
||||
struct mls_range *range;
|
||||
struct role_datum *role;
|
||||
struct type_datum *typdatum;
|
||||
struct user_datum *usrdatum;
|
||||
@ -1620,9 +1630,39 @@ static int convert_context(u32 key,
|
||||
goto bad;
|
||||
c->type = typdatum->value;
|
||||
|
||||
rc = mls_convert_context(args->oldp, args->newp, c);
|
||||
if (rc)
|
||||
goto bad;
|
||||
/* Convert the MLS fields if dealing with MLS policies */
|
||||
if (args->oldp->mls_enabled && args->newp->mls_enabled) {
|
||||
rc = mls_convert_context(args->oldp, args->newp, c);
|
||||
if (rc)
|
||||
goto bad;
|
||||
} else if (args->oldp->mls_enabled && !args->newp->mls_enabled) {
|
||||
/*
|
||||
* Switching between MLS and non-MLS policy:
|
||||
* free any storage used by the MLS fields in the
|
||||
* context for all existing entries in the sidtab.
|
||||
*/
|
||||
mls_context_destroy(c);
|
||||
} else if (!args->oldp->mls_enabled && args->newp->mls_enabled) {
|
||||
/*
|
||||
* Switching between non-MLS and MLS policy:
|
||||
* ensure that the MLS fields of the context for all
|
||||
* existing entries in the sidtab are filled in with a
|
||||
* suitable default value, likely taken from one of the
|
||||
* initial SIDs.
|
||||
*/
|
||||
oc = args->newp->ocontexts[OCON_ISID];
|
||||
while (oc && oc->sid[0] != SECINITSID_UNLABELED)
|
||||
oc = oc->next;
|
||||
if (!oc) {
|
||||
printk(KERN_ERR "SELinux: unable to look up"
|
||||
" the initial SIDs list\n");
|
||||
goto bad;
|
||||
}
|
||||
range = &oc->context[0].range;
|
||||
rc = mls_range_set(c, range);
|
||||
if (rc)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Check the validity of the new context. */
|
||||
if (!policydb_context_isvalid(args->newp, c)) {
|
||||
@ -1718,6 +1758,12 @@ int security_load_policy(void *data, size_t len)
|
||||
if (policydb_read(&newpolicydb, fp))
|
||||
return -EINVAL;
|
||||
|
||||
/* If switching between different policy types, log MLS status */
|
||||
if (policydb.mls_enabled && !newpolicydb.mls_enabled)
|
||||
printk(KERN_INFO "SELinux: Disabling MLS support...\n");
|
||||
else if (!policydb.mls_enabled && newpolicydb.mls_enabled)
|
||||
printk(KERN_INFO "SELinux: Enabling MLS support...\n");
|
||||
|
||||
rc = policydb_load_isids(&newpolicydb, &newsidtab);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "SELinux: unable to load the initial SIDs\n");
|
||||
@ -1749,8 +1795,12 @@ int security_load_policy(void *data, size_t len)
|
||||
args.oldp = &policydb;
|
||||
args.newp = &newpolicydb;
|
||||
rc = sidtab_map(&newsidtab, convert_context, &args);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
printk(KERN_ERR "SELinux: unable to convert the internal"
|
||||
" representation of contexts in the new SID"
|
||||
" table\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Save the old policydb and SID table to free later. */
|
||||
memcpy(&oldpolicydb, &policydb, sizeof policydb);
|
||||
@ -2346,7 +2396,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
|
||||
u32 len;
|
||||
int rc = 0;
|
||||
|
||||
if (!ss_initialized || !selinux_mls_enabled) {
|
||||
if (!ss_initialized || !policydb.mls_enabled) {
|
||||
*new_sid = sid;
|
||||
goto out;
|
||||
}
|
||||
@ -2447,7 +2497,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
|
||||
/* we don't need to check ss_initialized here since the only way both
|
||||
* nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
|
||||
* security server was initialized and ss_initialized was true */
|
||||
if (!selinux_mls_enabled) {
|
||||
if (!policydb.mls_enabled) {
|
||||
*peer_sid = SECSID_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user