[PATCH 2/2] tomoyo: Allow multiple use_group lines.

Tetsuo Handa penguin-kernel at I-love.SAKURA.ne.jp
Thu Jan 24 09:37:36 UTC 2019


Being able to specify multiple "use_group" lines makes it
easier to write whitelisted policies.

Signed-off-by: Tetsuo Handa <penguin-kernel at I-love.SAKURA.ne.jp>
---
 security/tomoyo/common.c | 44 +++++++++++++++++++++++++++++---------------
 security/tomoyo/common.h |  3 ++-
 security/tomoyo/domain.c | 17 +++++++++++------
 3 files changed, 42 insertions(+), 22 deletions(-)

diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 0f8079b..148ad50 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -1174,7 +1174,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
 	struct tomoyo_domain_info *domain = head->w.domain;
 	const bool is_delete = head->w.is_delete;
 	bool is_select = !is_delete && tomoyo_str_starts(&data, "select ");
-	unsigned int profile;
+	unsigned int idx;
 
 	if (*data == '<') {
 		int ret = 0;
@@ -1192,24 +1192,27 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
 	if (!domain)
 		return -EINVAL;
 	ns = domain->ns;
-	if (sscanf(data, "use_profile %u", &profile) == 1
-	    && profile < TOMOYO_MAX_PROFILES) {
-		if (!tomoyo_policy_loaded || ns->profile_ptr[profile])
-			domain->profile = (u8) profile;
+	if (sscanf(data, "use_profile %u", &idx) == 1
+	    && idx < TOMOYO_MAX_PROFILES) {
+		if (!tomoyo_policy_loaded || ns->profile_ptr[idx])
+			if (!is_delete)
+				domain->profile = (u8) idx;
 		return 0;
 	}
-	if (sscanf(data, "use_group %u\n", &profile) == 1
-	    && profile < TOMOYO_MAX_ACL_GROUPS) {
+	if (sscanf(data, "use_group %u\n", &idx) == 1
+	    && idx < TOMOYO_MAX_ACL_GROUPS) {
 		if (!is_delete)
-			domain->group = (u8) profile;
+			set_bit(idx, domain->group);
+		else
+			clear_bit(idx, domain->group);
 		return 0;
 	}
-	for (profile = 0; profile < TOMOYO_MAX_DOMAIN_INFO_FLAGS; profile++) {
-		const char *cp = tomoyo_dif[profile];
+	for (idx = 0; idx < TOMOYO_MAX_DOMAIN_INFO_FLAGS; idx++) {
+		const char *cp = tomoyo_dif[idx];
 
 		if (strncmp(data, cp, strlen(cp) - 1))
 			continue;
-		domain->flags[profile] = !is_delete;
+		domain->flags[idx] = !is_delete;
 		return 0;
 	}
 	return tomoyo_write_domain2(ns, &domain->acl_info_list, data,
@@ -1629,22 +1632,33 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head)
 			tomoyo_set_lf(head);
 			tomoyo_io_printf(head, "use_profile %u\n",
 					 domain->profile);
-			tomoyo_io_printf(head, "use_group %u\n",
-					 domain->group);
 			for (i = 0; i < TOMOYO_MAX_DOMAIN_INFO_FLAGS; i++)
 				if (domain->flags[i])
 					tomoyo_set_string(head, tomoyo_dif[i]);
+			head->r.index = 0;
 			head->r.step++;
-			tomoyo_set_lf(head);
 			/* fall through */
 		case 1:
+			while (head->r.index < TOMOYO_MAX_ACL_GROUPS) {
+				i = head->r.index++;
+				if (!test_bit(i, domain->group))
+					continue;
+				tomoyo_io_printf(head, "use_group %u\n", i);
+				if (!tomoyo_flush(head))
+					return;
+			}
+			head->r.index = 0;
+			head->r.step++;
+			tomoyo_set_lf(head);
+			/* fall through */
+		case 2:
 			if (!tomoyo_read_domain2(head, &domain->acl_info_list))
 				return;
 			head->r.step++;
 			if (!tomoyo_set_lf(head))
 				return;
 			/* fall through */
-		case 2:
+		case 3:
 			head->r.step = 0;
 			if (head->r.print_this_domain_only)
 				goto done;
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index f2c458a..74dbd3b 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -684,8 +684,9 @@ struct tomoyo_domain_info {
 	const struct tomoyo_path_info *domainname;
 	/* Namespace for this domain. Never NULL. */
 	struct tomoyo_policy_namespace *ns;
+	/* Group numbers to use.   */
+	unsigned long group[TOMOYO_MAX_ACL_GROUPS / BITS_PER_LONG];
 	u8 profile;        /* Profile number to use. */
-	u8 group;          /* Group number to use.   */
 	bool is_deleted;   /* Delete flag.           */
 	bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS];
 	atomic_t users; /* Number of referring tasks. */
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index bf832b3..8526a0a 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -162,8 +162,8 @@ void tomoyo_check_acl(struct tomoyo_request_info *r,
 {
 	const struct tomoyo_domain_info *domain = r->domain;
 	struct tomoyo_acl_info *ptr;
-	bool retried = false;
 	const struct list_head *list = &domain->acl_info_list;
+	u16 i = 0;
 
 retry:
 	list_for_each_entry_rcu(ptr, list, list) {
@@ -177,9 +177,10 @@ void tomoyo_check_acl(struct tomoyo_request_info *r,
 		r->granted = true;
 		return;
 	}
-	if (!retried) {
-		retried = true;
-		list = &domain->ns->acl_group[domain->group];
+	for (; i < TOMOYO_MAX_ACL_GROUPS; i++) {
+		if (!test_bit(i, domain->group))
+			continue;
+		list = &domain->ns->acl_group[i++];
 		goto retry;
 	}
 	r->granted = false;
@@ -561,7 +562,7 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
 		const struct tomoyo_domain_info *domain = tomoyo_domain();
 
 		e.profile = domain->profile;
-		e.group = domain->group;
+		memcpy(e.group, domain->group, sizeof(e.group));
 	}
 	e.domainname = tomoyo_get_name(domainname);
 	if (!e.domainname)
@@ -583,13 +584,17 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
 	if (entry && transit) {
 		if (created) {
 			struct tomoyo_request_info r;
+			int i;
 
 			tomoyo_init_request_info(&r, entry,
 						 TOMOYO_MAC_FILE_EXECUTE);
 			r.granted = false;
 			tomoyo_write_log(&r, "use_profile %u\n",
 					 entry->profile);
-			tomoyo_write_log(&r, "use_group %u\n", entry->group);
+			for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
+				if (test_bit(i, entry->group))
+					tomoyo_write_log(&r, "use_group %u\n",
+							 i);
 			tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES);
 		}
 	}
-- 
1.8.3.1



More information about the Linux-security-module-archive mailing list