| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 1 | /* | 
|  | 2 | * security/tomoyo/gc.c | 
|  | 3 | * | 
|  | 4 | * Implementation of the Domain-Based Mandatory Access Control. | 
|  | 5 | * | 
|  | 6 | * Copyright (C) 2005-2010  NTT DATA CORPORATION | 
|  | 7 | * | 
|  | 8 | */ | 
|  | 9 |  | 
|  | 10 | #include "common.h" | 
|  | 11 | #include <linux/kthread.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 12 | #include <linux/slab.h> | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 13 |  | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 14 | struct tomoyo_gc { | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 15 | struct list_head list; | 
|  | 16 | int type; | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 17 | struct list_head *element; | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 18 | }; | 
|  | 19 | static LIST_HEAD(tomoyo_gc_queue); | 
|  | 20 | static DEFINE_MUTEX(tomoyo_gc_mutex); | 
|  | 21 |  | 
|  | 22 | /* Caller holds tomoyo_policy_lock mutex. */ | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 23 | static bool tomoyo_add_to_gc(const int type, struct list_head *element) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 24 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 25 | struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 26 | if (!entry) | 
|  | 27 | return false; | 
|  | 28 | entry->type = type; | 
|  | 29 | entry->element = element; | 
|  | 30 | list_add(&entry->list, &tomoyo_gc_queue); | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 31 | list_del_rcu(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 32 | return true; | 
|  | 33 | } | 
|  | 34 |  | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 35 | static void tomoyo_del_allow_read(struct list_head *element) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 36 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 37 | struct tomoyo_readable_file *ptr = | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 38 | container_of(element, typeof(*ptr), head.list); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 39 | tomoyo_put_name(ptr->filename); | 
|  | 40 | } | 
|  | 41 |  | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 42 | static void tomoyo_del_file_pattern(struct list_head *element) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 43 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 44 | struct tomoyo_no_pattern *ptr = | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 45 | container_of(element, typeof(*ptr), head.list); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 46 | tomoyo_put_name(ptr->pattern); | 
|  | 47 | } | 
|  | 48 |  | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 49 | static void tomoyo_del_no_rewrite(struct list_head *element) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 50 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 51 | struct tomoyo_no_rewrite *ptr = | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 52 | container_of(element, typeof(*ptr), head.list); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 53 | tomoyo_put_name(ptr->pattern); | 
|  | 54 | } | 
|  | 55 |  | 
| Tetsuo Handa | 5448ec4 | 2010-06-21 11:14:39 +0900 | [diff] [blame] | 56 | static void tomoyo_del_transition_control(struct list_head *element) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 57 | { | 
| Tetsuo Handa | 5448ec4 | 2010-06-21 11:14:39 +0900 | [diff] [blame] | 58 | struct tomoyo_transition_control *ptr = | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 59 | container_of(element, typeof(*ptr), head.list); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 60 | tomoyo_put_name(ptr->domainname); | 
|  | 61 | tomoyo_put_name(ptr->program); | 
|  | 62 | } | 
|  | 63 |  | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 64 | static void tomoyo_del_aggregator(struct list_head *element) | 
| Tetsuo Handa | 1084307 | 2010-06-03 20:38:03 +0900 | [diff] [blame] | 65 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 66 | struct tomoyo_aggregator *ptr = | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 67 | container_of(element, typeof(*ptr), head.list); | 
| Tetsuo Handa | 1084307 | 2010-06-03 20:38:03 +0900 | [diff] [blame] | 68 | tomoyo_put_name(ptr->original_name); | 
|  | 69 | tomoyo_put_name(ptr->aggregated_name); | 
|  | 70 | } | 
|  | 71 |  | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 72 | static void tomoyo_del_manager(struct list_head *element) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 73 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 74 | struct tomoyo_manager *ptr = | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 75 | container_of(element, typeof(*ptr), head.list); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 76 | tomoyo_put_name(ptr->manager); | 
|  | 77 | } | 
|  | 78 |  | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 79 | static void tomoyo_del_acl(struct list_head *element) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 80 | { | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 81 | struct tomoyo_acl_info *acl = | 
|  | 82 | container_of(element, typeof(*acl), list); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 83 | switch (acl->type) { | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 84 | case TOMOYO_TYPE_PATH_ACL: | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 85 | { | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 86 | struct tomoyo_path_acl *entry | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 87 | = container_of(acl, typeof(*entry), head); | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 88 | tomoyo_put_name_union(&entry->name); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 89 | } | 
|  | 90 | break; | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 91 | case TOMOYO_TYPE_PATH2_ACL: | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 92 | { | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 93 | struct tomoyo_path2_acl *entry | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 94 | = container_of(acl, typeof(*entry), head); | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 95 | tomoyo_put_name_union(&entry->name1); | 
|  | 96 | tomoyo_put_name_union(&entry->name2); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 97 | } | 
|  | 98 | break; | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 99 | case TOMOYO_TYPE_PATH_NUMBER_ACL: | 
|  | 100 | { | 
|  | 101 | struct tomoyo_path_number_acl *entry | 
|  | 102 | = container_of(acl, typeof(*entry), head); | 
|  | 103 | tomoyo_put_name_union(&entry->name); | 
|  | 104 | tomoyo_put_number_union(&entry->number); | 
|  | 105 | } | 
|  | 106 | break; | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 107 | case TOMOYO_TYPE_MKDEV_ACL: | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 108 | { | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 109 | struct tomoyo_mkdev_acl *entry | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 110 | = container_of(acl, typeof(*entry), head); | 
|  | 111 | tomoyo_put_name_union(&entry->name); | 
|  | 112 | tomoyo_put_number_union(&entry->mode); | 
|  | 113 | tomoyo_put_number_union(&entry->major); | 
|  | 114 | tomoyo_put_number_union(&entry->minor); | 
|  | 115 | } | 
|  | 116 | break; | 
| Tetsuo Handa | 2106ccd | 2010-05-17 10:10:31 +0900 | [diff] [blame] | 117 | case TOMOYO_TYPE_MOUNT_ACL: | 
|  | 118 | { | 
|  | 119 | struct tomoyo_mount_acl *entry | 
|  | 120 | = container_of(acl, typeof(*entry), head); | 
|  | 121 | tomoyo_put_name_union(&entry->dev_name); | 
|  | 122 | tomoyo_put_name_union(&entry->dir_name); | 
|  | 123 | tomoyo_put_name_union(&entry->fs_type); | 
|  | 124 | tomoyo_put_number_union(&entry->flags); | 
|  | 125 | } | 
|  | 126 | break; | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 127 | } | 
|  | 128 | } | 
|  | 129 |  | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 130 | static bool tomoyo_del_domain(struct list_head *element) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 131 | { | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 132 | struct tomoyo_domain_info *domain = | 
|  | 133 | container_of(element, typeof(*domain), list); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 134 | struct tomoyo_acl_info *acl; | 
|  | 135 | struct tomoyo_acl_info *tmp; | 
|  | 136 | /* | 
|  | 137 | * Since we don't protect whole execve() operation using SRCU, | 
|  | 138 | * we need to recheck domain->users at this point. | 
|  | 139 | * | 
|  | 140 | * (1) Reader starts SRCU section upon execve(). | 
|  | 141 | * (2) Reader traverses tomoyo_domain_list and finds this domain. | 
|  | 142 | * (3) Writer marks this domain as deleted. | 
|  | 143 | * (4) Garbage collector removes this domain from tomoyo_domain_list | 
|  | 144 | *     because this domain is marked as deleted and used by nobody. | 
|  | 145 | * (5) Reader saves reference to this domain into | 
|  | 146 | *     "struct linux_binprm"->cred->security . | 
|  | 147 | * (6) Reader finishes SRCU section, although execve() operation has | 
|  | 148 | *     not finished yet. | 
|  | 149 | * (7) Garbage collector waits for SRCU synchronization. | 
|  | 150 | * (8) Garbage collector kfree() this domain because this domain is | 
|  | 151 | *     used by nobody. | 
|  | 152 | * (9) Reader finishes execve() operation and restores this domain from | 
|  | 153 | *     "struct linux_binprm"->cred->security. | 
|  | 154 | * | 
|  | 155 | * By updating domain->users at (5), we can solve this race problem | 
|  | 156 | * by rechecking domain->users at (8). | 
|  | 157 | */ | 
|  | 158 | if (atomic_read(&domain->users)) | 
|  | 159 | return false; | 
|  | 160 | list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 161 | tomoyo_del_acl(&acl->list); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 162 | tomoyo_memory_free(acl); | 
|  | 163 | } | 
|  | 164 | tomoyo_put_name(domain->domainname); | 
|  | 165 | return true; | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 |  | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 169 | static void tomoyo_del_name(struct list_head *element) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 170 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 171 | const struct tomoyo_name *ptr = | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 172 | container_of(element, typeof(*ptr), list); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 173 | } | 
|  | 174 |  | 
| Tetsuo Handa | a98aa4d | 2010-06-17 16:52:29 +0900 | [diff] [blame] | 175 | static void tomoyo_del_path_group(struct list_head *element) | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 176 | { | 
| Tetsuo Handa | a98aa4d | 2010-06-17 16:52:29 +0900 | [diff] [blame] | 177 | struct tomoyo_path_group *member = | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 178 | container_of(element, typeof(*member), head.list); | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 179 | tomoyo_put_name(member->member_name); | 
|  | 180 | } | 
|  | 181 |  | 
| Tetsuo Handa | a98aa4d | 2010-06-17 16:52:29 +0900 | [diff] [blame] | 182 | static void tomoyo_del_group(struct list_head *element) | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 183 | { | 
| Tetsuo Handa | a98aa4d | 2010-06-17 16:52:29 +0900 | [diff] [blame] | 184 | struct tomoyo_group *group = | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 185 | container_of(element, typeof(*group), list); | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 186 | tomoyo_put_name(group->group_name); | 
|  | 187 | } | 
|  | 188 |  | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 189 | static void tomoyo_del_number_group(struct list_head *element) | 
| Tetsuo Handa | 4c3e9e2 | 2010-05-17 10:06:58 +0900 | [diff] [blame] | 190 | { | 
| Tetsuo Handa | a98aa4d | 2010-06-17 16:52:29 +0900 | [diff] [blame] | 191 | struct tomoyo_number_group *member = | 
|  | 192 | container_of(element, typeof(*member), head.list); | 
| Tetsuo Handa | 4c3e9e2 | 2010-05-17 10:06:58 +0900 | [diff] [blame] | 193 | } | 
|  | 194 |  | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 195 | static bool tomoyo_collect_member(struct list_head *member_list, int id) | 
|  | 196 | { | 
|  | 197 | struct tomoyo_acl_head *member; | 
|  | 198 | list_for_each_entry(member, member_list, list) { | 
|  | 199 | if (!member->is_deleted) | 
|  | 200 | continue; | 
|  | 201 | if (!tomoyo_add_to_gc(id, &member->list)) | 
|  | 202 | return false; | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 203 | } | 
|  | 204 | return true; | 
|  | 205 | } | 
|  | 206 |  | 
|  | 207 | static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain) | 
|  | 208 | { | 
|  | 209 | struct tomoyo_acl_info *acl; | 
|  | 210 | list_for_each_entry(acl, &domain->acl_info_list, list) { | 
|  | 211 | if (!acl->is_deleted) | 
|  | 212 | continue; | 
|  | 213 | if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list)) | 
|  | 214 | return false; | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 215 | } | 
|  | 216 | return true; | 
|  | 217 | } | 
|  | 218 |  | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 219 | static void tomoyo_collect_entry(void) | 
|  | 220 | { | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 221 | int i; | 
| Tetsuo Handa | 2928238 | 2010-05-06 00:18:15 +0900 | [diff] [blame] | 222 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 
|  | 223 | return; | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 224 | for (i = 0; i < TOMOYO_MAX_POLICY; i++) { | 
| Tetsuo Handa | a230f9e | 2010-06-17 16:53:24 +0900 | [diff] [blame] | 225 | if (!tomoyo_collect_member(&tomoyo_policy_list[i], i)) | 
|  | 226 | goto unlock; | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 227 | } | 
|  | 228 | { | 
|  | 229 | struct tomoyo_domain_info *domain; | 
|  | 230 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 231 | if (!tomoyo_collect_acl(domain)) | 
|  | 232 | goto unlock; | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 233 | if (!domain->is_deleted || atomic_read(&domain->users)) | 
|  | 234 | continue; | 
|  | 235 | /* | 
|  | 236 | * Nobody is referring this domain. But somebody may | 
|  | 237 | * refer this domain after successful execve(). | 
|  | 238 | * We recheck domain->users after SRCU synchronization. | 
|  | 239 | */ | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 240 | if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list)) | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 241 | goto unlock; | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 242 | } | 
|  | 243 | } | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 244 | for (i = 0; i < TOMOYO_MAX_HASH; i++) { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 245 | struct tomoyo_name *ptr; | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 246 | list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], list) { | 
|  | 247 | if (atomic_read(&ptr->users)) | 
|  | 248 | continue; | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 249 | if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list)) | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 250 | goto unlock; | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 251 | } | 
|  | 252 | } | 
| Tetsuo Handa | 7c2ea22 | 2010-06-17 16:55:58 +0900 | [diff] [blame] | 253 | for (i = 0; i < TOMOYO_MAX_GROUP; i++) { | 
|  | 254 | struct list_head *list = &tomoyo_group_list[i]; | 
|  | 255 | int id; | 
| Tetsuo Handa | a98aa4d | 2010-06-17 16:52:29 +0900 | [diff] [blame] | 256 | struct tomoyo_group *group; | 
| Tetsuo Handa | 7c2ea22 | 2010-06-17 16:55:58 +0900 | [diff] [blame] | 257 | switch (i) { | 
|  | 258 | case 0: | 
|  | 259 | id = TOMOYO_ID_PATH_GROUP; | 
|  | 260 | break; | 
|  | 261 | default: | 
|  | 262 | id = TOMOYO_ID_NUMBER_GROUP; | 
|  | 263 | break; | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 264 | } | 
| Tetsuo Handa | 7c2ea22 | 2010-06-17 16:55:58 +0900 | [diff] [blame] | 265 | list_for_each_entry(group, list, list) { | 
|  | 266 | if (!tomoyo_collect_member(&group->member_list, id)) | 
|  | 267 | goto unlock; | 
| Tetsuo Handa | 4c3e9e2 | 2010-05-17 10:06:58 +0900 | [diff] [blame] | 268 | if (!list_empty(&group->member_list) || | 
|  | 269 | atomic_read(&group->users)) | 
|  | 270 | continue; | 
| Tetsuo Handa | 7c2ea22 | 2010-06-17 16:55:58 +0900 | [diff] [blame] | 271 | if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list)) | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 272 | goto unlock; | 
| Tetsuo Handa | 4c3e9e2 | 2010-05-17 10:06:58 +0900 | [diff] [blame] | 273 | } | 
|  | 274 | } | 
| Tetsuo Handa | d2f8b23 | 2010-06-15 10:10:37 +0900 | [diff] [blame] | 275 | unlock: | 
| Tetsuo Handa | 2928238 | 2010-05-06 00:18:15 +0900 | [diff] [blame] | 276 | mutex_unlock(&tomoyo_policy_lock); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 277 | } | 
|  | 278 |  | 
|  | 279 | static void tomoyo_kfree_entry(void) | 
|  | 280 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 281 | struct tomoyo_gc *p; | 
|  | 282 | struct tomoyo_gc *tmp; | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 283 |  | 
|  | 284 | list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 285 | struct list_head *element = p->element; | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 286 | switch (p->type) { | 
| Tetsuo Handa | 5448ec4 | 2010-06-21 11:14:39 +0900 | [diff] [blame] | 287 | case TOMOYO_ID_TRANSITION_CONTROL: | 
|  | 288 | tomoyo_del_transition_control(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 289 | break; | 
| Tetsuo Handa | 1084307 | 2010-06-03 20:38:03 +0900 | [diff] [blame] | 290 | case TOMOYO_ID_AGGREGATOR: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 291 | tomoyo_del_aggregator(element); | 
| Tetsuo Handa | 1084307 | 2010-06-03 20:38:03 +0900 | [diff] [blame] | 292 | break; | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 293 | case TOMOYO_ID_GLOBALLY_READABLE: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 294 | tomoyo_del_allow_read(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 295 | break; | 
|  | 296 | case TOMOYO_ID_PATTERN: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 297 | tomoyo_del_file_pattern(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 298 | break; | 
|  | 299 | case TOMOYO_ID_NO_REWRITE: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 300 | tomoyo_del_no_rewrite(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 301 | break; | 
|  | 302 | case TOMOYO_ID_MANAGER: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 303 | tomoyo_del_manager(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 304 | break; | 
|  | 305 | case TOMOYO_ID_NAME: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 306 | tomoyo_del_name(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 307 | break; | 
|  | 308 | case TOMOYO_ID_ACL: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 309 | tomoyo_del_acl(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 310 | break; | 
|  | 311 | case TOMOYO_ID_DOMAIN: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 312 | if (!tomoyo_del_domain(element)) | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 313 | continue; | 
|  | 314 | break; | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 315 | case TOMOYO_ID_PATH_GROUP: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 316 | tomoyo_del_path_group(element); | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 317 | break; | 
| Tetsuo Handa | a98aa4d | 2010-06-17 16:52:29 +0900 | [diff] [blame] | 318 | case TOMOYO_ID_GROUP: | 
|  | 319 | tomoyo_del_group(element); | 
| Tetsuo Handa | 4c3e9e2 | 2010-05-17 10:06:58 +0900 | [diff] [blame] | 320 | break; | 
|  | 321 | case TOMOYO_ID_NUMBER_GROUP: | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 322 | tomoyo_del_number_group(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 323 | break; | 
|  | 324 | } | 
| Tetsuo Handa | e79acf0 | 2010-06-16 16:31:50 +0900 | [diff] [blame] | 325 | tomoyo_memory_free(element); | 
| Tetsuo Handa | 847b173 | 2010-02-11 09:43:54 +0900 | [diff] [blame] | 326 | list_del(&p->list); | 
|  | 327 | kfree(p); | 
|  | 328 | } | 
|  | 329 | } | 
|  | 330 |  | 
|  | 331 | static int tomoyo_gc_thread(void *unused) | 
|  | 332 | { | 
|  | 333 | daemonize("GC for TOMOYO"); | 
|  | 334 | if (mutex_trylock(&tomoyo_gc_mutex)) { | 
|  | 335 | int i; | 
|  | 336 | for (i = 0; i < 10; i++) { | 
|  | 337 | tomoyo_collect_entry(); | 
|  | 338 | if (list_empty(&tomoyo_gc_queue)) | 
|  | 339 | break; | 
|  | 340 | synchronize_srcu(&tomoyo_ss); | 
|  | 341 | tomoyo_kfree_entry(); | 
|  | 342 | } | 
|  | 343 | mutex_unlock(&tomoyo_gc_mutex); | 
|  | 344 | } | 
|  | 345 | do_exit(0); | 
|  | 346 | } | 
|  | 347 |  | 
|  | 348 | void tomoyo_run_gc(void) | 
|  | 349 | { | 
|  | 350 | struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL, | 
|  | 351 | "GC for TOMOYO"); | 
|  | 352 | if (!IS_ERR(task)) | 
|  | 353 | wake_up_process(task); | 
|  | 354 | } |