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