From fdb8ebb729bbb640e64028a4f579a02ebc405727 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 8 Dec 2009 09:34:43 +0900 Subject: TOMOYO: Use RCU primitives for list operation Replace list operation with RCU primitives and replace down_read()/up_read() with srcu_read_lock()/srcu_read_unlock(). Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/domain.c | 63 ++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 26 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index fcf52accce2b..2fd190168b7e 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -217,6 +217,8 @@ static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_domain_initializer_entry(const char *domainname, const char *program, @@ -246,7 +248,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, if (!saved_program) return -ENOMEM; down_write(&tomoyo_domain_initializer_list_lock); - list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || ptr->program != saved_program) @@ -266,7 +268,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, new_entry->program = saved_program; new_entry->is_not = is_not; new_entry->is_last_name = is_last_name; - list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); error = 0; out: up_write(&tomoyo_domain_initializer_list_lock); @@ -279,13 +281,14 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, * @head: Pointer to "struct tomoyo_io_buffer". * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) { struct list_head *pos; bool done = true; - down_read(&tomoyo_domain_initializer_list_lock); list_for_each_cookie(pos, head->read_var2, &tomoyo_domain_initializer_list) { const char *no; @@ -308,7 +311,6 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_domain_initializer_list_lock); return done; } @@ -320,6 +322,8 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, const bool is_delete) @@ -345,6 +349,8 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, * * Returns true if executing @program reinitializes domain transition, * false otherwise. + * + * Caller holds tomoyo_read_lock(). */ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * domainname, @@ -355,8 +361,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * struct tomoyo_domain_initializer_entry *ptr; bool flag = false; - down_read(&tomoyo_domain_initializer_list_lock); - list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_deleted) continue; if (ptr->domainname) { @@ -376,7 +381,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * } flag = true; } - up_read(&tomoyo_domain_initializer_list_lock); return flag; } @@ -430,6 +434,8 @@ static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_domain_keeper_entry(const char *domainname, const char *program, @@ -459,7 +465,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, if (!saved_domainname) return -ENOMEM; down_write(&tomoyo_domain_keeper_list_lock); - list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || ptr->program != saved_program) @@ -479,7 +485,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, new_entry->program = saved_program; new_entry->is_not = is_not; new_entry->is_last_name = is_last_name; - list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); error = 0; out: up_write(&tomoyo_domain_keeper_list_lock); @@ -493,6 +499,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, * @is_not: True if it is "no_keep_domain" entry. * @is_delete: True if it is a delete request. * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, const bool is_delete) @@ -513,13 +520,14 @@ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, * @head: Pointer to "struct tomoyo_io_buffer". * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) { struct list_head *pos; bool done = true; - down_read(&tomoyo_domain_keeper_list_lock); list_for_each_cookie(pos, head->read_var2, &tomoyo_domain_keeper_list) { struct tomoyo_domain_keeper_entry *ptr; @@ -542,7 +550,6 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_domain_keeper_list_lock); return done; } @@ -555,6 +562,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) * * Returns true if executing @program supresses domain transition, * false otherwise. + * + * Caller holds tomoyo_read_lock(). */ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, const struct tomoyo_path_info *program, @@ -563,8 +572,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, struct tomoyo_domain_keeper_entry *ptr; bool flag = false; - down_read(&tomoyo_domain_keeper_list_lock); - list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_deleted) continue; if (!ptr->is_last_name) { @@ -582,7 +590,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, } flag = true; } - up_read(&tomoyo_domain_keeper_list_lock); return flag; } @@ -627,6 +634,8 @@ static DECLARE_RWSEM(tomoyo_alias_list_lock); * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_alias_entry(const char *original_name, const char *aliased_name, @@ -646,7 +655,7 @@ static int tomoyo_update_alias_entry(const char *original_name, if (!saved_original_name || !saved_aliased_name) return -ENOMEM; down_write(&tomoyo_alias_list_lock); - list_for_each_entry(ptr, &tomoyo_alias_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || ptr->aliased_name != saved_aliased_name) continue; @@ -663,7 +672,7 @@ static int tomoyo_update_alias_entry(const char *original_name, goto out; new_entry->original_name = saved_original_name; new_entry->aliased_name = saved_aliased_name; - list_add_tail(&new_entry->list, &tomoyo_alias_list); + list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); error = 0; out: up_write(&tomoyo_alias_list_lock); @@ -676,13 +685,14 @@ static int tomoyo_update_alias_entry(const char *original_name, * @head: Pointer to "struct tomoyo_io_buffer". * * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). */ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) { struct list_head *pos; bool done = true; - down_read(&tomoyo_alias_list_lock); list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { struct tomoyo_alias_entry *ptr; @@ -695,7 +705,6 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) if (!done) break; } - up_read(&tomoyo_alias_list_lock); return done; } @@ -706,6 +715,8 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_alias_policy(char *data, const bool is_delete) { @@ -724,6 +735,8 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete) * @profile: Profile number to assign if the domain was newly created. * * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. + * + * Caller holds tomoyo_read_lock(). */ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, @@ -742,7 +755,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * if (!saved_domainname) goto out; /* Can I reuse memory of deleted domain? */ - list_for_each_entry(domain, &tomoyo_domain_list, list) { + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { struct task_struct *p; struct tomoyo_acl_info *ptr; bool flag; @@ -760,7 +773,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * read_unlock(&tasklist_lock); if (flag) continue; - list_for_each_entry(ptr, &domain->acl_info_list, list) { + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { ptr->type |= TOMOYO_ACL_DELETED; } tomoyo_set_domain_flag(domain, true, domain->flags); @@ -776,7 +789,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * INIT_LIST_HEAD(&domain->acl_info_list); domain->domainname = saved_domainname; domain->profile = profile; - list_add_tail(&domain->list, &tomoyo_domain_list); + list_add_tail_rcu(&domain->list, &tomoyo_domain_list); } out: up_write(&tomoyo_domain_list_lock); @@ -789,6 +802,8 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * * @bprm: Pointer to "struct linux_binprm". * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_find_next_domain(struct linux_binprm *bprm) { @@ -849,8 +864,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (tomoyo_pathcmp(&r, &s)) { struct tomoyo_alias_entry *ptr; /* Is this program allowed to be called via symbolic links? */ - down_read(&tomoyo_alias_list_lock); - list_for_each_entry(ptr, &tomoyo_alias_list, list) { + list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->is_deleted || tomoyo_pathcmp(&r, ptr->original_name) || tomoyo_pathcmp(&s, ptr->aliased_name)) @@ -861,7 +875,6 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) tomoyo_fill_path_info(&r); break; } - up_read(&tomoyo_alias_list_lock); } /* Check execute permission. */ @@ -892,9 +905,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) } if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) goto done; - down_read(&tomoyo_domain_list_lock); domain = tomoyo_find_domain(new_domain_name); - up_read(&tomoyo_domain_list_lock); if (domain) goto done; if (is_enforce) -- cgit v1.2.3-59-g8ed1b From f737d95ddfea4df68a36ffc9231db4bf34b06d13 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sun, 3 Jan 2010 21:16:32 +0900 Subject: TOMOYO: Replace rw_semaphore by mutex. Since readers no longer use down_read(), writers no longer need to use rw_semaphore. Replace individual rw_semaphore by single mutex. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 12 +++++++----- security/tomoyo/common.h | 5 ++--- security/tomoyo/domain.c | 20 ++++++++------------ security/tomoyo/file.c | 26 ++++++++++---------------- 4 files changed, 27 insertions(+), 36 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index f01b9364db2d..642e0e565dfc 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -16,6 +16,9 @@ #include "common.h" #include "tomoyo.h" +/* Lock for protecting policy. */ +DEFINE_MUTEX(tomoyo_policy_lock); + /* Has loading policy done? */ bool tomoyo_policy_loaded; @@ -1086,7 +1089,6 @@ struct tomoyo_policy_manager_entry { * # cat /sys/kernel/security/tomoyo/manager */ static LIST_HEAD(tomoyo_policy_manager_list); -static DECLARE_RWSEM(tomoyo_policy_manager_list_lock); /** * tomoyo_update_manager_entry - Add a manager entry. @@ -1118,7 +1120,7 @@ static int tomoyo_update_manager_entry(const char *manager, saved_manager = tomoyo_save_name(manager); if (!saved_manager) return -ENOMEM; - down_write(&tomoyo_policy_manager_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (ptr->manager != saved_manager) continue; @@ -1138,7 +1140,7 @@ static int tomoyo_update_manager_entry(const char *manager, list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); error = 0; out: - up_write(&tomoyo_policy_manager_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -1315,7 +1317,7 @@ static int tomoyo_delete_domain(char *domainname) name.name = domainname; tomoyo_fill_path_info(&name); - down_write(&tomoyo_domain_list_lock); + mutex_lock(&tomoyo_policy_lock); /* Is there an active domain? */ list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { /* Never delete tomoyo_kernel_domain */ @@ -1327,7 +1329,7 @@ static int tomoyo_delete_domain(char *domainname) domain->is_deleted = true; break; } - up_write(&tomoyo_domain_list_lock); + mutex_unlock(&tomoyo_policy_lock); return 0; } diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index c6f13925472a..874abf8df43e 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -431,10 +431,9 @@ static inline bool tomoyo_is_invalid(const unsigned char c) /* The list for "struct tomoyo_domain_info". */ extern struct list_head tomoyo_domain_list; -extern struct rw_semaphore tomoyo_domain_list_lock; -/* Lock for domain->acl_info_list. */ -extern struct rw_semaphore tomoyo_domain_acl_info_list_lock; +/* Lock for protecting policy. */ +extern struct mutex tomoyo_policy_lock; /* Has /sbin/init started? */ extern bool tomoyo_policy_loaded; diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 2fd190168b7e..7d0b0bc48201 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -58,7 +58,6 @@ struct tomoyo_domain_info tomoyo_kernel_domain; * exceptions. */ LIST_HEAD(tomoyo_domain_list); -DECLARE_RWSEM(tomoyo_domain_list_lock); /* * tomoyo_domain_initializer_entry is a structure which is used for holding @@ -206,7 +205,6 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) * unless executed from " /etc/rc.d/init.d/httpd" domain. */ static LIST_HEAD(tomoyo_domain_initializer_list); -static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock); /** * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. @@ -247,7 +245,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, saved_program = tomoyo_save_name(program); if (!saved_program) return -ENOMEM; - down_write(&tomoyo_domain_initializer_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || @@ -271,7 +269,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); error = 0; out: - up_write(&tomoyo_domain_initializer_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -423,7 +421,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * * explicitly specified by "initialize_domain". */ static LIST_HEAD(tomoyo_domain_keeper_list); -static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock); /** * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. @@ -464,7 +461,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) return -ENOMEM; - down_write(&tomoyo_domain_keeper_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || ptr->domainname != saved_domainname || @@ -488,7 +485,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); error = 0; out: - up_write(&tomoyo_domain_keeper_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -624,7 +621,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . */ static LIST_HEAD(tomoyo_alias_list); -static DECLARE_RWSEM(tomoyo_alias_list_lock); /** * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. @@ -654,7 +650,7 @@ static int tomoyo_update_alias_entry(const char *original_name, saved_aliased_name = tomoyo_save_name(aliased_name); if (!saved_original_name || !saved_aliased_name) return -ENOMEM; - down_write(&tomoyo_alias_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || ptr->aliased_name != saved_aliased_name) @@ -675,7 +671,7 @@ static int tomoyo_update_alias_entry(const char *original_name, list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); error = 0; out: - up_write(&tomoyo_alias_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -745,7 +741,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * struct tomoyo_domain_info *domain = NULL; const struct tomoyo_path_info *saved_domainname; - down_write(&tomoyo_domain_list_lock); + mutex_lock(&tomoyo_policy_lock); domain = tomoyo_find_domain(domainname); if (domain) goto out; @@ -792,7 +788,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * list_add_tail_rcu(&domain->list, &tomoyo_domain_list); } out: - up_write(&tomoyo_domain_list_lock); + mutex_unlock(&tomoyo_policy_lock); return domain; } diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 3c472867634f..5d1689d6e16c 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -167,9 +167,6 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path) return NULL; } -/* Lock for domain->acl_info_list. */ -DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock); - static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, const char *filename2, struct tomoyo_domain_info * @@ -204,7 +201,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, * belongs to. */ static LIST_HEAD(tomoyo_globally_readable_list); -static DECLARE_RWSEM(tomoyo_globally_readable_list_lock); /** * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. @@ -229,7 +225,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; - down_write(&tomoyo_globally_readable_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { if (ptr->filename != saved_filename) continue; @@ -248,7 +244,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); error = 0; out: - up_write(&tomoyo_globally_readable_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -352,7 +348,6 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) * current process from accessing other process's information. */ static LIST_HEAD(tomoyo_pattern_list); -static DECLARE_RWSEM(tomoyo_pattern_list_lock); /** * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. @@ -377,7 +372,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) return -ENOMEM; - down_write(&tomoyo_pattern_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (saved_pattern != ptr->pattern) continue; @@ -396,7 +391,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); error = 0; out: - up_write(&tomoyo_pattern_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -505,7 +500,6 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) * need to worry whether the file is already unlink()ed or not. */ static LIST_HEAD(tomoyo_no_rewrite_list); -static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock); /** * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. @@ -529,7 +523,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) return -ENOMEM; - down_write(&tomoyo_no_rewrite_list_lock); + mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->pattern != saved_pattern) continue; @@ -548,7 +542,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); error = 0; out: - up_write(&tomoyo_no_rewrite_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -881,7 +875,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; - down_write(&tomoyo_domain_acl_info_list_lock); + mutex_lock(&tomoyo_policy_lock); if (is_delete) goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { @@ -943,7 +937,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, break; } out: - up_write(&tomoyo_domain_acl_info_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } @@ -981,7 +975,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, saved_filename2 = tomoyo_save_name(filename2); if (!saved_filename1 || !saved_filename2) return -ENOMEM; - down_write(&tomoyo_domain_acl_info_list_lock); + mutex_lock(&tomoyo_policy_lock); if (is_delete) goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { @@ -1027,7 +1021,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, break; } out: - up_write(&tomoyo_domain_acl_info_list_lock); + mutex_unlock(&tomoyo_policy_lock); return error; } -- cgit v1.2.3-59-g8ed1b From cd7bec6ad80188394a8ea857ff1aa3512fc2282a Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 5 Jan 2010 06:39:37 +0900 Subject: TOMOYO: Remove memory pool for list elements. Currently, TOMOYO allocates memory for list elements from memory pool allocated by kmalloc(PAGE_SIZE). But that makes it difficult to kfree() when garbage collector is added. Thus, remove memory pool and use kmalloc(sizeof()). Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 41 ++++++----------------------- security/tomoyo/common.h | 2 -- security/tomoyo/domain.c | 58 ++++++++++++++--------------------------- security/tomoyo/file.c | 34 +++++++++++++++++------- security/tomoyo/realpath.c | 65 ++++++++++++++-------------------------------- security/tomoyo/realpath.h | 7 ++--- 6 files changed, 73 insertions(+), 134 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 642e0e565dfc..e331e699cf54 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -900,9 +900,11 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned ptr = tomoyo_profile_ptr[profile]; if (ptr) goto ok; - ptr = tomoyo_alloc_element(sizeof(*ptr)); - if (!ptr) + ptr = kmalloc(sizeof(*ptr), GFP_KERNEL); + if (!tomoyo_memory_ok(ptr)) { + kfree(ptr); goto ok; + } for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) ptr->value[i] = tomoyo_control_array[i].current_value; mb(); /* Avoid out-of-order execution. */ @@ -1120,6 +1122,7 @@ static int tomoyo_update_manager_entry(const char *manager, saved_manager = tomoyo_save_name(manager); if (!saved_manager) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (ptr->manager != saved_manager) @@ -1132,15 +1135,16 @@ static int tomoyo_update_manager_entry(const char *manager, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->manager = saved_manager; new_entry->is_domain = is_domain; list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -2147,35 +2151,6 @@ static int tomoyo_close_control(struct file *file) return 0; } -/** - * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry. - * - * @acl_type: Type of ACL entry. - * - * Returns pointer to the ACL entry on success, NULL otherwise. - */ -void *tomoyo_alloc_acl_element(const u8 acl_type) -{ - int len; - struct tomoyo_acl_info *ptr; - - switch (acl_type) { - case TOMOYO_TYPE_SINGLE_PATH_ACL: - len = sizeof(struct tomoyo_single_path_acl_record); - break; - case TOMOYO_TYPE_DOUBLE_PATH_ACL: - len = sizeof(struct tomoyo_double_path_acl_record); - break; - default: - return NULL; - } - ptr = tomoyo_alloc_element(len); - if (!ptr) - return NULL; - ptr->type = acl_type; - return ptr; -} - /** * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. * diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 874abf8df43e..610a6a056828 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -376,8 +376,6 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * /* Check mode for specified functionality. */ unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, const u8 index); -/* Allocate memory for structures. */ -void *tomoyo_alloc_acl_element(const u8 acl_type); /* Fill in "struct tomoyo_path_info" members. */ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); /* Run policy loader when /sbin/init starts. */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 7d0b0bc48201..a55a1cced58e 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -245,6 +245,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, saved_program = tomoyo_save_name(program); if (!saved_program) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || @@ -259,17 +260,18 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->domainname = saved_domainname; new_entry->program = saved_program; new_entry->is_not = is_not; new_entry->is_last_name = is_last_name; list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -461,6 +463,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || @@ -475,17 +478,18 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->domainname = saved_domainname; new_entry->program = saved_program; new_entry->is_not = is_not; new_entry->is_last_name = is_last_name; list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -650,6 +654,7 @@ static int tomoyo_update_alias_entry(const char *original_name, saved_aliased_name = tomoyo_save_name(aliased_name); if (!saved_original_name || !saved_aliased_name) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || @@ -663,15 +668,16 @@ static int tomoyo_update_alias_entry(const char *original_name, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->original_name = saved_original_name; new_entry->aliased_name = saved_aliased_name; list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -738,7 +744,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, const u8 profile) { - struct tomoyo_domain_info *domain = NULL; + struct tomoyo_domain_info *domain; const struct tomoyo_path_info *saved_domainname; mutex_lock(&tomoyo_policy_lock); @@ -750,43 +756,17 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) goto out; - /* Can I reuse memory of deleted domain? */ - list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { - struct task_struct *p; - struct tomoyo_acl_info *ptr; - bool flag; - if (!domain->is_deleted || - domain->domainname != saved_domainname) - continue; - flag = false; - read_lock(&tasklist_lock); - for_each_process(p) { - if (tomoyo_real_domain(p) != domain) - continue; - flag = true; - break; - } - read_unlock(&tasklist_lock); - if (flag) - continue; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - ptr->type |= TOMOYO_ACL_DELETED; - } - tomoyo_set_domain_flag(domain, true, domain->flags); - domain->profile = profile; - domain->quota_warned = false; - mb(); /* Avoid out-of-order execution. */ - domain->is_deleted = false; - goto out; - } - /* No memory reusable. Create using new memory. */ - domain = tomoyo_alloc_element(sizeof(*domain)); - if (domain) { + domain = kmalloc(sizeof(*domain), GFP_KERNEL); + if (tomoyo_memory_ok(domain)) { INIT_LIST_HEAD(&domain->acl_info_list); domain->domainname = saved_domainname; domain->profile = profile; list_add_tail_rcu(&domain->list, &tomoyo_domain_list); + } else { + kfree(domain); + domain = NULL; } + out: mutex_unlock(&tomoyo_policy_lock); return domain; diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 5d1689d6e16c..075392c052b4 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -225,6 +225,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { if (ptr->filename != saved_filename) @@ -237,14 +238,15 @@ static int tomoyo_update_globally_readable_entry(const char *filename, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->filename = saved_filename; list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -372,6 +374,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (saved_pattern != ptr->pattern) @@ -384,14 +387,15 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->pattern = saved_pattern; list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -523,6 +527,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) return -ENOMEM; + new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->pattern != saved_pattern) @@ -535,14 +540,15 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, error = -ENOENT; goto out; } - new_entry = tomoyo_alloc_element(sizeof(*new_entry)); - if (!new_entry) + if (!tomoyo_memory_ok(new_entry)) goto out; new_entry->pattern = saved_pattern; list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); + new_entry = NULL; error = 0; out: mutex_unlock(&tomoyo_policy_lock); + kfree(new_entry); return error; } @@ -901,9 +907,13 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, goto out; } /* Not found. Append it to the tail. */ - acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL); - if (!acl) + acl = kmalloc(sizeof(*acl), GFP_KERNEL); + if (!tomoyo_memory_ok(acl)) { + kfree(acl); + acl = NULL; goto out; + } + acl->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; if (perm <= 0xFFFF) acl->perm = perm; else @@ -995,9 +1005,13 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, goto out; } /* Not found. Append it to the tail. */ - acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL); - if (!acl) + acl = kmalloc(sizeof(*acl), GFP_KERNEL); + if (!tomoyo_memory_ok(acl)) { + kfree(acl); + acl = NULL; goto out; + } + acl->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; acl->perm = perm; acl->filename1 = saved_filename1; acl->filename2 = saved_filename2; diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 9105e5e29da9..54226d5be493 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -212,57 +212,32 @@ static unsigned int tomoyo_allocated_memory_for_elements; static unsigned int tomoyo_quota_for_elements; /** - * tomoyo_alloc_element - Allocate permanent memory for structures. + * tomoyo_memory_ok - Check memory quota. * - * @size: Size in bytes. + * @ptr: Pointer to allocated memory. * - * Returns pointer to allocated memory on success, NULL otherwise. + * Returns true on success, false otherwise. * - * Memory has to be zeroed. - * The RAM is chunked, so NEVER try to kfree() the returned pointer. + * Caller holds tomoyo_policy_lock. + * Memory pointed by @ptr will be zeroed on success. */ -void *tomoyo_alloc_element(const unsigned int size) +bool tomoyo_memory_ok(void *ptr) { - static char *buf; - static DEFINE_MUTEX(lock); - static unsigned int buf_used_len = PATH_MAX; - char *ptr = NULL; - /*Assumes sizeof(void *) >= sizeof(long) is true. */ - const unsigned int word_aligned_size - = roundup(size, max(sizeof(void *), sizeof(long))); - if (word_aligned_size > PATH_MAX) - return NULL; - mutex_lock(&lock); - if (buf_used_len + word_aligned_size > PATH_MAX) { - if (!tomoyo_quota_for_elements || - tomoyo_allocated_memory_for_elements - + PATH_MAX <= tomoyo_quota_for_elements) - ptr = kzalloc(PATH_MAX, GFP_KERNEL); - if (!ptr) { - printk(KERN_WARNING "ERROR: Out of memory " - "for tomoyo_alloc_element().\n"); - if (!tomoyo_policy_loaded) - panic("MAC Initialization failed.\n"); - } else { - buf = ptr; - tomoyo_allocated_memory_for_elements += PATH_MAX; - buf_used_len = word_aligned_size; - ptr = buf; - } - } else if (word_aligned_size) { - int i; - ptr = buf + buf_used_len; - buf_used_len += word_aligned_size; - for (i = 0; i < word_aligned_size; i++) { - if (!ptr[i]) - continue; - printk(KERN_ERR "WARNING: Reserved memory was tainted! " - "The system might go wrong.\n"); - ptr[i] = '\0'; - } + int allocated_len = ptr ? ksize(ptr) : 0; + bool result = false; + if (!ptr || (tomoyo_quota_for_elements && + tomoyo_allocated_memory_for_elements + + allocated_len > tomoyo_quota_for_elements)) { + printk(KERN_WARNING "ERROR: Out of memory " + "for tomoyo_alloc_element().\n"); + if (!tomoyo_policy_loaded) + panic("MAC Initialization failed.\n"); + } else { + result = true; + tomoyo_allocated_memory_for_elements += allocated_len; + memset(ptr, 0, allocated_len); } - mutex_unlock(&lock); - return ptr; + return result; } /* Memory allocated for string data in bytes. */ diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h index 78217a37960b..47b4f59dad6f 100644 --- a/security/tomoyo/realpath.h +++ b/security/tomoyo/realpath.h @@ -36,11 +36,8 @@ char *tomoyo_realpath_nofollow(const char *pathname); /* Same with tomoyo_realpath() except that the pathname is already solved. */ char *tomoyo_realpath_from_path(struct path *path); -/* - * Allocate memory for ACL entry. - * The RAM is chunked, so NEVER try to kfree() the returned pointer. - */ -void *tomoyo_alloc_element(const unsigned int size); +/* Check memory quota. */ +bool tomoyo_memory_ok(void *ptr); /* * Keep the given name on the RAM. -- cgit v1.2.3-59-g8ed1b From 8e2d39a1665e680c095545993aac2fcac6916eb9 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 26 Jan 2010 20:45:27 +0900 Subject: TOMOYO: Remove usage counter for temporary memory. TOMOYO was using own memory usage counter for detecting memory leak. But as kernel 2.6.31 introduced memory leak detection mechanism ( CONFIG_DEBUG_KMEMLEAK ), we no longer need to have own counter. We remove usage counter for memory used for permission checks, but we keep usage counter for memory used for policy so that we can apply quota. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 22 +++++++++++----------- security/tomoyo/common.h | 2 +- security/tomoyo/domain.c | 8 ++++---- security/tomoyo/file.c | 15 ++++++++------- security/tomoyo/realpath.c | 45 ++++----------------------------------------- security/tomoyo/realpath.h | 8 +------- 6 files changed, 29 insertions(+), 71 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index e331e699cf54..ef6622300a81 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -750,7 +750,7 @@ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) * * Returns the tomoyo_realpath() of current process on success, NULL otherwise. * - * This function uses tomoyo_alloc(), so the caller must call tomoyo_free() + * This function uses kzalloc(), so the caller must call kfree() * if this function didn't return NULL. */ static const char *tomoyo_get_exe(void) @@ -1248,7 +1248,7 @@ static bool tomoyo_is_policy_manager(void) last_pid = pid; } } - tomoyo_free(exe); + kfree(exe); return found; } @@ -1931,7 +1931,7 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head) */ static int tomoyo_open_control(const u8 type, struct file *file) { - struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head)); + struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL); if (!head) return -ENOMEM; @@ -1992,9 +1992,9 @@ static int tomoyo_open_control(const u8 type, struct file *file) } else { if (!head->readbuf_size) head->readbuf_size = 4096 * 2; - head->read_buf = tomoyo_alloc(head->readbuf_size); + head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL); if (!head->read_buf) { - tomoyo_free(head); + kfree(head); return -ENOMEM; } } @@ -2006,10 +2006,10 @@ static int tomoyo_open_control(const u8 type, struct file *file) head->write = NULL; } else if (head->write) { head->writebuf_size = 4096 * 2; - head->write_buf = tomoyo_alloc(head->writebuf_size); + head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL); if (!head->write_buf) { - tomoyo_free(head->read_buf); - tomoyo_free(head); + kfree(head->read_buf); + kfree(head); return -ENOMEM; } } @@ -2141,11 +2141,11 @@ static int tomoyo_close_control(struct file *file) tomoyo_read_unlock(head->reader_idx); /* Release memory used for policy I/O. */ - tomoyo_free(head->read_buf); + kfree(head->read_buf); head->read_buf = NULL; - tomoyo_free(head->write_buf); + kfree(head->write_buf); head->write_buf = NULL; - tomoyo_free(head); + kfree(head); head = NULL; file->private_data = NULL; return 0; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 610a6a056828..8b59ec8fe11e 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -89,7 +89,7 @@ struct tomoyo_path_info { * "struct tomoyo_path_info_with_data". */ struct tomoyo_path_info_with_data { - /* Keep "head" first, for this pointer is passed to tomoyo_free(). */ + /* Keep "head" first, for this pointer is passed to kfree(). */ struct tomoyo_path_info head; char barrier1[16]; /* Safeguard for overrun. */ char body[TOMOYO_MAX_PATHNAME_LEN]; diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index a55a1cced58e..34843971cc60 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -787,7 +787,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) * This function assumes that the size of buffer returned by * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. */ - struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp)); + struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); struct tomoyo_domain_info *old_domain = tomoyo_domain(); struct tomoyo_domain_info *domain = NULL; const char *old_domain_name = old_domain->domainname->name; @@ -902,8 +902,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (!domain) domain = old_domain; bprm->cred->security = domain; - tomoyo_free(real_program_name); - tomoyo_free(symlink_program_name); - tomoyo_free(tmp); + kfree(real_program_name); + kfree(symlink_program_name); + kfree(tmp); return retval; } diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index cfcb096ee97a..24af081f1af9 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -150,7 +150,8 @@ static bool tomoyo_strendswith(const char *name, const char *tail) static struct tomoyo_path_info *tomoyo_get_path(struct path *path) { int error; - struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf)); + struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), + GFP_KERNEL); if (!buf) return NULL; @@ -162,7 +163,7 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path) tomoyo_fill_path_info(&buf->head); return &buf->head; } - tomoyo_free(buf); + kfree(buf); return NULL; } @@ -1227,7 +1228,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, TOMOYO_TYPE_TRUNCATE_ACL, buf, mode); out: - tomoyo_free(buf); + kfree(buf); tomoyo_read_unlock(idx); if (!is_enforce) error = 0; @@ -1273,7 +1274,7 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, error = tomoyo_check_single_path_permission2(domain, operation, buf, mode); out: - tomoyo_free(buf); + kfree(buf); tomoyo_read_unlock(idx); if (!is_enforce) error = 0; @@ -1312,7 +1313,7 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, TOMOYO_TYPE_REWRITE_ACL, buf, mode); out: - tomoyo_free(buf); + kfree(buf); tomoyo_read_unlock(idx); if (!is_enforce) error = 0; @@ -1379,8 +1380,8 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, false); } out: - tomoyo_free(buf1); - tomoyo_free(buf2); + kfree(buf1); + kfree(buf2); tomoyo_read_unlock(idx); if (!is_enforce) error = 0; diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 54226d5be493..92460c7ded67 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -150,12 +150,12 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname, * * Returns the realpath of the given @path on success, NULL otherwise. * - * These functions use tomoyo_alloc(), so the caller must call tomoyo_free() + * These functions use kzalloc(), so the caller must call kfree() * if these functions didn't return NULL. */ char *tomoyo_realpath_from_path(struct path *path) { - char *buf = tomoyo_alloc(sizeof(struct tomoyo_page_buffer)); + char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_KERNEL); BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) <= TOMOYO_MAX_PATHNAME_LEN - 1); @@ -164,7 +164,7 @@ char *tomoyo_realpath_from_path(struct path *path) if (tomoyo_realpath_from_path2(path, buf, TOMOYO_MAX_PATHNAME_LEN - 1) == 0) return buf; - tomoyo_free(buf); + kfree(buf); return NULL; } @@ -346,39 +346,6 @@ void __init tomoyo_realpath_init(void) panic("Can't register tomoyo_kernel_domain"); } -/* Memory allocated for temporary purpose. */ -static atomic_t tomoyo_dynamic_memory_size; - -/** - * tomoyo_alloc - Allocate memory for temporary purpose. - * - * @size: Size in bytes. - * - * Returns pointer to allocated memory on success, NULL otherwise. - */ -void *tomoyo_alloc(const size_t size) -{ - void *p = kzalloc(size, GFP_KERNEL); - if (p) - atomic_add(ksize(p), &tomoyo_dynamic_memory_size); - return p; -} - -/** - * tomoyo_free - Release memory allocated by tomoyo_alloc(). - * - * @p: Pointer returned by tomoyo_alloc(). May be NULL. - * - * Returns nothing. - */ -void tomoyo_free(const void *p) -{ - if (p) { - atomic_sub(ksize(p), &tomoyo_dynamic_memory_size); - kfree(p); - } -} - /** * tomoyo_read_memory_counter - Check for memory usage in bytes. * @@ -393,8 +360,6 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) = tomoyo_allocated_memory_for_savename; const unsigned int private = tomoyo_allocated_memory_for_elements; - const unsigned int dynamic - = atomic_read(&tomoyo_dynamic_memory_size); char buffer[64]; memset(buffer, 0, sizeof(buffer)); @@ -412,9 +377,7 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) else buffer[0] = '\0'; tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer); - tomoyo_io_printf(head, "Dynamic: %10u\n", dynamic); - tomoyo_io_printf(head, "Total: %10u\n", - shared + private + dynamic); + tomoyo_io_printf(head, "Total: %10u\n", shared + private); head->read_eof = true; } return 0; diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h index 47b4f59dad6f..da4f06ff6f8d 100644 --- a/security/tomoyo/realpath.h +++ b/security/tomoyo/realpath.h @@ -25,7 +25,7 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname, /* * Returns realpath(3) of the given pathname but ignores chroot'ed root. - * These functions use tomoyo_alloc(), so the caller must call tomoyo_free() + * These functions use kzalloc(), so the caller must call kfree() * if these functions didn't return NULL. */ char *tomoyo_realpath(const char *pathname); @@ -45,12 +45,6 @@ bool tomoyo_memory_ok(void *ptr); */ const struct tomoyo_path_info *tomoyo_save_name(const char *name); -/* Allocate memory for temporary use (e.g. permission checks). */ -void *tomoyo_alloc(const size_t size); - -/* Free memory allocated by tomoyo_alloc(). */ -void tomoyo_free(const void *p); - /* Check for memory usage. */ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); -- cgit v1.2.3-59-g8ed1b From ea13ddbad0eb4be9cdc406cd7e0804fa4011f6e4 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 3 Feb 2010 06:43:06 +0900 Subject: TOMOYO: Extract bitfield Since list elements are rounded up to kmalloc() size rather than sizeof(int), saving one byte by using bitfields is no longer helpful. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 16 +++++---------- security/tomoyo/common.h | 53 +++++++++++------------------------------------- security/tomoyo/domain.c | 25 +---------------------- security/tomoyo/file.c | 27 +++++++----------------- 4 files changed, 25 insertions(+), 96 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ef6622300a81..ae3ed7313ee0 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -842,9 +842,7 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) if (!domain) return true; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (ptr->type & TOMOYO_ACL_DELETED) - continue; - switch (tomoyo_acl_type2(ptr)) { + switch (ptr->type) { struct tomoyo_single_path_acl_record *acl; u32 perm; u8 i; @@ -1384,8 +1382,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) return 0; } if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { - tomoyo_set_domain_flag(domain, is_delete, - TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ); + domain->ignore_global_allow_read = !is_delete; return 0; } return tomoyo_write_file_policy(data, domain, is_delete); @@ -1486,10 +1483,8 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, struct tomoyo_acl_info *ptr) { - const u8 acl_type = tomoyo_acl_type2(ptr); + const u8 acl_type = ptr->type; - if (acl_type & TOMOYO_ACL_DELETED) - return true; if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) { struct tomoyo_single_path_acl_record *acl = container_of(ptr, @@ -1540,10 +1535,9 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) /* Print domainname and flags. */ if (domain->quota_warned) quota_exceeded = "quota_exceeded\n"; - if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED) + if (domain->transition_failed) transition_failed = "transition_failed\n"; - if (domain->flags & - TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) + if (domain->ignore_global_allow_read) ignore_global_allow_read = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 8b59ec8fe11e..509ced9ce698 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -101,11 +101,9 @@ struct tomoyo_path_info_with_data { * * (1) "list" which is linked to the ->acl_info_list of * "struct tomoyo_domain_info" - * (2) "type" which tells - * (a) type & 0x7F : type of the entry (either - * "struct tomoyo_single_path_acl_record" or - * "struct tomoyo_double_path_acl_record") - * (b) type & 0x80 : whether the entry is marked as "deleted". + * (2) "type" which tells type of the entry (either + * "struct tomoyo_single_path_acl_record" or + * "struct tomoyo_double_path_acl_record"). * * Packing "struct tomoyo_acl_info" allows * "struct tomoyo_single_path_acl_record" to embed "u8" + "u16" and @@ -114,17 +112,9 @@ struct tomoyo_path_info_with_data { */ struct tomoyo_acl_info { struct list_head list; - /* - * Type of this ACL entry. - * - * MSB is is_deleted flag. - */ u8 type; } __packed; -/* This ACL entry is deleted. */ -#define TOMOYO_ACL_DELETED 0x80 - /* * tomoyo_domain_info is a structure which is used for holding permissions * (e.g. "allow_read /lib/libc-2.5.so") given to each domain. @@ -138,7 +128,13 @@ struct tomoyo_acl_info { * "deleted", false otherwise. * (6) "quota_warned" is a bool which is used for suppressing warning message * when learning mode learned too much entries. - * (7) "flags" which remembers this domain's attributes. + * (7) "ignore_global_allow_read" is a bool which is true if this domain + * should ignore "allow_read" directive in exception policy. + * (8) "transition_failed" is a bool which is set to true when this domain was + * unable to create a new domain at tomoyo_find_next_domain() because the + * name of the domain to be created was too long or it could not allocate + * memory. If set to true, more than one process continued execve() + * without domain transition. * * A domain's lifecycle is an analogy of files on / directory. * Multiple domains with the same domainname cannot be created (as with @@ -155,23 +151,13 @@ struct tomoyo_domain_info { u8 profile; /* Profile number to use. */ bool is_deleted; /* Delete flag. */ bool quota_warned; /* Quota warnning flag. */ - /* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */ - u8 flags; + bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ + bool transition_failed; /* Domain transition failed flag. */ }; /* Profile number is an integer between 0 and 255. */ #define TOMOYO_MAX_PROFILES 256 -/* Ignore "allow_read" directive in exception policy. */ -#define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1 -/* - * This domain was unable to create a new domain at tomoyo_find_next_domain() - * because the name of the domain to be created was too long or - * it could not allocate memory. - * More than one process continued execve() without domain transition. - */ -#define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED 2 - /* * tomoyo_single_path_acl_record is a structure which is used for holding an * entry with one pathname operation (e.g. open(), mkdir()). @@ -380,9 +366,6 @@ unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); /* Run policy loader when /sbin/init starts. */ void tomoyo_load_policy(const char *filename); -/* Change "struct tomoyo_domain_info"->flags. */ -void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, - const bool is_delete, const u8 flags); /* strcmp() for "struct tomoyo_path_info" structure. */ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, @@ -391,18 +374,6 @@ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, return a->hash != b->hash || strcmp(a->name, b->name); } -/* Get type of an ACL entry. */ -static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr) -{ - return ptr->type & ~TOMOYO_ACL_DELETED; -} - -/* Get type of an ACL entry. */ -static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr) -{ - return ptr->type; -} - /** * tomoyo_is_valid - Check whether the character is a valid char. * diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 34843971cc60..ec612ae87b51 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -129,28 +129,6 @@ struct tomoyo_alias_entry { bool is_deleted; }; -/** - * tomoyo_set_domain_flag - Set or clear domain's attribute flags. - * - * @domain: Pointer to "struct tomoyo_domain_info". - * @is_delete: True if it is a delete request. - * @flags: Flags to set or clear. - * - * Returns nothing. - */ -void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, - const bool is_delete, const u8 flags) -{ - /* We need to serialize because this is bitfield operation. */ - static DEFINE_SPINLOCK(lock); - spin_lock(&lock); - if (!is_delete) - domain->flags |= flags; - else - domain->flags &= ~flags; - spin_unlock(&lock); -} - /** * tomoyo_get_last_name - Get last component of a domainname. * @@ -896,8 +874,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (is_enforce) retval = -EPERM; else - tomoyo_set_domain_flag(old_domain, false, - TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); + old_domain->transition_failed = true; out: if (!domain) domain = old_domain; diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 24af081f1af9..84c821a245ca 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -688,7 +688,7 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_single_path_acl_record *acl; - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_single_path_acl_record, head); @@ -770,8 +770,7 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, if (!filename) return 0; error = tomoyo_check_file_acl(domain, filename, perm); - if (error && perm == 4 && - (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0 + if (error && perm == 4 && !domain->ignore_global_allow_read && tomoyo_is_globally_readable_file(filename)) error = 0; if (perm == 6) @@ -885,15 +884,12 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, if (is_delete) goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_single_path_acl_record, head); if (acl->filename != saved_filename) continue; - /* Special case. Clear all bits if marked as deleted. */ - if (ptr->type & TOMOYO_ACL_DELETED) - acl->perm = 0; if (perm <= 0xFFFF) acl->perm |= perm; else @@ -902,7 +898,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) acl->perm |= rw_mask; - ptr->type &= ~TOMOYO_ACL_DELETED; error = 0; goto out; } @@ -927,7 +922,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, delete: error = -ENOENT; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_single_path_acl_record, head); @@ -941,8 +936,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) acl->perm &= ~rw_mask; - if (!acl->perm && !acl->perm_high) - ptr->type |= TOMOYO_ACL_DELETED; error = 0; break; } @@ -989,18 +982,14 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, if (is_delete) goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_double_path_acl_record, head); if (acl->filename1 != saved_filename1 || acl->filename2 != saved_filename2) continue; - /* Special case. Clear all bits if marked as deleted. */ - if (ptr->type & TOMOYO_ACL_DELETED) - acl->perm = 0; acl->perm |= perm; - ptr->type &= ~TOMOYO_ACL_DELETED; error = 0; goto out; } @@ -1021,7 +1010,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, delete: error = -ENOENT; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_double_path_acl_record, head); @@ -1029,8 +1018,6 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, acl->filename2 != saved_filename2) continue; acl->perm &= ~perm; - if (!acl->perm) - ptr->type |= TOMOYO_ACL_DELETED; error = 0; break; } @@ -1086,7 +1073,7 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, return 0; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { struct tomoyo_double_path_acl_record *acl; - if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) + if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) continue; acl = container_of(ptr, struct tomoyo_double_path_acl_record, head); -- cgit v1.2.3-59-g8ed1b From ca0b7df3374c5566468c17f26fa2dfd3fe3c6a37 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sun, 7 Feb 2010 20:23:59 +0900 Subject: TOMOYO: Reduce lines by using common path for addition and deletion. Since the codes for adding an entry and removing an entry are similar, we can save some lines by using "if (is_delete) { ... } else { ... }" branches. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 28 +++--- security/tomoyo/domain.c | 147 +++++++++++++++-------------- security/tomoyo/file.c | 234 ++++++++++++++++++++--------------------------- 3 files changed, 183 insertions(+), 226 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ae3ed7313ee0..a53ee059da48 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1103,10 +1103,10 @@ static LIST_HEAD(tomoyo_policy_manager_list); static int tomoyo_update_manager_entry(const char *manager, const bool is_delete) { - struct tomoyo_policy_manager_entry *new_entry; + struct tomoyo_policy_manager_entry *entry = NULL; struct tomoyo_policy_manager_entry *ptr; const struct tomoyo_path_info *saved_manager; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; bool is_domain = false; if (tomoyo_is_domain_def(manager)) { @@ -1120,29 +1120,25 @@ static int tomoyo_update_manager_entry(const char *manager, saved_manager = tomoyo_save_name(manager); if (!saved_manager) return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { if (ptr->manager != saved_manager) continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->manager = saved_manager; + entry->is_domain = is_domain; + list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->manager = saved_manager; - new_entry->is_domain = is_domain; - list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + kfree(entry); return error; } diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index ec612ae87b51..229de1e71a38 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -201,11 +201,11 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, const bool is_not, const bool is_delete) { - struct tomoyo_domain_initializer_entry *new_entry; + struct tomoyo_domain_initializer_entry *entry = NULL; struct tomoyo_domain_initializer_entry *ptr; const struct tomoyo_path_info *saved_program; const struct tomoyo_path_info *saved_domainname = NULL; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) @@ -218,12 +218,13 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, return -EINVAL; saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) - return -ENOMEM; + goto out; } saved_program = tomoyo_save_name(program); if (!saved_program) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { if (ptr->is_not != is_not || @@ -232,24 +233,21 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->domainname = saved_domainname; + entry->program = saved_program; + entry->is_not = is_not; + entry->is_last_name = is_last_name; + list_add_tail_rcu(&entry->list, + &tomoyo_domain_initializer_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->domainname = saved_domainname; - new_entry->program = saved_program; - new_entry->is_not = is_not; - new_entry->is_last_name = is_last_name; - list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + out: + kfree(entry); return error; } @@ -419,11 +417,11 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, const bool is_not, const bool is_delete) { - struct tomoyo_domain_keeper_entry *new_entry; + struct tomoyo_domain_keeper_entry *entry = NULL; struct tomoyo_domain_keeper_entry *ptr; const struct tomoyo_path_info *saved_domainname; const struct tomoyo_path_info *saved_program = NULL; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; if (!tomoyo_is_domain_def(domainname) && @@ -436,12 +434,13 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, return -EINVAL; saved_program = tomoyo_save_name(program); if (!saved_program) - return -ENOMEM; + goto out; } saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { if (ptr->is_not != is_not || @@ -450,24 +449,20 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->domainname = saved_domainname; + entry->program = saved_program; + entry->is_not = is_not; + entry->is_last_name = is_last_name; + list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->domainname = saved_domainname; - new_entry->program = saved_program; - new_entry->is_not = is_not; - new_entry->is_last_name = is_last_name; - list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + out: + kfree(entry); return error; } @@ -619,11 +614,11 @@ static int tomoyo_update_alias_entry(const char *original_name, const char *aliased_name, const bool is_delete) { - struct tomoyo_alias_entry *new_entry; + struct tomoyo_alias_entry *entry = NULL; struct tomoyo_alias_entry *ptr; const struct tomoyo_path_info *saved_original_name; const struct tomoyo_path_info *saved_aliased_name; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) @@ -631,8 +626,9 @@ static int tomoyo_update_alias_entry(const char *original_name, saved_original_name = tomoyo_save_name(original_name); saved_aliased_name = tomoyo_save_name(aliased_name); if (!saved_original_name || !saved_aliased_name) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->original_name != saved_original_name || @@ -640,22 +636,18 @@ static int tomoyo_update_alias_entry(const char *original_name, continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->original_name = saved_original_name; + entry->aliased_name = saved_aliased_name; + list_add_tail_rcu(&entry->list, &tomoyo_alias_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->original_name = saved_original_name; - new_entry->aliased_name = saved_aliased_name; - list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + out: + kfree(entry); return error; } @@ -722,32 +714,37 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, const u8 profile) { + struct tomoyo_domain_info *entry; struct tomoyo_domain_info *domain; const struct tomoyo_path_info *saved_domainname; + bool found = false; - mutex_lock(&tomoyo_policy_lock); - domain = tomoyo_find_domain(domainname); - if (domain) - goto out; if (!tomoyo_is_correct_domain(domainname, __func__)) - goto out; + return NULL; saved_domainname = tomoyo_save_name(domainname); if (!saved_domainname) - goto out; - domain = kmalloc(sizeof(*domain), GFP_KERNEL); - if (tomoyo_memory_ok(domain)) { - INIT_LIST_HEAD(&domain->acl_info_list); - domain->domainname = saved_domainname; - domain->profile = profile; - list_add_tail_rcu(&domain->list, &tomoyo_domain_list); - } else { - kfree(domain); - domain = NULL; + return NULL; + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + mutex_lock(&tomoyo_policy_lock); + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { + if (domain->is_deleted || + tomoyo_pathcmp(saved_domainname, domain->domainname)) + continue; + found = true; + break; + } + if (!found && tomoyo_memory_ok(entry)) { + INIT_LIST_HEAD(&entry->acl_info_list); + entry->domainname = saved_domainname; + entry->profile = profile; + list_add_tail_rcu(&entry->list, &tomoyo_domain_list); + domain = entry; + entry = NULL; + found = true; } - - out: mutex_unlock(&tomoyo_policy_lock); - return domain; + kfree(entry); + return found ? domain : NULL; } /** diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 84c821a245ca..f4a27714e077 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -215,38 +215,34 @@ static LIST_HEAD(tomoyo_globally_readable_list); static int tomoyo_update_globally_readable_entry(const char *filename, const bool is_delete) { - struct tomoyo_globally_readable_file_entry *new_entry; + struct tomoyo_globally_readable_file_entry *entry = NULL; struct tomoyo_globally_readable_file_entry *ptr; const struct tomoyo_path_info *saved_filename; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) return -EINVAL; saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { if (ptr->filename != saved_filename) continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->filename = saved_filename; + list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->filename = saved_filename; - list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + kfree(entry); return error; } @@ -364,38 +360,35 @@ static LIST_HEAD(tomoyo_pattern_list); static int tomoyo_update_file_pattern_entry(const char *pattern, const bool is_delete) { - struct tomoyo_pattern_entry *new_entry; + struct tomoyo_pattern_entry *entry = NULL; struct tomoyo_pattern_entry *ptr; const struct tomoyo_path_info *saved_pattern; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__)) - return -EINVAL; saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + return error; + if (!saved_pattern->is_patterned) + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { if (saved_pattern != ptr->pattern) continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->pattern = saved_pattern; + list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->pattern = saved_pattern; - list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + out: + kfree(entry); return error; } @@ -518,37 +511,34 @@ static LIST_HEAD(tomoyo_no_rewrite_list); static int tomoyo_update_no_rewrite_entry(const char *pattern, const bool is_delete) { - struct tomoyo_no_rewrite_entry *new_entry, *ptr; + struct tomoyo_no_rewrite_entry *entry = NULL; + struct tomoyo_no_rewrite_entry *ptr; const struct tomoyo_path_info *saved_pattern; - int error = -ENOMEM; + int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) return -EINVAL; saved_pattern = tomoyo_save_name(pattern); if (!saved_pattern) - return -ENOMEM; - new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); + return error; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { if (ptr->pattern != saved_pattern) continue; ptr->is_deleted = is_delete; error = 0; - goto out; + break; } - if (is_delete) { - error = -ENOENT; - goto out; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->pattern = saved_pattern; + list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); + entry = NULL; + error = 0; } - if (!tomoyo_memory_ok(new_entry)) - goto out; - new_entry->pattern = saved_pattern; - list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); - new_entry = NULL; - error = 0; - out: mutex_unlock(&tomoyo_policy_lock); - kfree(new_entry); + kfree(entry); return error; } @@ -869,8 +859,8 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL); const struct tomoyo_path_info *saved_filename; struct tomoyo_acl_info *ptr; - struct tomoyo_single_path_acl_record *acl; - int error = -ENOMEM; + struct tomoyo_single_path_acl_record *entry = NULL; + int error = is_delete ? -ENOENT : -ENOMEM; const u32 perm = 1 << type; if (!domain) @@ -880,67 +870,55 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, saved_filename = tomoyo_save_name(filename); if (!saved_filename) return -ENOMEM; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); - if (is_delete) - goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { + struct tomoyo_single_path_acl_record *acl = + container_of(ptr, struct tomoyo_single_path_acl_record, + head); if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) continue; - acl = container_of(ptr, struct tomoyo_single_path_acl_record, - head); if (acl->filename != saved_filename) continue; - if (perm <= 0xFFFF) - acl->perm |= perm; - else - acl->perm_high |= (perm >> 16); - if ((acl->perm & rw_mask) == rw_mask) - acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; - else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) - acl->perm |= rw_mask; + if (is_delete) { + if (perm <= 0xFFFF) + acl->perm &= ~perm; + else + acl->perm_high &= ~(perm >> 16); + if ((acl->perm & rw_mask) != rw_mask) + acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); + else if (!(acl->perm & + (1 << TOMOYO_TYPE_READ_WRITE_ACL))) + acl->perm &= ~rw_mask; + } else { + if (perm <= 0xFFFF) + acl->perm |= perm; + else + acl->perm_high |= (perm >> 16); + if ((acl->perm & rw_mask) == rw_mask) + acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; + else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) + acl->perm |= rw_mask; + } error = 0; - goto out; - } - /* Not found. Append it to the tail. */ - acl = kmalloc(sizeof(*acl), GFP_KERNEL); - if (!tomoyo_memory_ok(acl)) { - kfree(acl); - acl = NULL; - goto out; + break; } - acl->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; - if (perm <= 0xFFFF) - acl->perm = perm; - else - acl->perm_high = (perm >> 16); - if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) - acl->perm |= rw_mask; - acl->filename = saved_filename; - list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); - error = 0; - goto out; - delete: - error = -ENOENT; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) - continue; - acl = container_of(ptr, struct tomoyo_single_path_acl_record, - head); - if (acl->filename != saved_filename) - continue; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; if (perm <= 0xFFFF) - acl->perm &= ~perm; + entry->perm = perm; else - acl->perm_high &= ~(perm >> 16); - if ((acl->perm & rw_mask) != rw_mask) - acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); - else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) - acl->perm &= ~rw_mask; + entry->perm_high = (perm >> 16); + if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) + entry->perm |= rw_mask; + entry->filename = saved_filename; + list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); + entry = NULL; error = 0; - break; } - out: mutex_unlock(&tomoyo_policy_lock); + kfree(entry); return error; } @@ -965,8 +943,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, const struct tomoyo_path_info *saved_filename1; const struct tomoyo_path_info *saved_filename2; struct tomoyo_acl_info *ptr; - struct tomoyo_double_path_acl_record *acl; - int error = -ENOMEM; + struct tomoyo_double_path_acl_record *entry = NULL; + int error = is_delete ? -ENOENT : -ENOMEM; const u8 perm = 1 << type; if (!domain) @@ -977,52 +955,38 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, saved_filename1 = tomoyo_save_name(filename1); saved_filename2 = tomoyo_save_name(filename2); if (!saved_filename1 || !saved_filename2) - return -ENOMEM; + goto out; + if (!is_delete) + entry = kmalloc(sizeof(*entry), GFP_KERNEL); mutex_lock(&tomoyo_policy_lock); - if (is_delete) - goto delete; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { + struct tomoyo_double_path_acl_record *acl = + container_of(ptr, struct tomoyo_double_path_acl_record, + head); if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) continue; - acl = container_of(ptr, struct tomoyo_double_path_acl_record, - head); if (acl->filename1 != saved_filename1 || acl->filename2 != saved_filename2) continue; - acl->perm |= perm; + if (is_delete) + acl->perm &= ~perm; + else + acl->perm |= perm; error = 0; - goto out; - } - /* Not found. Append it to the tail. */ - acl = kmalloc(sizeof(*acl), GFP_KERNEL); - if (!tomoyo_memory_ok(acl)) { - kfree(acl); - acl = NULL; - goto out; + break; } - acl->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; - acl->perm = perm; - acl->filename1 = saved_filename1; - acl->filename2 = saved_filename2; - list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); - error = 0; - goto out; - delete: - error = -ENOENT; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) - continue; - acl = container_of(ptr, struct tomoyo_double_path_acl_record, - head); - if (acl->filename1 != saved_filename1 || - acl->filename2 != saved_filename2) - continue; - acl->perm &= ~perm; + if (!is_delete && error && tomoyo_memory_ok(entry)) { + entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; + entry->perm = perm; + entry->filename1 = saved_filename1; + entry->filename2 = saved_filename2; + list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); + entry = NULL; error = 0; - break; } - out: mutex_unlock(&tomoyo_policy_lock); + out: + kfree(entry); return error; } -- cgit v1.2.3-59-g8ed1b From bf24fb016c861b7f52be0c36c4cedd3e89afa2e2 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 11 Feb 2010 09:41:58 +0900 Subject: TOMOYO: Add refcounter on string data. Add refcounter to "struct tomoyo_name_entry" and replace tomoyo_save_name() with tomoyo_get_name()/tomoyo_put_name() pair so that we can kfree() when garbage collector is added. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 10 +++++++--- security/tomoyo/domain.c | 32 +++++++++++++++++++++++--------- security/tomoyo/file.c | 24 ++++++++++++++++++------ security/tomoyo/realpath.c | 30 +++++++++--------------------- security/tomoyo/realpath.h | 21 ++++++++++++++++++++- 5 files changed, 77 insertions(+), 40 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index a53ee059da48..0c7ea51e7a45 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -12,8 +12,8 @@ #include #include #include -#include "realpath.h" #include "common.h" +#include "realpath.h" #include "tomoyo.h" /* Lock for protecting policy. */ @@ -943,7 +943,9 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) return -EINVAL; *cp = '\0'; if (!strcmp(data, "COMMENT")) { - profile->comment = tomoyo_save_name(cp + 1); + const struct tomoyo_path_info *old_comment = profile->comment; + profile->comment = tomoyo_get_name(cp + 1); + tomoyo_put_name(old_comment); return 0; } for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { @@ -1117,7 +1119,7 @@ static int tomoyo_update_manager_entry(const char *manager, if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__)) return -EINVAL; } - saved_manager = tomoyo_save_name(manager); + saved_manager = tomoyo_get_name(manager); if (!saved_manager) return -ENOMEM; if (!is_delete) @@ -1132,12 +1134,14 @@ static int tomoyo_update_manager_entry(const char *manager, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->manager = saved_manager; + saved_manager = NULL; entry->is_domain = is_domain; list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); + tomoyo_put_name(saved_manager); kfree(entry); return error; } diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 229de1e71a38..0b8262567809 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -203,7 +203,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, { struct tomoyo_domain_initializer_entry *entry = NULL; struct tomoyo_domain_initializer_entry *ptr; - const struct tomoyo_path_info *saved_program; + const struct tomoyo_path_info *saved_program = NULL; const struct tomoyo_path_info *saved_domainname = NULL; int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; @@ -216,11 +216,11 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, is_last_name = true; else if (!tomoyo_is_correct_domain(domainname, __func__)) return -EINVAL; - saved_domainname = tomoyo_save_name(domainname); + saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) goto out; } - saved_program = tomoyo_save_name(program); + saved_program = tomoyo_get_name(program); if (!saved_program) goto out; if (!is_delete) @@ -237,7 +237,9 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->domainname = saved_domainname; + saved_domainname = NULL; entry->program = saved_program; + saved_program = NULL; entry->is_not = is_not; entry->is_last_name = is_last_name; list_add_tail_rcu(&entry->list, @@ -247,6 +249,8 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, } mutex_unlock(&tomoyo_policy_lock); out: + tomoyo_put_name(saved_domainname); + tomoyo_put_name(saved_program); kfree(entry); return error; } @@ -419,7 +423,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, { struct tomoyo_domain_keeper_entry *entry = NULL; struct tomoyo_domain_keeper_entry *ptr; - const struct tomoyo_path_info *saved_domainname; + const struct tomoyo_path_info *saved_domainname = NULL; const struct tomoyo_path_info *saved_program = NULL; int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; @@ -432,11 +436,11 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, if (program) { if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) return -EINVAL; - saved_program = tomoyo_save_name(program); + saved_program = tomoyo_get_name(program); if (!saved_program) goto out; } - saved_domainname = tomoyo_save_name(domainname); + saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) goto out; if (!is_delete) @@ -453,7 +457,9 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->domainname = saved_domainname; + saved_domainname = NULL; entry->program = saved_program; + saved_program = NULL; entry->is_not = is_not; entry->is_last_name = is_last_name; list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); @@ -462,6 +468,8 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, } mutex_unlock(&tomoyo_policy_lock); out: + tomoyo_put_name(saved_domainname); + tomoyo_put_name(saved_program); kfree(entry); return error; } @@ -623,8 +631,8 @@ static int tomoyo_update_alias_entry(const char *original_name, if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) return -EINVAL; /* No patterns allowed. */ - saved_original_name = tomoyo_save_name(original_name); - saved_aliased_name = tomoyo_save_name(aliased_name); + saved_original_name = tomoyo_get_name(original_name); + saved_aliased_name = tomoyo_get_name(aliased_name); if (!saved_original_name || !saved_aliased_name) goto out; if (!is_delete) @@ -640,13 +648,17 @@ static int tomoyo_update_alias_entry(const char *original_name, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->original_name = saved_original_name; + saved_original_name = NULL; entry->aliased_name = saved_aliased_name; + saved_aliased_name = NULL; list_add_tail_rcu(&entry->list, &tomoyo_alias_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); out: + tomoyo_put_name(saved_original_name); + tomoyo_put_name(saved_aliased_name); kfree(entry); return error; } @@ -721,7 +733,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * if (!tomoyo_is_correct_domain(domainname, __func__)) return NULL; - saved_domainname = tomoyo_save_name(domainname); + saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) return NULL; entry = kzalloc(sizeof(*entry), GFP_KERNEL); @@ -736,6 +748,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * if (!found && tomoyo_memory_ok(entry)) { INIT_LIST_HEAD(&entry->acl_info_list); entry->domainname = saved_domainname; + saved_domainname = NULL; entry->profile = profile; list_add_tail_rcu(&entry->list, &tomoyo_domain_list); domain = entry; @@ -743,6 +756,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * found = true; } mutex_unlock(&tomoyo_policy_lock); + tomoyo_put_name(saved_domainname); kfree(entry); return found ? domain : NULL; } diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index f4a27714e077..a49e18cc7bc2 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -222,7 +222,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) return -EINVAL; - saved_filename = tomoyo_save_name(filename); + saved_filename = tomoyo_get_name(filename); if (!saved_filename) return -ENOMEM; if (!is_delete) @@ -237,11 +237,13 @@ static int tomoyo_update_globally_readable_entry(const char *filename, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->filename = saved_filename; + saved_filename = NULL; list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); + tomoyo_put_name(saved_filename); kfree(entry); return error; } @@ -365,7 +367,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, const struct tomoyo_path_info *saved_pattern; int error = is_delete ? -ENOENT : -ENOMEM; - saved_pattern = tomoyo_save_name(pattern); + saved_pattern = tomoyo_get_name(pattern); if (!saved_pattern) return error; if (!saved_pattern->is_patterned) @@ -382,6 +384,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->pattern = saved_pattern; + saved_pattern = NULL; list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); entry = NULL; error = 0; @@ -389,6 +392,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, mutex_unlock(&tomoyo_policy_lock); out: kfree(entry); + tomoyo_put_name(saved_pattern); return error; } @@ -518,7 +522,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) return -EINVAL; - saved_pattern = tomoyo_save_name(pattern); + saved_pattern = tomoyo_get_name(pattern); if (!saved_pattern) return error; if (!is_delete) @@ -533,11 +537,13 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, } if (!is_delete && error && tomoyo_memory_ok(entry)) { entry->pattern = saved_pattern; + saved_pattern = NULL; list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); + tomoyo_put_name(saved_pattern); kfree(entry); return error; } @@ -867,7 +873,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, return -EINVAL; if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__)) return -EINVAL; - saved_filename = tomoyo_save_name(filename); + saved_filename = tomoyo_get_name(filename); if (!saved_filename) return -ENOMEM; if (!is_delete) @@ -913,12 +919,14 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) entry->perm |= rw_mask; entry->filename = saved_filename; + saved_filename = NULL; list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); kfree(entry); + tomoyo_put_name(saved_filename); return error; } @@ -952,8 +960,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) || !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__)) return -EINVAL; - saved_filename1 = tomoyo_save_name(filename1); - saved_filename2 = tomoyo_save_name(filename2); + saved_filename1 = tomoyo_get_name(filename1); + saved_filename2 = tomoyo_get_name(filename2); if (!saved_filename1 || !saved_filename2) goto out; if (!is_delete) @@ -979,13 +987,17 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; entry->perm = perm; entry->filename1 = saved_filename1; + saved_filename1 = NULL; entry->filename2 = saved_filename2; + saved_filename2 = NULL; list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); entry = NULL; error = 0; } mutex_unlock(&tomoyo_policy_lock); out: + tomoyo_put_name(saved_filename1); + tomoyo_put_name(saved_filename2); kfree(entry); return error; } diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 92460c7ded67..2f7f54fc6812 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -253,21 +253,6 @@ static unsigned int tomoyo_quota_for_savename; #define TOMOYO_HASH_BITS 8 #define TOMOYO_MAX_HASH (1u<entry.hash && !strcmp(name, ptr->entry.name)) - goto out; + if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) + continue; + atomic_inc(&ptr->users); + goto out; } ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); allocated_len = ptr ? ksize(ptr) : 0; @@ -309,7 +296,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) > tomoyo_quota_for_savename)) { kfree(ptr); printk(KERN_WARNING "ERROR: Out of memory " - "for tomoyo_save_name().\n"); + "for tomoyo_get_name().\n"); if (!tomoyo_policy_loaded) panic("MAC Initialization failed.\n"); ptr = NULL; @@ -318,6 +305,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) tomoyo_allocated_memory_for_savename += allocated_len; ptr->entry.name = ((char *) ptr) + sizeof(*ptr); memmove((char *) ptr->entry.name, name, len); + atomic_set(&ptr->users, 1); tomoyo_fill_path_info(&ptr->entry); list_add_tail(&ptr->list, head); out: @@ -336,7 +324,7 @@ void __init tomoyo_realpath_init(void) for (i = 0; i < TOMOYO_MAX_HASH; i++) INIT_LIST_HEAD(&tomoyo_name_list[i]); INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); - tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME); + tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); /* * tomoyo_read_lock() is not needed because this function is * called before the first "delete" request. diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h index da4f06ff6f8d..b94cb512adb5 100644 --- a/security/tomoyo/realpath.h +++ b/security/tomoyo/realpath.h @@ -43,7 +43,7 @@ bool tomoyo_memory_ok(void *ptr); * Keep the given name on the RAM. * The RAM is shared, so NEVER try to modify or kfree() the returned name. */ -const struct tomoyo_path_info *tomoyo_save_name(const char *name); +const struct tomoyo_path_info *tomoyo_get_name(const char *name); /* Check for memory usage. */ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); @@ -54,4 +54,23 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); /* Initialize realpath related code. */ void __init tomoyo_realpath_init(void); +/* + * tomoyo_name_entry is a structure which is used for linking + * "struct tomoyo_path_info" into tomoyo_name_list . + */ +struct tomoyo_name_entry { + struct list_head list; + atomic_t users; + struct tomoyo_path_info entry; +}; + +static inline void tomoyo_put_name(const struct tomoyo_path_info *name) +{ + if (name) { + struct tomoyo_name_entry *ptr = + container_of(name, struct tomoyo_name_entry, entry); + atomic_dec(&ptr->users); + } +} + #endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */ -- cgit v1.2.3-59-g8ed1b From 76bb0895d038be7bcdb6ccfcd2dd7deb30371d6b Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 11 Feb 2010 09:42:40 +0900 Subject: TOMOYO: Merge headers. Gather structures and constants scattered around security/tomoyo/ directory. This is for preparation for adding garbage collector since garbage collector needs to know structures and constants which TOMOYO uses. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.c | 23 --- security/tomoyo/common.h | 411 ++++++++++++++++++++++++++++++++++++++------- security/tomoyo/domain.c | 72 -------- security/tomoyo/file.c | 52 ------ security/tomoyo/realpath.c | 10 -- security/tomoyo/realpath.h | 76 --------- security/tomoyo/tomoyo.c | 2 - security/tomoyo/tomoyo.h | 102 ----------- 8 files changed, 351 insertions(+), 397 deletions(-) delete mode 100644 security/tomoyo/realpath.h delete mode 100644 security/tomoyo/tomoyo.h (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 0c7ea51e7a45..634f7449e8ba 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -13,8 +13,6 @@ #include #include #include "common.h" -#include "realpath.h" -#include "tomoyo.h" /* Lock for protecting policy. */ DEFINE_MUTEX(tomoyo_policy_lock); @@ -1039,27 +1037,6 @@ static int tomoyo_read_profile(struct tomoyo_io_buffer *head) return 0; } -/* - * tomoyo_policy_manager_entry is a structure which is used for holding list of - * domainnames or programs which are permitted to modify configuration via - * /sys/kernel/security/tomoyo/ interface. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_policy_manager_list . - * (2) "manager" is a domainname or a program's pathname. - * (3) "is_domain" is a bool which is true if "manager" is a domainname, false - * otherwise. - * (4) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - */ -struct tomoyo_policy_manager_entry { - struct list_head list; - /* A path to program or a domainname. */ - const struct tomoyo_path_info *manager; - bool is_domain; /* True if manager is a domainname. */ - bool is_deleted; /* True if this entry is deleted. */ -}; - /* * tomoyo_policy_manager_list is used for holding list of domainnames or * programs which are permitted to modify configuration via diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 509ced9ce698..f6aff59b0885 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -1,12 +1,9 @@ /* * security/tomoyo/common.h * - * Common functions for TOMOYO. - * - * Copyright (C) 2005-2009 NTT DATA CORPORATION - * - * Version: 2.2.0 2009/04/01 + * Header file for TOMOYO. * + * Copyright (C) 2005-2010 NTT DATA CORPORATION */ #ifndef _SECURITY_TOMOYO_COMMON_H @@ -22,9 +19,110 @@ #include #include #include +#include +struct linux_binprm; + +/********** Constants definitions. **********/ + +/* + * TOMOYO uses this hash only when appending a string into the string + * table. Frequency of appending strings is very low. So we don't need + * large (e.g. 64k) hash size. 256 will be sufficient. + */ +#define TOMOYO_HASH_BITS 8 +#define TOMOYO_MAX_HASH (1u<. */ +#define TOMOYO_ROOT_NAME "" +#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) + +/* Index numbers for Access Controls. */ +#define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */ +#define TOMOYO_MAX_ACCEPT_ENTRY 1 +#define TOMOYO_VERBOSE 2 +#define TOMOYO_MAX_CONTROL_INDEX 3 + +/* Index numbers for Access Controls. */ + +#define TOMOYO_TYPE_SINGLE_PATH_ACL 0 +#define TOMOYO_TYPE_DOUBLE_PATH_ACL 1 + +/* Index numbers for File Controls. */ + +/* + * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set + * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and + * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set. + * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or + * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are + * automatically cleared if TYPE_READ_WRITE_ACL is cleared. + */ + +#define TOMOYO_TYPE_READ_WRITE_ACL 0 +#define TOMOYO_TYPE_EXECUTE_ACL 1 +#define TOMOYO_TYPE_READ_ACL 2 +#define TOMOYO_TYPE_WRITE_ACL 3 +#define TOMOYO_TYPE_CREATE_ACL 4 +#define TOMOYO_TYPE_UNLINK_ACL 5 +#define TOMOYO_TYPE_MKDIR_ACL 6 +#define TOMOYO_TYPE_RMDIR_ACL 7 +#define TOMOYO_TYPE_MKFIFO_ACL 8 +#define TOMOYO_TYPE_MKSOCK_ACL 9 +#define TOMOYO_TYPE_MKBLOCK_ACL 10 +#define TOMOYO_TYPE_MKCHAR_ACL 11 +#define TOMOYO_TYPE_TRUNCATE_ACL 12 +#define TOMOYO_TYPE_SYMLINK_ACL 13 +#define TOMOYO_TYPE_REWRITE_ACL 14 +#define TOMOYO_TYPE_IOCTL_ACL 15 +#define TOMOYO_TYPE_CHMOD_ACL 16 +#define TOMOYO_TYPE_CHOWN_ACL 17 +#define TOMOYO_TYPE_CHGRP_ACL 18 +#define TOMOYO_TYPE_CHROOT_ACL 19 +#define TOMOYO_TYPE_MOUNT_ACL 20 +#define TOMOYO_TYPE_UMOUNT_ACL 21 +#define TOMOYO_MAX_SINGLE_PATH_OPERATION 22 + +#define TOMOYO_TYPE_LINK_ACL 0 +#define TOMOYO_TYPE_RENAME_ACL 1 +#define TOMOYO_TYPE_PIVOT_ROOT_ACL 2 +#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 3 + +#define TOMOYO_DOMAINPOLICY 0 +#define TOMOYO_EXCEPTIONPOLICY 1 +#define TOMOYO_DOMAIN_STATUS 2 +#define TOMOYO_PROCESS_STATUS 3 +#define TOMOYO_MEMINFO 4 +#define TOMOYO_SELFDOMAIN 5 +#define TOMOYO_VERSION 6 +#define TOMOYO_PROFILE 7 +#define TOMOYO_MANAGER 8 -struct dentry; -struct vfsmount; +/********** Structure definitions. **********/ /* * tomoyo_page_buffer is a structure which is used for holding a pathname @@ -66,13 +164,14 @@ struct tomoyo_path_info { }; /* - * This is the max length of a token. - * - * A token consists of only ASCII printable characters. - * Non printable characters in a token is represented in \ooo style - * octal string. Thus, \ itself is represented as \\. + * tomoyo_name_entry is a structure which is used for linking + * "struct tomoyo_path_info" into tomoyo_name_list . */ -#define TOMOYO_MAX_PATHNAME_LEN 4000 +struct tomoyo_name_entry { + struct list_head list; + atomic_t users; + struct tomoyo_path_info entry; +}; /* * tomoyo_path_info_with_data is a structure which is used for holding a @@ -155,9 +254,6 @@ struct tomoyo_domain_info { bool transition_failed; /* Domain transition failed flag. */ }; -/* Profile number is an integer between 0 and 255. */ -#define TOMOYO_MAX_PROFILES 256 - /* * tomoyo_single_path_acl_record is a structure which is used for holding an * entry with one pathname operation (e.g. open(), mkdir()). @@ -204,29 +300,6 @@ struct tomoyo_double_path_acl_record { const struct tomoyo_path_info *filename2; }; -/* Keywords for ACLs. */ -#define TOMOYO_KEYWORD_ALIAS "alias " -#define TOMOYO_KEYWORD_ALLOW_READ "allow_read " -#define TOMOYO_KEYWORD_DELETE "delete " -#define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite " -#define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern " -#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain " -#define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " -#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " -#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " -#define TOMOYO_KEYWORD_SELECT "select " -#define TOMOYO_KEYWORD_USE_PROFILE "use_profile " -#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" -/* A domain definition starts with . */ -#define TOMOYO_ROOT_NAME "" -#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) - -/* Index numbers for Access Controls. */ -#define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */ -#define TOMOYO_MAX_ACCEPT_ENTRY 1 -#define TOMOYO_VERBOSE 2 -#define TOMOYO_MAX_CONTROL_INDEX 3 - /* * tomoyo_io_buffer is a structure which is used for reading and modifying * configuration via /sys/kernel/security/tomoyo/ interface. @@ -285,6 +358,149 @@ struct tomoyo_io_buffer { int writebuf_size; }; +/* + * tomoyo_globally_readable_file_entry is a structure which is used for holding + * "allow_read" entries. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_globally_readable_list . + * (2) "filename" is a pathname which is allowed to open(O_RDONLY). + * (3) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + */ +struct tomoyo_globally_readable_file_entry { + struct list_head list; + const struct tomoyo_path_info *filename; + bool is_deleted; +}; + +/* + * tomoyo_pattern_entry is a structure which is used for holding + * "tomoyo_pattern_list" entries. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_pattern_list . + * (2) "pattern" is a pathname pattern which is used for converting pathnames + * to pathname patterns during learning mode. + * (3) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + */ +struct tomoyo_pattern_entry { + struct list_head list; + const struct tomoyo_path_info *pattern; + bool is_deleted; +}; + +/* + * tomoyo_no_rewrite_entry is a structure which is used for holding + * "deny_rewrite" entries. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_no_rewrite_list . + * (2) "pattern" is a pathname which is by default not permitted to modify + * already existing content. + * (3) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + */ +struct tomoyo_no_rewrite_entry { + struct list_head list; + const struct tomoyo_path_info *pattern; + bool is_deleted; +}; + +/* + * tomoyo_domain_initializer_entry is a structure which is used for holding + * "initialize_domain" and "no_initialize_domain" entries. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_domain_initializer_list . + * (2) "domainname" which is "a domainname" or "the last component of a + * domainname". This field is NULL if "from" clause is not specified. + * (3) "program" which is a program's pathname. + * (4) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + * (5) "is_not" is a bool which is true if "no_initialize_domain", false + * otherwise. + * (6) "is_last_name" is a bool which is true if "domainname" is "the last + * component of a domainname", false otherwise. + */ +struct tomoyo_domain_initializer_entry { + struct list_head list; + const struct tomoyo_path_info *domainname; /* This may be NULL */ + const struct tomoyo_path_info *program; + bool is_deleted; + bool is_not; /* True if this entry is "no_initialize_domain". */ + /* True if the domainname is tomoyo_get_last_name(). */ + bool is_last_name; +}; + +/* + * tomoyo_domain_keeper_entry is a structure which is used for holding + * "keep_domain" and "no_keep_domain" entries. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_domain_keeper_list . + * (2) "domainname" which is "a domainname" or "the last component of a + * domainname". + * (3) "program" which is a program's pathname. + * This field is NULL if "from" clause is not specified. + * (4) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + * (5) "is_not" is a bool which is true if "no_initialize_domain", false + * otherwise. + * (6) "is_last_name" is a bool which is true if "domainname" is "the last + * component of a domainname", false otherwise. + */ +struct tomoyo_domain_keeper_entry { + struct list_head list; + const struct tomoyo_path_info *domainname; + const struct tomoyo_path_info *program; /* This may be NULL */ + bool is_deleted; + bool is_not; /* True if this entry is "no_keep_domain". */ + /* True if the domainname is tomoyo_get_last_name(). */ + bool is_last_name; +}; + +/* + * tomoyo_alias_entry is a structure which is used for holding "alias" entries. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_alias_list . + * (2) "original_name" which is a dereferenced pathname. + * (3) "aliased_name" which is a symlink's pathname. + * (4) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + */ +struct tomoyo_alias_entry { + struct list_head list; + const struct tomoyo_path_info *original_name; + const struct tomoyo_path_info *aliased_name; + bool is_deleted; +}; + +/* + * tomoyo_policy_manager_entry is a structure which is used for holding list of + * domainnames or programs which are permitted to modify configuration via + * /sys/kernel/security/tomoyo/ interface. + * It has following fields. + * + * (1) "list" which is linked to tomoyo_policy_manager_list . + * (2) "manager" is a domainname or a program's pathname. + * (3) "is_domain" is a bool which is true if "manager" is a domainname, false + * otherwise. + * (4) "is_deleted" is a bool which is true if marked as deleted, false + * otherwise. + */ +struct tomoyo_policy_manager_entry { + struct list_head list; + /* A path to program or a domainname. */ + const struct tomoyo_path_info *manager; + bool is_domain; /* True if manager is a domainname. */ + bool is_deleted; /* True if this entry is deleted. */ +}; + +/********** Function prototypes. **********/ + /* Check whether the domain has too many ACL entries to hold. */ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); /* Transactional sprintf() for policy dump. */ @@ -367,6 +583,85 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); /* Run policy loader when /sbin/init starts. */ void tomoyo_load_policy(const char *filename); +/* Convert binary string to ascii string. */ +int tomoyo_encode(char *buffer, int buflen, const char *str); + +/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */ +int tomoyo_realpath_from_path2(struct path *path, char *newname, + int newname_len); + +/* + * Returns realpath(3) of the given pathname but ignores chroot'ed root. + * These functions use kzalloc(), so the caller must call kfree() + * if these functions didn't return NULL. + */ +char *tomoyo_realpath(const char *pathname); +/* + * Same with tomoyo_realpath() except that it doesn't follow the final symlink. + */ +char *tomoyo_realpath_nofollow(const char *pathname); +/* Same with tomoyo_realpath() except that the pathname is already solved. */ +char *tomoyo_realpath_from_path(struct path *path); + +/* Check memory quota. */ +bool tomoyo_memory_ok(void *ptr); + +/* + * Keep the given name on the RAM. + * The RAM is shared, so NEVER try to modify or kfree() the returned name. + */ +const struct tomoyo_path_info *tomoyo_get_name(const char *name); + +/* Check for memory usage. */ +int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); + +/* Set memory quota. */ +int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); + +/* Initialize realpath related code. */ +void __init tomoyo_realpath_init(void); +int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, + const struct tomoyo_path_info *filename); +int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, + struct path *path, const int flag); +int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, + const u8 operation, struct path *path); +int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain, + const u8 operation, struct path *path1, + struct path *path2); +int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, + struct file *filp); +int tomoyo_find_next_domain(struct linux_binprm *bprm); + +/********** External variable definitions. **********/ + +/* Lock for GC. */ +extern struct srcu_struct tomoyo_ss; + +/* The list for "struct tomoyo_domain_info". */ +extern struct list_head tomoyo_domain_list; + +/* Lock for protecting policy. */ +extern struct mutex tomoyo_policy_lock; + +/* Has /sbin/init started? */ +extern bool tomoyo_policy_loaded; + +/* The kernel's domain. */ +extern struct tomoyo_domain_info tomoyo_kernel_domain; + +/********** Inlined functions. **********/ + +static inline int tomoyo_read_lock(void) +{ + return srcu_read_lock(&tomoyo_ss); +} + +static inline void tomoyo_read_unlock(int idx) +{ + srcu_read_unlock(&tomoyo_ss, idx); +} + /* strcmp() for "struct tomoyo_path_info" structure. */ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, const struct tomoyo_path_info *b) @@ -398,17 +693,25 @@ static inline bool tomoyo_is_invalid(const unsigned char c) return c && (c <= ' ' || c >= 127); } -/* The list for "struct tomoyo_domain_info". */ -extern struct list_head tomoyo_domain_list; - -/* Lock for protecting policy. */ -extern struct mutex tomoyo_policy_lock; +static inline void tomoyo_put_name(const struct tomoyo_path_info *name) +{ + if (name) { + struct tomoyo_name_entry *ptr = + container_of(name, struct tomoyo_name_entry, entry); + atomic_dec(&ptr->users); + } +} -/* Has /sbin/init started? */ -extern bool tomoyo_policy_loaded; +static inline struct tomoyo_domain_info *tomoyo_domain(void) +{ + return current_cred()->security; +} -/* The kernel's domain. */ -extern struct tomoyo_domain_info tomoyo_kernel_domain; +static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct + *task) +{ + return task_cred_xxx(task, security); +} /** * list_for_each_cookie - iterate over a list with cookie. @@ -428,16 +731,4 @@ extern struct tomoyo_domain_info tomoyo_kernel_domain; prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ (cookie) = pos, pos = rcu_dereference(pos->next)) -extern struct srcu_struct tomoyo_ss; - -static inline int tomoyo_read_lock(void) -{ - return srcu_read_lock(&tomoyo_ss); -} - -static inline void tomoyo_read_unlock(int idx) -{ - srcu_read_unlock(&tomoyo_ss, idx); -} - #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 0b8262567809..d60b8a61b0c8 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -10,8 +10,6 @@ */ #include "common.h" -#include "tomoyo.h" -#include "realpath.h" #include /* Variables definitions.*/ @@ -59,76 +57,6 @@ struct tomoyo_domain_info tomoyo_kernel_domain; */ LIST_HEAD(tomoyo_domain_list); -/* - * tomoyo_domain_initializer_entry is a structure which is used for holding - * "initialize_domain" and "no_initialize_domain" entries. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_domain_initializer_list . - * (2) "domainname" which is "a domainname" or "the last component of a - * domainname". This field is NULL if "from" clause is not specified. - * (3) "program" which is a program's pathname. - * (4) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - * (5) "is_not" is a bool which is true if "no_initialize_domain", false - * otherwise. - * (6) "is_last_name" is a bool which is true if "domainname" is "the last - * component of a domainname", false otherwise. - */ -struct tomoyo_domain_initializer_entry { - struct list_head list; - const struct tomoyo_path_info *domainname; /* This may be NULL */ - const struct tomoyo_path_info *program; - bool is_deleted; - bool is_not; /* True if this entry is "no_initialize_domain". */ - /* True if the domainname is tomoyo_get_last_name(). */ - bool is_last_name; -}; - -/* - * tomoyo_domain_keeper_entry is a structure which is used for holding - * "keep_domain" and "no_keep_domain" entries. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_domain_keeper_list . - * (2) "domainname" which is "a domainname" or "the last component of a - * domainname". - * (3) "program" which is a program's pathname. - * This field is NULL if "from" clause is not specified. - * (4) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - * (5) "is_not" is a bool which is true if "no_initialize_domain", false - * otherwise. - * (6) "is_last_name" is a bool which is true if "domainname" is "the last - * component of a domainname", false otherwise. - */ -struct tomoyo_domain_keeper_entry { - struct list_head list; - const struct tomoyo_path_info *domainname; - const struct tomoyo_path_info *program; /* This may be NULL */ - bool is_deleted; - bool is_not; /* True if this entry is "no_keep_domain". */ - /* True if the domainname is tomoyo_get_last_name(). */ - bool is_last_name; -}; - -/* - * tomoyo_alias_entry is a structure which is used for holding "alias" entries. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_alias_list . - * (2) "original_name" which is a dereferenced pathname. - * (3) "aliased_name" which is a symlink's pathname. - * (4) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - */ -struct tomoyo_alias_entry { - struct list_head list; - const struct tomoyo_path_info *original_name; - const struct tomoyo_path_info *aliased_name; - bool is_deleted; -}; - /** * tomoyo_get_last_name - Get last component of a domainname. * diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index a49e18cc7bc2..c69dd39e6042 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -10,58 +10,6 @@ */ #include "common.h" -#include "tomoyo.h" -#include "realpath.h" - -/* - * tomoyo_globally_readable_file_entry is a structure which is used for holding - * "allow_read" entries. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_globally_readable_list . - * (2) "filename" is a pathname which is allowed to open(O_RDONLY). - * (3) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - */ -struct tomoyo_globally_readable_file_entry { - struct list_head list; - const struct tomoyo_path_info *filename; - bool is_deleted; -}; - -/* - * tomoyo_pattern_entry is a structure which is used for holding - * "tomoyo_pattern_list" entries. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_pattern_list . - * (2) "pattern" is a pathname pattern which is used for converting pathnames - * to pathname patterns during learning mode. - * (3) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - */ -struct tomoyo_pattern_entry { - struct list_head list; - const struct tomoyo_path_info *pattern; - bool is_deleted; -}; - -/* - * tomoyo_no_rewrite_entry is a structure which is used for holding - * "deny_rewrite" entries. - * It has following fields. - * - * (1) "list" which is linked to tomoyo_no_rewrite_list . - * (2) "pattern" is a pathname which is by default not permitted to modify - * already existing content. - * (3) "is_deleted" is a bool which is true if marked as deleted, false - * otherwise. - */ -struct tomoyo_no_rewrite_entry { - struct list_head list; - const struct tomoyo_path_info *pattern; - bool is_deleted; -}; /* Keyword array for single path operations. */ static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = { diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 2f7f54fc6812..9557168b3767 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -15,9 +15,7 @@ #include #include #include - #include "common.h" -#include "realpath.h" /** * tomoyo_encode: Convert binary string to ascii string. @@ -245,14 +243,6 @@ static unsigned int tomoyo_allocated_memory_for_savename; /* Quota for holding string data in bytes. */ static unsigned int tomoyo_quota_for_savename; -/* - * TOMOYO uses this hash only when appending a string into the string - * table. Frequency of appending strings is very low. So we don't need - * large (e.g. 64k) hash size. 256 will be sufficient. - */ -#define TOMOYO_HASH_BITS 8 -#define TOMOYO_MAX_HASH (1u<users); - } -} - -#endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */ diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 714daa34d493..8a0988dade79 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -11,8 +11,6 @@ #include #include "common.h" -#include "tomoyo.h" -#include "realpath.h" static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) { diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h deleted file mode 100644 index bf3986addc1a..000000000000 --- a/security/tomoyo/tomoyo.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * security/tomoyo/tomoyo.h - * - * Implementation of the Domain-Based Mandatory Access Control. - * - * Copyright (C) 2005-2009 NTT DATA CORPORATION - * - * Version: 2.2.0 2009/04/01 - * - */ - -#ifndef _SECURITY_TOMOYO_TOMOYO_H -#define _SECURITY_TOMOYO_TOMOYO_H - -struct tomoyo_path_info; -struct path; -struct inode; -struct linux_binprm; -struct pt_regs; - -int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, - const struct tomoyo_path_info *filename); -int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, - struct path *path, const int flag); -int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, - const u8 operation, struct path *path); -int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain, - const u8 operation, struct path *path1, - struct path *path2); -int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, - struct file *filp); -int tomoyo_find_next_domain(struct linux_binprm *bprm); - -/* Index numbers for Access Controls. */ - -#define TOMOYO_TYPE_SINGLE_PATH_ACL 0 -#define TOMOYO_TYPE_DOUBLE_PATH_ACL 1 - -/* Index numbers for File Controls. */ - -/* - * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set - * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and - * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set. - * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or - * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are - * automatically cleared if TYPE_READ_WRITE_ACL is cleared. - */ - -#define TOMOYO_TYPE_READ_WRITE_ACL 0 -#define TOMOYO_TYPE_EXECUTE_ACL 1 -#define TOMOYO_TYPE_READ_ACL 2 -#define TOMOYO_TYPE_WRITE_ACL 3 -#define TOMOYO_TYPE_CREATE_ACL 4 -#define TOMOYO_TYPE_UNLINK_ACL 5 -#define TOMOYO_TYPE_MKDIR_ACL 6 -#define TOMOYO_TYPE_RMDIR_ACL 7 -#define TOMOYO_TYPE_MKFIFO_ACL 8 -#define TOMOYO_TYPE_MKSOCK_ACL 9 -#define TOMOYO_TYPE_MKBLOCK_ACL 10 -#define TOMOYO_TYPE_MKCHAR_ACL 11 -#define TOMOYO_TYPE_TRUNCATE_ACL 12 -#define TOMOYO_TYPE_SYMLINK_ACL 13 -#define TOMOYO_TYPE_REWRITE_ACL 14 -#define TOMOYO_TYPE_IOCTL_ACL 15 -#define TOMOYO_TYPE_CHMOD_ACL 16 -#define TOMOYO_TYPE_CHOWN_ACL 17 -#define TOMOYO_TYPE_CHGRP_ACL 18 -#define TOMOYO_TYPE_CHROOT_ACL 19 -#define TOMOYO_TYPE_MOUNT_ACL 20 -#define TOMOYO_TYPE_UMOUNT_ACL 21 -#define TOMOYO_MAX_SINGLE_PATH_OPERATION 22 - -#define TOMOYO_TYPE_LINK_ACL 0 -#define TOMOYO_TYPE_RENAME_ACL 1 -#define TOMOYO_TYPE_PIVOT_ROOT_ACL 2 -#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 3 - -#define TOMOYO_DOMAINPOLICY 0 -#define TOMOYO_EXCEPTIONPOLICY 1 -#define TOMOYO_DOMAIN_STATUS 2 -#define TOMOYO_PROCESS_STATUS 3 -#define TOMOYO_MEMINFO 4 -#define TOMOYO_SELFDOMAIN 5 -#define TOMOYO_VERSION 6 -#define TOMOYO_PROFILE 7 -#define TOMOYO_MANAGER 8 - -extern struct tomoyo_domain_info tomoyo_kernel_domain; - -static inline struct tomoyo_domain_info *tomoyo_domain(void) -{ - return current_cred()->security; -} - -static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct - *task) -{ - return task_cred_xxx(task, security); -} - -#endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */ -- cgit v1.2.3-59-g8ed1b From ec8e6a4e062e2edebef91e930c20572c9f4c0dda Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 11 Feb 2010 09:43:20 +0900 Subject: TOMOYO: Add refcounter on domain structure. Add refcounter to "struct tomoyo_domain_info" since garbage collector needs to determine whether this struct is referred by "struct cred"->security or not. Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/common.h | 5 +++++ security/tomoyo/domain.c | 2 ++ security/tomoyo/tomoyo.c | 37 +++++++++++++++++++++---------------- 3 files changed, 28 insertions(+), 16 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f6aff59b0885..521b4b5addaf 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -234,6 +234,10 @@ struct tomoyo_acl_info { * name of the domain to be created was too long or it could not allocate * memory. If set to true, more than one process continued execve() * without domain transition. + * (9) "users" is an atomic_t that holds how many "struct cred"->security + * are referring this "struct tomoyo_domain_info". If is_deleted == true + * and users == 0, this struct will be kfree()d upon next garbage + * collection. * * A domain's lifecycle is an analogy of files on / directory. * Multiple domains with the same domainname cannot be created (as with @@ -252,6 +256,7 @@ struct tomoyo_domain_info { bool quota_warned; /* Quota warnning flag. */ bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ bool transition_failed; /* Domain transition failed flag. */ + atomic_t users; /* Number of referring credentials. */ }; /* diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index d60b8a61b0c8..6f74b30d6bb1 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -817,6 +817,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) out: if (!domain) domain = old_domain; + /* Update reference count on "struct tomoyo_domain_info". */ + atomic_inc(&domain->users); bprm->cred->security = domain; kfree(real_program_name); kfree(symlink_program_name); diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 8a0988dade79..87e82bfeac2f 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -21,21 +21,23 @@ static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) { - /* - * Since "struct tomoyo_domain_info *" is a sharable pointer, - * we don't need to duplicate. - */ - new->security = old->security; + struct tomoyo_domain_info *domain = old->security; + new->security = domain; + if (domain) + atomic_inc(&domain->users); return 0; } static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) { - /* - * Since "struct tomoyo_domain_info *" is a sharable pointer, - * we don't need to duplicate. - */ - new->security = old->security; + tomoyo_cred_prepare(new, old, 0); +} + +static void tomoyo_cred_free(struct cred *cred) +{ + struct tomoyo_domain_info *domain = cred->security; + if (domain) + atomic_dec(&domain->users); } static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) @@ -58,6 +60,14 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) */ if (!tomoyo_policy_loaded) tomoyo_load_policy(bprm->filename); + /* + * Release reference to "struct tomoyo_domain_info" stored inside + * "bprm->cred->security". New reference to "struct tomoyo_domain_info" + * stored inside "bprm->cred->security" will be acquired later inside + * tomoyo_find_next_domain(). + */ + atomic_dec(&((struct tomoyo_domain_info *) + bprm->cred->security)->users); /* * Tell tomoyo_bprm_check_security() is called for the first time of an * execve operation. @@ -75,12 +85,6 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) * using current domain. */ if (!domain) { - /* - * We will need to protect whole execve() operation when GC - * starts kfree()ing "struct tomoyo_domain_info" because - * bprm->cred->security points to "struct tomoyo_domain_info" - * but "struct tomoyo_domain_info" does not have a refcounter. - */ const int idx = tomoyo_read_lock(); const int err = tomoyo_find_next_domain(bprm); tomoyo_read_unlock(idx); @@ -265,6 +269,7 @@ static struct security_operations tomoyo_security_ops = { .cred_alloc_blank = tomoyo_cred_alloc_blank, .cred_prepare = tomoyo_cred_prepare, .cred_transfer = tomoyo_cred_transfer, + .cred_free = tomoyo_cred_free, .bprm_set_creds = tomoyo_bprm_set_creds, .bprm_check_security = tomoyo_bprm_check_security, .file_fcntl = tomoyo_file_fcntl, -- cgit v1.2.3-59-g8ed1b From 847b173ea3d6f50936823d07f2245059bf44713b Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 11 Feb 2010 09:43:54 +0900 Subject: TOMOYO: Add garbage collector. This patch adds garbage collector support to TOMOYO. Elements are protected by "struct srcu_struct tomoyo_ss". Signed-off-by: Tetsuo Handa Acked-by: Serge Hallyn Signed-off-by: James Morris --- security/tomoyo/Makefile | 2 +- security/tomoyo/common.c | 5 +- security/tomoyo/common.h | 15 ++ security/tomoyo/domain.c | 6 +- security/tomoyo/file.c | 6 +- security/tomoyo/gc.c | 370 +++++++++++++++++++++++++++++++++++++++++++++ security/tomoyo/realpath.c | 86 +++++------ 7 files changed, 436 insertions(+), 54 deletions(-) create mode 100644 security/tomoyo/gc.c (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 10ccd686b290..60a9e2002da1 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile @@ -1 +1 @@ -obj-y = common.o realpath.o tomoyo.o domain.o file.o +obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 634f7449e8ba..3a36b56a2f5c 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1067,7 +1067,7 @@ static int tomoyo_read_profile(struct tomoyo_io_buffer *head) * * # cat /sys/kernel/security/tomoyo/manager */ -static LIST_HEAD(tomoyo_policy_manager_list); +LIST_HEAD(tomoyo_policy_manager_list); /** * tomoyo_update_manager_entry - Add a manager entry. @@ -2109,6 +2109,7 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer, static int tomoyo_close_control(struct file *file) { struct tomoyo_io_buffer *head = file->private_data; + const bool is_write = !!head->write_buf; tomoyo_read_unlock(head->reader_idx); /* Release memory used for policy I/O. */ @@ -2119,6 +2120,8 @@ static int tomoyo_close_control(struct file *file) kfree(head); head = NULL; file->private_data = NULL; + if (is_write) + tomoyo_run_gc(); return 0; } diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 521b4b5addaf..1c8c97a4c069 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -638,6 +638,11 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, struct file *filp); int tomoyo_find_next_domain(struct linux_binprm *bprm); +/* Run garbage collector. */ +void tomoyo_run_gc(void); + +void tomoyo_memory_free(void *ptr); + /********** External variable definitions. **********/ /* Lock for GC. */ @@ -646,6 +651,16 @@ extern struct srcu_struct tomoyo_ss; /* The list for "struct tomoyo_domain_info". */ extern struct list_head tomoyo_domain_list; +extern struct list_head tomoyo_domain_initializer_list; +extern struct list_head tomoyo_domain_keeper_list; +extern struct list_head tomoyo_alias_list; +extern struct list_head tomoyo_globally_readable_list; +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_name_list[TOMOYO_MAX_HASH]; +extern struct mutex tomoyo_name_list_lock; + /* Lock for protecting policy. */ extern struct mutex tomoyo_policy_lock; diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 6f74b30d6bb1..74cd0f52e3a8 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -110,7 +110,7 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) * will cause "/usr/sbin/httpd" to belong to " /usr/sbin/httpd" domain * unless executed from " /etc/rc.d/init.d/httpd" domain. */ -static LIST_HEAD(tomoyo_domain_initializer_list); +LIST_HEAD(tomoyo_domain_initializer_list); /** * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. @@ -330,7 +330,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * * " /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless * explicitly specified by "initialize_domain". */ -static LIST_HEAD(tomoyo_domain_keeper_list); +LIST_HEAD(tomoyo_domain_keeper_list); /** * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. @@ -533,7 +533,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, * /bin/busybox and domainname which the current process will belong to after * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . */ -static LIST_HEAD(tomoyo_alias_list); +LIST_HEAD(tomoyo_alias_list); /** * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index c69dd39e6042..10ee7cece080 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -148,7 +148,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, * given "allow_read /lib/libc-2.5.so" to the domain which current process * belongs to. */ -static LIST_HEAD(tomoyo_globally_readable_list); +LIST_HEAD(tomoyo_globally_readable_list); /** * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. @@ -295,7 +295,7 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) * which pretends as if /proc/self/ is not a symlink; so that we can forbid * current process from accessing other process's information. */ -static LIST_HEAD(tomoyo_pattern_list); +LIST_HEAD(tomoyo_pattern_list); /** * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. @@ -448,7 +448,7 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) * " (deleted)" suffix if the file is already unlink()ed; so that we don't * need to worry whether the file is already unlink()ed or not. */ -static LIST_HEAD(tomoyo_no_rewrite_list); +LIST_HEAD(tomoyo_no_rewrite_list); /** * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c new file mode 100644 index 000000000000..ee15da39387d --- /dev/null +++ b/security/tomoyo/gc.c @@ -0,0 +1,370 @@ +/* + * security/tomoyo/gc.c + * + * Implementation of the Domain-Based Mandatory Access Control. + * + * Copyright (C) 2005-2010 NTT DATA CORPORATION + * + */ + +#include "common.h" +#include + +enum tomoyo_gc_id { + TOMOYO_ID_DOMAIN_INITIALIZER, + TOMOYO_ID_DOMAIN_KEEPER, + TOMOYO_ID_ALIAS, + TOMOYO_ID_GLOBALLY_READABLE, + TOMOYO_ID_PATTERN, + TOMOYO_ID_NO_REWRITE, + TOMOYO_ID_MANAGER, + TOMOYO_ID_NAME, + TOMOYO_ID_ACL, + TOMOYO_ID_DOMAIN +}; + +struct tomoyo_gc_entry { + struct list_head list; + int type; + void *element; +}; +static LIST_HEAD(tomoyo_gc_queue); +static DEFINE_MUTEX(tomoyo_gc_mutex); + +/* Caller holds tomoyo_policy_lock mutex. */ +static bool tomoyo_add_to_gc(const int type, void *element) +{ + struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); + if (!entry) + return false; + entry->type = type; + entry->element = element; + list_add(&entry->list, &tomoyo_gc_queue); + return true; +} + +static void tomoyo_del_allow_read +(struct tomoyo_globally_readable_file_entry *ptr) +{ + tomoyo_put_name(ptr->filename); +} + +static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr) +{ + tomoyo_put_name(ptr->pattern); +} + +static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr) +{ + tomoyo_put_name(ptr->pattern); +} + +static void tomoyo_del_domain_initializer +(struct tomoyo_domain_initializer_entry *ptr) +{ + tomoyo_put_name(ptr->domainname); + tomoyo_put_name(ptr->program); +} + +static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr) +{ + tomoyo_put_name(ptr->domainname); + tomoyo_put_name(ptr->program); +} + +static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr) +{ + tomoyo_put_name(ptr->original_name); + tomoyo_put_name(ptr->aliased_name); +} + +static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr) +{ + tomoyo_put_name(ptr->manager); +} + +static void tomoyo_del_acl(struct tomoyo_acl_info *acl) +{ + switch (acl->type) { + case TOMOYO_TYPE_SINGLE_PATH_ACL: + { + struct tomoyo_single_path_acl_record *entry + = container_of(acl, typeof(*entry), head); + tomoyo_put_name(entry->filename); + } + break; + case TOMOYO_TYPE_DOUBLE_PATH_ACL: + { + struct tomoyo_double_path_acl_record *entry + = container_of(acl, typeof(*entry), head); + tomoyo_put_name(entry->filename1); + tomoyo_put_name(entry->filename2); + } + break; + default: + printk(KERN_WARNING "Unknown type\n"); + break; + } +} + +static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) +{ + struct tomoyo_acl_info *acl; + struct tomoyo_acl_info *tmp; + /* + * Since we don't protect whole execve() operation using SRCU, + * we need to recheck domain->users at this point. + * + * (1) Reader starts SRCU section upon execve(). + * (2) Reader traverses tomoyo_domain_list and finds this domain. + * (3) Writer marks this domain as deleted. + * (4) Garbage collector removes this domain from tomoyo_domain_list + * because this domain is marked as deleted and used by nobody. + * (5) Reader saves reference to this domain into + * "struct linux_binprm"->cred->security . + * (6) Reader finishes SRCU section, although execve() operation has + * not finished yet. + * (7) Garbage collector waits for SRCU synchronization. + * (8) Garbage collector kfree() this domain because this domain is + * used by nobody. + * (9) Reader finishes execve() operation and restores this domain from + * "struct linux_binprm"->cred->security. + * + * By updating domain->users at (5), we can solve this race problem + * by rechecking domain->users at (8). + */ + if (atomic_read(&domain->users)) + return false; + list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { + tomoyo_del_acl(acl); + tomoyo_memory_free(acl); + } + tomoyo_put_name(domain->domainname); + return true; +} + + +static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) +{ +} + +static void tomoyo_collect_entry(void) +{ + mutex_lock(&tomoyo_policy_lock); + { + struct tomoyo_globally_readable_file_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, + list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_pattern_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_no_rewrite_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_domain_initializer_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, + list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_domain_keeper_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_alias_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_policy_manager_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, + list) { + if (!ptr->is_deleted) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { + struct tomoyo_domain_info *domain; + list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { + struct tomoyo_acl_info *acl; + list_for_each_entry_rcu(acl, &domain->acl_info_list, + list) { + switch (acl->type) { + case TOMOYO_TYPE_SINGLE_PATH_ACL: + if (container_of(acl, + struct tomoyo_single_path_acl_record, + head)->perm || + container_of(acl, + struct tomoyo_single_path_acl_record, + head)->perm_high) + continue; + break; + case TOMOYO_TYPE_DOUBLE_PATH_ACL: + if (container_of(acl, + struct tomoyo_double_path_acl_record, + head)->perm) + continue; + break; + default: + continue; + } + if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl)) + list_del_rcu(&acl->list); + else + break; + } + if (!domain->is_deleted || atomic_read(&domain->users)) + continue; + /* + * Nobody is referring this domain. But somebody may + * refer this domain after successful execve(). + * We recheck domain->users after SRCU synchronization. + */ + if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain)) + list_del_rcu(&domain->list); + else + break; + } + } + mutex_unlock(&tomoyo_policy_lock); + mutex_lock(&tomoyo_name_list_lock); + { + int i; + for (i = 0; i < TOMOYO_MAX_HASH; i++) { + struct tomoyo_name_entry *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], + list) { + if (atomic_read(&ptr->users)) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr)) + list_del_rcu(&ptr->list); + else { + i = TOMOYO_MAX_HASH; + break; + } + } + } + } + mutex_unlock(&tomoyo_name_list_lock); +} + +static void tomoyo_kfree_entry(void) +{ + struct tomoyo_gc_entry *p; + struct tomoyo_gc_entry *tmp; + + list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { + switch (p->type) { + case TOMOYO_ID_DOMAIN_INITIALIZER: + tomoyo_del_domain_initializer(p->element); + break; + case TOMOYO_ID_DOMAIN_KEEPER: + tomoyo_del_domain_keeper(p->element); + break; + case TOMOYO_ID_ALIAS: + tomoyo_del_alias(p->element); + break; + case TOMOYO_ID_GLOBALLY_READABLE: + tomoyo_del_allow_read(p->element); + break; + case TOMOYO_ID_PATTERN: + tomoyo_del_file_pattern(p->element); + break; + case TOMOYO_ID_NO_REWRITE: + tomoyo_del_no_rewrite(p->element); + break; + case TOMOYO_ID_MANAGER: + tomoyo_del_manager(p->element); + break; + case TOMOYO_ID_NAME: + tomoyo_del_name(p->element); + break; + case TOMOYO_ID_ACL: + tomoyo_del_acl(p->element); + break; + case TOMOYO_ID_DOMAIN: + if (!tomoyo_del_domain(p->element)) + continue; + break; + default: + printk(KERN_WARNING "Unknown type\n"); + break; + } + tomoyo_memory_free(p->element); + list_del(&p->list); + kfree(p); + } +} + +static int tomoyo_gc_thread(void *unused) +{ + daemonize("GC for TOMOYO"); + if (mutex_trylock(&tomoyo_gc_mutex)) { + int i; + for (i = 0; i < 10; i++) { + tomoyo_collect_entry(); + if (list_empty(&tomoyo_gc_queue)) + break; + synchronize_srcu(&tomoyo_ss); + tomoyo_kfree_entry(); + } + mutex_unlock(&tomoyo_gc_mutex); + } + do_exit(0); +} + +void tomoyo_run_gc(void) +{ + struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL, + "GC for TOMOYO"); + if (!IS_ERR(task)) + wake_up_process(task); +} diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 9557168b3767..c00df45c7ede 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -205,9 +205,9 @@ char *tomoyo_realpath_nofollow(const char *pathname) } /* Memory allocated for non-string data. */ -static unsigned int tomoyo_allocated_memory_for_elements; -/* Quota for holding non-string data. */ -static unsigned int tomoyo_quota_for_elements; +static atomic_t tomoyo_policy_memory_size; +/* Quota for holding policy. */ +static unsigned int tomoyo_quota_for_policy; /** * tomoyo_memory_ok - Check memory quota. @@ -222,26 +222,30 @@ static unsigned int tomoyo_quota_for_elements; bool tomoyo_memory_ok(void *ptr) { int allocated_len = ptr ? ksize(ptr) : 0; - bool result = false; - if (!ptr || (tomoyo_quota_for_elements && - tomoyo_allocated_memory_for_elements - + allocated_len > tomoyo_quota_for_elements)) { - printk(KERN_WARNING "ERROR: Out of memory " - "for tomoyo_alloc_element().\n"); - if (!tomoyo_policy_loaded) - panic("MAC Initialization failed.\n"); - } else { - result = true; - tomoyo_allocated_memory_for_elements += allocated_len; + atomic_add(allocated_len, &tomoyo_policy_memory_size); + if (ptr && (!tomoyo_quota_for_policy || + atomic_read(&tomoyo_policy_memory_size) + <= tomoyo_quota_for_policy)) { memset(ptr, 0, allocated_len); + return true; } - return result; + printk(KERN_WARNING "ERROR: Out of memory " + "for tomoyo_alloc_element().\n"); + if (!tomoyo_policy_loaded) + panic("MAC Initialization failed.\n"); + return false; } -/* Memory allocated for string data in bytes. */ -static unsigned int tomoyo_allocated_memory_for_savename; -/* Quota for holding string data in bytes. */ -static unsigned int tomoyo_quota_for_savename; +/** + * tomoyo_memory_free - Free memory for elements. + * + * @ptr: Pointer to allocated memory. + */ +void tomoyo_memory_free(void *ptr) +{ + atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); + kfree(ptr); +} /* * tomoyo_name_list is used for holding string data used by TOMOYO. @@ -249,7 +253,9 @@ static unsigned int tomoyo_quota_for_savename; * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of * "const struct tomoyo_path_info *". */ -static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; +struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; +/* Lock for protecting tomoyo_name_list . */ +DEFINE_MUTEX(tomoyo_name_list_lock); /** * tomoyo_get_name - Allocate permanent memory for string data. @@ -260,7 +266,6 @@ static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; */ const struct tomoyo_path_info *tomoyo_get_name(const char *name) { - static DEFINE_MUTEX(lock); struct tomoyo_name_entry *ptr; unsigned int hash; int len; @@ -272,7 +277,7 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) len = strlen(name) + 1; hash = full_name_hash((const unsigned char *) name, len - 1); head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; - mutex_lock(&lock); + mutex_lock(&tomoyo_name_list_lock); list_for_each_entry(ptr, head, list) { if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) continue; @@ -281,9 +286,9 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) } ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); allocated_len = ptr ? ksize(ptr) : 0; - if (!ptr || (tomoyo_quota_for_savename && - tomoyo_allocated_memory_for_savename + allocated_len - > tomoyo_quota_for_savename)) { + if (!ptr || (tomoyo_quota_for_policy && + atomic_read(&tomoyo_policy_memory_size) + allocated_len + > tomoyo_quota_for_policy)) { kfree(ptr); printk(KERN_WARNING "ERROR: Out of memory " "for tomoyo_get_name().\n"); @@ -292,14 +297,14 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) ptr = NULL; goto out; } - tomoyo_allocated_memory_for_savename += allocated_len; + atomic_add(allocated_len, &tomoyo_policy_memory_size); ptr->entry.name = ((char *) ptr) + sizeof(*ptr); memmove((char *) ptr->entry.name, name, len); atomic_set(&ptr->users, 1); tomoyo_fill_path_info(&ptr->entry); list_add_tail(&ptr->list, head); out: - mutex_unlock(&lock); + mutex_unlock(&tomoyo_name_list_lock); return ptr ? &ptr->entry : NULL; } @@ -334,28 +339,19 @@ void __init tomoyo_realpath_init(void) int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) { if (!head->read_eof) { - const unsigned int shared - = tomoyo_allocated_memory_for_savename; - const unsigned int private - = tomoyo_allocated_memory_for_elements; + const unsigned int policy + = atomic_read(&tomoyo_policy_memory_size); char buffer[64]; memset(buffer, 0, sizeof(buffer)); - if (tomoyo_quota_for_savename) - snprintf(buffer, sizeof(buffer) - 1, - " (Quota: %10u)", - tomoyo_quota_for_savename); - else - buffer[0] = '\0'; - tomoyo_io_printf(head, "Shared: %10u%s\n", shared, buffer); - if (tomoyo_quota_for_elements) + if (tomoyo_quota_for_policy) snprintf(buffer, sizeof(buffer) - 1, " (Quota: %10u)", - tomoyo_quota_for_elements); + tomoyo_quota_for_policy); else buffer[0] = '\0'; - tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer); - tomoyo_io_printf(head, "Total: %10u\n", shared + private); + tomoyo_io_printf(head, "Policy: %10u%s\n", policy, buffer); + tomoyo_io_printf(head, "Total: %10u\n", policy); head->read_eof = true; } return 0; @@ -373,9 +369,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) char *data = head->write_buf; unsigned int size; - if (sscanf(data, "Shared: %u", &size) == 1) - tomoyo_quota_for_savename = size; - else if (sscanf(data, "Private: %u", &size) == 1) - tomoyo_quota_for_elements = size; + if (sscanf(data, "Policy: %u", &size) == 1) + tomoyo_quota_for_policy = size; return 0; } -- cgit v1.2.3-59-g8ed1b From 170800088666963de1111d62fb503889c8c82eda Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Tue, 16 Feb 2010 21:14:48 +0900 Subject: TOMOYO: Remove __func__ from tomoyo_is_correct_path/domain __func__ is used for only debug printk(). We can remove it. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 18 ++++-------------- security/tomoyo/common.h | 6 ++---- security/tomoyo/domain.c | 18 +++++++++--------- security/tomoyo/file.c | 10 +++++----- 4 files changed, 20 insertions(+), 32 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ffcf02450560..30dd1c68a647 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -179,14 +179,12 @@ static void tomoyo_normalize_line(unsigned char *buffer) * 1 = must / -1 = must not / 0 = don't care * @end_type: Should the pathname end with '/'? * 1 = must / -1 = must not / 0 = don't care - * @function: The name of function calling me. * * Check whether the given filename follows the naming rules. * Returns true if @filename follows the naming rules, false otherwise. */ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, - const s8 pattern_type, const s8 end_type, - const char *function) + const s8 pattern_type, const s8 end_type) { const char *const start = filename; bool in_repetition = false; @@ -194,7 +192,6 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, unsigned char c; unsigned char d; unsigned char e; - const char *original_filename = filename; if (!filename) goto out; @@ -283,25 +280,20 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, goto out; return true; out: - printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function, - original_filename); return false; } /** * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. * @domainname: The domainname to check. - * @function: The name of function calling me. * * Returns true if @domainname follows the naming rules, false otherwise. */ -bool tomoyo_is_correct_domain(const unsigned char *domainname, - const char *function) +bool tomoyo_is_correct_domain(const unsigned char *domainname) { unsigned char c; unsigned char d; unsigned char e; - const char *org_domainname = domainname; if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN)) @@ -344,8 +336,6 @@ bool tomoyo_is_correct_domain(const unsigned char *domainname, } while (*domainname); return true; out: - printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function, - org_domainname); return false; } @@ -1086,11 +1076,11 @@ static int tomoyo_update_manager_entry(const char *manager, bool is_domain = false; if (tomoyo_is_domain_def(manager)) { - if (!tomoyo_is_correct_domain(manager, __func__)) + if (!tomoyo_is_correct_domain(manager)) return -EINVAL; is_domain = true; } else { - if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__)) + if (!tomoyo_is_correct_path(manager, 1, -1, -1)) return -EINVAL; } saved_manager = tomoyo_get_name(manager); diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 17ed365521b1..67bd22dd3e68 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -520,12 +520,10 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); /* Check whether the domainname is correct. */ -bool tomoyo_is_correct_domain(const unsigned char *domainname, - const char *function); +bool tomoyo_is_correct_domain(const unsigned char *domainname); /* Check whether the token is correct. */ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, - const s8 pattern_type, const s8 end_type, - const char *function); + const s8 pattern_type, const s8 end_type); /* Check whether the token can be a domainname. */ bool tomoyo_is_domain_def(const unsigned char *buffer); /* Check whether the given filename matches the given pattern. */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 74cd0f52e3a8..66caaa1b842a 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -136,13 +136,13 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, int error = is_delete ? -ENOENT : -ENOMEM; bool is_last_name = false; - if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) + if (!tomoyo_is_correct_path(program, 1, -1, -1)) return -EINVAL; /* No patterns allowed. */ if (domainname) { if (!tomoyo_is_domain_def(domainname) && - tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) + tomoyo_is_correct_path(domainname, 1, -1, -1)) is_last_name = true; - else if (!tomoyo_is_correct_domain(domainname, __func__)) + else if (!tomoyo_is_correct_domain(domainname)) return -EINVAL; saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) @@ -357,12 +357,12 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, bool is_last_name = false; if (!tomoyo_is_domain_def(domainname) && - tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) + tomoyo_is_correct_path(domainname, 1, -1, -1)) is_last_name = true; - else if (!tomoyo_is_correct_domain(domainname, __func__)) + else if (!tomoyo_is_correct_domain(domainname)) return -EINVAL; if (program) { - if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) + if (!tomoyo_is_correct_path(program, 1, -1, -1)) return -EINVAL; saved_program = tomoyo_get_name(program); if (!saved_program) @@ -556,8 +556,8 @@ static int tomoyo_update_alias_entry(const char *original_name, const struct tomoyo_path_info *saved_aliased_name; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || - !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) + if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || + !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) return -EINVAL; /* No patterns allowed. */ saved_original_name = tomoyo_get_name(original_name); saved_aliased_name = tomoyo_get_name(aliased_name); @@ -659,7 +659,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * const struct tomoyo_path_info *saved_domainname; bool found = false; - if (!tomoyo_is_correct_domain(domainname, __func__)) + if (!tomoyo_is_correct_domain(domainname)) return NULL; saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index db342ef87af7..1b24304edb7d 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -168,7 +168,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, const struct tomoyo_path_info *saved_filename; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) + if (!tomoyo_is_correct_path(filename, 1, 0, -1)) return -EINVAL; saved_filename = tomoyo_get_name(filename); if (!saved_filename) @@ -468,7 +468,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, const struct tomoyo_path_info *saved_pattern; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) + if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) return -EINVAL; saved_pattern = tomoyo_get_name(pattern); if (!saved_pattern) @@ -814,7 +814,7 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, if (!domain) return -EINVAL; - if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__)) + if (!tomoyo_is_correct_path(filename, 0, 0, 0)) return -EINVAL; saved_filename = tomoyo_get_name(filename); if (!saved_filename) @@ -898,8 +898,8 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, if (!domain) return -EINVAL; - if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) || - !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__)) + if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || + !tomoyo_is_correct_path(filename2, 0, 0, 0)) return -EINVAL; saved_filename1 = tomoyo_get_name(filename1); saved_filename2 = tomoyo_get_name(filename2); -- cgit v1.2.3-59-g8ed1b