domain.c revision 99a852596beb26cc449ca1a79834c107ef4080e1
1/* 2 * security/tomoyo/domain.c 3 * 4 * Domain transition functions for TOMOYO. 5 * 6 * Copyright (C) 2005-2010 NTT DATA CORPORATION 7 */ 8 9#include "common.h" 10#include <linux/binfmts.h> 11#include <linux/slab.h> 12 13/* Variables definitions.*/ 14 15/* The initial domain. */ 16struct tomoyo_domain_info tomoyo_kernel_domain; 17 18/** 19 * tomoyo_update_policy - Update an entry for exception policy. 20 * 21 * @new_entry: Pointer to "struct tomoyo_acl_info". 22 * @size: Size of @new_entry in bytes. 23 * @is_delete: True if it is a delete request. 24 * @list: Pointer to "struct list_head". 25 * @check_duplicate: Callback function to find duplicated entry. 26 * 27 * Returns 0 on success, negative value otherwise. 28 * 29 * Caller holds tomoyo_read_lock(). 30 */ 31int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, 32 bool is_delete, struct list_head *list, 33 bool (*check_duplicate) (const struct tomoyo_acl_head 34 *, 35 const struct tomoyo_acl_head 36 *)) 37{ 38 int error = is_delete ? -ENOENT : -ENOMEM; 39 struct tomoyo_acl_head *entry; 40 41 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 42 return -ENOMEM; 43 list_for_each_entry_rcu(entry, list, list) { 44 if (!check_duplicate(entry, new_entry)) 45 continue; 46 entry->is_deleted = is_delete; 47 error = 0; 48 break; 49 } 50 if (error && !is_delete) { 51 entry = tomoyo_commit_ok(new_entry, size); 52 if (entry) { 53 list_add_tail_rcu(&entry->list, list); 54 error = 0; 55 } 56 } 57 mutex_unlock(&tomoyo_policy_lock); 58 return error; 59} 60 61/** 62 * tomoyo_update_domain - Update an entry for domain policy. 63 * 64 * @new_entry: Pointer to "struct tomoyo_acl_info". 65 * @size: Size of @new_entry in bytes. 66 * @is_delete: True if it is a delete request. 67 * @domain: Pointer to "struct tomoyo_domain_info". 68 * @check_duplicate: Callback function to find duplicated entry. 69 * @merge_duplicate: Callback function to merge duplicated entry. 70 * 71 * Returns 0 on success, negative value otherwise. 72 * 73 * Caller holds tomoyo_read_lock(). 74 */ 75int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 76 bool is_delete, struct tomoyo_domain_info *domain, 77 bool (*check_duplicate) (const struct tomoyo_acl_info 78 *, 79 const struct tomoyo_acl_info 80 *), 81 bool (*merge_duplicate) (struct tomoyo_acl_info *, 82 struct tomoyo_acl_info *, 83 const bool)) 84{ 85 int error = is_delete ? -ENOENT : -ENOMEM; 86 struct tomoyo_acl_info *entry; 87 88 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 89 return error; 90 list_for_each_entry_rcu(entry, &domain->acl_info_list, list) { 91 if (!check_duplicate(entry, new_entry)) 92 continue; 93 if (merge_duplicate) 94 entry->is_deleted = merge_duplicate(entry, new_entry, 95 is_delete); 96 else 97 entry->is_deleted = is_delete; 98 error = 0; 99 break; 100 } 101 if (error && !is_delete) { 102 entry = tomoyo_commit_ok(new_entry, size); 103 if (entry) { 104 list_add_tail_rcu(&entry->list, &domain->acl_info_list); 105 error = 0; 106 } 107 } 108 mutex_unlock(&tomoyo_policy_lock); 109 return error; 110} 111 112void tomoyo_check_acl(struct tomoyo_request_info *r, 113 bool (*check_entry) (const struct tomoyo_request_info *, 114 const struct tomoyo_acl_info *)) 115{ 116 const struct tomoyo_domain_info *domain = r->domain; 117 struct tomoyo_acl_info *ptr; 118 119 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 120 if (ptr->is_deleted || ptr->type != r->param_type) 121 continue; 122 if (check_entry(r, ptr)) { 123 r->granted = true; 124 return; 125 } 126 } 127 r->granted = false; 128} 129 130/* 131 * tomoyo_domain_list is used for holding list of domains. 132 * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding 133 * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain. 134 * 135 * An entry is added by 136 * 137 * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \ 138 * /sys/kernel/security/tomoyo/domain_policy 139 * 140 * and is deleted by 141 * 142 * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \ 143 * /sys/kernel/security/tomoyo/domain_policy 144 * 145 * and all entries are retrieved by 146 * 147 * # cat /sys/kernel/security/tomoyo/domain_policy 148 * 149 * A domain is added by 150 * 151 * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy 152 * 153 * and is deleted by 154 * 155 * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy 156 * 157 * and all domains are retrieved by 158 * 159 * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy 160 * 161 * Normally, a domainname is monotonically getting longer because a domainname 162 * which the process will belong to if an execve() operation succeeds is 163 * defined as a concatenation of "current domainname" + "pathname passed to 164 * execve()". 165 * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for 166 * exceptions. 167 */ 168LIST_HEAD(tomoyo_domain_list); 169 170/** 171 * tomoyo_get_last_name - Get last component of a domainname. 172 * 173 * @domain: Pointer to "struct tomoyo_domain_info". 174 * 175 * Returns the last component of the domainname. 176 */ 177const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) 178{ 179 const char *cp0 = domain->domainname->name; 180 const char *cp1 = strrchr(cp0, ' '); 181 182 if (cp1) 183 return cp1 + 1; 184 return cp0; 185} 186 187/* 188 * tomoyo_domain_initializer_list is used for holding list of programs which 189 * triggers reinitialization of domainname. Normally, a domainname is 190 * monotonically getting longer. But sometimes, we restart daemon programs. 191 * It would be convenient for us that "a daemon started upon system boot" and 192 * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO 193 * provides a way to shorten domainnames. 194 * 195 * An entry is added by 196 * 197 * # echo 'initialize_domain /usr/sbin/httpd' > \ 198 * /sys/kernel/security/tomoyo/exception_policy 199 * 200 * and is deleted by 201 * 202 * # echo 'delete initialize_domain /usr/sbin/httpd' > \ 203 * /sys/kernel/security/tomoyo/exception_policy 204 * 205 * and all entries are retrieved by 206 * 207 * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy 208 * 209 * In the example above, /usr/sbin/httpd will belong to 210 * "<kernel> /usr/sbin/httpd" domain. 211 * 212 * You may specify a domainname using "from" keyword. 213 * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd" 214 * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd" 215 * domain to belong to "<kernel> /usr/sbin/httpd" domain. 216 * 217 * You may add "no_" prefix to "initialize_domain". 218 * "initialize_domain /usr/sbin/httpd" and 219 * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd" 220 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain 221 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain. 222 */ 223LIST_HEAD(tomoyo_domain_initializer_list); 224 225static bool tomoyo_same_domain_initializer_entry(const struct tomoyo_acl_head * 226 a, 227 const struct tomoyo_acl_head * 228 b) 229{ 230 const struct tomoyo_domain_initializer_entry *p1 = 231 container_of(a, typeof(*p1), head); 232 const struct tomoyo_domain_initializer_entry *p2 = 233 container_of(b, typeof(*p2), head); 234 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name 235 && p1->domainname == p2->domainname 236 && p1->program == p2->program; 237} 238 239/** 240 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. 241 * 242 * @domainname: The name of domain. May be NULL. 243 * @program: The name of program. 244 * @is_not: True if it is "no_initialize_domain" entry. 245 * @is_delete: True if it is a delete request. 246 * 247 * Returns 0 on success, negative value otherwise. 248 * 249 * Caller holds tomoyo_read_lock(). 250 */ 251static int tomoyo_update_domain_initializer_entry(const char *domainname, 252 const char *program, 253 const bool is_not, 254 const bool is_delete) 255{ 256 struct tomoyo_domain_initializer_entry e = { .is_not = is_not }; 257 int error = is_delete ? -ENOENT : -ENOMEM; 258 259 if (!tomoyo_is_correct_path(program)) 260 return -EINVAL; 261 if (domainname) { 262 if (!tomoyo_is_domain_def(domainname) && 263 tomoyo_is_correct_path(domainname)) 264 e.is_last_name = true; 265 else if (!tomoyo_is_correct_domain(domainname)) 266 return -EINVAL; 267 e.domainname = tomoyo_get_name(domainname); 268 if (!e.domainname) 269 goto out; 270 } 271 e.program = tomoyo_get_name(program); 272 if (!e.program) 273 goto out; 274 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 275 &tomoyo_domain_initializer_list, 276 tomoyo_same_domain_initializer_entry); 277 out: 278 tomoyo_put_name(e.domainname); 279 tomoyo_put_name(e.program); 280 return error; 281} 282 283/** 284 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list. 285 * 286 * @head: Pointer to "struct tomoyo_io_buffer". 287 * 288 * Returns true on success, false otherwise. 289 * 290 * Caller holds tomoyo_read_lock(). 291 */ 292bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 293{ 294 struct list_head *pos; 295 bool done = true; 296 297 list_for_each_cookie(pos, head->read_var2, 298 &tomoyo_domain_initializer_list) { 299 const char *no; 300 const char *from = ""; 301 const char *domain = ""; 302 struct tomoyo_domain_initializer_entry *ptr; 303 ptr = list_entry(pos, struct tomoyo_domain_initializer_entry, 304 head.list); 305 if (ptr->head.is_deleted) 306 continue; 307 no = ptr->is_not ? "no_" : ""; 308 if (ptr->domainname) { 309 from = " from "; 310 domain = ptr->domainname->name; 311 } 312 done = tomoyo_io_printf(head, 313 "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN 314 "%s%s%s\n", no, ptr->program->name, 315 from, domain); 316 if (!done) 317 break; 318 } 319 return done; 320} 321 322/** 323 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list. 324 * 325 * @data: String to parse. 326 * @is_not: True if it is "no_initialize_domain" entry. 327 * @is_delete: True if it is a delete request. 328 * 329 * Returns 0 on success, negative value otherwise. 330 * 331 * Caller holds tomoyo_read_lock(). 332 */ 333int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 334 const bool is_delete) 335{ 336 char *cp = strstr(data, " from "); 337 338 if (cp) { 339 *cp = '\0'; 340 return tomoyo_update_domain_initializer_entry(cp + 6, data, 341 is_not, 342 is_delete); 343 } 344 return tomoyo_update_domain_initializer_entry(NULL, data, is_not, 345 is_delete); 346} 347 348/** 349 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization. 350 * 351 * @domainname: The name of domain. 352 * @program: The name of program. 353 * @last_name: The last component of @domainname. 354 * 355 * Returns true if executing @program reinitializes domain transition, 356 * false otherwise. 357 * 358 * Caller holds tomoyo_read_lock(). 359 */ 360static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * 361 domainname, 362 const struct tomoyo_path_info *program, 363 const struct tomoyo_path_info * 364 last_name) 365{ 366 struct tomoyo_domain_initializer_entry *ptr; 367 bool flag = false; 368 369 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, 370 head.list) { 371 if (ptr->head.is_deleted) 372 continue; 373 if (ptr->domainname) { 374 if (!ptr->is_last_name) { 375 if (ptr->domainname != domainname) 376 continue; 377 } else { 378 if (tomoyo_pathcmp(ptr->domainname, last_name)) 379 continue; 380 } 381 } 382 if (tomoyo_pathcmp(ptr->program, program)) 383 continue; 384 if (ptr->is_not) { 385 flag = false; 386 break; 387 } 388 flag = true; 389 } 390 return flag; 391} 392 393/* 394 * tomoyo_domain_keeper_list is used for holding list of domainnames which 395 * suppresses domain transition. Normally, a domainname is monotonically 396 * getting longer. But sometimes, we want to suppress domain transition. 397 * It would be convenient for us that programs executed from a login session 398 * belong to the same domain. Thus, TOMOYO provides a way to suppress domain 399 * transition. 400 * 401 * An entry is added by 402 * 403 * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \ 404 * /sys/kernel/security/tomoyo/exception_policy 405 * 406 * and is deleted by 407 * 408 * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \ 409 * /sys/kernel/security/tomoyo/exception_policy 410 * 411 * and all entries are retrieved by 412 * 413 * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy 414 * 415 * In the example above, any process which belongs to 416 * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain, 417 * unless explicitly specified by "initialize_domain" or "no_keep_domain". 418 * 419 * You may specify a program using "from" keyword. 420 * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash" 421 * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash" 422 * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain. 423 * 424 * You may add "no_" prefix to "keep_domain". 425 * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and 426 * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will 427 * cause "/usr/bin/passwd" to belong to 428 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless 429 * explicitly specified by "initialize_domain". 430 */ 431LIST_HEAD(tomoyo_domain_keeper_list); 432 433static bool tomoyo_same_domain_keeper_entry(const struct tomoyo_acl_head *a, 434 const struct tomoyo_acl_head *b) 435{ 436 const struct tomoyo_domain_keeper_entry *p1 = 437 container_of(a, typeof(*p1), head); 438 const struct tomoyo_domain_keeper_entry *p2 = 439 container_of(b, typeof(*p2), head); 440 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name 441 && p1->domainname == p2->domainname 442 && p1->program == p2->program; 443} 444 445/** 446 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. 447 * 448 * @domainname: The name of domain. 449 * @program: The name of program. May be NULL. 450 * @is_not: True if it is "no_keep_domain" entry. 451 * @is_delete: True if it is a delete request. 452 * 453 * Returns 0 on success, negative value otherwise. 454 * 455 * Caller holds tomoyo_read_lock(). 456 */ 457static int tomoyo_update_domain_keeper_entry(const char *domainname, 458 const char *program, 459 const bool is_not, 460 const bool is_delete) 461{ 462 struct tomoyo_domain_keeper_entry e = { .is_not = is_not }; 463 int error = is_delete ? -ENOENT : -ENOMEM; 464 465 if (!tomoyo_is_domain_def(domainname) && 466 tomoyo_is_correct_path(domainname)) 467 e.is_last_name = true; 468 else if (!tomoyo_is_correct_domain(domainname)) 469 return -EINVAL; 470 if (program) { 471 if (!tomoyo_is_correct_path(program)) 472 return -EINVAL; 473 e.program = tomoyo_get_name(program); 474 if (!e.program) 475 goto out; 476 } 477 e.domainname = tomoyo_get_name(domainname); 478 if (!e.domainname) 479 goto out; 480 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 481 &tomoyo_domain_keeper_list, 482 tomoyo_same_domain_keeper_entry); 483 out: 484 tomoyo_put_name(e.domainname); 485 tomoyo_put_name(e.program); 486 return error; 487} 488 489/** 490 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list. 491 * 492 * @data: String to parse. 493 * @is_not: True if it is "no_keep_domain" entry. 494 * @is_delete: True if it is a delete request. 495 * 496 * Caller holds tomoyo_read_lock(). 497 */ 498int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 499 const bool is_delete) 500{ 501 char *cp = strstr(data, " from "); 502 503 if (cp) { 504 *cp = '\0'; 505 return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not, 506 is_delete); 507 } 508 return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete); 509} 510 511/** 512 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list. 513 * 514 * @head: Pointer to "struct tomoyo_io_buffer". 515 * 516 * Returns true on success, false otherwise. 517 * 518 * Caller holds tomoyo_read_lock(). 519 */ 520bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 521{ 522 struct list_head *pos; 523 bool done = true; 524 525 list_for_each_cookie(pos, head->read_var2, 526 &tomoyo_domain_keeper_list) { 527 struct tomoyo_domain_keeper_entry *ptr; 528 const char *no; 529 const char *from = ""; 530 const char *program = ""; 531 532 ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, 533 head.list); 534 if (ptr->head.is_deleted) 535 continue; 536 no = ptr->is_not ? "no_" : ""; 537 if (ptr->program) { 538 from = " from "; 539 program = ptr->program->name; 540 } 541 done = tomoyo_io_printf(head, 542 "%s" TOMOYO_KEYWORD_KEEP_DOMAIN 543 "%s%s%s\n", no, program, from, 544 ptr->domainname->name); 545 if (!done) 546 break; 547 } 548 return done; 549} 550 551/** 552 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression. 553 * 554 * @domainname: The name of domain. 555 * @program: The name of program. 556 * @last_name: The last component of @domainname. 557 * 558 * Returns true if executing @program supresses domain transition, 559 * false otherwise. 560 * 561 * Caller holds tomoyo_read_lock(). 562 */ 563static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, 564 const struct tomoyo_path_info *program, 565 const struct tomoyo_path_info *last_name) 566{ 567 struct tomoyo_domain_keeper_entry *ptr; 568 bool flag = false; 569 570 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, head.list) { 571 if (ptr->head.is_deleted) 572 continue; 573 if (!ptr->is_last_name) { 574 if (ptr->domainname != domainname) 575 continue; 576 } else { 577 if (tomoyo_pathcmp(ptr->domainname, last_name)) 578 continue; 579 } 580 if (ptr->program && tomoyo_pathcmp(ptr->program, program)) 581 continue; 582 if (ptr->is_not) { 583 flag = false; 584 break; 585 } 586 flag = true; 587 } 588 return flag; 589} 590 591/* 592 * tomoyo_aggregator_list is used for holding list of rewrite table for 593 * execve() request. Some programs provides similar functionality. This keyword 594 * allows users to aggregate such programs. 595 * 596 * Entries are added by 597 * 598 * # echo 'aggregator /usr/bin/vi /./editor' > \ 599 * /sys/kernel/security/tomoyo/exception_policy 600 * # echo 'aggregator /usr/bin/emacs /./editor' > \ 601 * /sys/kernel/security/tomoyo/exception_policy 602 * 603 * and are deleted by 604 * 605 * # echo 'delete aggregator /usr/bin/vi /./editor' > \ 606 * /sys/kernel/security/tomoyo/exception_policy 607 * # echo 'delete aggregator /usr/bin/emacs /./editor' > \ 608 * /sys/kernel/security/tomoyo/exception_policy 609 * 610 * and all entries are retrieved by 611 * 612 * # grep ^aggregator /sys/kernel/security/tomoyo/exception_policy 613 * 614 * In the example above, if /usr/bin/vi or /usr/bin/emacs are executed, 615 * permission is checked for /./editor and domainname which the current process 616 * will belong to after execve() succeeds is calculated using /./editor . 617 */ 618LIST_HEAD(tomoyo_aggregator_list); 619 620static bool tomoyo_same_aggregator_entry(const struct tomoyo_acl_head *a, 621 const struct tomoyo_acl_head *b) 622{ 623 const struct tomoyo_aggregator_entry *p1 = container_of(a, typeof(*p1), 624 head); 625 const struct tomoyo_aggregator_entry *p2 = container_of(b, typeof(*p2), 626 head); 627 return p1->original_name == p2->original_name && 628 p1->aggregated_name == p2->aggregated_name; 629} 630 631/** 632 * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator_entry" list. 633 * 634 * @original_name: The original program's name. 635 * @aggregated_name: The program name to use. 636 * @is_delete: True if it is a delete request. 637 * 638 * Returns 0 on success, negative value otherwise. 639 * 640 * Caller holds tomoyo_read_lock(). 641 */ 642static int tomoyo_update_aggregator_entry(const char *original_name, 643 const char *aggregated_name, 644 const bool is_delete) 645{ 646 struct tomoyo_aggregator_entry e = { }; 647 int error = is_delete ? -ENOENT : -ENOMEM; 648 649 if (!tomoyo_is_correct_path(original_name) || 650 !tomoyo_is_correct_path(aggregated_name)) 651 return -EINVAL; 652 e.original_name = tomoyo_get_name(original_name); 653 e.aggregated_name = tomoyo_get_name(aggregated_name); 654 if (!e.original_name || !e.aggregated_name || 655 e.aggregated_name->is_patterned) /* No patterns allowed. */ 656 goto out; 657 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 658 &tomoyo_aggregator_list, 659 tomoyo_same_aggregator_entry); 660 out: 661 tomoyo_put_name(e.original_name); 662 tomoyo_put_name(e.aggregated_name); 663 return error; 664} 665 666/** 667 * tomoyo_read_aggregator_policy - Read "struct tomoyo_aggregator_entry" list. 668 * 669 * @head: Pointer to "struct tomoyo_io_buffer". 670 * 671 * Returns true on success, false otherwise. 672 * 673 * Caller holds tomoyo_read_lock(). 674 */ 675bool tomoyo_read_aggregator_policy(struct tomoyo_io_buffer *head) 676{ 677 struct list_head *pos; 678 bool done = true; 679 680 list_for_each_cookie(pos, head->read_var2, &tomoyo_aggregator_list) { 681 struct tomoyo_aggregator_entry *ptr; 682 683 ptr = list_entry(pos, struct tomoyo_aggregator_entry, 684 head.list); 685 if (ptr->head.is_deleted) 686 continue; 687 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_AGGREGATOR 688 "%s %s\n", ptr->original_name->name, 689 ptr->aggregated_name->name); 690 if (!done) 691 break; 692 } 693 return done; 694} 695 696/** 697 * tomoyo_write_aggregator_policy - Write "struct tomoyo_aggregator_entry" list. 698 * 699 * @data: String to parse. 700 * @is_delete: True if it is a delete request. 701 * 702 * Returns 0 on success, negative value otherwise. 703 * 704 * Caller holds tomoyo_read_lock(). 705 */ 706int tomoyo_write_aggregator_policy(char *data, const bool is_delete) 707{ 708 char *cp = strchr(data, ' '); 709 710 if (!cp) 711 return -EINVAL; 712 *cp++ = '\0'; 713 return tomoyo_update_aggregator_entry(data, cp, is_delete); 714} 715 716/* 717 * tomoyo_alias_list is used for holding list of symlink's pathnames which are 718 * allowed to be passed to an execve() request. Normally, the domainname which 719 * the current process will belong to after execve() succeeds is calculated 720 * using dereferenced pathnames. But some programs behave differently depending 721 * on the name passed to argv[0]. For busybox, calculating domainname using 722 * dereferenced pathnames will cause all programs in the busybox to belong to 723 * the same domain. Thus, TOMOYO provides a way to allow use of symlink's 724 * pathname for checking execve()'s permission and calculating domainname which 725 * the current process will belong to after execve() succeeds. 726 * 727 * An entry is added by 728 * 729 * # echo 'alias /bin/busybox /bin/cat' > \ 730 * /sys/kernel/security/tomoyo/exception_policy 731 * 732 * and is deleted by 733 * 734 * # echo 'delete alias /bin/busybox /bin/cat' > \ 735 * /sys/kernel/security/tomoyo/exception_policy 736 * 737 * and all entries are retrieved by 738 * 739 * # grep ^alias /sys/kernel/security/tomoyo/exception_policy 740 * 741 * In the example above, if /bin/cat is a symlink to /bin/busybox and execution 742 * of /bin/cat is requested, permission is checked for /bin/cat rather than 743 * /bin/busybox and domainname which the current process will belong to after 744 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . 745 */ 746LIST_HEAD(tomoyo_alias_list); 747 748static bool tomoyo_same_alias_entry(const struct tomoyo_acl_head *a, 749 const struct tomoyo_acl_head *b) 750{ 751 const struct tomoyo_alias_entry *p1 = container_of(a, typeof(*p1), 752 head); 753 const struct tomoyo_alias_entry *p2 = container_of(b, typeof(*p2), 754 head); 755 return p1->original_name == p2->original_name && 756 p1->aliased_name == p2->aliased_name; 757} 758 759/** 760 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. 761 * 762 * @original_name: The original program's real name. 763 * @aliased_name: The symbolic program's symbolic link's name. 764 * @is_delete: True if it is a delete request. 765 * 766 * Returns 0 on success, negative value otherwise. 767 * 768 * Caller holds tomoyo_read_lock(). 769 */ 770static int tomoyo_update_alias_entry(const char *original_name, 771 const char *aliased_name, 772 const bool is_delete) 773{ 774 struct tomoyo_alias_entry e = { }; 775 int error = is_delete ? -ENOENT : -ENOMEM; 776 777 if (!tomoyo_is_correct_path(original_name) || 778 !tomoyo_is_correct_path(aliased_name)) 779 return -EINVAL; 780 e.original_name = tomoyo_get_name(original_name); 781 e.aliased_name = tomoyo_get_name(aliased_name); 782 if (!e.original_name || !e.aliased_name || 783 e.original_name->is_patterned || e.aliased_name->is_patterned) 784 goto out; /* No patterns allowed. */ 785 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 786 &tomoyo_alias_list, 787 tomoyo_same_alias_entry); 788 out: 789 tomoyo_put_name(e.original_name); 790 tomoyo_put_name(e.aliased_name); 791 return error; 792} 793 794/** 795 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list. 796 * 797 * @head: Pointer to "struct tomoyo_io_buffer". 798 * 799 * Returns true on success, false otherwise. 800 * 801 * Caller holds tomoyo_read_lock(). 802 */ 803bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) 804{ 805 struct list_head *pos; 806 bool done = true; 807 808 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { 809 struct tomoyo_alias_entry *ptr; 810 811 ptr = list_entry(pos, struct tomoyo_alias_entry, head.list); 812 if (ptr->head.is_deleted) 813 continue; 814 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n", 815 ptr->original_name->name, 816 ptr->aliased_name->name); 817 if (!done) 818 break; 819 } 820 return done; 821} 822 823/** 824 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list. 825 * 826 * @data: String to parse. 827 * @is_delete: True if it is a delete request. 828 * 829 * Returns 0 on success, negative value otherwise. 830 * 831 * Caller holds tomoyo_read_lock(). 832 */ 833int tomoyo_write_alias_policy(char *data, const bool is_delete) 834{ 835 char *cp = strchr(data, ' '); 836 837 if (!cp) 838 return -EINVAL; 839 *cp++ = '\0'; 840 return tomoyo_update_alias_entry(data, cp, is_delete); 841} 842 843/** 844 * tomoyo_find_or_assign_new_domain - Create a domain. 845 * 846 * @domainname: The name of domain. 847 * @profile: Profile number to assign if the domain was newly created. 848 * 849 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 850 * 851 * Caller holds tomoyo_read_lock(). 852 */ 853struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 854 domainname, 855 const u8 profile) 856{ 857 struct tomoyo_domain_info *entry; 858 struct tomoyo_domain_info *domain = NULL; 859 const struct tomoyo_path_info *saved_domainname; 860 bool found = false; 861 862 if (!tomoyo_is_correct_domain(domainname)) 863 return NULL; 864 saved_domainname = tomoyo_get_name(domainname); 865 if (!saved_domainname) 866 return NULL; 867 entry = kzalloc(sizeof(*entry), GFP_NOFS); 868 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 869 goto out; 870 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 871 if (domain->is_deleted || 872 tomoyo_pathcmp(saved_domainname, domain->domainname)) 873 continue; 874 found = true; 875 break; 876 } 877 if (!found && tomoyo_memory_ok(entry)) { 878 INIT_LIST_HEAD(&entry->acl_info_list); 879 entry->domainname = saved_domainname; 880 saved_domainname = NULL; 881 entry->profile = profile; 882 list_add_tail_rcu(&entry->list, &tomoyo_domain_list); 883 domain = entry; 884 entry = NULL; 885 found = true; 886 } 887 mutex_unlock(&tomoyo_policy_lock); 888 out: 889 tomoyo_put_name(saved_domainname); 890 kfree(entry); 891 return found ? domain : NULL; 892} 893 894/** 895 * tomoyo_find_next_domain - Find a domain. 896 * 897 * @bprm: Pointer to "struct linux_binprm". 898 * 899 * Returns 0 on success, negative value otherwise. 900 * 901 * Caller holds tomoyo_read_lock(). 902 */ 903int tomoyo_find_next_domain(struct linux_binprm *bprm) 904{ 905 struct tomoyo_request_info r; 906 char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); 907 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 908 struct tomoyo_domain_info *domain = NULL; 909 const char *old_domain_name = old_domain->domainname->name; 910 const char *original_name = bprm->filename; 911 u8 mode; 912 bool is_enforce; 913 int retval = -ENOMEM; 914 bool need_kfree = false; 915 struct tomoyo_path_info rn = { }; /* real name */ 916 struct tomoyo_path_info sn = { }; /* symlink name */ 917 struct tomoyo_path_info ln; /* last name */ 918 919 ln.name = tomoyo_get_last_name(old_domain); 920 tomoyo_fill_path_info(&ln); 921 mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); 922 is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); 923 if (!tmp) 924 goto out; 925 926 retry: 927 if (need_kfree) { 928 kfree(rn.name); 929 need_kfree = false; 930 } 931 /* Get tomoyo_realpath of program. */ 932 retval = -ENOENT; 933 rn.name = tomoyo_realpath(original_name); 934 if (!rn.name) 935 goto out; 936 tomoyo_fill_path_info(&rn); 937 need_kfree = true; 938 939 /* Get tomoyo_realpath of symbolic link. */ 940 sn.name = tomoyo_realpath_nofollow(original_name); 941 if (!sn.name) 942 goto out; 943 tomoyo_fill_path_info(&sn); 944 945 /* Check 'alias' directive. */ 946 if (tomoyo_pathcmp(&rn, &sn)) { 947 struct tomoyo_alias_entry *ptr; 948 /* Is this program allowed to be called via symbolic links? */ 949 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, head.list) { 950 if (ptr->head.is_deleted || 951 tomoyo_pathcmp(&rn, ptr->original_name) || 952 tomoyo_pathcmp(&sn, ptr->aliased_name)) 953 continue; 954 kfree(rn.name); 955 need_kfree = false; 956 /* This is OK because it is read only. */ 957 rn = *ptr->aliased_name; 958 break; 959 } 960 } 961 962 /* Check 'aggregator' directive. */ 963 { 964 struct tomoyo_aggregator_entry *ptr; 965 list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list, 966 head.list) { 967 if (ptr->head.is_deleted || 968 !tomoyo_path_matches_pattern(&rn, 969 ptr->original_name)) 970 continue; 971 if (need_kfree) 972 kfree(rn.name); 973 need_kfree = false; 974 /* This is OK because it is read only. */ 975 rn = *ptr->aggregated_name; 976 break; 977 } 978 } 979 980 /* Check execute permission. */ 981 retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn); 982 if (retval == TOMOYO_RETRY_REQUEST) 983 goto retry; 984 if (retval < 0) 985 goto out; 986 987 if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) { 988 /* Transit to the child of tomoyo_kernel_domain domain. */ 989 snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, 990 TOMOYO_ROOT_NAME " " "%s", rn.name); 991 } else if (old_domain == &tomoyo_kernel_domain && 992 !tomoyo_policy_loaded) { 993 /* 994 * Needn't to transit from kernel domain before starting 995 * /sbin/init. But transit from kernel domain if executing 996 * initializers because they might start before /sbin/init. 997 */ 998 domain = old_domain; 999 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &rn, &ln)) { 1000 /* Keep current domain. */ 1001 domain = old_domain; 1002 } else { 1003 /* Normal domain transition. */ 1004 snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, 1005 "%s %s", old_domain_name, rn.name); 1006 } 1007 if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10) 1008 goto done; 1009 domain = tomoyo_find_domain(tmp); 1010 if (domain) 1011 goto done; 1012 if (is_enforce) { 1013 int error = tomoyo_supervisor(&r, "# wants to create domain\n" 1014 "%s\n", tmp); 1015 if (error == TOMOYO_RETRY_REQUEST) 1016 goto retry; 1017 if (error < 0) 1018 goto done; 1019 } 1020 domain = tomoyo_find_or_assign_new_domain(tmp, old_domain->profile); 1021 done: 1022 if (domain) 1023 goto out; 1024 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp); 1025 if (is_enforce) 1026 retval = -EPERM; 1027 else 1028 old_domain->transition_failed = true; 1029 out: 1030 if (!domain) 1031 domain = old_domain; 1032 /* Update reference count on "struct tomoyo_domain_info". */ 1033 atomic_inc(&domain->users); 1034 bprm->cred->security = domain; 1035 if (need_kfree) 1036 kfree(rn.name); 1037 kfree(sn.name); 1038 kfree(tmp); 1039 return retval; 1040} 1041