aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/services.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r--security/selinux/ss/services.c210
1 files changed, 192 insertions, 18 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b52f923ce680..343c8ab14af0 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -88,6 +88,11 @@ static u32 latest_granting;
88static int context_struct_to_string(struct context *context, char **scontext, 88static int context_struct_to_string(struct context *context, char **scontext,
89 u32 *scontext_len); 89 u32 *scontext_len);
90 90
91static int context_struct_compute_av(struct context *scontext,
92 struct context *tcontext,
93 u16 tclass,
94 u32 requested,
95 struct av_decision *avd);
91/* 96/*
92 * Return the boolean value of a constraint expression 97 * Return the boolean value of a constraint expression
93 * when it is applied to the specified source and target 98 * when it is applied to the specified source and target
@@ -274,6 +279,100 @@ mls_ops:
274} 279}
275 280
276/* 281/*
282 * security_boundary_permission - drops violated permissions
283 * on boundary constraint.
284 */
285static void type_attribute_bounds_av(struct context *scontext,
286 struct context *tcontext,
287 u16 tclass,
288 u32 requested,
289 struct av_decision *avd)
290{
291 struct context lo_scontext;
292 struct context lo_tcontext;
293 struct av_decision lo_avd;
294 struct type_datum *source
295 = policydb.type_val_to_struct[scontext->type - 1];
296 struct type_datum *target
297 = policydb.type_val_to_struct[tcontext->type - 1];
298 u32 masked = 0;
299
300 if (source->bounds) {
301 memset(&lo_avd, 0, sizeof(lo_avd));
302
303 memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
304 lo_scontext.type = source->bounds;
305
306 context_struct_compute_av(&lo_scontext,
307 tcontext,
308 tclass,
309 requested,
310 &lo_avd);
311 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
312 return; /* no masked permission */
313 masked = ~lo_avd.allowed & avd->allowed;
314 }
315
316 if (target->bounds) {
317 memset(&lo_avd, 0, sizeof(lo_avd));
318
319 memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
320 lo_tcontext.type = target->bounds;
321
322 context_struct_compute_av(scontext,
323 &lo_tcontext,
324 tclass,
325 requested,
326 &lo_avd);
327 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
328 return; /* no masked permission */
329 masked = ~lo_avd.allowed & avd->allowed;
330 }
331
332 if (source->bounds && target->bounds) {
333 memset(&lo_avd, 0, sizeof(lo_avd));
334 /*
335 * lo_scontext and lo_tcontext are already
336 * set up.
337 */
338
339 context_struct_compute_av(&lo_scontext,
340 &lo_tcontext,
341 tclass,
342 requested,
343 &lo_avd);
344 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
345 return; /* no masked permission */
346 masked = ~lo_avd.allowed & avd->allowed;
347 }
348
349 if (masked) {
350 struct audit_buffer *ab;
351 char *stype_name
352 = policydb.p_type_val_to_name[source->value - 1];
353 char *ttype_name
354 = policydb.p_type_val_to_name[target->value - 1];
355 char *tclass_name
356 = policydb.p_class_val_to_name[tclass - 1];
357
358 /* mask violated permissions */
359 avd->allowed &= ~masked;
360
361 /* notice to userspace via audit message */
362 ab = audit_log_start(current->audit_context,
363 GFP_ATOMIC, AUDIT_SELINUX_ERR);
364 if (!ab)
365 return;
366
367 audit_log_format(ab, "av boundary violation: "
368 "source=%s target=%s tclass=%s",
369 stype_name, ttype_name, tclass_name);
370 avc_dump_av(ab, tclass, masked);
371 audit_log_end(ab);
372 }
373}
374
375/*
277 * Compute access vectors based on a context structure pair for 376 * Compute access vectors based on a context structure pair for
278 * the permissions in a particular class. 377 * the permissions in a particular class.
279 */ 378 */
@@ -356,7 +455,7 @@ static int context_struct_compute_av(struct context *scontext,
356 avkey.source_type = i + 1; 455 avkey.source_type = i + 1;
357 avkey.target_type = j + 1; 456 avkey.target_type = j + 1;
358 for (node = avtab_search_node(&policydb.te_avtab, &avkey); 457 for (node = avtab_search_node(&policydb.te_avtab, &avkey);
359 node != NULL; 458 node;
360 node = avtab_search_node_next(node, avkey.specified)) { 459 node = avtab_search_node_next(node, avkey.specified)) {
361 if (node->key.specified == AVTAB_ALLOWED) 460 if (node->key.specified == AVTAB_ALLOWED)
362 avd->allowed |= node->datum.data; 461 avd->allowed |= node->datum.data;
@@ -404,6 +503,14 @@ static int context_struct_compute_av(struct context *scontext,
404 PROCESS__DYNTRANSITION); 503 PROCESS__DYNTRANSITION);
405 } 504 }
406 505
506 /*
507 * If the given source and target types have boundary
508 * constraint, lazy checks have to mask any violated
509 * permission and notice it to userspace via audit.
510 */
511 type_attribute_bounds_av(scontext, tcontext,
512 tclass, requested, avd);
513
407 return 0; 514 return 0;
408 515
409inval_class: 516inval_class:
@@ -549,6 +656,69 @@ out:
549 return rc; 656 return rc;
550} 657}
551 658
659/*
660 * security_bounded_transition - check whether the given
661 * transition is directed to bounded, or not.
662 * It returns 0, if @newsid is bounded by @oldsid.
663 * Otherwise, it returns error code.
664 *
665 * @oldsid : current security identifier
666 * @newsid : destinated security identifier
667 */
668int security_bounded_transition(u32 old_sid, u32 new_sid)
669{
670 struct context *old_context, *new_context;
671 struct type_datum *type;
672 int index;
673 int rc = -EINVAL;
674
675 read_lock(&policy_rwlock);
676
677 old_context = sidtab_search(&sidtab, old_sid);
678 if (!old_context) {
679 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
680 __func__, old_sid);
681 goto out;
682 }
683
684 new_context = sidtab_search(&sidtab, new_sid);
685 if (!new_context) {
686 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
687 __func__, new_sid);
688 goto out;
689 }
690
691 /* type/domain unchaned */
692 if (old_context->type == new_context->type) {
693 rc = 0;
694 goto out;
695 }
696
697 index = new_context->type;
698 while (true) {
699 type = policydb.type_val_to_struct[index - 1];
700 BUG_ON(!type);
701
702 /* not bounded anymore */
703 if (!type->bounds) {
704 rc = -EPERM;
705 break;
706 }
707
708 /* @newsid is bounded by @oldsid */
709 if (type->bounds == old_context->type) {
710 rc = 0;
711 break;
712 }
713 index = type->bounds;
714 }
715out:
716 read_unlock(&policy_rwlock);
717
718 return rc;
719}
720
721
552/** 722/**
553 * security_compute_av - Compute access vector decisions. 723 * security_compute_av - Compute access vector decisions.
554 * @ssid: source security identifier 724 * @ssid: source security identifier
@@ -794,7 +964,7 @@ static int string_to_context_struct(struct policydb *pol,
794 *p++ = 0; 964 *p++ = 0;
795 965
796 typdatum = hashtab_search(pol->p_types.table, scontextp); 966 typdatum = hashtab_search(pol->p_types.table, scontextp);
797 if (!typdatum) 967 if (!typdatum || typdatum->attribute)
798 goto out; 968 goto out;
799 969
800 ctx->type = typdatum->value; 970 ctx->type = typdatum->value;
@@ -811,11 +981,12 @@ static int string_to_context_struct(struct policydb *pol,
811 /* Check the validity of the new context. */ 981 /* Check the validity of the new context. */
812 if (!policydb_context_isvalid(pol, ctx)) { 982 if (!policydb_context_isvalid(pol, ctx)) {
813 rc = -EINVAL; 983 rc = -EINVAL;
814 context_destroy(ctx);
815 goto out; 984 goto out;
816 } 985 }
817 rc = 0; 986 rc = 0;
818out: 987out:
988 if (rc)
989 context_destroy(ctx);
819 return rc; 990 return rc;
820} 991}
821 992
@@ -868,8 +1039,7 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
868 } else if (rc) 1039 } else if (rc)
869 goto out; 1040 goto out;
870 rc = sidtab_context_to_sid(&sidtab, &context, sid); 1041 rc = sidtab_context_to_sid(&sidtab, &context, sid);
871 if (rc) 1042 context_destroy(&context);
872 context_destroy(&context);
873out: 1043out:
874 read_unlock(&policy_rwlock); 1044 read_unlock(&policy_rwlock);
875 kfree(scontext2); 1045 kfree(scontext2);
@@ -1037,7 +1207,7 @@ static int security_compute_sid(u32 ssid,
1037 /* If no permanent rule, also check for enabled conditional rules */ 1207 /* If no permanent rule, also check for enabled conditional rules */
1038 if (!avdatum) { 1208 if (!avdatum) {
1039 node = avtab_search_node(&policydb.te_cond_avtab, &avkey); 1209 node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
1040 for (; node != NULL; node = avtab_search_node_next(node, specified)) { 1210 for (; node; node = avtab_search_node_next(node, specified)) {
1041 if (node->key.specified & AVTAB_ENABLED) { 1211 if (node->key.specified & AVTAB_ENABLED) {
1042 avdatum = &node->datum; 1212 avdatum = &node->datum;
1043 break; 1213 break;
@@ -2050,7 +2220,7 @@ int security_set_bools(int len, int *values)
2050 policydb.bool_val_to_struct[i]->state = 0; 2220 policydb.bool_val_to_struct[i]->state = 0;
2051 } 2221 }
2052 2222
2053 for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { 2223 for (cur = policydb.cond_list; cur; cur = cur->next) {
2054 rc = evaluate_cond_node(&policydb, cur); 2224 rc = evaluate_cond_node(&policydb, cur);
2055 if (rc) 2225 if (rc)
2056 goto out; 2226 goto out;
@@ -2102,7 +2272,7 @@ static int security_preserve_bools(struct policydb *p)
2102 if (booldatum) 2272 if (booldatum)
2103 booldatum->state = bvalues[i]; 2273 booldatum->state = bvalues[i];
2104 } 2274 }
2105 for (cur = p->cond_list; cur != NULL; cur = cur->next) { 2275 for (cur = p->cond_list; cur; cur = cur->next) {
2106 rc = evaluate_cond_node(p, cur); 2276 rc = evaluate_cond_node(p, cur);
2107 if (rc) 2277 if (rc)
2108 goto out; 2278 goto out;
@@ -2737,6 +2907,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2737 if (ctx == NULL) 2907 if (ctx == NULL)
2738 goto netlbl_secattr_to_sid_return; 2908 goto netlbl_secattr_to_sid_return;
2739 2909
2910 context_init(&ctx_new);
2740 ctx_new.user = ctx->user; 2911 ctx_new.user = ctx->user;
2741 ctx_new.role = ctx->role; 2912 ctx_new.role = ctx->role;
2742 ctx_new.type = ctx->type; 2913 ctx_new.type = ctx->type;
@@ -2745,13 +2916,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2745 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat, 2916 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
2746 secattr->attr.mls.cat) != 0) 2917 secattr->attr.mls.cat) != 0)
2747 goto netlbl_secattr_to_sid_return; 2918 goto netlbl_secattr_to_sid_return;
2748 ctx_new.range.level[1].cat.highbit = 2919 memcpy(&ctx_new.range.level[1].cat,
2749 ctx_new.range.level[0].cat.highbit; 2920 &ctx_new.range.level[0].cat,
2750 ctx_new.range.level[1].cat.node = 2921 sizeof(ctx_new.range.level[0].cat));
2751 ctx_new.range.level[0].cat.node;
2752 } else {
2753 ebitmap_init(&ctx_new.range.level[0].cat);
2754 ebitmap_init(&ctx_new.range.level[1].cat);
2755 } 2922 }
2756 if (mls_context_isvalid(&policydb, &ctx_new) != 1) 2923 if (mls_context_isvalid(&policydb, &ctx_new) != 1)
2757 goto netlbl_secattr_to_sid_return_cleanup; 2924 goto netlbl_secattr_to_sid_return_cleanup;
@@ -2788,7 +2955,7 @@ netlbl_secattr_to_sid_return_cleanup:
2788 */ 2955 */
2789int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr) 2956int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2790{ 2957{
2791 int rc = -ENOENT; 2958 int rc;
2792 struct context *ctx; 2959 struct context *ctx;
2793 2960
2794 if (!ss_initialized) 2961 if (!ss_initialized)
@@ -2796,11 +2963,18 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
2796 2963
2797 read_lock(&policy_rwlock); 2964 read_lock(&policy_rwlock);
2798 ctx = sidtab_search(&sidtab, sid); 2965 ctx = sidtab_search(&sidtab, sid);
2799 if (ctx == NULL) 2966 if (ctx == NULL) {
2967 rc = -ENOENT;
2800 goto netlbl_sid_to_secattr_failure; 2968 goto netlbl_sid_to_secattr_failure;
2969 }
2801 secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], 2970 secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
2802 GFP_ATOMIC); 2971 GFP_ATOMIC);
2803 secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY; 2972 if (secattr->domain == NULL) {
2973 rc = -ENOMEM;
2974 goto netlbl_sid_to_secattr_failure;
2975 }
2976 secattr->attr.secid = sid;
2977 secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
2804 mls_export_netlbl_lvl(ctx, secattr); 2978 mls_export_netlbl_lvl(ctx, secattr);
2805 rc = mls_export_netlbl_cat(ctx, secattr); 2979 rc = mls_export_netlbl_cat(ctx, secattr);
2806 if (rc != 0) 2980 if (rc != 0)