diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2010-01-04 16:39:37 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-01-10 17:27:40 -0500 |
commit | cd7bec6ad80188394a8ea857ff1aa3512fc2282a (patch) | |
tree | 598e7d59c29966e0d8fa8abf24eb51bbb2f567a6 | |
parent | e41035a996356c257183e53a70abfb46fa84908b (diff) |
TOMOYO: Remove memory pool for list elements.
Currently, TOMOYO allocates memory for list elements from memory pool allocated
by kmalloc(PAGE_SIZE). But that makes it difficult to kfree() when garbage
collector is added. Thus, remove memory pool and use kmalloc(sizeof()).
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r-- | security/tomoyo/common.c | 41 | ||||
-rw-r--r-- | security/tomoyo/common.h | 2 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 58 | ||||
-rw-r--r-- | security/tomoyo/file.c | 34 | ||||
-rw-r--r-- | security/tomoyo/realpath.c | 65 | ||||
-rw-r--r-- | security/tomoyo/realpath.h | 7 |
6 files changed, 73 insertions, 134 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 642e0e565dfc..e331e699cf54 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -900,9 +900,11 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned | |||
900 | ptr = tomoyo_profile_ptr[profile]; | 900 | ptr = tomoyo_profile_ptr[profile]; |
901 | if (ptr) | 901 | if (ptr) |
902 | goto ok; | 902 | goto ok; |
903 | ptr = tomoyo_alloc_element(sizeof(*ptr)); | 903 | ptr = kmalloc(sizeof(*ptr), GFP_KERNEL); |
904 | if (!ptr) | 904 | if (!tomoyo_memory_ok(ptr)) { |
905 | kfree(ptr); | ||
905 | goto ok; | 906 | goto ok; |
907 | } | ||
906 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) | 908 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) |
907 | ptr->value[i] = tomoyo_control_array[i].current_value; | 909 | ptr->value[i] = tomoyo_control_array[i].current_value; |
908 | mb(); /* Avoid out-of-order execution. */ | 910 | mb(); /* Avoid out-of-order execution. */ |
@@ -1120,6 +1122,7 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1120 | saved_manager = tomoyo_save_name(manager); | 1122 | saved_manager = tomoyo_save_name(manager); |
1121 | if (!saved_manager) | 1123 | if (!saved_manager) |
1122 | return -ENOMEM; | 1124 | return -ENOMEM; |
1125 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | ||
1123 | mutex_lock(&tomoyo_policy_lock); | 1126 | mutex_lock(&tomoyo_policy_lock); |
1124 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { | 1127 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { |
1125 | if (ptr->manager != saved_manager) | 1128 | if (ptr->manager != saved_manager) |
@@ -1132,15 +1135,16 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1132 | error = -ENOENT; | 1135 | error = -ENOENT; |
1133 | goto out; | 1136 | goto out; |
1134 | } | 1137 | } |
1135 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 1138 | if (!tomoyo_memory_ok(new_entry)) |
1136 | if (!new_entry) | ||
1137 | goto out; | 1139 | goto out; |
1138 | new_entry->manager = saved_manager; | 1140 | new_entry->manager = saved_manager; |
1139 | new_entry->is_domain = is_domain; | 1141 | new_entry->is_domain = is_domain; |
1140 | list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); | 1142 | list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); |
1143 | new_entry = NULL; | ||
1141 | error = 0; | 1144 | error = 0; |
1142 | out: | 1145 | out: |
1143 | mutex_unlock(&tomoyo_policy_lock); | 1146 | mutex_unlock(&tomoyo_policy_lock); |
1147 | kfree(new_entry); | ||
1144 | return error; | 1148 | return error; |
1145 | } | 1149 | } |
1146 | 1150 | ||
@@ -2148,35 +2152,6 @@ static int tomoyo_close_control(struct file *file) | |||
2148 | } | 2152 | } |
2149 | 2153 | ||
2150 | /** | 2154 | /** |
2151 | * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry. | ||
2152 | * | ||
2153 | * @acl_type: Type of ACL entry. | ||
2154 | * | ||
2155 | * Returns pointer to the ACL entry on success, NULL otherwise. | ||
2156 | */ | ||
2157 | void *tomoyo_alloc_acl_element(const u8 acl_type) | ||
2158 | { | ||
2159 | int len; | ||
2160 | struct tomoyo_acl_info *ptr; | ||
2161 | |||
2162 | switch (acl_type) { | ||
2163 | case TOMOYO_TYPE_SINGLE_PATH_ACL: | ||
2164 | len = sizeof(struct tomoyo_single_path_acl_record); | ||
2165 | break; | ||
2166 | case TOMOYO_TYPE_DOUBLE_PATH_ACL: | ||
2167 | len = sizeof(struct tomoyo_double_path_acl_record); | ||
2168 | break; | ||
2169 | default: | ||
2170 | return NULL; | ||
2171 | } | ||
2172 | ptr = tomoyo_alloc_element(len); | ||
2173 | if (!ptr) | ||
2174 | return NULL; | ||
2175 | ptr->type = acl_type; | ||
2176 | return ptr; | ||
2177 | } | ||
2178 | |||
2179 | /** | ||
2180 | * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. | 2155 | * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. |
2181 | * | 2156 | * |
2182 | * @inode: Pointer to "struct inode". | 2157 | * @inode: Pointer to "struct inode". |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 874abf8df43e..610a6a056828 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -376,8 +376,6 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
376 | /* Check mode for specified functionality. */ | 376 | /* Check mode for specified functionality. */ |
377 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | 377 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, |
378 | const u8 index); | 378 | const u8 index); |
379 | /* Allocate memory for structures. */ | ||
380 | void *tomoyo_alloc_acl_element(const u8 acl_type); | ||
381 | /* Fill in "struct tomoyo_path_info" members. */ | 379 | /* Fill in "struct tomoyo_path_info" members. */ |
382 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | 380 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); |
383 | /* Run policy loader when /sbin/init starts. */ | 381 | /* Run policy loader when /sbin/init starts. */ |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 7d0b0bc48201..a55a1cced58e 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -245,6 +245,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
245 | saved_program = tomoyo_save_name(program); | 245 | saved_program = tomoyo_save_name(program); |
246 | if (!saved_program) | 246 | if (!saved_program) |
247 | return -ENOMEM; | 247 | return -ENOMEM; |
248 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | ||
248 | mutex_lock(&tomoyo_policy_lock); | 249 | mutex_lock(&tomoyo_policy_lock); |
249 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { | 250 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { |
250 | if (ptr->is_not != is_not || | 251 | if (ptr->is_not != is_not || |
@@ -259,17 +260,18 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
259 | error = -ENOENT; | 260 | error = -ENOENT; |
260 | goto out; | 261 | goto out; |
261 | } | 262 | } |
262 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 263 | if (!tomoyo_memory_ok(new_entry)) |
263 | if (!new_entry) | ||
264 | goto out; | 264 | goto out; |
265 | new_entry->domainname = saved_domainname; | 265 | new_entry->domainname = saved_domainname; |
266 | new_entry->program = saved_program; | 266 | new_entry->program = saved_program; |
267 | new_entry->is_not = is_not; | 267 | new_entry->is_not = is_not; |
268 | new_entry->is_last_name = is_last_name; | 268 | new_entry->is_last_name = is_last_name; |
269 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); | 269 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); |
270 | new_entry = NULL; | ||
270 | error = 0; | 271 | error = 0; |
271 | out: | 272 | out: |
272 | mutex_unlock(&tomoyo_policy_lock); | 273 | mutex_unlock(&tomoyo_policy_lock); |
274 | kfree(new_entry); | ||
273 | return error; | 275 | return error; |
274 | } | 276 | } |
275 | 277 | ||
@@ -461,6 +463,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
461 | saved_domainname = tomoyo_save_name(domainname); | 463 | saved_domainname = tomoyo_save_name(domainname); |
462 | if (!saved_domainname) | 464 | if (!saved_domainname) |
463 | return -ENOMEM; | 465 | return -ENOMEM; |
466 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | ||
464 | mutex_lock(&tomoyo_policy_lock); | 467 | mutex_lock(&tomoyo_policy_lock); |
465 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { | 468 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { |
466 | if (ptr->is_not != is_not || | 469 | if (ptr->is_not != is_not || |
@@ -475,17 +478,18 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
475 | error = -ENOENT; | 478 | error = -ENOENT; |
476 | goto out; | 479 | goto out; |
477 | } | 480 | } |
478 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 481 | if (!tomoyo_memory_ok(new_entry)) |
479 | if (!new_entry) | ||
480 | goto out; | 482 | goto out; |
481 | new_entry->domainname = saved_domainname; | 483 | new_entry->domainname = saved_domainname; |
482 | new_entry->program = saved_program; | 484 | new_entry->program = saved_program; |
483 | new_entry->is_not = is_not; | 485 | new_entry->is_not = is_not; |
484 | new_entry->is_last_name = is_last_name; | 486 | new_entry->is_last_name = is_last_name; |
485 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); | 487 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); |
488 | new_entry = NULL; | ||
486 | error = 0; | 489 | error = 0; |
487 | out: | 490 | out: |
488 | mutex_unlock(&tomoyo_policy_lock); | 491 | mutex_unlock(&tomoyo_policy_lock); |
492 | kfree(new_entry); | ||
489 | return error; | 493 | return error; |
490 | } | 494 | } |
491 | 495 | ||
@@ -650,6 +654,7 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
650 | saved_aliased_name = tomoyo_save_name(aliased_name); | 654 | saved_aliased_name = tomoyo_save_name(aliased_name); |
651 | if (!saved_original_name || !saved_aliased_name) | 655 | if (!saved_original_name || !saved_aliased_name) |
652 | return -ENOMEM; | 656 | return -ENOMEM; |
657 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | ||
653 | mutex_lock(&tomoyo_policy_lock); | 658 | mutex_lock(&tomoyo_policy_lock); |
654 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { | 659 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { |
655 | if (ptr->original_name != saved_original_name || | 660 | if (ptr->original_name != saved_original_name || |
@@ -663,15 +668,16 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
663 | error = -ENOENT; | 668 | error = -ENOENT; |
664 | goto out; | 669 | goto out; |
665 | } | 670 | } |
666 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 671 | if (!tomoyo_memory_ok(new_entry)) |
667 | if (!new_entry) | ||
668 | goto out; | 672 | goto out; |
669 | new_entry->original_name = saved_original_name; | 673 | new_entry->original_name = saved_original_name; |
670 | new_entry->aliased_name = saved_aliased_name; | 674 | new_entry->aliased_name = saved_aliased_name; |
671 | list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); | 675 | list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); |
676 | new_entry = NULL; | ||
672 | error = 0; | 677 | error = 0; |
673 | out: | 678 | out: |
674 | mutex_unlock(&tomoyo_policy_lock); | 679 | mutex_unlock(&tomoyo_policy_lock); |
680 | kfree(new_entry); | ||
675 | return error; | 681 | return error; |
676 | } | 682 | } |
677 | 683 | ||
@@ -738,7 +744,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
738 | domainname, | 744 | domainname, |
739 | const u8 profile) | 745 | const u8 profile) |
740 | { | 746 | { |
741 | struct tomoyo_domain_info *domain = NULL; | 747 | struct tomoyo_domain_info *domain; |
742 | const struct tomoyo_path_info *saved_domainname; | 748 | const struct tomoyo_path_info *saved_domainname; |
743 | 749 | ||
744 | mutex_lock(&tomoyo_policy_lock); | 750 | mutex_lock(&tomoyo_policy_lock); |
@@ -750,43 +756,17 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
750 | saved_domainname = tomoyo_save_name(domainname); | 756 | saved_domainname = tomoyo_save_name(domainname); |
751 | if (!saved_domainname) | 757 | if (!saved_domainname) |
752 | goto out; | 758 | goto out; |
753 | /* Can I reuse memory of deleted domain? */ | 759 | domain = kmalloc(sizeof(*domain), GFP_KERNEL); |
754 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { | 760 | if (tomoyo_memory_ok(domain)) { |
755 | struct task_struct *p; | ||
756 | struct tomoyo_acl_info *ptr; | ||
757 | bool flag; | ||
758 | if (!domain->is_deleted || | ||
759 | domain->domainname != saved_domainname) | ||
760 | continue; | ||
761 | flag = false; | ||
762 | read_lock(&tasklist_lock); | ||
763 | for_each_process(p) { | ||
764 | if (tomoyo_real_domain(p) != domain) | ||
765 | continue; | ||
766 | flag = true; | ||
767 | break; | ||
768 | } | ||
769 | read_unlock(&tasklist_lock); | ||
770 | if (flag) | ||
771 | continue; | ||
772 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | ||
773 | ptr->type |= TOMOYO_ACL_DELETED; | ||
774 | } | ||
775 | tomoyo_set_domain_flag(domain, true, domain->flags); | ||
776 | domain->profile = profile; | ||
777 | domain->quota_warned = false; | ||
778 | mb(); /* Avoid out-of-order execution. */ | ||
779 | domain->is_deleted = false; | ||
780 | goto out; | ||
781 | } | ||
782 | /* No memory reusable. Create using new memory. */ | ||
783 | domain = tomoyo_alloc_element(sizeof(*domain)); | ||
784 | if (domain) { | ||
785 | INIT_LIST_HEAD(&domain->acl_info_list); | 761 | INIT_LIST_HEAD(&domain->acl_info_list); |
786 | domain->domainname = saved_domainname; | 762 | domain->domainname = saved_domainname; |
787 | domain->profile = profile; | 763 | domain->profile = profile; |
788 | list_add_tail_rcu(&domain->list, &tomoyo_domain_list); | 764 | list_add_tail_rcu(&domain->list, &tomoyo_domain_list); |
765 | } else { | ||
766 | kfree(domain); | ||
767 | domain = NULL; | ||
789 | } | 768 | } |
769 | |||
790 | out: | 770 | out: |
791 | mutex_unlock(&tomoyo_policy_lock); | 771 | mutex_unlock(&tomoyo_policy_lock); |
792 | return domain; | 772 | return domain; |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 5d1689d6e16c..075392c052b4 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -225,6 +225,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
225 | saved_filename = tomoyo_save_name(filename); | 225 | saved_filename = tomoyo_save_name(filename); |
226 | if (!saved_filename) | 226 | if (!saved_filename) |
227 | return -ENOMEM; | 227 | return -ENOMEM; |
228 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | ||
228 | mutex_lock(&tomoyo_policy_lock); | 229 | mutex_lock(&tomoyo_policy_lock); |
229 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { | 230 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { |
230 | if (ptr->filename != saved_filename) | 231 | if (ptr->filename != saved_filename) |
@@ -237,14 +238,15 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
237 | error = -ENOENT; | 238 | error = -ENOENT; |
238 | goto out; | 239 | goto out; |
239 | } | 240 | } |
240 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 241 | if (!tomoyo_memory_ok(new_entry)) |
241 | if (!new_entry) | ||
242 | goto out; | 242 | goto out; |
243 | new_entry->filename = saved_filename; | 243 | new_entry->filename = saved_filename; |
244 | list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); | 244 | list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); |
245 | new_entry = NULL; | ||
245 | error = 0; | 246 | error = 0; |
246 | out: | 247 | out: |
247 | mutex_unlock(&tomoyo_policy_lock); | 248 | mutex_unlock(&tomoyo_policy_lock); |
249 | kfree(new_entry); | ||
248 | return error; | 250 | return error; |
249 | } | 251 | } |
250 | 252 | ||
@@ -372,6 +374,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
372 | saved_pattern = tomoyo_save_name(pattern); | 374 | saved_pattern = tomoyo_save_name(pattern); |
373 | if (!saved_pattern) | 375 | if (!saved_pattern) |
374 | return -ENOMEM; | 376 | return -ENOMEM; |
377 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | ||
375 | mutex_lock(&tomoyo_policy_lock); | 378 | mutex_lock(&tomoyo_policy_lock); |
376 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { | 379 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { |
377 | if (saved_pattern != ptr->pattern) | 380 | if (saved_pattern != ptr->pattern) |
@@ -384,14 +387,15 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
384 | error = -ENOENT; | 387 | error = -ENOENT; |
385 | goto out; | 388 | goto out; |
386 | } | 389 | } |
387 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 390 | if (!tomoyo_memory_ok(new_entry)) |
388 | if (!new_entry) | ||
389 | goto out; | 391 | goto out; |
390 | new_entry->pattern = saved_pattern; | 392 | new_entry->pattern = saved_pattern; |
391 | list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); | 393 | list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); |
394 | new_entry = NULL; | ||
392 | error = 0; | 395 | error = 0; |
393 | out: | 396 | out: |
394 | mutex_unlock(&tomoyo_policy_lock); | 397 | mutex_unlock(&tomoyo_policy_lock); |
398 | kfree(new_entry); | ||
395 | return error; | 399 | return error; |
396 | } | 400 | } |
397 | 401 | ||
@@ -523,6 +527,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
523 | saved_pattern = tomoyo_save_name(pattern); | 527 | saved_pattern = tomoyo_save_name(pattern); |
524 | if (!saved_pattern) | 528 | if (!saved_pattern) |
525 | return -ENOMEM; | 529 | return -ENOMEM; |
530 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | ||
526 | mutex_lock(&tomoyo_policy_lock); | 531 | mutex_lock(&tomoyo_policy_lock); |
527 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { | 532 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { |
528 | if (ptr->pattern != saved_pattern) | 533 | if (ptr->pattern != saved_pattern) |
@@ -535,14 +540,15 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
535 | error = -ENOENT; | 540 | error = -ENOENT; |
536 | goto out; | 541 | goto out; |
537 | } | 542 | } |
538 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 543 | if (!tomoyo_memory_ok(new_entry)) |
539 | if (!new_entry) | ||
540 | goto out; | 544 | goto out; |
541 | new_entry->pattern = saved_pattern; | 545 | new_entry->pattern = saved_pattern; |
542 | list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); | 546 | list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); |
547 | new_entry = NULL; | ||
543 | error = 0; | 548 | error = 0; |
544 | out: | 549 | out: |
545 | mutex_unlock(&tomoyo_policy_lock); | 550 | mutex_unlock(&tomoyo_policy_lock); |
551 | kfree(new_entry); | ||
546 | return error; | 552 | return error; |
547 | } | 553 | } |
548 | 554 | ||
@@ -901,9 +907,13 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
901 | goto out; | 907 | goto out; |
902 | } | 908 | } |
903 | /* Not found. Append it to the tail. */ | 909 | /* Not found. Append it to the tail. */ |
904 | acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL); | 910 | acl = kmalloc(sizeof(*acl), GFP_KERNEL); |
905 | if (!acl) | 911 | if (!tomoyo_memory_ok(acl)) { |
912 | kfree(acl); | ||
913 | acl = NULL; | ||
906 | goto out; | 914 | goto out; |
915 | } | ||
916 | acl->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; | ||
907 | if (perm <= 0xFFFF) | 917 | if (perm <= 0xFFFF) |
908 | acl->perm = perm; | 918 | acl->perm = perm; |
909 | else | 919 | else |
@@ -995,9 +1005,13 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
995 | goto out; | 1005 | goto out; |
996 | } | 1006 | } |
997 | /* Not found. Append it to the tail. */ | 1007 | /* Not found. Append it to the tail. */ |
998 | acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL); | 1008 | acl = kmalloc(sizeof(*acl), GFP_KERNEL); |
999 | if (!acl) | 1009 | if (!tomoyo_memory_ok(acl)) { |
1010 | kfree(acl); | ||
1011 | acl = NULL; | ||
1000 | goto out; | 1012 | goto out; |
1013 | } | ||
1014 | acl->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; | ||
1001 | acl->perm = perm; | 1015 | acl->perm = perm; |
1002 | acl->filename1 = saved_filename1; | 1016 | acl->filename1 = saved_filename1; |
1003 | acl->filename2 = saved_filename2; | 1017 | acl->filename2 = saved_filename2; |
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 9105e5e29da9..54226d5be493 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c | |||
@@ -212,57 +212,32 @@ static unsigned int tomoyo_allocated_memory_for_elements; | |||
212 | static unsigned int tomoyo_quota_for_elements; | 212 | static unsigned int tomoyo_quota_for_elements; |
213 | 213 | ||
214 | /** | 214 | /** |
215 | * tomoyo_alloc_element - Allocate permanent memory for structures. | 215 | * tomoyo_memory_ok - Check memory quota. |
216 | * | 216 | * |
217 | * @size: Size in bytes. | 217 | * @ptr: Pointer to allocated memory. |
218 | * | 218 | * |
219 | * Returns pointer to allocated memory on success, NULL otherwise. | 219 | * Returns true on success, false otherwise. |
220 | * | 220 | * |
221 | * Memory has to be zeroed. | 221 | * Caller holds tomoyo_policy_lock. |
222 | * The RAM is chunked, so NEVER try to kfree() the returned pointer. | 222 | * Memory pointed by @ptr will be zeroed on success. |
223 | */ | 223 | */ |
224 | void *tomoyo_alloc_element(const unsigned int size) | 224 | bool tomoyo_memory_ok(void *ptr) |
225 | { | 225 | { |
226 | static char *buf; | 226 | int allocated_len = ptr ? ksize(ptr) : 0; |
227 | static DEFINE_MUTEX(lock); | 227 | bool result = false; |
228 | static unsigned int buf_used_len = PATH_MAX; | 228 | if (!ptr || (tomoyo_quota_for_elements && |
229 | char *ptr = NULL; | 229 | tomoyo_allocated_memory_for_elements |
230 | /*Assumes sizeof(void *) >= sizeof(long) is true. */ | 230 | + allocated_len > tomoyo_quota_for_elements)) { |
231 | const unsigned int word_aligned_size | 231 | printk(KERN_WARNING "ERROR: Out of memory " |
232 | = roundup(size, max(sizeof(void *), sizeof(long))); | 232 | "for tomoyo_alloc_element().\n"); |
233 | if (word_aligned_size > PATH_MAX) | 233 | if (!tomoyo_policy_loaded) |
234 | return NULL; | 234 | panic("MAC Initialization failed.\n"); |
235 | mutex_lock(&lock); | 235 | } else { |
236 | if (buf_used_len + word_aligned_size > PATH_MAX) { | 236 | result = true; |
237 | if (!tomoyo_quota_for_elements || | 237 | tomoyo_allocated_memory_for_elements += allocated_len; |
238 | tomoyo_allocated_memory_for_elements | 238 | memset(ptr, 0, allocated_len); |
239 | + PATH_MAX <= tomoyo_quota_for_elements) | ||
240 | ptr = kzalloc(PATH_MAX, GFP_KERNEL); | ||
241 | if (!ptr) { | ||
242 | printk(KERN_WARNING "ERROR: Out of memory " | ||
243 | "for tomoyo_alloc_element().\n"); | ||
244 | if (!tomoyo_policy_loaded) | ||
245 | panic("MAC Initialization failed.\n"); | ||
246 | } else { | ||
247 | buf = ptr; | ||
248 | tomoyo_allocated_memory_for_elements += PATH_MAX; | ||
249 | buf_used_len = word_aligned_size; | ||
250 | ptr = buf; | ||
251 | } | ||
252 | } else if (word_aligned_size) { | ||
253 | int i; | ||
254 | ptr = buf + buf_used_len; | ||
255 | buf_used_len += word_aligned_size; | ||
256 | for (i = 0; i < word_aligned_size; i++) { | ||
257 | if (!ptr[i]) | ||
258 | continue; | ||
259 | printk(KERN_ERR "WARNING: Reserved memory was tainted! " | ||
260 | "The system might go wrong.\n"); | ||
261 | ptr[i] = '\0'; | ||
262 | } | ||
263 | } | 239 | } |
264 | mutex_unlock(&lock); | 240 | return result; |
265 | return ptr; | ||
266 | } | 241 | } |
267 | 242 | ||
268 | /* Memory allocated for string data in bytes. */ | 243 | /* Memory allocated for string data in bytes. */ |
diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h index 78217a37960b..47b4f59dad6f 100644 --- a/security/tomoyo/realpath.h +++ b/security/tomoyo/realpath.h | |||
@@ -36,11 +36,8 @@ char *tomoyo_realpath_nofollow(const char *pathname); | |||
36 | /* Same with tomoyo_realpath() except that the pathname is already solved. */ | 36 | /* Same with tomoyo_realpath() except that the pathname is already solved. */ |
37 | char *tomoyo_realpath_from_path(struct path *path); | 37 | char *tomoyo_realpath_from_path(struct path *path); |
38 | 38 | ||
39 | /* | 39 | /* Check memory quota. */ |
40 | * Allocate memory for ACL entry. | 40 | bool tomoyo_memory_ok(void *ptr); |
41 | * The RAM is chunked, so NEVER try to kfree() the returned pointer. | ||
42 | */ | ||
43 | void *tomoyo_alloc_element(const unsigned int size); | ||
44 | 41 | ||
45 | /* | 42 | /* |
46 | * Keep the given name on the RAM. | 43 | * Keep the given name on the RAM. |