lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 10 Jun 2010 21:08:49 +0900
From:	Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
To:	linux-security-module@...r.kernel.org
Cc:	linux-kernel@...r.kernel.org
Subject: [PATCH 1/4] TOMOYO: Add caller task's credential condition support.

This patch allows users to check caller task's UID/GID etc. for each request.
For example,

  allow_read /tmp/file if task.uid=0

will allow opening /tmp/file for reading only if the caller task's UID is 0.

Signed-off-by: Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
---
 security/tomoyo/Makefile    |    2 
 security/tomoyo/common.c    |  199 ++++++++++++++++++++----
 security/tomoyo/common.h    |   98 +++++++++++
 security/tomoyo/condition.c |  364 ++++++++++++++++++++++++++++++++++++++++++++
 security/tomoyo/domain.c    |   17 +-
 security/tomoyo/file.c      |   62 +++++--
 security/tomoyo/gc.c        |   43 +++++
 security/tomoyo/memory.c    |    4 
 security/tomoyo/mount.c     |   13 +
 9 files changed, 733 insertions(+), 69 deletions(-)

--- security-testing-2.6.orig/security/tomoyo/Makefile
+++ security-testing-2.6/security/tomoyo/Makefile
@@ -1 +1 @@
-obj-y = common.o domain.o file.o gc.o load_policy.o memory.o mount.o number_group.o path_group.o realpath.o securityfs_if.o tomoyo.o util.o
+obj-y = condition.o common.o domain.o file.o gc.o load_policy.o memory.o mount.o number_group.o path_group.o realpath.o securityfs_if.o tomoyo.o util.o
--- security-testing-2.6.orig/security/tomoyo/common.c
+++ security-testing-2.6/security/tomoyo/common.c
@@ -85,7 +85,7 @@ static const char *tomoyo_yesno(const un
  * Returns true on success, false otherwise.
  */
 static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head,
-				 const struct tomoyo_name_union *ptr)
+				    const struct tomoyo_name_union *ptr)
 {
 	int pos = head->read_avail;
 	if (pos && head->read_buf[pos - 1] == ' ')
@@ -97,25 +97,27 @@ static bool tomoyo_print_name_union(stru
 }
 
 /**
- * tomoyo_print_number_union - Print a tomoyo_number_union.
+ * tomoyo_print_number_union_common - Print a tomoyo_number_union.
  *
  * @head:       Pointer to "struct tomoyo_io_buffer".
  * @ptr:        Pointer to "struct tomoyo_number_union".
+ * @need_space: True if a space character is needed.
  *
  * Returns true on success, false otherwise.
  */
-bool tomoyo_print_number_union(struct tomoyo_io_buffer *head,
-			       const struct tomoyo_number_union *ptr)
+static bool tomoyo_print_number_union_common(struct tomoyo_io_buffer *head,
+					  const struct tomoyo_number_union *ptr,
+					  const bool need_space)
 {
 	unsigned long min;
 	unsigned long max;
 	u8 min_type;
 	u8 max_type;
-	if (!tomoyo_io_printf(head, " "))
+	if (need_space && !tomoyo_io_printf(head, " "))
 		return false;
 	if (ptr->is_group)
 		return tomoyo_io_printf(head, "@%s",
-					ptr->group->group_name->name);
+				     ptr->group->group_name->name);
 	min_type = ptr->min_type;
 	max_type = ptr->max_type;
 	min = ptr->values[0];
@@ -147,6 +149,35 @@ bool tomoyo_print_number_union(struct to
 }
 
 /**
+ * tomoyo_print_number_union - Print a tomoyo_number_union.
+ *
+ * @head:       Pointer to "struct tomoyo_io_buffer".
+ * @ptr:        Pointer to "struct tomoyo_number_union".
+ *
+ * Returns true on success, false otherwise.
+ */
+bool tomoyo_print_number_union(struct tomoyo_io_buffer *head,
+			    const struct tomoyo_number_union *ptr)
+{
+	return tomoyo_print_number_union_common(head, ptr, true);
+}
+
+/**
+ * tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space character.
+ *
+ * @head:       Pointer to "struct tomoyo_io_buffer".
+ * @ptr:        Pointer to "struct tomoyo_number_union".
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_print_number_union_nospace(struct tomoyo_io_buffer *head,
+					      const struct tomoyo_number_union
+					      *ptr)
+{
+	return tomoyo_print_number_union_common(head, ptr, false);
+}
+
+/**
  * tomoyo_io_printf - Transactional printf() to "struct tomoyo_io_buffer" structure.
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
@@ -729,11 +760,39 @@ static int tomoyo_delete_domain(char *do
  */
 static int tomoyo_write_domain_policy2(char *data,
 				       struct tomoyo_domain_info *domain,
+				       struct tomoyo_condition *cond,
 				       const bool is_delete)
 {
 	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_MOUNT))
-                return tomoyo_write_mount_policy(data, domain, is_delete);
-	return tomoyo_write_file_policy(data, domain, is_delete);
+		return tomoyo_write_mount_policy(data, domain, cond, is_delete);
+	return tomoyo_write_file_policy(data, domain, cond, is_delete);
+}
+
+/**
+ * tomoyo_find_condition_part - Find condition part from the statement.
+ *
+ * @data: String to parse.
+ *
+ * Returns pointer to the condition part if it was found in the statement,
+ * NULL otherwise.
+ */
+static char *tomoyo_find_condition_part(char *data)
+{
+	char *cp = strstr(data, " if ");
+	if (cp) {
+		while (1) {
+			char *cp2 = strstr(cp + 3, " if ");
+			if (!cp2)
+				break;
+			cp = cp2;
+		}
+		*cp++ = '\0';
+	} else {
+		cp = strstr(data, " ; set ");
+		if (cp)
+			*cp++ = '\0';
+	}
+	return cp;
 }
 
 /**
@@ -752,6 +811,9 @@ static int tomoyo_write_domain_policy(st
 	bool is_delete = false;
 	bool is_select = false;
 	unsigned int profile;
+	struct tomoyo_condition *cond = NULL;
+	char *cp;
+	int error;
 
 	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE))
 		is_delete = true;
@@ -794,7 +856,82 @@ static int tomoyo_write_domain_policy(st
 		domain->transition_failed = !is_delete;
 		return 0;
 	}
-	return tomoyo_write_domain_policy2(data, domain, is_delete);
+	cp = tomoyo_find_condition_part(data);
+	if (cp) {
+		cond = tomoyo_get_condition(cp);
+		if (!cond)
+			return -EINVAL;
+	}
+	error = tomoyo_write_domain_policy2(data, domain, cond, is_delete);
+	if (cond)
+		tomoyo_put_condition(cond);
+	return error;
+}
+
+/**
+ * tomoyo_print_condition - Print condition part.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @cond: Pointer to "struct tomoyo_condition". May be NULL.
+ *
+ * Returns true on success, false otherwise.
+ */
+static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
+				   const struct tomoyo_condition *cond)
+{
+	const struct tomoyo_condition_element *condp;
+	const struct tomoyo_number_union *numbers_p;
+	u16 condc;
+	u16 i;
+	char buffer[32];
+	if (!cond)
+		goto no_condition;
+	condc = cond->condc;
+	condp = (const struct tomoyo_condition_element *) (cond + 1);
+	numbers_p = (const struct tomoyo_number_union *) (condp + condc);
+	memset(buffer, 0, sizeof(buffer));
+	if (condc && !tomoyo_io_printf(head, "%s", " if"))
+		goto out;
+	for (i = 0; i < condc; i++) {
+		const u8 match = condp->equals;
+		const u8 left = condp->left;
+		const u8 right = condp->right;
+		condp++;
+		switch (left) {
+		case TOMOYO_NUMBER_UNION:
+			if (!tomoyo_print_number_union(head, numbers_p++))
+				goto out;
+			break;
+		default:
+			if (left >= TOMOYO_MAX_CONDITION_KEYWORD)
+				goto out;
+			if (!tomoyo_io_printf(head, " %s",
+					   tomoyo_condition_keyword[left]))
+				goto out;
+			break;
+		}
+		if (!tomoyo_io_printf(head, "%s", match ? "=" : "!="))
+			goto out;
+		switch (right) {
+		case TOMOYO_NUMBER_UNION:
+			if (!tomoyo_print_number_union_nospace(head,
+							       numbers_p++))
+				goto out;
+			break;
+		default:
+			if (right >= TOMOYO_MAX_CONDITION_KEYWORD)
+				goto out;
+			if (!tomoyo_io_printf(head, "%s",
+					   tomoyo_condition_keyword[right]))
+				goto out;
+			break;
+		}
+	}
+ no_condition:
+	if (tomoyo_io_printf(head, "\n"))
+		return true;
+ out:
+	return false;
 }
 
 /**
@@ -802,11 +939,13 @@ static int tomoyo_write_domain_policy(st
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
  * @ptr:  Pointer to "struct tomoyo_path_acl".
+ * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
  *
  * Returns true on success, false otherwise.
  */
 static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head,
-				  struct tomoyo_path_acl *ptr)
+				  struct tomoyo_path_acl *ptr,
+				  const struct tomoyo_condition *cond)
 {
 	int pos;
 	u8 bit;
@@ -823,7 +962,7 @@ static bool tomoyo_print_path_acl(struct
 		if (!tomoyo_io_printf(head, "allow_%s ",
 				      tomoyo_path2keyword(bit)) ||
 		    !tomoyo_print_name_union(head, &ptr->name) ||
-		    !tomoyo_io_printf(head, "\n"))
+		    !tomoyo_print_condition(head, cond))
 			goto out;
 	}
 	head->read_bit = 0;
@@ -839,11 +978,13 @@ static bool tomoyo_print_path_acl(struct
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
  * @ptr:  Pointer to "struct tomoyo_path2_acl".
+ * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
  *
  * Returns true on success, false otherwise.
  */
 static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head,
-				   struct tomoyo_path2_acl *ptr)
+				   struct tomoyo_path2_acl *ptr,
+				   const struct tomoyo_condition *cond)
 {
 	int pos;
 	const u8 perm = ptr->perm;
@@ -857,7 +998,7 @@ static bool tomoyo_print_path2_acl(struc
 				      tomoyo_path22keyword(bit)) ||
 		    !tomoyo_print_name_union(head, &ptr->name1) ||
 		    !tomoyo_print_name_union(head, &ptr->name2) ||
-		    !tomoyo_io_printf(head, "\n"))
+		    !tomoyo_print_condition(head, cond))
 			goto out;
 	}
 	head->read_bit = 0;
@@ -873,11 +1014,13 @@ static bool tomoyo_print_path2_acl(struc
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
  * @ptr:  Pointer to "struct tomoyo_path_number_acl".
+ * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
  *
  * Returns true on success, false otherwise.
  */
 static bool tomoyo_print_path_number_acl(struct tomoyo_io_buffer *head,
-					 struct tomoyo_path_number_acl *ptr)
+					 struct tomoyo_path_number_acl *ptr,
+					 const struct tomoyo_condition *cond)
 {
 	int pos;
 	u8 bit;
@@ -891,7 +1034,7 @@ static bool tomoyo_print_path_number_acl
 				      tomoyo_path_number2keyword(bit)) ||
 		    !tomoyo_print_name_union(head, &ptr->name) ||
 		    !tomoyo_print_number_union(head, &ptr->number) ||
-		    !tomoyo_io_printf(head, "\n"))
+		    !tomoyo_print_condition(head, cond))
 			goto out;
 	}
 	head->read_bit = 0;
@@ -907,11 +1050,13 @@ static bool tomoyo_print_path_number_acl
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
  * @ptr:  Pointer to "struct tomoyo_path_number3_acl".
+ * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
  *
  * Returns true on success, false otherwise.
  */
 static bool tomoyo_print_path_number3_acl(struct tomoyo_io_buffer *head,
-					  struct tomoyo_path_number3_acl *ptr)
+					  struct tomoyo_path_number3_acl *ptr,
+					  const struct tomoyo_condition *cond)
 {
 	int pos;
 	u8 bit;
@@ -927,7 +1072,7 @@ static bool tomoyo_print_path_number3_ac
 		    !tomoyo_print_number_union(head, &ptr->mode) ||
 		    !tomoyo_print_number_union(head, &ptr->major) ||
 		    !tomoyo_print_number_union(head, &ptr->minor) ||
-		    !tomoyo_io_printf(head, "\n"))
+		    !tomoyo_print_condition(head, cond))
 			goto out;
 	}
 	head->read_bit = 0;
@@ -943,11 +1088,13 @@ static bool tomoyo_print_path_number3_ac
  *
  * @head: Pointer to "struct tomoyo_io_buffer".
  * @ptr:  Pointer to "struct tomoyo_mount_acl".
+ * @cond: Pointer to "struct tomoyo_condition". Maybe NULL.
  *
  * Returns true on success, false otherwise.
  */
 static bool tomoyo_print_mount_acl(struct tomoyo_io_buffer *head,
-				   struct tomoyo_mount_acl *ptr)
+				   struct tomoyo_mount_acl *ptr,
+				   const struct tomoyo_condition *cond)
 {
 	const int pos = head->read_avail;
 	if (ptr->is_deleted)
@@ -957,7 +1104,7 @@ static bool tomoyo_print_mount_acl(struc
 	    !tomoyo_print_name_union(head, &ptr->dir_name) ||
 	    !tomoyo_print_name_union(head, &ptr->fs_type) ||
 	    !tomoyo_print_number_union(head, &ptr->flags) ||
-	    !tomoyo_io_printf(head, "\n")) {
+	    !tomoyo_print_condition(head, cond)) {
 		head->read_avail = pos;
 		return false;
 	}
@@ -975,34 +1122,35 @@ static bool tomoyo_print_mount_acl(struc
 static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
 			       struct tomoyo_acl_info *ptr)
 {
+	const struct tomoyo_condition *cond = ptr->cond;
 	const u8 acl_type = ptr->type;
 
 	if (acl_type == TOMOYO_TYPE_PATH_ACL) {
 		struct tomoyo_path_acl *acl
 			= container_of(ptr, struct tomoyo_path_acl, head);
-		return tomoyo_print_path_acl(head, acl);
+		return tomoyo_print_path_acl(head, acl, cond);
 	}
 	if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
 		struct tomoyo_path2_acl *acl
 			= container_of(ptr, struct tomoyo_path2_acl, head);
-		return tomoyo_print_path2_acl(head, acl);
+		return tomoyo_print_path2_acl(head, acl, cond);
 	}
 	if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) {
 		struct tomoyo_path_number_acl *acl
 			= container_of(ptr, struct tomoyo_path_number_acl,
 				       head);
-		return tomoyo_print_path_number_acl(head, acl);
+		return tomoyo_print_path_number_acl(head, acl, cond);
 	}
 	if (acl_type == TOMOYO_TYPE_PATH_NUMBER3_ACL) {
 		struct tomoyo_path_number3_acl *acl
 			= container_of(ptr, struct tomoyo_path_number3_acl,
 				       head);
-		return tomoyo_print_path_number3_acl(head, acl);
+		return tomoyo_print_path_number3_acl(head, acl, cond);
 	}
 	if (acl_type == TOMOYO_TYPE_MOUNT_ACL) {
 		struct tomoyo_mount_acl *acl
 			= container_of(ptr, struct tomoyo_mount_acl, head);
-		return tomoyo_print_mount_acl(head, acl);
+		return tomoyo_print_mount_acl(head, acl, cond);
 	}
 	BUG(); /* This must not happen. */
 	return false;
@@ -1445,8 +1593,7 @@ int tomoyo_supervisor(struct tomoyo_requ
 		vsnprintf(buffer, len - 1, fmt, args);
 		va_end(args);
 		tomoyo_normalize_line(buffer);
-		tomoyo_write_domain_policy2(buffer, r->domain, false);
-		kfree(buffer);
+		tomoyo_write_domain_policy2(buffer, r->domain, NULL, false);
 		/* fall through */
 	case TOMOYO_CONFIG_PERMISSIVE:
 		return 0;
--- security-testing-2.6.orig/security/tomoyo/common.h
+++ security-testing-2.6/security/tomoyo/common.h
@@ -21,7 +21,7 @@
 #include <linux/list.h>
 #include <linux/cred.h>
 #include <linux/poll.h>
-struct linux_binprm;
+#include <linux/binfmts.h>
 
 /********** Constants definitions. **********/
 
@@ -182,20 +182,65 @@ enum tomoyo_mac_category_index {
 	TOMOYO_MAX_MAC_CATEGORY_INDEX
 };
 
+enum tomoyo_conditions_index {
+	TOMOYO_TASK_UID,             /* current_uid()   */
+	TOMOYO_TASK_EUID,            /* current_euid()  */
+	TOMOYO_TASK_SUID,            /* current_suid()  */
+	TOMOYO_TASK_FSUID,           /* current_fsuid() */
+	TOMOYO_TASK_GID,             /* current_gid()   */
+	TOMOYO_TASK_EGID,            /* current_egid()  */
+	TOMOYO_TASK_SGID,            /* current_sgid()  */
+	TOMOYO_TASK_FSGID,           /* current_fsgid() */
+	TOMOYO_TASK_PID,             /* sys_getpid()   */
+	TOMOYO_TASK_PPID,            /* sys_getppid()  */
+	TOMOYO_MAX_CONDITION_KEYWORD,
+	TOMOYO_NUMBER_UNION,
+};
+
 #define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */
 
 /********** Structure definitions. **********/
 
+struct tomoyo_condition_element {
+	/* Left hand operand. */
+	u8 left;
+	/*
+	 * Right hand operand. A "struct tomoyo_number_union" for
+	 * TOMOYO_NUMBER_UNION is attached to the tail of the array of this
+	 * struct.
+	 */
+	u8 right;
+	/* Equation operator. true if equals or overlaps, false otherwise. */
+	bool equals;
+};
+
+/* Structure for " if " part. */
+struct tomoyo_condition {
+	struct list_head list;
+	atomic_t users;
+	u32 size;
+	u16 condc;
+	u16 numbers_count;
+	/*
+	 * struct tomoyo_condition_element condition[condc];
+	 * struct tomoyo_number_union values[numbers_count];
+	 */
+};
+
+struct tomoyo_execve_entry;
+
 /*
  * tomoyo_request_info is a structure which is used for holding
  *
  * (1) Domain information of current process.
- * (2) How many retries are made for this request.
- * (3) Profile number used for this request.
- * (4) Access control mode of the profile.
+ * (2) Parameters specific to execve() request. NULL if not for execve().
+ * (3) How many retries are made for this request.
+ * (4) Profile number used for this request.
+ * (5) Access control mode of the profile.
  */
 struct tomoyo_request_info {
 	struct tomoyo_domain_info *domain;
+	struct tomoyo_execve_entry *ee;
 	u8 retry;
 	u8 profile;
 	u8 mode; /* One of tomoyo_mode_index . */
@@ -284,12 +329,21 @@ struct tomoyo_number_group_member {
 	struct tomoyo_number_union number;
 };
 
+/* Structure for execve() operation. */
+struct tomoyo_execve_entry {
+	struct tomoyo_request_info r;
+	int reader_idx;
+	/* For temporary use. */
+	char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */
+};
+
 /*
  * tomoyo_acl_info is a structure which is used for holding
  *
  *  (1) "list" which is linked to the ->acl_info_list of
  *      "struct tomoyo_domain_info"
- *  (2) "type" which tells type of the entry (either
+ *  (2) "cond" which tells optional conditions for this entry. Maybe NULL.
+ *  (3) "type" which tells type of the entry (either
  *      "struct tomoyo_path_acl" or "struct tomoyo_path2_acl").
  *
  * Packing "struct tomoyo_acl_info" allows
@@ -299,6 +353,7 @@ struct tomoyo_number_group_member {
  */
 struct tomoyo_acl_info {
 	struct list_head list;
+	struct tomoyo_condition *cond;
 	u8 type;
 } __packed;
 
@@ -697,6 +752,11 @@ struct tomoyo_profile {
 extern asmlinkage long sys_getpid(void);
 extern asmlinkage long sys_getppid(void);
 
+bool tomoyo_condition(struct tomoyo_request_info *r,
+		      const struct tomoyo_acl_info *acl);
+u8 tomoyo_parse_ulong(unsigned long *result, char **str);
+struct tomoyo_condition *tomoyo_get_condition(char * const condition);
+void tomoyo_del_condition(struct tomoyo_condition *cond);
 /* Check whether the given string starts with the given keyword. */
 bool tomoyo_str_starts(char **src, const char *find);
 /* Get tomoyo_realpath() of current process. */
@@ -817,11 +877,13 @@ int tomoyo_write_domain_keeper_policy(ch
  * "allow_link" entry in domain policy.
  */
 int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
+			     struct tomoyo_condition *cond,
 			     const bool is_delete);
 /* Create "allow_read" entry in exception policy. */
 int tomoyo_write_globally_readable_policy(char *data, const bool is_delete);
 /* Create "allow_mount" entry in domain policy. */
 int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain,
+			      struct tomoyo_condition *cond,
 			      const bool is_delete);
 /* Create "deny_rewrite" entry in exception policy. */
 int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
@@ -932,6 +994,7 @@ extern struct list_head tomoyo_globally_
 extern struct list_head tomoyo_pattern_list;
 extern struct list_head tomoyo_no_rewrite_list;
 extern struct list_head tomoyo_policy_manager_list;
+extern struct list_head tomoyo_condition_list;
 extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
 
 /* Lock for protecting policy. */
@@ -943,6 +1006,7 @@ extern bool tomoyo_policy_loaded;
 /* The kernel's domain. */
 extern struct tomoyo_domain_info tomoyo_kernel_domain;
 
+extern const char *tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD];
 extern unsigned int tomoyo_quota_for_query;
 extern unsigned int tomoyo_query_memory_size;
 
@@ -989,6 +1053,12 @@ static inline bool tomoyo_is_invalid(con
 	return c && (c <= ' ' || c >= 127);
 }
 
+static inline void tomoyo_put_condition(struct tomoyo_condition *cond)
+{
+	if (cond)
+		atomic_dec(&cond->users);
+}
+
 static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
 {
 	if (name) {
@@ -1010,6 +1080,14 @@ static inline void tomoyo_put_number_gro
 		atomic_dec(&group->users);
 }
 
+static inline void tomoyo_add_domain_acl(struct tomoyo_domain_info *domain,
+					 struct tomoyo_acl_info *acl)
+{
+	if (acl->cond)
+		atomic_inc(&acl->cond->users);
+	list_add_tail_rcu(&acl->list, &domain->acl_info_list);
+}
+
 static inline struct tomoyo_domain_info *tomoyo_domain(void)
 {
 	return current_cred()->security;
@@ -1024,7 +1102,7 @@ static inline struct tomoyo_domain_info 
 static inline bool tomoyo_is_same_acl_head(const struct tomoyo_acl_info *p1,
 					   const struct tomoyo_acl_info *p2)
 {
-	return p1->type == p2->type;
+	return p1->type == p2->type && p1->cond == p2->cond;
 }
 
 static inline bool tomoyo_is_same_name_union
@@ -1114,6 +1192,14 @@ static inline bool tomoyo_is_same_aggreg
 		p1->aggregated_name == p2->aggregated_name;
 }
 
+static inline bool tomoyo_is_same_condition(const struct tomoyo_condition *p1,
+					    const struct tomoyo_condition *p2)
+{
+	return p1->size == p2->size && p1->condc == p2->condc &&
+		p1->numbers_count == p2->numbers_count &&
+		!memcmp(p1 + 1, p2 + 1, p1->size - sizeof(*p1));
+}
+
 static inline bool tomoyo_is_same_alias_entry
 (const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2)
 {
--- /dev/null
+++ security-testing-2.6/security/tomoyo/condition.c
@@ -0,0 +1,364 @@
+/*
+ * security/tomoyo/condition.c
+ *
+ * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ */
+
+#include "common.h"
+#include <linux/slab.h>
+
+/* The list for "struct tomoyo_condition". */
+LIST_HEAD(tomoyo_condition_list);
+
+const char *tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = {
+	[TOMOYO_TASK_UID]             = "task.uid",
+	[TOMOYO_TASK_EUID]            = "task.euid",
+	[TOMOYO_TASK_SUID]            = "task.suid",
+	[TOMOYO_TASK_FSUID]           = "task.fsuid",
+	[TOMOYO_TASK_GID]             = "task.gid",
+	[TOMOYO_TASK_EGID]            = "task.egid",
+	[TOMOYO_TASK_SGID]            = "task.sgid",
+	[TOMOYO_TASK_FSGID]           = "task.fsgid",
+	[TOMOYO_TASK_PID]             = "task.pid",
+	[TOMOYO_TASK_PPID]            = "task.ppid",
+};
+
+/* #define DEBUG_CONDITION */
+
+#ifdef DEBUG_CONDITION
+#define dprintk printk
+#else
+#define dprintk(...) do { } while (0)
+#endif
+
+/**
+ * tomoyo_get_condition - Parse condition part.
+ *
+ * @condition: Pointer to string to parse.
+ *
+ * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise.
+ */
+struct tomoyo_condition *tomoyo_get_condition(char * const condition)
+{
+	char *start = condition;
+	struct tomoyo_condition *entry = NULL;
+	struct tomoyo_condition *ptr;
+	struct tomoyo_condition_element *condp;
+	struct tomoyo_number_union *numbers_p;
+	u32 size;
+	bool found = false;
+	u16 condc = 0;
+	u16 numbers_count = 0;
+	char *end_of_string;
+	start = condition;
+	if (!strncmp(start, "if ", 3))
+		start += 3;
+	else if (*start)
+		return NULL;
+	end_of_string = start + strlen(start);
+	while (1) {
+		u8 left;
+		u8 right;
+		char *word = start;
+		char *cp;
+		char *eq;
+		bool is_not = false;
+		if (!*word)
+			break;
+		cp = strchr(start, ' ');
+		if (cp) {
+			*cp = '\0';
+			start = cp + 1;
+		} else {
+			start = "";
+		}
+		dprintk(KERN_WARNING "%u: <%s>\n", __LINE__, word);
+		eq = strchr(word, '=');
+		if (!eq)
+			goto out;
+		if (eq > word && *(eq - 1) == '!') {
+			is_not = true;
+			eq--;
+		}
+		*eq = '\0';
+		for (left = 0; left < TOMOYO_MAX_CONDITION_KEYWORD; left++) {
+			if (strcmp(word, tomoyo_condition_keyword[left]))
+				continue;
+			break;
+		}
+		dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__,
+			word, left);
+		if (left == TOMOYO_MAX_CONDITION_KEYWORD)
+			numbers_count++;
+		*eq = is_not ? '!' : '=';
+		word = eq + 1;
+		if (is_not)
+			word++;
+		condc++;
+		dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__,
+			word, left);
+		for (right = 0; right < TOMOYO_MAX_CONDITION_KEYWORD; right++) {
+			if (strcmp(word, tomoyo_condition_keyword[right]))
+				continue;
+			break;
+		}
+		dprintk(KERN_WARNING "%u: <%s> right=%u\n", __LINE__,
+			word, right);
+		if (right == TOMOYO_MAX_CONDITION_KEYWORD)
+			numbers_count++;
+	}
+	dprintk(KERN_DEBUG "%u: cond=%u numbers=%u\n", __LINE__,
+		condc, numbers_count);
+	size = sizeof(*entry)
+		+ condc * sizeof(struct tomoyo_condition_element)
+		+ numbers_count * sizeof(struct tomoyo_number_union);
+	entry = kzalloc(size, GFP_NOFS);
+	if (!entry)
+		return NULL;
+	INIT_LIST_HEAD(&entry->list);
+	entry->condc = condc;
+	entry->numbers_count = numbers_count;
+	condp = (struct tomoyo_condition_element *) (entry + 1);
+	numbers_p = (struct tomoyo_number_union *) (condp + condc);
+	for (start = condition; start < end_of_string; start++)
+		if (!*start)
+			*start = ' ';
+	start = condition;
+	if (!strncmp(start, "if ", 3))
+		start += 3;
+	else if (*start)
+		goto out;
+	while (1) {
+		u8 left;
+		u8 right;
+		char *word = start;
+		char *cp;
+		char *eq;
+		bool is_not = false;
+		if (!*word)
+			break;
+		cp = strchr(start, ' ');
+		if (cp) {
+			*cp = '\0';
+			start = cp + 1;
+		} else {
+			start = "";
+		}
+		dprintk(KERN_WARNING "%u: <%s>\n", __LINE__, word);
+		eq = strchr(word, '=');
+		if (!eq) {
+			dprintk(KERN_WARNING "%u: No operator.\n",
+				__LINE__);
+			goto out;
+		}
+		if (eq > word && *(eq - 1) == '!') {
+			is_not = true;
+			eq--;
+		}
+		*eq = '\0';
+		for (left = 0; left < TOMOYO_MAX_CONDITION_KEYWORD; left++) {
+			if (strcmp(word, tomoyo_condition_keyword[left]))
+				continue;
+			break;
+		}
+		dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__,
+			word, left);
+		if (left == TOMOYO_MAX_CONDITION_KEYWORD) {
+			left = TOMOYO_NUMBER_UNION;
+			if (!tomoyo_parse_number_union(word, numbers_p))
+				goto out;
+			if (numbers_p->is_group)
+				goto out;
+			numbers_p++;
+			numbers_count--;
+		}
+		*eq = is_not ? '!' : '=';
+		word = eq + 1;
+		if (is_not)
+			word++;
+		condc--;
+		dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__,
+			word, left);
+		for (right = 0; right < TOMOYO_MAX_CONDITION_KEYWORD; right++) {
+			if (strcmp(word, tomoyo_condition_keyword[right]))
+				continue;
+			break;
+		}
+		if (right == TOMOYO_MAX_CONDITION_KEYWORD) {
+			right = TOMOYO_NUMBER_UNION;
+			if (!tomoyo_parse_number_union(word, numbers_p++))
+				goto out;
+			numbers_count--;
+		}
+		condp->left = left;
+		condp->right = right;
+		condp->equals = !is_not;
+		dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
+			__LINE__, condp->left, condp->right,
+			condp->equals);
+		condp++;
+	}
+#ifdef DEBUG_CONFITION
+	for (start = condition; start < end_of_string; start++)
+		if (!*start)
+			*start = ' ';
+	dprintk(KERN_DEBUG "%u: <%s> cond=%u numbers=%u\n",
+		__LINE__, condition, condc, numbers_count);
+	BUG_ON(numbers_count);
+	BUG_ON(condc);
+#else
+	BUG_ON(numbers_count | condc);
+#endif
+	entry->size = size;
+	if (mutex_lock_interruptible(&tomoyo_policy_lock))
+		goto out;
+	list_for_each_entry_rcu(ptr, &tomoyo_condition_list, list) {
+		if (!tomoyo_is_same_condition(ptr, entry))
+			continue;
+		/* Same entry found. Share this entry. */
+		atomic_inc(&ptr->users);
+		found = true;
+		break;
+	}
+	if (!found) {
+		if (tomoyo_memory_ok(entry)) {
+			atomic_set(&entry->users, 1);
+			list_add_rcu(&entry->list, &tomoyo_condition_list);
+		} else {
+			found = true;
+			ptr = NULL;
+		}
+	}
+	mutex_unlock(&tomoyo_policy_lock);
+	if (found) {
+		tomoyo_del_condition(entry);
+		kfree(entry);
+		entry = ptr;
+	}
+	return entry;
+ out:
+	dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
+	if (entry) {
+		tomoyo_del_condition(entry);
+		kfree(entry);
+	}
+	return NULL;
+}
+
+/**
+ * tomoyo_condition - Check condition part.
+ *
+ * @r:   Pointer to "struct tomoyo_request_info".
+ * @acl: Pointer to "struct tomoyo_acl_info".
+ *
+ * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
+ */
+bool tomoyo_condition(struct tomoyo_request_info *r,
+		      const struct tomoyo_acl_info *acl)
+{
+	u32 i;
+	unsigned long left_min = 0;
+	unsigned long left_max = 0;
+	unsigned long right_min = 0;
+	unsigned long right_max = 0;
+	const struct tomoyo_condition_element *condp;
+	const struct tomoyo_number_union *numbers_p;
+	u16 condc;
+	const struct tomoyo_condition *cond = acl->cond;
+	if (!cond)
+		return true;
+	condc = cond->condc;
+	condp = (struct tomoyo_condition_element *) (cond + 1);
+	numbers_p = (const struct tomoyo_number_union *) (condp + condc);
+	for (i = 0; i < condc; i++) {
+		const bool match = condp->equals;
+		const u8 left = condp->left;
+		const u8 right = condp->right;
+		u8 j;
+		condp++;
+		/* Check numeric or bit-op expressions. */
+		for (j = 0; j < 2; j++) {
+			const u8 index = j ? right : left;
+			unsigned long value = 0;
+			switch (index) {
+			case TOMOYO_TASK_UID:
+				value = current_uid();
+				break;
+			case TOMOYO_TASK_EUID:
+				value = current_euid();
+				break;
+			case TOMOYO_TASK_SUID:
+				value = current_suid();
+				break;
+			case TOMOYO_TASK_FSUID:
+				value = current_fsuid();
+				break;
+			case TOMOYO_TASK_GID:
+				value = current_gid();
+				break;
+			case TOMOYO_TASK_EGID:
+				value = current_egid();
+				break;
+			case TOMOYO_TASK_SGID:
+				value = current_sgid();
+				break;
+			case TOMOYO_TASK_FSGID:
+				value = current_fsgid();
+				break;
+			case TOMOYO_TASK_PID:
+				value = sys_getpid();
+				break;
+			case TOMOYO_TASK_PPID:
+				value = sys_getppid();
+				break;
+			case TOMOYO_NUMBER_UNION:
+				/* Fetch values later. */
+				break;
+			default:
+				goto out;
+			}
+			value = value;
+			if (j) {
+				right_max = value;
+				right_min = value;
+			} else {
+				left_max = value;
+				left_min = value;
+			}
+		}
+		if (left == TOMOYO_NUMBER_UNION) {
+			/* Fetch values now. */
+			const struct tomoyo_number_union *ptr = numbers_p++;
+			left_min = ptr->values[0];
+			left_max = ptr->values[1];
+		}
+		if (right == TOMOYO_NUMBER_UNION) {
+			/* Fetch values now. */
+			const struct tomoyo_number_union *ptr = numbers_p++;
+			if (ptr->is_group) {
+				if (tomoyo_number_matches_group(left_min,
+							     left_max,
+							     ptr->group)
+				    == match)
+					continue;
+			} else {
+				if ((left_min <= ptr->values[1] &&
+				     left_max >= ptr->values[0]) == match)
+					continue;
+			}
+			goto out;
+		}
+		if (match) {
+			if (left_min <= right_max && left_max >= right_min)
+				continue;
+		} else {
+			if (left_min > right_max || left_max < right_min)
+				continue;
+		}
+ out:
+		return false;
+	}
+	return true;
+}
--- security-testing-2.6.orig/security/tomoyo/domain.c
+++ security-testing-2.6/security/tomoyo/domain.c
@@ -9,6 +9,7 @@
 #include "common.h"
 #include <linux/binfmts.h>
 #include <linux/slab.h>
+#include <linux/highmem.h>
 
 /* Variables definitions.*/
 
@@ -806,13 +807,12 @@ struct tomoyo_domain_info *tomoyo_find_o
  */
 int tomoyo_find_next_domain(struct linux_binprm *bprm)
 {
+	char *tmp = kmalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
 	struct tomoyo_request_info r;
-	char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
 	struct tomoyo_domain_info *old_domain = tomoyo_domain();
 	struct tomoyo_domain_info *domain = NULL;
 	const char *old_domain_name = old_domain->domainname->name;
 	const char *original_name = bprm->filename;
-	u8 mode;
 	bool is_enforce;
 	int retval = -ENOMEM;
 	bool need_kfree = false;
@@ -820,13 +820,13 @@ int tomoyo_find_next_domain(struct linux
 	struct tomoyo_path_info sn = { }; /* symlink name */
 	struct tomoyo_path_info ln; /* last name */
 
-	ln.name = tomoyo_get_last_name(old_domain);
-	tomoyo_fill_path_info(&ln);
-	mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE);
-	is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
 	if (!tmp)
-		goto out;
+		return -ENOMEM;
+	tomoyo_init_request_info(&r, NULL, TOMOYO_TYPE_EXECUTE);
+	is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
 
+	ln.name = tomoyo_get_last_name(old_domain);
+	tomoyo_fill_path_info(&ln);
  retry:
 	if (need_kfree) {
 		kfree(rn.name);
@@ -924,7 +924,8 @@ int tomoyo_find_next_domain(struct linux
  done:
 	if (domain)
 		goto out;
-	printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp);
+	printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n",
+	       tmp);
 	if (is_enforce)
 		retval = -EPERM;
 	else
--- security-testing-2.6.orig/security/tomoyo/file.c
+++ security-testing-2.6/security/tomoyo/file.c
@@ -221,9 +221,11 @@ static bool tomoyo_get_realpath(struct t
 static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
 				   const char *filename2,
 				   struct tomoyo_domain_info *const domain,
+				   struct tomoyo_condition *cond,
 				   const bool is_delete);
 static int tomoyo_update_path_acl(const u8 type, const char *filename,
 				  struct tomoyo_domain_info *const domain,
+				  struct tomoyo_condition *cond,
 				  const bool is_delete);
 
 /*
@@ -670,6 +672,7 @@ bool tomoyo_read_no_rewrite_policy(struc
  * @perm:      Permission (between 1 to 7).
  * @filename:  Filename.
  * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @cond:      Pointer to "struct tomoyo_condition". Maybe NULL.
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
@@ -683,6 +686,7 @@ bool tomoyo_read_no_rewrite_policy(struc
  */
 static int tomoyo_update_file_acl(u8 perm, const char *filename,
 				  struct tomoyo_domain_info * const domain,
+				  struct tomoyo_condition *cond,
 				  const bool is_delete)
 {
 	if (perm > 7 || !perm) {
@@ -698,13 +702,13 @@ static int tomoyo_update_file_acl(u8 per
 		return 0;
 	if (perm & 4)
 		tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain,
-				       is_delete);
+				       cond, is_delete);
 	if (perm & 2)
 		tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain,
-				       is_delete);
+				       cond, is_delete);
 	if (perm & 1)
 		tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain,
-				       is_delete);
+				       cond, is_delete);
 	return 0;
 }
 
@@ -719,7 +723,7 @@ static int tomoyo_update_file_acl(u8 per
  *
  * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_path_acl(const struct tomoyo_request_info *r,
+static int tomoyo_path_acl(struct tomoyo_request_info *r,
 			   const struct tomoyo_path_info *filename,
 			   const u32 perm)
 {
@@ -733,7 +737,8 @@ static int tomoyo_path_acl(const struct 
 			continue;
 		acl = container_of(ptr, struct tomoyo_path_acl, head);
 		if (!(acl->perm & perm) ||
-		    !tomoyo_compare_name_union(filename, &acl->name))
+		    !tomoyo_compare_name_union(filename, &acl->name) ||
+		    !tomoyo_condition(r, ptr))
 			continue;
 		error = 0;
 		break;
@@ -803,6 +808,7 @@ static int tomoyo_file_perm(struct tomoy
  * @type:      Type of operation.
  * @filename:  Filename.
  * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @cond:      Pointer to "struct tomoyo_condition". Maybe NULL.
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
@@ -811,6 +817,7 @@ static int tomoyo_file_perm(struct tomoy
  */
 static int tomoyo_update_path_acl(const u8 type, const char *filename,
 				  struct tomoyo_domain_info *const domain,
+				  struct tomoyo_condition *cond,
 				  const bool is_delete)
 {
 	static const u16 tomoyo_rw_mask =
@@ -819,6 +826,7 @@ static int tomoyo_update_path_acl(const 
 	struct tomoyo_acl_info *ptr;
 	struct tomoyo_path_acl e = {
 		.head.type = TOMOYO_TYPE_PATH_ACL,
+		.head.cond = cond,
 		.perm = perm
 	};
 	int error = is_delete ? -ENOENT : -ENOMEM;
@@ -856,8 +864,7 @@ static int tomoyo_update_path_acl(const 
 		struct tomoyo_path_acl *entry =
 			tomoyo_commit_ok(&e, sizeof(e));
 		if (entry) {
-			list_add_tail_rcu(&entry->head.list,
-					  &domain->acl_info_list);
+			tomoyo_add_domain_acl(domain, &entry->head);
 			error = 0;
 		}
 	}
@@ -876,6 +883,7 @@ static int tomoyo_update_path_acl(const 
  * @major:     Device major number.
  * @minor:     Device minor number.
  * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @cond:      Pointer to "struct tomoyo_condition". Maybe NULL.
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
@@ -886,12 +894,14 @@ static inline int tomoyo_update_path_num
 						 char *major, char *minor,
 						 struct tomoyo_domain_info *
 						 const domain,
+						 struct tomoyo_condition *cond,
 						 const bool is_delete)
 {
 	const u8 perm = 1 << type;
 	struct tomoyo_acl_info *ptr;
 	struct tomoyo_path_number3_acl e = {
 		.head.type = TOMOYO_TYPE_PATH_NUMBER3_ACL,
+		.head.cond = cond,
 		.perm = perm
 	};
 	int error = is_delete ? -ENOENT : -ENOMEM;
@@ -918,8 +928,7 @@ static inline int tomoyo_update_path_num
 		struct tomoyo_path_number3_acl *entry =
 			tomoyo_commit_ok(&e, sizeof(e));
 		if (entry) {
-			list_add_tail_rcu(&entry->head.list,
-					  &domain->acl_info_list);
+			tomoyo_add_domain_acl(domain, &entry->head);
 			error = 0;
 		}
 	}
@@ -939,6 +948,7 @@ static inline int tomoyo_update_path_num
  * @filename1: First filename.
  * @filename2: Second filename.
  * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @cond:      Pointer to "struct tomoyo_condition". Maybe NULL.
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
@@ -948,11 +958,13 @@ static inline int tomoyo_update_path_num
 static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
 				   const char *filename2,
 				   struct tomoyo_domain_info *const domain,
+				   struct tomoyo_condition *cond,
 				   const bool is_delete)
 {
 	const u8 perm = 1 << type;
 	struct tomoyo_path2_acl e = {
 		.head.type = TOMOYO_TYPE_PATH2_ACL,
+		.head.cond = cond,
 		.perm = perm
 	};
 	struct tomoyo_acl_info *ptr;
@@ -981,8 +993,7 @@ static int tomoyo_update_path2_acl(const
 		struct tomoyo_path2_acl *entry =
 			tomoyo_commit_ok(&e, sizeof(e));
 		if (entry) {
-			list_add_tail_rcu(&entry->head.list,
-					  &domain->acl_info_list);
+			tomoyo_add_domain_acl(domain, &entry->head);
 			error = 0;
 		}
 	}
@@ -1031,6 +1042,8 @@ static int tomoyo_path_number3_acl(struc
 			continue;
 		if (!tomoyo_compare_name_union(filename, &acl->name))
 			continue;
+		if (!tomoyo_condition(r, ptr))
+			continue;
 		error = 0;
 		break;
 	}
@@ -1049,7 +1062,7 @@ static int tomoyo_path_number3_acl(struc
  *
  * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type,
+static int tomoyo_path2_acl(struct tomoyo_request_info *r, const u8 type,
 			    const struct tomoyo_path_info *filename1,
 			    const struct tomoyo_path_info *filename2)
 {
@@ -1069,6 +1082,8 @@ static int tomoyo_path2_acl(const struct
 			continue;
 		if (!tomoyo_compare_name_union(filename2, &acl->name2))
 			continue;
+		if (!tomoyo_condition(r, ptr))
+			continue;
 		error = 0;
 		break;
 	}
@@ -1149,7 +1164,8 @@ static int tomoyo_path_number_acl(struct
 				   head);
 		if (!(acl->perm & perm) ||
 		    !tomoyo_compare_number_union(number, &acl->number) ||
-		    !tomoyo_compare_name_union(filename, &acl->name))
+		    !tomoyo_compare_name_union(filename, &acl->name) ||
+		    !tomoyo_condition(r, ptr))
 			continue;
 		error = 0;
 		break;
@@ -1164,6 +1180,7 @@ static int tomoyo_path_number_acl(struct
  * @filename:  Filename.
  * @number:    Number.
  * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @cond:      Pointer to "struct tomoyo_condition". Maybe NULL.
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
@@ -1173,12 +1190,14 @@ static inline int tomoyo_update_path_num
 						char *number,
 						struct tomoyo_domain_info *
 						const domain,
+						struct tomoyo_condition *cond,
 						const bool is_delete)
 {
 	const u8 perm = 1 << type;
 	struct tomoyo_acl_info *ptr;
 	struct tomoyo_path_number_acl e = {
 		.head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
+		.head.cond = cond,
 		.perm = perm
 	};
 	int error = is_delete ? -ENOENT : -ENOMEM;
@@ -1206,8 +1225,7 @@ static inline int tomoyo_update_path_num
 		struct tomoyo_path_number_acl *entry =
 			tomoyo_commit_ok(&e, sizeof(e));
 		if (entry) {
-			list_add_tail_rcu(&entry->head.list,
-					  &domain->acl_info_list);
+			tomoyo_add_domain_acl(domain, &entry->head);
 			error = 0;
 		}
 	}
@@ -1572,6 +1590,7 @@ int tomoyo_path2_perm(const u8 operation
  *
  * @data:      String to parse.
  * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @cond:      Pointer to "struct tomoyo_condition". Maybe NULL.
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
@@ -1579,6 +1598,7 @@ int tomoyo_path2_perm(const u8 operation
  * Caller holds tomoyo_read_lock().
  */
 int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
+			     struct tomoyo_condition *cond,
 			     const bool is_delete)
 {
 	char *w[5];
@@ -1589,14 +1609,15 @@ int tomoyo_write_file_policy(char *data,
 		unsigned int perm;
 		if (sscanf(w[0], "%u", &perm) == 1)
 			return tomoyo_update_file_acl((u8) perm, w[1], domain,
-						      is_delete);
+						      cond, is_delete);
 		goto out;
 	}
 	w[0] += 6;
 	for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
 		if (strcmp(w[0], tomoyo_path_keyword[type]))
 			continue;
-		return tomoyo_update_path_acl(type, w[1], domain, is_delete);
+		return tomoyo_update_path_acl(type, w[1], domain, cond,
+					      is_delete);
 	}
 	if (!w[2][0])
 		goto out;
@@ -1604,13 +1625,13 @@ int tomoyo_write_file_policy(char *data,
 		if (strcmp(w[0], tomoyo_path2_keyword[type]))
 			continue;
 		return tomoyo_update_path2_acl(type, w[1], w[2], domain,
-					       is_delete);
+					       cond, is_delete);
 	}
 	for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) {
 		if (strcmp(w[0], tomoyo_path_number_keyword[type]))
 			continue;
 		return tomoyo_update_path_number_acl(type, w[1], w[2], domain,
-						     is_delete);
+						     cond, is_delete);
 	}
 	if (!w[3][0] || !w[4][0])
 		goto out;
@@ -1618,7 +1639,8 @@ int tomoyo_write_file_policy(char *data,
 		if (strcmp(w[0], tomoyo_path_number3_keyword[type]))
 			continue;
 		return tomoyo_update_path_number3_acl(type, w[1], w[2], w[3],
-						      w[4], domain, is_delete);
+						      w[4], domain, cond,
+						      is_delete);
 	}
  out:
 	return -EINVAL;
--- security-testing-2.6.orig/security/tomoyo/gc.c
+++ security-testing-2.6/security/tomoyo/gc.c
@@ -24,6 +24,7 @@ enum tomoyo_gc_id {
 	TOMOYO_ID_PATTERN,
 	TOMOYO_ID_NO_REWRITE,
 	TOMOYO_ID_MANAGER,
+	TOMOYO_ID_CONDITION,
 	TOMOYO_ID_NAME,
 	TOMOYO_ID_ACL,
 	TOMOYO_ID_DOMAIN
@@ -97,6 +98,7 @@ static void tomoyo_del_manager(struct to
 
 static void tomoyo_del_acl(struct tomoyo_acl_info *acl)
 {
+	tomoyo_put_condition(acl->cond);
 	switch (acl->type) {
 	case TOMOYO_TYPE_PATH_ACL:
 		{
@@ -183,6 +185,23 @@ static bool tomoyo_del_domain(struct tom
 	return true;
 }
 
+/**
+ * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
+ *
+ * @cond: Pointer to "struct tomoyo_condition".
+ */
+void tomoyo_del_condition(struct tomoyo_condition *cond)
+{
+	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++);
+}
 
 static void tomoyo_del_name(const struct tomoyo_name_entry *ptr)
 {
@@ -335,8 +354,14 @@ static void tomoyo_collect_entry(void)
 							 head)->perm)
 						continue;
 					break;
+				case TOMOYO_TYPE_MOUNT_ACL:
+					if (!container_of(acl,
+					 struct tomoyo_mount_acl,
+							  head)->is_deleted)
+						continue;
+					break;
 				default:
-					continue;
+						continue;
 				}
 				if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl))
 					list_del_rcu(&acl->list);
@@ -357,6 +382,17 @@ static void tomoyo_collect_entry(void)
 		}
 	}
 	{
+		struct tomoyo_condition *ptr;
+		list_for_each_entry_rcu(ptr, &tomoyo_condition_list, list) {
+			if (atomic_read(&ptr->users))
+				continue;
+			if (tomoyo_add_to_gc(TOMOYO_ID_CONDITION, ptr))
+				list_del_rcu(&ptr->list);
+			else
+				break;
+		}
+	}
+	{
 		int i;
 		for (i = 0; i < TOMOYO_MAX_HASH; i++) {
 			struct tomoyo_name_entry *ptr;
@@ -453,6 +489,11 @@ static void tomoyo_kfree_entry(void)
 		case TOMOYO_ID_MANAGER:
 			tomoyo_del_manager(p->element);
 			break;
+		case TOMOYO_ID_CONDITION:
+			tomoyo_del_condition(container_of(p->element, struct
+							  tomoyo_condition,
+							  list));
+			break;
 		case TOMOYO_ID_NAME:
 			tomoyo_del_name(p->element);
 			break;
--- security-testing-2.6.orig/security/tomoyo/memory.c
+++ security-testing-2.6/security/tomoyo/memory.c
@@ -49,10 +49,8 @@ bool tomoyo_memory_ok(void *ptr)
 	atomic_add(s, &tomoyo_policy_memory_size);
 	if (ptr && (!tomoyo_quota_for_policy ||
 		    atomic_read(&tomoyo_policy_memory_size)
-		    <= tomoyo_quota_for_policy)) {
-		memset(ptr, 0, s);
+		    <= tomoyo_quota_for_policy))
 		return true;
-	}
 	atomic_sub(s, &tomoyo_policy_memory_size);
 	tomoyo_warn_oom(__func__);
 	return false;
--- security-testing-2.6.orig/security/tomoyo/mount.c
+++ security-testing-2.6/security/tomoyo/mount.c
@@ -122,7 +122,8 @@ static int tomoyo_mount_acl2(struct tomo
 		    !tomoyo_compare_name_union(&rtype, &acl->fs_type) ||
 		    !tomoyo_compare_name_union(&rdir, &acl->dir_name) ||
 		    (need_dev &&
-		     !tomoyo_compare_name_union(&rdev, &acl->dev_name)))
+		     !tomoyo_compare_name_union(&rdev, &acl->dev_name)) ||
+		    !tomoyo_condition(r, ptr))
 			continue;
 		error = 0;
 		break;
@@ -264,15 +265,20 @@ int tomoyo_mount_permission(char *dev_na
  *
  * @data:      String to parse.
  * @domain:    Pointer to "struct tomoyo_domain_info".
+ * @cond:      Pointer to "struct tomoyo_condition". Maybe NULL.
  * @is_delete: True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
  */
 int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain,
+			      struct tomoyo_condition *cond,
 			      const bool is_delete)
 {
 	struct tomoyo_acl_info *ptr;
-	struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
+	struct tomoyo_mount_acl e = {
+		.head.type = TOMOYO_TYPE_MOUNT_ACL,
+		.head.cond = cond
+	};
 	int error = is_delete ? -ENOENT : -ENOMEM;
 	char *w[4];
 	if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0])
@@ -297,8 +303,7 @@ int tomoyo_write_mount_policy(char *data
 		struct tomoyo_mount_acl *entry =
 			tomoyo_commit_ok(&e, sizeof(e));
 		if (entry) {
-			list_add_tail_rcu(&entry->head.list,
-					  &domain->acl_info_list);
+			tomoyo_add_domain_acl(domain, &entry->head);
 			error = 0;
 		}
 	}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ