aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2011-06-26 10:17:10 -0400
committerJames Morris <jmorris@namei.org>2011-06-28 19:31:20 -0400
commita238cf5b89ed5285be8de56335665d023972f7d5 (patch)
treecd2594f5c80345b5f880a3ccd445d15fb6b7d6cd /security
parent0df7e8b8f1c25c10820bdc679555f2fbfb897ca0 (diff)
TOMOYO: Use struct for passing ACL line.
Use structure for passing ACL line, in preparation for supporting policy namespace and conditional parameters. 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/common.c77
-rw-r--r--security/tomoyo/common.h32
-rw-r--r--security/tomoyo/domain.c146
-rw-r--r--security/tomoyo/file.c237
-rw-r--r--security/tomoyo/group.c33
-rw-r--r--security/tomoyo/memory.c20
-rw-r--r--security/tomoyo/mount.c53
-rw-r--r--security/tomoyo/util.c120
8 files changed, 347 insertions, 371 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 2e6792ded357..2cfadafd02f5 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -611,8 +611,11 @@ static int tomoyo_update_manager_entry(const char *manager,
611 const bool is_delete) 611 const bool is_delete)
612{ 612{
613 struct tomoyo_manager e = { }; 613 struct tomoyo_manager e = { };
614 int error; 614 struct tomoyo_acl_param param = {
615 615 .is_delete = is_delete,
616 .list = &tomoyo_policy_list[TOMOYO_ID_MANAGER],
617 };
618 int error = is_delete ? -ENOENT : -ENOMEM;
616 if (tomoyo_domain_def(manager)) { 619 if (tomoyo_domain_def(manager)) {
617 if (!tomoyo_correct_domain(manager)) 620 if (!tomoyo_correct_domain(manager))
618 return -EINVAL; 621 return -EINVAL;
@@ -622,12 +625,11 @@ static int tomoyo_update_manager_entry(const char *manager,
622 return -EINVAL; 625 return -EINVAL;
623 } 626 }
624 e.manager = tomoyo_get_name(manager); 627 e.manager = tomoyo_get_name(manager);
625 if (!e.manager) 628 if (e.manager) {
626 return -ENOMEM; 629 error = tomoyo_update_policy(&e.head, sizeof(e), &param,
627 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 630 tomoyo_same_manager);
628 &tomoyo_policy_list[TOMOYO_ID_MANAGER], 631 tomoyo_put_name(e.manager);
629 tomoyo_same_manager); 632 }
630 tomoyo_put_name(e.manager);
631 return error; 633 return error;
632} 634}
633 635
@@ -821,18 +823,36 @@ static int tomoyo_delete_domain(char *domainname)
821/** 823/**
822 * tomoyo_write_domain2 - Write domain policy. 824 * tomoyo_write_domain2 - Write domain policy.
823 * 825 *
824 * @head: Pointer to "struct tomoyo_io_buffer". 826 * @list: Pointer to "struct list_head".
827 * @data: Policy to be interpreted.
828 * @is_delete: True if it is a delete request.
825 * 829 *
826 * Returns 0 on success, negative value otherwise. 830 * Returns 0 on success, negative value otherwise.
827 * 831 *
828 * Caller holds tomoyo_read_lock(). 832 * Caller holds tomoyo_read_lock().
829 */ 833 */
830static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain, 834static int tomoyo_write_domain2(struct list_head *list, char *data,
831 const bool is_delete) 835 const bool is_delete)
832{ 836{
833 if (tomoyo_str_starts(&data, "allow_mount ")) 837 struct tomoyo_acl_param param = {
834 return tomoyo_write_mount(data, domain, is_delete); 838 .list = list,
835 return tomoyo_write_file(data, domain, is_delete); 839 .data = data,
840 .is_delete = is_delete,
841 };
842 static const struct {
843 const char *keyword;
844 int (*write) (struct tomoyo_acl_param *);
845 } tomoyo_callback[1] = {
846 { "file ", tomoyo_write_file },
847 };
848 u8 i;
849 for (i = 0; i < 1; i++) {
850 if (!tomoyo_str_starts(&param.data,
851 tomoyo_callback[i].keyword))
852 continue;
853 return tomoyo_callback[i].write(&param);
854 }
855 return -EINVAL;
836} 856}
837 857
838/** 858/**
@@ -889,7 +909,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
889 domain->transition_failed = !is_delete; 909 domain->transition_failed = !is_delete;
890 return 0; 910 return 0;
891 } 911 }
892 return tomoyo_write_domain2(data, domain, is_delete); 912 return tomoyo_write_domain2(&domain->acl_info_list, data, is_delete);
893} 913}
894 914
895/** 915/**
@@ -1213,26 +1233,19 @@ static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = {
1213 */ 1233 */
1214static int tomoyo_write_exception(struct tomoyo_io_buffer *head) 1234static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
1215{ 1235{
1216 char *data = head->write_buf; 1236 struct tomoyo_acl_param param = {
1217 bool is_delete = tomoyo_str_starts(&data, "delete "); 1237 .data = head->write_buf,
1218 u8 i;
1219 static const struct {
1220 const char *keyword;
1221 int (*write) (char *, const bool);
1222 } tomoyo_callback[1] = {
1223 { "aggregator ", tomoyo_write_aggregator },
1224 }; 1238 };
1225 1239 u8 i;
1240 param.is_delete = tomoyo_str_starts(&param.data, "delete ");
1241 if (tomoyo_str_starts(&param.data, "aggregator "))
1242 return tomoyo_write_aggregator(&param);
1226 for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) 1243 for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++)
1227 if (tomoyo_str_starts(&data, tomoyo_transition_type[i])) 1244 if (tomoyo_str_starts(&param.data, tomoyo_transition_type[i]))
1228 return tomoyo_write_transition_control(data, is_delete, 1245 return tomoyo_write_transition_control(&param, i);
1229 i);
1230 for (i = 0; i < 1; i++)
1231 if (tomoyo_str_starts(&data, tomoyo_callback[i].keyword))
1232 return tomoyo_callback[i].write(data, is_delete);
1233 for (i = 0; i < TOMOYO_MAX_GROUP; i++) 1246 for (i = 0; i < TOMOYO_MAX_GROUP; i++)
1234 if (tomoyo_str_starts(&data, tomoyo_group_name[i])) 1247 if (tomoyo_str_starts(&param.data, tomoyo_group_name[i]))
1235 return tomoyo_write_group(data, is_delete, i); 1248 return tomoyo_write_group(&param, i);
1236 return -EINVAL; 1249 return -EINVAL;
1237} 1250}
1238 1251
@@ -1490,7 +1503,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
1490 vsnprintf(buffer, len - 1, fmt, args); 1503 vsnprintf(buffer, len - 1, fmt, args);
1491 va_end(args); 1504 va_end(args);
1492 tomoyo_normalize_line(buffer); 1505 tomoyo_normalize_line(buffer);
1493 tomoyo_write_domain2(buffer, r->domain, false); 1506 tomoyo_write_domain2(&r->domain->acl_info_list, buffer, false);
1494 kfree(buffer); 1507 kfree(buffer);
1495 /* fall through */ 1508 /* fall through */
1496 case TOMOYO_CONFIG_PERMISSIVE: 1509 case TOMOYO_CONFIG_PERMISSIVE:
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 7aa55eef67bd..6f9711ff73c1 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -397,6 +397,13 @@ struct tomoyo_mount_acl {
397 struct tomoyo_number_union flags; 397 struct tomoyo_number_union flags;
398}; 398};
399 399
400/* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */
401struct tomoyo_acl_param {
402 char *data;
403 struct list_head *list;
404 bool is_delete;
405};
406
400#define TOMOYO_MAX_IO_READ_QUEUE 32 407#define TOMOYO_MAX_IO_READ_QUEUE 32
401 408
402/* 409/*
@@ -521,7 +528,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname);
521bool tomoyo_correct_path(const char *filename); 528bool tomoyo_correct_path(const char *filename);
522bool tomoyo_correct_word(const char *string); 529bool tomoyo_correct_word(const char *string);
523bool tomoyo_domain_def(const unsigned char *buffer); 530bool tomoyo_domain_def(const unsigned char *buffer);
524bool tomoyo_parse_name_union(const char *filename, 531bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
525 struct tomoyo_name_union *ptr); 532 struct tomoyo_name_union *ptr);
526const struct tomoyo_path_info * 533const struct tomoyo_path_info *
527tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, 534tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
@@ -531,7 +538,8 @@ bool tomoyo_number_matches_group(const unsigned long min,
531 const struct tomoyo_group *group); 538 const struct tomoyo_group *group);
532bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 539bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
533 const struct tomoyo_path_info *pattern); 540 const struct tomoyo_path_info *pattern);
534bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num); 541bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
542 struct tomoyo_number_union *ptr);
535bool tomoyo_tokenize(char *buffer, char *w[], size_t size); 543bool tomoyo_tokenize(char *buffer, char *w[], size_t size);
536bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); 544bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain);
537int tomoyo_init_request_info(struct tomoyo_request_info *r, 545int tomoyo_init_request_info(struct tomoyo_request_info *r,
@@ -540,21 +548,19 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r,
540int tomoyo_mount_permission(char *dev_name, struct path *path, 548int tomoyo_mount_permission(char *dev_name, struct path *path,
541 const char *type, unsigned long flags, 549 const char *type, unsigned long flags,
542 void *data_page); 550 void *data_page);
543int tomoyo_write_aggregator(char *data, const bool is_delete); 551int tomoyo_write_aggregator(struct tomoyo_acl_param *param);
544int tomoyo_write_transition_control(char *data, const bool is_delete, 552int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
545 const u8 type); 553 const u8 type);
546int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, 554int tomoyo_write_file(struct tomoyo_acl_param *param);
547 const bool is_delete); 555int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type);
548int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain,
549 const bool is_delete);
550int tomoyo_write_group(char *data, const bool is_delete, const u8 type);
551int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) 556int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
552 __attribute__ ((format(printf, 2, 3))); 557 __attribute__ ((format(printf, 2, 3)));
553struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); 558struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
554struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, 559struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
555 const u8 profile); 560 const u8 profile);
556struct tomoyo_profile *tomoyo_profile(const u8 profile); 561struct tomoyo_profile *tomoyo_profile(const u8 profile);
557struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type); 562struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
563 const u8 idx);
558unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, 564unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
559 const u8 index); 565 const u8 index);
560void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); 566void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
@@ -587,7 +593,7 @@ void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
587void tomoyo_run_gc(void); 593void tomoyo_run_gc(void);
588void tomoyo_memory_free(void *ptr); 594void tomoyo_memory_free(void *ptr);
589int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 595int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
590 bool is_delete, struct tomoyo_domain_info *domain, 596 struct tomoyo_acl_param *param,
591 bool (*check_duplicate) (const struct tomoyo_acl_info 597 bool (*check_duplicate) (const struct tomoyo_acl_info
592 *, 598 *,
593 const struct tomoyo_acl_info 599 const struct tomoyo_acl_info
@@ -596,7 +602,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
596 struct tomoyo_acl_info *, 602 struct tomoyo_acl_info *,
597 const bool)); 603 const bool));
598int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, 604int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
599 bool is_delete, struct list_head *list, 605 struct tomoyo_acl_param *param,
600 bool (*check_duplicate) (const struct tomoyo_acl_head 606 bool (*check_duplicate) (const struct tomoyo_acl_head
601 *, 607 *,
602 const struct tomoyo_acl_head 608 const struct tomoyo_acl_head
@@ -604,6 +610,8 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
604void tomoyo_check_acl(struct tomoyo_request_info *r, 610void tomoyo_check_acl(struct tomoyo_request_info *r,
605 bool (*check_entry) (struct tomoyo_request_info *, 611 bool (*check_entry) (struct tomoyo_request_info *,
606 const struct tomoyo_acl_info *)); 612 const struct tomoyo_acl_info *));
613char *tomoyo_read_token(struct tomoyo_acl_param *param);
614bool tomoyo_permstr(const char *string, const char *keyword);
607 615
608/********** External variable definitions. **********/ 616/********** External variable definitions. **********/
609 617
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 43977083254b..d818717954f8 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -20,8 +20,7 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
20 * 20 *
21 * @new_entry: Pointer to "struct tomoyo_acl_info". 21 * @new_entry: Pointer to "struct tomoyo_acl_info".
22 * @size: Size of @new_entry in bytes. 22 * @size: Size of @new_entry in bytes.
23 * @is_delete: True if it is a delete request. 23 * @param: Pointer to "struct tomoyo_acl_param".
24 * @list: Pointer to "struct list_head".
25 * @check_duplicate: Callback function to find duplicated entry. 24 * @check_duplicate: Callback function to find duplicated entry.
26 * 25 *
27 * Returns 0 on success, negative value otherwise. 26 * Returns 0 on success, negative value otherwise.
@@ -29,25 +28,26 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
29 * Caller holds tomoyo_read_lock(). 28 * Caller holds tomoyo_read_lock().
30 */ 29 */
31int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, 30int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
32 bool is_delete, struct list_head *list, 31 struct tomoyo_acl_param *param,
33 bool (*check_duplicate) (const struct tomoyo_acl_head 32 bool (*check_duplicate) (const struct tomoyo_acl_head
34 *, 33 *,
35 const struct tomoyo_acl_head 34 const struct tomoyo_acl_head
36 *)) 35 *))
37{ 36{
38 int error = is_delete ? -ENOENT : -ENOMEM; 37 int error = param->is_delete ? -ENOENT : -ENOMEM;
39 struct tomoyo_acl_head *entry; 38 struct tomoyo_acl_head *entry;
39 struct list_head *list = param->list;
40 40
41 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 41 if (mutex_lock_interruptible(&tomoyo_policy_lock))
42 return -ENOMEM; 42 return -ENOMEM;
43 list_for_each_entry_rcu(entry, list, list) { 43 list_for_each_entry_rcu(entry, list, list) {
44 if (!check_duplicate(entry, new_entry)) 44 if (!check_duplicate(entry, new_entry))
45 continue; 45 continue;
46 entry->is_deleted = is_delete; 46 entry->is_deleted = param->is_delete;
47 error = 0; 47 error = 0;
48 break; 48 break;
49 } 49 }
50 if (error && !is_delete) { 50 if (error && !param->is_delete) {
51 entry = tomoyo_commit_ok(new_entry, size); 51 entry = tomoyo_commit_ok(new_entry, size);
52 if (entry) { 52 if (entry) {
53 list_add_tail_rcu(&entry->list, list); 53 list_add_tail_rcu(&entry->list, list);
@@ -77,8 +77,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
77 * 77 *
78 * @new_entry: Pointer to "struct tomoyo_acl_info". 78 * @new_entry: Pointer to "struct tomoyo_acl_info".
79 * @size: Size of @new_entry in bytes. 79 * @size: Size of @new_entry in bytes.
80 * @is_delete: True if it is a delete request. 80 * @param: Pointer to "struct tomoyo_acl_param".
81 * @domain: Pointer to "struct tomoyo_domain_info".
82 * @check_duplicate: Callback function to find duplicated entry. 81 * @check_duplicate: Callback function to find duplicated entry.
83 * @merge_duplicate: Callback function to merge duplicated entry. 82 * @merge_duplicate: Callback function to merge duplicated entry.
84 * 83 *
@@ -87,7 +86,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
87 * Caller holds tomoyo_read_lock(). 86 * Caller holds tomoyo_read_lock().
88 */ 87 */
89int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 88int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
90 bool is_delete, struct tomoyo_domain_info *domain, 89 struct tomoyo_acl_param *param,
91 bool (*check_duplicate) (const struct tomoyo_acl_info 90 bool (*check_duplicate) (const struct tomoyo_acl_info
92 *, 91 *,
93 const struct tomoyo_acl_info 92 const struct tomoyo_acl_info
@@ -96,12 +95,14 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
96 struct tomoyo_acl_info *, 95 struct tomoyo_acl_info *,
97 const bool)) 96 const bool))
98{ 97{
98 const bool is_delete = param->is_delete;
99 int error = is_delete ? -ENOENT : -ENOMEM; 99 int error = is_delete ? -ENOENT : -ENOMEM;
100 struct tomoyo_acl_info *entry; 100 struct tomoyo_acl_info *entry;
101 struct list_head * const list = param->list;
101 102
102 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 103 if (mutex_lock_interruptible(&tomoyo_policy_lock))
103 return error; 104 return error;
104 list_for_each_entry_rcu(entry, &domain->acl_info_list, list) { 105 list_for_each_entry_rcu(entry, list, list) {
105 if (!tomoyo_same_acl_head(entry, new_entry) || 106 if (!tomoyo_same_acl_head(entry, new_entry) ||
106 !check_duplicate(entry, new_entry)) 107 !check_duplicate(entry, new_entry))
107 continue; 108 continue;
@@ -116,7 +117,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
116 if (error && !is_delete) { 117 if (error && !is_delete) {
117 entry = tomoyo_commit_ok(new_entry, size); 118 entry = tomoyo_commit_ok(new_entry, size);
118 if (entry) { 119 if (entry) {
119 list_add_tail_rcu(&entry->list, &domain->acl_info_list); 120 list_add_tail_rcu(&entry->list, list);
120 error = 0; 121 error = 0;
121 } 122 }
122 } 123 }
@@ -163,6 +164,14 @@ static const char *tomoyo_last_word(const char *name)
163 return name; 164 return name;
164} 165}
165 166
167/**
168 * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry.
169 *
170 * @a: Pointer to "struct tomoyo_acl_head".
171 * @b: Pointer to "struct tomoyo_acl_head".
172 *
173 * Returns true if @a == @b, false otherwise.
174 */
166static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, 175static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
167 const struct tomoyo_acl_head *b) 176 const struct tomoyo_acl_head *b)
168{ 177{
@@ -178,22 +187,28 @@ static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
178} 187}
179 188
180/** 189/**
181 * tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list. 190 * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
182 * 191 *
183 * @domainname: The name of domain. Maybe NULL. 192 * @param: Pointer to "struct tomoyo_acl_param".
184 * @program: The name of program. Maybe NULL. 193 * @type: Type of this entry.
185 * @type: Type of transition.
186 * @is_delete: True if it is a delete request.
187 * 194 *
188 * Returns 0 on success, negative value otherwise. 195 * Returns 0 on success, negative value otherwise.
189 */ 196 */
190static int tomoyo_update_transition_control_entry(const char *domainname, 197int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
191 const char *program, 198 const u8 type)
192 const u8 type,
193 const bool is_delete)
194{ 199{
195 struct tomoyo_transition_control e = { .type = type }; 200 struct tomoyo_transition_control e = { .type = type };
196 int error = is_delete ? -ENOENT : -ENOMEM; 201 int error = param->is_delete ? -ENOENT : -ENOMEM;
202 char *program = param->data;
203 char *domainname = strstr(program, " from ");
204 if (domainname) {
205 *domainname = '\0';
206 domainname += 6;
207 } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
208 type == TOMOYO_TRANSITION_CONTROL_KEEP) {
209 domainname = program;
210 program = NULL;
211 }
197 if (program) { 212 if (program) {
198 if (!tomoyo_correct_path(program)) 213 if (!tomoyo_correct_path(program))
199 return -EINVAL; 214 return -EINVAL;
@@ -211,42 +226,16 @@ static int tomoyo_update_transition_control_entry(const char *domainname,
211 if (!e.domainname) 226 if (!e.domainname)
212 goto out; 227 goto out;
213 } 228 }
214 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 229 param->list = &tomoyo_policy_list[TOMOYO_ID_TRANSITION_CONTROL];
215 &tomoyo_policy_list 230 error = tomoyo_update_policy(&e.head, sizeof(e), param,
216 [TOMOYO_ID_TRANSITION_CONTROL],
217 tomoyo_same_transition_control); 231 tomoyo_same_transition_control);
218 out: 232out:
219 tomoyo_put_name(e.domainname); 233 tomoyo_put_name(e.domainname);
220 tomoyo_put_name(e.program); 234 tomoyo_put_name(e.program);
221 return error; 235 return error;
222} 236}
223 237
224/** 238/**
225 * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
226 *
227 * @data: String to parse.
228 * @is_delete: True if it is a delete request.
229 * @type: Type of this entry.
230 *
231 * Returns 0 on success, negative value otherwise.
232 */
233int tomoyo_write_transition_control(char *data, const bool is_delete,
234 const u8 type)
235{
236 char *domainname = strstr(data, " from ");
237 if (domainname) {
238 *domainname = '\0';
239 domainname += 6;
240 } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
241 type == TOMOYO_TRANSITION_CONTROL_KEEP) {
242 domainname = data;
243 data = NULL;
244 }
245 return tomoyo_update_transition_control_entry(domainname, data, type,
246 is_delete);
247}
248
249/**
250 * tomoyo_transition_type - Get domain transition type. 239 * tomoyo_transition_type - Get domain transition type.
251 * 240 *
252 * @domainname: The name of domain. 241 * @domainname: The name of domain.
@@ -303,34 +292,41 @@ static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
303 return type; 292 return type;
304} 293}
305 294
295/**
296 * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry.
297 *
298 * @a: Pointer to "struct tomoyo_acl_head".
299 * @b: Pointer to "struct tomoyo_acl_head".
300 *
301 * Returns true if @a == @b, false otherwise.
302 */
306static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, 303static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
307 const struct tomoyo_acl_head *b) 304 const struct tomoyo_acl_head *b)
308{ 305{
309 const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), head); 306 const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1),
310 const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head); 307 head);
308 const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2),
309 head);
311 return p1->original_name == p2->original_name && 310 return p1->original_name == p2->original_name &&
312 p1->aggregated_name == p2->aggregated_name; 311 p1->aggregated_name == p2->aggregated_name;
313} 312}
314 313
315/** 314/**
316 * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list. 315 * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
317 * 316 *
318 * @original_name: The original program's name. 317 * @param: Pointer to "struct tomoyo_acl_param".
319 * @aggregated_name: The program name to use.
320 * @is_delete: True if it is a delete request.
321 * 318 *
322 * Returns 0 on success, negative value otherwise. 319 * Returns 0 on success, negative value otherwise.
323 * 320 *
324 * Caller holds tomoyo_read_lock(). 321 * Caller holds tomoyo_read_lock().
325 */ 322 */
326static int tomoyo_update_aggregator_entry(const char *original_name, 323int tomoyo_write_aggregator(struct tomoyo_acl_param *param)
327 const char *aggregated_name,
328 const bool is_delete)
329{ 324{
330 struct tomoyo_aggregator e = { }; 325 struct tomoyo_aggregator e = { };
331 int error = is_delete ? -ENOENT : -ENOMEM; 326 int error = param->is_delete ? -ENOENT : -ENOMEM;
332 327 const char *original_name = tomoyo_read_token(param);
333 if (!tomoyo_correct_path(original_name) || 328 const char *aggregated_name = tomoyo_read_token(param);
329 if (!tomoyo_correct_word(original_name) ||
334 !tomoyo_correct_path(aggregated_name)) 330 !tomoyo_correct_path(aggregated_name))
335 return -EINVAL; 331 return -EINVAL;
336 e.original_name = tomoyo_get_name(original_name); 332 e.original_name = tomoyo_get_name(original_name);
@@ -338,36 +334,16 @@ static int tomoyo_update_aggregator_entry(const char *original_name,
338 if (!e.original_name || !e.aggregated_name || 334 if (!e.original_name || !e.aggregated_name ||
339 e.aggregated_name->is_patterned) /* No patterns allowed. */ 335 e.aggregated_name->is_patterned) /* No patterns allowed. */
340 goto out; 336 goto out;
341 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 337 param->list = &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR];
342 &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR], 338 error = tomoyo_update_policy(&e.head, sizeof(e), param,
343 tomoyo_same_aggregator); 339 tomoyo_same_aggregator);
344 out: 340out:
345 tomoyo_put_name(e.original_name); 341 tomoyo_put_name(e.original_name);
346 tomoyo_put_name(e.aggregated_name); 342 tomoyo_put_name(e.aggregated_name);
347 return error; 343 return error;
348} 344}
349 345
350/** 346/**
351 * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
352 *
353 * @data: String to parse.
354 * @is_delete: True if it is a delete request.
355 *
356 * Returns 0 on success, negative value otherwise.
357 *
358 * Caller holds tomoyo_read_lock().
359 */
360int tomoyo_write_aggregator(char *data, const bool is_delete)
361{
362 char *cp = strchr(data, ' ');
363
364 if (!cp)
365 return -EINVAL;
366 *cp++ = '\0';
367 return tomoyo_update_aggregator_entry(data, cp, is_delete);
368}
369
370/**
371 * tomoyo_assign_domain - Create a domain. 347 * tomoyo_assign_domain - Create a domain.
372 * 348 *
373 * @domainname: The name of domain. 349 * @domainname: The name of domain.
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 4259e0a136d8..e60745f9f31e 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -428,29 +428,27 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
428/** 428/**
429 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. 429 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
430 * 430 *
431 * @type: Type of operation. 431 * @perm: Permission.
432 * @filename: Filename. 432 * @param: Pointer to "struct tomoyo_acl_param".
433 * @domain: Pointer to "struct tomoyo_domain_info".
434 * @is_delete: True if it is a delete request.
435 * 433 *
436 * Returns 0 on success, negative value otherwise. 434 * Returns 0 on success, negative value otherwise.
437 * 435 *
438 * Caller holds tomoyo_read_lock(). 436 * Caller holds tomoyo_read_lock().
439 */ 437 */
440static int tomoyo_update_path_acl(const u8 type, const char *filename, 438static int tomoyo_update_path_acl(const u16 perm,
441 struct tomoyo_domain_info * const domain, 439 struct tomoyo_acl_param *param)
442 const bool is_delete)
443{ 440{
444 struct tomoyo_path_acl e = { 441 struct tomoyo_path_acl e = {
445 .head.type = TOMOYO_TYPE_PATH_ACL, 442 .head.type = TOMOYO_TYPE_PATH_ACL,
446 .perm = 1 << type 443 .perm = perm
447 }; 444 };
448 int error; 445 int error;
449 if (!tomoyo_parse_name_union(filename, &e.name)) 446 if (!tomoyo_parse_name_union(param, &e.name))
450 return -EINVAL; 447 error = -EINVAL;
451 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 448 else
452 tomoyo_same_path_acl, 449 error = tomoyo_update_domain(&e.head, sizeof(e), param,
453 tomoyo_merge_path_acl); 450 tomoyo_same_path_acl,
451 tomoyo_merge_path_acl);
454 tomoyo_put_name_union(&e.name); 452 tomoyo_put_name_union(&e.name);
455 return error; 453 return error;
456} 454}
@@ -503,37 +501,30 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
503/** 501/**
504 * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. 502 * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
505 * 503 *
506 * @type: Type of operation. 504 * @perm: Permission.
507 * @filename: Filename. 505 * @param: Pointer to "struct tomoyo_acl_param".
508 * @mode: Create mode.
509 * @major: Device major number.
510 * @minor: Device minor number.
511 * @domain: Pointer to "struct tomoyo_domain_info".
512 * @is_delete: True if it is a delete request.
513 * 506 *
514 * Returns 0 on success, negative value otherwise. 507 * Returns 0 on success, negative value otherwise.
515 * 508 *
516 * Caller holds tomoyo_read_lock(). 509 * Caller holds tomoyo_read_lock().
517 */ 510 */
518static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, 511static int tomoyo_update_mkdev_acl(const u8 perm,
519 char *mode, char *major, char *minor, 512 struct tomoyo_acl_param *param)
520 struct tomoyo_domain_info * const domain,
521 const bool is_delete)
522{ 513{
523 struct tomoyo_mkdev_acl e = { 514 struct tomoyo_mkdev_acl e = {
524 .head.type = TOMOYO_TYPE_MKDEV_ACL, 515 .head.type = TOMOYO_TYPE_MKDEV_ACL,
525 .perm = 1 << type 516 .perm = perm
526 }; 517 };
527 int error = is_delete ? -ENOENT : -ENOMEM; 518 int error;
528 if (!tomoyo_parse_name_union(filename, &e.name) || 519 if (!tomoyo_parse_name_union(param, &e.name) ||
529 !tomoyo_parse_number_union(mode, &e.mode) || 520 !tomoyo_parse_number_union(param, &e.mode) ||
530 !tomoyo_parse_number_union(major, &e.major) || 521 !tomoyo_parse_number_union(param, &e.major) ||
531 !tomoyo_parse_number_union(minor, &e.minor)) 522 !tomoyo_parse_number_union(param, &e.minor))
532 goto out; 523 error = -EINVAL;
533 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 524 else
534 tomoyo_same_mkdev_acl, 525 error = tomoyo_update_domain(&e.head, sizeof(e), param,
535 tomoyo_merge_mkdev_acl); 526 tomoyo_same_mkdev_acl,
536 out: 527 tomoyo_merge_mkdev_acl);
537 tomoyo_put_name_union(&e.name); 528 tomoyo_put_name_union(&e.name);
538 tomoyo_put_number_union(&e.mode); 529 tomoyo_put_number_union(&e.mode);
539 tomoyo_put_number_union(&e.major); 530 tomoyo_put_number_union(&e.major);
@@ -586,33 +577,28 @@ static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
586/** 577/**
587 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. 578 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
588 * 579 *
589 * @type: Type of operation. 580 * @perm: Permission.
590 * @filename1: First filename. 581 * @param: Pointer to "struct tomoyo_acl_param".
591 * @filename2: Second filename.
592 * @domain: Pointer to "struct tomoyo_domain_info".
593 * @is_delete: True if it is a delete request.
594 * 582 *
595 * Returns 0 on success, negative value otherwise. 583 * Returns 0 on success, negative value otherwise.
596 * 584 *
597 * Caller holds tomoyo_read_lock(). 585 * Caller holds tomoyo_read_lock().
598 */ 586 */
599static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 587static int tomoyo_update_path2_acl(const u8 perm,
600 const char *filename2, 588 struct tomoyo_acl_param *param)
601 struct tomoyo_domain_info * const domain,
602 const bool is_delete)
603{ 589{
604 struct tomoyo_path2_acl e = { 590 struct tomoyo_path2_acl e = {
605 .head.type = TOMOYO_TYPE_PATH2_ACL, 591 .head.type = TOMOYO_TYPE_PATH2_ACL,
606 .perm = 1 << type 592 .perm = perm
607 }; 593 };
608 int error = is_delete ? -ENOENT : -ENOMEM; 594 int error;
609 if (!tomoyo_parse_name_union(filename1, &e.name1) || 595 if (!tomoyo_parse_name_union(param, &e.name1) ||
610 !tomoyo_parse_name_union(filename2, &e.name2)) 596 !tomoyo_parse_name_union(param, &e.name2))
611 goto out; 597 error = -EINVAL;
612 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 598 else
613 tomoyo_same_path2_acl, 599 error = tomoyo_update_domain(&e.head, sizeof(e), param,
614 tomoyo_merge_path2_acl); 600 tomoyo_same_path2_acl,
615 out: 601 tomoyo_merge_path2_acl);
616 tomoyo_put_name_union(&e.name1); 602 tomoyo_put_name_union(&e.name1);
617 tomoyo_put_name_union(&e.name2); 603 tomoyo_put_name_union(&e.name2);
618 return error; 604 return error;
@@ -701,32 +687,26 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
701/** 687/**
702 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. 688 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
703 * 689 *
704 * @type: Type of operation. 690 * @perm: Permission.
705 * @filename: Filename. 691 * @param: Pointer to "struct tomoyo_acl_param".
706 * @number: Number.
707 * @domain: Pointer to "struct tomoyo_domain_info".
708 * @is_delete: True if it is a delete request.
709 * 692 *
710 * Returns 0 on success, negative value otherwise. 693 * Returns 0 on success, negative value otherwise.
711 */ 694 */
712static int tomoyo_update_path_number_acl(const u8 type, const char *filename, 695static int tomoyo_update_path_number_acl(const u8 perm,
713 char *number, 696 struct tomoyo_acl_param *param)
714 struct tomoyo_domain_info * const
715 domain, const bool is_delete)
716{ 697{
717 struct tomoyo_path_number_acl e = { 698 struct tomoyo_path_number_acl e = {
718 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, 699 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
719 .perm = 1 << type 700 .perm = perm
720 }; 701 };
721 int error = is_delete ? -ENOENT : -ENOMEM; 702 int error;
722 if (!tomoyo_parse_name_union(filename, &e.name)) 703 if (!tomoyo_parse_name_union(param, &e.name) ||
723 return -EINVAL; 704 !tomoyo_parse_number_union(param, &e.number))
724 if (!tomoyo_parse_number_union(number, &e.number)) 705 error = -EINVAL;
725 goto out; 706 else
726 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 707 error = tomoyo_update_domain(&e.head, sizeof(e), param,
727 tomoyo_same_path_number_acl, 708 tomoyo_same_path_number_acl,
728 tomoyo_merge_path_number_acl); 709 tomoyo_merge_path_number_acl);
729 out:
730 tomoyo_put_name_union(&e.name); 710 tomoyo_put_name_union(&e.name);
731 tomoyo_put_number_union(&e.number); 711 tomoyo_put_number_union(&e.number);
732 return error; 712 return error;
@@ -963,53 +943,88 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
963} 943}
964 944
965/** 945/**
946 * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
947 *
948 * @a: Pointer to "struct tomoyo_acl_info".
949 * @b: Pointer to "struct tomoyo_acl_info".
950 *
951 * Returns true if @a == @b, false otherwise.
952 */
953static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
954 const struct tomoyo_acl_info *b)
955{
956 const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
957 const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
958 return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
959 tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
960 tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
961 tomoyo_same_number_union(&p1->flags, &p2->flags);
962}
963
964/**
965 * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list.
966 *
967 * @param: Pointer to "struct tomoyo_acl_param".
968 *
969 * Returns 0 on success, negative value otherwise.
970 *
971 * Caller holds tomoyo_read_lock().
972 */
973static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
974{
975 struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
976 int error;
977 if (!tomoyo_parse_name_union(param, &e.dev_name) ||
978 !tomoyo_parse_name_union(param, &e.dir_name) ||
979 !tomoyo_parse_name_union(param, &e.fs_type) ||
980 !tomoyo_parse_number_union(param, &e.flags))
981 error = -EINVAL;
982 else
983 error = tomoyo_update_domain(&e.head, sizeof(e), param,
984 tomoyo_same_mount_acl, NULL);
985 tomoyo_put_name_union(&e.dev_name);
986 tomoyo_put_name_union(&e.dir_name);
987 tomoyo_put_name_union(&e.fs_type);
988 tomoyo_put_number_union(&e.flags);
989 return error;
990}
991
992/**
966 * tomoyo_write_file - Update file related list. 993 * tomoyo_write_file - Update file related list.
967 * 994 *
968 * @data: String to parse. 995 * @param: Pointer to "struct tomoyo_acl_param".
969 * @domain: Pointer to "struct tomoyo_domain_info".
970 * @is_delete: True if it is a delete request.
971 * 996 *
972 * Returns 0 on success, negative value otherwise. 997 * Returns 0 on success, negative value otherwise.
973 * 998 *
974 * Caller holds tomoyo_read_lock(). 999 * Caller holds tomoyo_read_lock().
975 */ 1000 */
976int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, 1001int tomoyo_write_file(struct tomoyo_acl_param *param)
977 const bool is_delete)
978{ 1002{
979 char *w[5]; 1003 u16 perm = 0;
980 u8 type; 1004 u8 type;
981 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) 1005 const char *operation = tomoyo_read_token(param);
982 return -EINVAL; 1006 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
983 if (strncmp(w[0], "allow_", 6)) 1007 if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
984 goto out; 1008 perm |= 1 << type;
985 w[0] += 6; 1009 if (perm)
986 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { 1010 return tomoyo_update_path_acl(perm, param);
987 if (strcmp(w[0], tomoyo_path_keyword[type])) 1011 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
988 continue; 1012 if (tomoyo_permstr(operation, tomoyo_path2_keyword[type]))
989 return tomoyo_update_path_acl(type, w[1], domain, is_delete); 1013 perm |= 1 << type;
990 } 1014 if (perm)
991 if (!w[2][0]) 1015 return tomoyo_update_path2_acl(perm, param);
992 goto out; 1016 for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
993 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { 1017 if (tomoyo_permstr(operation,
994 if (strcmp(w[0], tomoyo_path2_keyword[type])) 1018 tomoyo_path_number_keyword[type]))
995 continue; 1019 perm |= 1 << type;
996 return tomoyo_update_path2_acl(type, w[1], w[2], domain, 1020 if (perm)
997 is_delete); 1021 return tomoyo_update_path_number_acl(perm, param);
998 } 1022 for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
999 for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) { 1023 if (tomoyo_permstr(operation, tomoyo_mkdev_keyword[type]))
1000 if (strcmp(w[0], tomoyo_path_number_keyword[type])) 1024 perm |= 1 << type;
1001 continue; 1025 if (perm)
1002 return tomoyo_update_path_number_acl(type, w[1], w[2], domain, 1026 return tomoyo_update_mkdev_acl(perm, param);
1003 is_delete); 1027 if (tomoyo_permstr(operation, "mount"))
1004 } 1028 return tomoyo_update_mount_acl(param);
1005 if (!w[3][0] || !w[4][0])
1006 goto out;
1007 for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) {
1008 if (strcmp(w[0], tomoyo_mkdev_keyword[type]))
1009 continue;
1010 return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3],
1011 w[4], domain, is_delete);
1012 }
1013 out:
1014 return -EINVAL; 1029 return -EINVAL;
1015} 1030}
diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c
index e94352ce723f..2e5b7bc73264 100644
--- a/security/tomoyo/group.c
+++ b/security/tomoyo/group.c
@@ -28,48 +28,41 @@ static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
28/** 28/**
29 * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list. 29 * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
30 * 30 *
31 * @data: String to parse. 31 * @param: Pointer to "struct tomoyo_acl_param".
32 * @is_delete: True if it is a delete request.
33 * @type: Type of this group. 32 * @type: Type of this group.
34 * 33 *
35 * Returns 0 on success, negative value otherwise. 34 * Returns 0 on success, negative value otherwise.
36 */ 35 */
37int tomoyo_write_group(char *data, const bool is_delete, const u8 type) 36int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type)
38{ 37{
39 struct tomoyo_group *group; 38 struct tomoyo_group *group = tomoyo_get_group(param, type);
40 struct list_head *member;
41 char *w[2];
42 int error = -EINVAL; 39 int error = -EINVAL;
43 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
44 return -EINVAL;
45 group = tomoyo_get_group(w[0], type);
46 if (!group) 40 if (!group)
47 return -ENOMEM; 41 return -ENOMEM;
48 member = &group->member_list; 42 param->list = &group->member_list;
49 if (type == TOMOYO_PATH_GROUP) { 43 if (type == TOMOYO_PATH_GROUP) {
50 struct tomoyo_path_group e = { }; 44 struct tomoyo_path_group e = { };
51 e.member_name = tomoyo_get_name(w[1]); 45 e.member_name = tomoyo_get_name(tomoyo_read_token(param));
52 if (!e.member_name) { 46 if (!e.member_name) {
53 error = -ENOMEM; 47 error = -ENOMEM;
54 goto out; 48 goto out;
55 } 49 }
56 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 50 error = tomoyo_update_policy(&e.head, sizeof(e), param,
57 member, tomoyo_same_path_group); 51 tomoyo_same_path_group);
58 tomoyo_put_name(e.member_name); 52 tomoyo_put_name(e.member_name);
59 } else if (type == TOMOYO_NUMBER_GROUP) { 53 } else if (type == TOMOYO_NUMBER_GROUP) {
60 struct tomoyo_number_group e = { }; 54 struct tomoyo_number_group e = { };
61 if (w[1][0] == '@' 55 if (param->data[0] == '@' ||
62 || !tomoyo_parse_number_union(w[1], &e.number) 56 !tomoyo_parse_number_union(param, &e.number))
63 || e.number.values[0] > e.number.values[1])
64 goto out; 57 goto out;
65 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 58 error = tomoyo_update_policy(&e.head, sizeof(e), param,
66 member, tomoyo_same_number_group); 59 tomoyo_same_number_group);
67 /* 60 /*
68 * tomoyo_put_number_union() is not needed because 61 * tomoyo_put_number_union() is not needed because
69 * w[1][0] != '@'. 62 * param->data[0] != '@'.
70 */ 63 */
71 } 64 }
72 out: 65out:
73 tomoyo_put_group(group); 66 tomoyo_put_group(group);
74 return error; 67 return error;
75} 68}
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c
index dfef0cb268dc..839b8ebc6fe6 100644
--- a/security/tomoyo/memory.c
+++ b/security/tomoyo/memory.c
@@ -93,15 +93,18 @@ void tomoyo_memory_free(void *ptr)
93/** 93/**
94 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". 94 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
95 * 95 *
96 * @group_name: The name of address group. 96 * @param: Pointer to "struct tomoyo_acl_param".
97 * @idx: Index number. 97 * @idx: Index number.
98 * 98 *
99 * Returns pointer to "struct tomoyo_group" on success, NULL otherwise. 99 * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.
100 */ 100 */
101struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) 101struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
102 const u8 idx)
102{ 103{
103 struct tomoyo_group e = { }; 104 struct tomoyo_group e = { };
104 struct tomoyo_group *group = NULL; 105 struct tomoyo_group *group = NULL;
106 struct list_head *list;
107 const char *group_name = tomoyo_read_token(param);
105 bool found = false; 108 bool found = false;
106 if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) 109 if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
107 return NULL; 110 return NULL;
@@ -110,7 +113,8 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
110 return NULL; 113 return NULL;
111 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 114 if (mutex_lock_interruptible(&tomoyo_policy_lock))
112 goto out; 115 goto out;
113 list_for_each_entry(group, &tomoyo_group_list[idx], head.list) { 116 list = &tomoyo_group_list[idx];
117 list_for_each_entry(group, list, head.list) {
114 if (e.group_name != group->group_name) 118 if (e.group_name != group->group_name)
115 continue; 119 continue;
116 atomic_inc(&group->head.users); 120 atomic_inc(&group->head.users);
@@ -122,14 +126,13 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
122 if (entry) { 126 if (entry) {
123 INIT_LIST_HEAD(&entry->member_list); 127 INIT_LIST_HEAD(&entry->member_list);
124 atomic_set(&entry->head.users, 1); 128 atomic_set(&entry->head.users, 1);
125 list_add_tail_rcu(&entry->head.list, 129 list_add_tail_rcu(&entry->head.list, list);
126 &tomoyo_group_list[idx]);
127 group = entry; 130 group = entry;
128 found = true; 131 found = true;
129 } 132 }
130 } 133 }
131 mutex_unlock(&tomoyo_policy_lock); 134 mutex_unlock(&tomoyo_policy_lock);
132 out: 135out:
133 tomoyo_put_name(e.group_name); 136 tomoyo_put_name(e.group_name);
134 return found ? group : NULL; 137 return found ? group : NULL;
135} 138}
@@ -210,6 +213,8 @@ void __init tomoyo_mm_init(void)
210 idx = tomoyo_read_lock(); 213 idx = tomoyo_read_lock();
211 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) 214 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
212 panic("Can't register tomoyo_kernel_domain"); 215 panic("Can't register tomoyo_kernel_domain");
216#if 0
217 /* Will be replaced with tomoyo_load_builtin_policy(). */
213 { 218 {
214 /* Load built-in policy. */ 219 /* Load built-in policy. */
215 tomoyo_write_transition_control("/sbin/hotplug", false, 220 tomoyo_write_transition_control("/sbin/hotplug", false,
@@ -217,6 +222,7 @@ void __init tomoyo_mm_init(void)
217 tomoyo_write_transition_control("/sbin/modprobe", false, 222 tomoyo_write_transition_control("/sbin/modprobe", false,
218 TOMOYO_TRANSITION_CONTROL_INITIALIZE); 223 TOMOYO_TRANSITION_CONTROL_INITIALIZE);
219 } 224 }
225#endif
220 tomoyo_read_unlock(idx); 226 tomoyo_read_unlock(idx);
221} 227}
222 228
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
index 7649dbc6a56b..1e610f96c99d 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -243,56 +243,3 @@ int tomoyo_mount_permission(char *dev_name, struct path *path,
243 tomoyo_read_unlock(idx); 243 tomoyo_read_unlock(idx);
244 return error; 244 return error;
245} 245}
246
247/**
248 * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
249 *
250 * @a: Pointer to "struct tomoyo_acl_info".
251 * @b: Pointer to "struct tomoyo_acl_info".
252 *
253 * Returns true if @a == @b, false otherwise.
254 */
255static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
256 const struct tomoyo_acl_info *b)
257{
258 const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
259 const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
260 return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
261 tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
262 tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
263 tomoyo_same_number_union(&p1->flags, &p2->flags);
264}
265
266/**
267 * tomoyo_write_mount - Write "struct tomoyo_mount_acl" list.
268 *
269 * @data: String to parse.
270 * @domain: Pointer to "struct tomoyo_domain_info".
271 * @is_delete: True if it is a delete request.
272 *
273 * Returns 0 on success, negative value otherwise.
274 *
275 * Caller holds tomoyo_read_lock().
276 */
277int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain,
278 const bool is_delete)
279{
280 struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
281 int error = is_delete ? -ENOENT : -ENOMEM;
282 char *w[4];
283 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0])
284 return -EINVAL;
285 if (!tomoyo_parse_name_union(w[0], &e.dev_name) ||
286 !tomoyo_parse_name_union(w[1], &e.dir_name) ||
287 !tomoyo_parse_name_union(w[2], &e.fs_type) ||
288 !tomoyo_parse_number_union(w[3], &e.flags))
289 goto out;
290 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
291 tomoyo_same_mount_acl, NULL);
292 out:
293 tomoyo_put_name_union(&e.dev_name);
294 tomoyo_put_name_union(&e.dir_name);
295 tomoyo_put_name_union(&e.fs_type);
296 tomoyo_put_number_union(&e.flags);
297 return error;
298}
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index abb177c2d7c2..72cd2b97cae8 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -16,6 +16,46 @@ DEFINE_MUTEX(tomoyo_policy_lock);
16bool tomoyo_policy_loaded; 16bool tomoyo_policy_loaded;
17 17
18/** 18/**
19 * tomoyo_permstr - Find permission keywords.
20 *
21 * @string: String representation for permissions in foo/bar/buz format.
22 * @keyword: Keyword to find from @string/
23 *
24 * Returns ture if @keyword was found in @string, false otherwise.
25 *
26 * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
27 */
28bool tomoyo_permstr(const char *string, const char *keyword)
29{
30 const char *cp = strstr(string, keyword);
31 if (cp)
32 return cp == string || *(cp - 1) == '/';
33 return false;
34}
35
36/**
37 * tomoyo_read_token - Read a word from a line.
38 *
39 * @param: Pointer to "struct tomoyo_acl_param".
40 *
41 * Returns a word on success, "" otherwise.
42 *
43 * To allow the caller to skip NULL check, this function returns "" rather than
44 * NULL if there is no more words to read.
45 */
46char *tomoyo_read_token(struct tomoyo_acl_param *param)
47{
48 char *pos = param->data;
49 char *del = strchr(pos, ' ');
50 if (del)
51 *del++ = '\0';
52 else
53 del = pos + strlen(pos);
54 param->data = del;
55 return pos;
56}
57
58/**
19 * tomoyo_parse_ulong - Parse an "unsigned long" value. 59 * tomoyo_parse_ulong - Parse an "unsigned long" value.
20 * 60 *
21 * @result: Pointer to "unsigned long". 61 * @result: Pointer to "unsigned long".
@@ -81,20 +121,23 @@ void tomoyo_print_ulong(char *buffer, const int buffer_len,
81/** 121/**
82 * tomoyo_parse_name_union - Parse a tomoyo_name_union. 122 * tomoyo_parse_name_union - Parse a tomoyo_name_union.
83 * 123 *
84 * @filename: Name or name group. 124 * @param: Pointer to "struct tomoyo_acl_param".
85 * @ptr: Pointer to "struct tomoyo_name_union". 125 * @ptr: Pointer to "struct tomoyo_name_union".
86 * 126 *
87 * Returns true on success, false otherwise. 127 * Returns true on success, false otherwise.
88 */ 128 */
89bool tomoyo_parse_name_union(const char *filename, 129bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
90 struct tomoyo_name_union *ptr) 130 struct tomoyo_name_union *ptr)
91{ 131{
92 if (!tomoyo_correct_word(filename)) 132 char *filename;
93 return false; 133 if (param->data[0] == '@') {
94 if (filename[0] == '@') { 134 param->data++;
95 ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP); 135 ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP);
96 return ptr->group != NULL; 136 return ptr->group != NULL;
97 } 137 }
138 filename = tomoyo_read_token(param);
139 if (!tomoyo_correct_word(filename))
140 return false;
98 ptr->filename = tomoyo_get_name(filename); 141 ptr->filename = tomoyo_get_name(filename);
99 return ptr->filename != NULL; 142 return ptr->filename != NULL;
100} 143}
@@ -102,39 +145,41 @@ bool tomoyo_parse_name_union(const char *filename,
102/** 145/**
103 * tomoyo_parse_number_union - Parse a tomoyo_number_union. 146 * tomoyo_parse_number_union - Parse a tomoyo_number_union.
104 * 147 *
105 * @data: Number or number range or number group. 148 * @param: Pointer to "struct tomoyo_acl_param".
106 * @ptr: Pointer to "struct tomoyo_number_union". 149 * @ptr: Pointer to "struct tomoyo_number_union".
107 * 150 *
108 * Returns true on success, false otherwise. 151 * Returns true on success, false otherwise.
109 */ 152 */
110bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) 153bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
154 struct tomoyo_number_union *ptr)
111{ 155{
156 char *data;
112 u8 type; 157 u8 type;
113 unsigned long v; 158 unsigned long v;
114 memset(num, 0, sizeof(*num)); 159 memset(ptr, 0, sizeof(*ptr));
115 if (data[0] == '@') { 160 if (param->data[0] == '@') {
116 if (!tomoyo_correct_word(data)) 161 param->data++;
117 return false; 162 ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP);
118 num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP); 163 return ptr->group != NULL;
119 return num->group != NULL;
120 } 164 }
165 data = tomoyo_read_token(param);
121 type = tomoyo_parse_ulong(&v, &data); 166 type = tomoyo_parse_ulong(&v, &data);
122 if (!type) 167 if (type == TOMOYO_VALUE_TYPE_INVALID)
123 return false; 168 return false;
124 num->values[0] = v; 169 ptr->values[0] = v;
125 num->value_type[0] = type; 170 ptr->value_type[0] = type;
126 if (!*data) { 171 if (!*data) {
127 num->values[1] = v; 172 ptr->values[1] = v;
128 num->value_type[1] = type; 173 ptr->value_type[1] = type;
129 return true; 174 return true;
130 } 175 }
131 if (*data++ != '-') 176 if (*data++ != '-')
132 return false; 177 return false;
133 type = tomoyo_parse_ulong(&v, &data); 178 type = tomoyo_parse_ulong(&v, &data);
134 if (!type || *data) 179 if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
135 return false; 180 return false;
136 num->values[1] = v; 181 ptr->values[1] = v;
137 num->value_type[1] = type; 182 ptr->value_type[1] = type;
138 return true; 183 return true;
139} 184}
140 185
@@ -259,33 +304,6 @@ void tomoyo_normalize_line(unsigned char *buffer)
259} 304}
260 305
261/** 306/**
262 * tomoyo_tokenize - Tokenize string.
263 *
264 * @buffer: The line to tokenize.
265 * @w: Pointer to "char *".
266 * @size: Sizeof @w .
267 *
268 * Returns true on success, false otherwise.
269 */
270bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
271{
272 int count = size / sizeof(char *);
273 int i;
274 for (i = 0; i < count; i++)
275 w[i] = "";
276 for (i = 0; i < count; i++) {
277 char *cp = strchr(buffer, ' ');
278 if (cp)
279 *cp = '\0';
280 w[i] = buffer;
281 if (!cp)
282 break;
283 buffer = cp + 1;
284 }
285 return i < count || !*buffer;
286}
287
288/**
289 * tomoyo_correct_word2 - Validate a string. 307 * tomoyo_correct_word2 - Validate a string.
290 * 308 *
291 * @string: The string to check. May be non-'\0'-terminated. 309 * @string: The string to check. May be non-'\0'-terminated.