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. */ 20 struct tomoyo_domain_info tomoyo_kernel_domain; 21 22 /* The list for "struct tomoyo_domain_info". */ 23 LIST_HEAD(tomoyo_domain_list); 24 DECLARE_RWSEM(tomoyo_domain_list_lock); 25 26 /* Structure for "initialize_domain" and "no_initialize_domain" keyword. */ 27 struct 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. */ 38 struct 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. */ 49 struct 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 */ 65 void 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 */ 87 const 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". */ 98 static LIST_HEAD(tomoyo_domain_initializer_list); 99 static 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 */ 111 static 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 */ 175 bool 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 */ 217 int 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 */ 242 static 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". */ 277 static LIST_HEAD(tomoyo_domain_keeper_list); 278 static 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 */ 290 static 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 */ 356 int 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 */ 376 bool 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 */ 419 static 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". */ 450 static LIST_HEAD(tomoyo_alias_list); 451 static 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 */ 462 static 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 */ 513 bool 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 */ 544 int 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 handler. */ 555 556 /** 557 * tomoyo_delete_domain - Delete a domain. 558 * 559 * @domainname: The name of domain. 560 * 561 * Returns 0. 562 */ 563 int tomoyo_delete_domain(char *domainname) 564 { 565 struct tomoyo_domain_info *domain; 566 struct tomoyo_path_info name; 567 568 name.name = domainname; 569 tomoyo_fill_path_info(&name); 570 /***** EXCLUSIVE SECTION START *****/ 571 down_write(&tomoyo_domain_list_lock); 572 /* Is there an active domain? */ 573 list_for_each_entry(domain, &tomoyo_domain_list, list) { 574 /* Never delete tomoyo_kernel_domain */ 575 if (domain == &tomoyo_kernel_domain) 576 continue; 577 if (domain->is_deleted || 578 tomoyo_pathcmp(domain->domainname, &name)) 579 continue; 580 domain->is_deleted = true; 581 break; 582 } 583 up_write(&tomoyo_domain_list_lock); 584 /***** EXCLUSIVE SECTION END *****/ 585 return 0; 586 } 587 588 /** 589 * tomoyo_find_or_assign_new_domain - Create a domain. 590 * 591 * @domainname: The name of domain. 592 * @profile: Profile number to assign if the domain was newly created. 593 * 594 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 595 */ 596 struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 597 domainname, 598 const u8 profile) 599 { 600 struct tomoyo_domain_info *domain = NULL; 601 const struct tomoyo_path_info *saved_domainname; 602 603 /***** EXCLUSIVE SECTION START *****/ 604 down_write(&tomoyo_domain_list_lock); 605 domain = tomoyo_find_domain(domainname); 606 if (domain) 607 goto out; 608 if (!tomoyo_is_correct_domain(domainname, __func__)) 609 goto out; 610 saved_domainname = tomoyo_save_name(domainname); 611 if (!saved_domainname) 612 goto out; 613 /* Can I reuse memory of deleted domain? */ 614 list_for_each_entry(domain, &tomoyo_domain_list, list) { 615 struct task_struct *p; 616 struct tomoyo_acl_info *ptr; 617 bool flag; 618 if (!domain->is_deleted || 619 domain->domainname != saved_domainname) 620 continue; 621 flag = false; 622 /***** CRITICAL SECTION START *****/ 623 read_lock(&tasklist_lock); 624 for_each_process(p) { 625 if (tomoyo_real_domain(p) != domain) 626 continue; 627 flag = true; 628 break; 629 } 630 read_unlock(&tasklist_lock); 631 /***** CRITICAL SECTION END *****/ 632 if (flag) 633 continue; 634 list_for_each_entry(ptr, &domain->acl_info_list, list) { 635 ptr->type |= TOMOYO_ACL_DELETED; 636 } 637 tomoyo_set_domain_flag(domain, true, domain->flags); 638 domain->profile = profile; 639 domain->quota_warned = false; 640 mb(); /* Avoid out-of-order execution. */ 641 domain->is_deleted = false; 642 goto out; 643 } 644 /* No memory reusable. Create using new memory. */ 645 domain = tomoyo_alloc_element(sizeof(*domain)); 646 if (domain) { 647 INIT_LIST_HEAD(&domain->acl_info_list); 648 domain->domainname = saved_domainname; 649 domain->profile = profile; 650 list_add_tail(&domain->list, &tomoyo_domain_list); 651 } 652 out: 653 up_write(&tomoyo_domain_list_lock); 654 /***** EXCLUSIVE SECTION END *****/ 655 return domain; 656 } 657 658 /** 659 * tomoyo_find_next_domain - Find a domain. 660 * 661 * @bprm: Pointer to "struct linux_binprm". 662 * @next_domain: Pointer to pointer to "struct tomoyo_domain_info". 663 * 664 * Returns 0 on success, negative value otherwise. 665 */ 666 int tomoyo_find_next_domain(struct linux_binprm *bprm, 667 struct tomoyo_domain_info **next_domain) 668 { 669 /* 670 * This function assumes that the size of buffer returned by 671 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. 672 */ 673 struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp)); 674 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 675 struct tomoyo_domain_info *domain = NULL; 676 const char *old_domain_name = old_domain->domainname->name; 677 const char *original_name = bprm->filename; 678 char *new_domain_name = NULL; 679 char *real_program_name = NULL; 680 char *symlink_program_name = NULL; 681 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); 682 const bool is_enforce = (mode == 3); 683 int retval = -ENOMEM; 684 struct tomoyo_path_info r; /* real name */ 685 struct tomoyo_path_info s; /* symlink name */ 686 struct tomoyo_path_info l; /* last name */ 687 static bool initialized; 688 689 if (!tmp) 690 goto out; 691 692 if (!initialized) { 693 /* 694 * Built-in initializers. This is needed because policies are 695 * not loaded until starting /sbin/init. 696 */ 697 tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug", 698 false, false); 699 tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe", 700 false, false); 701 initialized = true; 702 } 703 704 /* Get tomoyo_realpath of program. */ 705 retval = -ENOENT; 706 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ 707 real_program_name = tomoyo_realpath(original_name); 708 if (!real_program_name) 709 goto out; 710 /* Get tomoyo_realpath of symbolic link. */ 711 symlink_program_name = tomoyo_realpath_nofollow(original_name); 712 if (!symlink_program_name) 713 goto out; 714 715 r.name = real_program_name; 716 tomoyo_fill_path_info(&r); 717 s.name = symlink_program_name; 718 tomoyo_fill_path_info(&s); 719 l.name = tomoyo_get_last_name(old_domain); 720 tomoyo_fill_path_info(&l); 721 722 /* Check 'alias' directive. */ 723 if (tomoyo_pathcmp(&r, &s)) { 724 struct tomoyo_alias_entry *ptr; 725 /* Is this program allowed to be called via symbolic links? */ 726 down_read(&tomoyo_alias_list_lock); 727 list_for_each_entry(ptr, &tomoyo_alias_list, list) { 728 if (ptr->is_deleted || 729 tomoyo_pathcmp(&r, ptr->original_name) || 730 tomoyo_pathcmp(&s, ptr->aliased_name)) 731 continue; 732 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); 733 strncpy(real_program_name, ptr->aliased_name->name, 734 TOMOYO_MAX_PATHNAME_LEN - 1); 735 tomoyo_fill_path_info(&r); 736 break; 737 } 738 up_read(&tomoyo_alias_list_lock); 739 } 740 741 /* Check execute permission. */ 742 retval = tomoyo_check_exec_perm(old_domain, &r, tmp); 743 if (retval < 0) 744 goto out; 745 746 new_domain_name = tmp->buffer; 747 if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) { 748 /* Transit to the child of tomoyo_kernel_domain domain. */ 749 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 750 TOMOYO_ROOT_NAME " " "%s", real_program_name); 751 } else if (old_domain == &tomoyo_kernel_domain && 752 !tomoyo_policy_loaded) { 753 /* 754 * Needn't to transit from kernel domain before starting 755 * /sbin/init. But transit from kernel domain if executing 756 * initializers because they might start before /sbin/init. 757 */ 758 domain = old_domain; 759 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) { 760 /* Keep current domain. */ 761 domain = old_domain; 762 } else { 763 /* Normal domain transition. */ 764 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 765 "%s %s", old_domain_name, real_program_name); 766 } 767 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) 768 goto done; 769 down_read(&tomoyo_domain_list_lock); 770 domain = tomoyo_find_domain(new_domain_name); 771 up_read(&tomoyo_domain_list_lock); 772 if (domain) 773 goto done; 774 if (is_enforce) 775 goto done; 776 domain = tomoyo_find_or_assign_new_domain(new_domain_name, 777 old_domain->profile); 778 done: 779 if (domain) 780 goto out; 781 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", 782 new_domain_name); 783 if (is_enforce) 784 retval = -EPERM; 785 else 786 tomoyo_set_domain_flag(old_domain, false, 787 TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); 788 out: 789 tomoyo_free(real_program_name); 790 tomoyo_free(symlink_program_name); 791 *next_domain = domain ? domain : old_domain; 792 tomoyo_free(tmp); 793 return retval; 794 } 795