diff options
-rw-r--r-- | security/tomoyo/gc.c | 212 |
1 files changed, 66 insertions, 146 deletions
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 2dd9665af26..4290e519eaa 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -11,7 +11,7 @@ #include <linux/kthread.h> #include <linux/slab.h> -enum tomoyo_gc_id { +enum tomoyo_policy_id { TOMOYO_ID_PATH_GROUP, TOMOYO_ID_PATH_GROUP_MEMBER, TOMOYO_ID_NUMBER_GROUP, @@ -26,7 +26,8 @@ enum tomoyo_gc_id { TOMOYO_ID_MANAGER, TOMOYO_ID_NAME, TOMOYO_ID_ACL, - TOMOYO_ID_DOMAIN + TOMOYO_ID_DOMAIN, + TOMOYO_MAX_POLICY }; struct tomoyo_gc_entry { @@ -209,117 +210,58 @@ static void tomoyo_del_number_group(struct tomoyo_number_group *group) tomoyo_put_name(group->group_name); } +static struct list_head *tomoyo_policy_list[TOMOYO_MAX_POLICY] = { + [TOMOYO_ID_GLOBALLY_READABLE] = &tomoyo_globally_readable_list, + [TOMOYO_ID_PATTERN] = &tomoyo_pattern_list, + [TOMOYO_ID_NO_REWRITE] = &tomoyo_no_rewrite_list, + [TOMOYO_ID_DOMAIN_INITIALIZER] = &tomoyo_domain_initializer_list, + [TOMOYO_ID_DOMAIN_KEEPER] = &tomoyo_domain_keeper_list, + [TOMOYO_ID_AGGREGATOR] = &tomoyo_aggregator_list, + [TOMOYO_ID_ALIAS] = &tomoyo_alias_list, + [TOMOYO_ID_MANAGER] = &tomoyo_policy_manager_list, +}; + +static bool tomoyo_collect_member(struct list_head *member_list, int id) +{ + struct tomoyo_acl_head *member; + list_for_each_entry(member, member_list, list) { + if (!member->is_deleted) + continue; + if (!tomoyo_add_to_gc(id, &member->list)) + return false; + list_del_rcu(&member->list); + } + return true; +} + +static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain) +{ + struct tomoyo_acl_info *acl; + list_for_each_entry(acl, &domain->acl_info_list, list) { + if (!acl->is_deleted) + continue; + if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list)) + return false; + list_del_rcu(&acl->list); + } + return true; +} + static void tomoyo_collect_entry(void) { + int i; if (mutex_lock_interruptible(&tomoyo_policy_lock)) return; - { - struct tomoyo_globally_readable_file_entry *ptr; - list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, - head.list) { - if (!ptr->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr)) - list_del_rcu(&ptr->head.list); - else - break; - } - } - { - struct tomoyo_pattern_entry *ptr; - list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, head.list) { - if (!ptr->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr)) - list_del_rcu(&ptr->head.list); - else - break; - } - } - { - struct tomoyo_no_rewrite_entry *ptr; - list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, - head.list) { - if (!ptr->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr)) - list_del_rcu(&ptr->head.list); - else - break; - } - } - { - struct tomoyo_domain_initializer_entry *ptr; - list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, - head.list) { - if (!ptr->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr)) - list_del_rcu(&ptr->head.list); - else - break; - } - } - { - struct tomoyo_domain_keeper_entry *ptr; - list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, - head.list) { - if (!ptr->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr)) - list_del_rcu(&ptr->head.list); - else - break; - } - } - { - struct tomoyo_aggregator_entry *ptr; - list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list, - head.list) { - if (!ptr->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_AGGREGATOR, ptr)) - list_del_rcu(&ptr->head.list); - else - break; - } - } - { - struct tomoyo_alias_entry *ptr; - list_for_each_entry_rcu(ptr, &tomoyo_alias_list, head.list) { - if (!ptr->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr)) - list_del_rcu(&ptr->head.list); - else - break; - } - } - { - struct tomoyo_policy_manager_entry *ptr; - list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, - head.list) { - if (!ptr->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr)) - list_del_rcu(&ptr->head.list); - else - break; - } + for (i = 0; i < TOMOYO_MAX_POLICY; i++) { + if (tomoyo_policy_list[i]) + if (!tomoyo_collect_member(tomoyo_policy_list[i], i)) + goto unlock; } { 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) { - if (!acl->is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl)) - list_del_rcu(&acl->list); - else - break; - } + if (!tomoyo_collect_acl(domain)) + goto unlock; if (!domain->is_deleted || atomic_read(&domain->users)) continue; /* @@ -330,72 +272,50 @@ static void tomoyo_collect_entry(void) if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain)) list_del_rcu(&domain->list); else - break; + goto unlock; } } - { - 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; - } - } + 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 + goto unlock; } } { struct tomoyo_path_group *group; list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { - struct tomoyo_path_group_member *member; - list_for_each_entry_rcu(member, &group->member_list, - head.list) { - if (!member->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER, - member)) - list_del_rcu(&member->head.list); - else - break; - } + tomoyo_collect_member(&group->member_list, + TOMOYO_ID_PATH_GROUP_MEMBER); if (!list_empty(&group->member_list) || atomic_read(&group->users)) continue; if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group)) list_del_rcu(&group->list); else - break; + goto unlock; } } { struct tomoyo_number_group *group; - list_for_each_entry_rcu(group, &tomoyo_number_group_list, list) { - struct tomoyo_number_group_member *member; - list_for_each_entry_rcu(member, &group->member_list, - head.list) { - if (!member->head.is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP_MEMBER, - member)) - list_del_rcu(&member->head.list); - else - break; - } + list_for_each_entry_rcu(group, &tomoyo_number_group_list, + list) { + tomoyo_collect_member(&group->member_list, + TOMOYO_ID_NUMBER_GROUP_MEMBER); if (!list_empty(&group->member_list) || atomic_read(&group->users)) continue; if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP, group)) list_del_rcu(&group->list); else - break; + goto unlock; } } + unlock: mutex_unlock(&tomoyo_policy_lock); } |