diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2010-02-10 19:41:58 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-02-14 17:00:16 -0500 |
commit | bf24fb016c861b7f52be0c36c4cedd3e89afa2e2 (patch) | |
tree | f485ca2e70d8305d9aaecf45b5fd929b68b971b2 | |
parent | ca0b7df3374c5566468c17f26fa2dfd3fe3c6a37 (diff) |
TOMOYO: Add refcounter on string data.
Add refcounter to "struct tomoyo_name_entry" and replace tomoyo_save_name()
with tomoyo_get_name()/tomoyo_put_name() pair so that we can kfree() when
garbage collector is added.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r-- | security/tomoyo/common.c | 10 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 32 | ||||
-rw-r--r-- | security/tomoyo/file.c | 24 | ||||
-rw-r--r-- | security/tomoyo/realpath.c | 30 | ||||
-rw-r--r-- | security/tomoyo/realpath.h | 21 |
5 files changed, 77 insertions, 40 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index a53ee059da48..0c7ea51e7a45 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -12,8 +12,8 @@ | |||
12 | #include <linux/uaccess.h> | 12 | #include <linux/uaccess.h> |
13 | #include <linux/security.h> | 13 | #include <linux/security.h> |
14 | #include <linux/hardirq.h> | 14 | #include <linux/hardirq.h> |
15 | #include "realpath.h" | ||
16 | #include "common.h" | 15 | #include "common.h" |
16 | #include "realpath.h" | ||
17 | #include "tomoyo.h" | 17 | #include "tomoyo.h" |
18 | 18 | ||
19 | /* Lock for protecting policy. */ | 19 | /* Lock for protecting policy. */ |
@@ -943,7 +943,9 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
943 | return -EINVAL; | 943 | return -EINVAL; |
944 | *cp = '\0'; | 944 | *cp = '\0'; |
945 | if (!strcmp(data, "COMMENT")) { | 945 | if (!strcmp(data, "COMMENT")) { |
946 | profile->comment = tomoyo_save_name(cp + 1); | 946 | const struct tomoyo_path_info *old_comment = profile->comment; |
947 | profile->comment = tomoyo_get_name(cp + 1); | ||
948 | tomoyo_put_name(old_comment); | ||
947 | return 0; | 949 | return 0; |
948 | } | 950 | } |
949 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { | 951 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { |
@@ -1117,7 +1119,7 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1117 | if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__)) | 1119 | if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__)) |
1118 | return -EINVAL; | 1120 | return -EINVAL; |
1119 | } | 1121 | } |
1120 | saved_manager = tomoyo_save_name(manager); | 1122 | saved_manager = tomoyo_get_name(manager); |
1121 | if (!saved_manager) | 1123 | if (!saved_manager) |
1122 | return -ENOMEM; | 1124 | return -ENOMEM; |
1123 | if (!is_delete) | 1125 | if (!is_delete) |
@@ -1132,12 +1134,14 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1132 | } | 1134 | } |
1133 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 1135 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
1134 | entry->manager = saved_manager; | 1136 | entry->manager = saved_manager; |
1137 | saved_manager = NULL; | ||
1135 | entry->is_domain = is_domain; | 1138 | entry->is_domain = is_domain; |
1136 | list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); | 1139 | list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); |
1137 | entry = NULL; | 1140 | entry = NULL; |
1138 | error = 0; | 1141 | error = 0; |
1139 | } | 1142 | } |
1140 | mutex_unlock(&tomoyo_policy_lock); | 1143 | mutex_unlock(&tomoyo_policy_lock); |
1144 | tomoyo_put_name(saved_manager); | ||
1141 | kfree(entry); | 1145 | kfree(entry); |
1142 | return error; | 1146 | return error; |
1143 | } | 1147 | } |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 229de1e71a38..0b8262567809 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -203,7 +203,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
203 | { | 203 | { |
204 | struct tomoyo_domain_initializer_entry *entry = NULL; | 204 | struct tomoyo_domain_initializer_entry *entry = NULL; |
205 | struct tomoyo_domain_initializer_entry *ptr; | 205 | struct tomoyo_domain_initializer_entry *ptr; |
206 | const struct tomoyo_path_info *saved_program; | 206 | const struct tomoyo_path_info *saved_program = NULL; |
207 | const struct tomoyo_path_info *saved_domainname = NULL; | 207 | const struct tomoyo_path_info *saved_domainname = NULL; |
208 | int error = is_delete ? -ENOENT : -ENOMEM; | 208 | int error = is_delete ? -ENOENT : -ENOMEM; |
209 | bool is_last_name = false; | 209 | bool is_last_name = false; |
@@ -216,11 +216,11 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
216 | is_last_name = true; | 216 | is_last_name = true; |
217 | else if (!tomoyo_is_correct_domain(domainname, __func__)) | 217 | else if (!tomoyo_is_correct_domain(domainname, __func__)) |
218 | return -EINVAL; | 218 | return -EINVAL; |
219 | saved_domainname = tomoyo_save_name(domainname); | 219 | saved_domainname = tomoyo_get_name(domainname); |
220 | if (!saved_domainname) | 220 | if (!saved_domainname) |
221 | goto out; | 221 | goto out; |
222 | } | 222 | } |
223 | saved_program = tomoyo_save_name(program); | 223 | saved_program = tomoyo_get_name(program); |
224 | if (!saved_program) | 224 | if (!saved_program) |
225 | goto out; | 225 | goto out; |
226 | if (!is_delete) | 226 | if (!is_delete) |
@@ -237,7 +237,9 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
237 | } | 237 | } |
238 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 238 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
239 | entry->domainname = saved_domainname; | 239 | entry->domainname = saved_domainname; |
240 | saved_domainname = NULL; | ||
240 | entry->program = saved_program; | 241 | entry->program = saved_program; |
242 | saved_program = NULL; | ||
241 | entry->is_not = is_not; | 243 | entry->is_not = is_not; |
242 | entry->is_last_name = is_last_name; | 244 | entry->is_last_name = is_last_name; |
243 | list_add_tail_rcu(&entry->list, | 245 | list_add_tail_rcu(&entry->list, |
@@ -247,6 +249,8 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
247 | } | 249 | } |
248 | mutex_unlock(&tomoyo_policy_lock); | 250 | mutex_unlock(&tomoyo_policy_lock); |
249 | out: | 251 | out: |
252 | tomoyo_put_name(saved_domainname); | ||
253 | tomoyo_put_name(saved_program); | ||
250 | kfree(entry); | 254 | kfree(entry); |
251 | return error; | 255 | return error; |
252 | } | 256 | } |
@@ -419,7 +423,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
419 | { | 423 | { |
420 | struct tomoyo_domain_keeper_entry *entry = NULL; | 424 | struct tomoyo_domain_keeper_entry *entry = NULL; |
421 | struct tomoyo_domain_keeper_entry *ptr; | 425 | struct tomoyo_domain_keeper_entry *ptr; |
422 | const struct tomoyo_path_info *saved_domainname; | 426 | const struct tomoyo_path_info *saved_domainname = NULL; |
423 | const struct tomoyo_path_info *saved_program = NULL; | 427 | const struct tomoyo_path_info *saved_program = NULL; |
424 | int error = is_delete ? -ENOENT : -ENOMEM; | 428 | int error = is_delete ? -ENOENT : -ENOMEM; |
425 | bool is_last_name = false; | 429 | bool is_last_name = false; |
@@ -432,11 +436,11 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
432 | if (program) { | 436 | if (program) { |
433 | if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) | 437 | if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) |
434 | return -EINVAL; | 438 | return -EINVAL; |
435 | saved_program = tomoyo_save_name(program); | 439 | saved_program = tomoyo_get_name(program); |
436 | if (!saved_program) | 440 | if (!saved_program) |
437 | goto out; | 441 | goto out; |
438 | } | 442 | } |
439 | saved_domainname = tomoyo_save_name(domainname); | 443 | saved_domainname = tomoyo_get_name(domainname); |
440 | if (!saved_domainname) | 444 | if (!saved_domainname) |
441 | goto out; | 445 | goto out; |
442 | if (!is_delete) | 446 | if (!is_delete) |
@@ -453,7 +457,9 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
453 | } | 457 | } |
454 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 458 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
455 | entry->domainname = saved_domainname; | 459 | entry->domainname = saved_domainname; |
460 | saved_domainname = NULL; | ||
456 | entry->program = saved_program; | 461 | entry->program = saved_program; |
462 | saved_program = NULL; | ||
457 | entry->is_not = is_not; | 463 | entry->is_not = is_not; |
458 | entry->is_last_name = is_last_name; | 464 | entry->is_last_name = is_last_name; |
459 | list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); | 465 | list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); |
@@ -462,6 +468,8 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
462 | } | 468 | } |
463 | mutex_unlock(&tomoyo_policy_lock); | 469 | mutex_unlock(&tomoyo_policy_lock); |
464 | out: | 470 | out: |
471 | tomoyo_put_name(saved_domainname); | ||
472 | tomoyo_put_name(saved_program); | ||
465 | kfree(entry); | 473 | kfree(entry); |
466 | return error; | 474 | return error; |
467 | } | 475 | } |
@@ -623,8 +631,8 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
623 | if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || | 631 | if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || |
624 | !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) | 632 | !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) |
625 | return -EINVAL; /* No patterns allowed. */ | 633 | return -EINVAL; /* No patterns allowed. */ |
626 | saved_original_name = tomoyo_save_name(original_name); | 634 | saved_original_name = tomoyo_get_name(original_name); |
627 | saved_aliased_name = tomoyo_save_name(aliased_name); | 635 | saved_aliased_name = tomoyo_get_name(aliased_name); |
628 | if (!saved_original_name || !saved_aliased_name) | 636 | if (!saved_original_name || !saved_aliased_name) |
629 | goto out; | 637 | goto out; |
630 | if (!is_delete) | 638 | if (!is_delete) |
@@ -640,13 +648,17 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
640 | } | 648 | } |
641 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 649 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
642 | entry->original_name = saved_original_name; | 650 | entry->original_name = saved_original_name; |
651 | saved_original_name = NULL; | ||
643 | entry->aliased_name = saved_aliased_name; | 652 | entry->aliased_name = saved_aliased_name; |
653 | saved_aliased_name = NULL; | ||
644 | list_add_tail_rcu(&entry->list, &tomoyo_alias_list); | 654 | list_add_tail_rcu(&entry->list, &tomoyo_alias_list); |
645 | entry = NULL; | 655 | entry = NULL; |
646 | error = 0; | 656 | error = 0; |
647 | } | 657 | } |
648 | mutex_unlock(&tomoyo_policy_lock); | 658 | mutex_unlock(&tomoyo_policy_lock); |
649 | out: | 659 | out: |
660 | tomoyo_put_name(saved_original_name); | ||
661 | tomoyo_put_name(saved_aliased_name); | ||
650 | kfree(entry); | 662 | kfree(entry); |
651 | return error; | 663 | return error; |
652 | } | 664 | } |
@@ -721,7 +733,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
721 | 733 | ||
722 | if (!tomoyo_is_correct_domain(domainname, __func__)) | 734 | if (!tomoyo_is_correct_domain(domainname, __func__)) |
723 | return NULL; | 735 | return NULL; |
724 | saved_domainname = tomoyo_save_name(domainname); | 736 | saved_domainname = tomoyo_get_name(domainname); |
725 | if (!saved_domainname) | 737 | if (!saved_domainname) |
726 | return NULL; | 738 | return NULL; |
727 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 739 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
@@ -736,6 +748,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
736 | if (!found && tomoyo_memory_ok(entry)) { | 748 | if (!found && tomoyo_memory_ok(entry)) { |
737 | INIT_LIST_HEAD(&entry->acl_info_list); | 749 | INIT_LIST_HEAD(&entry->acl_info_list); |
738 | entry->domainname = saved_domainname; | 750 | entry->domainname = saved_domainname; |
751 | saved_domainname = NULL; | ||
739 | entry->profile = profile; | 752 | entry->profile = profile; |
740 | list_add_tail_rcu(&entry->list, &tomoyo_domain_list); | 753 | list_add_tail_rcu(&entry->list, &tomoyo_domain_list); |
741 | domain = entry; | 754 | domain = entry; |
@@ -743,6 +756,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
743 | found = true; | 756 | found = true; |
744 | } | 757 | } |
745 | mutex_unlock(&tomoyo_policy_lock); | 758 | mutex_unlock(&tomoyo_policy_lock); |
759 | tomoyo_put_name(saved_domainname); | ||
746 | kfree(entry); | 760 | kfree(entry); |
747 | return found ? domain : NULL; | 761 | return found ? domain : NULL; |
748 | } | 762 | } |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index f4a27714e077..a49e18cc7bc2 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -222,7 +222,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
222 | 222 | ||
223 | if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) | 223 | if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) |
224 | return -EINVAL; | 224 | return -EINVAL; |
225 | saved_filename = tomoyo_save_name(filename); | 225 | saved_filename = tomoyo_get_name(filename); |
226 | if (!saved_filename) | 226 | if (!saved_filename) |
227 | return -ENOMEM; | 227 | return -ENOMEM; |
228 | if (!is_delete) | 228 | if (!is_delete) |
@@ -237,11 +237,13 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
237 | } | 237 | } |
238 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 238 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
239 | entry->filename = saved_filename; | 239 | entry->filename = saved_filename; |
240 | saved_filename = NULL; | ||
240 | list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); | 241 | list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); |
241 | entry = NULL; | 242 | entry = NULL; |
242 | error = 0; | 243 | error = 0; |
243 | } | 244 | } |
244 | mutex_unlock(&tomoyo_policy_lock); | 245 | mutex_unlock(&tomoyo_policy_lock); |
246 | tomoyo_put_name(saved_filename); | ||
245 | kfree(entry); | 247 | kfree(entry); |
246 | return error; | 248 | return error; |
247 | } | 249 | } |
@@ -365,7 +367,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
365 | const struct tomoyo_path_info *saved_pattern; | 367 | const struct tomoyo_path_info *saved_pattern; |
366 | int error = is_delete ? -ENOENT : -ENOMEM; | 368 | int error = is_delete ? -ENOENT : -ENOMEM; |
367 | 369 | ||
368 | saved_pattern = tomoyo_save_name(pattern); | 370 | saved_pattern = tomoyo_get_name(pattern); |
369 | if (!saved_pattern) | 371 | if (!saved_pattern) |
370 | return error; | 372 | return error; |
371 | if (!saved_pattern->is_patterned) | 373 | if (!saved_pattern->is_patterned) |
@@ -382,6 +384,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
382 | } | 384 | } |
383 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 385 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
384 | entry->pattern = saved_pattern; | 386 | entry->pattern = saved_pattern; |
387 | saved_pattern = NULL; | ||
385 | list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); | 388 | list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); |
386 | entry = NULL; | 389 | entry = NULL; |
387 | error = 0; | 390 | error = 0; |
@@ -389,6 +392,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
389 | mutex_unlock(&tomoyo_policy_lock); | 392 | mutex_unlock(&tomoyo_policy_lock); |
390 | out: | 393 | out: |
391 | kfree(entry); | 394 | kfree(entry); |
395 | tomoyo_put_name(saved_pattern); | ||
392 | return error; | 396 | return error; |
393 | } | 397 | } |
394 | 398 | ||
@@ -518,7 +522,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
518 | 522 | ||
519 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) | 523 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) |
520 | return -EINVAL; | 524 | return -EINVAL; |
521 | saved_pattern = tomoyo_save_name(pattern); | 525 | saved_pattern = tomoyo_get_name(pattern); |
522 | if (!saved_pattern) | 526 | if (!saved_pattern) |
523 | return error; | 527 | return error; |
524 | if (!is_delete) | 528 | if (!is_delete) |
@@ -533,11 +537,13 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
533 | } | 537 | } |
534 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | 538 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
535 | entry->pattern = saved_pattern; | 539 | entry->pattern = saved_pattern; |
540 | saved_pattern = NULL; | ||
536 | list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); | 541 | list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); |
537 | entry = NULL; | 542 | entry = NULL; |
538 | error = 0; | 543 | error = 0; |
539 | } | 544 | } |
540 | mutex_unlock(&tomoyo_policy_lock); | 545 | mutex_unlock(&tomoyo_policy_lock); |
546 | tomoyo_put_name(saved_pattern); | ||
541 | kfree(entry); | 547 | kfree(entry); |
542 | return error; | 548 | return error; |
543 | } | 549 | } |
@@ -867,7 +873,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
867 | return -EINVAL; | 873 | return -EINVAL; |
868 | if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__)) | 874 | if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__)) |
869 | return -EINVAL; | 875 | return -EINVAL; |
870 | saved_filename = tomoyo_save_name(filename); | 876 | saved_filename = tomoyo_get_name(filename); |
871 | if (!saved_filename) | 877 | if (!saved_filename) |
872 | return -ENOMEM; | 878 | return -ENOMEM; |
873 | if (!is_delete) | 879 | if (!is_delete) |
@@ -913,12 +919,14 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
913 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | 919 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) |
914 | entry->perm |= rw_mask; | 920 | entry->perm |= rw_mask; |
915 | entry->filename = saved_filename; | 921 | entry->filename = saved_filename; |
922 | saved_filename = NULL; | ||
916 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); | 923 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); |
917 | entry = NULL; | 924 | entry = NULL; |
918 | error = 0; | 925 | error = 0; |
919 | } | 926 | } |
920 | mutex_unlock(&tomoyo_policy_lock); | 927 | mutex_unlock(&tomoyo_policy_lock); |
921 | kfree(entry); | 928 | kfree(entry); |
929 | tomoyo_put_name(saved_filename); | ||
922 | return error; | 930 | return error; |
923 | } | 931 | } |
924 | 932 | ||
@@ -952,8 +960,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
952 | if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) || | 960 | if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) || |
953 | !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__)) | 961 | !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__)) |
954 | return -EINVAL; | 962 | return -EINVAL; |
955 | saved_filename1 = tomoyo_save_name(filename1); | 963 | saved_filename1 = tomoyo_get_name(filename1); |
956 | saved_filename2 = tomoyo_save_name(filename2); | 964 | saved_filename2 = tomoyo_get_name(filename2); |
957 | if (!saved_filename1 || !saved_filename2) | 965 | if (!saved_filename1 || !saved_filename2) |
958 | goto out; | 966 | goto out; |
959 | if (!is_delete) | 967 | if (!is_delete) |
@@ -979,13 +987,17 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
979 | entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; | 987 | entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; |
980 | entry->perm = perm; | 988 | entry->perm = perm; |
981 | entry->filename1 = saved_filename1; | 989 | entry->filename1 = saved_filename1; |
990 | saved_filename1 = NULL; | ||
982 | entry->filename2 = saved_filename2; | 991 | entry->filename2 = saved_filename2; |
992 | saved_filename2 = NULL; | ||
983 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); | 993 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); |
984 | entry = NULL; | 994 | entry = NULL; |
985 | error = 0; | 995 | error = 0; |
986 | } | 996 | } |
987 | mutex_unlock(&tomoyo_policy_lock); | 997 | mutex_unlock(&tomoyo_policy_lock); |
988 | out: | 998 | out: |
999 | tomoyo_put_name(saved_filename1); | ||
1000 | tomoyo_put_name(saved_filename2); | ||
989 | kfree(entry); | 1001 | kfree(entry); |
990 | return error; | 1002 | return error; |
991 | } | 1003 | } |
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 92460c7ded67..2f7f54fc6812 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c | |||
@@ -254,21 +254,6 @@ static unsigned int tomoyo_quota_for_savename; | |||
254 | #define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) | 254 | #define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) |
255 | 255 | ||
256 | /* | 256 | /* |
257 | * tomoyo_name_entry is a structure which is used for linking | ||
258 | * "struct tomoyo_path_info" into tomoyo_name_list . | ||
259 | * | ||
260 | * Since tomoyo_name_list manages a list of strings which are shared by | ||
261 | * multiple processes (whereas "struct tomoyo_path_info" inside | ||
262 | * "struct tomoyo_path_info_with_data" is not shared), a reference counter will | ||
263 | * be added to "struct tomoyo_name_entry" rather than "struct tomoyo_path_info" | ||
264 | * when TOMOYO starts supporting garbage collector. | ||
265 | */ | ||
266 | struct tomoyo_name_entry { | ||
267 | struct list_head list; | ||
268 | struct tomoyo_path_info entry; | ||
269 | }; | ||
270 | |||
271 | /* | ||
272 | * tomoyo_name_list is used for holding string data used by TOMOYO. | 257 | * tomoyo_name_list is used for holding string data used by TOMOYO. |
273 | * Since same string data is likely used for multiple times (e.g. | 258 | * Since same string data is likely used for multiple times (e.g. |
274 | * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of | 259 | * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of |
@@ -277,13 +262,13 @@ struct tomoyo_name_entry { | |||
277 | static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; | 262 | static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; |
278 | 263 | ||
279 | /** | 264 | /** |
280 | * tomoyo_save_name - Allocate permanent memory for string data. | 265 | * tomoyo_get_name - Allocate permanent memory for string data. |
281 | * | 266 | * |
282 | * @name: The string to store into the permernent memory. | 267 | * @name: The string to store into the permernent memory. |
283 | * | 268 | * |
284 | * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. | 269 | * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. |
285 | */ | 270 | */ |
286 | const struct tomoyo_path_info *tomoyo_save_name(const char *name) | 271 | const struct tomoyo_path_info *tomoyo_get_name(const char *name) |
287 | { | 272 | { |
288 | static DEFINE_MUTEX(lock); | 273 | static DEFINE_MUTEX(lock); |
289 | struct tomoyo_name_entry *ptr; | 274 | struct tomoyo_name_entry *ptr; |
@@ -299,8 +284,10 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) | |||
299 | head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; | 284 | head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; |
300 | mutex_lock(&lock); | 285 | mutex_lock(&lock); |
301 | list_for_each_entry(ptr, head, list) { | 286 | list_for_each_entry(ptr, head, list) { |
302 | if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name)) | 287 | if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) |
303 | goto out; | 288 | continue; |
289 | atomic_inc(&ptr->users); | ||
290 | goto out; | ||
304 | } | 291 | } |
305 | ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); | 292 | ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); |
306 | allocated_len = ptr ? ksize(ptr) : 0; | 293 | allocated_len = ptr ? ksize(ptr) : 0; |
@@ -309,7 +296,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) | |||
309 | > tomoyo_quota_for_savename)) { | 296 | > tomoyo_quota_for_savename)) { |
310 | kfree(ptr); | 297 | kfree(ptr); |
311 | printk(KERN_WARNING "ERROR: Out of memory " | 298 | printk(KERN_WARNING "ERROR: Out of memory " |
312 | "for tomoyo_save_name().\n"); | 299 | "for tomoyo_get_name().\n"); |
313 | if (!tomoyo_policy_loaded) | 300 | if (!tomoyo_policy_loaded) |
314 | panic("MAC Initialization failed.\n"); | 301 | panic("MAC Initialization failed.\n"); |
315 | ptr = NULL; | 302 | ptr = NULL; |
@@ -318,6 +305,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name) | |||
318 | tomoyo_allocated_memory_for_savename += allocated_len; | 305 | tomoyo_allocated_memory_for_savename += allocated_len; |
319 | ptr->entry.name = ((char *) ptr) + sizeof(*ptr); | 306 | ptr->entry.name = ((char *) ptr) + sizeof(*ptr); |
320 | memmove((char *) ptr->entry.name, name, len); | 307 | memmove((char *) ptr->entry.name, name, len); |
308 | atomic_set(&ptr->users, 1); | ||
321 | tomoyo_fill_path_info(&ptr->entry); | 309 | tomoyo_fill_path_info(&ptr->entry); |
322 | list_add_tail(&ptr->list, head); | 310 | list_add_tail(&ptr->list, head); |
323 | out: | 311 | out: |
@@ -336,7 +324,7 @@ void __init tomoyo_realpath_init(void) | |||
336 | for (i = 0; i < TOMOYO_MAX_HASH; i++) | 324 | for (i = 0; i < TOMOYO_MAX_HASH; i++) |
337 | INIT_LIST_HEAD(&tomoyo_name_list[i]); | 325 | INIT_LIST_HEAD(&tomoyo_name_list[i]); |
338 | INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); | 326 | INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); |
339 | tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME); | 327 | tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); |
340 | /* | 328 | /* |
341 | * tomoyo_read_lock() is not needed because this function is | 329 | * tomoyo_read_lock() is not needed because this function is |
342 | * called before the first "delete" request. | 330 | * called before the first "delete" request. |
diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h index da4f06ff6f8d..b94cb512adb5 100644 --- a/security/tomoyo/realpath.h +++ b/security/tomoyo/realpath.h | |||
@@ -43,7 +43,7 @@ bool tomoyo_memory_ok(void *ptr); | |||
43 | * Keep the given name on the RAM. | 43 | * Keep the given name on the RAM. |
44 | * The RAM is shared, so NEVER try to modify or kfree() the returned name. | 44 | * The RAM is shared, so NEVER try to modify or kfree() the returned name. |
45 | */ | 45 | */ |
46 | const struct tomoyo_path_info *tomoyo_save_name(const char *name); | 46 | const struct tomoyo_path_info *tomoyo_get_name(const char *name); |
47 | 47 | ||
48 | /* Check for memory usage. */ | 48 | /* Check for memory usage. */ |
49 | int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); | 49 | int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); |
@@ -54,4 +54,23 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); | |||
54 | /* Initialize realpath related code. */ | 54 | /* Initialize realpath related code. */ |
55 | void __init tomoyo_realpath_init(void); | 55 | void __init tomoyo_realpath_init(void); |
56 | 56 | ||
57 | /* | ||
58 | * tomoyo_name_entry is a structure which is used for linking | ||
59 | * "struct tomoyo_path_info" into tomoyo_name_list . | ||
60 | */ | ||
61 | struct tomoyo_name_entry { | ||
62 | struct list_head list; | ||
63 | atomic_t users; | ||
64 | struct tomoyo_path_info entry; | ||
65 | }; | ||
66 | |||
67 | static inline void tomoyo_put_name(const struct tomoyo_path_info *name) | ||
68 | { | ||
69 | if (name) { | ||
70 | struct tomoyo_name_entry *ptr = | ||
71 | container_of(name, struct tomoyo_name_entry, entry); | ||
72 | atomic_dec(&ptr->users); | ||
73 | } | ||
74 | } | ||
75 | |||
57 | #endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */ | 76 | #endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */ |