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