diff options
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r-- | security/selinux/ss/services.c | 135 |
1 files changed, 85 insertions, 50 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 922bb45..aecdded 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -266,8 +266,11 @@ static int context_struct_compute_av(struct context *scontext, struct constraint_node *constraint; struct role_allow *ra; struct avtab_key avkey; - struct avtab_datum *avdatum; + struct avtab_node *node; struct class_datum *tclass_datum; + struct ebitmap *sattr, *tattr; + struct ebitmap_node *snode, *tnode; + unsigned int i, j; /* * Remap extended Netlink classes for old policy versions. @@ -300,21 +303,34 @@ static int context_struct_compute_av(struct context *scontext, * If a specific type enforcement rule was defined for * this permission check, then use it. */ - avkey.source_type = scontext->type; - avkey.target_type = tcontext->type; avkey.target_class = tclass; - avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV); - if (avdatum) { - if (avdatum->specified & AVTAB_ALLOWED) - avd->allowed = avtab_allowed(avdatum); - if (avdatum->specified & AVTAB_AUDITDENY) - avd->auditdeny = avtab_auditdeny(avdatum); - if (avdatum->specified & AVTAB_AUDITALLOW) - avd->auditallow = avtab_auditallow(avdatum); - } + avkey.specified = AVTAB_AV; + sattr = &policydb.type_attr_map[scontext->type - 1]; + tattr = &policydb.type_attr_map[tcontext->type - 1]; + ebitmap_for_each_bit(sattr, snode, i) { + if (!ebitmap_node_get_bit(snode, i)) + continue; + ebitmap_for_each_bit(tattr, tnode, j) { + if (!ebitmap_node_get_bit(tnode, j)) + continue; + avkey.source_type = i + 1; + avkey.target_type = j + 1; + for (node = avtab_search_node(&policydb.te_avtab, &avkey); + node != NULL; + node = avtab_search_node_next(node, avkey.specified)) { + if (node->key.specified == AVTAB_ALLOWED) + avd->allowed |= node->datum.data; + else if (node->key.specified == AVTAB_AUDITALLOW) + avd->auditallow |= node->datum.data; + else if (node->key.specified == AVTAB_AUDITDENY) + avd->auditdeny &= node->datum.data; + } + + /* Check conditional av table for additional permissions */ + cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); - /* Check conditional av table for additional permissions */ - cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); + } + } /* * Remove any permissions prohibited by a constraint (this includes @@ -365,7 +381,7 @@ static int security_validtrans_handle_fail(struct context *ocontext, goto out; if (context_struct_to_string(tcontext, &t, &tlen) < 0) goto out; - audit_log(current->audit_context, AUDIT_SELINUX_ERR, + audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, "security_validate_transition: denied for" " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", o, n, t, policydb.p_class_val_to_name[tclass-1]); @@ -601,18 +617,7 @@ out: } -/** - * security_context_to_sid - Obtain a SID for a given security context. - * @scontext: security context - * @scontext_len: length in bytes - * @sid: security identifier, SID - * - * Obtains a SID associated with the security context that - * has the string representation specified by @scontext. - * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient - * memory is available, or 0 on success. - */ -int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid) +static int security_context_to_sid_core(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid) { char *scontext2; struct context context; @@ -703,7 +708,7 @@ int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid) context.type = typdatum->value; - rc = mls_context_to_sid(oldc, &p, &context); + rc = mls_context_to_sid(oldc, &p, &context, &sidtab, def_sid); if (rc) goto out_unlock; @@ -727,6 +732,46 @@ out: return rc; } +/** + * security_context_to_sid - Obtain a SID for a given security context. + * @scontext: security context + * @scontext_len: length in bytes + * @sid: security identifier, SID + * + * Obtains a SID associated with the security context that + * has the string representation specified by @scontext. + * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient + * memory is available, or 0 on success. + */ +int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid) +{ + return security_context_to_sid_core(scontext, scontext_len, + sid, SECSID_NULL); +} + +/** + * security_context_to_sid_default - Obtain a SID for a given security context, + * falling back to specified default if needed. + * + * @scontext: security context + * @scontext_len: length in bytes + * @sid: security identifier, SID + * @def_sid: default SID to assign on errror + * + * Obtains a SID associated with the security context that + * has the string representation specified by @scontext. + * The default SID is passed to the MLS layer to be used to allow + * kernel labeling of the MLS field if the MLS field is not present + * (for upgrading to MLS without full relabel). + * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient + * memory is available, or 0 on success. + */ +int security_context_to_sid_default(char *scontext, u32 scontext_len, u32 *sid, u32 def_sid) +{ + return security_context_to_sid_core(scontext, scontext_len, + sid, def_sid); +} + static int compute_sid_handle_invalid_context( struct context *scontext, struct context *tcontext, @@ -742,7 +787,7 @@ static int compute_sid_handle_invalid_context( goto out; if (context_struct_to_string(newcontext, &n, &nlen) < 0) goto out; - audit_log(current->audit_context, AUDIT_SELINUX_ERR, + audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, "security_compute_sid: invalid context %s" " for scontext=%s" " tcontext=%s" @@ -768,7 +813,6 @@ static int security_compute_sid(u32 ssid, struct avtab_key avkey; struct avtab_datum *avdatum; struct avtab_node *node; - unsigned int type_change = 0; int rc = 0; if (!ss_initialized) { @@ -833,33 +877,23 @@ static int security_compute_sid(u32 ssid, avkey.source_type = scontext->type; avkey.target_type = tcontext->type; avkey.target_class = tclass; - avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE); + avkey.specified = specified; + avdatum = avtab_search(&policydb.te_avtab, &avkey); /* If no permanent rule, also check for enabled conditional rules */ if(!avdatum) { - node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified); + node = avtab_search_node(&policydb.te_cond_avtab, &avkey); for (; node != NULL; node = avtab_search_node_next(node, specified)) { - if (node->datum.specified & AVTAB_ENABLED) { + if (node->key.specified & AVTAB_ENABLED) { avdatum = &node->datum; break; } } } - type_change = (avdatum && (avdatum->specified & specified)); - if (type_change) { + if (avdatum) { /* Use the type from the type transition/member/change rule. */ - switch (specified) { - case AVTAB_TRANSITION: - newcontext.type = avtab_transition(avdatum); - break; - case AVTAB_MEMBER: - newcontext.type = avtab_member(avdatum); - break; - case AVTAB_CHANGE: - newcontext.type = avtab_change(avdatum); - break; - } + newcontext.type = avdatum->data; } /* Check for class-specific changes. */ @@ -1473,6 +1507,7 @@ int security_get_user_sids(u32 fromsid, struct user_datum *user; struct role_datum *role; struct av_decision avd; + struct ebitmap_node *rnode, *tnode; int rc = 0, i, j; if (!ss_initialized) { @@ -1503,13 +1538,13 @@ int security_get_user_sids(u32 fromsid, } memset(mysids, 0, maxnel*sizeof(*mysids)); - for (i = ebitmap_startbit(&user->roles); i < ebitmap_length(&user->roles); i++) { - if (!ebitmap_get_bit(&user->roles, i)) + ebitmap_for_each_bit(&user->roles, rnode, i) { + if (!ebitmap_node_get_bit(rnode, i)) continue; role = policydb.role_val_to_struct[i]; usercon.role = i+1; - for (j = ebitmap_startbit(&role->types); j < ebitmap_length(&role->types); j++) { - if (!ebitmap_get_bit(&role->types, j)) + ebitmap_for_each_bit(&role->types, tnode, j) { + if (!ebitmap_node_get_bit(tnode, j)) continue; usercon.type = j+1; |