domain.c revision 33043cbb9fd49a957089f5948fe814764d7abbd6
1/* 2 * security/tomoyo/domain.c 3 * 4 * Implementation of the Domain-Based Mandatory Access Control. 5 * 6 * Copyright (C) 2005-2009 NTT DATA CORPORATION 7 * 8 * Version: 2.2.0-pre 2009/02/01 9 * 10 */ 11 12#include "common.h" 13#include "tomoyo.h" 14#include "realpath.h" 15#include <linux/binfmts.h> 16 17/* Variables definitions.*/ 18 19/* The initial domain. */ 20struct tomoyo_domain_info tomoyo_kernel_domain; 21 22/* The list for "struct tomoyo_domain_info". */ 23LIST_HEAD(tomoyo_domain_list); 24DECLARE_RWSEM(tomoyo_domain_list_lock); 25 26/* Structure for "initialize_domain" and "no_initialize_domain" keyword. */ 27struct tomoyo_domain_initializer_entry { 28 struct list_head list; 29 const struct tomoyo_path_info *domainname; /* This may be NULL */ 30 const struct tomoyo_path_info *program; 31 bool is_deleted; 32 bool is_not; /* True if this entry is "no_initialize_domain". */ 33 /* True if the domainname is tomoyo_get_last_name(). */ 34 bool is_last_name; 35}; 36 37/* Structure for "keep_domain" and "no_keep_domain" keyword. */ 38struct tomoyo_domain_keeper_entry { 39 struct list_head list; 40 const struct tomoyo_path_info *domainname; 41 const struct tomoyo_path_info *program; /* This may be NULL */ 42 bool is_deleted; 43 bool is_not; /* True if this entry is "no_keep_domain". */ 44 /* True if the domainname is tomoyo_get_last_name(). */ 45 bool is_last_name; 46}; 47 48/* Structure for "alias" keyword. */ 49struct tomoyo_alias_entry { 50 struct list_head list; 51 const struct tomoyo_path_info *original_name; 52 const struct tomoyo_path_info *aliased_name; 53 bool is_deleted; 54}; 55 56/** 57 * tomoyo_set_domain_flag - Set or clear domain's attribute flags. 58 * 59 * @domain: Pointer to "struct tomoyo_domain_info". 60 * @is_delete: True if it is a delete request. 61 * @flags: Flags to set or clear. 62 * 63 * Returns nothing. 64 */ 65void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, 66 const bool is_delete, const u8 flags) 67{ 68 /* We need to serialize because this is bitfield operation. */ 69 static DEFINE_SPINLOCK(lock); 70 /***** CRITICAL SECTION START *****/ 71 spin_lock(&lock); 72 if (!is_delete) 73 domain->flags |= flags; 74 else 75 domain->flags &= ~flags; 76 spin_unlock(&lock); 77 /***** CRITICAL SECTION END *****/ 78} 79 80/** 81 * tomoyo_get_last_name - Get last component of a domainname. 82 * 83 * @domain: Pointer to "struct tomoyo_domain_info". 84 * 85 * Returns the last component of the domainname. 86 */ 87const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) 88{ 89 const char *cp0 = domain->domainname->name; 90 const char *cp1 = strrchr(cp0, ' '); 91 92 if (cp1) 93 return cp1 + 1; 94 return cp0; 95} 96 97/* The list for "struct tomoyo_domain_initializer_entry". */ 98static LIST_HEAD(tomoyo_domain_initializer_list); 99static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock); 100 101/** 102 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. 103 * 104 * @domainname: The name of domain. May be NULL. 105 * @program: The name of program. 106 * @is_not: True if it is "no_initialize_domain" entry. 107 * @is_delete: True if it is a delete request. 108 * 109 * Returns 0 on success, negative value otherwise. 110 */ 111static int tomoyo_update_domain_initializer_entry(const char *domainname, 112 const char *program, 113 const bool is_not, 114 const bool is_delete) 115{ 116 struct tomoyo_domain_initializer_entry *new_entry; 117 struct tomoyo_domain_initializer_entry *ptr; 118 const struct tomoyo_path_info *saved_program; 119 const struct tomoyo_path_info *saved_domainname = NULL; 120 int error = -ENOMEM; 121 bool is_last_name = false; 122 123 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) 124 return -EINVAL; /* No patterns allowed. */ 125 if (domainname) { 126 if (!tomoyo_is_domain_def(domainname) && 127 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) 128 is_last_name = true; 129 else if (!tomoyo_is_correct_domain(domainname, __func__)) 130 return -EINVAL; 131 saved_domainname = tomoyo_save_name(domainname); 132 if (!saved_domainname) 133 return -ENOMEM; 134 } 135 saved_program = tomoyo_save_name(program); 136 if (!saved_program) 137 return -ENOMEM; 138 /***** EXCLUSIVE SECTION START *****/ 139 down_write(&tomoyo_domain_initializer_list_lock); 140 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { 141 if (ptr->is_not != is_not || 142 ptr->domainname != saved_domainname || 143 ptr->program != saved_program) 144 continue; 145 ptr->is_deleted = is_delete; 146 error = 0; 147 goto out; 148 } 149 if (is_delete) { 150 error = -ENOENT; 151 goto out; 152 } 153 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 154 if (!new_entry) 155 goto out; 156 new_entry->domainname = saved_domainname; 157 new_entry->program = saved_program; 158 new_entry->is_not = is_not; 159 new_entry->is_last_name = is_last_name; 160 list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list); 161 error = 0; 162 out: 163 up_write(&tomoyo_domain_initializer_list_lock); 164 /***** EXCLUSIVE SECTION END *****/ 165 return error; 166} 167 168/** 169 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list. 170 * 171 * @head: Pointer to "struct tomoyo_io_buffer". 172 * 173 * Returns true on success, false otherwise. 174 */ 175bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 176{ 177 struct list_head *pos; 178 bool done = true; 179 180 down_read(&tomoyo_domain_initializer_list_lock); 181 list_for_each_cookie(pos, head->read_var2, 182 &tomoyo_domain_initializer_list) { 183 const char *no; 184 const char *from = ""; 185 const char *domain = ""; 186 struct tomoyo_domain_initializer_entry *ptr; 187 ptr = list_entry(pos, struct tomoyo_domain_initializer_entry, 188 list); 189 if (ptr->is_deleted) 190 continue; 191 no = ptr->is_not ? "no_" : ""; 192 if (ptr->domainname) { 193 from = " from "; 194 domain = ptr->domainname->name; 195 } 196 if (!tomoyo_io_printf(head, 197 "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN 198 "%s%s%s\n", no, ptr->program->name, from, 199 domain)) { 200 done = false; 201 break; 202 } 203 } 204 up_read(&tomoyo_domain_initializer_list_lock); 205 return done; 206} 207 208/** 209 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list. 210 * 211 * @data: String to parse. 212 * @is_not: True if it is "no_initialize_domain" entry. 213 * @is_delete: True if it is a delete request. 214 * 215 * Returns 0 on success, negative value otherwise. 216 */ 217int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 218 const bool is_delete) 219{ 220 char *cp = strstr(data, " from "); 221 222 if (cp) { 223 *cp = '\0'; 224 return tomoyo_update_domain_initializer_entry(cp + 6, data, 225 is_not, 226 is_delete); 227 } 228 return tomoyo_update_domain_initializer_entry(NULL, data, is_not, 229 is_delete); 230} 231 232/** 233 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization. 234 * 235 * @domainname: The name of domain. 236 * @program: The name of program. 237 * @last_name: The last component of @domainname. 238 * 239 * Returns true if executing @program reinitializes domain transition, 240 * false otherwise. 241 */ 242static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * 243 domainname, 244 const struct tomoyo_path_info *program, 245 const struct tomoyo_path_info * 246 last_name) 247{ 248 struct tomoyo_domain_initializer_entry *ptr; 249 bool flag = false; 250 251 down_read(&tomoyo_domain_initializer_list_lock); 252 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { 253 if (ptr->is_deleted) 254 continue; 255 if (ptr->domainname) { 256 if (!ptr->is_last_name) { 257 if (ptr->domainname != domainname) 258 continue; 259 } else { 260 if (tomoyo_pathcmp(ptr->domainname, last_name)) 261 continue; 262 } 263 } 264 if (tomoyo_pathcmp(ptr->program, program)) 265 continue; 266 if (ptr->is_not) { 267 flag = false; 268 break; 269 } 270 flag = true; 271 } 272 up_read(&tomoyo_domain_initializer_list_lock); 273 return flag; 274} 275 276/* The list for "struct tomoyo_domain_keeper_entry". */ 277static LIST_HEAD(tomoyo_domain_keeper_list); 278static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock); 279 280/** 281 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. 282 * 283 * @domainname: The name of domain. 284 * @program: The name of program. May be NULL. 285 * @is_not: True if it is "no_keep_domain" entry. 286 * @is_delete: True if it is a delete request. 287 * 288 * Returns 0 on success, negative value otherwise. 289 */ 290static int tomoyo_update_domain_keeper_entry(const char *domainname, 291 const char *program, 292 const bool is_not, 293 const bool is_delete) 294{ 295 struct tomoyo_domain_keeper_entry *new_entry; 296 struct tomoyo_domain_keeper_entry *ptr; 297 const struct tomoyo_path_info *saved_domainname; 298 const struct tomoyo_path_info *saved_program = NULL; 299 static DEFINE_MUTEX(lock); 300 int error = -ENOMEM; 301 bool is_last_name = false; 302 303 if (!tomoyo_is_domain_def(domainname) && 304 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) 305 is_last_name = true; 306 else if (!tomoyo_is_correct_domain(domainname, __func__)) 307 return -EINVAL; 308 if (program) { 309 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) 310 return -EINVAL; 311 saved_program = tomoyo_save_name(program); 312 if (!saved_program) 313 return -ENOMEM; 314 } 315 saved_domainname = tomoyo_save_name(domainname); 316 if (!saved_domainname) 317 return -ENOMEM; 318 /***** EXCLUSIVE SECTION START *****/ 319 down_write(&tomoyo_domain_keeper_list_lock); 320 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { 321 if (ptr->is_not != is_not || 322 ptr->domainname != saved_domainname || 323 ptr->program != saved_program) 324 continue; 325 ptr->is_deleted = is_delete; 326 error = 0; 327 goto out; 328 } 329 if (is_delete) { 330 error = -ENOENT; 331 goto out; 332 } 333 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 334 if (!new_entry) 335 goto out; 336 new_entry->domainname = saved_domainname; 337 new_entry->program = saved_program; 338 new_entry->is_not = is_not; 339 new_entry->is_last_name = is_last_name; 340 list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list); 341 error = 0; 342 out: 343 up_write(&tomoyo_domain_keeper_list_lock); 344 /***** EXCLUSIVE SECTION END *****/ 345 return error; 346} 347 348/** 349 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list. 350 * 351 * @data: String to parse. 352 * @is_not: True if it is "no_keep_domain" entry. 353 * @is_delete: True if it is a delete request. 354 * 355 */ 356int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 357 const bool is_delete) 358{ 359 char *cp = strstr(data, " from "); 360 361 if (cp) { 362 *cp = '\0'; 363 return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not, 364 is_delete); 365 } 366 return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete); 367} 368 369/** 370 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list. 371 * 372 * @head: Pointer to "struct tomoyo_io_buffer". 373 * 374 * Returns true on success, false otherwise. 375 */ 376bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 377{ 378 struct list_head *pos; 379 bool done = true; 380 381 down_read(&tomoyo_domain_keeper_list_lock); 382 list_for_each_cookie(pos, head->read_var2, 383 &tomoyo_domain_keeper_list) { 384 struct tomoyo_domain_keeper_entry *ptr; 385 const char *no; 386 const char *from = ""; 387 const char *program = ""; 388 389 ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list); 390 if (ptr->is_deleted) 391 continue; 392 no = ptr->is_not ? "no_" : ""; 393 if (ptr->program) { 394 from = " from "; 395 program = ptr->program->name; 396 } 397 if (!tomoyo_io_printf(head, 398 "%s" TOMOYO_KEYWORD_KEEP_DOMAIN 399 "%s%s%s\n", no, program, from, 400 ptr->domainname->name)) { 401 done = false; 402 break; 403 } 404 } 405 up_read(&tomoyo_domain_keeper_list_lock); 406 return done; 407} 408 409/** 410 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression. 411 * 412 * @domainname: The name of domain. 413 * @program: The name of program. 414 * @last_name: The last component of @domainname. 415 * 416 * Returns true if executing @program supresses domain transition, 417 * false otherwise. 418 */ 419static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, 420 const struct tomoyo_path_info *program, 421 const struct tomoyo_path_info *last_name) 422{ 423 struct tomoyo_domain_keeper_entry *ptr; 424 bool flag = false; 425 426 down_read(&tomoyo_domain_keeper_list_lock); 427 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { 428 if (ptr->is_deleted) 429 continue; 430 if (!ptr->is_last_name) { 431 if (ptr->domainname != domainname) 432 continue; 433 } else { 434 if (tomoyo_pathcmp(ptr->domainname, last_name)) 435 continue; 436 } 437 if (ptr->program && tomoyo_pathcmp(ptr->program, program)) 438 continue; 439 if (ptr->is_not) { 440 flag = false; 441 break; 442 } 443 flag = true; 444 } 445 up_read(&tomoyo_domain_keeper_list_lock); 446 return flag; 447} 448 449/* The list for "struct tomoyo_alias_entry". */ 450static LIST_HEAD(tomoyo_alias_list); 451static DECLARE_RWSEM(tomoyo_alias_list_lock); 452 453/** 454 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. 455 * 456 * @original_name: The original program's real name. 457 * @aliased_name: The symbolic program's symbolic link's name. 458 * @is_delete: True if it is a delete request. 459 * 460 * Returns 0 on success, negative value otherwise. 461 */ 462static int tomoyo_update_alias_entry(const char *original_name, 463 const char *aliased_name, 464 const bool is_delete) 465{ 466 struct tomoyo_alias_entry *new_entry; 467 struct tomoyo_alias_entry *ptr; 468 const struct tomoyo_path_info *saved_original_name; 469 const struct tomoyo_path_info *saved_aliased_name; 470 int error = -ENOMEM; 471 472 if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || 473 !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) 474 return -EINVAL; /* No patterns allowed. */ 475 saved_original_name = tomoyo_save_name(original_name); 476 saved_aliased_name = tomoyo_save_name(aliased_name); 477 if (!saved_original_name || !saved_aliased_name) 478 return -ENOMEM; 479 /***** EXCLUSIVE SECTION START *****/ 480 down_write(&tomoyo_alias_list_lock); 481 list_for_each_entry(ptr, &tomoyo_alias_list, list) { 482 if (ptr->original_name != saved_original_name || 483 ptr->aliased_name != saved_aliased_name) 484 continue; 485 ptr->is_deleted = is_delete; 486 error = 0; 487 goto out; 488 } 489 if (is_delete) { 490 error = -ENOENT; 491 goto out; 492 } 493 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 494 if (!new_entry) 495 goto out; 496 new_entry->original_name = saved_original_name; 497 new_entry->aliased_name = saved_aliased_name; 498 list_add_tail(&new_entry->list, &tomoyo_alias_list); 499 error = 0; 500 out: 501 up_write(&tomoyo_alias_list_lock); 502 /***** EXCLUSIVE SECTION END *****/ 503 return error; 504} 505 506/** 507 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list. 508 * 509 * @head: Pointer to "struct tomoyo_io_buffer". 510 * 511 * Returns true on success, false otherwise. 512 */ 513bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) 514{ 515 struct list_head *pos; 516 bool done = true; 517 518 down_read(&tomoyo_alias_list_lock); 519 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { 520 struct tomoyo_alias_entry *ptr; 521 522 ptr = list_entry(pos, struct tomoyo_alias_entry, list); 523 if (ptr->is_deleted) 524 continue; 525 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n", 526 ptr->original_name->name, 527 ptr->aliased_name->name)) { 528 done = false; 529 break; 530 } 531 } 532 up_read(&tomoyo_alias_list_lock); 533 return done; 534} 535 536/** 537 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list. 538 * 539 * @data: String to parse. 540 * @is_delete: True if it is a delete request. 541 * 542 * Returns 0 on success, negative value otherwise. 543 */ 544int tomoyo_write_alias_policy(char *data, const bool is_delete) 545{ 546 char *cp = strchr(data, ' '); 547 548 if (!cp) 549 return -EINVAL; 550 *cp++ = '\0'; 551 return tomoyo_update_alias_entry(data, cp, is_delete); 552} 553 554/* Domain create/delete/undelete handler. */ 555 556/* #define TOMOYO_DEBUG_DOMAIN_UNDELETE */ 557 558/** 559 * tomoyo_delete_domain - Delete a domain. 560 * 561 * @domainname: The name of domain. 562 * 563 * Returns 0. 564 */ 565int tomoyo_delete_domain(char *domainname) 566{ 567 struct tomoyo_domain_info *domain; 568 struct tomoyo_path_info name; 569 570 name.name = domainname; 571 tomoyo_fill_path_info(&name); 572 /***** EXCLUSIVE SECTION START *****/ 573 down_write(&tomoyo_domain_list_lock); 574#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE 575 printk(KERN_DEBUG "tomoyo_delete_domain %s\n", domainname); 576 list_for_each_entry(domain, &tomoyo_domain_list, list) { 577 if (tomoyo_pathcmp(domain->domainname, &name)) 578 continue; 579 printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted); 580 } 581#endif 582 /* Is there an active domain? */ 583 list_for_each_entry(domain, &tomoyo_domain_list, list) { 584 struct tomoyo_domain_info *domain2; 585 /* Never delete tomoyo_kernel_domain */ 586 if (domain == &tomoyo_kernel_domain) 587 continue; 588 if (domain->is_deleted || 589 tomoyo_pathcmp(domain->domainname, &name)) 590 continue; 591 /* Mark already deleted domains as non undeletable. */ 592 list_for_each_entry(domain2, &tomoyo_domain_list, list) { 593 if (!domain2->is_deleted || 594 tomoyo_pathcmp(domain2->domainname, &name)) 595 continue; 596#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE 597 if (domain2->is_deleted != 255) 598 printk(KERN_DEBUG 599 "Marked %p as non undeletable\n", 600 domain2); 601#endif 602 domain2->is_deleted = 255; 603 } 604 /* Delete and mark active domain as undeletable. */ 605 domain->is_deleted = 1; 606#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE 607 printk(KERN_DEBUG "Marked %p as undeletable\n", domain); 608#endif 609 break; 610 } 611 up_write(&tomoyo_domain_list_lock); 612 /***** EXCLUSIVE SECTION END *****/ 613 return 0; 614} 615 616/** 617 * tomoyo_undelete_domain - Undelete a domain. 618 * 619 * @domainname: The name of domain. 620 * 621 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 622 */ 623struct tomoyo_domain_info *tomoyo_undelete_domain(const char *domainname) 624{ 625 struct tomoyo_domain_info *domain; 626 struct tomoyo_domain_info *candidate_domain = NULL; 627 struct tomoyo_path_info name; 628 629 name.name = domainname; 630 tomoyo_fill_path_info(&name); 631 /***** EXCLUSIVE SECTION START *****/ 632 down_write(&tomoyo_domain_list_lock); 633#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE 634 printk(KERN_DEBUG "tomoyo_undelete_domain %s\n", domainname); 635 list_for_each_entry(domain, &tomoyo_domain_list, list) { 636 if (tomoyo_pathcmp(domain->domainname, &name)) 637 continue; 638 printk(KERN_DEBUG "List: %p %u\n", domain, domain->is_deleted); 639 } 640#endif 641 list_for_each_entry(domain, &tomoyo_domain_list, list) { 642 if (tomoyo_pathcmp(&name, domain->domainname)) 643 continue; 644 if (!domain->is_deleted) { 645 /* This domain is active. I can't undelete. */ 646 candidate_domain = NULL; 647#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE 648 printk(KERN_DEBUG "%p is active. I can't undelete.\n", 649 domain); 650#endif 651 break; 652 } 653 /* Is this domain undeletable? */ 654 if (domain->is_deleted == 1) 655 candidate_domain = domain; 656 } 657 if (candidate_domain) { 658 candidate_domain->is_deleted = 0; 659#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE 660 printk(KERN_DEBUG "%p was undeleted.\n", candidate_domain); 661#endif 662 } 663 up_write(&tomoyo_domain_list_lock); 664 /***** EXCLUSIVE SECTION END *****/ 665 return candidate_domain; 666} 667 668/** 669 * tomoyo_find_or_assign_new_domain - Create a domain. 670 * 671 * @domainname: The name of domain. 672 * @profile: Profile number to assign if the domain was newly created. 673 * 674 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 675 */ 676struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 677 domainname, 678 const u8 profile) 679{ 680 struct tomoyo_domain_info *domain = NULL; 681 const struct tomoyo_path_info *saved_domainname; 682 683 /***** EXCLUSIVE SECTION START *****/ 684 down_write(&tomoyo_domain_list_lock); 685 domain = tomoyo_find_domain(domainname); 686 if (domain) 687 goto out; 688 if (!tomoyo_is_correct_domain(domainname, __func__)) 689 goto out; 690 saved_domainname = tomoyo_save_name(domainname); 691 if (!saved_domainname) 692 goto out; 693 /* Can I reuse memory of deleted domain? */ 694 list_for_each_entry(domain, &tomoyo_domain_list, list) { 695 struct task_struct *p; 696 struct tomoyo_acl_info *ptr; 697 bool flag; 698 if (!domain->is_deleted || 699 domain->domainname != saved_domainname) 700 continue; 701 flag = false; 702 /***** CRITICAL SECTION START *****/ 703 read_lock(&tasklist_lock); 704 for_each_process(p) { 705 if (tomoyo_real_domain(p) != domain) 706 continue; 707 flag = true; 708 break; 709 } 710 read_unlock(&tasklist_lock); 711 /***** CRITICAL SECTION END *****/ 712 if (flag) 713 continue; 714#ifdef TOMOYO_DEBUG_DOMAIN_UNDELETE 715 printk(KERN_DEBUG "Reusing %p %s\n", domain, 716 domain->domainname->name); 717#endif 718 list_for_each_entry(ptr, &domain->acl_info_list, list) { 719 ptr->type |= TOMOYO_ACL_DELETED; 720 } 721 tomoyo_set_domain_flag(domain, true, domain->flags); 722 domain->profile = profile; 723 domain->quota_warned = false; 724 mb(); /* Avoid out-of-order execution. */ 725 domain->is_deleted = 0; 726 goto out; 727 } 728 /* No memory reusable. Create using new memory. */ 729 domain = tomoyo_alloc_element(sizeof(*domain)); 730 if (domain) { 731 INIT_LIST_HEAD(&domain->acl_info_list); 732 domain->domainname = saved_domainname; 733 domain->profile = profile; 734 list_add_tail(&domain->list, &tomoyo_domain_list); 735 } 736 out: 737 up_write(&tomoyo_domain_list_lock); 738 /***** EXCLUSIVE SECTION END *****/ 739 return domain; 740} 741 742/** 743 * tomoyo_find_next_domain - Find a domain. 744 * 745 * @bprm: Pointer to "struct linux_binprm". 746 * @next_domain: Pointer to pointer to "struct tomoyo_domain_info". 747 * 748 * Returns 0 on success, negative value otherwise. 749 */ 750int tomoyo_find_next_domain(struct linux_binprm *bprm, 751 struct tomoyo_domain_info **next_domain) 752{ 753 /* 754 * This function assumes that the size of buffer returned by 755 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. 756 */ 757 struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp)); 758 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 759 struct tomoyo_domain_info *domain = NULL; 760 const char *old_domain_name = old_domain->domainname->name; 761 const char *original_name = bprm->filename; 762 char *new_domain_name = NULL; 763 char *real_program_name = NULL; 764 char *symlink_program_name = NULL; 765 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); 766 const bool is_enforce = (mode == 3); 767 int retval = -ENOMEM; 768 struct tomoyo_path_info r; /* real name */ 769 struct tomoyo_path_info s; /* symlink name */ 770 struct tomoyo_path_info l; /* last name */ 771 static bool initialized; 772 773 if (!tmp) 774 goto out; 775 776 if (!initialized) { 777 /* 778 * Built-in initializers. This is needed because policies are 779 * not loaded until starting /sbin/init. 780 */ 781 tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug", 782 false, false); 783 tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe", 784 false, false); 785 initialized = true; 786 } 787 788 /* Get tomoyo_realpath of program. */ 789 retval = -ENOENT; 790 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ 791 real_program_name = tomoyo_realpath(original_name); 792 if (!real_program_name) 793 goto out; 794 /* Get tomoyo_realpath of symbolic link. */ 795 symlink_program_name = tomoyo_realpath_nofollow(original_name); 796 if (!symlink_program_name) 797 goto out; 798 799 r.name = real_program_name; 800 tomoyo_fill_path_info(&r); 801 s.name = symlink_program_name; 802 tomoyo_fill_path_info(&s); 803 l.name = tomoyo_get_last_name(old_domain); 804 tomoyo_fill_path_info(&l); 805 806 /* Check 'alias' directive. */ 807 if (tomoyo_pathcmp(&r, &s)) { 808 struct tomoyo_alias_entry *ptr; 809 /* Is this program allowed to be called via symbolic links? */ 810 down_read(&tomoyo_alias_list_lock); 811 list_for_each_entry(ptr, &tomoyo_alias_list, list) { 812 if (ptr->is_deleted || 813 tomoyo_pathcmp(&r, ptr->original_name) || 814 tomoyo_pathcmp(&s, ptr->aliased_name)) 815 continue; 816 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); 817 strncpy(real_program_name, ptr->aliased_name->name, 818 TOMOYO_MAX_PATHNAME_LEN - 1); 819 tomoyo_fill_path_info(&r); 820 break; 821 } 822 up_read(&tomoyo_alias_list_lock); 823 } 824 825 /* Check execute permission. */ 826 retval = tomoyo_check_exec_perm(old_domain, &r, tmp); 827 if (retval < 0) 828 goto out; 829 830 new_domain_name = tmp->buffer; 831 if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) { 832 /* Transit to the child of tomoyo_kernel_domain domain. */ 833 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 834 TOMOYO_ROOT_NAME " " "%s", real_program_name); 835 } else if (old_domain == &tomoyo_kernel_domain && 836 !tomoyo_policy_loaded) { 837 /* 838 * Needn't to transit from kernel domain before starting 839 * /sbin/init. But transit from kernel domain if executing 840 * initializers because they might start before /sbin/init. 841 */ 842 domain = old_domain; 843 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) { 844 /* Keep current domain. */ 845 domain = old_domain; 846 } else { 847 /* Normal domain transition. */ 848 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 849 "%s %s", old_domain_name, real_program_name); 850 } 851 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) 852 goto done; 853 down_read(&tomoyo_domain_list_lock); 854 domain = tomoyo_find_domain(new_domain_name); 855 up_read(&tomoyo_domain_list_lock); 856 if (domain) 857 goto done; 858 if (is_enforce) 859 goto done; 860 domain = tomoyo_find_or_assign_new_domain(new_domain_name, 861 old_domain->profile); 862 done: 863 if (domain) 864 goto out; 865 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", 866 new_domain_name); 867 if (is_enforce) 868 retval = -EPERM; 869 else 870 tomoyo_set_domain_flag(old_domain, false, 871 TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); 872 out: 873 tomoyo_free(real_program_name); 874 tomoyo_free(symlink_program_name); 875 *next_domain = domain ? domain : old_domain; 876 tomoyo_free(tmp); 877 return retval; 878} 879