diff options
-rw-r--r-- | security/tomoyo/common.c | 22 | ||||
-rw-r--r-- | security/tomoyo/common.h | 27 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 2 | ||||
-rw-r--r-- | security/tomoyo/file.c | 315 | ||||
-rw-r--r-- | security/tomoyo/tomoyo.c | 2 |
5 files changed, 162 insertions, 206 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index d82c2978b1be..34d65871096c 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -985,21 +985,6 @@ static const char *tomoyo_get_exe(void) | |||
985 | } | 985 | } |
986 | 986 | ||
987 | /** | 987 | /** |
988 | * tomoyo_get_msg - Get warning message. | ||
989 | * | ||
990 | * @is_enforce: Is it enforcing mode? | ||
991 | * | ||
992 | * Returns "ERROR" or "WARNING". | ||
993 | */ | ||
994 | const char *tomoyo_get_msg(const bool is_enforce) | ||
995 | { | ||
996 | if (is_enforce) | ||
997 | return "ERROR"; | ||
998 | else | ||
999 | return "WARNING"; | ||
1000 | } | ||
1001 | |||
1002 | /** | ||
1003 | * tomoyo_check_flags - Check mode for specified functionality. | 988 | * tomoyo_check_flags - Check mode for specified functionality. |
1004 | * | 989 | * |
1005 | * @domain: Pointer to "struct tomoyo_domain_info". | 990 | * @domain: Pointer to "struct tomoyo_domain_info". |
@@ -1040,17 +1025,20 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain) | |||
1040 | /** | 1025 | /** |
1041 | * tomoyo_domain_quota_is_ok - Check for domain's quota. | 1026 | * tomoyo_domain_quota_is_ok - Check for domain's quota. |
1042 | * | 1027 | * |
1043 | * @domain: Pointer to "struct tomoyo_domain_info". | 1028 | * @r: Pointer to "struct tomoyo_request_info". |
1044 | * | 1029 | * |
1045 | * Returns true if the domain is not exceeded quota, false otherwise. | 1030 | * Returns true if the domain is not exceeded quota, false otherwise. |
1046 | * | 1031 | * |
1047 | * Caller holds tomoyo_read_lock(). | 1032 | * Caller holds tomoyo_read_lock(). |
1048 | */ | 1033 | */ |
1049 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) | 1034 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) |
1050 | { | 1035 | { |
1051 | unsigned int count = 0; | 1036 | unsigned int count = 0; |
1037 | struct tomoyo_domain_info *domain = r->domain; | ||
1052 | struct tomoyo_acl_info *ptr; | 1038 | struct tomoyo_acl_info *ptr; |
1053 | 1039 | ||
1040 | if (r->mode != TOMOYO_CONFIG_LEARNING) | ||
1041 | return false; | ||
1054 | if (!domain) | 1042 | if (!domain) |
1055 | return true; | 1043 | return true; |
1056 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 1044 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 33d3072f9bb4..91e2bcfd56e3 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -44,6 +44,13 @@ struct linux_binprm; | |||
44 | /* Profile number is an integer between 0 and 255. */ | 44 | /* Profile number is an integer between 0 and 255. */ |
45 | #define TOMOYO_MAX_PROFILES 256 | 45 | #define TOMOYO_MAX_PROFILES 256 |
46 | 46 | ||
47 | enum tomoyo_mode_index { | ||
48 | TOMOYO_CONFIG_DISABLED, | ||
49 | TOMOYO_CONFIG_LEARNING, | ||
50 | TOMOYO_CONFIG_PERMISSIVE, | ||
51 | TOMOYO_CONFIG_ENFORCING | ||
52 | }; | ||
53 | |||
47 | /* Keywords for ACLs. */ | 54 | /* Keywords for ACLs. */ |
48 | #define TOMOYO_KEYWORD_ALIAS "alias " | 55 | #define TOMOYO_KEYWORD_ALIAS "alias " |
49 | #define TOMOYO_KEYWORD_ALLOW_READ "allow_read " | 56 | #define TOMOYO_KEYWORD_ALLOW_READ "allow_read " |
@@ -153,6 +160,17 @@ struct tomoyo_page_buffer { | |||
153 | }; | 160 | }; |
154 | 161 | ||
155 | /* | 162 | /* |
163 | * tomoyo_request_info is a structure which is used for holding | ||
164 | * | ||
165 | * (1) Domain information of current process. | ||
166 | * (2) Access control mode of the profile. | ||
167 | */ | ||
168 | struct tomoyo_request_info { | ||
169 | struct tomoyo_domain_info *domain; | ||
170 | u8 mode; /* One of tomoyo_mode_index . */ | ||
171 | }; | ||
172 | |||
173 | /* | ||
156 | * tomoyo_path_info is a structure which is used for holding a string data | 174 | * tomoyo_path_info is a structure which is used for holding a string data |
157 | * used by TOMOYO. | 175 | * used by TOMOYO. |
158 | * This structure has several fields for supporting pattern matching. | 176 | * This structure has several fields for supporting pattern matching. |
@@ -332,8 +350,8 @@ struct tomoyo_domain_info { | |||
332 | * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", | 350 | * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", |
333 | * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock", | 351 | * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock", |
334 | * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite", | 352 | * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite", |
335 | * "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", "allow_mount" | 353 | * "allow_ioctl", "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", |
336 | * and "allow_unmount". | 354 | * "allow_mount" and "allow_unmount". |
337 | */ | 355 | */ |
338 | struct tomoyo_path_acl { | 356 | struct tomoyo_path_acl { |
339 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ | 357 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ |
@@ -567,7 +585,7 @@ struct tomoyo_policy_manager_entry { | |||
567 | bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, | 585 | bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, |
568 | const struct tomoyo_name_union *ptr); | 586 | const struct tomoyo_name_union *ptr); |
569 | /* Check whether the domain has too many ACL entries to hold. */ | 587 | /* Check whether the domain has too many ACL entries to hold. */ |
570 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); | 588 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); |
571 | /* Transactional sprintf() for policy dump. */ | 589 | /* Transactional sprintf() for policy dump. */ |
572 | bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) | 590 | bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) |
573 | __attribute__ ((format(printf, 2, 3))); | 591 | __attribute__ ((format(printf, 2, 3))); |
@@ -623,8 +641,6 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); | |||
623 | const char *tomoyo_path22keyword(const u8 operation); | 641 | const char *tomoyo_path22keyword(const u8 operation); |
624 | /* Get the last component of the given domainname. */ | 642 | /* Get the last component of the given domainname. */ |
625 | const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); | 643 | const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); |
626 | /* Get warning message. */ | ||
627 | const char *tomoyo_get_msg(const bool is_enforce); | ||
628 | /* Convert single path operation to operation name. */ | 644 | /* Convert single path operation to operation name. */ |
629 | const char *tomoyo_path2keyword(const u8 operation); | 645 | const char *tomoyo_path2keyword(const u8 operation); |
630 | /* Create "alias" entry in exception policy. */ | 646 | /* Create "alias" entry in exception policy. */ |
@@ -723,7 +739,6 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
723 | int tomoyo_path_perm(const u8 operation, struct path *path); | 739 | int tomoyo_path_perm(const u8 operation, struct path *path); |
724 | int tomoyo_path2_perm(const u8 operation, struct path *path1, | 740 | int tomoyo_path2_perm(const u8 operation, struct path *path1, |
725 | struct path *path2); | 741 | struct path *path2); |
726 | int tomoyo_check_rewrite_permission(struct file *filp); | ||
727 | int tomoyo_find_next_domain(struct linux_binprm *bprm); | 742 | int tomoyo_find_next_domain(struct linux_binprm *bprm); |
728 | 743 | ||
729 | /* Drop refcount on tomoyo_name_union. */ | 744 | /* Drop refcount on tomoyo_name_union. */ |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index cd8ba4446763..afdf26128bfe 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -691,7 +691,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
691 | char *real_program_name = NULL; | 691 | char *real_program_name = NULL; |
692 | char *symlink_program_name = NULL; | 692 | char *symlink_program_name = NULL; |
693 | const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); | 693 | const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); |
694 | const bool is_enforce = (mode == 3); | 694 | const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); |
695 | int retval = -ENOMEM; | 695 | int retval = -ENOMEM; |
696 | struct tomoyo_path_info r; /* real name */ | 696 | struct tomoyo_path_info r; /* real name */ |
697 | struct tomoyo_path_info s; /* symlink name */ | 697 | struct tomoyo_path_info s; /* symlink name */ |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 2dffe0730918..f1d2adfd33bc 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -91,6 +91,61 @@ bool tomoyo_compare_number_union(const unsigned long value, | |||
91 | } | 91 | } |
92 | 92 | ||
93 | /** | 93 | /** |
94 | * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members. | ||
95 | * | ||
96 | * @r: Pointer to "struct tomoyo_request_info" to initialize. | ||
97 | * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain(). | ||
98 | * | ||
99 | * Returns mode. | ||
100 | */ | ||
101 | static int tomoyo_init_request_info(struct tomoyo_request_info *r, | ||
102 | struct tomoyo_domain_info *domain) | ||
103 | { | ||
104 | memset(r, 0, sizeof(*r)); | ||
105 | if (!domain) | ||
106 | domain = tomoyo_domain(); | ||
107 | r->domain = domain; | ||
108 | r->mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | ||
109 | return r->mode; | ||
110 | } | ||
111 | |||
112 | static void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) | ||
113 | __attribute__ ((format(printf, 2, 3))); | ||
114 | /** | ||
115 | * tomoyo_warn_log - Print warning or error message on console. | ||
116 | * | ||
117 | * @r: Pointer to "struct tomoyo_request_info". | ||
118 | * @fmt: The printf()'s format string, followed by parameters. | ||
119 | */ | ||
120 | static void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) | ||
121 | { | ||
122 | int len = PAGE_SIZE; | ||
123 | va_list args; | ||
124 | char *buffer; | ||
125 | if (!tomoyo_verbose_mode(r->domain)) | ||
126 | return; | ||
127 | while (1) { | ||
128 | int len2; | ||
129 | buffer = kmalloc(len, GFP_NOFS); | ||
130 | if (!buffer) | ||
131 | return; | ||
132 | va_start(args, fmt); | ||
133 | len2 = vsnprintf(buffer, len - 1, fmt, args); | ||
134 | va_end(args); | ||
135 | if (len2 <= len - 1) { | ||
136 | buffer[len2] = '\0'; | ||
137 | break; | ||
138 | } | ||
139 | len = len2 + 1; | ||
140 | kfree(buffer); | ||
141 | } | ||
142 | printk(KERN_WARNING "TOMOYO-%s: Access %s denied for %s\n", | ||
143 | r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", | ||
144 | buffer, tomoyo_get_last_name(r->domain)); | ||
145 | kfree(buffer); | ||
146 | } | ||
147 | |||
148 | /** | ||
94 | * tomoyo_path2keyword - Get the name of single path operation. | 149 | * tomoyo_path2keyword - Get the name of single path operation. |
95 | * | 150 | * |
96 | * @operation: Type of operation. | 151 | * @operation: Type of operation. |
@@ -652,9 +707,9 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, | |||
652 | } | 707 | } |
653 | 708 | ||
654 | /** | 709 | /** |
655 | * tomoyo_path_acl2 - Check permission for single path operation. | 710 | * tomoyo_path_acl - Check permission for single path operation. |
656 | * | 711 | * |
657 | * @domain: Pointer to "struct tomoyo_domain_info". | 712 | * @r: Pointer to "struct tomoyo_request_info". |
658 | * @filename: Filename to check. | 713 | * @filename: Filename to check. |
659 | * @perm: Permission. | 714 | * @perm: Permission. |
660 | * @may_use_pattern: True if patterned ACL is permitted. | 715 | * @may_use_pattern: True if patterned ACL is permitted. |
@@ -663,10 +718,11 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, | |||
663 | * | 718 | * |
664 | * Caller holds tomoyo_read_lock(). | 719 | * Caller holds tomoyo_read_lock(). |
665 | */ | 720 | */ |
666 | static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain, | 721 | static int tomoyo_path_acl(const struct tomoyo_request_info *r, |
667 | const struct tomoyo_path_info *filename, | 722 | const struct tomoyo_path_info *filename, |
668 | const u32 perm, const bool may_use_pattern) | 723 | const u32 perm, const bool may_use_pattern) |
669 | { | 724 | { |
725 | struct tomoyo_domain_info *domain = r->domain; | ||
670 | struct tomoyo_acl_info *ptr; | 726 | struct tomoyo_acl_info *ptr; |
671 | int error = -EPERM; | 727 | int error = -EPERM; |
672 | 728 | ||
@@ -692,89 +748,56 @@ static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain, | |||
692 | } | 748 | } |
693 | 749 | ||
694 | /** | 750 | /** |
695 | * tomoyo_check_file_acl - Check permission for opening files. | 751 | * tomoyo_file_perm - Check permission for opening files. |
696 | * | 752 | * |
697 | * @domain: Pointer to "struct tomoyo_domain_info". | 753 | * @r: Pointer to "struct tomoyo_request_info". |
698 | * @filename: Filename to check. | 754 | * @filename: Filename to check. |
699 | * @operation: Mode ("read" or "write" or "read/write" or "execute"). | 755 | * @mode: Mode ("read" or "write" or "read/write" or "execute"). |
700 | * | ||
701 | * Returns 0 on success, -EPERM otherwise. | ||
702 | * | ||
703 | * Caller holds tomoyo_read_lock(). | ||
704 | */ | ||
705 | static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, | ||
706 | const struct tomoyo_path_info *filename, | ||
707 | const u8 operation) | ||
708 | { | ||
709 | u32 perm = 0; | ||
710 | |||
711 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | ||
712 | return 0; | ||
713 | if (operation == 6) | ||
714 | perm = 1 << TOMOYO_TYPE_READ_WRITE; | ||
715 | else if (operation == 4) | ||
716 | perm = 1 << TOMOYO_TYPE_READ; | ||
717 | else if (operation == 2) | ||
718 | perm = 1 << TOMOYO_TYPE_WRITE; | ||
719 | else if (operation == 1) | ||
720 | perm = 1 << TOMOYO_TYPE_EXECUTE; | ||
721 | else | ||
722 | BUG(); | ||
723 | return tomoyo_path_acl2(domain, filename, perm, operation != 1); | ||
724 | } | ||
725 | |||
726 | /** | ||
727 | * tomoyo_check_file_perm2 - Check permission for opening files. | ||
728 | * | ||
729 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
730 | * @filename: Filename to check. | ||
731 | * @perm: Mode ("read" or "write" or "read/write" or "execute"). | ||
732 | * @operation: Operation name passed used for verbose mode. | ||
733 | * @mode: Access control mode. | ||
734 | * | 756 | * |
735 | * Returns 0 on success, negative value otherwise. | 757 | * Returns 0 on success, negative value otherwise. |
736 | * | 758 | * |
737 | * Caller holds tomoyo_read_lock(). | 759 | * Caller holds tomoyo_read_lock(). |
738 | */ | 760 | */ |
739 | static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | 761 | static int tomoyo_file_perm(struct tomoyo_request_info *r, |
740 | const struct tomoyo_path_info *filename, | 762 | const struct tomoyo_path_info *filename, |
741 | const u8 perm, const char *operation, | 763 | const u8 mode) |
742 | const u8 mode) | ||
743 | { | 764 | { |
744 | const bool is_enforce = (mode == 3); | ||
745 | const char *msg = "<unknown>"; | 765 | const char *msg = "<unknown>"; |
746 | int error = 0; | 766 | int error = 0; |
767 | u32 perm = 0; | ||
747 | 768 | ||
748 | if (!filename) | 769 | if (!filename) |
749 | return 0; | 770 | return 0; |
750 | error = tomoyo_check_file_acl(domain, filename, perm); | 771 | |
751 | if (error && perm == 4 && !domain->ignore_global_allow_read | 772 | if (mode == 6) { |
752 | && tomoyo_is_globally_readable_file(filename)) | ||
753 | error = 0; | ||
754 | if (perm == 6) | ||
755 | msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE); | 773 | msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE); |
756 | else if (perm == 4) | 774 | perm = 1 << TOMOYO_TYPE_READ_WRITE; |
775 | } else if (mode == 4) { | ||
757 | msg = tomoyo_path2keyword(TOMOYO_TYPE_READ); | 776 | msg = tomoyo_path2keyword(TOMOYO_TYPE_READ); |
758 | else if (perm == 2) | 777 | perm = 1 << TOMOYO_TYPE_READ; |
778 | } else if (mode == 2) { | ||
759 | msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE); | 779 | msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE); |
760 | else if (perm == 1) | 780 | perm = 1 << TOMOYO_TYPE_WRITE; |
781 | } else if (mode == 1) { | ||
761 | msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE); | 782 | msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE); |
762 | else | 783 | perm = 1 << TOMOYO_TYPE_EXECUTE; |
784 | } else | ||
763 | BUG(); | 785 | BUG(); |
786 | error = tomoyo_path_acl(r, filename, perm, mode != 1); | ||
787 | if (error && mode == 4 && !r->domain->ignore_global_allow_read | ||
788 | && tomoyo_is_globally_readable_file(filename)) | ||
789 | error = 0; | ||
764 | if (!error) | 790 | if (!error) |
765 | return 0; | 791 | return 0; |
766 | if (tomoyo_verbose_mode(domain)) | 792 | tomoyo_warn_log(r, "%s %s", msg, filename->name); |
767 | printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied " | 793 | if (r->mode == TOMOYO_CONFIG_ENFORCING) |
768 | "for %s\n", tomoyo_get_msg(is_enforce), msg, operation, | ||
769 | filename->name, tomoyo_get_last_name(domain)); | ||
770 | if (is_enforce) | ||
771 | return error; | 794 | return error; |
772 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { | 795 | if (tomoyo_domain_quota_is_ok(r)) { |
773 | /* Don't use patterns for execute permission. */ | 796 | /* Don't use patterns for execute permission. */ |
774 | const struct tomoyo_path_info *patterned_file = (perm != 1) ? | 797 | const struct tomoyo_path_info *patterned_file = (mode != 1) ? |
775 | tomoyo_get_file_pattern(filename) : filename; | 798 | tomoyo_get_file_pattern(filename) : filename; |
776 | tomoyo_update_file_acl(patterned_file->name, perm, | 799 | tomoyo_update_file_acl(patterned_file->name, mode, |
777 | domain, false); | 800 | r->domain, false); |
778 | } | 801 | } |
779 | return 0; | 802 | return 0; |
780 | } | 803 | } |
@@ -966,28 +989,9 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | |||
966 | } | 989 | } |
967 | 990 | ||
968 | /** | 991 | /** |
969 | * tomoyo_path_acl - Check permission for single path operation. | ||
970 | * | ||
971 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
972 | * @type: Type of operation. | ||
973 | * @filename: Filename to check. | ||
974 | * | ||
975 | * Returns 0 on success, negative value otherwise. | ||
976 | * | ||
977 | * Caller holds tomoyo_read_lock(). | ||
978 | */ | ||
979 | static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type, | ||
980 | const struct tomoyo_path_info *filename) | ||
981 | { | ||
982 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | ||
983 | return 0; | ||
984 | return tomoyo_path_acl2(domain, filename, 1 << type, 1); | ||
985 | } | ||
986 | |||
987 | /** | ||
988 | * tomoyo_path2_acl - Check permission for double path operation. | 992 | * tomoyo_path2_acl - Check permission for double path operation. |
989 | * | 993 | * |
990 | * @domain: Pointer to "struct tomoyo_domain_info". | 994 | * @r: Pointer to "struct tomoyo_request_info". |
991 | * @type: Type of operation. | 995 | * @type: Type of operation. |
992 | * @filename1: First filename to check. | 996 | * @filename1: First filename to check. |
993 | * @filename2: Second filename to check. | 997 | * @filename2: Second filename to check. |
@@ -996,17 +1000,15 @@ static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type, | |||
996 | * | 1000 | * |
997 | * Caller holds tomoyo_read_lock(). | 1001 | * Caller holds tomoyo_read_lock(). |
998 | */ | 1002 | */ |
999 | static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain, | 1003 | static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type, |
1000 | const u8 type, | ||
1001 | const struct tomoyo_path_info *filename1, | 1004 | const struct tomoyo_path_info *filename1, |
1002 | const struct tomoyo_path_info *filename2) | 1005 | const struct tomoyo_path_info *filename2) |
1003 | { | 1006 | { |
1007 | const struct tomoyo_domain_info *domain = r->domain; | ||
1004 | struct tomoyo_acl_info *ptr; | 1008 | struct tomoyo_acl_info *ptr; |
1005 | const u8 perm = 1 << type; | 1009 | const u8 perm = 1 << type; |
1006 | int error = -EPERM; | 1010 | int error = -EPERM; |
1007 | 1011 | ||
1008 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | ||
1009 | return 0; | ||
1010 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 1012 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
1011 | struct tomoyo_path2_acl *acl; | 1013 | struct tomoyo_path2_acl *acl; |
1012 | if (ptr->type != TOMOYO_TYPE_PATH2_ACL) | 1014 | if (ptr->type != TOMOYO_TYPE_PATH2_ACL) |
@@ -1025,42 +1027,32 @@ static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain, | |||
1025 | } | 1027 | } |
1026 | 1028 | ||
1027 | /** | 1029 | /** |
1028 | * tomoyo_path_permission2 - Check permission for single path operation. | 1030 | * tomoyo_path_permission - Check permission for single path operation. |
1029 | * | 1031 | * |
1030 | * @domain: Pointer to "struct tomoyo_domain_info". | 1032 | * @r: Pointer to "struct tomoyo_request_info". |
1031 | * @operation: Type of operation. | 1033 | * @operation: Type of operation. |
1032 | * @filename: Filename to check. | 1034 | * @filename: Filename to check. |
1033 | * @mode: Access control mode. | ||
1034 | * | 1035 | * |
1035 | * Returns 0 on success, negative value otherwise. | 1036 | * Returns 0 on success, negative value otherwise. |
1036 | * | 1037 | * |
1037 | * Caller holds tomoyo_read_lock(). | 1038 | * Caller holds tomoyo_read_lock(). |
1038 | */ | 1039 | */ |
1039 | static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain, | 1040 | static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, |
1040 | u8 operation, | 1041 | const struct tomoyo_path_info *filename) |
1041 | const struct tomoyo_path_info *filename, | ||
1042 | const u8 mode) | ||
1043 | { | 1042 | { |
1044 | const char *msg; | ||
1045 | int error; | 1043 | int error; |
1046 | const bool is_enforce = (mode == 3); | ||
1047 | 1044 | ||
1048 | if (!mode) | ||
1049 | return 0; | ||
1050 | next: | 1045 | next: |
1051 | error = tomoyo_path_acl(domain, operation, filename); | 1046 | error = tomoyo_path_acl(r, filename, 1 << operation, 1); |
1052 | msg = tomoyo_path2keyword(operation); | ||
1053 | if (!error) | 1047 | if (!error) |
1054 | goto ok; | 1048 | goto ok; |
1055 | if (tomoyo_verbose_mode(domain)) | 1049 | tomoyo_warn_log(r, "%s %s", tomoyo_path2keyword(operation), |
1056 | printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n", | 1050 | filename->name); |
1057 | tomoyo_get_msg(is_enforce), msg, filename->name, | 1051 | if (tomoyo_domain_quota_is_ok(r)) { |
1058 | tomoyo_get_last_name(domain)); | ||
1059 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { | ||
1060 | const char *name = tomoyo_get_file_pattern(filename)->name; | 1052 | const char *name = tomoyo_get_file_pattern(filename)->name; |
1061 | tomoyo_update_path_acl(operation, name, domain, false); | 1053 | tomoyo_update_path_acl(operation, name, r->domain, false); |
1062 | } | 1054 | } |
1063 | if (!is_enforce) | 1055 | if (r->mode != TOMOYO_CONFIG_ENFORCING) |
1064 | error = 0; | 1056 | error = 0; |
1065 | ok: | 1057 | ok: |
1066 | /* | 1058 | /* |
@@ -1089,11 +1081,11 @@ static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain, | |||
1089 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | 1081 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, |
1090 | const struct tomoyo_path_info *filename) | 1082 | const struct tomoyo_path_info *filename) |
1091 | { | 1083 | { |
1092 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1084 | struct tomoyo_request_info r; |
1093 | 1085 | ||
1094 | if (!mode) | 1086 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED) |
1095 | return 0; | 1087 | return 0; |
1096 | return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode); | 1088 | return tomoyo_file_perm(&r, filename, 1); |
1097 | } | 1089 | } |
1098 | 1090 | ||
1099 | /** | 1091 | /** |
@@ -1111,11 +1103,11 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1111 | const u8 acc_mode = ACC_MODE(flag); | 1103 | const u8 acc_mode = ACC_MODE(flag); |
1112 | int error = -ENOMEM; | 1104 | int error = -ENOMEM; |
1113 | struct tomoyo_path_info *buf; | 1105 | struct tomoyo_path_info *buf; |
1114 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1106 | struct tomoyo_request_info r; |
1115 | const bool is_enforce = (mode == 3); | ||
1116 | int idx; | 1107 | int idx; |
1117 | 1108 | ||
1118 | if (!mode || !path->mnt) | 1109 | if (tomoyo_init_request_info(&r, domain) == TOMOYO_CONFIG_DISABLED || |
1110 | !path->mnt) | ||
1119 | return 0; | 1111 | return 0; |
1120 | if (acc_mode == 0) | 1112 | if (acc_mode == 0) |
1121 | return 0; | 1113 | return 0; |
@@ -1138,25 +1130,22 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1138 | if ((acc_mode & MAY_WRITE) && | 1130 | if ((acc_mode & MAY_WRITE) && |
1139 | ((flag & O_TRUNC) || !(flag & O_APPEND)) && | 1131 | ((flag & O_TRUNC) || !(flag & O_APPEND)) && |
1140 | (tomoyo_is_no_rewrite_file(buf))) { | 1132 | (tomoyo_is_no_rewrite_file(buf))) { |
1141 | error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, | 1133 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, buf); |
1142 | buf, mode); | ||
1143 | } | 1134 | } |
1144 | if (!error) | 1135 | if (!error) |
1145 | error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open", | 1136 | error = tomoyo_file_perm(&r, buf, acc_mode); |
1146 | mode); | ||
1147 | if (!error && (flag & O_TRUNC)) | 1137 | if (!error && (flag & O_TRUNC)) |
1148 | error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE, | 1138 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_TRUNCATE, buf); |
1149 | buf, mode); | ||
1150 | out: | 1139 | out: |
1151 | kfree(buf); | 1140 | kfree(buf); |
1152 | tomoyo_read_unlock(idx); | 1141 | tomoyo_read_unlock(idx); |
1153 | if (!is_enforce) | 1142 | if (r.mode != TOMOYO_CONFIG_ENFORCING) |
1154 | error = 0; | 1143 | error = 0; |
1155 | return error; | 1144 | return error; |
1156 | } | 1145 | } |
1157 | 1146 | ||
1158 | /** | 1147 | /** |
1159 | * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount". | 1148 | * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "rewrite", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount". |
1160 | * | 1149 | * |
1161 | * @operation: Type of operation. | 1150 | * @operation: Type of operation. |
1162 | * @path: Pointer to "struct path". | 1151 | * @path: Pointer to "struct path". |
@@ -1167,18 +1156,23 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1167 | { | 1156 | { |
1168 | int error = -ENOMEM; | 1157 | int error = -ENOMEM; |
1169 | struct tomoyo_path_info *buf; | 1158 | struct tomoyo_path_info *buf; |
1170 | struct tomoyo_domain_info *domain = tomoyo_domain(); | 1159 | struct tomoyo_request_info r; |
1171 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | ||
1172 | const bool is_enforce = (mode == 3); | ||
1173 | int idx; | 1160 | int idx; |
1174 | 1161 | ||
1175 | if (!mode || !path->mnt) | 1162 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || |
1163 | !path->mnt) | ||
1176 | return 0; | 1164 | return 0; |
1177 | idx = tomoyo_read_lock(); | 1165 | idx = tomoyo_read_lock(); |
1178 | buf = tomoyo_get_path(path); | 1166 | buf = tomoyo_get_path(path); |
1179 | if (!buf) | 1167 | if (!buf) |
1180 | goto out; | 1168 | goto out; |
1181 | switch (operation) { | 1169 | switch (operation) { |
1170 | case TOMOYO_TYPE_REWRITE: | ||
1171 | if (!tomoyo_is_no_rewrite_file(buf)) { | ||
1172 | error = 0; | ||
1173 | goto out; | ||
1174 | } | ||
1175 | break; | ||
1182 | case TOMOYO_TYPE_MKDIR: | 1176 | case TOMOYO_TYPE_MKDIR: |
1183 | case TOMOYO_TYPE_RMDIR: | 1177 | case TOMOYO_TYPE_RMDIR: |
1184 | case TOMOYO_TYPE_CHROOT: | 1178 | case TOMOYO_TYPE_CHROOT: |
@@ -1190,47 +1184,11 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1190 | tomoyo_fill_path_info(buf); | 1184 | tomoyo_fill_path_info(buf); |
1191 | } | 1185 | } |
1192 | } | 1186 | } |
1193 | error = tomoyo_path_permission2(domain, operation, buf, mode); | 1187 | error = tomoyo_path_permission(&r, operation, buf); |
1194 | out: | ||
1195 | kfree(buf); | ||
1196 | tomoyo_read_unlock(idx); | ||
1197 | if (!is_enforce) | ||
1198 | error = 0; | ||
1199 | return error; | ||
1200 | } | ||
1201 | |||
1202 | /** | ||
1203 | * tomoyo_check_rewrite_permission - Check permission for "rewrite". | ||
1204 | * | ||
1205 | * @filp: Pointer to "struct file". | ||
1206 | * | ||
1207 | * Returns 0 on success, negative value otherwise. | ||
1208 | */ | ||
1209 | int tomoyo_check_rewrite_permission(struct file *filp) | ||
1210 | { | ||
1211 | int error = -ENOMEM; | ||
1212 | struct tomoyo_domain_info *domain = tomoyo_domain(); | ||
1213 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | ||
1214 | const bool is_enforce = (mode == 3); | ||
1215 | struct tomoyo_path_info *buf; | ||
1216 | int idx; | ||
1217 | |||
1218 | if (!mode || !filp->f_path.mnt) | ||
1219 | return 0; | ||
1220 | |||
1221 | idx = tomoyo_read_lock(); | ||
1222 | buf = tomoyo_get_path(&filp->f_path); | ||
1223 | if (!buf) | ||
1224 | goto out; | ||
1225 | if (!tomoyo_is_no_rewrite_file(buf)) { | ||
1226 | error = 0; | ||
1227 | goto out; | ||
1228 | } | ||
1229 | error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode); | ||
1230 | out: | 1188 | out: |
1231 | kfree(buf); | 1189 | kfree(buf); |
1232 | tomoyo_read_unlock(idx); | 1190 | tomoyo_read_unlock(idx); |
1233 | if (!is_enforce) | 1191 | if (r.mode != TOMOYO_CONFIG_ENFORCING) |
1234 | error = 0; | 1192 | error = 0; |
1235 | return error; | 1193 | return error; |
1236 | } | 1194 | } |
@@ -1248,14 +1206,13 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, | |||
1248 | struct path *path2) | 1206 | struct path *path2) |
1249 | { | 1207 | { |
1250 | int error = -ENOMEM; | 1208 | int error = -ENOMEM; |
1251 | struct tomoyo_path_info *buf1, *buf2; | 1209 | struct tomoyo_path_info *buf1; |
1252 | struct tomoyo_domain_info *domain = tomoyo_domain(); | 1210 | struct tomoyo_path_info *buf2; |
1253 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1211 | struct tomoyo_request_info r; |
1254 | const bool is_enforce = (mode == 3); | ||
1255 | const char *msg; | ||
1256 | int idx; | 1212 | int idx; |
1257 | 1213 | ||
1258 | if (!mode || !path1->mnt || !path2->mnt) | 1214 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || |
1215 | !path1->mnt || !path2->mnt) | ||
1259 | return 0; | 1216 | return 0; |
1260 | idx = tomoyo_read_lock(); | 1217 | idx = tomoyo_read_lock(); |
1261 | buf1 = tomoyo_get_path(path1); | 1218 | buf1 = tomoyo_get_path(path1); |
@@ -1278,26 +1235,22 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, | |||
1278 | } | 1235 | } |
1279 | } | 1236 | } |
1280 | } | 1237 | } |
1281 | error = tomoyo_path2_acl(domain, operation, buf1, buf2); | 1238 | error = tomoyo_path2_acl(&r, operation, buf1, buf2); |
1282 | msg = tomoyo_path22keyword(operation); | ||
1283 | if (!error) | 1239 | if (!error) |
1284 | goto out; | 1240 | goto out; |
1285 | if (tomoyo_verbose_mode(domain)) | 1241 | tomoyo_warn_log(&r, "%s %s %s", tomoyo_path22keyword(operation), |
1286 | printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' " | 1242 | buf1->name, buf2->name); |
1287 | "denied for %s\n", tomoyo_get_msg(is_enforce), | 1243 | if (tomoyo_domain_quota_is_ok(&r)) { |
1288 | msg, buf1->name, buf2->name, | ||
1289 | tomoyo_get_last_name(domain)); | ||
1290 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { | ||
1291 | const char *name1 = tomoyo_get_file_pattern(buf1)->name; | 1244 | const char *name1 = tomoyo_get_file_pattern(buf1)->name; |
1292 | const char *name2 = tomoyo_get_file_pattern(buf2)->name; | 1245 | const char *name2 = tomoyo_get_file_pattern(buf2)->name; |
1293 | tomoyo_update_path2_acl(operation, name1, name2, domain, | 1246 | tomoyo_update_path2_acl(operation, name1, name2, r.domain, |
1294 | false); | 1247 | false); |
1295 | } | 1248 | } |
1296 | out: | 1249 | out: |
1297 | kfree(buf1); | 1250 | kfree(buf1); |
1298 | kfree(buf2); | 1251 | kfree(buf2); |
1299 | tomoyo_read_unlock(idx); | 1252 | tomoyo_read_unlock(idx); |
1300 | if (!is_enforce) | 1253 | if (r.mode != TOMOYO_CONFIG_ENFORCING) |
1301 | error = 0; | 1254 | error = 0; |
1302 | return error; | 1255 | return error; |
1303 | } | 1256 | } |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index dedd97d0c163..4120f5a0e1bc 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -173,7 +173,7 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, | |||
173 | unsigned long arg) | 173 | unsigned long arg) |
174 | { | 174 | { |
175 | if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) | 175 | if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) |
176 | return tomoyo_check_rewrite_permission(file); | 176 | return tomoyo_path_perm(TOMOYO_TYPE_REWRITE, &file->f_path); |
177 | return 0; | 177 | return 0; |
178 | } | 178 | } |
179 | 179 | ||