diff options
Diffstat (limited to 'security/tomoyo/domain.c')
-rw-r--r-- | security/tomoyo/domain.c | 147 |
1 files changed, 72 insertions, 75 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index ec612ae87b51..229de1e71a38 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -201,11 +201,11 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
201 | const bool is_not, | 201 | const bool is_not, |
202 | const bool is_delete) | 202 | const bool is_delete) |
203 | { | 203 | { |
204 | struct tomoyo_domain_initializer_entry *new_entry; | 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; |
207 | const struct tomoyo_path_info *saved_domainname = NULL; | 207 | const struct tomoyo_path_info *saved_domainname = NULL; |
208 | int error = -ENOMEM; | 208 | int error = is_delete ? -ENOENT : -ENOMEM; |
209 | bool is_last_name = false; | 209 | bool is_last_name = false; |
210 | 210 | ||
211 | if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) | 211 | if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) |
@@ -218,12 +218,13 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
218 | return -EINVAL; | 218 | return -EINVAL; |
219 | saved_domainname = tomoyo_save_name(domainname); | 219 | saved_domainname = tomoyo_save_name(domainname); |
220 | if (!saved_domainname) | 220 | if (!saved_domainname) |
221 | return -ENOMEM; | 221 | goto out; |
222 | } | 222 | } |
223 | saved_program = tomoyo_save_name(program); | 223 | saved_program = tomoyo_save_name(program); |
224 | if (!saved_program) | 224 | if (!saved_program) |
225 | return -ENOMEM; | 225 | goto out; |
226 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | 226 | if (!is_delete) |
227 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
227 | mutex_lock(&tomoyo_policy_lock); | 228 | mutex_lock(&tomoyo_policy_lock); |
228 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { | 229 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { |
229 | if (ptr->is_not != is_not || | 230 | if (ptr->is_not != is_not || |
@@ -232,24 +233,21 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
232 | continue; | 233 | continue; |
233 | ptr->is_deleted = is_delete; | 234 | ptr->is_deleted = is_delete; |
234 | error = 0; | 235 | error = 0; |
235 | goto out; | 236 | break; |
236 | } | 237 | } |
237 | if (is_delete) { | 238 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
238 | error = -ENOENT; | 239 | entry->domainname = saved_domainname; |
239 | goto out; | 240 | entry->program = saved_program; |
241 | entry->is_not = is_not; | ||
242 | entry->is_last_name = is_last_name; | ||
243 | list_add_tail_rcu(&entry->list, | ||
244 | &tomoyo_domain_initializer_list); | ||
245 | entry = NULL; | ||
246 | error = 0; | ||
240 | } | 247 | } |
241 | if (!tomoyo_memory_ok(new_entry)) | ||
242 | goto out; | ||
243 | new_entry->domainname = saved_domainname; | ||
244 | new_entry->program = saved_program; | ||
245 | new_entry->is_not = is_not; | ||
246 | new_entry->is_last_name = is_last_name; | ||
247 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); | ||
248 | new_entry = NULL; | ||
249 | error = 0; | ||
250 | out: | ||
251 | mutex_unlock(&tomoyo_policy_lock); | 248 | mutex_unlock(&tomoyo_policy_lock); |
252 | kfree(new_entry); | 249 | out: |
250 | kfree(entry); | ||
253 | return error; | 251 | return error; |
254 | } | 252 | } |
255 | 253 | ||
@@ -419,11 +417,11 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
419 | const bool is_not, | 417 | const bool is_not, |
420 | const bool is_delete) | 418 | const bool is_delete) |
421 | { | 419 | { |
422 | struct tomoyo_domain_keeper_entry *new_entry; | 420 | struct tomoyo_domain_keeper_entry *entry = NULL; |
423 | struct tomoyo_domain_keeper_entry *ptr; | 421 | struct tomoyo_domain_keeper_entry *ptr; |
424 | const struct tomoyo_path_info *saved_domainname; | 422 | const struct tomoyo_path_info *saved_domainname; |
425 | const struct tomoyo_path_info *saved_program = NULL; | 423 | const struct tomoyo_path_info *saved_program = NULL; |
426 | int error = -ENOMEM; | 424 | int error = is_delete ? -ENOENT : -ENOMEM; |
427 | bool is_last_name = false; | 425 | bool is_last_name = false; |
428 | 426 | ||
429 | if (!tomoyo_is_domain_def(domainname) && | 427 | if (!tomoyo_is_domain_def(domainname) && |
@@ -436,12 +434,13 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
436 | return -EINVAL; | 434 | return -EINVAL; |
437 | saved_program = tomoyo_save_name(program); | 435 | saved_program = tomoyo_save_name(program); |
438 | if (!saved_program) | 436 | if (!saved_program) |
439 | return -ENOMEM; | 437 | goto out; |
440 | } | 438 | } |
441 | saved_domainname = tomoyo_save_name(domainname); | 439 | saved_domainname = tomoyo_save_name(domainname); |
442 | if (!saved_domainname) | 440 | if (!saved_domainname) |
443 | return -ENOMEM; | 441 | goto out; |
444 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | 442 | if (!is_delete) |
443 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
445 | mutex_lock(&tomoyo_policy_lock); | 444 | mutex_lock(&tomoyo_policy_lock); |
446 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { | 445 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { |
447 | if (ptr->is_not != is_not || | 446 | if (ptr->is_not != is_not || |
@@ -450,24 +449,20 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
450 | continue; | 449 | continue; |
451 | ptr->is_deleted = is_delete; | 450 | ptr->is_deleted = is_delete; |
452 | error = 0; | 451 | error = 0; |
453 | goto out; | 452 | break; |
454 | } | 453 | } |
455 | if (is_delete) { | 454 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
456 | error = -ENOENT; | 455 | entry->domainname = saved_domainname; |
457 | goto out; | 456 | entry->program = saved_program; |
457 | entry->is_not = is_not; | ||
458 | entry->is_last_name = is_last_name; | ||
459 | list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); | ||
460 | entry = NULL; | ||
461 | error = 0; | ||
458 | } | 462 | } |
459 | if (!tomoyo_memory_ok(new_entry)) | ||
460 | goto out; | ||
461 | new_entry->domainname = saved_domainname; | ||
462 | new_entry->program = saved_program; | ||
463 | new_entry->is_not = is_not; | ||
464 | new_entry->is_last_name = is_last_name; | ||
465 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); | ||
466 | new_entry = NULL; | ||
467 | error = 0; | ||
468 | out: | ||
469 | mutex_unlock(&tomoyo_policy_lock); | 463 | mutex_unlock(&tomoyo_policy_lock); |
470 | kfree(new_entry); | 464 | out: |
465 | kfree(entry); | ||
471 | return error; | 466 | return error; |
472 | } | 467 | } |
473 | 468 | ||
@@ -619,11 +614,11 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
619 | const char *aliased_name, | 614 | const char *aliased_name, |
620 | const bool is_delete) | 615 | const bool is_delete) |
621 | { | 616 | { |
622 | struct tomoyo_alias_entry *new_entry; | 617 | struct tomoyo_alias_entry *entry = NULL; |
623 | struct tomoyo_alias_entry *ptr; | 618 | struct tomoyo_alias_entry *ptr; |
624 | const struct tomoyo_path_info *saved_original_name; | 619 | const struct tomoyo_path_info *saved_original_name; |
625 | const struct tomoyo_path_info *saved_aliased_name; | 620 | const struct tomoyo_path_info *saved_aliased_name; |
626 | int error = -ENOMEM; | 621 | int error = is_delete ? -ENOENT : -ENOMEM; |
627 | 622 | ||
628 | if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || | 623 | if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || |
629 | !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) | 624 | !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) |
@@ -631,8 +626,9 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
631 | saved_original_name = tomoyo_save_name(original_name); | 626 | saved_original_name = tomoyo_save_name(original_name); |
632 | saved_aliased_name = tomoyo_save_name(aliased_name); | 627 | saved_aliased_name = tomoyo_save_name(aliased_name); |
633 | if (!saved_original_name || !saved_aliased_name) | 628 | if (!saved_original_name || !saved_aliased_name) |
634 | return -ENOMEM; | 629 | goto out; |
635 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | 630 | if (!is_delete) |
631 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
636 | mutex_lock(&tomoyo_policy_lock); | 632 | mutex_lock(&tomoyo_policy_lock); |
637 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { | 633 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { |
638 | if (ptr->original_name != saved_original_name || | 634 | if (ptr->original_name != saved_original_name || |
@@ -640,22 +636,18 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
640 | continue; | 636 | continue; |
641 | ptr->is_deleted = is_delete; | 637 | ptr->is_deleted = is_delete; |
642 | error = 0; | 638 | error = 0; |
643 | goto out; | 639 | break; |
644 | } | 640 | } |
645 | if (is_delete) { | 641 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
646 | error = -ENOENT; | 642 | entry->original_name = saved_original_name; |
647 | goto out; | 643 | entry->aliased_name = saved_aliased_name; |
644 | list_add_tail_rcu(&entry->list, &tomoyo_alias_list); | ||
645 | entry = NULL; | ||
646 | error = 0; | ||
648 | } | 647 | } |
649 | if (!tomoyo_memory_ok(new_entry)) | ||
650 | goto out; | ||
651 | new_entry->original_name = saved_original_name; | ||
652 | new_entry->aliased_name = saved_aliased_name; | ||
653 | list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); | ||
654 | new_entry = NULL; | ||
655 | error = 0; | ||
656 | out: | ||
657 | mutex_unlock(&tomoyo_policy_lock); | 648 | mutex_unlock(&tomoyo_policy_lock); |
658 | kfree(new_entry); | 649 | out: |
650 | kfree(entry); | ||
659 | return error; | 651 | return error; |
660 | } | 652 | } |
661 | 653 | ||
@@ -722,32 +714,37 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
722 | domainname, | 714 | domainname, |
723 | const u8 profile) | 715 | const u8 profile) |
724 | { | 716 | { |
717 | struct tomoyo_domain_info *entry; | ||
725 | struct tomoyo_domain_info *domain; | 718 | struct tomoyo_domain_info *domain; |
726 | const struct tomoyo_path_info *saved_domainname; | 719 | const struct tomoyo_path_info *saved_domainname; |
720 | bool found = false; | ||
727 | 721 | ||
728 | mutex_lock(&tomoyo_policy_lock); | ||
729 | domain = tomoyo_find_domain(domainname); | ||
730 | if (domain) | ||
731 | goto out; | ||
732 | if (!tomoyo_is_correct_domain(domainname, __func__)) | 722 | if (!tomoyo_is_correct_domain(domainname, __func__)) |
733 | goto out; | 723 | return NULL; |
734 | saved_domainname = tomoyo_save_name(domainname); | 724 | saved_domainname = tomoyo_save_name(domainname); |
735 | if (!saved_domainname) | 725 | if (!saved_domainname) |
736 | goto out; | 726 | return NULL; |
737 | domain = kmalloc(sizeof(*domain), GFP_KERNEL); | 727 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
738 | if (tomoyo_memory_ok(domain)) { | 728 | mutex_lock(&tomoyo_policy_lock); |
739 | INIT_LIST_HEAD(&domain->acl_info_list); | 729 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
740 | domain->domainname = saved_domainname; | 730 | if (domain->is_deleted || |
741 | domain->profile = profile; | 731 | tomoyo_pathcmp(saved_domainname, domain->domainname)) |
742 | list_add_tail_rcu(&domain->list, &tomoyo_domain_list); | 732 | continue; |
743 | } else { | 733 | found = true; |
744 | kfree(domain); | 734 | break; |
745 | domain = NULL; | 735 | } |
736 | if (!found && tomoyo_memory_ok(entry)) { | ||
737 | INIT_LIST_HEAD(&entry->acl_info_list); | ||
738 | entry->domainname = saved_domainname; | ||
739 | entry->profile = profile; | ||
740 | list_add_tail_rcu(&entry->list, &tomoyo_domain_list); | ||
741 | domain = entry; | ||
742 | entry = NULL; | ||
743 | found = true; | ||
746 | } | 744 | } |
747 | |||
748 | out: | ||
749 | mutex_unlock(&tomoyo_policy_lock); | 745 | mutex_unlock(&tomoyo_policy_lock); |
750 | return domain; | 746 | kfree(entry); |
747 | return found ? domain : NULL; | ||
751 | } | 748 | } |
752 | 749 | ||
753 | /** | 750 | /** |