aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2010-05-10 04:30:26 -0400
committerJames Morris <jmorris@namei.org>2010-05-16 19:25:57 -0400
commit7762fbfffdbce8191f5236d5053b290035d3d749 (patch)
tree08b6de0c09c5571d3bdb61c429e1ec68e748f796
parentba0c1709f4946a5ca1a678f4318ed72c0d409b3c (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>
-rw-r--r--security/tomoyo/Makefile2
-rw-r--r--security/tomoyo/common.c100
-rw-r--r--security/tomoyo/common.h94
-rw-r--r--security/tomoyo/file.c71
-rw-r--r--security/tomoyo/gc.c48
-rw-r--r--security/tomoyo/path_group.c172
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 */
86bool 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 */
109static 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 */
226bool 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
208struct 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. */
215struct 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. */
223struct 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 {
307struct tomoyo_path2_acl { 328struct 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. */
537bool 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. */
518bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); 540bool 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. */
528bool tomoyo_is_domain_def(const unsigned char *buffer); 550bool tomoyo_is_domain_def(const unsigned char *buffer);
551bool tomoyo_parse_name_union(const char *filename,
552 struct tomoyo_name_union *ptr);
553/* Check whether the given filename matches the given path_group. */
554bool 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. */
530bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 558bool 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);
540bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head); 568bool 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. */
542bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head); 570bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head);
571/* Read "path_group" entry in exception policy. */
572bool 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. */
544bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head); 574bool 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. */
546bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); 576bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head);
577/* Tokenize a line. */
578bool 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? */
548bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); 580bool 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);
580int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); 612int 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. */
582int tomoyo_write_pattern_policy(char *data, const bool is_delete); 614int tomoyo_write_pattern_policy(char *data, const bool is_delete);
615/* Create "path_group" entry in exception policy. */
616int 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. */
584struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); 618struct 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. */
586struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 620struct 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". */
625struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name);
626
589/* Check mode for specified functionality. */ 627/* Check mode for specified functionality. */
590unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, 628unsigned 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,
642int tomoyo_check_rewrite_permission(struct file *filp); 680int tomoyo_check_rewrite_permission(struct file *filp);
643int tomoyo_find_next_domain(struct linux_binprm *bprm); 681int tomoyo_find_next_domain(struct linux_binprm *bprm);
644 682
683/* Drop refcount on tomoyo_name_union. */
684void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
685
645/* Run garbage collector. */ 686/* Run garbage collector. */
646void tomoyo_run_gc(void); 687void 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". */
656extern struct list_head tomoyo_domain_list; 697extern struct list_head tomoyo_domain_list;
657 698
699extern struct list_head tomoyo_path_group_list;
658extern struct list_head tomoyo_domain_initializer_list; 700extern struct list_head tomoyo_domain_initializer_list;
659extern struct list_head tomoyo_domain_keeper_list; 701extern struct list_head tomoyo_domain_keeper_list;
660extern struct list_head tomoyo_alias_list; 702extern 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
770static inline void tomoyo_put_path_group(struct tomoyo_path_group *group)
771{
772 if (group)
773 atomic_dec(&group->users);
774}
775
728static inline struct tomoyo_domain_info *tomoyo_domain(void) 776static 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
787static 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
793static 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
800static 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
807static 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
739static inline bool tomoyo_is_same_domain_initializer_entry 815static 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
48void 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
58bool 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
66static 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
14enum tomoyo_gc_id { 14enum 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
154static void tomoyo_del_path_group_member(struct tomoyo_path_group_member
155 *member)
156{
157 tomoyo_put_name(member->member_name);
158}
159
160static void tomoyo_del_path_group(struct tomoyo_path_group *group)
161{
162 tomoyo_put_name(group->group_name);
163}
164
152static void tomoyo_collect_entry(void) 165static 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". */
10LIST_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 */
19struct 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 */
66int 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 */
114bool 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 */
150bool 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}