diff options
-rw-r--r-- | security/tomoyo/Makefile | 2 | ||||
-rw-r--r-- | security/tomoyo/common.c | 4 | ||||
-rw-r--r-- | security/tomoyo/common.h | 13 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 36 | ||||
-rw-r--r-- | security/tomoyo/group.c | 130 | ||||
-rw-r--r-- | security/tomoyo/memory.c | 44 | ||||
-rw-r--r-- | security/tomoyo/number_group.c | 126 | ||||
-rw-r--r-- | security/tomoyo/path_group.c | 122 | ||||
-rw-r--r-- | security/tomoyo/util.c | 4 |
9 files changed, 199 insertions, 282 deletions
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 3aa6f076948e..91640e96bd06 100644 --- a/security/tomoyo/Makefile +++ b/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 = common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 044115d49033..183fe6513400 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1186,9 +1186,9 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) return tomoyo_write_no_rewrite_policy(data, is_delete); if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) - return tomoyo_write_path_group_policy(data, is_delete); + return tomoyo_write_group(data, is_delete, TOMOYO_PATH_GROUP); if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NUMBER_GROUP)) - return tomoyo_write_number_group_policy(data, is_delete); + return tomoyo_write_group(data, is_delete, TOMOYO_NUMBER_GROUP); return -EINVAL; } diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 21eb1e7885b8..ec3ed488ee30 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -838,12 +838,10 @@ int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain, int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); /* Create "file_pattern" entry in exception policy. */ int tomoyo_write_pattern_policy(char *data, const bool is_delete); -/* Create "path_group" entry in exception policy. */ -int tomoyo_write_path_group_policy(char *data, const bool is_delete); +/* Create "path_group"/"number_group" entry in exception policy. */ +int tomoyo_write_group(char *data, const bool is_delete, const u8 type); int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); -/* Create "number_group" entry in exception policy. */ -int tomoyo_write_number_group_policy(char *data, const bool is_delete); /* Find a domain by the given name. */ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); /* Find or create a domain by the given name. */ @@ -851,9 +849,10 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, const u8 profile); struct tomoyo_profile *tomoyo_profile(const u8 profile); -/* Allocate memory for "struct tomoyo_path_group". */ -struct tomoyo_group *tomoyo_get_path_group(const char *group_name); -struct tomoyo_group *tomoyo_get_number_group(const char *group_name); +/* + * Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". + */ +struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type); /* Check mode for specified functionality. */ unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 414e18bd93c7..cf62a4ee79c2 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -266,33 +266,25 @@ static void tomoyo_collect_entry(void) goto unlock; } } - { + for (i = 0; i < TOMOYO_MAX_GROUP; i++) { + struct list_head *list = &tomoyo_group_list[i]; + int id; struct tomoyo_group *group; - list_for_each_entry_rcu(group, - &tomoyo_group_list[TOMOYO_PATH_GROUP], - list) { - tomoyo_collect_member(&group->member_list, - TOMOYO_ID_PATH_GROUP); - if (!list_empty(&group->member_list) || - atomic_read(&group->users)) - continue; - if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, - &group->list)) - goto unlock; + switch (i) { + case 0: + id = TOMOYO_ID_PATH_GROUP; + break; + default: + id = TOMOYO_ID_NUMBER_GROUP; + break; } - } - { - struct tomoyo_group *group; - list_for_each_entry_rcu(group, - &tomoyo_group_list[TOMOYO_NUMBER_GROUP], - list) { - tomoyo_collect_member(&group->member_list, - TOMOYO_ID_NUMBER_GROUP); + list_for_each_entry(group, list, list) { + if (!tomoyo_collect_member(&group->member_list, id)) + goto unlock; if (!list_empty(&group->member_list) || atomic_read(&group->users)) continue; - if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, - &group->list)) + if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list)) goto unlock; } } diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c new file mode 100644 index 000000000000..3f0a2abf65cc --- /dev/null +++ b/security/tomoyo/group.c @@ -0,0 +1,130 @@ +/* + * security/tomoyo/group.c + * + * Copyright (C) 2005-2010 NTT DATA CORPORATION + */ + +#include <linux/slab.h> +#include "common.h" + +static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a, + const struct tomoyo_acl_head *b) +{ + return container_of(a, struct tomoyo_path_group, head)->member_name == + container_of(b, struct tomoyo_path_group, head)->member_name; +} + +static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a, + const struct tomoyo_acl_head *b) +{ + return !memcmp(&container_of(a, struct tomoyo_number_group, head) + ->number, + &container_of(b, struct tomoyo_number_group, head) + ->number, + sizeof(container_of(a, struct tomoyo_number_group, head) + ->number)); +} + +/** + * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list. + * + * @data: String to parse. + * @is_delete: True if it is a delete request. + * @type: Type of this group. + * + * Returns 0 on success, negative value otherwise. + */ +int tomoyo_write_group(char *data, const bool is_delete, const u8 type) +{ + struct tomoyo_group *group; + struct list_head *member; + char *w[2]; + int error = -EINVAL; + if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) + return -EINVAL; + group = tomoyo_get_group(w[0], type); + if (!group) + return -ENOMEM; + member = &group->member_list; + if (type == TOMOYO_PATH_GROUP) { + struct tomoyo_path_group e = { }; + e.member_name = tomoyo_get_name(w[1]); + if (!e.member_name) { + error = -ENOMEM; + goto out; + } + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, + member, tomoyo_same_path_group); + tomoyo_put_name(e.member_name); + } else if (type == TOMOYO_NUMBER_GROUP) { + struct tomoyo_number_group e = { }; + if (w[1][0] == '@' + || !tomoyo_parse_number_union(w[1], &e.number) + || e.number.values[0] > e.number.values[1]) + goto out; + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, + member, tomoyo_same_number_group); + /* + * tomoyo_put_number_union() is not needed because + * w[1][0] != '@'. + */ + } + out: + tomoyo_put_group(group); + return error; +} + +/** + * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. + * + * @pathname: The name of pathname. + * @group: Pointer to "struct tomoyo_path_group". + * + * Returns true if @pathname matches pathnames in @group, false otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, + const struct tomoyo_group *group) +{ + struct tomoyo_path_group *member; + bool matched = false; + list_for_each_entry_rcu(member, &group->member_list, head.list) { + if (member->head.is_deleted) + continue; + if (!tomoyo_path_matches_pattern(pathname, member->member_name)) + continue; + matched = true; + break; + } + return matched; +} + +/** + * tomoyo_number_matches_group - Check whether the given number matches members of the given number group. + * + * @min: Min number. + * @max: Max number. + * @group: Pointer to "struct tomoyo_number_group". + * + * Returns true if @min and @max partially overlaps @group, false otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +bool tomoyo_number_matches_group(const unsigned long min, + const unsigned long max, + const struct tomoyo_group *group) +{ + struct tomoyo_number_group *member; + bool matched = false; + list_for_each_entry_rcu(member, &group->member_list, head.list) { + if (member->head.is_deleted) + continue; + if (min > member->number.values[1] || + max < member->number.values[0]) + continue; + matched = true; + break; + } + return matched; +} diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 249835abdf4e..a1d75df93e16 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c @@ -89,6 +89,50 @@ void tomoyo_memory_free(void *ptr) kfree(ptr); } +/** + * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". + * + * @group_name: The name of address group. + * @idx: Index number. + * + * Returns pointer to "struct tomoyo_group" on success, NULL otherwise. + */ +struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) +{ + struct tomoyo_group e = { }; + struct tomoyo_group *group = NULL; + bool found = false; + if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) + return NULL; + e.group_name = tomoyo_get_name(group_name); + if (!e.group_name) + return NULL; + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; + list_for_each_entry(group, &tomoyo_group_list[idx], list) { + if (e.group_name != group->group_name) + continue; + atomic_inc(&group->users); + found = true; + break; + } + if (!found) { + struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + INIT_LIST_HEAD(&entry->member_list); + atomic_set(&entry->users, 1); + list_add_tail_rcu(&entry->list, + &tomoyo_group_list[idx]); + group = entry; + found = true; + } + } + mutex_unlock(&tomoyo_policy_lock); + out: + tomoyo_put_name(e.group_name); + return found ? group : NULL; +} + /* * tomoyo_name_list is used for holding string data used by TOMOYO. * Since same string data is likely used for multiple times (e.g. diff --git a/security/tomoyo/number_group.c b/security/tomoyo/number_group.c deleted file mode 100644 index 5e75f5314bda..000000000000 --- a/security/tomoyo/number_group.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * security/tomoyo/number_group.c - * - * Copyright (C) 2005-2009 NTT DATA CORPORATION - */ - -#include <linux/slab.h> -#include "common.h" - -/** - * tomoyo_get_group - Allocate memory for "struct tomoyo_number_group". - * - * @group_name: The name of number group. - * - * Returns pointer to "struct tomoyo_number_group" on success, - * NULL otherwise. - */ -struct tomoyo_group *tomoyo_get_number_group(const char *group_name) -{ - struct tomoyo_group *entry = NULL; - struct tomoyo_group *group = NULL; - const struct tomoyo_path_info *saved_group_name; - int error = -ENOMEM; - if (!tomoyo_correct_word(group_name)) - return NULL; - saved_group_name = tomoyo_get_name(group_name); - if (!saved_group_name) - return NULL; - entry = kzalloc(sizeof(*entry), GFP_NOFS); - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - list_for_each_entry_rcu(group, &tomoyo_group_list[TOMOYO_NUMBER_GROUP], - list) { - if (saved_group_name != group->group_name) - continue; - atomic_inc(&group->users); - error = 0; - break; - } - if (error && tomoyo_memory_ok(entry)) { - INIT_LIST_HEAD(&entry->member_list); - entry->group_name = saved_group_name; - saved_group_name = NULL; - atomic_set(&entry->users, 1); - list_add_tail_rcu(&entry->list, - &tomoyo_group_list[TOMOYO_NUMBER_GROUP]); - group = entry; - entry = NULL; - error = 0; - } - mutex_unlock(&tomoyo_policy_lock); - out: - tomoyo_put_name(saved_group_name); - kfree(entry); - return !error ? group : NULL; -} - -static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a, - const struct tomoyo_acl_head *b) -{ - return !memcmp(&container_of(a, struct tomoyo_number_group, - head)->number, - &container_of(b, struct tomoyo_number_group, - head)->number, - sizeof(container_of(a, - struct tomoyo_number_group, - head)->number)); -} - -/** - * tomoyo_write_number_group_policy - Write "struct tomoyo_number_group" list. - * - * @data: String to parse. - * @is_delete: True if it is a delete request. - * - * Returns 0 on success, nagative value otherwise. - */ -int tomoyo_write_number_group_policy(char *data, const bool is_delete) -{ - struct tomoyo_group *group; - struct tomoyo_number_group e = { }; - int error; - char *w[2]; - if (!tomoyo_tokenize(data, w, sizeof(w))) - return -EINVAL; - if (w[1][0] == '@' || !tomoyo_parse_number_union(w[1], &e.number) || - e.number.values[0] > e.number.values[1]) - return -EINVAL; - group = tomoyo_get_number_group(w[0]); - if (!group) - return -ENOMEM; - error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, - &group->member_list, - tomoyo_same_number_group); - tomoyo_put_group(group); - return error; -} - -/** - * tomoyo_number_matches_group - Check whether the given number matches members of the given number group. - * - * @min: Min number. - * @max: Max number. - * @group: Pointer to "struct tomoyo_number_group". - * - * Returns true if @min and @max partially overlaps @group, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -bool tomoyo_number_matches_group(const unsigned long min, - const unsigned long max, - const struct tomoyo_group *group) -{ - struct tomoyo_number_group *member; - bool matched = false; - list_for_each_entry_rcu(member, &group->member_list, head.list) { - if (member->head.is_deleted) - continue; - if (min > member->number.values[1] || - max < member->number.values[0]) - continue; - matched = true; - break; - } - return matched; -} diff --git a/security/tomoyo/path_group.c b/security/tomoyo/path_group.c deleted file mode 100644 index 2f9f9240bf5a..000000000000 --- a/security/tomoyo/path_group.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * security/tomoyo/path_group.c - * - * Copyright (C) 2005-2009 NTT DATA CORPORATION - */ - -#include <linux/slab.h> -#include "common.h" - -/** - * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group". - * - * @group_name: The name of pathname group. - * - * Returns pointer to "struct tomoyo_path_group" on success, NULL otherwise. - */ -struct tomoyo_group *tomoyo_get_path_group(const char *group_name) -{ - struct tomoyo_group *entry = NULL; - struct tomoyo_group *group = NULL; - const struct tomoyo_path_info *saved_group_name; - int error = -ENOMEM; - if (!tomoyo_correct_word(group_name)) - return NULL; - saved_group_name = tomoyo_get_name(group_name); - if (!saved_group_name) - return NULL; - entry = kzalloc(sizeof(*entry), GFP_NOFS); - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - list_for_each_entry_rcu(group, &tomoyo_group_list[TOMOYO_PATH_GROUP], - list) { - if (saved_group_name != group->group_name) - continue; - atomic_inc(&group->users); - error = 0; - break; - } - if (error && tomoyo_memory_ok(entry)) { - INIT_LIST_HEAD(&entry->member_list); - entry->group_name = saved_group_name; - saved_group_name = NULL; - atomic_set(&entry->users, 1); - list_add_tail_rcu(&entry->list, - &tomoyo_group_list[TOMOYO_PATH_GROUP]); - group = entry; - entry = NULL; - error = 0; - } - mutex_unlock(&tomoyo_policy_lock); - out: - tomoyo_put_name(saved_group_name); - kfree(entry); - return !error ? group : NULL; -} - -static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a, - const struct tomoyo_acl_head *b) -{ - return container_of(a, struct tomoyo_path_group, head) - ->member_name == - container_of(b, struct tomoyo_path_group, head) - ->member_name; -} - -/** - * tomoyo_write_path_group_policy - Write "struct tomoyo_path_group" list. - * - * @data: String to parse. - * @is_delete: True if it is a delete request. - * - * Returns 0 on success, nagative value otherwise. - */ -int tomoyo_write_path_group_policy(char *data, const bool is_delete) -{ - struct tomoyo_group *group; - struct tomoyo_path_group e = { }; - int error = is_delete ? -ENOENT : -ENOMEM; - char *w[2]; - if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) - return -EINVAL; - group = tomoyo_get_path_group(w[0]); - if (!group) - return -ENOMEM; - e.member_name = tomoyo_get_name(w[1]); - if (!e.member_name) - goto out; - error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, - &group->member_list, - tomoyo_same_path_group); - out: - tomoyo_put_name(e.member_name); - tomoyo_put_group(group); - return error; -} - -/** - * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. - * - * @pathname: The name of pathname. - * @group: Pointer to "struct tomoyo_path_group". - * - * Returns true if @pathname matches pathnames in @group, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, - const struct tomoyo_group *group) -{ - struct tomoyo_path_group *member; - bool matched = false; - list_for_each_entry_rcu(member, &group->member_list, head.list) { - if (member->head.is_deleted) - continue; - if (!tomoyo_path_matches_pattern(pathname, - member->member_name)) - continue; - matched = true; - break; - } - return matched; -} diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 945eeefbbdfe..20abba22af42 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -92,7 +92,7 @@ bool tomoyo_parse_name_union(const char *filename, if (!tomoyo_correct_word(filename)) return false; if (filename[0] == '@') { - ptr->group = tomoyo_get_path_group(filename + 1); + ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP); ptr->is_group = true; return ptr->group != NULL; } @@ -117,7 +117,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) if (data[0] == '@') { if (!tomoyo_correct_word(data)) return false; - num->group = tomoyo_get_number_group(data + 1); + num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP); num->is_group = true; return num->group != NULL; } |