diff options
Diffstat (limited to 'security/tomoyo/domain.c')
-rw-r--r-- | security/tomoyo/domain.c | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index fcf52accce2b..2fd190168b7e 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -217,6 +217,8 @@ static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock); | |||
217 | * @is_delete: True if it is a delete request. | 217 | * @is_delete: True if it is a delete request. |
218 | * | 218 | * |
219 | * Returns 0 on success, negative value otherwise. | 219 | * Returns 0 on success, negative value otherwise. |
220 | * | ||
221 | * Caller holds tomoyo_read_lock(). | ||
220 | */ | 222 | */ |
221 | static int tomoyo_update_domain_initializer_entry(const char *domainname, | 223 | static int tomoyo_update_domain_initializer_entry(const char *domainname, |
222 | const char *program, | 224 | const char *program, |
@@ -246,7 +248,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
246 | if (!saved_program) | 248 | if (!saved_program) |
247 | return -ENOMEM; | 249 | return -ENOMEM; |
248 | down_write(&tomoyo_domain_initializer_list_lock); | 250 | down_write(&tomoyo_domain_initializer_list_lock); |
249 | list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { | 251 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { |
250 | if (ptr->is_not != is_not || | 252 | if (ptr->is_not != is_not || |
251 | ptr->domainname != saved_domainname || | 253 | ptr->domainname != saved_domainname || |
252 | ptr->program != saved_program) | 254 | ptr->program != saved_program) |
@@ -266,7 +268,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
266 | new_entry->program = saved_program; | 268 | new_entry->program = saved_program; |
267 | new_entry->is_not = is_not; | 269 | new_entry->is_not = is_not; |
268 | new_entry->is_last_name = is_last_name; | 270 | new_entry->is_last_name = is_last_name; |
269 | list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list); | 271 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); |
270 | error = 0; | 272 | error = 0; |
271 | out: | 273 | out: |
272 | up_write(&tomoyo_domain_initializer_list_lock); | 274 | up_write(&tomoyo_domain_initializer_list_lock); |
@@ -279,13 +281,14 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
279 | * @head: Pointer to "struct tomoyo_io_buffer". | 281 | * @head: Pointer to "struct tomoyo_io_buffer". |
280 | * | 282 | * |
281 | * Returns true on success, false otherwise. | 283 | * Returns true on success, false otherwise. |
284 | * | ||
285 | * Caller holds tomoyo_read_lock(). | ||
282 | */ | 286 | */ |
283 | bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) | 287 | bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) |
284 | { | 288 | { |
285 | struct list_head *pos; | 289 | struct list_head *pos; |
286 | bool done = true; | 290 | bool done = true; |
287 | 291 | ||
288 | down_read(&tomoyo_domain_initializer_list_lock); | ||
289 | list_for_each_cookie(pos, head->read_var2, | 292 | list_for_each_cookie(pos, head->read_var2, |
290 | &tomoyo_domain_initializer_list) { | 293 | &tomoyo_domain_initializer_list) { |
291 | const char *no; | 294 | const char *no; |
@@ -308,7 +311,6 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) | |||
308 | if (!done) | 311 | if (!done) |
309 | break; | 312 | break; |
310 | } | 313 | } |
311 | up_read(&tomoyo_domain_initializer_list_lock); | ||
312 | return done; | 314 | return done; |
313 | } | 315 | } |
314 | 316 | ||
@@ -320,6 +322,8 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) | |||
320 | * @is_delete: True if it is a delete request. | 322 | * @is_delete: True if it is a delete request. |
321 | * | 323 | * |
322 | * Returns 0 on success, negative value otherwise. | 324 | * Returns 0 on success, negative value otherwise. |
325 | * | ||
326 | * Caller holds tomoyo_read_lock(). | ||
323 | */ | 327 | */ |
324 | int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, | 328 | int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, |
325 | const bool is_delete) | 329 | const bool is_delete) |
@@ -345,6 +349,8 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, | |||
345 | * | 349 | * |
346 | * Returns true if executing @program reinitializes domain transition, | 350 | * Returns true if executing @program reinitializes domain transition, |
347 | * false otherwise. | 351 | * false otherwise. |
352 | * | ||
353 | * Caller holds tomoyo_read_lock(). | ||
348 | */ | 354 | */ |
349 | static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | 355 | static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * |
350 | domainname, | 356 | domainname, |
@@ -355,8 +361,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | |||
355 | struct tomoyo_domain_initializer_entry *ptr; | 361 | struct tomoyo_domain_initializer_entry *ptr; |
356 | bool flag = false; | 362 | bool flag = false; |
357 | 363 | ||
358 | down_read(&tomoyo_domain_initializer_list_lock); | 364 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { |
359 | list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { | ||
360 | if (ptr->is_deleted) | 365 | if (ptr->is_deleted) |
361 | continue; | 366 | continue; |
362 | if (ptr->domainname) { | 367 | if (ptr->domainname) { |
@@ -376,7 +381,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | |||
376 | } | 381 | } |
377 | flag = true; | 382 | flag = true; |
378 | } | 383 | } |
379 | up_read(&tomoyo_domain_initializer_list_lock); | ||
380 | return flag; | 384 | return flag; |
381 | } | 385 | } |
382 | 386 | ||
@@ -430,6 +434,8 @@ static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock); | |||
430 | * @is_delete: True if it is a delete request. | 434 | * @is_delete: True if it is a delete request. |
431 | * | 435 | * |
432 | * Returns 0 on success, negative value otherwise. | 436 | * Returns 0 on success, negative value otherwise. |
437 | * | ||
438 | * Caller holds tomoyo_read_lock(). | ||
433 | */ | 439 | */ |
434 | static int tomoyo_update_domain_keeper_entry(const char *domainname, | 440 | static int tomoyo_update_domain_keeper_entry(const char *domainname, |
435 | const char *program, | 441 | const char *program, |
@@ -459,7 +465,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
459 | if (!saved_domainname) | 465 | if (!saved_domainname) |
460 | return -ENOMEM; | 466 | return -ENOMEM; |
461 | down_write(&tomoyo_domain_keeper_list_lock); | 467 | down_write(&tomoyo_domain_keeper_list_lock); |
462 | list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { | 468 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { |
463 | if (ptr->is_not != is_not || | 469 | if (ptr->is_not != is_not || |
464 | ptr->domainname != saved_domainname || | 470 | ptr->domainname != saved_domainname || |
465 | ptr->program != saved_program) | 471 | ptr->program != saved_program) |
@@ -479,7 +485,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
479 | new_entry->program = saved_program; | 485 | new_entry->program = saved_program; |
480 | new_entry->is_not = is_not; | 486 | new_entry->is_not = is_not; |
481 | new_entry->is_last_name = is_last_name; | 487 | new_entry->is_last_name = is_last_name; |
482 | list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list); | 488 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); |
483 | error = 0; | 489 | error = 0; |
484 | out: | 490 | out: |
485 | up_write(&tomoyo_domain_keeper_list_lock); | 491 | up_write(&tomoyo_domain_keeper_list_lock); |
@@ -493,6 +499,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
493 | * @is_not: True if it is "no_keep_domain" entry. | 499 | * @is_not: True if it is "no_keep_domain" entry. |
494 | * @is_delete: True if it is a delete request. | 500 | * @is_delete: True if it is a delete request. |
495 | * | 501 | * |
502 | * Caller holds tomoyo_read_lock(). | ||
496 | */ | 503 | */ |
497 | int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, | 504 | int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, |
498 | const bool is_delete) | 505 | const bool is_delete) |
@@ -513,13 +520,14 @@ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, | |||
513 | * @head: Pointer to "struct tomoyo_io_buffer". | 520 | * @head: Pointer to "struct tomoyo_io_buffer". |
514 | * | 521 | * |
515 | * Returns true on success, false otherwise. | 522 | * Returns true on success, false otherwise. |
523 | * | ||
524 | * Caller holds tomoyo_read_lock(). | ||
516 | */ | 525 | */ |
517 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) | 526 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) |
518 | { | 527 | { |
519 | struct list_head *pos; | 528 | struct list_head *pos; |
520 | bool done = true; | 529 | bool done = true; |
521 | 530 | ||
522 | down_read(&tomoyo_domain_keeper_list_lock); | ||
523 | list_for_each_cookie(pos, head->read_var2, | 531 | list_for_each_cookie(pos, head->read_var2, |
524 | &tomoyo_domain_keeper_list) { | 532 | &tomoyo_domain_keeper_list) { |
525 | struct tomoyo_domain_keeper_entry *ptr; | 533 | struct tomoyo_domain_keeper_entry *ptr; |
@@ -542,7 +550,6 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) | |||
542 | if (!done) | 550 | if (!done) |
543 | break; | 551 | break; |
544 | } | 552 | } |
545 | up_read(&tomoyo_domain_keeper_list_lock); | ||
546 | return done; | 553 | return done; |
547 | } | 554 | } |
548 | 555 | ||
@@ -555,6 +562,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) | |||
555 | * | 562 | * |
556 | * Returns true if executing @program supresses domain transition, | 563 | * Returns true if executing @program supresses domain transition, |
557 | * false otherwise. | 564 | * false otherwise. |
565 | * | ||
566 | * Caller holds tomoyo_read_lock(). | ||
558 | */ | 567 | */ |
559 | static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | 568 | static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, |
560 | const struct tomoyo_path_info *program, | 569 | const struct tomoyo_path_info *program, |
@@ -563,8 +572,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | |||
563 | struct tomoyo_domain_keeper_entry *ptr; | 572 | struct tomoyo_domain_keeper_entry *ptr; |
564 | bool flag = false; | 573 | bool flag = false; |
565 | 574 | ||
566 | down_read(&tomoyo_domain_keeper_list_lock); | 575 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { |
567 | list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { | ||
568 | if (ptr->is_deleted) | 576 | if (ptr->is_deleted) |
569 | continue; | 577 | continue; |
570 | if (!ptr->is_last_name) { | 578 | if (!ptr->is_last_name) { |
@@ -582,7 +590,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | |||
582 | } | 590 | } |
583 | flag = true; | 591 | flag = true; |
584 | } | 592 | } |
585 | up_read(&tomoyo_domain_keeper_list_lock); | ||
586 | return flag; | 593 | return flag; |
587 | } | 594 | } |
588 | 595 | ||
@@ -627,6 +634,8 @@ static DECLARE_RWSEM(tomoyo_alias_list_lock); | |||
627 | * @is_delete: True if it is a delete request. | 634 | * @is_delete: True if it is a delete request. |
628 | * | 635 | * |
629 | * Returns 0 on success, negative value otherwise. | 636 | * Returns 0 on success, negative value otherwise. |
637 | * | ||
638 | * Caller holds tomoyo_read_lock(). | ||
630 | */ | 639 | */ |
631 | static int tomoyo_update_alias_entry(const char *original_name, | 640 | static int tomoyo_update_alias_entry(const char *original_name, |
632 | const char *aliased_name, | 641 | const char *aliased_name, |
@@ -646,7 +655,7 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
646 | if (!saved_original_name || !saved_aliased_name) | 655 | if (!saved_original_name || !saved_aliased_name) |
647 | return -ENOMEM; | 656 | return -ENOMEM; |
648 | down_write(&tomoyo_alias_list_lock); | 657 | down_write(&tomoyo_alias_list_lock); |
649 | list_for_each_entry(ptr, &tomoyo_alias_list, list) { | 658 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { |
650 | if (ptr->original_name != saved_original_name || | 659 | if (ptr->original_name != saved_original_name || |
651 | ptr->aliased_name != saved_aliased_name) | 660 | ptr->aliased_name != saved_aliased_name) |
652 | continue; | 661 | continue; |
@@ -663,7 +672,7 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
663 | goto out; | 672 | goto out; |
664 | new_entry->original_name = saved_original_name; | 673 | new_entry->original_name = saved_original_name; |
665 | new_entry->aliased_name = saved_aliased_name; | 674 | new_entry->aliased_name = saved_aliased_name; |
666 | list_add_tail(&new_entry->list, &tomoyo_alias_list); | 675 | list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); |
667 | error = 0; | 676 | error = 0; |
668 | out: | 677 | out: |
669 | up_write(&tomoyo_alias_list_lock); | 678 | up_write(&tomoyo_alias_list_lock); |
@@ -676,13 +685,14 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
676 | * @head: Pointer to "struct tomoyo_io_buffer". | 685 | * @head: Pointer to "struct tomoyo_io_buffer". |
677 | * | 686 | * |
678 | * Returns true on success, false otherwise. | 687 | * Returns true on success, false otherwise. |
688 | * | ||
689 | * Caller holds tomoyo_read_lock(). | ||
679 | */ | 690 | */ |
680 | bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) | 691 | bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) |
681 | { | 692 | { |
682 | struct list_head *pos; | 693 | struct list_head *pos; |
683 | bool done = true; | 694 | bool done = true; |
684 | 695 | ||
685 | down_read(&tomoyo_alias_list_lock); | ||
686 | list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { | 696 | list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { |
687 | struct tomoyo_alias_entry *ptr; | 697 | struct tomoyo_alias_entry *ptr; |
688 | 698 | ||
@@ -695,7 +705,6 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) | |||
695 | if (!done) | 705 | if (!done) |
696 | break; | 706 | break; |
697 | } | 707 | } |
698 | up_read(&tomoyo_alias_list_lock); | ||
699 | return done; | 708 | return done; |
700 | } | 709 | } |
701 | 710 | ||
@@ -706,6 +715,8 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) | |||
706 | * @is_delete: True if it is a delete request. | 715 | * @is_delete: True if it is a delete request. |
707 | * | 716 | * |
708 | * Returns 0 on success, negative value otherwise. | 717 | * Returns 0 on success, negative value otherwise. |
718 | * | ||
719 | * Caller holds tomoyo_read_lock(). | ||
709 | */ | 720 | */ |
710 | int tomoyo_write_alias_policy(char *data, const bool is_delete) | 721 | int tomoyo_write_alias_policy(char *data, const bool is_delete) |
711 | { | 722 | { |
@@ -724,6 +735,8 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete) | |||
724 | * @profile: Profile number to assign if the domain was newly created. | 735 | * @profile: Profile number to assign if the domain was newly created. |
725 | * | 736 | * |
726 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. | 737 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. |
738 | * | ||
739 | * Caller holds tomoyo_read_lock(). | ||
727 | */ | 740 | */ |
728 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | 741 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * |
729 | domainname, | 742 | domainname, |
@@ -742,7 +755,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
742 | if (!saved_domainname) | 755 | if (!saved_domainname) |
743 | goto out; | 756 | goto out; |
744 | /* Can I reuse memory of deleted domain? */ | 757 | /* Can I reuse memory of deleted domain? */ |
745 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | 758 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
746 | struct task_struct *p; | 759 | struct task_struct *p; |
747 | struct tomoyo_acl_info *ptr; | 760 | struct tomoyo_acl_info *ptr; |
748 | bool flag; | 761 | bool flag; |
@@ -760,7 +773,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
760 | read_unlock(&tasklist_lock); | 773 | read_unlock(&tasklist_lock); |
761 | if (flag) | 774 | if (flag) |
762 | continue; | 775 | continue; |
763 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 776 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
764 | ptr->type |= TOMOYO_ACL_DELETED; | 777 | ptr->type |= TOMOYO_ACL_DELETED; |
765 | } | 778 | } |
766 | tomoyo_set_domain_flag(domain, true, domain->flags); | 779 | tomoyo_set_domain_flag(domain, true, domain->flags); |
@@ -776,7 +789,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
776 | INIT_LIST_HEAD(&domain->acl_info_list); | 789 | INIT_LIST_HEAD(&domain->acl_info_list); |
777 | domain->domainname = saved_domainname; | 790 | domain->domainname = saved_domainname; |
778 | domain->profile = profile; | 791 | domain->profile = profile; |
779 | list_add_tail(&domain->list, &tomoyo_domain_list); | 792 | list_add_tail_rcu(&domain->list, &tomoyo_domain_list); |
780 | } | 793 | } |
781 | out: | 794 | out: |
782 | up_write(&tomoyo_domain_list_lock); | 795 | up_write(&tomoyo_domain_list_lock); |
@@ -789,6 +802,8 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
789 | * @bprm: Pointer to "struct linux_binprm". | 802 | * @bprm: Pointer to "struct linux_binprm". |
790 | * | 803 | * |
791 | * Returns 0 on success, negative value otherwise. | 804 | * Returns 0 on success, negative value otherwise. |
805 | * | ||
806 | * Caller holds tomoyo_read_lock(). | ||
792 | */ | 807 | */ |
793 | int tomoyo_find_next_domain(struct linux_binprm *bprm) | 808 | int tomoyo_find_next_domain(struct linux_binprm *bprm) |
794 | { | 809 | { |
@@ -849,8 +864,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
849 | if (tomoyo_pathcmp(&r, &s)) { | 864 | if (tomoyo_pathcmp(&r, &s)) { |
850 | struct tomoyo_alias_entry *ptr; | 865 | struct tomoyo_alias_entry *ptr; |
851 | /* Is this program allowed to be called via symbolic links? */ | 866 | /* Is this program allowed to be called via symbolic links? */ |
852 | down_read(&tomoyo_alias_list_lock); | 867 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { |
853 | list_for_each_entry(ptr, &tomoyo_alias_list, list) { | ||
854 | if (ptr->is_deleted || | 868 | if (ptr->is_deleted || |
855 | tomoyo_pathcmp(&r, ptr->original_name) || | 869 | tomoyo_pathcmp(&r, ptr->original_name) || |
856 | tomoyo_pathcmp(&s, ptr->aliased_name)) | 870 | tomoyo_pathcmp(&s, ptr->aliased_name)) |
@@ -861,7 +875,6 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
861 | tomoyo_fill_path_info(&r); | 875 | tomoyo_fill_path_info(&r); |
862 | break; | 876 | break; |
863 | } | 877 | } |
864 | up_read(&tomoyo_alias_list_lock); | ||
865 | } | 878 | } |
866 | 879 | ||
867 | /* Check execute permission. */ | 880 | /* Check execute permission. */ |
@@ -892,9 +905,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
892 | } | 905 | } |
893 | if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) | 906 | if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) |
894 | goto done; | 907 | goto done; |
895 | down_read(&tomoyo_domain_list_lock); | ||
896 | domain = tomoyo_find_domain(new_domain_name); | 908 | domain = tomoyo_find_domain(new_domain_name); |
897 | up_read(&tomoyo_domain_list_lock); | ||
898 | if (domain) | 909 | if (domain) |
899 | goto done; | 910 | goto done; |
900 | if (is_enforce) | 911 | if (is_enforce) |