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 <linux/binfmts.h> 14 #include <linux/slab.h> 15 16 /* Variables definitions.*/ 17 18 /* The initial domain. */ 19 struct tomoyo_domain_info tomoyo_kernel_domain; 20 21 /* 22 * tomoyo_domain_list is used for holding list of domains. 23 * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding 24 * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain. 25 * 26 * An entry is added by 27 * 28 * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \ 29 * /sys/kernel/security/tomoyo/domain_policy 30 * 31 * and is deleted by 32 * 33 * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \ 34 * /sys/kernel/security/tomoyo/domain_policy 35 * 36 * and all entries are retrieved by 37 * 38 * # cat /sys/kernel/security/tomoyo/domain_policy 39 * 40 * A domain is added by 41 * 42 * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy 43 * 44 * and is deleted by 45 * 46 * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy 47 * 48 * and all domains are retrieved by 49 * 50 * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy 51 * 52 * Normally, a domainname is monotonically getting longer because a domainname 53 * which the process will belong to if an execve() operation succeeds is 54 * defined as a concatenation of "current domainname" + "pathname passed to 55 * execve()". 56 * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for 57 * exceptions. 58 */ 59 LIST_HEAD(tomoyo_domain_list); 60 61 /** 62 * tomoyo_get_last_name - Get last component of a domainname. 63 * 64 * @domain: Pointer to "struct tomoyo_domain_info". 65 * 66 * Returns the last component of the domainname. 67 */ 68 const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) 69 { 70 const char *cp0 = domain->domainname->name; 71 const char *cp1 = strrchr(cp0, ' '); 72 73 if (cp1) 74 return cp1 + 1; 75 return cp0; 76 } 77 78 /* 79 * tomoyo_domain_initializer_list is used for holding list of programs which 80 * triggers reinitialization of domainname. Normally, a domainname is 81 * monotonically getting longer. But sometimes, we restart daemon programs. 82 * It would be convenient for us that "a daemon started upon system boot" and 83 * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO 84 * provides a way to shorten domainnames. 85 * 86 * An entry is added by 87 * 88 * # echo 'initialize_domain /usr/sbin/httpd' > \ 89 * /sys/kernel/security/tomoyo/exception_policy 90 * 91 * and is deleted by 92 * 93 * # echo 'delete initialize_domain /usr/sbin/httpd' > \ 94 * /sys/kernel/security/tomoyo/exception_policy 95 * 96 * and all entries are retrieved by 97 * 98 * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy 99 * 100 * In the example above, /usr/sbin/httpd will belong to 101 * "<kernel> /usr/sbin/httpd" domain. 102 * 103 * You may specify a domainname using "from" keyword. 104 * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd" 105 * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd" 106 * domain to belong to "<kernel> /usr/sbin/httpd" domain. 107 * 108 * You may add "no_" prefix to "initialize_domain". 109 * "initialize_domain /usr/sbin/httpd" and 110 * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd" 111 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain 112 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain. 113 */ 114 LIST_HEAD(tomoyo_domain_initializer_list); 115 116 /** 117 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. 118 * 119 * @domainname: The name of domain. May be NULL. 120 * @program: The name of program. 121 * @is_not: True if it is "no_initialize_domain" entry. 122 * @is_delete: True if it is a delete request. 123 * 124 * Returns 0 on success, negative value otherwise. 125 * 126 * Caller holds tomoyo_read_lock(). 127 */ 128 static int tomoyo_update_domain_initializer_entry(const char *domainname, 129 const char *program, 130 const bool is_not, 131 const bool is_delete) 132 { 133 struct tomoyo_domain_initializer_entry *entry = NULL; 134 struct tomoyo_domain_initializer_entry *ptr; 135 const struct tomoyo_path_info *saved_program = NULL; 136 const struct tomoyo_path_info *saved_domainname = NULL; 137 int error = is_delete ? -ENOENT : -ENOMEM; 138 bool is_last_name = false; 139 140 if (!tomoyo_is_correct_path(program, 1, -1, -1)) 141 return -EINVAL; /* No patterns allowed. */ 142 if (domainname) { 143 if (!tomoyo_is_domain_def(domainname) && 144 tomoyo_is_correct_path(domainname, 1, -1, -1)) 145 is_last_name = true; 146 else if (!tomoyo_is_correct_domain(domainname)) 147 return -EINVAL; 148 saved_domainname = tomoyo_get_name(domainname); 149 if (!saved_domainname) 150 goto out; 151 } 152 saved_program = tomoyo_get_name(program); 153 if (!saved_program) 154 goto out; 155 if (!is_delete) 156 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 157 mutex_lock(&tomoyo_policy_lock); 158 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { 159 if (ptr->is_not != is_not || 160 ptr->domainname != saved_domainname || 161 ptr->program != saved_program) 162 continue; 163 ptr->is_deleted = is_delete; 164 error = 0; 165 break; 166 } 167 if (!is_delete && error && tomoyo_memory_ok(entry)) { 168 entry->domainname = saved_domainname; 169 saved_domainname = NULL; 170 entry->program = saved_program; 171 saved_program = NULL; 172 entry->is_not = is_not; 173 entry->is_last_name = is_last_name; 174 list_add_tail_rcu(&entry->list, 175 &tomoyo_domain_initializer_list); 176 entry = NULL; 177 error = 0; 178 } 179 mutex_unlock(&tomoyo_policy_lock); 180 out: 181 tomoyo_put_name(saved_domainname); 182 tomoyo_put_name(saved_program); 183 kfree(entry); 184 return error; 185 } 186 187 /** 188 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list. 189 * 190 * @head: Pointer to "struct tomoyo_io_buffer". 191 * 192 * Returns true on success, false otherwise. 193 * 194 * Caller holds tomoyo_read_lock(). 195 */ 196 bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 197 { 198 struct list_head *pos; 199 bool done = true; 200 201 list_for_each_cookie(pos, head->read_var2, 202 &tomoyo_domain_initializer_list) { 203 const char *no; 204 const char *from = ""; 205 const char *domain = ""; 206 struct tomoyo_domain_initializer_entry *ptr; 207 ptr = list_entry(pos, struct tomoyo_domain_initializer_entry, 208 list); 209 if (ptr->is_deleted) 210 continue; 211 no = ptr->is_not ? "no_" : ""; 212 if (ptr->domainname) { 213 from = " from "; 214 domain = ptr->domainname->name; 215 } 216 done = tomoyo_io_printf(head, 217 "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN 218 "%s%s%s\n", no, ptr->program->name, 219 from, domain); 220 if (!done) 221 break; 222 } 223 return done; 224 } 225 226 /** 227 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list. 228 * 229 * @data: String to parse. 230 * @is_not: True if it is "no_initialize_domain" entry. 231 * @is_delete: True if it is a delete request. 232 * 233 * Returns 0 on success, negative value otherwise. 234 * 235 * Caller holds tomoyo_read_lock(). 236 */ 237 int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 238 const bool is_delete) 239 { 240 char *cp = strstr(data, " from "); 241 242 if (cp) { 243 *cp = '\0'; 244 return tomoyo_update_domain_initializer_entry(cp + 6, data, 245 is_not, 246 is_delete); 247 } 248 return tomoyo_update_domain_initializer_entry(NULL, data, is_not, 249 is_delete); 250 } 251 252 /** 253 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization. 254 * 255 * @domainname: The name of domain. 256 * @program: The name of program. 257 * @last_name: The last component of @domainname. 258 * 259 * Returns true if executing @program reinitializes domain transition, 260 * false otherwise. 261 * 262 * Caller holds tomoyo_read_lock(). 263 */ 264 static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * 265 domainname, 266 const struct tomoyo_path_info *program, 267 const struct tomoyo_path_info * 268 last_name) 269 { 270 struct tomoyo_domain_initializer_entry *ptr; 271 bool flag = false; 272 273 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { 274 if (ptr->is_deleted) 275 continue; 276 if (ptr->domainname) { 277 if (!ptr->is_last_name) { 278 if (ptr->domainname != domainname) 279 continue; 280 } else { 281 if (tomoyo_pathcmp(ptr->domainname, last_name)) 282 continue; 283 } 284 } 285 if (tomoyo_pathcmp(ptr->program, program)) 286 continue; 287 if (ptr->is_not) { 288 flag = false; 289 break; 290 } 291 flag = true; 292 } 293 return flag; 294 } 295 296 /* 297 * tomoyo_domain_keeper_list is used for holding list of domainnames which 298 * suppresses domain transition. Normally, a domainname is monotonically 299 * getting longer. But sometimes, we want to suppress domain transition. 300 * It would be convenient for us that programs executed from a login session 301 * belong to the same domain. Thus, TOMOYO provides a way to suppress domain 302 * transition. 303 * 304 * An entry is added by 305 * 306 * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \ 307 * /sys/kernel/security/tomoyo/exception_policy 308 * 309 * and is deleted by 310 * 311 * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \ 312 * /sys/kernel/security/tomoyo/exception_policy 313 * 314 * and all entries are retrieved by 315 * 316 * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy 317 * 318 * In the example above, any process which belongs to 319 * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain, 320 * unless explicitly specified by "initialize_domain" or "no_keep_domain". 321 * 322 * You may specify a program using "from" keyword. 323 * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash" 324 * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash" 325 * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain. 326 * 327 * You may add "no_" prefix to "keep_domain". 328 * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and 329 * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will 330 * cause "/usr/bin/passwd" to belong to 331 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless 332 * explicitly specified by "initialize_domain". 333 */ 334 LIST_HEAD(tomoyo_domain_keeper_list); 335 336 /** 337 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. 338 * 339 * @domainname: The name of domain. 340 * @program: The name of program. May be NULL. 341 * @is_not: True if it is "no_keep_domain" entry. 342 * @is_delete: True if it is a delete request. 343 * 344 * Returns 0 on success, negative value otherwise. 345 * 346 * Caller holds tomoyo_read_lock(). 347 */ 348 static int tomoyo_update_domain_keeper_entry(const char *domainname, 349 const char *program, 350 const bool is_not, 351 const bool is_delete) 352 { 353 struct tomoyo_domain_keeper_entry *entry = NULL; 354 struct tomoyo_domain_keeper_entry *ptr; 355 const struct tomoyo_path_info *saved_domainname = NULL; 356 const struct tomoyo_path_info *saved_program = NULL; 357 int error = is_delete ? -ENOENT : -ENOMEM; 358 bool is_last_name = false; 359 360 if (!tomoyo_is_domain_def(domainname) && 361 tomoyo_is_correct_path(domainname, 1, -1, -1)) 362 is_last_name = true; 363 else if (!tomoyo_is_correct_domain(domainname)) 364 return -EINVAL; 365 if (program) { 366 if (!tomoyo_is_correct_path(program, 1, -1, -1)) 367 return -EINVAL; 368 saved_program = tomoyo_get_name(program); 369 if (!saved_program) 370 goto out; 371 } 372 saved_domainname = tomoyo_get_name(domainname); 373 if (!saved_domainname) 374 goto out; 375 if (!is_delete) 376 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 377 mutex_lock(&tomoyo_policy_lock); 378 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 379 if (ptr->is_not != is_not || 380 ptr->domainname != saved_domainname || 381 ptr->program != saved_program) 382 continue; 383 ptr->is_deleted = is_delete; 384 error = 0; 385 break; 386 } 387 if (!is_delete && error && tomoyo_memory_ok(entry)) { 388 entry->domainname = saved_domainname; 389 saved_domainname = NULL; 390 entry->program = saved_program; 391 saved_program = NULL; 392 entry->is_not = is_not; 393 entry->is_last_name = is_last_name; 394 list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); 395 entry = NULL; 396 error = 0; 397 } 398 mutex_unlock(&tomoyo_policy_lock); 399 out: 400 tomoyo_put_name(saved_domainname); 401 tomoyo_put_name(saved_program); 402 kfree(entry); 403 return error; 404 } 405 406 /** 407 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list. 408 * 409 * @data: String to parse. 410 * @is_not: True if it is "no_keep_domain" entry. 411 * @is_delete: True if it is a delete request. 412 * 413 * Caller holds tomoyo_read_lock(). 414 */ 415 int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 416 const bool is_delete) 417 { 418 char *cp = strstr(data, " from "); 419 420 if (cp) { 421 *cp = '\0'; 422 return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not, 423 is_delete); 424 } 425 return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete); 426 } 427 428 /** 429 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list. 430 * 431 * @head: Pointer to "struct tomoyo_io_buffer". 432 * 433 * Returns true on success, false otherwise. 434 * 435 * Caller holds tomoyo_read_lock(). 436 */ 437 bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 438 { 439 struct list_head *pos; 440 bool done = true; 441 442 list_for_each_cookie(pos, head->read_var2, 443 &tomoyo_domain_keeper_list) { 444 struct tomoyo_domain_keeper_entry *ptr; 445 const char *no; 446 const char *from = ""; 447 const char *program = ""; 448 449 ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list); 450 if (ptr->is_deleted) 451 continue; 452 no = ptr->is_not ? "no_" : ""; 453 if (ptr->program) { 454 from = " from "; 455 program = ptr->program->name; 456 } 457 done = tomoyo_io_printf(head, 458 "%s" TOMOYO_KEYWORD_KEEP_DOMAIN 459 "%s%s%s\n", no, program, from, 460 ptr->domainname->name); 461 if (!done) 462 break; 463 } 464 return done; 465 } 466 467 /** 468 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression. 469 * 470 * @domainname: The name of domain. 471 * @program: The name of program. 472 * @last_name: The last component of @domainname. 473 * 474 * Returns true if executing @program supresses domain transition, 475 * false otherwise. 476 * 477 * Caller holds tomoyo_read_lock(). 478 */ 479 static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, 480 const struct tomoyo_path_info *program, 481 const struct tomoyo_path_info *last_name) 482 { 483 struct tomoyo_domain_keeper_entry *ptr; 484 bool flag = false; 485 486 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 487 if (ptr->is_deleted) 488 continue; 489 if (!ptr->is_last_name) { 490 if (ptr->domainname != domainname) 491 continue; 492 } else { 493 if (tomoyo_pathcmp(ptr->domainname, last_name)) 494 continue; 495 } 496 if (ptr->program && tomoyo_pathcmp(ptr->program, program)) 497 continue; 498 if (ptr->is_not) { 499 flag = false; 500 break; 501 } 502 flag = true; 503 } 504 return flag; 505 } 506 507 /* 508 * tomoyo_alias_list is used for holding list of symlink's pathnames which are 509 * allowed to be passed to an execve() request. Normally, the domainname which 510 * the current process will belong to after execve() succeeds is calculated 511 * using dereferenced pathnames. But some programs behave differently depending 512 * on the name passed to argv[0]. For busybox, calculating domainname using 513 * dereferenced pathnames will cause all programs in the busybox to belong to 514 * the same domain. Thus, TOMOYO provides a way to allow use of symlink's 515 * pathname for checking execve()'s permission and calculating domainname which 516 * the current process will belong to after execve() succeeds. 517 * 518 * An entry is added by 519 * 520 * # echo 'alias /bin/busybox /bin/cat' > \ 521 * /sys/kernel/security/tomoyo/exception_policy 522 * 523 * and is deleted by 524 * 525 * # echo 'delete alias /bin/busybox /bin/cat' > \ 526 * /sys/kernel/security/tomoyo/exception_policy 527 * 528 * and all entries are retrieved by 529 * 530 * # grep ^alias /sys/kernel/security/tomoyo/exception_policy 531 * 532 * In the example above, if /bin/cat is a symlink to /bin/busybox and execution 533 * of /bin/cat is requested, permission is checked for /bin/cat rather than 534 * /bin/busybox and domainname which the current process will belong to after 535 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . 536 */ 537 LIST_HEAD(tomoyo_alias_list); 538 539 /** 540 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. 541 * 542 * @original_name: The original program's real name. 543 * @aliased_name: The symbolic program's symbolic link's name. 544 * @is_delete: True if it is a delete request. 545 * 546 * Returns 0 on success, negative value otherwise. 547 * 548 * Caller holds tomoyo_read_lock(). 549 */ 550 static int tomoyo_update_alias_entry(const char *original_name, 551 const char *aliased_name, 552 const bool is_delete) 553 { 554 struct tomoyo_alias_entry *entry = NULL; 555 struct tomoyo_alias_entry *ptr; 556 const struct tomoyo_path_info *saved_original_name; 557 const struct tomoyo_path_info *saved_aliased_name; 558 int error = is_delete ? -ENOENT : -ENOMEM; 559 560 if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || 561 !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) 562 return -EINVAL; /* No patterns allowed. */ 563 saved_original_name = tomoyo_get_name(original_name); 564 saved_aliased_name = tomoyo_get_name(aliased_name); 565 if (!saved_original_name || !saved_aliased_name) 566 goto out; 567 if (!is_delete) 568 entry = kmalloc(sizeof(*entry), GFP_KERNEL); 569 mutex_lock(&tomoyo_policy_lock); 570 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 571 if (ptr->original_name != saved_original_name || 572 ptr->aliased_name != saved_aliased_name) 573 continue; 574 ptr->is_deleted = is_delete; 575 error = 0; 576 break; 577 } 578 if (!is_delete && error && tomoyo_memory_ok(entry)) { 579 entry->original_name = saved_original_name; 580 saved_original_name = NULL; 581 entry->aliased_name = saved_aliased_name; 582 saved_aliased_name = NULL; 583 list_add_tail_rcu(&entry->list, &tomoyo_alias_list); 584 entry = NULL; 585 error = 0; 586 } 587 mutex_unlock(&tomoyo_policy_lock); 588 out: 589 tomoyo_put_name(saved_original_name); 590 tomoyo_put_name(saved_aliased_name); 591 kfree(entry); 592 return error; 593 } 594 595 /** 596 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list. 597 * 598 * @head: Pointer to "struct tomoyo_io_buffer". 599 * 600 * Returns true on success, false otherwise. 601 * 602 * Caller holds tomoyo_read_lock(). 603 */ 604 bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) 605 { 606 struct list_head *pos; 607 bool done = true; 608 609 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { 610 struct tomoyo_alias_entry *ptr; 611 612 ptr = list_entry(pos, struct tomoyo_alias_entry, list); 613 if (ptr->is_deleted) 614 continue; 615 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n", 616 ptr->original_name->name, 617 ptr->aliased_name->name); 618 if (!done) 619 break; 620 } 621 return done; 622 } 623 624 /** 625 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list. 626 * 627 * @data: String to parse. 628 * @is_delete: True if it is a delete request. 629 * 630 * Returns 0 on success, negative value otherwise. 631 * 632 * Caller holds tomoyo_read_lock(). 633 */ 634 int tomoyo_write_alias_policy(char *data, const bool is_delete) 635 { 636 char *cp = strchr(data, ' '); 637 638 if (!cp) 639 return -EINVAL; 640 *cp++ = '\0'; 641 return tomoyo_update_alias_entry(data, cp, is_delete); 642 } 643 644 /** 645 * tomoyo_find_or_assign_new_domain - Create a domain. 646 * 647 * @domainname: The name of domain. 648 * @profile: Profile number to assign if the domain was newly created. 649 * 650 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 651 * 652 * Caller holds tomoyo_read_lock(). 653 */ 654 struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 655 domainname, 656 const u8 profile) 657 { 658 struct tomoyo_domain_info *entry; 659 struct tomoyo_domain_info *domain; 660 const struct tomoyo_path_info *saved_domainname; 661 bool found = false; 662 663 if (!tomoyo_is_correct_domain(domainname)) 664 return NULL; 665 saved_domainname = tomoyo_get_name(domainname); 666 if (!saved_domainname) 667 return NULL; 668 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 669 mutex_lock(&tomoyo_policy_lock); 670 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 671 if (domain->is_deleted || 672 tomoyo_pathcmp(saved_domainname, domain->domainname)) 673 continue; 674 found = true; 675 break; 676 } 677 if (!found && tomoyo_memory_ok(entry)) { 678 INIT_LIST_HEAD(&entry->acl_info_list); 679 entry->domainname = saved_domainname; 680 saved_domainname = NULL; 681 entry->profile = profile; 682 list_add_tail_rcu(&entry->list, &tomoyo_domain_list); 683 domain = entry; 684 entry = NULL; 685 found = true; 686 } 687 mutex_unlock(&tomoyo_policy_lock); 688 tomoyo_put_name(saved_domainname); 689 kfree(entry); 690 return found ? domain : NULL; 691 } 692 693 /** 694 * tomoyo_find_next_domain - Find a domain. 695 * 696 * @bprm: Pointer to "struct linux_binprm". 697 * 698 * Returns 0 on success, negative value otherwise. 699 * 700 * Caller holds tomoyo_read_lock(). 701 */ 702 int tomoyo_find_next_domain(struct linux_binprm *bprm) 703 { 704 /* 705 * This function assumes that the size of buffer returned by 706 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. 707 */ 708 struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); 709 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 710 struct tomoyo_domain_info *domain = NULL; 711 const char *old_domain_name = old_domain->domainname->name; 712 const char *original_name = bprm->filename; 713 char *new_domain_name = NULL; 714 char *real_program_name = NULL; 715 char *symlink_program_name = NULL; 716 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); 717 const bool is_enforce = (mode == 3); 718 int retval = -ENOMEM; 719 struct tomoyo_path_info r; /* real name */ 720 struct tomoyo_path_info s; /* symlink name */ 721 struct tomoyo_path_info l; /* last name */ 722 static bool initialized; 723 724 if (!tmp) 725 goto out; 726 727 if (!initialized) { 728 /* 729 * Built-in initializers. This is needed because policies are 730 * not loaded until starting /sbin/init. 731 */ 732 tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug", 733 false, false); 734 tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe", 735 false, false); 736 initialized = true; 737 } 738 739 /* Get tomoyo_realpath of program. */ 740 retval = -ENOENT; 741 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ 742 real_program_name = tomoyo_realpath(original_name); 743 if (!real_program_name) 744 goto out; 745 /* Get tomoyo_realpath of symbolic link. */ 746 symlink_program_name = tomoyo_realpath_nofollow(original_name); 747 if (!symlink_program_name) 748 goto out; 749 750 r.name = real_program_name; 751 tomoyo_fill_path_info(&r); 752 s.name = symlink_program_name; 753 tomoyo_fill_path_info(&s); 754 l.name = tomoyo_get_last_name(old_domain); 755 tomoyo_fill_path_info(&l); 756 757 /* Check 'alias' directive. */ 758 if (tomoyo_pathcmp(&r, &s)) { 759 struct tomoyo_alias_entry *ptr; 760 /* Is this program allowed to be called via symbolic links? */ 761 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 762 if (ptr->is_deleted || 763 tomoyo_pathcmp(&r, ptr->original_name) || 764 tomoyo_pathcmp(&s, ptr->aliased_name)) 765 continue; 766 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); 767 strncpy(real_program_name, ptr->aliased_name->name, 768 TOMOYO_MAX_PATHNAME_LEN - 1); 769 tomoyo_fill_path_info(&r); 770 break; 771 } 772 } 773 774 /* Check execute permission. */ 775 retval = tomoyo_check_exec_perm(old_domain, &r); 776 if (retval < 0) 777 goto out; 778 779 new_domain_name = tmp->buffer; 780 if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) { 781 /* Transit to the child of tomoyo_kernel_domain domain. */ 782 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 783 TOMOYO_ROOT_NAME " " "%s", real_program_name); 784 } else if (old_domain == &tomoyo_kernel_domain && 785 !tomoyo_policy_loaded) { 786 /* 787 * Needn't to transit from kernel domain before starting 788 * /sbin/init. But transit from kernel domain if executing 789 * initializers because they might start before /sbin/init. 790 */ 791 domain = old_domain; 792 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) { 793 /* Keep current domain. */ 794 domain = old_domain; 795 } else { 796 /* Normal domain transition. */ 797 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 798 "%s %s", old_domain_name, real_program_name); 799 } 800 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) 801 goto done; 802 domain = tomoyo_find_domain(new_domain_name); 803 if (domain) 804 goto done; 805 if (is_enforce) 806 goto done; 807 domain = tomoyo_find_or_assign_new_domain(new_domain_name, 808 old_domain->profile); 809 done: 810 if (domain) 811 goto out; 812 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", 813 new_domain_name); 814 if (is_enforce) 815 retval = -EPERM; 816 else 817 old_domain->transition_failed = true; 818 out: 819 if (!domain) 820 domain = old_domain; 821 /* Update reference count on "struct tomoyo_domain_info". */ 822 atomic_inc(&domain->users); 823 bprm->cred->security = domain; 824 kfree(real_program_name); 825 kfree(symlink_program_name); 826 kfree(tmp); 827 return retval; 828 } 829