diff options
-rw-r--r-- | security/selinux/ss/services.c | 115 |
1 files changed, 55 insertions, 60 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b341b8fd8c7c..fc3dfca475d6 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Implementation of the security services. | 2 | * Implementation of the security services. |
3 | * | 3 | * |
4 | * Authors : Stephen Smalley, <sds@epoch.ncsc.mil> | 4 | * Authors : Stephen Smalley, <sds@epoch.ncsc.mil> |
5 | * James Morris <jmorris@redhat.com> | 5 | * James Morris <jmorris@redhat.com> |
6 | * | 6 | * |
7 | * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> | 7 | * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> |
8 | * | 8 | * |
@@ -11,7 +11,7 @@ | |||
11 | * | 11 | * |
12 | * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> | 12 | * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com> |
13 | * | 13 | * |
14 | * Added conditional policy language extensions | 14 | * Added conditional policy language extensions |
15 | * | 15 | * |
16 | * Updated: Hewlett-Packard <paul.moore@hp.com> | 16 | * Updated: Hewlett-Packard <paul.moore@hp.com> |
17 | * | 17 | * |
@@ -27,7 +27,7 @@ | |||
27 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC | 27 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC |
28 | * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> | 28 | * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> |
29 | * This program is free software; you can redistribute it and/or modify | 29 | * This program is free software; you can redistribute it and/or modify |
30 | * it under the terms of the GNU General Public License as published by | 30 | * it under the terms of the GNU General Public License as published by |
31 | * the Free Software Foundation, version 2. | 31 | * the Free Software Foundation, version 2. |
32 | */ | 32 | */ |
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
@@ -82,7 +82,7 @@ static DEFINE_MUTEX(load_mutex); | |||
82 | 82 | ||
83 | static struct sidtab sidtab; | 83 | static struct sidtab sidtab; |
84 | struct policydb policydb; | 84 | struct policydb policydb; |
85 | int ss_initialized = 0; | 85 | int ss_initialized; |
86 | 86 | ||
87 | /* | 87 | /* |
88 | * The largest sequence number that has been used when | 88 | * The largest sequence number that has been used when |
@@ -90,7 +90,7 @@ int ss_initialized = 0; | |||
90 | * The sequence number only changes when a policy change | 90 | * The sequence number only changes when a policy change |
91 | * occurs. | 91 | * occurs. |
92 | */ | 92 | */ |
93 | static u32 latest_granting = 0; | 93 | static u32 latest_granting; |
94 | 94 | ||
95 | /* Forward declaration. */ | 95 | /* Forward declaration. */ |
96 | static int context_struct_to_string(struct context *context, char **scontext, | 96 | static int context_struct_to_string(struct context *context, char **scontext, |
@@ -163,10 +163,10 @@ static int constraint_expr_eval(struct context *scontext, | |||
163 | val1 - 1); | 163 | val1 - 1); |
164 | continue; | 164 | continue; |
165 | case CEXPR_INCOMP: | 165 | case CEXPR_INCOMP: |
166 | s[++sp] = ( !ebitmap_get_bit(&r1->dominates, | 166 | s[++sp] = (!ebitmap_get_bit(&r1->dominates, |
167 | val2 - 1) && | 167 | val2 - 1) && |
168 | !ebitmap_get_bit(&r2->dominates, | 168 | !ebitmap_get_bit(&r2->dominates, |
169 | val1 - 1) ); | 169 | val1 - 1)); |
170 | continue; | 170 | continue; |
171 | default: | 171 | default: |
172 | break; | 172 | break; |
@@ -409,7 +409,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
409 | } | 409 | } |
410 | if (!ra) | 410 | if (!ra) |
411 | avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | | 411 | avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | |
412 | PROCESS__DYNTRANSITION); | 412 | PROCESS__DYNTRANSITION); |
413 | } | 413 | } |
414 | 414 | ||
415 | return 0; | 415 | return 0; |
@@ -445,9 +445,9 @@ int security_permissive_sid(u32 sid) | |||
445 | } | 445 | } |
446 | 446 | ||
447 | static int security_validtrans_handle_fail(struct context *ocontext, | 447 | static int security_validtrans_handle_fail(struct context *ocontext, |
448 | struct context *ncontext, | 448 | struct context *ncontext, |
449 | struct context *tcontext, | 449 | struct context *tcontext, |
450 | u16 tclass) | 450 | u16 tclass) |
451 | { | 451 | { |
452 | char *o = NULL, *n = NULL, *t = NULL; | 452 | char *o = NULL, *n = NULL, *t = NULL; |
453 | u32 olen, nlen, tlen; | 453 | u32 olen, nlen, tlen; |
@@ -459,9 +459,9 @@ static int security_validtrans_handle_fail(struct context *ocontext, | |||
459 | if (context_struct_to_string(tcontext, &t, &tlen) < 0) | 459 | if (context_struct_to_string(tcontext, &t, &tlen) < 0) |
460 | goto out; | 460 | goto out; |
461 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 461 | audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
462 | "security_validate_transition: denied for" | 462 | "security_validate_transition: denied for" |
463 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", | 463 | " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s", |
464 | o, n, t, policydb.p_class_val_to_name[tclass-1]); | 464 | o, n, t, policydb.p_class_val_to_name[tclass-1]); |
465 | out: | 465 | out: |
466 | kfree(o); | 466 | kfree(o); |
467 | kfree(n); | 467 | kfree(n); |
@@ -473,7 +473,7 @@ out: | |||
473 | } | 473 | } |
474 | 474 | ||
475 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | 475 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, |
476 | u16 tclass) | 476 | u16 tclass) |
477 | { | 477 | { |
478 | struct context *ocontext; | 478 | struct context *ocontext; |
479 | struct context *ncontext; | 479 | struct context *ncontext; |
@@ -533,9 +533,9 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | |||
533 | constraint = tclass_datum->validatetrans; | 533 | constraint = tclass_datum->validatetrans; |
534 | while (constraint) { | 534 | while (constraint) { |
535 | if (!constraint_expr_eval(ocontext, ncontext, tcontext, | 535 | if (!constraint_expr_eval(ocontext, ncontext, tcontext, |
536 | constraint->expr)) { | 536 | constraint->expr)) { |
537 | rc = security_validtrans_handle_fail(ocontext, ncontext, | 537 | rc = security_validtrans_handle_fail(ocontext, ncontext, |
538 | tcontext, tclass); | 538 | tcontext, tclass); |
539 | goto out; | 539 | goto out; |
540 | } | 540 | } |
541 | constraint = constraint->next; | 541 | constraint = constraint->next; |
@@ -623,9 +623,8 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
623 | 623 | ||
624 | /* Allocate space for the context; caller must free this space. */ | 624 | /* Allocate space for the context; caller must free this space. */ |
625 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); | 625 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); |
626 | if (!scontextp) { | 626 | if (!scontextp) |
627 | return -ENOMEM; | 627 | return -ENOMEM; |
628 | } | ||
629 | *scontext = scontextp; | 628 | *scontext = scontextp; |
630 | 629 | ||
631 | /* | 630 | /* |
@@ -636,8 +635,8 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 | |||
636 | policydb.p_role_val_to_name[context->role - 1], | 635 | policydb.p_role_val_to_name[context->role - 1], |
637 | policydb.p_type_val_to_name[context->type - 1]); | 636 | policydb.p_type_val_to_name[context->type - 1]); |
638 | scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) + | 637 | scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) + |
639 | 1 + strlen(policydb.p_role_val_to_name[context->role - 1]) + | 638 | 1 + strlen(policydb.p_role_val_to_name[context->role - 1]) + |
640 | 1 + strlen(policydb.p_type_val_to_name[context->type - 1]); | 639 | 1 + strlen(policydb.p_type_val_to_name[context->type - 1]); |
641 | 640 | ||
642 | mls_sid_to_context(context, &scontextp); | 641 | mls_sid_to_context(context, &scontextp); |
643 | 642 | ||
@@ -678,7 +677,7 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len) | |||
678 | char *scontextp; | 677 | char *scontextp; |
679 | 678 | ||
680 | *scontext_len = strlen(initial_sid_to_string[sid]) + 1; | 679 | *scontext_len = strlen(initial_sid_to_string[sid]) + 1; |
681 | scontextp = kmalloc(*scontext_len,GFP_ATOMIC); | 680 | scontextp = kmalloc(*scontext_len, GFP_ATOMIC); |
682 | if (!scontextp) { | 681 | if (!scontextp) { |
683 | rc = -ENOMEM; | 682 | rc = -ENOMEM; |
684 | goto out; | 683 | goto out; |
@@ -974,7 +973,7 @@ static int security_compute_sid(u32 ssid, | |||
974 | avdatum = avtab_search(&policydb.te_avtab, &avkey); | 973 | avdatum = avtab_search(&policydb.te_avtab, &avkey); |
975 | 974 | ||
976 | /* If no permanent rule, also check for enabled conditional rules */ | 975 | /* If no permanent rule, also check for enabled conditional rules */ |
977 | if(!avdatum) { | 976 | if (!avdatum) { |
978 | node = avtab_search_node(&policydb.te_cond_avtab, &avkey); | 977 | node = avtab_search_node(&policydb.te_cond_avtab, &avkey); |
979 | for (; node != NULL; node = avtab_search_node_next(node, specified)) { | 978 | for (; node != NULL; node = avtab_search_node_next(node, specified)) { |
980 | if (node->key.specified & AVTAB_ENABLED) { | 979 | if (node->key.specified & AVTAB_ENABLED) { |
@@ -1288,26 +1287,23 @@ static int convert_context(u32 key, | |||
1288 | 1287 | ||
1289 | /* Convert the user. */ | 1288 | /* Convert the user. */ |
1290 | usrdatum = hashtab_search(args->newp->p_users.table, | 1289 | usrdatum = hashtab_search(args->newp->p_users.table, |
1291 | args->oldp->p_user_val_to_name[c->user - 1]); | 1290 | args->oldp->p_user_val_to_name[c->user - 1]); |
1292 | if (!usrdatum) { | 1291 | if (!usrdatum) |
1293 | goto bad; | 1292 | goto bad; |
1294 | } | ||
1295 | c->user = usrdatum->value; | 1293 | c->user = usrdatum->value; |
1296 | 1294 | ||
1297 | /* Convert the role. */ | 1295 | /* Convert the role. */ |
1298 | role = hashtab_search(args->newp->p_roles.table, | 1296 | role = hashtab_search(args->newp->p_roles.table, |
1299 | args->oldp->p_role_val_to_name[c->role - 1]); | 1297 | args->oldp->p_role_val_to_name[c->role - 1]); |
1300 | if (!role) { | 1298 | if (!role) |
1301 | goto bad; | 1299 | goto bad; |
1302 | } | ||
1303 | c->role = role->value; | 1300 | c->role = role->value; |
1304 | 1301 | ||
1305 | /* Convert the type. */ | 1302 | /* Convert the type. */ |
1306 | typdatum = hashtab_search(args->newp->p_types.table, | 1303 | typdatum = hashtab_search(args->newp->p_types.table, |
1307 | args->oldp->p_type_val_to_name[c->type - 1]); | 1304 | args->oldp->p_type_val_to_name[c->type - 1]); |
1308 | if (!typdatum) { | 1305 | if (!typdatum) |
1309 | goto bad; | 1306 | goto bad; |
1310 | } | ||
1311 | c->type = typdatum->value; | 1307 | c->type = typdatum->value; |
1312 | 1308 | ||
1313 | rc = mls_convert_context(args->oldp, args->newp, c); | 1309 | rc = mls_convert_context(args->oldp, args->newp, c); |
@@ -1556,8 +1552,8 @@ static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask) | |||
1556 | { | 1552 | { |
1557 | int i, fail = 0; | 1553 | int i, fail = 0; |
1558 | 1554 | ||
1559 | for(i = 0; i < 4; i++) | 1555 | for (i = 0; i < 4; i++) |
1560 | if(addr[i] != (input[i] & mask[i])) { | 1556 | if (addr[i] != (input[i] & mask[i])) { |
1561 | fail = 1; | 1557 | fail = 1; |
1562 | break; | 1558 | break; |
1563 | } | 1559 | } |
@@ -1656,7 +1652,7 @@ out: | |||
1656 | */ | 1652 | */ |
1657 | 1653 | ||
1658 | int security_get_user_sids(u32 fromsid, | 1654 | int security_get_user_sids(u32 fromsid, |
1659 | char *username, | 1655 | char *username, |
1660 | u32 **sids, | 1656 | u32 **sids, |
1661 | u32 *nel) | 1657 | u32 *nel) |
1662 | { | 1658 | { |
@@ -1766,7 +1762,7 @@ out: | |||
1766 | * transition SIDs or task SIDs. | 1762 | * transition SIDs or task SIDs. |
1767 | */ | 1763 | */ |
1768 | int security_genfs_sid(const char *fstype, | 1764 | int security_genfs_sid(const char *fstype, |
1769 | char *path, | 1765 | char *path, |
1770 | u16 sclass, | 1766 | u16 sclass, |
1771 | u32 *sid) | 1767 | u32 *sid) |
1772 | { | 1768 | { |
@@ -1881,7 +1877,7 @@ int security_get_bools(int *len, char ***names, int **values) | |||
1881 | goto out; | 1877 | goto out; |
1882 | } | 1878 | } |
1883 | 1879 | ||
1884 | *names = kcalloc(*len, sizeof(char*), GFP_ATOMIC); | 1880 | *names = kcalloc(*len, sizeof(char *), GFP_ATOMIC); |
1885 | if (!*names) | 1881 | if (!*names) |
1886 | goto err; | 1882 | goto err; |
1887 | 1883 | ||
@@ -1893,7 +1889,7 @@ int security_get_bools(int *len, char ***names, int **values) | |||
1893 | size_t name_len; | 1889 | size_t name_len; |
1894 | (*values)[i] = policydb.bool_val_to_struct[i]->state; | 1890 | (*values)[i] = policydb.bool_val_to_struct[i]->state; |
1895 | name_len = strlen(policydb.p_bool_val_to_name[i]) + 1; | 1891 | name_len = strlen(policydb.p_bool_val_to_name[i]) + 1; |
1896 | (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC); | 1892 | (*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC); |
1897 | if (!(*names)[i]) | 1893 | if (!(*names)[i]) |
1898 | goto err; | 1894 | goto err; |
1899 | strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len); | 1895 | strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len); |
@@ -1938,11 +1934,10 @@ int security_set_bools(int len, int *values) | |||
1938 | audit_get_loginuid(current), | 1934 | audit_get_loginuid(current), |
1939 | audit_get_sessionid(current)); | 1935 | audit_get_sessionid(current)); |
1940 | } | 1936 | } |
1941 | if (values[i]) { | 1937 | if (values[i]) |
1942 | policydb.bool_val_to_struct[i]->state = 1; | 1938 | policydb.bool_val_to_struct[i]->state = 1; |
1943 | } else { | 1939 | else |
1944 | policydb.bool_val_to_struct[i]->state = 0; | 1940 | policydb.bool_val_to_struct[i]->state = 0; |
1945 | } | ||
1946 | } | 1941 | } |
1947 | 1942 | ||
1948 | for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { | 1943 | for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { |
@@ -2435,7 +2430,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | |||
2435 | 2430 | ||
2436 | if (!rule) { | 2431 | if (!rule) { |
2437 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 2432 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
2438 | "selinux_audit_rule_match: missing rule\n"); | 2433 | "selinux_audit_rule_match: missing rule\n"); |
2439 | return -ENOENT; | 2434 | return -ENOENT; |
2440 | } | 2435 | } |
2441 | 2436 | ||
@@ -2443,7 +2438,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | |||
2443 | 2438 | ||
2444 | if (rule->au_seqno < latest_granting) { | 2439 | if (rule->au_seqno < latest_granting) { |
2445 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 2440 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
2446 | "selinux_audit_rule_match: stale rule\n"); | 2441 | "selinux_audit_rule_match: stale rule\n"); |
2447 | match = -ESTALE; | 2442 | match = -ESTALE; |
2448 | goto out; | 2443 | goto out; |
2449 | } | 2444 | } |
@@ -2451,8 +2446,8 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | |||
2451 | ctxt = sidtab_search(&sidtab, sid); | 2446 | ctxt = sidtab_search(&sidtab, sid); |
2452 | if (!ctxt) { | 2447 | if (!ctxt) { |
2453 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 2448 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, |
2454 | "selinux_audit_rule_match: unrecognized SID %d\n", | 2449 | "selinux_audit_rule_match: unrecognized SID %d\n", |
2455 | sid); | 2450 | sid); |
2456 | match = -ENOENT; | 2451 | match = -ENOENT; |
2457 | goto out; | 2452 | goto out; |
2458 | } | 2453 | } |
@@ -2498,36 +2493,36 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, | |||
2498 | case AUDIT_OBJ_LEV_LOW: | 2493 | case AUDIT_OBJ_LEV_LOW: |
2499 | case AUDIT_OBJ_LEV_HIGH: | 2494 | case AUDIT_OBJ_LEV_HIGH: |
2500 | level = ((field == AUDIT_SUBJ_SEN || | 2495 | level = ((field == AUDIT_SUBJ_SEN || |
2501 | field == AUDIT_OBJ_LEV_LOW) ? | 2496 | field == AUDIT_OBJ_LEV_LOW) ? |
2502 | &ctxt->range.level[0] : &ctxt->range.level[1]); | 2497 | &ctxt->range.level[0] : &ctxt->range.level[1]); |
2503 | switch (op) { | 2498 | switch (op) { |
2504 | case AUDIT_EQUAL: | 2499 | case AUDIT_EQUAL: |
2505 | match = mls_level_eq(&rule->au_ctxt.range.level[0], | 2500 | match = mls_level_eq(&rule->au_ctxt.range.level[0], |
2506 | level); | 2501 | level); |
2507 | break; | 2502 | break; |
2508 | case AUDIT_NOT_EQUAL: | 2503 | case AUDIT_NOT_EQUAL: |
2509 | match = !mls_level_eq(&rule->au_ctxt.range.level[0], | 2504 | match = !mls_level_eq(&rule->au_ctxt.range.level[0], |
2510 | level); | 2505 | level); |
2511 | break; | 2506 | break; |
2512 | case AUDIT_LESS_THAN: | 2507 | case AUDIT_LESS_THAN: |
2513 | match = (mls_level_dom(&rule->au_ctxt.range.level[0], | 2508 | match = (mls_level_dom(&rule->au_ctxt.range.level[0], |
2514 | level) && | 2509 | level) && |
2515 | !mls_level_eq(&rule->au_ctxt.range.level[0], | 2510 | !mls_level_eq(&rule->au_ctxt.range.level[0], |
2516 | level)); | 2511 | level)); |
2517 | break; | 2512 | break; |
2518 | case AUDIT_LESS_THAN_OR_EQUAL: | 2513 | case AUDIT_LESS_THAN_OR_EQUAL: |
2519 | match = mls_level_dom(&rule->au_ctxt.range.level[0], | 2514 | match = mls_level_dom(&rule->au_ctxt.range.level[0], |
2520 | level); | 2515 | level); |
2521 | break; | 2516 | break; |
2522 | case AUDIT_GREATER_THAN: | 2517 | case AUDIT_GREATER_THAN: |
2523 | match = (mls_level_dom(level, | 2518 | match = (mls_level_dom(level, |
2524 | &rule->au_ctxt.range.level[0]) && | 2519 | &rule->au_ctxt.range.level[0]) && |
2525 | !mls_level_eq(level, | 2520 | !mls_level_eq(level, |
2526 | &rule->au_ctxt.range.level[0])); | 2521 | &rule->au_ctxt.range.level[0])); |
2527 | break; | 2522 | break; |
2528 | case AUDIT_GREATER_THAN_OR_EQUAL: | 2523 | case AUDIT_GREATER_THAN_OR_EQUAL: |
2529 | match = mls_level_dom(level, | 2524 | match = mls_level_dom(level, |
2530 | &rule->au_ctxt.range.level[0]); | 2525 | &rule->au_ctxt.range.level[0]); |
2531 | break; | 2526 | break; |
2532 | } | 2527 | } |
2533 | } | 2528 | } |
@@ -2554,7 +2549,7 @@ static int __init aurule_init(void) | |||
2554 | int err; | 2549 | int err; |
2555 | 2550 | ||
2556 | err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, | 2551 | err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, |
2557 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); | 2552 | SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); |
2558 | if (err) | 2553 | if (err) |
2559 | panic("avc_add_callback() failed, error %d\n", err); | 2554 | panic("avc_add_callback() failed, error %d\n", err); |
2560 | 2555 | ||