diff options
Diffstat (limited to 'security/tomoyo')
-rw-r--r-- | security/tomoyo/Makefile | 2 | ||||
-rw-r--r-- | security/tomoyo/common.c | 161 | ||||
-rw-r--r-- | security/tomoyo/common.h | 61 | ||||
-rw-r--r-- | security/tomoyo/file.c | 14 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 41 | ||||
-rw-r--r-- | security/tomoyo/number_group.c | 176 |
6 files changed, 454 insertions, 1 deletions
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 4fb39030f6bd..4d1b5af4f1f7 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile | |||
@@ -1 +1 @@ | |||
obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o | obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o number_group.o | ||
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index b5dbdc9ff73c..d82c2978b1be 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -119,6 +119,159 @@ static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head, | |||
119 | } | 119 | } |
120 | 120 | ||
121 | /** | 121 | /** |
122 | * tomoyo_parse_ulong - Parse an "unsigned long" value. | ||
123 | * | ||
124 | * @result: Pointer to "unsigned long". | ||
125 | * @str: Pointer to string to parse. | ||
126 | * | ||
127 | * Returns value type on success, 0 otherwise. | ||
128 | * | ||
129 | * The @src is updated to point the first character after the value | ||
130 | * on success. | ||
131 | */ | ||
132 | u8 tomoyo_parse_ulong(unsigned long *result, char **str) | ||
133 | { | ||
134 | const char *cp = *str; | ||
135 | char *ep; | ||
136 | int base = 10; | ||
137 | if (*cp == '0') { | ||
138 | char c = *(cp + 1); | ||
139 | if (c == 'x' || c == 'X') { | ||
140 | base = 16; | ||
141 | cp += 2; | ||
142 | } else if (c >= '0' && c <= '7') { | ||
143 | base = 8; | ||
144 | cp++; | ||
145 | } | ||
146 | } | ||
147 | *result = simple_strtoul(cp, &ep, base); | ||
148 | if (cp == ep) | ||
149 | return 0; | ||
150 | *str = ep; | ||
151 | switch (base) { | ||
152 | case 16: | ||
153 | return TOMOYO_VALUE_TYPE_HEXADECIMAL; | ||
154 | case 8: | ||
155 | return TOMOYO_VALUE_TYPE_OCTAL; | ||
156 | default: | ||
157 | return TOMOYO_VALUE_TYPE_DECIMAL; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * tomoyo_print_ulong - Print an "unsigned long" value. | ||
163 | * | ||
164 | * @buffer: Pointer to buffer. | ||
165 | * @buffer_len: Size of @buffer. | ||
166 | * @value: An "unsigned long" value. | ||
167 | * @type: Type of @value. | ||
168 | * | ||
169 | * Returns nothing. | ||
170 | */ | ||
171 | void tomoyo_print_ulong(char *buffer, const int buffer_len, | ||
172 | const unsigned long value, const u8 type) | ||
173 | { | ||
174 | if (type == TOMOYO_VALUE_TYPE_DECIMAL) | ||
175 | snprintf(buffer, buffer_len, "%lu", value); | ||
176 | else if (type == TOMOYO_VALUE_TYPE_OCTAL) | ||
177 | snprintf(buffer, buffer_len, "0%lo", value); | ||
178 | else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL) | ||
179 | snprintf(buffer, buffer_len, "0x%lX", value); | ||
180 | else | ||
181 | snprintf(buffer, buffer_len, "type(%u)", type); | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * tomoyo_print_number_union - Print a tomoyo_number_union. | ||
186 | * | ||
187 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
188 | * @ptr: Pointer to "struct tomoyo_number_union". | ||
189 | * | ||
190 | * Returns true on success, false otherwise. | ||
191 | */ | ||
192 | bool tomoyo_print_number_union(struct tomoyo_io_buffer *head, | ||
193 | const struct tomoyo_number_union *ptr) | ||
194 | { | ||
195 | unsigned long min; | ||
196 | unsigned long max; | ||
197 | u8 min_type; | ||
198 | u8 max_type; | ||
199 | if (!tomoyo_io_printf(head, " ")) | ||
200 | return false; | ||
201 | if (ptr->is_group) | ||
202 | return tomoyo_io_printf(head, "@%s", | ||
203 | ptr->group->group_name->name); | ||
204 | min_type = ptr->min_type; | ||
205 | max_type = ptr->max_type; | ||
206 | min = ptr->values[0]; | ||
207 | max = ptr->values[1]; | ||
208 | switch (min_type) { | ||
209 | case TOMOYO_VALUE_TYPE_HEXADECIMAL: | ||
210 | if (!tomoyo_io_printf(head, "0x%lX", min)) | ||
211 | return false; | ||
212 | break; | ||
213 | case TOMOYO_VALUE_TYPE_OCTAL: | ||
214 | if (!tomoyo_io_printf(head, "0%lo", min)) | ||
215 | return false; | ||
216 | break; | ||
217 | default: | ||
218 | if (!tomoyo_io_printf(head, "%lu", min)) | ||
219 | return false; | ||
220 | break; | ||
221 | } | ||
222 | if (min == max && min_type == max_type) | ||
223 | return true; | ||
224 | switch (max_type) { | ||
225 | case TOMOYO_VALUE_TYPE_HEXADECIMAL: | ||
226 | return tomoyo_io_printf(head, "-0x%lX", max); | ||
227 | case TOMOYO_VALUE_TYPE_OCTAL: | ||
228 | return tomoyo_io_printf(head, "-0%lo", max); | ||
229 | default: | ||
230 | return tomoyo_io_printf(head, "-%lu", max); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * tomoyo_parse_number_union - Parse a tomoyo_number_union. | ||
236 | * | ||
237 | * @data: Number or number range or number group. | ||
238 | * @ptr: Pointer to "struct tomoyo_number_union". | ||
239 | * | ||
240 | * Returns true on success, false otherwise. | ||
241 | */ | ||
242 | bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) | ||
243 | { | ||
244 | u8 type; | ||
245 | unsigned long v; | ||
246 | memset(num, 0, sizeof(*num)); | ||
247 | if (data[0] == '@') { | ||
248 | if (!tomoyo_is_correct_path(data, 0, 0, 0)) | ||
249 | return false; | ||
250 | num->group = tomoyo_get_number_group(data + 1); | ||
251 | num->is_group = true; | ||
252 | return num->group != NULL; | ||
253 | } | ||
254 | type = tomoyo_parse_ulong(&v, &data); | ||
255 | if (!type) | ||
256 | return false; | ||
257 | num->values[0] = v; | ||
258 | num->min_type = type; | ||
259 | if (!*data) { | ||
260 | num->values[1] = v; | ||
261 | num->max_type = type; | ||
262 | return true; | ||
263 | } | ||
264 | if (*data++ != '-') | ||
265 | return false; | ||
266 | type = tomoyo_parse_ulong(&v, &data); | ||
267 | if (!type || *data) | ||
268 | return false; | ||
269 | num->values[1] = v; | ||
270 | num->max_type = type; | ||
271 | return true; | ||
272 | } | ||
273 | |||
274 | /** | ||
122 | * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. | 275 | * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. |
123 | * | 276 | * |
124 | * @str: Pointer to the string. | 277 | * @str: Pointer to the string. |
@@ -1750,6 +1903,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) | |||
1750 | return tomoyo_write_no_rewrite_policy(data, is_delete); | 1903 | return tomoyo_write_no_rewrite_policy(data, is_delete); |
1751 | if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) | 1904 | if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) |
1752 | return tomoyo_write_path_group_policy(data, is_delete); | 1905 | return tomoyo_write_path_group_policy(data, is_delete); |
1906 | if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NUMBER_GROUP)) | ||
1907 | return tomoyo_write_number_group_policy(data, is_delete); | ||
1753 | return -EINVAL; | 1908 | return -EINVAL; |
1754 | } | 1909 | } |
1755 | 1910 | ||
@@ -1812,6 +1967,12 @@ static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) | |||
1812 | head->read_var2 = NULL; | 1967 | head->read_var2 = NULL; |
1813 | head->read_step = 10; | 1968 | head->read_step = 10; |
1814 | case 10: | 1969 | case 10: |
1970 | if (!tomoyo_read_number_group_policy(head)) | ||
1971 | break; | ||
1972 | head->read_var1 = NULL; | ||
1973 | head->read_var2 = NULL; | ||
1974 | head->read_step = 11; | ||
1975 | case 11: | ||
1815 | head->read_eof = true; | 1976 | head->read_eof = true; |
1816 | break; | 1977 | break; |
1817 | default: | 1978 | default: |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 9f1ae5e3ba51..33d3072f9bb4 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -55,6 +55,7 @@ struct linux_binprm; | |||
55 | #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " | 55 | #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " |
56 | #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " | 56 | #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " |
57 | #define TOMOYO_KEYWORD_PATH_GROUP "path_group " | 57 | #define TOMOYO_KEYWORD_PATH_GROUP "path_group " |
58 | #define TOMOYO_KEYWORD_NUMBER_GROUP "number_group " | ||
58 | #define TOMOYO_KEYWORD_SELECT "select " | 59 | #define TOMOYO_KEYWORD_SELECT "select " |
59 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " | 60 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " |
60 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" | 61 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" |
@@ -62,6 +63,12 @@ struct linux_binprm; | |||
62 | #define TOMOYO_ROOT_NAME "<kernel>" | 63 | #define TOMOYO_ROOT_NAME "<kernel>" |
63 | #define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) | 64 | #define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) |
64 | 65 | ||
66 | /* Value type definition. */ | ||
67 | #define TOMOYO_VALUE_TYPE_INVALID 0 | ||
68 | #define TOMOYO_VALUE_TYPE_DECIMAL 1 | ||
69 | #define TOMOYO_VALUE_TYPE_OCTAL 2 | ||
70 | #define TOMOYO_VALUE_TYPE_HEXADECIMAL 3 | ||
71 | |||
65 | /* Index numbers for Access Controls. */ | 72 | /* Index numbers for Access Controls. */ |
66 | enum tomoyo_mac_index { | 73 | enum tomoyo_mac_index { |
67 | TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */ | 74 | TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */ |
@@ -211,6 +218,14 @@ struct tomoyo_name_union { | |||
211 | u8 is_group; | 218 | u8 is_group; |
212 | }; | 219 | }; |
213 | 220 | ||
221 | struct tomoyo_number_union { | ||
222 | unsigned long values[2]; | ||
223 | struct tomoyo_number_group *group; | ||
224 | u8 min_type; | ||
225 | u8 max_type; | ||
226 | u8 is_group; | ||
227 | }; | ||
228 | |||
214 | /* Structure for "path_group" directive. */ | 229 | /* Structure for "path_group" directive. */ |
215 | struct tomoyo_path_group { | 230 | struct tomoyo_path_group { |
216 | struct list_head list; | 231 | struct list_head list; |
@@ -219,6 +234,14 @@ struct tomoyo_path_group { | |||
219 | atomic_t users; | 234 | atomic_t users; |
220 | }; | 235 | }; |
221 | 236 | ||
237 | /* Structure for "number_group" directive. */ | ||
238 | struct tomoyo_number_group { | ||
239 | struct list_head list; | ||
240 | const struct tomoyo_path_info *group_name; | ||
241 | struct list_head member_list; | ||
242 | atomic_t users; | ||
243 | }; | ||
244 | |||
222 | /* Structure for "path_group" directive. */ | 245 | /* Structure for "path_group" directive. */ |
223 | struct tomoyo_path_group_member { | 246 | struct tomoyo_path_group_member { |
224 | struct list_head list; | 247 | struct list_head list; |
@@ -226,6 +249,13 @@ struct tomoyo_path_group_member { | |||
226 | const struct tomoyo_path_info *member_name; | 249 | const struct tomoyo_path_info *member_name; |
227 | }; | 250 | }; |
228 | 251 | ||
252 | /* Structure for "number_group" directive. */ | ||
253 | struct tomoyo_number_group_member { | ||
254 | struct list_head list; | ||
255 | bool is_deleted; | ||
256 | struct tomoyo_number_union number; | ||
257 | }; | ||
258 | |||
229 | /* | 259 | /* |
230 | * tomoyo_acl_info is a structure which is used for holding | 260 | * tomoyo_acl_info is a structure which is used for holding |
231 | * | 261 | * |
@@ -554,9 +584,18 @@ bool tomoyo_parse_name_union(const char *filename, | |||
554 | bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, | 584 | bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, |
555 | const struct tomoyo_path_group *group, | 585 | const struct tomoyo_path_group *group, |
556 | const bool may_use_pattern); | 586 | const bool may_use_pattern); |
587 | /* Check whether the given value matches the given number_group. */ | ||
588 | bool tomoyo_number_matches_group(const unsigned long min, | ||
589 | const unsigned long max, | ||
590 | const struct tomoyo_number_group *group); | ||
557 | /* Check whether the given filename matches the given pattern. */ | 591 | /* Check whether the given filename matches the given pattern. */ |
558 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, | 592 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, |
559 | const struct tomoyo_path_info *pattern); | 593 | const struct tomoyo_path_info *pattern); |
594 | |||
595 | bool tomoyo_print_number_union(struct tomoyo_io_buffer *head, | ||
596 | const struct tomoyo_number_union *ptr); | ||
597 | bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num); | ||
598 | |||
560 | /* Read "alias" entry in exception policy. */ | 599 | /* Read "alias" entry in exception policy. */ |
561 | bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head); | 600 | bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head); |
562 | /* | 601 | /* |
@@ -570,6 +609,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head); | |||
570 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); | 609 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); |
571 | /* Read "path_group" entry in exception policy. */ | 610 | /* Read "path_group" entry in exception policy. */ |
572 | bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head); | 611 | bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head); |
612 | /* Read "number_group" entry in exception policy. */ | ||
613 | bool tomoyo_read_number_group_policy(struct tomoyo_io_buffer *head); | ||
573 | /* Read "allow_read" entry in exception policy. */ | 614 | /* Read "allow_read" entry in exception policy. */ |
574 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); | 615 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); |
575 | /* Read "deny_rewrite" entry in exception policy. */ | 616 | /* Read "deny_rewrite" entry in exception policy. */ |
@@ -614,6 +655,8 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); | |||
614 | int tomoyo_write_pattern_policy(char *data, const bool is_delete); | 655 | int tomoyo_write_pattern_policy(char *data, const bool is_delete); |
615 | /* Create "path_group" entry in exception policy. */ | 656 | /* Create "path_group" entry in exception policy. */ |
616 | int tomoyo_write_path_group_policy(char *data, const bool is_delete); | 657 | int tomoyo_write_path_group_policy(char *data, const bool is_delete); |
658 | /* Create "number_group" entry in exception policy. */ | ||
659 | int tomoyo_write_number_group_policy(char *data, const bool is_delete); | ||
617 | /* Find a domain by the given name. */ | 660 | /* Find a domain by the given name. */ |
618 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | 661 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); |
619 | /* Find or create a domain by the given name. */ | 662 | /* Find or create a domain by the given name. */ |
@@ -623,6 +666,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
623 | 666 | ||
624 | /* Allocate memory for "struct tomoyo_path_group". */ | 667 | /* Allocate memory for "struct tomoyo_path_group". */ |
625 | struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); | 668 | struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); |
669 | struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name); | ||
626 | 670 | ||
627 | /* Check mode for specified functionality. */ | 671 | /* Check mode for specified functionality. */ |
628 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | 672 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, |
@@ -632,6 +676,8 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | |||
632 | /* Run policy loader when /sbin/init starts. */ | 676 | /* Run policy loader when /sbin/init starts. */ |
633 | void tomoyo_load_policy(const char *filename); | 677 | void tomoyo_load_policy(const char *filename); |
634 | 678 | ||
679 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr); | ||
680 | |||
635 | /* Convert binary string to ascii string. */ | 681 | /* Convert binary string to ascii string. */ |
636 | int tomoyo_encode(char *buffer, int buflen, const char *str); | 682 | int tomoyo_encode(char *buffer, int buflen, const char *str); |
637 | 683 | ||
@@ -697,6 +743,7 @@ extern struct srcu_struct tomoyo_ss; | |||
697 | extern struct list_head tomoyo_domain_list; | 743 | extern struct list_head tomoyo_domain_list; |
698 | 744 | ||
699 | extern struct list_head tomoyo_path_group_list; | 745 | extern struct list_head tomoyo_path_group_list; |
746 | extern struct list_head tomoyo_number_group_list; | ||
700 | extern struct list_head tomoyo_domain_initializer_list; | 747 | extern struct list_head tomoyo_domain_initializer_list; |
701 | extern struct list_head tomoyo_domain_keeper_list; | 748 | extern struct list_head tomoyo_domain_keeper_list; |
702 | extern struct list_head tomoyo_alias_list; | 749 | extern struct list_head tomoyo_alias_list; |
@@ -773,6 +820,12 @@ static inline void tomoyo_put_path_group(struct tomoyo_path_group *group) | |||
773 | atomic_dec(&group->users); | 820 | atomic_dec(&group->users); |
774 | } | 821 | } |
775 | 822 | ||
823 | static inline void tomoyo_put_number_group(struct tomoyo_number_group *group) | ||
824 | { | ||
825 | if (group) | ||
826 | atomic_dec(&group->users); | ||
827 | } | ||
828 | |||
776 | static inline struct tomoyo_domain_info *tomoyo_domain(void) | 829 | static inline struct tomoyo_domain_info *tomoyo_domain(void) |
777 | { | 830 | { |
778 | return current_cred()->security; | 831 | return current_cred()->security; |
@@ -797,6 +850,14 @@ static inline bool tomoyo_is_same_name_union | |||
797 | p1->is_group == p2->is_group; | 850 | p1->is_group == p2->is_group; |
798 | } | 851 | } |
799 | 852 | ||
853 | static inline bool tomoyo_is_same_number_union | ||
854 | (const struct tomoyo_number_union *p1, const struct tomoyo_number_union *p2) | ||
855 | { | ||
856 | return p1->values[0] == p2->values[0] && p1->values[1] == p2->values[1] | ||
857 | && p1->group == p2->group && p1->min_type == p2->min_type && | ||
858 | p1->max_type == p2->max_type && p1->is_group == p2->is_group; | ||
859 | } | ||
860 | |||
800 | static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, | 861 | static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, |
801 | const struct tomoyo_path_acl *p2) | 862 | const struct tomoyo_path_acl *p2) |
802 | { | 863 | { |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 1c6f8238ec47..2dffe0730918 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -76,6 +76,20 @@ static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info | |||
76 | return false; | 76 | return false; |
77 | } | 77 | } |
78 | 78 | ||
79 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr) | ||
80 | { | ||
81 | if (ptr && ptr->is_group) | ||
82 | tomoyo_put_number_group(ptr->group); | ||
83 | } | ||
84 | |||
85 | bool tomoyo_compare_number_union(const unsigned long value, | ||
86 | const struct tomoyo_number_union *ptr) | ||
87 | { | ||
88 | if (ptr->is_group) | ||
89 | return tomoyo_number_matches_group(value, value, ptr->group); | ||
90 | return value >= ptr->values[0] && value <= ptr->values[1]; | ||
91 | } | ||
92 | |||
79 | /** | 93 | /** |
80 | * tomoyo_path2keyword - Get the name of single path operation. | 94 | * tomoyo_path2keyword - Get the name of single path operation. |
81 | * | 95 | * |
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index b9cc71b04314..6a48197f6ce5 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -14,6 +14,8 @@ | |||
14 | enum tomoyo_gc_id { | 14 | enum tomoyo_gc_id { |
15 | TOMOYO_ID_PATH_GROUP, | 15 | TOMOYO_ID_PATH_GROUP, |
16 | TOMOYO_ID_PATH_GROUP_MEMBER, | 16 | TOMOYO_ID_PATH_GROUP_MEMBER, |
17 | TOMOYO_ID_NUMBER_GROUP, | ||
18 | TOMOYO_ID_NUMBER_GROUP_MEMBER, | ||
17 | TOMOYO_ID_DOMAIN_INITIALIZER, | 19 | TOMOYO_ID_DOMAIN_INITIALIZER, |
18 | TOMOYO_ID_DOMAIN_KEEPER, | 20 | TOMOYO_ID_DOMAIN_KEEPER, |
19 | TOMOYO_ID_ALIAS, | 21 | TOMOYO_ID_ALIAS, |
@@ -162,6 +164,16 @@ static void tomoyo_del_path_group(struct tomoyo_path_group *group) | |||
162 | tomoyo_put_name(group->group_name); | 164 | tomoyo_put_name(group->group_name); |
163 | } | 165 | } |
164 | 166 | ||
167 | static void tomoyo_del_number_group_member(struct tomoyo_number_group_member | ||
168 | *member) | ||
169 | { | ||
170 | } | ||
171 | |||
172 | static void tomoyo_del_number_group(struct tomoyo_number_group *group) | ||
173 | { | ||
174 | tomoyo_put_name(group->group_name); | ||
175 | } | ||
176 | |||
165 | static void tomoyo_collect_entry(void) | 177 | static void tomoyo_collect_entry(void) |
166 | { | 178 | { |
167 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 179 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
@@ -329,6 +341,29 @@ static void tomoyo_collect_entry(void) | |||
329 | break; | 341 | break; |
330 | } | 342 | } |
331 | } | 343 | } |
344 | { | ||
345 | struct tomoyo_number_group *group; | ||
346 | list_for_each_entry_rcu(group, &tomoyo_number_group_list, list) { | ||
347 | struct tomoyo_number_group_member *member; | ||
348 | list_for_each_entry_rcu(member, &group->member_list, | ||
349 | list) { | ||
350 | if (!member->is_deleted) | ||
351 | continue; | ||
352 | if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP_MEMBER, | ||
353 | member)) | ||
354 | list_del_rcu(&member->list); | ||
355 | else | ||
356 | break; | ||
357 | } | ||
358 | if (!list_empty(&group->member_list) || | ||
359 | atomic_read(&group->users)) | ||
360 | continue; | ||
361 | if (tomoyo_add_to_gc(TOMOYO_ID_NUMBER_GROUP, group)) | ||
362 | list_del_rcu(&group->list); | ||
363 | else | ||
364 | break; | ||
365 | } | ||
366 | } | ||
332 | mutex_unlock(&tomoyo_policy_lock); | 367 | mutex_unlock(&tomoyo_policy_lock); |
333 | } | 368 | } |
334 | 369 | ||
@@ -376,6 +411,12 @@ static void tomoyo_kfree_entry(void) | |||
376 | case TOMOYO_ID_PATH_GROUP: | 411 | case TOMOYO_ID_PATH_GROUP: |
377 | tomoyo_del_path_group(p->element); | 412 | tomoyo_del_path_group(p->element); |
378 | break; | 413 | break; |
414 | case TOMOYO_ID_NUMBER_GROUP_MEMBER: | ||
415 | tomoyo_del_number_group_member(p->element); | ||
416 | break; | ||
417 | case TOMOYO_ID_NUMBER_GROUP: | ||
418 | tomoyo_del_number_group(p->element); | ||
419 | break; | ||
379 | default: | 420 | default: |
380 | printk(KERN_WARNING "Unknown type\n"); | 421 | printk(KERN_WARNING "Unknown type\n"); |
381 | break; | 422 | break; |
diff --git a/security/tomoyo/number_group.c b/security/tomoyo/number_group.c new file mode 100644 index 000000000000..c49792e09e81 --- /dev/null +++ b/security/tomoyo/number_group.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * security/tomoyo/number_group.c | ||
3 | * | ||
4 | * Copyright (C) 2005-2009 NTT DATA CORPORATION | ||
5 | */ | ||
6 | |||
7 | #include <linux/slab.h> | ||
8 | #include "common.h" | ||
9 | |||
10 | /* The list for "struct tomoyo_number_group". */ | ||
11 | LIST_HEAD(tomoyo_number_group_list); | ||
12 | |||
13 | /** | ||
14 | * tomoyo_get_number_group - Allocate memory for "struct tomoyo_number_group". | ||
15 | * | ||
16 | * @group_name: The name of number group. | ||
17 | * | ||
18 | * Returns pointer to "struct tomoyo_number_group" on success, | ||
19 | * NULL otherwise. | ||
20 | */ | ||
21 | struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name) | ||
22 | { | ||
23 | struct tomoyo_number_group *entry = NULL; | ||
24 | struct tomoyo_number_group *group = NULL; | ||
25 | const struct tomoyo_path_info *saved_group_name; | ||
26 | int error = -ENOMEM; | ||
27 | if (!tomoyo_is_correct_path(group_name, 0, 0, 0) || | ||
28 | !group_name[0]) | ||
29 | return NULL; | ||
30 | saved_group_name = tomoyo_get_name(group_name); | ||
31 | if (!saved_group_name) | ||
32 | return NULL; | ||
33 | entry = kzalloc(sizeof(*entry), GFP_NOFS); | ||
34 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
35 | goto out; | ||
36 | list_for_each_entry_rcu(group, &tomoyo_number_group_list, list) { | ||
37 | if (saved_group_name != group->group_name) | ||
38 | continue; | ||
39 | atomic_inc(&group->users); | ||
40 | error = 0; | ||
41 | break; | ||
42 | } | ||
43 | if (error && tomoyo_memory_ok(entry)) { | ||
44 | INIT_LIST_HEAD(&entry->member_list); | ||
45 | entry->group_name = saved_group_name; | ||
46 | saved_group_name = NULL; | ||
47 | atomic_set(&entry->users, 1); | ||
48 | list_add_tail_rcu(&entry->list, &tomoyo_number_group_list); | ||
49 | group = entry; | ||
50 | entry = NULL; | ||
51 | error = 0; | ||
52 | } | ||
53 | mutex_unlock(&tomoyo_policy_lock); | ||
54 | out: | ||
55 | tomoyo_put_name(saved_group_name); | ||
56 | kfree(entry); | ||
57 | return !error ? group : NULL; | ||
58 | } | ||
59 | |||
60 | /** | ||
61 | * tomoyo_write_number_group_policy - Write "struct tomoyo_number_group" list. | ||
62 | * | ||
63 | * @data: String to parse. | ||
64 | * @is_delete: True if it is a delete request. | ||
65 | * | ||
66 | * Returns 0 on success, nagative value otherwise. | ||
67 | */ | ||
68 | int tomoyo_write_number_group_policy(char *data, const bool is_delete) | ||
69 | { | ||
70 | struct tomoyo_number_group *group; | ||
71 | struct tomoyo_number_group_member e = { }; | ||
72 | struct tomoyo_number_group_member *member; | ||
73 | int error = is_delete ? -ENOENT : -ENOMEM; | ||
74 | char *w[2]; | ||
75 | if (!tomoyo_tokenize(data, w, sizeof(w))) | ||
76 | return -EINVAL; | ||
77 | if (!tomoyo_parse_number_union(w[1], &e.number)) | ||
78 | return -EINVAL; | ||
79 | if (e.number.is_group || e.number.values[0] > e.number.values[1]) { | ||
80 | tomoyo_put_number_union(&e.number); | ||
81 | return -EINVAL; | ||
82 | } | ||
83 | group = tomoyo_get_number_group(w[0]); | ||
84 | if (!group) | ||
85 | return -ENOMEM; | ||
86 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
87 | goto out; | ||
88 | list_for_each_entry_rcu(member, &group->member_list, list) { | ||
89 | if (memcmp(&member->number, &e.number, sizeof(e.number))) | ||
90 | continue; | ||
91 | member->is_deleted = is_delete; | ||
92 | error = 0; | ||
93 | break; | ||
94 | } | ||
95 | if (!is_delete && error) { | ||
96 | struct tomoyo_number_group_member *entry = | ||
97 | tomoyo_commit_ok(&e, sizeof(e)); | ||
98 | if (entry) { | ||
99 | list_add_tail_rcu(&entry->list, &group->member_list); | ||
100 | error = 0; | ||
101 | } | ||
102 | } | ||
103 | mutex_unlock(&tomoyo_policy_lock); | ||
104 | out: | ||
105 | tomoyo_put_number_group(group); | ||
106 | return error; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * tomoyo_read_number_group_policy - Read "struct tomoyo_number_group" list. | ||
111 | * | ||
112 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
113 | * | ||
114 | * Returns true on success, false otherwise. | ||
115 | * | ||
116 | * Caller holds tomoyo_read_lock(). | ||
117 | */ | ||
118 | bool tomoyo_read_number_group_policy(struct tomoyo_io_buffer *head) | ||
119 | { | ||
120 | struct list_head *gpos; | ||
121 | struct list_head *mpos; | ||
122 | list_for_each_cookie(gpos, head->read_var1, &tomoyo_number_group_list) { | ||
123 | struct tomoyo_number_group *group; | ||
124 | const char *name; | ||
125 | group = list_entry(gpos, struct tomoyo_number_group, list); | ||
126 | name = group->group_name->name; | ||
127 | list_for_each_cookie(mpos, head->read_var2, | ||
128 | &group->member_list) { | ||
129 | int pos; | ||
130 | const struct tomoyo_number_group_member *member | ||
131 | = list_entry(mpos, | ||
132 | struct tomoyo_number_group_member, | ||
133 | list); | ||
134 | if (member->is_deleted) | ||
135 | continue; | ||
136 | pos = head->read_avail; | ||
137 | if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_NUMBER_GROUP | ||
138 | "%s", name) || | ||
139 | !tomoyo_print_number_union(head, &member->number) || | ||
140 | !tomoyo_io_printf(head, "\n")) { | ||
141 | head->read_avail = pos; | ||
142 | return false; | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | return true; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * tomoyo_number_matches_group - Check whether the given number matches members of the given number group. | ||
151 | * | ||
152 | * @min: Min number. | ||
153 | * @max: Max number. | ||
154 | * @group: Pointer to "struct tomoyo_number_group". | ||
155 | * | ||
156 | * Returns true if @min and @max partially overlaps @group, false otherwise. | ||
157 | * | ||
158 | * Caller holds tomoyo_read_lock(). | ||
159 | */ | ||
160 | bool tomoyo_number_matches_group(const unsigned long min, | ||
161 | const unsigned long max, | ||
162 | const struct tomoyo_number_group *group) | ||
163 | { | ||
164 | struct tomoyo_number_group_member *member; | ||
165 | bool matched = false; | ||
166 | list_for_each_entry_rcu(member, &group->member_list, list) { | ||
167 | if (member->is_deleted) | ||
168 | continue; | ||
169 | if (min > member->number.values[1] || | ||
170 | max < member->number.values[0]) | ||
171 | continue; | ||
172 | matched = true; | ||
173 | break; | ||
174 | } | ||
175 | return matched; | ||
176 | } | ||