Commit d75f9d53 authored by dgoeddel@trustedcs.com's avatar dgoeddel@trustedcs.com Committed by Linus Torvalds

[PATCH] SELinux: enhanced MLS support

This patch replaces the original experimental Multi-Level Security (MLS)
implementation in SELinux with an enhanced MLS implementation contributed
by Trusted Computer Solutions (TCS).

The enhanced MLS implementation replaces the hardcoded MLS logic with a
flexible constraint-based system and replaces the compile-time option for
MLS support with a policy load-time enable based on whether MLS support was
enabled in the policy when it was built.

The latter change allows a single kernel and policy toolchain to support
both MLS and non-MLS policies.  Compatibility is still provided as usual
for existing policies.
Signed-off-by: default avatarStephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: default avatarJames Morris <jmorris@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b0234a62
......@@ -76,12 +76,3 @@ config SECURITY_SELINUX_AVC_STATS
/selinux/avc/cache_stats, which may be monitored via
tools such as avcstat.
config SECURITY_SELINUX_MLS
bool "NSA SELinux MLS policy (EXPERIMENTAL)"
depends on SECURITY_SELINUX && EXPERIMENTAL
default n
help
This enables the NSA SELinux Multi-Level Security (MLS) policy in
addition to the default RBAC/TE policy. This policy is
experimental and has not been configured for use. Unless you
specifically want to experiment with MLS, say N.
......@@ -10,6 +10,8 @@
*
* Copyright (C) 2001,2002 Networks Associates Technology, Inc.
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* <dgoeddel@trustedcs.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
......@@ -2211,6 +2213,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
if (rc)
return rc;
rc = security_validate_transition(isec->sid, newsid, tsec->sid,
isec->sclass);
if (rc)
return rc;
return avc_has_perm(newsid,
sbsec->sid,
SECCLASS_FILESYSTEM,
......
......@@ -21,10 +21,12 @@
#define POLICYDB_VERSION_BOOL 16
#define POLICYDB_VERSION_IPV6 17
#define POLICYDB_VERSION_NLCLASS 18
#define POLICYDB_VERSION_VALIDATETRANS 19
#define POLICYDB_VERSION_MLS 19
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_NLCLASS
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_MLS
#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
extern int selinux_enabled;
......@@ -32,11 +34,7 @@ extern int selinux_enabled;
#define selinux_enabled 1
#endif
#ifdef CONFIG_SECURITY_SELINUX_MLS
#define selinux_mls_enabled 1
#else
#define selinux_mls_enabled 0
#endif
extern int selinux_mls_enabled;
int security_load_policy(void * data, size_t len);
......@@ -79,6 +77,9 @@ int security_netif_sid(char *name, u32 *if_sid,
int security_node_sid(u16 domain, void *addr, u32 addrlen,
u32 *out_sid);
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
u16 tclass);
#define SECURITY_FS_USE_XATTR 1 /* use xattr */
#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
#define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */
......
......@@ -5,7 +5,5 @@
EXTRA_CFLAGS += -Isecurity/selinux/include
obj-y := ss.o
ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o
ss-$(CONFIG_SECURITY_SELINUX_MLS) += mls.o
ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o
......@@ -31,6 +31,13 @@ struct constraint_expr {
#define CEXPR_ROLE 2 /* role */
#define CEXPR_TYPE 4 /* type */
#define CEXPR_TARGET 8 /* target if set, source otherwise */
#define CEXPR_XTARGET 16 /* special 3rd target for validatetrans rule */
#define CEXPR_L1L2 32 /* low level 1 vs. low level 2 */
#define CEXPR_L1H2 64 /* low level 1 vs. high level 2 */
#define CEXPR_H1L2 128 /* high level 1 vs. low level 2 */
#define CEXPR_H1H2 256 /* high level 1 vs. high level 2 */
#define CEXPR_L1H1 512 /* low level 1 vs. high level 1 */
#define CEXPR_L2H2 1024 /* low level 2 vs. high level 2 */
u32 attr; /* attribute */
#define CEXPR_EQ 1 /* == or eq */
......
......@@ -17,6 +17,7 @@
#include "ebitmap.h"
#include "mls_types.h"
#include "security.h"
/*
* A security context consists of an authenticated user
......@@ -26,13 +27,9 @@ struct context {
u32 user;
u32 role;
u32 type;
#ifdef CONFIG_SECURITY_SELINUX_MLS
struct mls_range range;
#endif
};
#ifdef CONFIG_SECURITY_SELINUX_MLS
static inline void mls_context_init(struct context *c)
{
memset(&c->range, 0, sizeof(c->range));
......@@ -42,6 +39,9 @@ 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)
......@@ -57,6 +57,9 @@ static inline int mls_context_cpy(struct context *dst, struct context *src)
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) &&
......@@ -65,27 +68,14 @@ 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);
}
#else
static inline void mls_context_init(struct context *c)
{ }
static inline int mls_context_cpy(struct context *dst, struct context *src)
{ return 0; }
static inline int mls_context_cmp(struct context *c1, struct context *c2)
{ return 1; }
static inline void mls_context_destroy(struct context *c)
{ }
#endif
static inline void context_init(struct context *c)
{
memset(c, 0, sizeof(*c));
......
This diff is collapsed.
......@@ -3,21 +3,22 @@
*
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
/*
* Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
*
* Support for enhanced MLS infrastructure.
*
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
*/
#ifndef _SS_MLS_H_
#define _SS_MLS_H_
#include "context.h"
#include "policydb.h"
#ifdef CONFIG_SECURITY_SELINUX_MLS
void mls_compute_av(struct context *scontext,
struct context *tcontext,
struct class_datum *tclass,
u32 *allowed);
int mls_compute_context_len(struct context *context);
int mls_sid_to_context(struct context *context, char **scontext);
void mls_sid_to_context(struct context *context, char **scontext);
int mls_context_isvalid(struct policydb *p, struct context *c);
int mls_context_to_sid(char oldc,
......@@ -34,66 +35,8 @@ int mls_compute_sid(struct context *scontext,
u32 specified,
struct context *newcontext);
int sens_index(void *key, void *datum, void *datap);
int cat_index(void *key, void *datum, void *datap);
int sens_destroy(void *key, void *datum, void *p);
int cat_destroy(void *key, void *datum, void *p);
int sens_read(struct policydb *p, struct hashtab *h, void *fp);
int cat_read(struct policydb *p, struct hashtab *h, void *fp);
#define mls_for_user_ranges(user, usercon) { \
struct mls_range_list *__ranges; \
for (__ranges = user->ranges; __ranges; __ranges = __ranges->next) { \
usercon.range = __ranges->range;
#define mls_end_user_ranges } }
#define mls_symtab_names "levels", "categories",
#define mls_symtab_sizes 16, 16,
#define mls_index_f sens_index, cat_index,
#define mls_destroy_f sens_destroy, cat_destroy,
#define mls_read_f sens_read, cat_read,
#define mls_write_f sens_write, cat_write,
#define mls_policydb_index_others(p) printk(", %d levels", p->nlevels);
#define mls_set_config(config) config |= POLICYDB_CONFIG_MLS
void mls_user_destroy(struct user_datum *usrdatum);
int mls_read_range(struct context *c, void *fp);
int mls_read_perm(struct perm_datum *perdatum, void *fp);
int mls_read_class(struct class_datum *cladatum, void *fp);
int mls_read_user(struct user_datum *usrdatum, void *fp);
int mls_read_nlevels(struct policydb *p, void *fp);
int mls_read_trusted(struct policydb *p, void *fp);
#else
#define mls_compute_av(scontext, tcontext, tclass_datum, allowed)
#define mls_compute_context_len(context) 0
#define mls_sid_to_context(context, scontextpp)
#define mls_context_isvalid(p, c) 1
#define mls_context_to_sid(oldc, context_str, context) 0
#define mls_convert_context(oldp, newp, c) 0
#define mls_compute_sid(scontext, tcontext, tclass, specified, newcontextp) 0
#define mls_for_user_ranges(user, usercon)
#define mls_end_user_ranges
#define mls_symtab_names
#define mls_symtab_sizes
#define mls_index_f
#define mls_destroy_f
#define mls_read_f
#define mls_write_f
#define mls_policydb_index_others(p)
#define mls_set_config(config)
#define mls_user_destroy(usrdatum)
#define mls_read_range(c, fp) 0
#define mls_read_perm(p, fp) 0
#define mls_read_class(c, fp) 0
#define mls_read_user(u, fp) 0
#define mls_read_nlevels(p, fp) 0
#define mls_read_trusted(p, fp) 0
#endif
int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
struct context *usercon);
#endif /* _SS_MLS_H */
......@@ -3,9 +3,19 @@
*
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
/*
* Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
*
* Support for enhanced MLS infrastructure.
*
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
*/
#ifndef _SS_MLS_TYPES_H_
#define _SS_MLS_TYPES_H_
#include "security.h"
struct mls_level {
u32 sens; /* sensitivity */
struct ebitmap cat; /* category set */
......@@ -15,44 +25,32 @@ struct mls_range {
struct mls_level level[2]; /* low == level[0], high == level[1] */
};
struct mls_range_list {
struct mls_range range;
struct mls_range_list *next;
};
static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
{
if (!selinux_mls_enabled)
return 1;
#define MLS_RELATION_DOM 1 /* source dominates */
#define MLS_RELATION_DOMBY 2 /* target dominates */
#define MLS_RELATION_EQ 4 /* source and target are equivalent */
#define MLS_RELATION_INCOMP 8 /* source and target are incomparable */
#define mls_level_eq(l1,l2) \
(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat,&(l2).cat))
#define mls_level_relation(l1,l2) ( \
(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat,&(l2).cat)) ? \
MLS_RELATION_EQ : \
(((l1).sens >= (l2).sens) && ebitmap_contains(&(l1).cat, &(l2).cat)) ? \
MLS_RELATION_DOM : \
(((l2).sens >= (l1).sens) && ebitmap_contains(&(l2).cat, &(l1).cat)) ? \
MLS_RELATION_DOMBY : \
MLS_RELATION_INCOMP )
#define mls_range_contains(r1,r2) \
((mls_level_relation((r1).level[0], (r2).level[0]) & \
(MLS_RELATION_EQ | MLS_RELATION_DOMBY)) && \
(mls_level_relation((r1).level[1], (r2).level[1]) & \
(MLS_RELATION_EQ | MLS_RELATION_DOM)))
return ((l1->sens == l2->sens) &&
ebitmap_cmp(&l1->cat, &l2->cat));
}
/*
* Every access vector permission is mapped to a set of MLS base
* permissions, based on the flow properties of the corresponding
* operation.
*/
struct mls_perms {
u32 read; /* permissions that map to `read' */
u32 readby; /* permissions that map to `readby' */
u32 write; /* permissions that map to `write' */
u32 writeby; /* permissions that map to `writeby' */
};
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));
}
#define mls_level_incomp(l1, l2) \
(!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1)))
#define mls_level_between(l1, l2, l3) \
(mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1)))
#define mls_range_contains(r1, r2) \
(mls_level_dom(&(r2).level[0], &(r1).level[0]) && \
mls_level_dom(&(r1).level[1], &(r2).level[1]))
#endif /* _SS_MLS_TYPES_H_ */
This diff is collapsed.
......@@ -5,10 +5,16 @@
* Author : Stephen Smalley, <sds@epoch.ncsc.mil>
*/
/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
/*
* Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
*
* Support for enhanced MLS infrastructure.
*
* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
*
* Added conditional policy language extensions
*
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2004 Tresys Technology, LLC
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -34,13 +40,6 @@
/* Permission attributes */
struct perm_datum {
u32 value; /* permission bit + 1 */
#ifdef CONFIG_SECURITY_SELINUX_MLS
#define MLS_BASE_READ 1 /* MLS base permission `read' */
#define MLS_BASE_WRITE 2 /* MLS base permission `write' */
#define MLS_BASE_READBY 4 /* MLS base permission `readby' */
#define MLS_BASE_WRITEBY 8 /* MLS base permission `writeby' */
u32 base_perms; /* MLS base permission mask */
#endif
};
/* Attributes of a common prefix for access vectors */
......@@ -56,9 +55,7 @@ struct class_datum {
struct common_datum *comdatum; /* common datum */
struct symtab permissions; /* class-specific permission symbol table */
struct constraint_node *constraints; /* constraints on class permissions */
#ifdef CONFIG_SECURITY_SELINUX_MLS
struct mls_perms mlsperms; /* MLS base permission masks */
#endif
struct constraint_node *validatetrans; /* special transition rules */
};
/* Role attributes */
......@@ -91,13 +88,11 @@ struct type_datum {
struct user_datum {
u32 value; /* internal user value */
struct ebitmap roles; /* set of authorized roles for user */
#ifdef CONFIG_SECURITY_SELINUX_MLS
struct mls_range_list *ranges; /* list of authorized MLS ranges for user */
#endif
struct mls_range range; /* MLS range (min - max) for user */
struct mls_level dfltlevel; /* default login MLS level for user */
};
#ifdef CONFIG_SECURITY_SELINUX_MLS
/* Sensitivity attributes */
struct level_datum {
struct mls_level *level; /* sensitivity and associated categories */
......@@ -109,7 +104,13 @@ struct cat_datum {
u32 value; /* internal category bit + 1 */
unsigned char isalias; /* is this category an alias for another? */
};
#endif
struct range_trans {
u32 dom; /* current process domain */
u32 type; /* program executable type */
struct mls_range range; /* new range */
struct range_trans *next;
};
/* Boolean data type */
struct cond_bool_datum {
......@@ -164,15 +165,10 @@ struct genfs {
#define SYM_ROLES 2
#define SYM_TYPES 3
#define SYM_USERS 4
#ifdef CONFIG_SECURITY_SELINUX_MLS
#define SYM_LEVELS 5
#define SYM_CATS 6
#define SYM_BOOLS 7
#define SYM_NUM 8
#else
#define SYM_BOOLS 5
#define SYM_NUM 6
#endif
#define SYM_LEVELS 6
#define SYM_CATS 7
#define SYM_NUM 8
/* object context array indices */
#define OCON_ISID 0 /* initial SIDs */
......@@ -193,9 +189,9 @@ struct policydb {
#define p_roles symtab[SYM_ROLES]
#define p_types symtab[SYM_TYPES]
#define p_users symtab[SYM_USERS]
#define p_bools symtab[SYM_BOOLS]
#define p_levels symtab[SYM_LEVELS]
#define p_cats symtab[SYM_CATS]
#define p_bools symtab[SYM_BOOLS]
/* symbol names indexed by (value - 1) */
char **sym_val_to_name[SYM_NUM];
......@@ -204,9 +200,9 @@ struct policydb {
#define p_role_val_to_name sym_val_to_name[SYM_ROLES]
#define p_type_val_to_name sym_val_to_name[SYM_TYPES]
#define p_user_val_to_name sym_val_to_name[SYM_USERS]
#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
#define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
#define p_cat_val_to_name sym_val_to_name[SYM_CATS]
#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
/* class, role, and user attributes indexed by (value - 1) */
struct class_datum **class_val_to_struct;
......@@ -238,14 +234,8 @@ struct policydb {
fixed labeling behavior. */
struct genfs *genfs;
#ifdef CONFIG_SECURITY_SELINUX_MLS
/* number of legitimate MLS levels */
u32 nlevels;
struct ebitmap trustedreaders;
struct ebitmap trustedwriters;
struct ebitmap trustedobjects;
#endif
/* range transitions */
struct range_trans *range_tr;
unsigned int policyvers;
};
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment