aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo')
-rw-r--r--security/tomoyo/common.c4
-rw-r--r--security/tomoyo/common.h4
-rw-r--r--security/tomoyo/condition.c50
-rw-r--r--security/tomoyo/domain.c53
-rw-r--r--security/tomoyo/file.c38
5 files changed, 137 insertions, 12 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 084018351b4..0994948f3ed 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -1203,6 +1203,10 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
1203 case 0: 1203 case 0:
1204 head->r.cond_index = 0; 1204 head->r.cond_index = 0;
1205 head->r.cond_step++; 1205 head->r.cond_step++;
1206 if (cond->transit) {
1207 tomoyo_set_space(head);
1208 tomoyo_set_string(head, cond->transit->name);
1209 }
1206 /* fall through */ 1210 /* fall through */
1207 case 1: 1211 case 1:
1208 { 1212 {
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 471c9f9afc1..a2bc33fc60b 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -615,6 +615,7 @@ struct tomoyo_execve {
615 struct tomoyo_request_info r; 615 struct tomoyo_request_info r;
616 struct tomoyo_obj_info obj; 616 struct tomoyo_obj_info obj;
617 struct linux_binprm *bprm; 617 struct linux_binprm *bprm;
618 const struct tomoyo_path_info *transition;
618 /* For dumping argv[] and envp[]. */ 619 /* For dumping argv[] and envp[]. */
619 struct tomoyo_page_dump dump; 620 struct tomoyo_page_dump dump;
620 /* For temporary use. */ 621 /* For temporary use. */
@@ -650,6 +651,7 @@ struct tomoyo_condition {
650 u16 argc; /* Number of "struct tomoyo_argv". */ 651 u16 argc; /* Number of "struct tomoyo_argv". */
651 u16 envc; /* Number of "struct tomoyo_envp". */ 652 u16 envc; /* Number of "struct tomoyo_envp". */
652 u8 grant_log; /* One of values in "enum tomoyo_grant_log". */ 653 u8 grant_log; /* One of values in "enum tomoyo_grant_log". */
654 const struct tomoyo_path_info *transit; /* Maybe NULL. */
653 /* 655 /*
654 * struct tomoyo_condition_element condition[condc]; 656 * struct tomoyo_condition_element condition[condc];
655 * struct tomoyo_number_union values[numbers_count]; 657 * struct tomoyo_number_union values[numbers_count];
@@ -956,6 +958,8 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
956 struct path *path, const int flag); 958 struct path *path, const int flag);
957int tomoyo_close_control(struct tomoyo_io_buffer *head); 959int tomoyo_close_control(struct tomoyo_io_buffer *head);
958int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env); 960int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env);
961int tomoyo_execute_permission(struct tomoyo_request_info *r,
962 const struct tomoyo_path_info *filename);
959int tomoyo_find_next_domain(struct linux_binprm *bprm); 963int tomoyo_find_next_domain(struct linux_binprm *bprm);
960int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, 964int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
961 const u8 index); 965 const u8 index);
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c
index 3a05eb3e2a6..b854959c0fd 100644
--- a/security/tomoyo/condition.c
+++ b/security/tomoyo/condition.c
@@ -348,7 +348,7 @@ static inline bool tomoyo_same_condition(const struct tomoyo_condition *a,
348 a->numbers_count == b->numbers_count && 348 a->numbers_count == b->numbers_count &&
349 a->names_count == b->names_count && 349 a->names_count == b->names_count &&
350 a->argc == b->argc && a->envc == b->envc && 350 a->argc == b->argc && a->envc == b->envc &&
351 a->grant_log == b->grant_log && 351 a->grant_log == b->grant_log && a->transit == b->transit &&
352 !memcmp(a + 1, b + 1, a->size - sizeof(*a)); 352 !memcmp(a + 1, b + 1, a->size - sizeof(*a));
353} 353}
354 354
@@ -429,6 +429,46 @@ out:
429} 429}
430 430
431/** 431/**
432 * tomoyo_get_transit_preference - Parse domain transition preference for execve().
433 *
434 * @param: Pointer to "struct tomoyo_acl_param".
435 * @e: Pointer to "struct tomoyo_condition".
436 *
437 * Returns the condition string part.
438 */
439static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param,
440 struct tomoyo_condition *e)
441{
442 char * const pos = param->data;
443 bool flag;
444 if (*pos == '<') {
445 e->transit = tomoyo_get_domainname(param);
446 goto done;
447 }
448 {
449 char *cp = strchr(pos, ' ');
450 if (cp)
451 *cp = '\0';
452 flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") ||
453 !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
454 !strcmp(pos, "child") || !strcmp(pos, "parent");
455 if (cp)
456 *cp = ' ';
457 }
458 if (!flag)
459 return pos;
460 e->transit = tomoyo_get_name(tomoyo_read_token(param));
461done:
462 if (e->transit)
463 return param->data;
464 /*
465 * Return a bad read-only condition string that will let
466 * tomoyo_get_condition() return NULL.
467 */
468 return "/";
469}
470
471/**
432 * tomoyo_get_condition - Parse condition part. 472 * tomoyo_get_condition - Parse condition part.
433 * 473 *
434 * @param: Pointer to "struct tomoyo_acl_param". 474 * @param: Pointer to "struct tomoyo_acl_param".
@@ -444,7 +484,8 @@ struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param)
444 struct tomoyo_argv *argv = NULL; 484 struct tomoyo_argv *argv = NULL;
445 struct tomoyo_envp *envp = NULL; 485 struct tomoyo_envp *envp = NULL;
446 struct tomoyo_condition e = { }; 486 struct tomoyo_condition e = { };
447 char * const start_of_string = param->data; 487 char * const start_of_string =
488 tomoyo_get_transit_preference(param, &e);
448 char * const end_of_string = start_of_string + strlen(start_of_string); 489 char * const end_of_string = start_of_string + strlen(start_of_string);
449 char *pos; 490 char *pos;
450rerun: 491rerun:
@@ -608,8 +649,9 @@ store_value:
608 + e.envc * sizeof(struct tomoyo_envp); 649 + e.envc * sizeof(struct tomoyo_envp);
609 entry = kzalloc(e.size, GFP_NOFS); 650 entry = kzalloc(e.size, GFP_NOFS);
610 if (!entry) 651 if (!entry)
611 return NULL; 652 goto out2;
612 *entry = e; 653 *entry = e;
654 e.transit = NULL;
613 condp = (struct tomoyo_condition_element *) (entry + 1); 655 condp = (struct tomoyo_condition_element *) (entry + 1);
614 numbers_p = (struct tomoyo_number_union *) (condp + e.condc); 656 numbers_p = (struct tomoyo_number_union *) (condp + e.condc);
615 names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count); 657 names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count);
@@ -636,6 +678,8 @@ out:
636 tomoyo_del_condition(&entry->head.list); 678 tomoyo_del_condition(&entry->head.list);
637 kfree(entry); 679 kfree(entry);
638 } 680 }
681out2:
682 tomoyo_put_name(e.transit);
639 return NULL; 683 return NULL;
640} 684}
641 685
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index a1fc6b5f612..860390ee1fb 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -102,6 +102,15 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
102 new_entry->cond = tomoyo_get_condition(param); 102 new_entry->cond = tomoyo_get_condition(param);
103 if (!new_entry->cond) 103 if (!new_entry->cond)
104 return -EINVAL; 104 return -EINVAL;
105 /*
106 * Domain transition preference is allowed for only
107 * "file execute" entries.
108 */
109 if (new_entry->cond->transit &&
110 !(new_entry->type == TOMOYO_TYPE_PATH_ACL &&
111 container_of(new_entry, struct tomoyo_path_acl, head)
112 ->perm == 1 << TOMOYO_TYPE_EXECUTE))
113 goto out;
105 } 114 }
106 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 115 if (mutex_lock_interruptible(&tomoyo_policy_lock))
107 goto out; 116 goto out;
@@ -707,8 +716,7 @@ retry:
707 } 716 }
708 717
709 /* Check execute permission. */ 718 /* Check execute permission. */
710 retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE, 719 retval = tomoyo_execute_permission(&ee->r, candidate);
711 candidate);
712 if (retval == TOMOYO_RETRY_REQUEST) 720 if (retval == TOMOYO_RETRY_REQUEST)
713 goto retry; 721 goto retry;
714 if (retval < 0) 722 if (retval < 0)
@@ -722,10 +730,45 @@ retry:
722 if (ee->r.param.path.matched_path) 730 if (ee->r.param.path.matched_path)
723 candidate = ee->r.param.path.matched_path; 731 candidate = ee->r.param.path.matched_path;
724 732
725 /* Calculate domain to transit to. */ 733 /*
734 * Check for domain transition preference if "file execute" matched.
735 * If preference is given, make do_execve() fail if domain transition
736 * has failed, for domain transition preference should be used with
737 * destination domain defined.
738 */
739 if (ee->transition) {
740 const char *domainname = ee->transition->name;
741 reject_on_transition_failure = true;
742 if (!strcmp(domainname, "keep"))
743 goto force_keep_domain;
744 if (!strcmp(domainname, "child"))
745 goto force_child_domain;
746 if (!strcmp(domainname, "reset"))
747 goto force_reset_domain;
748 if (!strcmp(domainname, "initialize"))
749 goto force_initialize_domain;
750 if (!strcmp(domainname, "parent")) {
751 char *cp;
752 strncpy(ee->tmp, old_domain->domainname->name,
753 TOMOYO_EXEC_TMPSIZE - 1);
754 cp = strrchr(ee->tmp, ' ');
755 if (cp)
756 *cp = '\0';
757 } else if (*domainname == '<')
758 strncpy(ee->tmp, domainname, TOMOYO_EXEC_TMPSIZE - 1);
759 else
760 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
761 old_domain->domainname->name, domainname);
762 goto force_jump_domain;
763 }
764 /*
765 * No domain transition preference specified.
766 * Calculate domain to transit to.
767 */
726 switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname, 768 switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname,
727 candidate)) { 769 candidate)) {
728 case TOMOYO_TRANSITION_CONTROL_RESET: 770 case TOMOYO_TRANSITION_CONTROL_RESET:
771force_reset_domain:
729 /* Transit to the root of specified namespace. */ 772 /* Transit to the root of specified namespace. */
730 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", 773 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>",
731 candidate->name); 774 candidate->name);
@@ -736,11 +779,13 @@ retry:
736 reject_on_transition_failure = true; 779 reject_on_transition_failure = true;
737 break; 780 break;
738 case TOMOYO_TRANSITION_CONTROL_INITIALIZE: 781 case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
782force_initialize_domain:
739 /* Transit to the child of current namespace's root. */ 783 /* Transit to the child of current namespace's root. */
740 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", 784 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
741 old_domain->ns->name, candidate->name); 785 old_domain->ns->name, candidate->name);
742 break; 786 break;
743 case TOMOYO_TRANSITION_CONTROL_KEEP: 787 case TOMOYO_TRANSITION_CONTROL_KEEP:
788force_keep_domain:
744 /* Keep current domain. */ 789 /* Keep current domain. */
745 domain = old_domain; 790 domain = old_domain;
746 break; 791 break;
@@ -756,11 +801,13 @@ retry:
756 domain = old_domain; 801 domain = old_domain;
757 break; 802 break;
758 } 803 }
804force_child_domain:
759 /* Normal domain transition. */ 805 /* Normal domain transition. */
760 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", 806 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
761 old_domain->domainname->name, candidate->name); 807 old_domain->domainname->name, candidate->name);
762 break; 808 break;
763 } 809 }
810force_jump_domain:
764 if (!domain) 811 if (!domain)
765 domain = tomoyo_assign_domain(ee->tmp, true); 812 domain = tomoyo_assign_domain(ee->tmp, true);
766 if (domain) 813 if (domain)
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 743c35f5084..b280c1bd652 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -570,16 +570,42 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
570 do { 570 do {
571 tomoyo_check_acl(r, tomoyo_check_path_acl); 571 tomoyo_check_acl(r, tomoyo_check_path_acl);
572 error = tomoyo_audit_path_log(r); 572 error = tomoyo_audit_path_log(r);
573 /* 573 } while (error == TOMOYO_RETRY_REQUEST);
574 * Do not retry for execute request, for alias may have
575 * changed.
576 */
577 } while (error == TOMOYO_RETRY_REQUEST &&
578 operation != TOMOYO_TYPE_EXECUTE);
579 return error; 574 return error;
580} 575}
581 576
582/** 577/**
578 * tomoyo_execute_permission - Check permission for execute operation.
579 *
580 * @r: Pointer to "struct tomoyo_request_info".
581 * @filename: Filename to check.
582 *
583 * Returns 0 on success, negative value otherwise.
584 *
585 * Caller holds tomoyo_read_lock().
586 */
587int tomoyo_execute_permission(struct tomoyo_request_info *r,
588 const struct tomoyo_path_info *filename)
589{
590 /*
591 * Unlike other permission checks, this check is done regardless of
592 * profile mode settings in order to check for domain transition
593 * preference.
594 */
595 r->type = TOMOYO_MAC_FILE_EXECUTE;
596 r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
597 r->param_type = TOMOYO_TYPE_PATH_ACL;
598 r->param.path.filename = filename;
599 r->param.path.operation = TOMOYO_TYPE_EXECUTE;
600 tomoyo_check_acl(r, tomoyo_check_path_acl);
601 r->ee->transition = r->matched_acl && r->matched_acl->cond ?
602 r->matched_acl->cond->transit : NULL;
603 if (r->mode != TOMOYO_CONFIG_DISABLED)
604 return tomoyo_audit_path_log(r);
605 return 0;
606}
607
608/**
583 * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry. 609 * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
584 * 610 *
585 * @a: Pointer to "struct tomoyo_acl_info". 611 * @a: Pointer to "struct tomoyo_acl_info".