struct netlbl_lsm_secattr;
extern int selinux_enabled;
-extern int selinux_mls_enabled;
/* Policy capabilities */
enum {
/* 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);
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);
}
{
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)
{
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)
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) &&
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);
struct ebitmap *e;
struct ebitmap_node *node;
- if (!selinux_mls_enabled)
+ if (!policydb.mls_enabled)
return 0;
len = 1; /* for the beginning ":" */
struct ebitmap *e;
struct ebitmap_node *node;
- if (!selinux_mls_enabled)
+ if (!policydb.mls_enabled)
return;
scontextp = *scontext;
{
struct user_datum *usrdatum;
- if (!selinux_mls_enabled)
+ if (!p->mls_enabled)
return 1;
if (!mls_range_isvalid(p, &c->range))
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;
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
/*
* 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;
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]);
struct ebitmap_node *node;
int l, i;
- if (!selinux_mls_enabled)
+ if (!policydb.mls_enabled)
return 0;
for (l = 0; l < 2; l++) {
struct range_trans rtr;
struct mls_range *r;
- if (!selinux_mls_enabled)
+ if (!policydb.mls_enabled)
return 0;
switch (specified) {
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;
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;
{
int rc;
- if (!selinux_mls_enabled)
+ if (!policydb.mls_enabled)
return 0;
rc = ebitmap_netlbl_export(&context->range.level[0].cat,
{
int rc;
- if (!selinux_mls_enabled)
+ if (!policydb.mls_enabled)
return 0;
rc = ebitmap_netlbl_import(&context->range.level[0].cat,
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);
#define _SS_MLS_TYPES_H_
#include "security.h"
+#include "ebitmap.h"
struct mls_level {
u32 sens; /* sensitivity */
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));
}
};
#endif
-int selinux_mls_enabled;
-
static unsigned int symtab_sizes[SYM_NUM] = {
2,
32,
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");
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;
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;
}
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 "
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);
#include "symtab.h"
#include "avtab.h"
#include "sidtab.h"
+#include "ebitmap.h"
+#include "mls_types.h"
#include "context.h"
#include "constraint.h"
/* The policy database */
struct policydb {
+ int mls_enabled;
+
/* symbol tables */
struct symtab symtab[SYM_NUM];
#define p_commons symtab[SYM_COMMONS]
*
* 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.
}
}
+int security_mls_enabled(void)
+{
+ return policydb.mls_enabled;
+}
/*
* Return the boolean value of a constraint expression
{
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;
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)) {
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");
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);
u32 len;
int rc = 0;
- if (!ss_initialized || !selinux_mls_enabled) {
+ if (!ss_initialized || !policydb.mls_enabled) {
*new_sid = sid;
goto out;
}
/* 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;
}