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>
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 743c35f..b280c1b 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -570,16 +570,42 @@
 	do {
 		tomoyo_check_acl(r, tomoyo_check_path_acl);
 		error = tomoyo_audit_path_log(r);
-		/*
-		 * Do not retry for execute request, for alias may have
-		 * changed.
-		 */
-	} while (error == TOMOYO_RETRY_REQUEST &&
-		 operation != TOMOYO_TYPE_EXECUTE);
+	} while (error == TOMOYO_RETRY_REQUEST);
 	return error;
 }
 
 /**
+ * tomoyo_execute_permission - Check permission for execute operation.
+ *
+ * @r:         Pointer to "struct tomoyo_request_info".
+ * @filename:  Filename to check.
+ *
+ * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
+ */
+int tomoyo_execute_permission(struct tomoyo_request_info *r,
+			      const struct tomoyo_path_info *filename)
+{
+	/*
+	 * Unlike other permission checks, this check is done regardless of
+	 * profile mode settings in order to check for domain transition
+	 * preference.
+	 */
+	r->type = TOMOYO_MAC_FILE_EXECUTE;
+	r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
+	r->param_type = TOMOYO_TYPE_PATH_ACL;
+	r->param.path.filename = filename;
+	r->param.path.operation = TOMOYO_TYPE_EXECUTE;
+	tomoyo_check_acl(r, tomoyo_check_path_acl);
+	r->ee->transition = r->matched_acl && r->matched_acl->cond ?
+		r->matched_acl->cond->transit : NULL;
+	if (r->mode != TOMOYO_CONFIG_DISABLED)
+		return tomoyo_audit_path_log(r);
+	return 0;
+}
+
+/**
  * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
  *
  * @a: Pointer to "struct tomoyo_acl_info".