diff options
-rw-r--r-- | security/tomoyo/common.c | 16 | ||||
-rw-r--r-- | security/tomoyo/common.h | 53 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 25 | ||||
-rw-r--r-- | security/tomoyo/file.c | 27 |
4 files changed, 25 insertions, 96 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ef6622300a81..ae3ed7313ee0 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -842,9 +842,7 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) | |||
842 | if (!domain) | 842 | if (!domain) |
843 | return true; | 843 | return true; |
844 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 844 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
845 | if (ptr->type & TOMOYO_ACL_DELETED) | 845 | switch (ptr->type) { |
846 | continue; | ||
847 | switch (tomoyo_acl_type2(ptr)) { | ||
848 | struct tomoyo_single_path_acl_record *acl; | 846 | struct tomoyo_single_path_acl_record *acl; |
849 | u32 perm; | 847 | u32 perm; |
850 | u8 i; | 848 | u8 i; |
@@ -1384,8 +1382,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) | |||
1384 | return 0; | 1382 | return 0; |
1385 | } | 1383 | } |
1386 | if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { | 1384 | if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { |
1387 | tomoyo_set_domain_flag(domain, is_delete, | 1385 | domain->ignore_global_allow_read = !is_delete; |
1388 | TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ); | ||
1389 | return 0; | 1386 | return 0; |
1390 | } | 1387 | } |
1391 | return tomoyo_write_file_policy(data, domain, is_delete); | 1388 | return tomoyo_write_file_policy(data, domain, is_delete); |
@@ -1486,10 +1483,8 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, | |||
1486 | static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | 1483 | static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, |
1487 | struct tomoyo_acl_info *ptr) | 1484 | struct tomoyo_acl_info *ptr) |
1488 | { | 1485 | { |
1489 | const u8 acl_type = tomoyo_acl_type2(ptr); | 1486 | const u8 acl_type = ptr->type; |
1490 | 1487 | ||
1491 | if (acl_type & TOMOYO_ACL_DELETED) | ||
1492 | return true; | ||
1493 | if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) { | 1488 | if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) { |
1494 | struct tomoyo_single_path_acl_record *acl | 1489 | struct tomoyo_single_path_acl_record *acl |
1495 | = container_of(ptr, | 1490 | = container_of(ptr, |
@@ -1540,10 +1535,9 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) | |||
1540 | /* Print domainname and flags. */ | 1535 | /* Print domainname and flags. */ |
1541 | if (domain->quota_warned) | 1536 | if (domain->quota_warned) |
1542 | quota_exceeded = "quota_exceeded\n"; | 1537 | quota_exceeded = "quota_exceeded\n"; |
1543 | if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED) | 1538 | if (domain->transition_failed) |
1544 | transition_failed = "transition_failed\n"; | 1539 | transition_failed = "transition_failed\n"; |
1545 | if (domain->flags & | 1540 | if (domain->ignore_global_allow_read) |
1546 | TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) | ||
1547 | ignore_global_allow_read | 1541 | ignore_global_allow_read |
1548 | = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; | 1542 | = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; |
1549 | done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE | 1543 | done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 8b59ec8fe11e..509ced9ce698 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -101,11 +101,9 @@ struct tomoyo_path_info_with_data { | |||
101 | * | 101 | * |
102 | * (1) "list" which is linked to the ->acl_info_list of | 102 | * (1) "list" which is linked to the ->acl_info_list of |
103 | * "struct tomoyo_domain_info" | 103 | * "struct tomoyo_domain_info" |
104 | * (2) "type" which tells | 104 | * (2) "type" which tells type of the entry (either |
105 | * (a) type & 0x7F : type of the entry (either | 105 | * "struct tomoyo_single_path_acl_record" or |
106 | * "struct tomoyo_single_path_acl_record" or | 106 | * "struct tomoyo_double_path_acl_record"). |
107 | * "struct tomoyo_double_path_acl_record") | ||
108 | * (b) type & 0x80 : whether the entry is marked as "deleted". | ||
109 | * | 107 | * |
110 | * Packing "struct tomoyo_acl_info" allows | 108 | * Packing "struct tomoyo_acl_info" allows |
111 | * "struct tomoyo_single_path_acl_record" to embed "u8" + "u16" and | 109 | * "struct tomoyo_single_path_acl_record" to embed "u8" + "u16" and |
@@ -114,17 +112,9 @@ struct tomoyo_path_info_with_data { | |||
114 | */ | 112 | */ |
115 | struct tomoyo_acl_info { | 113 | struct tomoyo_acl_info { |
116 | struct list_head list; | 114 | struct list_head list; |
117 | /* | ||
118 | * Type of this ACL entry. | ||
119 | * | ||
120 | * MSB is is_deleted flag. | ||
121 | */ | ||
122 | u8 type; | 115 | u8 type; |
123 | } __packed; | 116 | } __packed; |
124 | 117 | ||
125 | /* This ACL entry is deleted. */ | ||
126 | #define TOMOYO_ACL_DELETED 0x80 | ||
127 | |||
128 | /* | 118 | /* |
129 | * tomoyo_domain_info is a structure which is used for holding permissions | 119 | * tomoyo_domain_info is a structure which is used for holding permissions |
130 | * (e.g. "allow_read /lib/libc-2.5.so") given to each domain. | 120 | * (e.g. "allow_read /lib/libc-2.5.so") given to each domain. |
@@ -138,7 +128,13 @@ struct tomoyo_acl_info { | |||
138 | * "deleted", false otherwise. | 128 | * "deleted", false otherwise. |
139 | * (6) "quota_warned" is a bool which is used for suppressing warning message | 129 | * (6) "quota_warned" is a bool which is used for suppressing warning message |
140 | * when learning mode learned too much entries. | 130 | * when learning mode learned too much entries. |
141 | * (7) "flags" which remembers this domain's attributes. | 131 | * (7) "ignore_global_allow_read" is a bool which is true if this domain |
132 | * should ignore "allow_read" directive in exception policy. | ||
133 | * (8) "transition_failed" is a bool which is set to true when this domain was | ||
134 | * unable to create a new domain at tomoyo_find_next_domain() because the | ||
135 | * name of the domain to be created was too long or it could not allocate | ||
136 | * memory. If set to true, more than one process continued execve() | ||
137 | * without domain transition. | ||
142 | * | 138 | * |
143 | * A domain's lifecycle is an analogy of files on / directory. | 139 | * A domain's lifecycle is an analogy of files on / directory. |
144 | * Multiple domains with the same domainname cannot be created (as with | 140 | * Multiple domains with the same domainname cannot be created (as with |
@@ -155,23 +151,13 @@ struct tomoyo_domain_info { | |||
155 | u8 profile; /* Profile number to use. */ | 151 | u8 profile; /* Profile number to use. */ |
156 | bool is_deleted; /* Delete flag. */ | 152 | bool is_deleted; /* Delete flag. */ |
157 | bool quota_warned; /* Quota warnning flag. */ | 153 | bool quota_warned; /* Quota warnning flag. */ |
158 | /* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */ | 154 | bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ |
159 | u8 flags; | 155 | bool transition_failed; /* Domain transition failed flag. */ |
160 | }; | 156 | }; |
161 | 157 | ||
162 | /* Profile number is an integer between 0 and 255. */ | 158 | /* Profile number is an integer between 0 and 255. */ |
163 | #define TOMOYO_MAX_PROFILES 256 | 159 | #define TOMOYO_MAX_PROFILES 256 |
164 | 160 | ||
165 | /* Ignore "allow_read" directive in exception policy. */ | ||
166 | #define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1 | ||
167 | /* | ||
168 | * This domain was unable to create a new domain at tomoyo_find_next_domain() | ||
169 | * because the name of the domain to be created was too long or | ||
170 | * it could not allocate memory. | ||
171 | * More than one process continued execve() without domain transition. | ||
172 | */ | ||
173 | #define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED 2 | ||
174 | |||
175 | /* | 161 | /* |
176 | * tomoyo_single_path_acl_record is a structure which is used for holding an | 162 | * tomoyo_single_path_acl_record is a structure which is used for holding an |
177 | * entry with one pathname operation (e.g. open(), mkdir()). | 163 | * entry with one pathname operation (e.g. open(), mkdir()). |
@@ -380,9 +366,6 @@ unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | |||
380 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | 366 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); |
381 | /* Run policy loader when /sbin/init starts. */ | 367 | /* Run policy loader when /sbin/init starts. */ |
382 | void tomoyo_load_policy(const char *filename); | 368 | void tomoyo_load_policy(const char *filename); |
383 | /* Change "struct tomoyo_domain_info"->flags. */ | ||
384 | void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, | ||
385 | const bool is_delete, const u8 flags); | ||
386 | 369 | ||
387 | /* strcmp() for "struct tomoyo_path_info" structure. */ | 370 | /* strcmp() for "struct tomoyo_path_info" structure. */ |
388 | static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, | 371 | static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, |
@@ -391,18 +374,6 @@ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, | |||
391 | return a->hash != b->hash || strcmp(a->name, b->name); | 374 | return a->hash != b->hash || strcmp(a->name, b->name); |
392 | } | 375 | } |
393 | 376 | ||
394 | /* Get type of an ACL entry. */ | ||
395 | static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr) | ||
396 | { | ||
397 | return ptr->type & ~TOMOYO_ACL_DELETED; | ||
398 | } | ||
399 | |||
400 | /* Get type of an ACL entry. */ | ||
401 | static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr) | ||
402 | { | ||
403 | return ptr->type; | ||
404 | } | ||
405 | |||
406 | /** | 377 | /** |
407 | * tomoyo_is_valid - Check whether the character is a valid char. | 378 | * tomoyo_is_valid - Check whether the character is a valid char. |
408 | * | 379 | * |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 34843971cc60..ec612ae87b51 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -130,28 +130,6 @@ struct tomoyo_alias_entry { | |||
130 | }; | 130 | }; |
131 | 131 | ||
132 | /** | 132 | /** |
133 | * tomoyo_set_domain_flag - Set or clear domain's attribute flags. | ||
134 | * | ||
135 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
136 | * @is_delete: True if it is a delete request. | ||
137 | * @flags: Flags to set or clear. | ||
138 | * | ||
139 | * Returns nothing. | ||
140 | */ | ||
141 | void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, | ||
142 | const bool is_delete, const u8 flags) | ||
143 | { | ||
144 | /* We need to serialize because this is bitfield operation. */ | ||
145 | static DEFINE_SPINLOCK(lock); | ||
146 | spin_lock(&lock); | ||
147 | if (!is_delete) | ||
148 | domain->flags |= flags; | ||
149 | else | ||
150 | domain->flags &= ~flags; | ||
151 | spin_unlock(&lock); | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * tomoyo_get_last_name - Get last component of a domainname. | 133 | * tomoyo_get_last_name - Get last component of a domainname. |
156 | * | 134 | * |
157 | * @domain: Pointer to "struct tomoyo_domain_info". | 135 | * @domain: Pointer to "struct tomoyo_domain_info". |
@@ -896,8 +874,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
896 | if (is_enforce) | 874 | if (is_enforce) |
897 | retval = -EPERM; | 875 | retval = -EPERM; |
898 | else | 876 | else |
899 | tomoyo_set_domain_flag(old_domain, false, | 877 | old_domain->transition_failed = true; |
900 | TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); | ||
901 | out: | 878 | out: |
902 | if (!domain) | 879 | if (!domain) |
903 | domain = old_domain; | 880 | domain = old_domain; |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 24af081f1af9..84c821a245ca 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -688,7 +688,7 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | |||
688 | 688 | ||
689 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 689 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
690 | struct tomoyo_single_path_acl_record *acl; | 690 | struct tomoyo_single_path_acl_record *acl; |
691 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | 691 | if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) |
692 | continue; | 692 | continue; |
693 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | 693 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, |
694 | head); | 694 | head); |
@@ -770,8 +770,7 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | |||
770 | if (!filename) | 770 | if (!filename) |
771 | return 0; | 771 | return 0; |
772 | error = tomoyo_check_file_acl(domain, filename, perm); | 772 | error = tomoyo_check_file_acl(domain, filename, perm); |
773 | if (error && perm == 4 && | 773 | if (error && perm == 4 && !domain->ignore_global_allow_read |
774 | (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0 | ||
775 | && tomoyo_is_globally_readable_file(filename)) | 774 | && tomoyo_is_globally_readable_file(filename)) |
776 | error = 0; | 775 | error = 0; |
777 | if (perm == 6) | 776 | if (perm == 6) |
@@ -885,15 +884,12 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
885 | if (is_delete) | 884 | if (is_delete) |
886 | goto delete; | 885 | goto delete; |
887 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 886 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
888 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | 887 | if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) |
889 | continue; | 888 | continue; |
890 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | 889 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, |
891 | head); | 890 | head); |
892 | if (acl->filename != saved_filename) | 891 | if (acl->filename != saved_filename) |
893 | continue; | 892 | continue; |
894 | /* Special case. Clear all bits if marked as deleted. */ | ||
895 | if (ptr->type & TOMOYO_ACL_DELETED) | ||
896 | acl->perm = 0; | ||
897 | if (perm <= 0xFFFF) | 893 | if (perm <= 0xFFFF) |
898 | acl->perm |= perm; | 894 | acl->perm |= perm; |
899 | else | 895 | else |
@@ -902,7 +898,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
902 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; | 898 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; |
903 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | 899 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) |
904 | acl->perm |= rw_mask; | 900 | acl->perm |= rw_mask; |
905 | ptr->type &= ~TOMOYO_ACL_DELETED; | ||
906 | error = 0; | 901 | error = 0; |
907 | goto out; | 902 | goto out; |
908 | } | 903 | } |
@@ -927,7 +922,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
927 | delete: | 922 | delete: |
928 | error = -ENOENT; | 923 | error = -ENOENT; |
929 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 924 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
930 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | 925 | if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) |
931 | continue; | 926 | continue; |
932 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | 927 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, |
933 | head); | 928 | head); |
@@ -941,8 +936,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
941 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); | 936 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); |
942 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) | 937 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) |
943 | acl->perm &= ~rw_mask; | 938 | acl->perm &= ~rw_mask; |
944 | if (!acl->perm && !acl->perm_high) | ||
945 | ptr->type |= TOMOYO_ACL_DELETED; | ||
946 | error = 0; | 939 | error = 0; |
947 | break; | 940 | break; |
948 | } | 941 | } |
@@ -989,18 +982,14 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
989 | if (is_delete) | 982 | if (is_delete) |
990 | goto delete; | 983 | goto delete; |
991 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 984 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
992 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | 985 | if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) |
993 | continue; | 986 | continue; |
994 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | 987 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, |
995 | head); | 988 | head); |
996 | if (acl->filename1 != saved_filename1 || | 989 | if (acl->filename1 != saved_filename1 || |
997 | acl->filename2 != saved_filename2) | 990 | acl->filename2 != saved_filename2) |
998 | continue; | 991 | continue; |
999 | /* Special case. Clear all bits if marked as deleted. */ | ||
1000 | if (ptr->type & TOMOYO_ACL_DELETED) | ||
1001 | acl->perm = 0; | ||
1002 | acl->perm |= perm; | 992 | acl->perm |= perm; |
1003 | ptr->type &= ~TOMOYO_ACL_DELETED; | ||
1004 | error = 0; | 993 | error = 0; |
1005 | goto out; | 994 | goto out; |
1006 | } | 995 | } |
@@ -1021,7 +1010,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
1021 | delete: | 1010 | delete: |
1022 | error = -ENOENT; | 1011 | error = -ENOENT; |
1023 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 1012 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
1024 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | 1013 | if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) |
1025 | continue; | 1014 | continue; |
1026 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | 1015 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, |
1027 | head); | 1016 | head); |
@@ -1029,8 +1018,6 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
1029 | acl->filename2 != saved_filename2) | 1018 | acl->filename2 != saved_filename2) |
1030 | continue; | 1019 | continue; |
1031 | acl->perm &= ~perm; | 1020 | acl->perm &= ~perm; |
1032 | if (!acl->perm) | ||
1033 | ptr->type |= TOMOYO_ACL_DELETED; | ||
1034 | error = 0; | 1021 | error = 0; |
1035 | break; | 1022 | break; |
1036 | } | 1023 | } |
@@ -1086,7 +1073,7 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1086 | return 0; | 1073 | return 0; |
1087 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 1074 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
1088 | struct tomoyo_double_path_acl_record *acl; | 1075 | struct tomoyo_double_path_acl_record *acl; |
1089 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | 1076 | if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) |
1090 | continue; | 1077 | continue; |
1091 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | 1078 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, |
1092 | head); | 1079 | head); |