gc.c revision 82e0f001a4c1112dcff9cafa9812a33889ad9b8a
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 14enum tomoyo_gc_id { 15 TOMOYO_ID_PATH_GROUP, 16 TOMOYO_ID_PATH_GROUP_MEMBER, 17 TOMOYO_ID_NUMBER_GROUP, 18 TOMOYO_ID_NUMBER_GROUP_MEMBER, 19 TOMOYO_ID_DOMAIN_INITIALIZER, 20 TOMOYO_ID_DOMAIN_KEEPER, 21 TOMOYO_ID_AGGREGATOR, 22 TOMOYO_ID_ALIAS, 23 TOMOYO_ID_GLOBALLY_READABLE, 24 TOMOYO_ID_PATTERN, 25 TOMOYO_ID_NO_REWRITE, 26 TOMOYO_ID_MANAGER, 27 TOMOYO_ID_NAME, 28 TOMOYO_ID_ACL, 29 TOMOYO_ID_DOMAIN 30}; 31 32struct tomoyo_gc_entry { 33 struct list_head list; 34 int type; 35 void *element; 36}; 37static LIST_HEAD(tomoyo_gc_queue); 38static DEFINE_MUTEX(tomoyo_gc_mutex); 39 40/* Caller holds tomoyo_policy_lock mutex. */ 41static bool tomoyo_add_to_gc(const int type, void *element) 42{ 43 struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 44 if (!entry) 45 return false; 46 entry->type = type; 47 entry->element = element; 48 list_add(&entry->list, &tomoyo_gc_queue); 49 return true; 50} 51 52static void tomoyo_del_allow_read 53(struct tomoyo_globally_readable_file_entry *ptr) 54{ 55 tomoyo_put_name(ptr->filename); 56} 57 58static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr) 59{ 60 tomoyo_put_name(ptr->pattern); 61} 62 63static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr) 64{ 65 tomoyo_put_name(ptr->pattern); 66} 67 68static void tomoyo_del_domain_initializer 69(struct tomoyo_domain_initializer_entry *ptr) 70{ 71 tomoyo_put_name(ptr->domainname); 72 tomoyo_put_name(ptr->program); 73} 74 75static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr) 76{ 77 tomoyo_put_name(ptr->domainname); 78 tomoyo_put_name(ptr->program); 79} 80 81static void tomoyo_del_aggregator(struct tomoyo_aggregator_entry *ptr) 82{ 83 tomoyo_put_name(ptr->original_name); 84 tomoyo_put_name(ptr->aggregated_name); 85} 86 87static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr) 88{ 89 tomoyo_put_name(ptr->original_name); 90 tomoyo_put_name(ptr->aliased_name); 91} 92 93static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr) 94{ 95 tomoyo_put_name(ptr->manager); 96} 97 98static void tomoyo_del_acl(struct tomoyo_acl_info *acl) 99{ 100 switch (acl->type) { 101 case TOMOYO_TYPE_PATH_ACL: 102 { 103 struct tomoyo_path_acl *entry 104 = container_of(acl, typeof(*entry), head); 105 tomoyo_put_name_union(&entry->name); 106 } 107 break; 108 case TOMOYO_TYPE_PATH2_ACL: 109 { 110 struct tomoyo_path2_acl *entry 111 = container_of(acl, typeof(*entry), head); 112 tomoyo_put_name_union(&entry->name1); 113 tomoyo_put_name_union(&entry->name2); 114 } 115 break; 116 case TOMOYO_TYPE_PATH_NUMBER_ACL: 117 { 118 struct tomoyo_path_number_acl *entry 119 = container_of(acl, typeof(*entry), head); 120 tomoyo_put_name_union(&entry->name); 121 tomoyo_put_number_union(&entry->number); 122 } 123 break; 124 case TOMOYO_TYPE_PATH_NUMBER3_ACL: 125 { 126 struct tomoyo_path_number3_acl *entry 127 = container_of(acl, typeof(*entry), head); 128 tomoyo_put_name_union(&entry->name); 129 tomoyo_put_number_union(&entry->mode); 130 tomoyo_put_number_union(&entry->major); 131 tomoyo_put_number_union(&entry->minor); 132 } 133 break; 134 case TOMOYO_TYPE_MOUNT_ACL: 135 { 136 struct tomoyo_mount_acl *entry 137 = container_of(acl, typeof(*entry), head); 138 tomoyo_put_name_union(&entry->dev_name); 139 tomoyo_put_name_union(&entry->dir_name); 140 tomoyo_put_name_union(&entry->fs_type); 141 tomoyo_put_number_union(&entry->flags); 142 } 143 break; 144 default: 145 printk(KERN_WARNING "Unknown type\n"); 146 break; 147 } 148} 149 150static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) 151{ 152 struct tomoyo_acl_info *acl; 153 struct tomoyo_acl_info *tmp; 154 /* 155 * Since we don't protect whole execve() operation using SRCU, 156 * we need to recheck domain->users at this point. 157 * 158 * (1) Reader starts SRCU section upon execve(). 159 * (2) Reader traverses tomoyo_domain_list and finds this domain. 160 * (3) Writer marks this domain as deleted. 161 * (4) Garbage collector removes this domain from tomoyo_domain_list 162 * because this domain is marked as deleted and used by nobody. 163 * (5) Reader saves reference to this domain into 164 * "struct linux_binprm"->cred->security . 165 * (6) Reader finishes SRCU section, although execve() operation has 166 * not finished yet. 167 * (7) Garbage collector waits for SRCU synchronization. 168 * (8) Garbage collector kfree() this domain because this domain is 169 * used by nobody. 170 * (9) Reader finishes execve() operation and restores this domain from 171 * "struct linux_binprm"->cred->security. 172 * 173 * By updating domain->users at (5), we can solve this race problem 174 * by rechecking domain->users at (8). 175 */ 176 if (atomic_read(&domain->users)) 177 return false; 178 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { 179 tomoyo_del_acl(acl); 180 tomoyo_memory_free(acl); 181 } 182 tomoyo_put_name(domain->domainname); 183 return true; 184} 185 186 187static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) 188{ 189} 190 191static void tomoyo_del_path_group_member(struct tomoyo_path_group_member 192 *member) 193{ 194 tomoyo_put_name(member->member_name); 195} 196 197static void tomoyo_del_path_group(struct tomoyo_path_group *group) 198{ 199 tomoyo_put_name(group->group_name); 200} 201 202static void tomoyo_del_number_group_member(struct tomoyo_number_group_member 203 *member) 204{ 205} 206 207static void tomoyo_del_number_group(struct tomoyo_number_group *group) 208{ 209 tomoyo_put_name(group->group_name); 210} 211 212static void tomoyo_collect_entry(void) 213{ 214 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 215 return; 216 { 217 struct tomoyo_globally_readable_file_entry *ptr; 218 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, 219 head.list) { 220 if (!ptr->head.is_deleted) 221 continue; 222 if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr)) 223 list_del_rcu(&ptr->head.list); 224 else 225 break; 226 } 227 } 228 { 229 struct tomoyo_pattern_entry *ptr; 230 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, head.list) { 231 if (!ptr->head.is_deleted) 232 continue; 233 if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr)) 234 list_del_rcu(&ptr->head.list); 235 else 236 break; 237 } 238 } 239 { 240 struct tomoyo_no_rewrite_entry *ptr; 241 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, 242 head.list) { 243 if (!ptr->head.is_deleted) 244 continue; 245 if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr)) 246 list_del_rcu(&ptr->head.list); 247 else 248 break; 249 } 250 } 251 { 252 struct tomoyo_domain_initializer_entry *ptr; 253 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, 254 head.list) { 255 if (!ptr->head.is_deleted) 256 continue; 257 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr)) 258 list_del_rcu(&ptr->head.list); 259 else 260 break; 261 } 262 } 263 { 264 struct tomoyo_domain_keeper_entry *ptr; 265 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, 266 head.list) { 267 if (!ptr->head.is_deleted) 268 continue; 269 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr)) 270 list_del_rcu(&ptr->head.list); 271 else 272 break; 273 } 274 } 275 { 276 struct tomoyo_aggregator_entry *ptr; 277 list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list, 278 head.list) { 279 if (!ptr->head.is_deleted) 280 continue; 281 if (tomoyo_add_to_gc(TOMOYO_ID_AGGREGATOR, ptr)) 282 list_del_rcu(&ptr->head.list); 283 else 284 break; 285 } 286 } 287 { 288 struct tomoyo_alias_entry *ptr; 289 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, head.list) { 290 if (!ptr->head.is_deleted) 291 continue; 292 if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr)) 293 list_del_rcu(&ptr->head.list); 294 else 295 break; 296 } 297 } 298 { 299 struct tomoyo_policy_manager_entry *ptr; 300 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, 301 head.list) { 302 if (!ptr->head.is_deleted) 303 continue; 304 if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr)) 305 list_del_rcu(&ptr->head.list); 306 else 307 break; 308 } 309 } 310 { 311 struct tomoyo_domain_info *domain; 312 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 313 struct tomoyo_acl_info *acl; 314 list_for_each_entry_rcu(acl, &domain->acl_info_list, 315 list) { 316 if (!acl->is_deleted) 317 continue; 318 if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl)) 319 list_del_rcu(&acl->list); 320 else 321 break; 322 } 323 if (!domain->is_deleted || atomic_read(&domain->users)) 324 continue; 325 /* 326 * Nobody is referring this domain. But somebody may 327 * refer this domain after successful execve(). 328 * We recheck domain->users after SRCU synchronization. 329 */ 330 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain)) 331 list_del_rcu(&domain->list); 332 else 333 break; 334 } 335 } 336 { 337 int i; 338 for (i = 0; i < TOMOYO_MAX_HASH; i++) { 339 struct tomoyo_name_entry *ptr; 340 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], 341 list) { 342 if (atomic_read(&ptr->users)) 343 continue; 344 if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr)) 345 list_del_rcu(&ptr->list); 346 else { 347 i = TOMOYO_MAX_HASH; 348 break; 349 } 350 } 351 } 352 } 353 { 354 struct tomoyo_path_group *group; 355 list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { 356 struct tomoyo_path_group_member *member; 357 list_for_each_entry_rcu(member, &group->member_list, 358 head.list) { 359 if (!member->head.is_deleted) 360 continue; 361 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER, 362 member)) 363 list_del_rcu(&member->head.list); 364 else 365 break; 366 } 367 if (!list_empty(&group->member_list) || 368 atomic_read(&group->users)) 369 continue; 370 if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group)) 371 list_del_rcu(&group->list); 372 else 373 break; 374 } 375 } 376 { 377 struct tomoyo_number_group *group; 378 list_for_each_entry_rcu(group, &tomoyo_number_group_list, list) { 379 struct tomoyo_number_group_member *member; 380 list_for_each_entry_rcu(member, &group->member_list, 381 head.list) { 382 if (!member->head.is_deleted) 383 continue; 384 if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP_MEMBER, 385 member)) 386 list_del_rcu(&member->head.list); 387 else 388 break; 389 } 390 if (!list_empty(&group->member_list) || 391 atomic_read(&group->users)) 392 continue; 393 if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP, group)) 394 list_del_rcu(&group->list); 395 else 396 break; 397 } 398 } 399 mutex_unlock(&tomoyo_policy_lock); 400} 401 402static void tomoyo_kfree_entry(void) 403{ 404 struct tomoyo_gc_entry *p; 405 struct tomoyo_gc_entry *tmp; 406 407 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { 408 switch (p->type) { 409 case TOMOYO_ID_DOMAIN_INITIALIZER: 410 tomoyo_del_domain_initializer(p->element); 411 break; 412 case TOMOYO_ID_DOMAIN_KEEPER: 413 tomoyo_del_domain_keeper(p->element); 414 break; 415 case TOMOYO_ID_AGGREGATOR: 416 tomoyo_del_aggregator(p->element); 417 break; 418 case TOMOYO_ID_ALIAS: 419 tomoyo_del_alias(p->element); 420 break; 421 case TOMOYO_ID_GLOBALLY_READABLE: 422 tomoyo_del_allow_read(p->element); 423 break; 424 case TOMOYO_ID_PATTERN: 425 tomoyo_del_file_pattern(p->element); 426 break; 427 case TOMOYO_ID_NO_REWRITE: 428 tomoyo_del_no_rewrite(p->element); 429 break; 430 case TOMOYO_ID_MANAGER: 431 tomoyo_del_manager(p->element); 432 break; 433 case TOMOYO_ID_NAME: 434 tomoyo_del_name(p->element); 435 break; 436 case TOMOYO_ID_ACL: 437 tomoyo_del_acl(p->element); 438 break; 439 case TOMOYO_ID_DOMAIN: 440 if (!tomoyo_del_domain(p->element)) 441 continue; 442 break; 443 case TOMOYO_ID_PATH_GROUP_MEMBER: 444 tomoyo_del_path_group_member(p->element); 445 break; 446 case TOMOYO_ID_PATH_GROUP: 447 tomoyo_del_path_group(p->element); 448 break; 449 case TOMOYO_ID_NUMBER_GROUP_MEMBER: 450 tomoyo_del_number_group_member(p->element); 451 break; 452 case TOMOYO_ID_NUMBER_GROUP: 453 tomoyo_del_number_group(p->element); 454 break; 455 default: 456 printk(KERN_WARNING "Unknown type\n"); 457 break; 458 } 459 tomoyo_memory_free(p->element); 460 list_del(&p->list); 461 kfree(p); 462 } 463} 464 465static int tomoyo_gc_thread(void *unused) 466{ 467 daemonize("GC for TOMOYO"); 468 if (mutex_trylock(&tomoyo_gc_mutex)) { 469 int i; 470 for (i = 0; i < 10; i++) { 471 tomoyo_collect_entry(); 472 if (list_empty(&tomoyo_gc_queue)) 473 break; 474 synchronize_srcu(&tomoyo_ss); 475 tomoyo_kfree_entry(); 476 } 477 mutex_unlock(&tomoyo_gc_mutex); 478 } 479 do_exit(0); 480} 481 482void tomoyo_run_gc(void) 483{ 484 struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL, 485 "GC for TOMOYO"); 486 if (!IS_ERR(task)) 487 wake_up_process(task); 488} 489