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;
};
......
......@@ -4,17 +4,17 @@
* Authors : Stephen Smalley, <sds@epoch.ncsc.mil>
* James Morris <jmorris@redhat.com>
*
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* Updated: 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,
* as published by the Free Software Foundation.
* 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
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* 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
* the Free Software Foundation, version 2.
......@@ -64,18 +64,30 @@ int ss_initialized = 0;
*/
static u32 latest_granting = 0;
/* Forward declarations. */
int context_struct_to_string(struct context *context, char **scontext,
u32 *scontext_len);
/*
* Return the boolean value of a constraint expression
* when it is applied to the specified source and target
* security contexts.
*
* xcontext is a special beast... It is used by the validatetrans rules
* only. For these rules, scontext is the context before the transition,
* tcontext is the context after the transition, and xcontext is the context
* of the process performing the transition. All other callers of
* constraint_expr_eval should pass in NULL for xcontext.
*/
static int constraint_expr_eval(struct context *scontext,
int constraint_expr_eval(struct context *scontext,
struct context *tcontext,
struct context *xcontext,
struct constraint_expr *cexpr)
{
u32 val1, val2;
struct context *c;
struct role_datum *r1, *r2;
struct mls_level *l1, *l2;
struct constraint_expr *e;
int s[CEXPR_MAXDEPTH];
int sp = -1;
......@@ -132,6 +144,52 @@ static int constraint_expr_eval(struct context *scontext,
break;
}
break;
case CEXPR_L1L2:
l1 = &(scontext->range.level[0]);
l2 = &(tcontext->range.level[0]);
goto mls_ops;
case CEXPR_L1H2:
l1 = &(scontext->range.level[0]);
l2 = &(tcontext->range.level[1]);
goto mls_ops;
case CEXPR_H1L2:
l1 = &(scontext->range.level[1]);
l2 = &(tcontext->range.level[0]);
goto mls_ops;
case CEXPR_H1H2:
l1 = &(scontext->range.level[1]);
l2 = &(tcontext->range.level[1]);
goto mls_ops;
case CEXPR_L1H1:
l1 = &(scontext->range.level[0]);
l2 = &(scontext->range.level[1]);
goto mls_ops;
case CEXPR_L2H2:
l1 = &(tcontext->range.level[0]);
l2 = &(tcontext->range.level[1]);
goto mls_ops;
mls_ops:
switch (e->op) {
case CEXPR_EQ:
s[++sp] = mls_level_eq(l1, l2);
continue;
case CEXPR_NEQ:
s[++sp] = !mls_level_eq(l1, l2);
continue;
case CEXPR_DOM:
s[++sp] = mls_level_dom(l1, l2);
continue;
case CEXPR_DOMBY:
s[++sp] = mls_level_dom(l2, l1);
continue;
case CEXPR_INCOMP:
s[++sp] = mls_level_incomp(l2, l1);
continue;
default:
BUG();
return 0;
}
break;
default:
BUG();
return 0;
......@@ -155,6 +213,13 @@ static int constraint_expr_eval(struct context *scontext,
c = scontext;
if (e->attr & CEXPR_TARGET)
c = tcontext;
else if (e->attr & CEXPR_XTARGET) {
c = xcontext;
if (!c) {
BUG();
return 0;
}
}
if (e->attr & CEXPR_USER)
val1 = c->user;
else if (e->attr & CEXPR_ROLE)
......@@ -252,17 +317,13 @@ static int context_struct_compute_av(struct context *scontext,
cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
/*
* Remove any permissions prohibited by the MLS policy.
*/
mls_compute_av(scontext, tcontext, tclass_datum, &avd->allowed);
/*
* Remove any permissions prohibited by a constraint.
* Remove any permissions prohibited by a constraint (this includes
* the MLS policy).
*/
constraint = tclass_datum->constraints;
while (constraint) {
if ((constraint->permissions & (avd->allowed)) &&
!constraint_expr_eval(scontext, tcontext,
!constraint_expr_eval(scontext, tcontext, NULL,
constraint->expr)) {
avd->allowed = (avd->allowed) & ~(constraint->permissions);
}
......@@ -290,6 +351,108 @@ static int context_struct_compute_av(struct context *scontext,
return 0;
}
static int security_validtrans_handle_fail(struct context *ocontext,
struct context *ncontext,
struct context *tcontext,
u16 tclass)
{
char *o = NULL, *n = NULL, *t = NULL;
u32 olen, nlen, tlen;
if (context_struct_to_string(ocontext, &o, &olen) < 0)
goto out;
if (context_struct_to_string(ncontext, &n, &nlen) < 0)
goto out;
if (context_struct_to_string(tcontext, &t, &tlen) < 0)
goto out;
audit_log(current->audit_context,
"security_validate_transition: denied for"
" oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
o, n, t, policydb.p_class_val_to_name[tclass-1]);
out:
kfree(o);
kfree(n);
kfree(t);
if (!selinux_enforcing)
return 0;
return -EPERM;
}
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
u16 tclass)
{
struct context *ocontext;
struct context *ncontext;
struct context *tcontext;
struct class_datum *tclass_datum;
struct constraint_node *constraint;
int rc = 0;
if (!ss_initialized)
return 0;
POLICY_RDLOCK;
/*
* Remap extended Netlink classes for old policy versions.
* Do this here rather than socket_type_to_security_class()
* in case a newer policy version is loaded, allowing sockets
* to remain in the correct class.
*/
if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS)
if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET &&
tclass <= SECCLASS_NETLINK_DNRT_SOCKET)
tclass = SECCLASS_NETLINK_SOCKET;
if (!tclass || tclass > policydb.p_classes.nprim) {
printk(KERN_ERR "security_validate_transition: "
"unrecognized class %d\n", tclass);
rc = -EINVAL;
goto out;
}
tclass_datum = policydb.class_val_to_struct[tclass - 1];
ocontext = sidtab_search(&sidtab, oldsid);
if (!ocontext) {
printk(KERN_ERR "security_validate_transition: "
" unrecognized SID %d\n", oldsid);
rc = -EINVAL;
goto out;
}
ncontext = sidtab_search(&sidtab, newsid);
if (!ncontext) {
printk(KERN_ERR "security_validate_transition: "
" unrecognized SID %d\n", newsid);
rc = -EINVAL;
goto out;
}
tcontext = sidtab_search(&sidtab, tasksid);
if (!tcontext) {
printk(KERN_ERR "security_validate_transition: "
" unrecognized SID %d\n", tasksid);
rc = -EINVAL;
goto out;
}
constraint = tclass_datum->validatetrans;
while (constraint) {
if (!constraint_expr_eval(ocontext, ncontext, tcontext,
constraint->expr)) {
rc = security_validtrans_handle_fail(ocontext, ncontext,
tcontext, tclass);
goto out;
}
constraint = constraint->next;
}
out:
POLICY_RDUNLOCK;
return rc;
}
/**
* security_compute_av - Compute access vector decisions.
* @ssid: source security identifier
......@@ -366,7 +529,7 @@ int context_struct_to_string(struct context *context, char **scontext, u32 *scon
*scontext_len += mls_compute_context_len(context);
/* Allocate space for the context; caller must free this space. */
scontextp = kmalloc(*scontext_len+1,GFP_ATOMIC);
scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
if (!scontextp) {
return -ENOMEM;
}
......@@ -375,17 +538,16 @@ int context_struct_to_string(struct context *context, char **scontext, u32 *scon
/*
* Copy the user name, role name and type name into the context.
*/
sprintf(scontextp, "%s:%s:%s:",
sprintf(scontextp, "%s:%s:%s",
policydb.p_user_val_to_name[context->user - 1],
policydb.p_role_val_to_name[context->role - 1],
policydb.p_type_val_to_name[context->type - 1]);
scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
1 + strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
mls_sid_to_context(context, &scontextp);
scontextp--;
*scontextp = 0;
return 0;
......@@ -715,23 +877,8 @@ static int security_compute_sid(u32 ssid,
}
}
}
if (!type_change && !roletr) {
/* No change in process role or type. */
*out_sid = ssid;
goto out_unlock;
}
break;
default:
if (!type_change &&
(newcontext.user == tcontext->user) &&
mls_context_cmp(scontext, tcontext)) {
/* No change in object type, owner,
or MLS attributes. */
*out_sid = tsid;
goto out_unlock;
}
break;
}
......@@ -1363,7 +1510,10 @@ int security_get_user_sids(u32 fromsid,
if (!ebitmap_get_bit(&role->types, j))
continue;
usercon.type = j+1;
mls_for_user_ranges(user,usercon) {
if (mls_setup_user_range(fromcon, user, &usercon))
continue;
rc = context_struct_compute_av(fromcon, &usercon,
SECCLASS_PROCESS,
PROCESS__TRANSITION,
......@@ -1392,8 +1542,6 @@ int security_get_user_sids(u32 fromsid,
mysids[mynel++] = sid;
}
}
mls_end_user_ranges;
}
}
*sids = mysids;
......
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