summaryrefslogtreecommitdiff
path: root/security/tomoyo/domain.c
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2011-09-16 22:54:25 +0900
committerJames Morris <jmorris@namei.org>2011-09-19 10:09:59 +1000
commit6bce98edc3365a8f780ff3944ac7992544c194fe (patch)
treeee10abf2345f651d65d7f10fd385c01e0dc891b3 /security/tomoyo/domain.c
parentcc100551b4d92f47abebfa7c7918b2be71263b4a (diff)
TOMOYO: Allow specifying domain transition preference.
I got an opinion that it is difficult to use exception policy's domain transition control directives because they need to match the pathname specified to "file execute" directives. For example, if "file execute /bin/\*\-ls\-cat" is given, corresponding domain transition control directive needs to be like "no_keep_domain /bin/\*\-ls\-cat from any". If we can specify like below, it will become more convenient. file execute /bin/ls keep exec.realpath="/bin/ls" exec.argv[0]="ls" file execute /bin/cat keep exec.realpath="/bin/cat" exec.argv[0]="cat" file execute /bin/\*\-ls\-cat child file execute /usr/sbin/httpd <apache> exec.realpath="/usr/sbin/httpd" exec.argv[0]="/usr/sbin/httpd" In above examples, "keep" works as if keep_domain is specified, "child" works as if "no_reset_domain" and "no_initialize_domain" and "no_keep_domain" are specified, "<apache>" causes domain transition to <apache> domain upon successful execve() operation. Moreover, we can also allow transition to different domains based on conditions like below example. <kernel> /usr/sbin/sshd file execute /bin/bash <kernel> /usr/sbin/sshd //batch-session exec.argc=2 exec.argv[1]="-c" file execute /bin/bash <kernel> /usr/sbin/sshd //root-session task.uid=0 file execute /bin/bash <kernel> /usr/sbin/sshd //nonroot-session task.uid!=0 Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo/domain.c')
-rw-r--r--security/tomoyo/domain.c53
1 files changed, 50 insertions, 3 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index a1fc6b5f6125..860390ee1fbe 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,
new_entry->cond = tomoyo_get_condition(param);
if (!new_entry->cond)
return -EINVAL;
+ /*
+ * Domain transition preference is allowed for only
+ * "file execute" entries.
+ */
+ if (new_entry->cond->transit &&
+ !(new_entry->type == TOMOYO_TYPE_PATH_ACL &&
+ container_of(new_entry, struct tomoyo_path_acl, head)
+ ->perm == 1 << TOMOYO_TYPE_EXECUTE))
+ goto out;
}
if (mutex_lock_interruptible(&tomoyo_policy_lock))
goto out;
@@ -707,8 +716,7 @@ retry:
}
/* Check execute permission. */
- retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE,
- candidate);
+ retval = tomoyo_execute_permission(&ee->r, candidate);
if (retval == TOMOYO_RETRY_REQUEST)
goto retry;
if (retval < 0)
@@ -722,10 +730,45 @@ retry:
if (ee->r.param.path.matched_path)
candidate = ee->r.param.path.matched_path;
- /* Calculate domain to transit to. */
+ /*
+ * Check for domain transition preference if "file execute" matched.
+ * If preference is given, make do_execve() fail if domain transition
+ * has failed, for domain transition preference should be used with
+ * destination domain defined.
+ */
+ if (ee->transition) {
+ const char *domainname = ee->transition->name;
+ reject_on_transition_failure = true;
+ if (!strcmp(domainname, "keep"))
+ goto force_keep_domain;
+ if (!strcmp(domainname, "child"))
+ goto force_child_domain;
+ if (!strcmp(domainname, "reset"))
+ goto force_reset_domain;
+ if (!strcmp(domainname, "initialize"))
+ goto force_initialize_domain;
+ if (!strcmp(domainname, "parent")) {
+ char *cp;
+ strncpy(ee->tmp, old_domain->domainname->name,
+ TOMOYO_EXEC_TMPSIZE - 1);
+ cp = strrchr(ee->tmp, ' ');
+ if (cp)
+ *cp = '\0';
+ } else if (*domainname == '<')
+ strncpy(ee->tmp, domainname, TOMOYO_EXEC_TMPSIZE - 1);
+ else
+ snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
+ old_domain->domainname->name, domainname);
+ goto force_jump_domain;
+ }
+ /*
+ * No domain transition preference specified.
+ * Calculate domain to transit to.
+ */
switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname,
candidate)) {
case TOMOYO_TRANSITION_CONTROL_RESET:
+force_reset_domain:
/* Transit to the root of specified namespace. */
snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>",
candidate->name);
@@ -736,11 +779,13 @@ retry:
reject_on_transition_failure = true;
break;
case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
+force_initialize_domain:
/* Transit to the child of current namespace's root. */
snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
old_domain->ns->name, candidate->name);
break;
case TOMOYO_TRANSITION_CONTROL_KEEP:
+force_keep_domain:
/* Keep current domain. */
domain = old_domain;
break;
@@ -756,11 +801,13 @@ retry:
domain = old_domain;
break;
}
+force_child_domain:
/* Normal domain transition. */
snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
old_domain->domainname->name, candidate->name);
break;
}
+force_jump_domain:
if (!domain)
domain = tomoyo_assign_domain(ee->tmp, true);
if (domain)