gc.c revision 32997144fd9925fc4d506a16990a0c405f766526
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 enum tomoyo_policy_id type; 17 struct list_head *element; 18}; 19static LIST_HEAD(tomoyo_gc_queue); 20static DEFINE_MUTEX(tomoyo_gc_mutex); 21 22/** 23 * tomoyo_add_to_gc - Add an entry to to be deleted list. 24 * 25 * @type: One of values in "enum tomoyo_policy_id". 26 * @element: Pointer to "struct list_head". 27 * 28 * Returns true on success, false otherwise. 29 * 30 * Caller holds tomoyo_policy_lock mutex. 31 * 32 * Adding an entry needs kmalloc(). Thus, if we try to add thousands of 33 * entries at once, it will take too long time. Thus, do not add more than 128 34 * entries per a scan. But to be able to handle worst case where all entries 35 * are in-use, we accept one more entry per a scan. 36 * 37 * If we use singly linked list using "struct list_head"->prev (which is 38 * LIST_POISON2), we can avoid kmalloc(). 39 */ 40static bool tomoyo_add_to_gc(const int type, struct list_head *element) 41{ 42 struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 43 if (!entry) 44 return false; 45 entry->type = type; 46 entry->element = element; 47 list_add(&entry->list, &tomoyo_gc_queue); 48 list_del_rcu(element); 49 return true; 50} 51 52/** 53 * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control". 54 * 55 * @element: Pointer to "struct list_head". 56 * 57 * Returns nothing. 58 */ 59static void tomoyo_del_transition_control(struct list_head *element) 60{ 61 struct tomoyo_transition_control *ptr = 62 container_of(element, typeof(*ptr), head.list); 63 tomoyo_put_name(ptr->domainname); 64 tomoyo_put_name(ptr->program); 65} 66 67/** 68 * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator". 69 * 70 * @element: Pointer to "struct list_head". 71 * 72 * Returns nothing. 73 */ 74static void tomoyo_del_aggregator(struct list_head *element) 75{ 76 struct tomoyo_aggregator *ptr = 77 container_of(element, typeof(*ptr), head.list); 78 tomoyo_put_name(ptr->original_name); 79 tomoyo_put_name(ptr->aggregated_name); 80} 81 82/** 83 * tomoyo_del_manager - Delete members in "struct tomoyo_manager". 84 * 85 * @element: Pointer to "struct list_head". 86 * 87 * Returns nothing. 88 */ 89static void tomoyo_del_manager(struct list_head *element) 90{ 91 struct tomoyo_manager *ptr = 92 container_of(element, typeof(*ptr), head.list); 93 tomoyo_put_name(ptr->manager); 94} 95 96/** 97 * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info". 98 * 99 * @element: Pointer to "struct list_head". 100 * 101 * Returns nothing. 102 */ 103static void tomoyo_del_acl(struct list_head *element) 104{ 105 struct tomoyo_acl_info *acl = 106 container_of(element, typeof(*acl), list); 107 switch (acl->type) { 108 case TOMOYO_TYPE_PATH_ACL: 109 { 110 struct tomoyo_path_acl *entry 111 = container_of(acl, typeof(*entry), head); 112 tomoyo_put_name_union(&entry->name); 113 } 114 break; 115 case TOMOYO_TYPE_PATH2_ACL: 116 { 117 struct tomoyo_path2_acl *entry 118 = container_of(acl, typeof(*entry), head); 119 tomoyo_put_name_union(&entry->name1); 120 tomoyo_put_name_union(&entry->name2); 121 } 122 break; 123 case TOMOYO_TYPE_PATH_NUMBER_ACL: 124 { 125 struct tomoyo_path_number_acl *entry 126 = container_of(acl, typeof(*entry), head); 127 tomoyo_put_name_union(&entry->name); 128 tomoyo_put_number_union(&entry->number); 129 } 130 break; 131 case TOMOYO_TYPE_MKDEV_ACL: 132 { 133 struct tomoyo_mkdev_acl *entry 134 = container_of(acl, typeof(*entry), head); 135 tomoyo_put_name_union(&entry->name); 136 tomoyo_put_number_union(&entry->mode); 137 tomoyo_put_number_union(&entry->major); 138 tomoyo_put_number_union(&entry->minor); 139 } 140 break; 141 case TOMOYO_TYPE_MOUNT_ACL: 142 { 143 struct tomoyo_mount_acl *entry 144 = container_of(acl, typeof(*entry), head); 145 tomoyo_put_name_union(&entry->dev_name); 146 tomoyo_put_name_union(&entry->dir_name); 147 tomoyo_put_name_union(&entry->fs_type); 148 tomoyo_put_number_union(&entry->flags); 149 } 150 break; 151 } 152} 153 154static bool tomoyo_del_domain(struct list_head *element) 155{ 156 struct tomoyo_domain_info *domain = 157 container_of(element, typeof(*domain), list); 158 struct tomoyo_acl_info *acl; 159 struct tomoyo_acl_info *tmp; 160 /* 161 * Since we don't protect whole execve() operation using SRCU, 162 * we need to recheck domain->users at this point. 163 * 164 * (1) Reader starts SRCU section upon execve(). 165 * (2) Reader traverses tomoyo_domain_list and finds this domain. 166 * (3) Writer marks this domain as deleted. 167 * (4) Garbage collector removes this domain from tomoyo_domain_list 168 * because this domain is marked as deleted and used by nobody. 169 * (5) Reader saves reference to this domain into 170 * "struct linux_binprm"->cred->security . 171 * (6) Reader finishes SRCU section, although execve() operation has 172 * not finished yet. 173 * (7) Garbage collector waits for SRCU synchronization. 174 * (8) Garbage collector kfree() this domain because this domain is 175 * used by nobody. 176 * (9) Reader finishes execve() operation and restores this domain from 177 * "struct linux_binprm"->cred->security. 178 * 179 * By updating domain->users at (5), we can solve this race problem 180 * by rechecking domain->users at (8). 181 */ 182 if (atomic_read(&domain->users)) 183 return false; 184 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { 185 tomoyo_del_acl(&acl->list); 186 tomoyo_memory_free(acl); 187 } 188 tomoyo_put_name(domain->domainname); 189 return true; 190} 191 192 193/** 194 * tomoyo_del_name - Delete members in "struct tomoyo_name". 195 * 196 * @element: Pointer to "struct list_head". 197 * 198 * Returns nothing. 199 */ 200static void tomoyo_del_name(struct list_head *element) 201{ 202 const struct tomoyo_name *ptr = 203 container_of(element, typeof(*ptr), head.list); 204} 205 206/** 207 * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group". 208 * 209 * @element: Pointer to "struct list_head". 210 * 211 * Returns nothing. 212 */ 213static void tomoyo_del_path_group(struct list_head *element) 214{ 215 struct tomoyo_path_group *member = 216 container_of(element, typeof(*member), head.list); 217 tomoyo_put_name(member->member_name); 218} 219 220/** 221 * tomoyo_del_group - Delete "struct tomoyo_group". 222 * 223 * @element: Pointer to "struct list_head". 224 * 225 * Returns nothing. 226 */ 227static void tomoyo_del_group(struct list_head *element) 228{ 229 struct tomoyo_group *group = 230 container_of(element, typeof(*group), head.list); 231 tomoyo_put_name(group->group_name); 232} 233 234/** 235 * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group". 236 * 237 * @element: Pointer to "struct list_head". 238 * 239 * Returns nothing. 240 */ 241static void tomoyo_del_number_group(struct list_head *element) 242{ 243 struct tomoyo_number_group *member = 244 container_of(element, typeof(*member), head.list); 245} 246 247/** 248 * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head". 249 * 250 * @id: One of values in "enum tomoyo_policy_id". 251 * @member_list: Pointer to "struct list_head". 252 * 253 * Returns true if some elements are deleted, false otherwise. 254 */ 255static bool tomoyo_collect_member(const enum tomoyo_policy_id id, 256 struct list_head *member_list) 257{ 258 struct tomoyo_acl_head *member; 259 list_for_each_entry(member, member_list, list) { 260 if (!member->is_deleted) 261 continue; 262 if (!tomoyo_add_to_gc(id, &member->list)) 263 return false; 264 } 265 return true; 266} 267 268/** 269 * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info". 270 * 271 * @list: Pointer to "struct list_head". 272 * 273 * Returns true if some elements are deleted, false otherwise. 274 */ 275static bool tomoyo_collect_acl(struct list_head *list) 276{ 277 struct tomoyo_acl_info *acl; 278 list_for_each_entry(acl, list, list) { 279 if (!acl->is_deleted) 280 continue; 281 if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list)) 282 return false; 283 } 284 return true; 285} 286 287/** 288 * tomoyo_collect_entry - Scan lists for deleted elements. 289 * 290 * Returns nothing. 291 */ 292static void tomoyo_collect_entry(void) 293{ 294 int i; 295 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 296 return; 297 for (i = 0; i < TOMOYO_MAX_POLICY; i++) { 298 if (!tomoyo_collect_member(i, &tomoyo_policy_list[i])) 299 goto unlock; 300 } 301 for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++) 302 if (!tomoyo_collect_acl(&tomoyo_acl_group[i])) 303 goto unlock; 304 { 305 struct tomoyo_domain_info *domain; 306 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 307 if (!tomoyo_collect_acl(&domain->acl_info_list)) 308 goto unlock; 309 if (!domain->is_deleted || atomic_read(&domain->users)) 310 continue; 311 /* 312 * Nobody is referring this domain. But somebody may 313 * refer this domain after successful execve(). 314 * We recheck domain->users after SRCU synchronization. 315 */ 316 if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list)) 317 goto unlock; 318 } 319 } 320 for (i = 0; i < TOMOYO_MAX_HASH; i++) { 321 struct tomoyo_name *ptr; 322 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], head.list) { 323 if (atomic_read(&ptr->head.users)) 324 continue; 325 if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->head.list)) 326 goto unlock; 327 } 328 } 329 for (i = 0; i < TOMOYO_MAX_GROUP; i++) { 330 struct list_head *list = &tomoyo_group_list[i]; 331 int id; 332 struct tomoyo_group *group; 333 switch (i) { 334 case 0: 335 id = TOMOYO_ID_PATH_GROUP; 336 break; 337 default: 338 id = TOMOYO_ID_NUMBER_GROUP; 339 break; 340 } 341 list_for_each_entry(group, list, head.list) { 342 if (!tomoyo_collect_member(id, &group->member_list)) 343 goto unlock; 344 if (!list_empty(&group->member_list) || 345 atomic_read(&group->head.users)) 346 continue; 347 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, 348 &group->head.list)) 349 goto unlock; 350 } 351 } 352 unlock: 353 mutex_unlock(&tomoyo_policy_lock); 354} 355 356static void tomoyo_kfree_entry(void) 357{ 358 struct tomoyo_gc *p; 359 struct tomoyo_gc *tmp; 360 361 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { 362 struct list_head *element = p->element; 363 switch (p->type) { 364 case TOMOYO_ID_TRANSITION_CONTROL: 365 tomoyo_del_transition_control(element); 366 break; 367 case TOMOYO_ID_AGGREGATOR: 368 tomoyo_del_aggregator(element); 369 break; 370 case TOMOYO_ID_MANAGER: 371 tomoyo_del_manager(element); 372 break; 373 case TOMOYO_ID_NAME: 374 tomoyo_del_name(element); 375 break; 376 case TOMOYO_ID_ACL: 377 tomoyo_del_acl(element); 378 break; 379 case TOMOYO_ID_DOMAIN: 380 if (!tomoyo_del_domain(element)) 381 continue; 382 break; 383 case TOMOYO_ID_PATH_GROUP: 384 tomoyo_del_path_group(element); 385 break; 386 case TOMOYO_ID_GROUP: 387 tomoyo_del_group(element); 388 break; 389 case TOMOYO_ID_NUMBER_GROUP: 390 tomoyo_del_number_group(element); 391 break; 392 case TOMOYO_MAX_POLICY: 393 break; 394 } 395 tomoyo_memory_free(element); 396 list_del(&p->list); 397 kfree(p); 398 } 399} 400 401/** 402 * tomoyo_gc_thread - Garbage collector thread function. 403 * 404 * @unused: Unused. 405 * 406 * In case OOM-killer choose this thread for termination, we create this thread 407 * as a short live thread whenever /sys/kernel/security/tomoyo/ interface was 408 * close()d. 409 * 410 * Returns 0. 411 */ 412static int tomoyo_gc_thread(void *unused) 413{ 414 daemonize("GC for TOMOYO"); 415 if (mutex_trylock(&tomoyo_gc_mutex)) { 416 int i; 417 for (i = 0; i < 10; i++) { 418 tomoyo_collect_entry(); 419 if (list_empty(&tomoyo_gc_queue)) 420 break; 421 synchronize_srcu(&tomoyo_ss); 422 tomoyo_kfree_entry(); 423 } 424 mutex_unlock(&tomoyo_gc_mutex); 425 } 426 do_exit(0); 427} 428 429void tomoyo_run_gc(void) 430{ 431 struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL, 432 "GC for TOMOYO"); 433 if (!IS_ERR(task)) 434 wake_up_process(task); 435} 436