diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2018-03-01 18:48:02 -0500 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2018-03-01 18:48:02 -0500 |
commit | aa8e712cee93d520e96a2ca8e3a20f807c937e3f (patch) | |
tree | 5e2bdce92022ebb334bfa68b6a731b71ef86974d /security/selinux/ss | |
parent | 2572f5b4245abf2b4e5a86cabf65a50efda09aac (diff) |
selinux: wrap global selinux state
Define a selinux state structure (struct selinux_state) for
global SELinux state and pass it explicitly to all security server
functions. The public portion of the structure contains state
that is used throughout the SELinux code, such as the enforcing mode.
The structure also contains a pointer to a selinux_ss structure whose
definition is private to the security server and contains security
server specific state such as the policy database and SID table.
This change should have no effect on SELinux behavior or APIs
(userspace or LSM). It merely wraps SELinux state and passes it
explicitly as needed.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
[PM: minor fixups needed due to collisions with the SCTP patches]
Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'security/selinux/ss')
-rw-r--r-- | security/selinux/ss/avtab.c | 9 | ||||
-rw-r--r-- | security/selinux/ss/avtab.h | 3 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.c | 7 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.h | 3 | ||||
-rw-r--r-- | security/selinux/ss/hashtab.c | 8 | ||||
-rw-r--r-- | security/selinux/ss/hashtab.h | 4 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 72 | ||||
-rw-r--r-- | security/selinux/ss/mls.h | 38 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 1078 | ||||
-rw-r--r-- | security/selinux/ss/services.h | 24 | ||||
-rw-r--r-- | security/selinux/ss/status.c | 47 |
11 files changed, 727 insertions, 566 deletions
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 2c3c7d010d8a..a2c9148b0662 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -655,7 +655,8 @@ int avtab_write(struct policydb *p, struct avtab *a, void *fp) return rc; } -void avtab_cache_init(void) + +void __init avtab_cache_init(void) { avtab_node_cachep = kmem_cache_create("avtab_node", sizeof(struct avtab_node), @@ -664,9 +665,3 @@ void avtab_cache_init(void) sizeof(struct avtab_extended_perms), 0, SLAB_PANIC, NULL); } - -void avtab_cache_destroy(void) -{ - kmem_cache_destroy(avtab_node_cachep); - kmem_cache_destroy(avtab_xperms_cachep); -} diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 725853cadc42..0d652fad5319 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -114,9 +114,6 @@ struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key); struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); -void avtab_cache_init(void); -void avtab_cache_destroy(void); - #define MAX_AVTAB_HASH_BITS 16 #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index b6a78b09235c..5ae8c61b75bf 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -523,14 +523,9 @@ int ebitmap_write(struct ebitmap *e, void *fp) return 0; } -void ebitmap_cache_init(void) +void __init ebitmap_cache_init(void) { ebitmap_node_cachep = kmem_cache_create("ebitmap_node", sizeof(struct ebitmap_node), 0, SLAB_PANIC, NULL); } - -void ebitmap_cache_destroy(void) -{ - kmem_cache_destroy(ebitmap_node_cachep); -} diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h index edf4fa39c60a..6aa7cf6a2197 100644 --- a/security/selinux/ss/ebitmap.h +++ b/security/selinux/ss/ebitmap.h @@ -131,9 +131,6 @@ void ebitmap_destroy(struct ebitmap *e); int ebitmap_read(struct ebitmap *e, void *fp); int ebitmap_write(struct ebitmap *e, void *fp); -void ebitmap_cache_init(void); -void ebitmap_cache_destroy(void); - #ifdef CONFIG_NETLABEL int ebitmap_netlbl_export(struct ebitmap *ebmap, struct netlbl_lsm_catmap **catmap); diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c index fe25b3fb2154..ebfdaa31ee32 100644 --- a/security/selinux/ss/hashtab.c +++ b/security/selinux/ss/hashtab.c @@ -169,14 +169,10 @@ void hashtab_stat(struct hashtab *h, struct hashtab_info *info) info->slots_used = slots_used; info->max_chain_len = max_chain_len; } -void hashtab_cache_init(void) + +void __init hashtab_cache_init(void) { hashtab_node_cachep = kmem_cache_create("hashtab_node", sizeof(struct hashtab_node), 0, SLAB_PANIC, NULL); } - -void hashtab_cache_destroy(void) -{ - kmem_cache_destroy(hashtab_node_cachep); -} diff --git a/security/selinux/ss/hashtab.h b/security/selinux/ss/hashtab.h index 6183ee2a2e7a..3e3e42bfd150 100644 --- a/security/selinux/ss/hashtab.h +++ b/security/selinux/ss/hashtab.h @@ -85,8 +85,4 @@ int hashtab_map(struct hashtab *h, /* Fill info with some hash table statistics */ void hashtab_stat(struct hashtab *h, struct hashtab_info *info); -/* Use kmem_cache for hashtab_node */ -void hashtab_cache_init(void); -void hashtab_cache_destroy(void); - #endif /* _SS_HASHTAB_H */ diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index ad982ce8bfa4..39475fb455bc 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -33,20 +33,20 @@ * Return the length in bytes for the MLS fields of the * security context string representation of `context'. */ -int mls_compute_context_len(struct context *context) +int mls_compute_context_len(struct policydb *p, struct context *context) { int i, l, len, head, prev; char *nm; struct ebitmap *e; struct ebitmap_node *node; - if (!policydb.mls_enabled) + if (!p->mls_enabled) return 0; len = 1; /* for the beginning ":" */ for (l = 0; l < 2; l++) { int index_sens = context->range.level[l].sens; - len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1)); + len += strlen(sym_name(p, SYM_LEVELS, index_sens - 1)); /* categories */ head = -2; @@ -56,17 +56,17 @@ int mls_compute_context_len(struct context *context) if (i - prev > 1) { /* one or more negative bits are skipped */ if (head != prev) { - nm = sym_name(&policydb, SYM_CATS, prev); + nm = sym_name(p, SYM_CATS, prev); len += strlen(nm) + 1; } - nm = sym_name(&policydb, SYM_CATS, i); + nm = sym_name(p, SYM_CATS, i); len += strlen(nm) + 1; head = i; } prev = i; } if (prev != head) { - nm = sym_name(&policydb, SYM_CATS, prev); + nm = sym_name(p, SYM_CATS, prev); len += strlen(nm) + 1; } if (l == 0) { @@ -86,7 +86,8 @@ int mls_compute_context_len(struct context *context) * the MLS fields of `context' into the string `*scontext'. * Update `*scontext' to point to the end of the MLS fields. */ -void mls_sid_to_context(struct context *context, +void mls_sid_to_context(struct policydb *p, + struct context *context, char **scontext) { char *scontextp, *nm; @@ -94,7 +95,7 @@ void mls_sid_to_context(struct context *context, struct ebitmap *e; struct ebitmap_node *node; - if (!policydb.mls_enabled) + if (!p->mls_enabled) return; scontextp = *scontext; @@ -103,7 +104,7 @@ void mls_sid_to_context(struct context *context, scontextp++; for (l = 0; l < 2; l++) { - strcpy(scontextp, sym_name(&policydb, SYM_LEVELS, + strcpy(scontextp, sym_name(p, SYM_LEVELS, context->range.level[l].sens - 1)); scontextp += strlen(scontextp); @@ -119,7 +120,7 @@ void mls_sid_to_context(struct context *context, *scontextp++ = '.'; else *scontextp++ = ','; - nm = sym_name(&policydb, SYM_CATS, prev); + nm = sym_name(p, SYM_CATS, prev); strcpy(scontextp, nm); scontextp += strlen(nm); } @@ -127,7 +128,7 @@ void mls_sid_to_context(struct context *context, *scontextp++ = ':'; else *scontextp++ = ','; - nm = sym_name(&policydb, SYM_CATS, i); + nm = sym_name(p, SYM_CATS, i); strcpy(scontextp, nm); scontextp += strlen(nm); head = i; @@ -140,7 +141,7 @@ void mls_sid_to_context(struct context *context, *scontextp++ = '.'; else *scontextp++ = ','; - nm = sym_name(&policydb, SYM_CATS, prev); + nm = sym_name(p, SYM_CATS, prev); strcpy(scontextp, nm); scontextp += strlen(nm); } @@ -375,12 +376,13 @@ out: * the string `str'. This function will allocate temporary memory with the * given constraints of gfp_mask. */ -int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) +int mls_from_string(struct policydb *p, char *str, struct context *context, + gfp_t gfp_mask) { char *tmpstr, *freestr; int rc; - if (!policydb.mls_enabled) + if (!p->mls_enabled) return -EINVAL; /* we need freestr because mls_context_to_sid will change @@ -389,7 +391,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) if (!tmpstr) { rc = -ENOMEM; } else { - rc = mls_context_to_sid(&policydb, ':', &tmpstr, context, + rc = mls_context_to_sid(p, ':', &tmpstr, context, NULL, SECSID_NULL); kfree(freestr); } @@ -417,10 +419,11 @@ int mls_range_set(struct context *context, return rc; } -int mls_setup_user_range(struct context *fromcon, struct user_datum *user, +int mls_setup_user_range(struct policydb *p, + struct context *fromcon, struct user_datum *user, struct context *usercon) { - if (policydb.mls_enabled) { + if (p->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]); @@ -470,7 +473,7 @@ int mls_convert_context(struct policydb *oldp, struct ebitmap_node *node; int l, i; - if (!policydb.mls_enabled) + if (!oldp->mls_enabled || !newp->mls_enabled) return 0; for (l = 0; l < 2; l++) { @@ -503,7 +506,8 @@ int mls_convert_context(struct policydb *oldp, return 0; } -int mls_compute_sid(struct context *scontext, +int mls_compute_sid(struct policydb *p, + struct context *scontext, struct context *tcontext, u16 tclass, u32 specified, @@ -515,7 +519,7 @@ int mls_compute_sid(struct context *scontext, struct class_datum *cladatum; int default_range = 0; - if (!policydb.mls_enabled) + if (!p->mls_enabled) return 0; switch (specified) { @@ -524,12 +528,12 @@ int mls_compute_sid(struct context *scontext, rtr.source_type = scontext->type; rtr.target_type = tcontext->type; rtr.target_class = tclass; - r = hashtab_search(policydb.range_tr, &rtr); + r = hashtab_search(p->range_tr, &rtr); if (r) return mls_range_set(newcontext, r); - if (tclass && tclass <= policydb.p_classes.nprim) { - cladatum = policydb.class_val_to_struct[tclass - 1]; + if (tclass && tclass <= p->p_classes.nprim) { + cladatum = p->class_val_to_struct[tclass - 1]; if (cladatum) default_range = cladatum->default_range; } @@ -551,7 +555,7 @@ int mls_compute_sid(struct context *scontext, /* Fallthrough */ case AVTAB_CHANGE: - if ((tclass == policydb.process_class) || (sock == true)) + if ((tclass == p->process_class) || (sock == true)) /* Use the process MLS attributes. */ return mls_context_cpy(newcontext, scontext); else @@ -577,10 +581,11 @@ int mls_compute_sid(struct context *scontext, * NetLabel MLS sensitivity level field. * */ -void mls_export_netlbl_lvl(struct context *context, +void mls_export_netlbl_lvl(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr) { - if (!policydb.mls_enabled) + if (!p->mls_enabled) return; secattr->attr.mls.lvl = context->range.level[0].sens - 1; @@ -597,10 +602,11 @@ void mls_export_netlbl_lvl(struct context *context, * NetLabel MLS sensitivity level into the context. * */ -void mls_import_netlbl_lvl(struct context *context, +void mls_import_netlbl_lvl(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr) { - if (!policydb.mls_enabled) + if (!p->mls_enabled) return; context->range.level[0].sens = secattr->attr.mls.lvl + 1; @@ -617,12 +623,13 @@ void mls_import_netlbl_lvl(struct context *context, * MLS category field. Returns zero on success, negative values on failure. * */ -int mls_export_netlbl_cat(struct context *context, +int mls_export_netlbl_cat(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr) { int rc; - if (!policydb.mls_enabled) + if (!p->mls_enabled) return 0; rc = ebitmap_netlbl_export(&context->range.level[0].cat, @@ -645,12 +652,13 @@ int mls_export_netlbl_cat(struct context *context, * negative values on failure. * */ -int mls_import_netlbl_cat(struct context *context, +int mls_import_netlbl_cat(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr) { int rc; - if (!policydb.mls_enabled) + if (!p->mls_enabled) return 0; rc = ebitmap_netlbl_import(&context->range.level[0].cat, diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 131d76266ea5..9a3ff7af70ad 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h @@ -25,8 +25,9 @@ #include "context.h" #include "policydb.h" -int mls_compute_context_len(struct context *context); -void mls_sid_to_context(struct context *context, char **scontext); +int mls_compute_context_len(struct policydb *p, struct context *context); +void mls_sid_to_context(struct policydb *p, struct context *context, + char **scontext); int mls_context_isvalid(struct policydb *p, struct context *c); int mls_range_isvalid(struct policydb *p, struct mls_range *r); int mls_level_isvalid(struct policydb *p, struct mls_level *l); @@ -38,7 +39,8 @@ int mls_context_to_sid(struct policydb *p, struct sidtab *s, u32 def_sid); -int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); +int mls_from_string(struct policydb *p, char *str, struct context *context, + gfp_t gfp_mask); int mls_range_set(struct context *context, struct mls_range *range); @@ -46,42 +48,52 @@ int mls_convert_context(struct policydb *oldp, struct policydb *newp, struct context *context); -int mls_compute_sid(struct context *scontext, +int mls_compute_sid(struct policydb *p, + struct context *scontext, struct context *tcontext, u16 tclass, u32 specified, struct context *newcontext, bool sock); -int mls_setup_user_range(struct context *fromcon, struct user_datum *user, +int mls_setup_user_range(struct policydb *p, + struct context *fromcon, struct user_datum *user, struct context *usercon); #ifdef CONFIG_NETLABEL -void mls_export_netlbl_lvl(struct context *context, +void mls_export_netlbl_lvl(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr); -void mls_import_netlbl_lvl(struct context *context, +void mls_import_netlbl_lvl(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr); -int mls_export_netlbl_cat(struct context *context, +int mls_export_netlbl_cat(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr); -int mls_import_netlbl_cat(struct context *context, +int mls_import_netlbl_cat(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr); #else -static inline void mls_export_netlbl_lvl(struct context *context, +static inline void mls_export_netlbl_lvl(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr) { return; } -static inline void mls_import_netlbl_lvl(struct context *context, +static inline void mls_import_netlbl_lvl(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr) { return; } -static inline int mls_export_netlbl_cat(struct context *context, +static inline int mls_export_netlbl_cat(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr) { return -ENOMEM; } -static inline int mls_import_netlbl_cat(struct context *context, +static inline int mls_import_netlbl_cat(struct policydb *p, + struct context *context, struct netlbl_lsm_secattr *secattr) { return -ENOMEM; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 8900ea5cbabf..3698352213d7 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -80,53 +80,32 @@ char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = { "nnp_nosuid_transition" }; -int selinux_policycap_netpeer; -int selinux_policycap_openperm; -int selinux_policycap_extsockclass; -int selinux_policycap_alwaysnetwork; -int selinux_policycap_cgroupseclabel; -int selinux_policycap_nnp_nosuid_transition; +static struct selinux_ss selinux_ss; -static DEFINE_RWLOCK(policy_rwlock); - -static struct sidtab sidtab; -struct policydb policydb; -int ss_initialized; - -/* - * The largest sequence number that has been used when - * providing an access decision to the access vector cache. - * The sequence number only changes when a policy change - * occurs. - */ -static u32 latest_granting; +void selinux_ss_init(struct selinux_ss **ss) +{ + rwlock_init(&selinux_ss.policy_rwlock); + mutex_init(&selinux_ss.status_lock); + *ss = &selinux_ss; +} /* Forward declaration. */ -static int context_struct_to_string(struct context *context, char **scontext, +static int context_struct_to_string(struct policydb *policydb, + struct context *context, + char **scontext, u32 *scontext_len); -static void context_struct_compute_av(struct context *scontext, - struct context *tcontext, - u16 tclass, - struct av_decision *avd, - struct extended_perms *xperms); - -struct selinux_mapping { - u16 value; /* policy value */ - unsigned num_perms; - u32 perms[sizeof(u32) * 8]; -}; - -static struct selinux_mapping *current_mapping; -static u16 current_mapping_size; +static void context_struct_compute_av(struct policydb *policydb, + struct context *scontext, + struct context *tcontext, + u16 tclass, + struct av_decision *avd, + struct extended_perms *xperms); static int selinux_set_mapping(struct policydb *pol, struct security_class_mapping *map, - struct selinux_mapping **out_map_p, - u16 *out_map_size) + struct selinux_map *out_map) { - struct selinux_mapping *out_map = NULL; - size_t size = sizeof(struct selinux_mapping); u16 i, j; unsigned k; bool print_unknown_handle = false; @@ -139,15 +118,15 @@ static int selinux_set_mapping(struct policydb *pol, i++; /* Allocate space for the class records, plus one for class zero */ - out_map = kcalloc(++i, size, GFP_ATOMIC); - if (!out_map) + out_map->mapping = kcalloc(++i, sizeof(*out_map->mapping), GFP_ATOMIC); + if (!out_map->mapping) return -ENOMEM; /* Store the raw class and permission values */ j = 0; while (map[j].name) { struct security_class_mapping *p_in = map + (j++); - struct selinux_mapping *p_out = out_map + j; + struct selinux_mapping *p_out = out_map->mapping + j; /* An empty class string skips ahead */ if (!strcmp(p_in->name, "")) { @@ -194,11 +173,11 @@ static int selinux_set_mapping(struct policydb *pol, printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", pol->allow_unknown ? "allowed" : "denied"); - *out_map_p = out_map; - *out_map_size = i; + out_map->size = i; return 0; err: - kfree(out_map); + kfree(out_map->mapping); + out_map->mapping = NULL; return -EINVAL; } @@ -206,10 +185,10 @@ err: * Get real, policy values from mapped values */ -static u16 unmap_class(u16 tclass) +static u16 unmap_class(struct selinux_map *map, u16 tclass) { - if (tclass < current_mapping_size) - return current_mapping[tclass].value; + if (tclass < map->size) + return map->mapping[tclass].value; return tclass; } @@ -217,42 +196,44 @@ static u16 unmap_class(u16 tclass) /* * Get kernel value for class from its policy value */ -static u16 map_class(u16 pol_value) +static u16 map_class(struct selinux_map *map, u16 pol_value) { u16 i; - for (i = 1; i < current_mapping_size; i++) { - if (current_mapping[i].value == pol_value) + for (i = 1; i < map->size; i++) { + if (map->mapping[i].value == pol_value) return i; } return SECCLASS_NULL; } -static void map_decision(u16 tclass, struct av_decision *avd, +static void map_decision(struct selinux_map *map, + u16 tclass, struct av_decision *avd, int allow_unknown) { - if (tclass < current_mapping_size) { - unsigned i, n = current_mapping[tclass].num_perms; + if (tclass < map->size) { + struct selinux_mapping *mapping = &map->mapping[tclass]; + unsigned int i, n = mapping->num_perms; u32 result; for (i = 0, result = 0; i < n; i++) { - if (avd->allowed & current_mapping[tclass].perms[i]) + if (avd->allowed & mapping->perms[i]) result |= 1<<i; - if (allow_unknown && !current_mapping[tclass].perms[i]) + if (allow_unknown && !mapping->perms[i]) result |= 1<<i; } avd->allowed = result; for (i = 0, result = 0; i < n; i++) - if (avd->auditallow & current_mapping[tclass].perms[i]) + if (avd->auditallow & mapping->perms[i]) result |= 1<<i; avd->auditallow = result; for (i = 0, result = 0; i < n; i++) { - if (avd->auditdeny & current_mapping[tclass].perms[i]) + if (avd->auditdeny & mapping->perms[i]) result |= 1<<i; - if (!allow_unknown && !current_mapping[tclass].perms[i]) + if (!allow_unknown && !mapping->perms[i]) result |= 1<<i; } /* @@ -266,9 +247,11 @@ static void map_decision(u16 tclass, struct av_decision *avd, } } -int security_mls_enabled(void) +int security_mls_enabled(struct selinux_state *state) { - return policydb.mls_enabled; + struct policydb *p = &state->ss->policydb; + + return p->mls_enabled; } /* @@ -282,7 +265,8 @@ int security_mls_enabled(void) * 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, +static int constraint_expr_eval(struct policydb *policydb, + struct context *scontext, struct context *tcontext, struct context *xcontext, struct constraint_expr *cexpr) @@ -326,8 +310,8 @@ static int constraint_expr_eval(struct context *scontext, case CEXPR_ROLE: val1 = scontext->role; val2 = tcontext->role; - r1 = policydb.role_val_to_struct[val1 - 1]; - r2 = policydb.role_val_to_struct[val2 - 1]; + r1 = policydb->role_val_to_struct[val1 - 1]; + r2 = policydb->role_val_to_struct[val2 - 1]; switch (e->op) { case CEXPR_DOM: s[++sp] = ebitmap_get_bit(&r1->dominates, @@ -472,7 +456,8 @@ static int dump_masked_av_helper(void *k, void *d, void *args) return 0; } -static void security_dump_masked_av(struct context *scontext, +static void security_dump_masked_av(struct policydb *policydb, + struct context *scontext, struct context *tcontext, u16 tclass, u32 permissions, @@ -492,8 +477,8 @@ static void security_dump_masked_av(struct context *scontext, if (!permissions) return; - tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1); - tclass_dat = policydb.class_val_to_struct[tclass - 1]; + tclass_name = sym_name(policydb, SYM_CLASSES, tclass - 1); + tclass_dat = policydb->class_val_to_struct[tclass - 1]; common_dat = tclass_dat->comdatum; /* init permission_names */ @@ -507,11 +492,11 @@ static void security_dump_masked_av(struct context *scontext, goto out; /* get scontext/tcontext in text form */ - if (context_struct_to_string(scontext, + if (context_struct_to_string(policydb, scontext, &scontext_name, &length) < 0) goto out; - if (context_struct_to_string(tcontext, + if (context_struct_to_string(policydb, tcontext, &tcontext_name, &length) < 0) goto out; @@ -550,7 +535,8 @@ out: * security_boundary_permission - drops violated permissions * on boundary constraint. */ -static void type_attribute_bounds_av(struct context *scontext, +static void type_attribute_bounds_av(struct policydb *policydb, + struct context *scontext, struct context *tcontext, u16 tclass, struct av_decision *avd) @@ -562,14 +548,14 @@ static void type_attribute_bounds_av(struct context *scontext, struct type_datum *target; u32 masked = 0; - source = flex_array_get_ptr(policydb.type_val_to_struct_array, + source = flex_array_get_ptr(policydb->type_val_to_struct_array, scontext->type - 1); BUG_ON(!source); if (!source->bounds) return; - target = flex_array_get_ptr(policydb.type_val_to_struct_array, + target = flex_array_get_ptr(policydb->type_val_to_struct_array, tcontext->type - 1); BUG_ON(!target); @@ -584,7 +570,7 @@ static void type_attribute_bounds_av(struct context *scontext, tcontextp = &lo_tcontext; } - context_struct_compute_av(&lo_scontext, + context_struct_compute_av(policydb, &lo_scontext, tcontextp, tclass, &lo_avd, @@ -599,7 +585,7 @@ static void type_attribute_bounds_av(struct context *scontext, avd->allowed &= ~masked; /* audit masked permissions */ - security_dump_masked_av(scontext, tcontext, + security_dump_masked_av(policydb, scontext, tcontext, tclass, masked, "bounds"); } @@ -632,11 +618,12 @@ void services_compute_xperms_drivers( * Compute access vectors and extended permissions based on a context * structure pair for the permissions in a particular class. */ -static void context_struct_compute_av(struct context *scontext, - struct context *tcontext, - u16 tclass, - struct av_decision *avd, - struct extended_perms *xperms) +static void context_struct_compute_av(struct policydb *policydb, + struct context *scontext, + struct context *tcontext, + u16 tclass, + struct av_decision *avd, + struct extended_perms *xperms) { struct constraint_node *constraint; struct role_allow *ra; @@ -655,13 +642,13 @@ static void context_struct_compute_av(struct context *scontext, xperms->len = 0; } - if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { + if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) { if (printk_ratelimit()) printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); return; } - tclass_datum = policydb.class_val_to_struct[tclass - 1]; + tclass_datum = policydb->class_val_to_struct[tclass - 1]; /* * If a specific type enforcement rule was defined for @@ -669,15 +656,18 @@ static void context_struct_compute_av(struct context *scontext, */ avkey.target_class = tclass; avkey.specified = AVTAB_AV | AVTAB_XPERMS; - sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1); + sattr = flex_array_get(policydb->type_attr_map_array, + scontext->type - 1); BUG_ON(!sattr); - tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1); + tattr = flex_array_get(policydb->type_attr_map_array, + tcontext->type - 1); BUG_ON(!tattr); ebitmap_for_each_positive_bit(sattr, snode, i) { ebitmap_for_each_positive_bit(tattr, tnode, j) { avkey.source_type = i + 1; avkey.target_type = j + 1; - for (node = avtab_search_node(&policydb.te_avtab, &avkey); + for (node = avtab_search_node(&policydb->te_avtab, + &avkey); node; node = avtab_search_node_next(node, avkey.specified)) { if (node->key.specified == AVTAB_ALLOWED) @@ -691,7 +681,7 @@ static void context_struct_compute_av(struct context *scontext, } /* Check conditional av table for additional permissions */ - cond_compute_av(&policydb.te_cond_avtab, &avkey, + cond_compute_av(&policydb->te_cond_avtab, &avkey, avd, xperms); } @@ -704,7 +694,7 @@ static void context_struct_compute_av(struct context *scontext, constraint = tclass_datum->constraints; while (constraint) { if ((constraint->permissions & (avd->allowed)) && - !constraint_expr_eval(scontext, tcontext, NULL, + !constraint_expr_eval(policydb, scontext, tcontext, NULL, constraint->expr)) { avd->allowed &= ~(constraint->permissions); } @@ -716,16 +706,16 @@ static void context_struct_compute_av(struct context *scontext, * role is changing, then check the (current_role, new_role) * pair. */ - if (tclass == policydb.process_class && - (avd->allowed & policydb.process_trans_perms) && + if (tclass == policydb->process_class && + (avd->allowed & policydb->process_trans_perms) && scontext->role != tcontext->role) { - for (ra = policydb.role_allow; ra; ra = ra->next) { + for (ra = policydb->role_allow; ra; ra = ra->next) { if (scontext->role == ra->role && tcontext->role == ra->new_role) break; } if (!ra) - avd->allowed &= ~policydb.process_trans_perms; + avd->allowed &= ~policydb->process_trans_perms; } /* @@ -733,41 +723,46 @@ static void context_struct_compute_av(struct context *scontext, * constraint, lazy checks have to mask any violated * permission and notice it to userspace via audit. */ - type_attribute_bounds_av(scontext, tcontext, + type_attribute_bounds_av(policydb, scontext, tcontext, tclass, avd); } -static int security_validtrans_handle_fail(struct context *ocontext, +static int security_validtrans_handle_fail(struct selinux_state *state, + struct context *ocontext, struct context *ncontext, struct context *tcontext, u16 tclass) { + struct policydb *p = &state->ss->policydb; char *o = NULL, *n = NULL, *t = NULL; u32 olen, nlen, tlen; - if (context_struct_to_string(ocontext, &o, &olen)) + if (context_struct_to_string(p, ocontext, &o, &olen)) goto out; - if (context_struct_to_string(ncontext, &n, &nlen)) + if (context_struct_to_string(p, ncontext, &n, &nlen)) goto out; - if (context_struct_to_string(tcontext, &t, &tlen)) + if (context_struct_to_string(p, tcontext, &t, &tlen)) goto out; audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, "op=security_validate_transition seresult=denied" " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", - o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1)); + o, n, t, sym_name(p, SYM_CLASSES, tclass-1)); out: kfree(o); kfree(n); kfree(t); - if (!selinux_enforcing) + if (!is_enforcing(state)) return 0; return -EPERM; } -static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, +static int security_compute_validatetrans(struct selinux_state *state, + u32 oldsid, u32 newsid, u32 tasksid, u16 orig_tclass, bool user) { + struct policydb *policydb; + struct sidtab *sidtab; struct context *ocontext; struct context *ncontext; struct context *tcontext; @@ -776,23 +771,27 @@ static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid, u16 tclass; int rc = 0; - if (!ss_initialized) + + if (!state->initialized) return 0; - read_lock(&policy_rwlock); + read_lock(&state->ss->policy_rwlock); + + policydb = &state->ss->policydb; + sidtab = &state->ss->sidtab; if (!user) - tclass = unmap_class(orig_tclass); + tclass = unmap_class(&state->ss->map, orig_tclass); else tclass = orig_tclass; - if (!tclass || tclass > policydb.p_classes.nprim) { + if (!tclass || tclass > policydb->p_classes.nprim) { rc = -EINVAL; goto out; } - tclass_datum = policydb.class_val_to_struct[tclass - 1]; + tclass_datum = policydb->class_val_to_struct[tclass - 1]; - ocontext = sidtab_search(&sidtab, oldsid); + ocontext = sidtab_search(sidtab, oldsid); if (!ocontext) { printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", __func__, oldsid); @@ -800,7 +799 |