diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2010-05-10 04:30:26 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-05-16 19:25:57 -0400 |
commit | 7762fbfffdbce8191f5236d5053b290035d3d749 (patch) | |
tree | 08b6de0c09c5571d3bdb61c429e1ec68e748f796 /security | |
parent | ba0c1709f4946a5ca1a678f4318ed72c0d409b3c (diff) |
TOMOYO: Add pathname grouping support.
This patch adds pathname grouping support, which is useful for grouping
pathnames that cannot be represented using /\{dir\}/ pattern.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/tomoyo/Makefile | 2 | ||||
-rw-r--r-- | security/tomoyo/common.c | 100 | ||||
-rw-r--r-- | security/tomoyo/common.h | 94 | ||||
-rw-r--r-- | security/tomoyo/file.c | 71 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 48 | ||||
-rw-r--r-- | security/tomoyo/path_group.c | 172 |
6 files changed, 433 insertions, 54 deletions
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 60a9e2002da1..4fb39030f6bd 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 | obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o path_group.o | ||
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 62e089c50ae8..b5dbdc9ff73c 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -76,6 +76,49 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer, | |||
76 | const int buffer_len); | 76 | const int buffer_len); |
77 | 77 | ||
78 | /** | 78 | /** |
79 | * tomoyo_parse_name_union - Parse a tomoyo_name_union. | ||
80 | * | ||
81 | * @filename: Name or name group. | ||
82 | * @ptr: Pointer to "struct tomoyo_name_union". | ||
83 | * | ||
84 | * Returns true on success, false otherwise. | ||
85 | */ | ||
86 | bool tomoyo_parse_name_union(const char *filename, | ||
87 | struct tomoyo_name_union *ptr) | ||
88 | { | ||
89 | if (!tomoyo_is_correct_path(filename, 0, 0, 0)) | ||
90 | return false; | ||
91 | if (filename[0] == '@') { | ||
92 | ptr->group = tomoyo_get_path_group(filename + 1); | ||
93 | ptr->is_group = true; | ||
94 | return ptr->group != NULL; | ||
95 | } | ||
96 | ptr->filename = tomoyo_get_name(filename); | ||
97 | ptr->is_group = false; | ||
98 | return ptr->filename != NULL; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * tomoyo_print_name_union - Print a tomoyo_name_union. | ||
103 | * | ||
104 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
105 | * @ptr: Pointer to "struct tomoyo_name_union". | ||
106 | * | ||
107 | * Returns true on success, false otherwise. | ||
108 | */ | ||
109 | static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head, | ||
110 | const struct tomoyo_name_union *ptr) | ||
111 | { | ||
112 | int pos = head->read_avail; | ||
113 | if (pos && head->read_buf[pos - 1] == ' ') | ||
114 | head->read_avail--; | ||
115 | if (ptr->is_group) | ||
116 | return tomoyo_io_printf(head, " @%s", | ||
117 | ptr->group->group_name->name); | ||
118 | return tomoyo_io_printf(head, " %s", ptr->filename->name); | ||
119 | } | ||
120 | |||
121 | /** | ||
79 | * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. | 122 | * tomoyo_is_byte_range - Check whether the string isa \ooo style octal value. |
80 | * | 123 | * |
81 | * @str: Pointer to the string. | 124 | * @str: Pointer to the string. |
@@ -172,6 +215,33 @@ static void tomoyo_normalize_line(unsigned char *buffer) | |||
172 | } | 215 | } |
173 | 216 | ||
174 | /** | 217 | /** |
218 | * tomoyo_tokenize - Tokenize string. | ||
219 | * | ||
220 | * @buffer: The line to tokenize. | ||
221 | * @w: Pointer to "char *". | ||
222 | * @size: Sizeof @w . | ||
223 | * | ||
224 | * Returns true on success, false otherwise. | ||
225 | */ | ||
226 | bool tomoyo_tokenize(char *buffer, char *w[], size_t size) | ||
227 | { | ||
228 | int count = size / sizeof(char *); | ||
229 | int i; | ||
230 | for (i = 0; i < count; i++) | ||
231 | w[i] = ""; | ||
232 | for (i = 0; i < count; i++) { | ||
233 | char *cp = strchr(buffer, ' '); | ||
234 | if (cp) | ||
235 | *cp = '\0'; | ||
236 | w[i] = buffer; | ||
237 | if (!cp) | ||
238 | break; | ||
239 | buffer = cp + 1; | ||
240 | } | ||
241 | return i < count || !*buffer; | ||
242 | } | ||
243 | |||
244 | /** | ||
175 | * tomoyo_is_correct_path - Validate a pathname. | 245 | * tomoyo_is_correct_path - Validate a pathname. |
176 | * @filename: The pathname to check. | 246 | * @filename: The pathname to check. |
177 | * @start_type: Should the pathname start with '/'? | 247 | * @start_type: Should the pathname start with '/'? |
@@ -1368,21 +1438,20 @@ static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head, | |||
1368 | { | 1438 | { |
1369 | int pos; | 1439 | int pos; |
1370 | u8 bit; | 1440 | u8 bit; |
1371 | const char *filename; | ||
1372 | const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); | 1441 | const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); |
1373 | 1442 | ||
1374 | filename = ptr->filename->name; | ||
1375 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { | 1443 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { |
1376 | const char *msg; | ||
1377 | if (!(perm & (1 << bit))) | 1444 | if (!(perm & (1 << bit))) |
1378 | continue; | 1445 | continue; |
1379 | /* Print "read/write" instead of "read" and "write". */ | 1446 | /* Print "read/write" instead of "read" and "write". */ |
1380 | if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE) | 1447 | if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE) |
1381 | && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) | 1448 | && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) |
1382 | continue; | 1449 | continue; |
1383 | msg = tomoyo_path2keyword(bit); | ||
1384 | pos = head->read_avail; | 1450 | pos = head->read_avail; |
1385 | if (!tomoyo_io_printf(head, "allow_%s %s\n", msg, filename)) | 1451 | if (!tomoyo_io_printf(head, "allow_%s ", |
1452 | tomoyo_path2keyword(bit)) || | ||
1453 | !tomoyo_print_name_union(head, &ptr->name) || | ||
1454 | !tomoyo_io_printf(head, "\n")) | ||
1386 | goto out; | 1455 | goto out; |
1387 | } | 1456 | } |
1388 | head->read_bit = 0; | 1457 | head->read_bit = 0; |
@@ -1405,21 +1474,18 @@ static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head, | |||
1405 | struct tomoyo_path2_acl *ptr) | 1474 | struct tomoyo_path2_acl *ptr) |
1406 | { | 1475 | { |
1407 | int pos; | 1476 | int pos; |
1408 | const char *filename1; | ||
1409 | const char *filename2; | ||
1410 | const u8 perm = ptr->perm; | 1477 | const u8 perm = ptr->perm; |
1411 | u8 bit; | 1478 | u8 bit; |
1412 | 1479 | ||
1413 | filename1 = ptr->filename1->name; | ||
1414 | filename2 = ptr->filename2->name; | ||
1415 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { | 1480 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { |
1416 | const char *msg; | ||
1417 | if (!(perm & (1 << bit))) | 1481 | if (!(perm & (1 << bit))) |
1418 | continue; | 1482 | continue; |
1419 | msg = tomoyo_path22keyword(bit); | ||
1420 | pos = head->read_avail; | 1483 | pos = head->read_avail; |
1421 | if (!tomoyo_io_printf(head, "allow_%s %s %s\n", msg, | 1484 | if (!tomoyo_io_printf(head, "allow_%s ", |
1422 | filename1, filename2)) | 1485 | tomoyo_path22keyword(bit)) || |
1486 | !tomoyo_print_name_union(head, &ptr->name1) || | ||
1487 | !tomoyo_print_name_union(head, &ptr->name2) || | ||
1488 | !tomoyo_io_printf(head, "\n")) | ||
1423 | goto out; | 1489 | goto out; |
1424 | } | 1490 | } |
1425 | head->read_bit = 0; | 1491 | head->read_bit = 0; |
@@ -1682,6 +1748,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) | |||
1682 | return tomoyo_write_pattern_policy(data, is_delete); | 1748 | return tomoyo_write_pattern_policy(data, is_delete); |
1683 | if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) | 1749 | if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) |
1684 | return tomoyo_write_no_rewrite_policy(data, is_delete); | 1750 | return tomoyo_write_no_rewrite_policy(data, is_delete); |
1751 | if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) | ||
1752 | return tomoyo_write_path_group_policy(data, is_delete); | ||
1685 | return -EINVAL; | 1753 | return -EINVAL; |
1686 | } | 1754 | } |
1687 | 1755 | ||
@@ -1738,6 +1806,12 @@ static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) | |||
1738 | head->read_var2 = NULL; | 1806 | head->read_var2 = NULL; |
1739 | head->read_step = 9; | 1807 | head->read_step = 9; |
1740 | case 9: | 1808 | case 9: |
1809 | if (!tomoyo_read_path_group_policy(head)) | ||
1810 | break; | ||
1811 | head->read_var1 = NULL; | ||
1812 | head->read_var2 = NULL; | ||
1813 | head->read_step = 10; | ||
1814 | case 10: | ||
1741 | head->read_eof = true; | 1815 | head->read_eof = true; |
1742 | break; | 1816 | break; |
1743 | default: | 1817 | default: |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index c95f48609461..9f1ae5e3ba51 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -54,6 +54,7 @@ struct linux_binprm; | |||
54 | #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " | 54 | #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " |
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_SELECT "select " | 58 | #define TOMOYO_KEYWORD_SELECT "select " |
58 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " | 59 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " |
59 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" | 60 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" |
@@ -204,6 +205,27 @@ struct tomoyo_path_info_with_data { | |||
204 | char barrier2[16]; /* Safeguard for overrun. */ | 205 | char barrier2[16]; /* Safeguard for overrun. */ |
205 | }; | 206 | }; |
206 | 207 | ||
208 | struct tomoyo_name_union { | ||
209 | const struct tomoyo_path_info *filename; | ||
210 | struct tomoyo_path_group *group; | ||
211 | u8 is_group; | ||
212 | }; | ||
213 | |||
214 | /* Structure for "path_group" directive. */ | ||
215 | struct tomoyo_path_group { | ||
216 | struct list_head list; | ||
217 | const struct tomoyo_path_info *group_name; | ||
218 | struct list_head member_list; | ||
219 | atomic_t users; | ||
220 | }; | ||
221 | |||
222 | /* Structure for "path_group" directive. */ | ||
223 | struct tomoyo_path_group_member { | ||
224 | struct list_head list; | ||
225 | bool is_deleted; | ||
226 | const struct tomoyo_path_info *member_name; | ||
227 | }; | ||
228 | |||
207 | /* | 229 | /* |
208 | * tomoyo_acl_info is a structure which is used for holding | 230 | * tomoyo_acl_info is a structure which is used for holding |
209 | * | 231 | * |
@@ -274,7 +296,7 @@ struct tomoyo_domain_info { | |||
274 | * | 296 | * |
275 | * (1) "head" which is a "struct tomoyo_acl_info". | 297 | * (1) "head" which is a "struct tomoyo_acl_info". |
276 | * (2) "perm" which is a bitmask of permitted operations. | 298 | * (2) "perm" which is a bitmask of permitted operations. |
277 | * (3) "filename" is the pathname. | 299 | * (3) "name" is the pathname. |
278 | * | 300 | * |
279 | * Directives held by this structure are "allow_read/write", "allow_execute", | 301 | * Directives held by this structure are "allow_read/write", "allow_execute", |
280 | * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", | 302 | * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", |
@@ -287,8 +309,7 @@ struct tomoyo_path_acl { | |||
287 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ | 309 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ |
288 | u8 perm_high; | 310 | u8 perm_high; |
289 | u16 perm; | 311 | u16 perm; |
290 | /* Pointer to single pathname. */ | 312 | struct tomoyo_name_union name; |
291 | const struct tomoyo_path_info *filename; | ||
292 | }; | 313 | }; |
293 | 314 | ||
294 | /* | 315 | /* |
@@ -298,8 +319,8 @@ struct tomoyo_path_acl { | |||
298 | * | 319 | * |
299 | * (1) "head" which is a "struct tomoyo_acl_info". | 320 | * (1) "head" which is a "struct tomoyo_acl_info". |
300 | * (2) "perm" which is a bitmask of permitted operations. | 321 | * (2) "perm" which is a bitmask of permitted operations. |
301 | * (3) "filename1" is the source/old pathname. | 322 | * (3) "name1" is the source/old pathname. |
302 | * (4) "filename2" is the destination/new pathname. | 323 | * (4) "name2" is the destination/new pathname. |
303 | * | 324 | * |
304 | * Directives held by this structure are "allow_rename", "allow_link" and | 325 | * Directives held by this structure are "allow_rename", "allow_link" and |
305 | * "allow_pivot_root". | 326 | * "allow_pivot_root". |
@@ -307,10 +328,8 @@ struct tomoyo_path_acl { | |||
307 | struct tomoyo_path2_acl { | 328 | struct tomoyo_path2_acl { |
308 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ | 329 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ |
309 | u8 perm; | 330 | u8 perm; |
310 | /* Pointer to single pathname. */ | 331 | struct tomoyo_name_union name1; |
311 | const struct tomoyo_path_info *filename1; | 332 | struct tomoyo_name_union name2; |
312 | /* Pointer to single pathname. */ | ||
313 | const struct tomoyo_path_info *filename2; | ||
314 | }; | 333 | }; |
315 | 334 | ||
316 | /* | 335 | /* |
@@ -514,6 +533,9 @@ struct tomoyo_policy_manager_entry { | |||
514 | 533 | ||
515 | /********** Function prototypes. **********/ | 534 | /********** Function prototypes. **********/ |
516 | 535 | ||
536 | /* Check whether the given name matches the given name_union. */ | ||
537 | bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, | ||
538 | const struct tomoyo_name_union *ptr); | ||
517 | /* Check whether the domain has too many ACL entries to hold. */ | 539 | /* Check whether the domain has too many ACL entries to hold. */ |
518 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); | 540 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); |
519 | /* Transactional sprintf() for policy dump. */ | 541 | /* Transactional sprintf() for policy dump. */ |
@@ -526,6 +548,12 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, | |||
526 | const s8 pattern_type, const s8 end_type); | 548 | const s8 pattern_type, const s8 end_type); |
527 | /* Check whether the token can be a domainname. */ | 549 | /* Check whether the token can be a domainname. */ |
528 | bool tomoyo_is_domain_def(const unsigned char *buffer); | 550 | bool tomoyo_is_domain_def(const unsigned char *buffer); |
551 | bool tomoyo_parse_name_union(const char *filename, | ||
552 | struct tomoyo_name_union *ptr); | ||
553 | /* Check whether the given filename matches the given path_group. */ | ||
554 | bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, | ||
555 | const struct tomoyo_path_group *group, | ||
556 | const bool may_use_pattern); | ||
529 | /* Check whether the given filename matches the given pattern. */ | 557 | /* Check whether the given filename matches the given pattern. */ |
530 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, | 558 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, |
531 | const struct tomoyo_path_info *pattern); | 559 | const struct tomoyo_path_info *pattern); |
@@ -540,10 +568,14 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head); | |||
540 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head); | 568 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head); |
541 | /* Read "file_pattern" entry in exception policy. */ | 569 | /* Read "file_pattern" entry in exception policy. */ |
542 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); | 570 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); |
571 | /* Read "path_group" entry in exception policy. */ | ||
572 | bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head); | ||
543 | /* Read "allow_read" entry in exception policy. */ | 573 | /* Read "allow_read" entry in exception policy. */ |
544 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); | 574 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); |
545 | /* Read "deny_rewrite" entry in exception policy. */ | 575 | /* Read "deny_rewrite" entry in exception policy. */ |
546 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); | 576 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); |
577 | /* Tokenize a line. */ | ||
578 | bool tomoyo_tokenize(char *buffer, char *w[], size_t size); | ||
547 | /* Write domain policy violation warning message to console? */ | 579 | /* Write domain policy violation warning message to console? */ |
548 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); | 580 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); |
549 | /* Convert double path operation to operation name. */ | 581 | /* Convert double path operation to operation name. */ |
@@ -580,12 +612,18 @@ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete); | |||
580 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); | 612 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); |
581 | /* Create "file_pattern" entry in exception policy. */ | 613 | /* Create "file_pattern" entry in exception policy. */ |
582 | int tomoyo_write_pattern_policy(char *data, const bool is_delete); | 614 | int tomoyo_write_pattern_policy(char *data, const bool is_delete); |
615 | /* Create "path_group" entry in exception policy. */ | ||
616 | int tomoyo_write_path_group_policy(char *data, const bool is_delete); | ||
583 | /* Find a domain by the given name. */ | 617 | /* Find a domain by the given name. */ |
584 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | 618 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); |
585 | /* Find or create a domain by the given name. */ | 619 | /* Find or create a domain by the given name. */ |
586 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | 620 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * |
587 | domainname, | 621 | domainname, |
588 | const u8 profile); | 622 | const u8 profile); |
623 | |||
624 | /* Allocate memory for "struct tomoyo_path_group". */ | ||
625 | struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); | ||
626 | |||
589 | /* Check mode for specified functionality. */ | 627 | /* Check mode for specified functionality. */ |
590 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | 628 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, |
591 | const u8 index); | 629 | const u8 index); |
@@ -642,6 +680,9 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, | |||
642 | int tomoyo_check_rewrite_permission(struct file *filp); | 680 | int tomoyo_check_rewrite_permission(struct file *filp); |
643 | int tomoyo_find_next_domain(struct linux_binprm *bprm); | 681 | int tomoyo_find_next_domain(struct linux_binprm *bprm); |
644 | 682 | ||
683 | /* Drop refcount on tomoyo_name_union. */ | ||
684 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr); | ||
685 | |||
645 | /* Run garbage collector. */ | 686 | /* Run garbage collector. */ |
646 | void tomoyo_run_gc(void); | 687 | void tomoyo_run_gc(void); |
647 | 688 | ||
@@ -655,6 +696,7 @@ extern struct srcu_struct tomoyo_ss; | |||
655 | /* The list for "struct tomoyo_domain_info". */ | 696 | /* The list for "struct tomoyo_domain_info". */ |
656 | extern struct list_head tomoyo_domain_list; | 697 | extern struct list_head tomoyo_domain_list; |
657 | 698 | ||
699 | extern struct list_head tomoyo_path_group_list; | ||
658 | extern struct list_head tomoyo_domain_initializer_list; | 700 | extern struct list_head tomoyo_domain_initializer_list; |
659 | extern struct list_head tomoyo_domain_keeper_list; | 701 | extern struct list_head tomoyo_domain_keeper_list; |
660 | extern struct list_head tomoyo_alias_list; | 702 | extern struct list_head tomoyo_alias_list; |
@@ -725,6 +767,12 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name) | |||
725 | } | 767 | } |
726 | } | 768 | } |
727 | 769 | ||
770 | static inline void tomoyo_put_path_group(struct tomoyo_path_group *group) | ||
771 | { | ||
772 | if (group) | ||
773 | atomic_dec(&group->users); | ||
774 | } | ||
775 | |||
728 | static inline struct tomoyo_domain_info *tomoyo_domain(void) | 776 | static inline struct tomoyo_domain_info *tomoyo_domain(void) |
729 | { | 777 | { |
730 | return current_cred()->security; | 778 | return current_cred()->security; |
@@ -736,6 +784,34 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct | |||
736 | return task_cred_xxx(task, security); | 784 | return task_cred_xxx(task, security); |
737 | } | 785 | } |
738 | 786 | ||
787 | static inline bool tomoyo_is_same_acl_head(const struct tomoyo_acl_info *p1, | ||
788 | const struct tomoyo_acl_info *p2) | ||
789 | { | ||
790 | return p1->type == p2->type; | ||
791 | } | ||
792 | |||
793 | static inline bool tomoyo_is_same_name_union | ||
794 | (const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2) | ||
795 | { | ||
796 | return p1->filename == p2->filename && p1->group == p2->group && | ||
797 | p1->is_group == p2->is_group; | ||
798 | } | ||
799 | |||
800 | static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, | ||
801 | const struct tomoyo_path_acl *p2) | ||
802 | { | ||
803 | return tomoyo_is_same_acl_head(&p1->head, &p2->head) && | ||
804 | tomoyo_is_same_name_union(&p1->name, &p2->name); | ||
805 | } | ||
806 | |||
807 | static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1, | ||
808 | const struct tomoyo_path2_acl *p2) | ||
809 | { | ||
810 | return tomoyo_is_same_acl_head(&p1->head, &p2->head) && | ||
811 | tomoyo_is_same_name_union(&p1->name1, &p2->name1) && | ||
812 | tomoyo_is_same_name_union(&p1->name2, &p2->name2); | ||
813 | } | ||
814 | |||
739 | static inline bool tomoyo_is_same_domain_initializer_entry | 815 | static inline bool tomoyo_is_same_domain_initializer_entry |
740 | (const struct tomoyo_domain_initializer_entry *p1, | 816 | (const struct tomoyo_domain_initializer_entry *p1, |
741 | const struct tomoyo_domain_initializer_entry *p2) | 817 | const struct tomoyo_domain_initializer_entry *p2) |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 6651cac87625..1c6f8238ec47 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -45,6 +45,37 @@ static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { | |||
45 | [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", | 45 | [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", |
46 | }; | 46 | }; |
47 | 47 | ||
48 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) | ||
49 | { | ||
50 | if (!ptr) | ||
51 | return; | ||
52 | if (ptr->is_group) | ||
53 | tomoyo_put_path_group(ptr->group); | ||
54 | else | ||
55 | tomoyo_put_name(ptr->filename); | ||
56 | } | ||
57 | |||
58 | bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, | ||
59 | const struct tomoyo_name_union *ptr) | ||
60 | { | ||
61 | if (ptr->is_group) | ||
62 | return tomoyo_path_matches_group(name, ptr->group, 1); | ||
63 | return tomoyo_path_matches_pattern(name, ptr->filename); | ||
64 | } | ||
65 | |||
66 | static bool tomoyo_compare_name_union_pattern(const struct tomoyo_path_info | ||
67 | *name, | ||
68 | const struct tomoyo_name_union | ||
69 | *ptr, const bool may_use_pattern) | ||
70 | { | ||
71 | if (ptr->is_group) | ||
72 | return tomoyo_path_matches_group(name, ptr->group, | ||
73 | may_use_pattern); | ||
74 | if (may_use_pattern || !ptr->filename->is_patterned) | ||
75 | return tomoyo_path_matches_pattern(name, ptr->filename); | ||
76 | return false; | ||
77 | } | ||
78 | |||
48 | /** | 79 | /** |
49 | * tomoyo_path2keyword - Get the name of single path operation. | 80 | * tomoyo_path2keyword - Get the name of single path operation. |
50 | * | 81 | * |
@@ -637,13 +668,9 @@ static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain, | |||
637 | if (!(acl->perm_high & (perm >> 16))) | 668 | if (!(acl->perm_high & (perm >> 16))) |
638 | continue; | 669 | continue; |
639 | } | 670 | } |
640 | if (may_use_pattern || !acl->filename->is_patterned) { | 671 | if (!tomoyo_compare_name_union_pattern(filename, &acl->name, |
641 | if (!tomoyo_path_matches_pattern(filename, | 672 | may_use_pattern)) |
642 | acl->filename)) | ||
643 | continue; | ||
644 | } else { | ||
645 | continue; | 673 | continue; |
646 | } | ||
647 | error = 0; | 674 | error = 0; |
648 | break; | 675 | break; |
649 | } | 676 | } |
@@ -817,19 +844,14 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, | |||
817 | e.perm |= tomoyo_rw_mask; | 844 | e.perm |= tomoyo_rw_mask; |
818 | if (!domain) | 845 | if (!domain) |
819 | return -EINVAL; | 846 | return -EINVAL; |
820 | if (!tomoyo_is_correct_path(filename, 0, 0, 0)) | 847 | if (!tomoyo_parse_name_union(filename, &e.name)) |
821 | return -EINVAL; | 848 | return -EINVAL; |
822 | e.filename = tomoyo_get_name(filename); | ||
823 | if (!e.filename) | ||
824 | return -ENOMEM; | ||
825 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 849 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
826 | goto out; | 850 | goto out; |
827 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 851 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
828 | struct tomoyo_path_acl *acl = | 852 | struct tomoyo_path_acl *acl = |
829 | container_of(ptr, struct tomoyo_path_acl, head); | 853 | container_of(ptr, struct tomoyo_path_acl, head); |
830 | if (ptr->type != TOMOYO_TYPE_PATH_ACL) | 854 | if (!tomoyo_is_same_path_acl(acl, &e)) |
831 | continue; | ||
832 | if (acl->filename != e.filename) | ||
833 | continue; | 855 | continue; |
834 | if (is_delete) { | 856 | if (is_delete) { |
835 | if (perm <= 0xFFFF) | 857 | if (perm <= 0xFFFF) |
@@ -864,7 +886,7 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, | |||
864 | } | 886 | } |
865 | mutex_unlock(&tomoyo_policy_lock); | 887 | mutex_unlock(&tomoyo_policy_lock); |
866 | out: | 888 | out: |
867 | tomoyo_put_name(e.filename); | 889 | tomoyo_put_name_union(&e.name); |
868 | return error; | 890 | return error; |
869 | } | 891 | } |
870 | 892 | ||
@@ -896,22 +918,15 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | |||
896 | 918 | ||
897 | if (!domain) | 919 | if (!domain) |
898 | return -EINVAL; | 920 | return -EINVAL; |
899 | if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || | 921 | if (!tomoyo_parse_name_union(filename1, &e.name1) || |
900 | !tomoyo_is_correct_path(filename2, 0, 0, 0)) | 922 | !tomoyo_parse_name_union(filename2, &e.name2)) |
901 | return -EINVAL; | ||
902 | e.filename1 = tomoyo_get_name(filename1); | ||
903 | e.filename2 = tomoyo_get_name(filename2); | ||
904 | if (!e.filename1 || !e.filename2) | ||
905 | goto out; | 923 | goto out; |
906 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 924 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
907 | goto out; | 925 | goto out; |
908 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 926 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
909 | struct tomoyo_path2_acl *acl = | 927 | struct tomoyo_path2_acl *acl = |
910 | container_of(ptr, struct tomoyo_path2_acl, head); | 928 | container_of(ptr, struct tomoyo_path2_acl, head); |
911 | if (ptr->type != TOMOYO_TYPE_PATH2_ACL) | 929 | if (!tomoyo_is_same_path2_acl(acl, &e)) |
912 | continue; | ||
913 | if (acl->filename1 != e.filename1 || | ||
914 | acl->filename2 != e.filename2) | ||
915 | continue; | 930 | continue; |
916 | if (is_delete) | 931 | if (is_delete) |
917 | acl->perm &= ~perm; | 932 | acl->perm &= ~perm; |
@@ -931,8 +946,8 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | |||
931 | } | 946 | } |
932 | mutex_unlock(&tomoyo_policy_lock); | 947 | mutex_unlock(&tomoyo_policy_lock); |
933 | out: | 948 | out: |
934 | tomoyo_put_name(e.filename1); | 949 | tomoyo_put_name_union(&e.name1); |
935 | tomoyo_put_name(e.filename2); | 950 | tomoyo_put_name_union(&e.name2); |
936 | return error; | 951 | return error; |
937 | } | 952 | } |
938 | 953 | ||
@@ -985,9 +1000,9 @@ static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain, | |||
985 | acl = container_of(ptr, struct tomoyo_path2_acl, head); | 1000 | acl = container_of(ptr, struct tomoyo_path2_acl, head); |
986 | if (!(acl->perm & perm)) | 1001 | if (!(acl->perm & perm)) |
987 | continue; | 1002 | continue; |
988 | if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) | 1003 | if (!tomoyo_compare_name_union(filename1, &acl->name1)) |
989 | continue; | 1004 | continue; |
990 | if (!tomoyo_path_matches_pattern(filename2, acl->filename2)) | 1005 | if (!tomoyo_compare_name_union(filename2, &acl->name2)) |
991 | continue; | 1006 | continue; |
992 | error = 0; | 1007 | error = 0; |
993 | break; | 1008 | break; |
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 245bf422e3a5..b9cc71b04314 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | 13 | ||
14 | enum tomoyo_gc_id { | 14 | enum tomoyo_gc_id { |
15 | TOMOYO_ID_PATH_GROUP, | ||
16 | TOMOYO_ID_PATH_GROUP_MEMBER, | ||
15 | TOMOYO_ID_DOMAIN_INITIALIZER, | 17 | TOMOYO_ID_DOMAIN_INITIALIZER, |
16 | TOMOYO_ID_DOMAIN_KEEPER, | 18 | TOMOYO_ID_DOMAIN_KEEPER, |
17 | TOMOYO_ID_ALIAS, | 19 | TOMOYO_ID_ALIAS, |
@@ -91,15 +93,15 @@ static void tomoyo_del_acl(struct tomoyo_acl_info *acl) | |||
91 | { | 93 | { |
92 | struct tomoyo_path_acl *entry | 94 | struct tomoyo_path_acl *entry |
93 | = container_of(acl, typeof(*entry), head); | 95 | = container_of(acl, typeof(*entry), head); |
94 | tomoyo_put_name(entry->filename); | 96 | tomoyo_put_name_union(&entry->name); |
95 | } | 97 | } |
96 | break; | 98 | break; |
97 | case TOMOYO_TYPE_PATH2_ACL: | 99 | case TOMOYO_TYPE_PATH2_ACL: |
98 | { | 100 | { |
99 | struct tomoyo_path2_acl *entry | 101 | struct tomoyo_path2_acl *entry |
100 | = container_of(acl, typeof(*entry), head); | 102 | = container_of(acl, typeof(*entry), head); |
101 | tomoyo_put_name(entry->filename1); | 103 | tomoyo_put_name_union(&entry->name1); |
102 | tomoyo_put_name(entry->filename2); | 104 | tomoyo_put_name_union(&entry->name2); |
103 | } | 105 | } |
104 | break; | 106 | break; |
105 | default: | 107 | default: |
@@ -149,6 +151,17 @@ static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) | |||
149 | { | 151 | { |
150 | } | 152 | } |
151 | 153 | ||
154 | static void tomoyo_del_path_group_member(struct tomoyo_path_group_member | ||
155 | *member) | ||
156 | { | ||
157 | tomoyo_put_name(member->member_name); | ||
158 | } | ||
159 | |||
160 | static void tomoyo_del_path_group(struct tomoyo_path_group *group) | ||
161 | { | ||
162 | tomoyo_put_name(group->group_name); | ||
163 | } | ||
164 | |||
152 | static void tomoyo_collect_entry(void) | 165 | static void tomoyo_collect_entry(void) |
153 | { | 166 | { |
154 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 167 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
@@ -293,6 +306,29 @@ static void tomoyo_collect_entry(void) | |||
293 | } | 306 | } |
294 | } | 307 | } |
295 | } | 308 | } |
309 | { | ||
310 | struct tomoyo_path_group *group; | ||
311 | list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { | ||
312 | struct tomoyo_path_group_member *member; | ||
313 | list_for_each_entry_rcu(member, &group->member_list, | ||
314 | list) { | ||
315 | if (!member->is_deleted) | ||
316 | continue; | ||
317 | if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP_MEMBER, | ||
318 | member)) | ||
319 | list_del_rcu(&member->list); | ||
320 | else | ||
321 | break; | ||
322 | } | ||
323 | if (!list_empty(&group->member_list) || | ||
324 | atomic_read(&group->users)) | ||
325 | continue; | ||
326 | if (tomoyo_add_to_gc(TOMOYO_ID_PATH_GROUP, group)) | ||
327 | list_del_rcu(&group->list); | ||
328 | else | ||
329 | break; | ||
330 | } | ||
331 | } | ||
296 | mutex_unlock(&tomoyo_policy_lock); | 332 | mutex_unlock(&tomoyo_policy_lock); |
297 | } | 333 | } |
298 | 334 | ||
@@ -334,6 +370,12 @@ static void tomoyo_kfree_entry(void) | |||
334 | if (!tomoyo_del_domain(p->element)) | 370 | if (!tomoyo_del_domain(p->element)) |
335 | continue; | 371 | continue; |
336 | break; | 372 | break; |
373 | case TOMOYO_ID_PATH_GROUP_MEMBER: | ||
374 | tomoyo_del_path_group_member(p->element); | ||
375 | break; | ||
376 | case TOMOYO_ID_PATH_GROUP: | ||
377 | tomoyo_del_path_group(p->element); | ||
378 | break; | ||
337 | default: | 379 | default: |
338 | printk(KERN_WARNING "Unknown type\n"); | 380 | printk(KERN_WARNING "Unknown type\n"); |
339 | break; | 381 | break; |
diff --git a/security/tomoyo/path_group.c b/security/tomoyo/path_group.c new file mode 100644 index 000000000000..c988041c8e1c --- /dev/null +++ b/security/tomoyo/path_group.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * security/tomoyo/path_group.c | ||
3 | * | ||
4 | * Copyright (C) 2005-2009 NTT DATA CORPORATION | ||
5 | */ | ||
6 | |||
7 | #include <linux/slab.h> | ||
8 | #include "common.h" | ||
9 | /* The list for "struct ccs_path_group". */ | ||
10 | LIST_HEAD(tomoyo_path_group_list); | ||
11 | |||
12 | /** | ||
13 | * tomoyo_get_path_group - Allocate memory for "struct tomoyo_path_group". | ||
14 | * | ||
15 | * @group_name: The name of pathname group. | ||
16 | * | ||
17 | * Returns pointer to "struct tomoyo_path_group" on success, NULL otherwise. | ||
18 | */ | ||
19 | struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name) | ||
20 | { | ||
21 | struct tomoyo_path_group *entry = NULL; | ||
22 | struct tomoyo_path_group *group = NULL; | ||
23 | const struct tomoyo_path_info *saved_group_name; | ||
24 | int error = -ENOMEM; | ||
25 | if (!tomoyo_is_correct_path(group_name, 0, 0, 0) || | ||
26 | !group_name[0]) | ||
27 | return NULL; | ||
28 | saved_group_name = tomoyo_get_name(group_name); | ||
29 | if (!saved_group_name) | ||
30 | return NULL; | ||
31 | entry = kzalloc(sizeof(*entry), GFP_NOFS); | ||
32 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
33 | goto out; | ||
34 | list_for_each_entry_rcu(group, &tomoyo_path_group_list, list) { | ||
35 | if (saved_group_name != group->group_name) | ||
36 | continue; | ||
37 | atomic_inc(&group->users); | ||
38 | error = 0; | ||
39 | break; | ||
40 | } | ||
41 | if (error && tomoyo_memory_ok(entry)) { | ||
42 | INIT_LIST_HEAD(&entry->member_list); | ||
43 | entry->group_name = saved_group_name; | ||
44 | saved_group_name = NULL; | ||
45 | atomic_set(&entry->users, 1); | ||
46 | list_add_tail_rcu(&entry->list, &tomoyo_path_group_list); | ||
47 | group = entry; | ||
48 | entry = NULL; | ||
49 | error = 0; | ||
50 | } | ||
51 | mutex_unlock(&tomoyo_policy_lock); | ||
52 | out: | ||
53 | tomoyo_put_name(saved_group_name); | ||
54 | kfree(entry); | ||
55 | return !error ? group : NULL; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * tomoyo_write_path_group_policy - Write "struct tomoyo_path_group" list. | ||
60 | * | ||
61 | * @data: String to parse. | ||
62 | * @is_delete: True if it is a delete request. | ||
63 | * | ||
64 | * Returns 0 on success, nagative value otherwise. | ||
65 | */ | ||
66 | int tomoyo_write_path_group_policy(char *data, const bool is_delete) | ||
67 | { | ||
68 | struct tomoyo_path_group *group; | ||
69 | struct tomoyo_path_group_member *member; | ||
70 | struct tomoyo_path_group_member e = { }; | ||
71 | int error = is_delete ? -ENOENT : -ENOMEM; | ||
72 | char *w[2]; | ||
73 | if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) | ||
74 | return -EINVAL; | ||
75 | group = tomoyo_get_path_group(w[0]); | ||
76 | if (!group) | ||
77 | return -ENOMEM; | ||
78 | e.member_name = tomoyo_get_name(w[1]); | ||
79 | if (!e.member_name) | ||
80 | goto out; | ||
81 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
82 | goto out; | ||
83 | list_for_each_entry_rcu(member, &group->member_list, list) { | ||
84 | if (member->member_name != e.member_name) | ||
85 | continue; | ||
86 | member->is_deleted = is_delete; | ||
87 | error = 0; | ||
88 | break; | ||
89 | } | ||
90 | if (!is_delete && error) { | ||
91 | struct tomoyo_path_group_member *entry = | ||
92 | tomoyo_commit_ok(&e, sizeof(e)); | ||
93 | if (entry) { | ||
94 | list_add_tail_rcu(&entry->list, &group->member_list); | ||
95 | error = 0; | ||
96 | } | ||
97 | } | ||
98 | mutex_unlock(&tomoyo_policy_lock); | ||
99 | out: | ||
100 | tomoyo_put_name(e.member_name); | ||
101 | tomoyo_put_path_group(group); | ||
102 | return error; | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * tomoyo_read_path_group_policy - Read "struct tomoyo_path_group" list. | ||
107 | * | ||
108 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
109 | * | ||
110 | * Returns true on success, false otherwise. | ||
111 | * | ||
112 | * Caller holds tomoyo_read_lock(). | ||
113 | */ | ||
114 | bool tomoyo_read_path_group_policy(struct tomoyo_io_buffer *head) | ||
115 | { | ||
116 | struct list_head *gpos; | ||
117 | struct list_head *mpos; | ||
118 | list_for_each_cookie(gpos, head->read_var1, &tomoyo_path_group_list) { | ||
119 | struct tomoyo_path_group *group; | ||
120 | group = list_entry(gpos, struct tomoyo_path_group, list); | ||
121 | list_for_each_cookie(mpos, head->read_var2, | ||
122 | &group->member_list) { | ||
123 | struct tomoyo_path_group_member *member; | ||
124 | member = list_entry(mpos, | ||
125 | struct tomoyo_path_group_member, | ||
126 | list); | ||
127 | if (member->is_deleted) | ||
128 | continue; | ||
129 | if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_PATH_GROUP | ||
130 | "%s %s\n", | ||
131 | group->group_name->name, | ||
132 | member->member_name->name)) | ||
133 | return false; | ||
134 | } | ||
135 | } | ||
136 | return true; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. | ||
141 | * | ||
142 | * @pathname: The name of pathname. | ||
143 | * @group: Pointer to "struct tomoyo_path_group". | ||
144 | * @may_use_pattern: True if wild card is permitted. | ||
145 | * | ||
146 | * Returns true if @pathname matches pathnames in @group, false otherwise. | ||
147 | * | ||
148 | * Caller holds tomoyo_read_lock(). | ||
149 | */ | ||
150 | bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, | ||
151 | const struct tomoyo_path_group *group, | ||
152 | const bool may_use_pattern) | ||
153 | { | ||
154 | struct tomoyo_path_group_member *member; | ||
155 | bool matched = false; | ||
156 | list_for_each_entry_rcu(member, &group->member_list, list) { | ||
157 | if (member->is_deleted) | ||
158 | continue; | ||
159 | if (!member->member_name->is_patterned) { | ||
160 | if (tomoyo_pathcmp(pathname, member->member_name)) | ||
161 | continue; | ||
162 | } else if (may_use_pattern) { | ||
163 | if (!tomoyo_path_matches_pattern(pathname, | ||
164 | member->member_name)) | ||
165 | continue; | ||
166 | } else | ||
167 | continue; | ||
168 | matched = true; | ||
169 | break; | ||
170 | } | ||
171 | return matched; | ||
172 | } | ||