diff options
Diffstat (limited to 'security/tomoyo/gc.c')
-rw-r--r-- | security/tomoyo/gc.c | 360 |
1 files changed, 151 insertions, 209 deletions
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index b9cc71b04314..a877e4c3b101 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -11,83 +11,75 @@ #include <linux/kthread.h> #include <linux/slab.h> -enum tomoyo_gc_id { - TOMOYO_ID_PATH_GROUP, - TOMOYO_ID_PATH_GROUP_MEMBER, - 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 tomoyo_gc { struct list_head list; int type; - void *element; + struct list_head *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) +static bool tomoyo_add_to_gc(const int type, struct list_head *element) { - struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); + struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) return false; entry->type = type; entry->element = element; list_add(&entry->list, &tomoyo_gc_queue); + list_del_rcu(element); return true; } -static void tomoyo_del_allow_read -(struct tomoyo_globally_readable_file_entry *ptr) +static void tomoyo_del_allow_read(struct list_head *element) { + struct tomoyo_readable_file *ptr = + container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->filename); } -static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr) +static void tomoyo_del_file_pattern(struct list_head *element) { + struct tomoyo_no_pattern *ptr = + container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->pattern); } -static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr) +static void tomoyo_del_no_rewrite(struct list_head *element) { + struct tomoyo_no_rewrite *ptr = + container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->pattern); } -static void tomoyo_del_domain_initializer -(struct tomoyo_domain_initializer_entry *ptr) +static void tomoyo_del_transition_control(struct list_head *element) { + struct tomoyo_transition_control *ptr = + container_of(element, typeof(*ptr), head.list); 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) +static void tomoyo_del_aggregator(struct list_head *element) { + struct tomoyo_aggregator *ptr = + container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->original_name); - tomoyo_put_name(ptr->aliased_name); + tomoyo_put_name(ptr->aggregated_name); } -static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr) +static void tomoyo_del_manager(struct list_head *element) { + struct tomoyo_manager *ptr = + container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->manager); } -static void tomoyo_del_acl(struct tomoyo_acl_info *acl) +static void tomoyo_del_acl(struct list_head *element) { + struct tomoyo_acl_info *acl = + container_of(element, typeof(*acl), list); switch (acl->type) { case TOMOYO_TYPE_PATH_ACL: { @@ -104,14 +96,41 @@ static void tomoyo_del_acl(struct tomoyo_acl_info *acl) tomoyo_put_name_union(&entry->name2); } break; - default: - printk(KERN_WARNING "Unknown type\n"); + case TOMOYO_TYPE_PATH_NUMBER_ACL: + { + struct tomoyo_path_number_acl *entry + = container_of(acl, typeof(*entry), head); + tomoyo_put_name_union(&entry->name); + tomoyo_put_number_union(&entry->number); + } + break; + case TOMOYO_TYPE_MKDEV_ACL: + { + struct tomoyo_mkdev_acl *entry + = container_of(acl, typeof(*entry), head); + tomoyo_put_name_union(&entry->name); + tomoyo_put_number_union(&entry->mode); + tomoyo_put_number_union(&entry->major); + tomoyo_put_number_union(&entry->minor); + } + break; + case TOMOYO_TYPE_MOUNT_ACL: + { + struct tomoyo_mount_acl *entry + = container_of(acl, typeof(*entry), head); + tomoyo_put_name_union(&entry->dev_name); + tomoyo_put_name_union(&entry->dir_name); + tomoyo_put_name_union(&entry->fs_type); + tomoyo_put_number_union(&entry->flags); + } break; } } -static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) +static bool tomoyo_del_domain(struct list_head *element) { + struct tomoyo_domain_info *domain = + container_of(element, typeof(*domain), list); struct tomoyo_acl_info *acl; struct tomoyo_acl_info *tmp; /* @@ -139,7 +158,7 @@ static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) if (atomic_read(&domain->users)) return false; list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { - tomoyo_del_acl(acl); + tomoyo_del_acl(&acl->list); tomoyo_memory_free(acl); } tomoyo_put_name(domain->domainname); @@ -147,135 +166,70 @@ static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) } -static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) +static void tomoyo_del_name(struct list_head *element) { + const struct tomoyo_name *ptr = + container_of(element, typeof(*ptr), list); } -static void tomoyo_del_path_group_member(struct tomoyo_path_group_member - *member) +static void tomoyo_del_path_group(struct list_head *element) { + struct tomoyo_path_group *member = + container_of(element, typeof(*member), head.list); tomoyo_put_name(member->member_name); } -static void tomoyo_del_path_group(struct tomoyo_path_group *group) +static void tomoyo_del_group(struct list_head *element) { + struct tomoyo_group *group = + container_of(element, typeof(*group), list); tomoyo_put_name(group->group_name); } +static void tomoyo_del_number_group(struct list_head *element) +{ + struct tomoyo_number_group *member = + container_of(element, typeof(*member), head.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; + } + 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; + } + 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, - 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; - } + for (i = 0; i < TOMOYO_MAX_POLICY; 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) { - switch (acl->type) { - case TOMOYO_TYPE_PATH_ACL: - if (container_of(acl, - struct tomoyo_path_acl, - head)->perm || - container_of(acl, - struct tomoyo_path_acl, - head)->perm_high) - continue; - break; - case TOMOYO_TYPE_PATH2_ACL: - if (container_of(acl, - struct tomoyo_path2_acl, - head)->perm) - continue; - break; - default: - 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; /* @@ -283,104 +237,92 @@ static void tomoyo_collect_entry(void) * 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; + if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list)) + 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 *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)) + 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, - list) { - if (!member->is_deleted) - continue; - if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER, - member)) - list_del_rcu(&member->list); - else - break; - } + for (i = 0; i < TOMOYO_MAX_GROUP; i++) { + struct list_head *list = &tomoyo_group_list[i]; + int id; + struct tomoyo_group *group; + switch (i) { + case 0: + id = TOMOYO_ID_PATH_GROUP; + break; + default: + id = TOMOYO_ID_NUMBER_GROUP; + break; + } + list_for_each_entry(group, list, list) { + if (!tomoyo_collect_member(&group->member_list, id)) + goto unlock; if (!list_empty(&group->member_list) || atomic_read(&group->users)) continue; - if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group)) - list_del_rcu(&group->list); - else - break; + if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list)) + goto unlock; } } + unlock: mutex_unlock(&tomoyo_policy_lock); } static void tomoyo_kfree_entry(void) { - struct tomoyo_gc_entry *p; - struct tomoyo_gc_entry *tmp; + struct tomoyo_gc *p; + struct tomoyo_gc *tmp; list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { + struct list_head *element = p->element; 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); + case TOMOYO_ID_TRANSITION_CONTROL: + tomoyo_del_transition_control(element); break; - case TOMOYO_ID_ALIAS: - tomoyo_del_alias(p->element); + case TOMOYO_ID_AGGREGATOR: + tomoyo_del_aggregator(element); break; case TOMOYO_ID_GLOBALLY_READABLE: - tomoyo_del_allow_read(p->element); + tomoyo_del_allow_read(element); break; case TOMOYO_ID_PATTERN: - tomoyo_del_file_pattern(p->element); + tomoyo_del_file_pattern(element); break; case TOMOYO_ID_NO_REWRITE: - tomoyo_del_no_rewrite(p->element); + tomoyo_del_no_rewrite(element); break; case TOMOYO_ID_MANAGER: - tomoyo_del_manager(p->element); + tomoyo_del_manager(element); break; case TOMOYO_ID_NAME: - tomoyo_del_name(p->element); + tomoyo_del_name(element); break; case TOMOYO_ID_ACL: - tomoyo_del_acl(p->element); + tomoyo_del_acl(element); break; case TOMOYO_ID_DOMAIN: - if (!tomoyo_del_domain(p->element)) + if (!tomoyo_del_domain(element)) continue; break; - case TOMOYO_ID_PATH_GROUP_MEMBER: - tomoyo_del_path_group_member(p->element); - break; case TOMOYO_ID_PATH_GROUP: - tomoyo_del_path_group(p->element); + tomoyo_del_path_group(element); break; - default: - printk(KERN_WARNING "Unknown type\n"); + case TOMOYO_ID_GROUP: + tomoyo_del_group(element); + break; + case TOMOYO_ID_NUMBER_GROUP: + tomoyo_del_number_group(element); break; } - tomoyo_memory_free(p->element); + tomoyo_memory_free(element); list_del(&p->list); kfree(p); } |