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