diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-06-26 10:17:10 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-06-28 19:31:20 -0400 |
commit | a238cf5b89ed5285be8de56335665d023972f7d5 (patch) | |
tree | cd2594f5c80345b5f880a3ccd445d15fb6b7d6cd /security | |
parent | 0df7e8b8f1c25c10820bdc679555f2fbfb897ca0 (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.c | 77 | ||||
-rw-r--r-- | security/tomoyo/common.h | 32 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 146 | ||||
-rw-r--r-- | security/tomoyo/file.c | 237 | ||||
-rw-r--r-- | security/tomoyo/group.c | 33 | ||||
-rw-r--r-- | security/tomoyo/memory.c | 20 | ||||
-rw-r--r-- | security/tomoyo/mount.c | 53 | ||||
-rw-r--r-- | security/tomoyo/util.c | 120 |
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), ¶m, |
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 | */ |
830 | static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain, | 834 | static 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(¶m.data, | ||
851 | tomoyo_callback[i].keyword)) | ||
852 | continue; | ||
853 | return tomoyo_callback[i].write(¶m); | ||
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 | */ |
1214 | static int tomoyo_write_exception(struct tomoyo_io_buffer *head) | 1234 | static 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(¶m.data, "delete "); | ||
1241 | if (tomoyo_str_starts(¶m.data, "aggregator ")) | ||
1242 | return tomoyo_write_aggregator(¶m); | ||
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(¶m.data, tomoyo_transition_type[i])) |
1228 | return tomoyo_write_transition_control(data, is_delete, | 1245 | return tomoyo_write_transition_control(¶m, 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(¶m.data, tomoyo_group_name[i])) |
1235 | return tomoyo_write_group(data, is_delete, i); | 1248 | return tomoyo_write_group(¶m, 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. */ | ||
401 | struct 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); | |||
521 | bool tomoyo_correct_path(const char *filename); | 528 | bool tomoyo_correct_path(const char *filename); |
522 | bool tomoyo_correct_word(const char *string); | 529 | bool tomoyo_correct_word(const char *string); |
523 | bool tomoyo_domain_def(const unsigned char *buffer); | 530 | bool tomoyo_domain_def(const unsigned char *buffer); |
524 | bool tomoyo_parse_name_union(const char *filename, | 531 | bool tomoyo_parse_name_union(struct tomoyo_acl_param *param, |
525 | struct tomoyo_name_union *ptr); | 532 | struct tomoyo_name_union *ptr); |
526 | const struct tomoyo_path_info * | 533 | const struct tomoyo_path_info * |
527 | tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, | 534 | tomoyo_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); |
532 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, | 539 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, |
533 | const struct tomoyo_path_info *pattern); | 540 | const struct tomoyo_path_info *pattern); |
534 | bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num); | 541 | bool tomoyo_parse_number_union(struct tomoyo_acl_param *param, |
542 | struct tomoyo_number_union *ptr); | ||
535 | bool tomoyo_tokenize(char *buffer, char *w[], size_t size); | 543 | bool tomoyo_tokenize(char *buffer, char *w[], size_t size); |
536 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); | 544 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); |
537 | int tomoyo_init_request_info(struct tomoyo_request_info *r, | 545 | int tomoyo_init_request_info(struct tomoyo_request_info *r, |
@@ -540,21 +548,19 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r, | |||
540 | int tomoyo_mount_permission(char *dev_name, struct path *path, | 548 | int 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); |
543 | int tomoyo_write_aggregator(char *data, const bool is_delete); | 551 | int tomoyo_write_aggregator(struct tomoyo_acl_param *param); |
544 | int tomoyo_write_transition_control(char *data, const bool is_delete, | 552 | int tomoyo_write_transition_control(struct tomoyo_acl_param *param, |
545 | const u8 type); | 553 | const u8 type); |
546 | int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, | 554 | int tomoyo_write_file(struct tomoyo_acl_param *param); |
547 | const bool is_delete); | 555 | int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type); |
548 | int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain, | ||
549 | const bool is_delete); | ||
550 | int tomoyo_write_group(char *data, const bool is_delete, const u8 type); | ||
551 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) | 556 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) |
552 | __attribute__ ((format(printf, 2, 3))); | 557 | __attribute__ ((format(printf, 2, 3))); |
553 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | 558 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); |
554 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | 559 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, |
555 | const u8 profile); | 560 | const u8 profile); |
556 | struct tomoyo_profile *tomoyo_profile(const u8 profile); | 561 | struct tomoyo_profile *tomoyo_profile(const u8 profile); |
557 | struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type); | 562 | struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, |
563 | const u8 idx); | ||
558 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | 564 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, |
559 | const u8 index); | 565 | const u8 index); |
560 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | 566 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); |
@@ -587,7 +593,7 @@ void tomoyo_put_name_union(struct tomoyo_name_union *ptr); | |||
587 | void tomoyo_run_gc(void); | 593 | void tomoyo_run_gc(void); |
588 | void tomoyo_memory_free(void *ptr); | 594 | void tomoyo_memory_free(void *ptr); |
589 | int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, | 595 | int 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)); |
598 | int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, | 604 | int 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, | |||
604 | void tomoyo_check_acl(struct tomoyo_request_info *r, | 610 | void 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 *)); |
613 | char *tomoyo_read_token(struct tomoyo_acl_param *param); | ||
614 | bool 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 | */ |
31 | int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, | 30 | int 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 | */ |
89 | int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, | 88 | int 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 | */ | ||
166 | static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, | 175 | static 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 | */ |
190 | static int tomoyo_update_transition_control_entry(const char *domainname, | 197 | int 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: | 232 | out: |
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 | */ | ||
233 | int 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 | */ | ||
306 | static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, | 303 | static 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 | */ |
326 | static int tomoyo_update_aggregator_entry(const char *original_name, | 323 | int 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: | 340 | out: |
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 | */ | ||
360 | int 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 | */ |
440 | static int tomoyo_update_path_acl(const u8 type, const char *filename, | 438 | static 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 | */ |
518 | static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, | 511 | static 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 | */ |
599 | static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | 587 | static 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 | */ |
712 | static int tomoyo_update_path_number_acl(const u8 type, const char *filename, | 695 | static 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 | */ | ||
953 | static 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 | */ | ||
973 | static 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 | */ |
976 | int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, | 1001 | int 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 | */ |
37 | int tomoyo_write_group(char *data, const bool is_delete, const u8 type) | 36 | int 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: | 65 | out: |
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 | */ |
101 | struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) | 101 | struct 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: | 135 | out: |
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 | */ | ||
255 | static 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 | */ | ||
277 | int 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); | |||
16 | bool tomoyo_policy_loaded; | 16 | bool 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 | */ | ||
28 | bool 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 | */ | ||
46 | char *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 | */ |
89 | bool tomoyo_parse_name_union(const char *filename, | 129 | bool 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 | */ |
110 | bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) | 153 | bool 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 | */ | ||
270 | bool 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. |