TOMOYO: Allow using UID/GID etc. of current thread as conditions.

This patch adds support for permission checks using current thread's UID/GID
etc. in addition to pathnames.

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/gc.c b/security/tomoyo/gc.c
index 1e1a6c8..21fccd6 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -25,6 +25,7 @@
 	[TOMOYO_ID_TRANSITION_CONTROL] =
 	sizeof(struct tomoyo_transition_control),
 	[TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager),
+	/* [TOMOYO_ID_CONDITION] = "struct tomoyo_condition"->size, */
 	/* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */
 	/* [TOMOYO_ID_ACL] =
 	   tomoyo_acl_size["struct tomoyo_acl_info"->type], */
@@ -162,6 +163,10 @@
 		entry->size = strlen(container_of(element,
 						  typeof(struct tomoyo_name),
 						  head.list)->entry.name) + 1;
+	else if (type == TOMOYO_ID_CONDITION)
+		entry->size =
+			container_of(element, typeof(struct tomoyo_condition),
+				     head.list)->size;
 	else
 		entry->size = tomoyo_element_size[type];
 	entry->element = element;
@@ -246,6 +251,7 @@
 {
 	struct tomoyo_acl_info *acl =
 		container_of(element, typeof(*acl), list);
+	tomoyo_put_condition(acl->cond);
 	switch (acl->type) {
 	case TOMOYO_TYPE_PATH_ACL:
 		{
@@ -338,6 +344,27 @@
 	return true;
 }
 
+/**
+ * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
+void tomoyo_del_condition(struct list_head *element)
+{
+	struct tomoyo_condition *cond = container_of(element, typeof(*cond),
+						     head.list);
+	const u16 condc = cond->condc;
+	const u16 numbers_count = cond->numbers_count;
+	unsigned int i;
+	const struct tomoyo_condition_element *condp
+		= (const struct tomoyo_condition_element *) (cond + 1);
+	struct tomoyo_number_union *numbers_p
+		= (struct tomoyo_number_union *) (condp + condc);
+	for (i = 0; i < numbers_count; i++)
+		tomoyo_put_number_union(numbers_p++);
+}
 
 /**
  * tomoyo_del_name - Delete members in "struct tomoyo_name".
@@ -494,15 +521,18 @@
 			}
 		}
 	}
-	for (i = 0; i < TOMOYO_MAX_HASH; i++) {
-		struct list_head *list = &tomoyo_name_list[i];
+	id = TOMOYO_ID_CONDITION;
+	for (i = 0; i < TOMOYO_MAX_HASH + 1; i++) {
+		struct list_head *list = !i ?
+			&tomoyo_condition_list : &tomoyo_name_list[i - 1];
 		struct tomoyo_shared_acl_head *ptr;
 		list_for_each_entry(ptr, list, list) {
 			if (atomic_read(&ptr->users))
 				continue;
-			if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list))
+			if (!tomoyo_add_to_gc(id, &ptr->list))
 				goto unlock;
 		}
+		id = TOMOYO_ID_NAME;
 	}
 unlock:
 	tomoyo_read_unlock(idx);
@@ -557,6 +587,9 @@
 		case TOMOYO_ID_MANAGER:
 			tomoyo_del_manager(element);
 			break;
+		case TOMOYO_ID_CONDITION:
+			tomoyo_del_condition(element);
+			break;
 		case TOMOYO_ID_NAME:
 			/*
 			 * Thirdly, defer until all "struct tomoyo_io_buffer"