diff options
| -rw-r--r-- | security/tomoyo/common.c | 28 | ||||
| -rw-r--r-- | security/tomoyo/domain.c | 147 | ||||
| -rw-r--r-- | security/tomoyo/file.c | 234 |
3 files changed, 183 insertions, 226 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ae3ed7313ee0..a53ee059da48 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
| @@ -1103,10 +1103,10 @@ static LIST_HEAD(tomoyo_policy_manager_list); | |||
| 1103 | static int tomoyo_update_manager_entry(const char *manager, | 1103 | static int tomoyo_update_manager_entry(const char *manager, |
| 1104 | const bool is_delete) | 1104 | const bool is_delete) |
| 1105 | { | 1105 | { |
| 1106 | struct tomoyo_policy_manager_entry *new_entry; | 1106 | struct tomoyo_policy_manager_entry *entry = NULL; |
| 1107 | struct tomoyo_policy_manager_entry *ptr; | 1107 | struct tomoyo_policy_manager_entry *ptr; |
| 1108 | const struct tomoyo_path_info *saved_manager; | 1108 | const struct tomoyo_path_info *saved_manager; |
| 1109 | int error = -ENOMEM; | 1109 | int error = is_delete ? -ENOENT : -ENOMEM; |
| 1110 | bool is_domain = false; | 1110 | bool is_domain = false; |
| 1111 | 1111 | ||
| 1112 | if (tomoyo_is_domain_def(manager)) { | 1112 | if (tomoyo_is_domain_def(manager)) { |
| @@ -1120,29 +1120,25 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
| 1120 | saved_manager = tomoyo_save_name(manager); | 1120 | saved_manager = tomoyo_save_name(manager); |
| 1121 | if (!saved_manager) | 1121 | if (!saved_manager) |
| 1122 | return -ENOMEM; | 1122 | return -ENOMEM; |
| 1123 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | 1123 | if (!is_delete) |
| 1124 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
| 1124 | mutex_lock(&tomoyo_policy_lock); | 1125 | mutex_lock(&tomoyo_policy_lock); |
| 1125 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { | 1126 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { |
| 1126 | if (ptr->manager != saved_manager) | 1127 | if (ptr->manager != saved_manager) |
| 1127 | continue; | 1128 | continue; |
| 1128 | ptr->is_deleted = is_delete; | 1129 | ptr->is_deleted = is_delete; |
| 1129 | error = 0; | 1130 | error = 0; |
| 1130 | goto out; | 1131 | break; |
| 1131 | } | 1132 | } |
| 1132 | if (is_delete) { | 1133 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
| 1133 | error = -ENOENT; | 1134 | entry->manager = saved_manager; |
| 1134 | goto out; | 1135 | entry->is_domain = is_domain; |
| 1136 | list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); | ||
| 1137 | entry = NULL; | ||
| 1138 | error = 0; | ||
| 1135 | } | 1139 | } |
| 1136 | if (!tomoyo_memory_ok(new_entry)) | ||
| 1137 | goto out; | ||
| 1138 | new_entry->manager = saved_manager; | ||
| 1139 | new_entry->is_domain = is_domain; | ||
| 1140 | list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); | ||
| 1141 | new_entry = NULL; | ||
| 1142 | error = 0; | ||
| 1143 | out: | ||
| 1144 | mutex_unlock(&tomoyo_policy_lock); | 1140 | mutex_unlock(&tomoyo_policy_lock); |
| 1145 | kfree(new_entry); | 1141 | kfree(entry); |
| 1146 | return error; | 1142 | return error; |
| 1147 | } | 1143 | } |
| 1148 | 1144 | ||
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 | /** |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 84c821a245ca..f4a27714e077 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
| @@ -215,38 +215,34 @@ static LIST_HEAD(tomoyo_globally_readable_list); | |||
| 215 | static int tomoyo_update_globally_readable_entry(const char *filename, | 215 | static int tomoyo_update_globally_readable_entry(const char *filename, |
| 216 | const bool is_delete) | 216 | const bool is_delete) |
| 217 | { | 217 | { |
| 218 | struct tomoyo_globally_readable_file_entry *new_entry; | 218 | struct tomoyo_globally_readable_file_entry *entry = NULL; |
| 219 | struct tomoyo_globally_readable_file_entry *ptr; | 219 | struct tomoyo_globally_readable_file_entry *ptr; |
| 220 | const struct tomoyo_path_info *saved_filename; | 220 | const struct tomoyo_path_info *saved_filename; |
| 221 | int error = -ENOMEM; | 221 | int error = is_delete ? -ENOENT : -ENOMEM; |
| 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_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 | if (!is_delete) |
| 229 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
| 229 | mutex_lock(&tomoyo_policy_lock); | 230 | mutex_lock(&tomoyo_policy_lock); |
| 230 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { | 231 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { |
| 231 | if (ptr->filename != saved_filename) | 232 | if (ptr->filename != saved_filename) |
| 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->filename = saved_filename; |
| 239 | goto out; | 240 | list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); |
| 241 | entry = NULL; | ||
| 242 | error = 0; | ||
| 240 | } | 243 | } |
| 241 | if (!tomoyo_memory_ok(new_entry)) | ||
| 242 | goto out; | ||
| 243 | new_entry->filename = saved_filename; | ||
| 244 | list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); | ||
| 245 | new_entry = NULL; | ||
| 246 | error = 0; | ||
| 247 | out: | ||
| 248 | mutex_unlock(&tomoyo_policy_lock); | 244 | mutex_unlock(&tomoyo_policy_lock); |
| 249 | kfree(new_entry); | 245 | kfree(entry); |
| 250 | return error; | 246 | return error; |
| 251 | } | 247 | } |
| 252 | 248 | ||
| @@ -364,38 +360,35 @@ static LIST_HEAD(tomoyo_pattern_list); | |||
| 364 | static int tomoyo_update_file_pattern_entry(const char *pattern, | 360 | static int tomoyo_update_file_pattern_entry(const char *pattern, |
| 365 | const bool is_delete) | 361 | const bool is_delete) |
| 366 | { | 362 | { |
| 367 | struct tomoyo_pattern_entry *new_entry; | 363 | struct tomoyo_pattern_entry *entry = NULL; |
| 368 | struct tomoyo_pattern_entry *ptr; | 364 | struct tomoyo_pattern_entry *ptr; |
| 369 | const struct tomoyo_path_info *saved_pattern; | 365 | const struct tomoyo_path_info *saved_pattern; |
| 370 | int error = -ENOMEM; | 366 | int error = is_delete ? -ENOENT : -ENOMEM; |
| 371 | 367 | ||
| 372 | if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__)) | ||
| 373 | return -EINVAL; | ||
| 374 | saved_pattern = tomoyo_save_name(pattern); | 368 | saved_pattern = tomoyo_save_name(pattern); |
| 375 | if (!saved_pattern) | 369 | if (!saved_pattern) |
| 376 | return -ENOMEM; | 370 | return error; |
| 377 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | 371 | if (!saved_pattern->is_patterned) |
| 372 | goto out; | ||
| 373 | if (!is_delete) | ||
| 374 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
| 378 | mutex_lock(&tomoyo_policy_lock); | 375 | mutex_lock(&tomoyo_policy_lock); |
| 379 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { | 376 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { |
| 380 | if (saved_pattern != ptr->pattern) | 377 | if (saved_pattern != ptr->pattern) |
| 381 | continue; | 378 | continue; |
| 382 | ptr->is_deleted = is_delete; | 379 | ptr->is_deleted = is_delete; |
| 383 | error = 0; | 380 | error = 0; |
| 384 | goto out; | 381 | break; |
| 385 | } | 382 | } |
| 386 | if (is_delete) { | 383 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
| 387 | error = -ENOENT; | 384 | entry->pattern = saved_pattern; |
| 388 | goto out; | 385 | list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); |
| 386 | entry = NULL; | ||
| 387 | error = 0; | ||
| 389 | } | 388 | } |
| 390 | if (!tomoyo_memory_ok(new_entry)) | ||
| 391 | goto out; | ||
| 392 | new_entry->pattern = saved_pattern; | ||
| 393 | list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); | ||
| 394 | new_entry = NULL; | ||
| 395 | error = 0; | ||
| 396 | out: | ||
| 397 | mutex_unlock(&tomoyo_policy_lock); | 389 | mutex_unlock(&tomoyo_policy_lock); |
| 398 | kfree(new_entry); | 390 | out: |
| 391 | kfree(entry); | ||
| 399 | return error; | 392 | return error; |
| 400 | } | 393 | } |
| 401 | 394 | ||
| @@ -518,37 +511,34 @@ static LIST_HEAD(tomoyo_no_rewrite_list); | |||
| 518 | static int tomoyo_update_no_rewrite_entry(const char *pattern, | 511 | static int tomoyo_update_no_rewrite_entry(const char *pattern, |
| 519 | const bool is_delete) | 512 | const bool is_delete) |
| 520 | { | 513 | { |
| 521 | struct tomoyo_no_rewrite_entry *new_entry, *ptr; | 514 | struct tomoyo_no_rewrite_entry *entry = NULL; |
| 515 | struct tomoyo_no_rewrite_entry *ptr; | ||
| 522 | const struct tomoyo_path_info *saved_pattern; | 516 | const struct tomoyo_path_info *saved_pattern; |
| 523 | int error = -ENOMEM; | 517 | int error = is_delete ? -ENOENT : -ENOMEM; |
| 524 | 518 | ||
| 525 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) | 519 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) |
| 526 | return -EINVAL; | 520 | return -EINVAL; |
| 527 | saved_pattern = tomoyo_save_name(pattern); | 521 | saved_pattern = tomoyo_save_name(pattern); |
| 528 | if (!saved_pattern) | 522 | if (!saved_pattern) |
| 529 | return -ENOMEM; | 523 | return error; |
| 530 | new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); | 524 | if (!is_delete) |
| 525 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
| 531 | mutex_lock(&tomoyo_policy_lock); | 526 | mutex_lock(&tomoyo_policy_lock); |
| 532 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { | 527 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { |
| 533 | if (ptr->pattern != saved_pattern) | 528 | if (ptr->pattern != saved_pattern) |
| 534 | continue; | 529 | continue; |
| 535 | ptr->is_deleted = is_delete; | 530 | ptr->is_deleted = is_delete; |
| 536 | error = 0; | 531 | error = 0; |
| 537 | goto out; | 532 | break; |
| 538 | } | 533 | } |
| 539 | if (is_delete) { | 534 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
| 540 | error = -ENOENT; | 535 | entry->pattern = saved_pattern; |
| 541 | goto out; | 536 | list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); |
| 537 | entry = NULL; | ||
| 538 | error = 0; | ||
| 542 | } | 539 | } |
| 543 | if (!tomoyo_memory_ok(new_entry)) | ||
| 544 | goto out; | ||
| 545 | new_entry->pattern = saved_pattern; | ||
| 546 | list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); | ||
| 547 | new_entry = NULL; | ||
| 548 | error = 0; | ||
| 549 | out: | ||
| 550 | mutex_unlock(&tomoyo_policy_lock); | 540 | mutex_unlock(&tomoyo_policy_lock); |
| 551 | kfree(new_entry); | 541 | kfree(entry); |
| 552 | return error; | 542 | return error; |
| 553 | } | 543 | } |
| 554 | 544 | ||
| @@ -869,8 +859,8 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
| 869 | (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL); | 859 | (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL); |
| 870 | const struct tomoyo_path_info *saved_filename; | 860 | const struct tomoyo_path_info *saved_filename; |
| 871 | struct tomoyo_acl_info *ptr; | 861 | struct tomoyo_acl_info *ptr; |
| 872 | struct tomoyo_single_path_acl_record *acl; | 862 | struct tomoyo_single_path_acl_record *entry = NULL; |
| 873 | int error = -ENOMEM; | 863 | int error = is_delete ? -ENOENT : -ENOMEM; |
| 874 | const u32 perm = 1 << type; | 864 | const u32 perm = 1 << type; |
| 875 | 865 | ||
| 876 | if (!domain) | 866 | if (!domain) |
| @@ -880,67 +870,55 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
| 880 | saved_filename = tomoyo_save_name(filename); | 870 | saved_filename = tomoyo_save_name(filename); |
| 881 | if (!saved_filename) | 871 | if (!saved_filename) |
| 882 | return -ENOMEM; | 872 | return -ENOMEM; |
| 873 | if (!is_delete) | ||
| 874 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
| 883 | mutex_lock(&tomoyo_policy_lock); | 875 | mutex_lock(&tomoyo_policy_lock); |
| 884 | if (is_delete) | ||
| 885 | goto delete; | ||
| 886 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 876 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
| 877 | struct tomoyo_single_path_acl_record *acl = | ||
| 878 | container_of(ptr, struct tomoyo_single_path_acl_record, | ||
| 879 | head); | ||
| 887 | if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) | 880 | if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) |
| 888 | continue; | 881 | continue; |
| 889 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | ||
| 890 | head); | ||
| 891 | if (acl->filename != saved_filename) | 882 | if (acl->filename != saved_filename) |
| 892 | continue; | 883 | continue; |
| 893 | if (perm <= 0xFFFF) | 884 | if (is_delete) { |
| 894 | acl->perm |= perm; | 885 | if (perm <= 0xFFFF) |
| 895 | else | 886 | acl->perm &= ~perm; |
| 896 | acl->perm_high |= (perm >> 16); | 887 | else |
| 897 | if ((acl->perm & rw_mask) == rw_mask) | 888 | acl->perm_high &= ~(perm >> 16); |
| 898 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; | 889 | if ((acl->perm & rw_mask) != rw_mask) |
| 899 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | 890 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); |
| 900 | acl->perm |= rw_mask; | 891 | else if (!(acl->perm & |
| 892 | (1 << TOMOYO_TYPE_READ_WRITE_ACL))) | ||
| 893 | acl->perm &= ~rw_mask; | ||
| 894 | } else { | ||
| 895 | if (perm <= 0xFFFF) | ||
| 896 | acl->perm |= perm; | ||
| 897 | else | ||
| 898 | acl->perm_high |= (perm >> 16); | ||
| 899 | if ((acl->perm & rw_mask) == rw_mask) | ||
| 900 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; | ||
| 901 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | ||
| 902 | acl->perm |= rw_mask; | ||
| 903 | } | ||
| 901 | error = 0; | 904 | error = 0; |
| 902 | goto out; | 905 | break; |
| 903 | } | ||
| 904 | /* Not found. Append it to the tail. */ | ||
| 905 | acl = kmalloc(sizeof(*acl), GFP_KERNEL); | ||
| 906 | if (!tomoyo_memory_ok(acl)) { | ||
| 907 | kfree(acl); | ||
| 908 | acl = NULL; | ||
| 909 | goto out; | ||
| 910 | } | 906 | } |
| 911 | acl->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; | 907 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
| 912 | if (perm <= 0xFFFF) | 908 | entry->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL; |
| 913 | acl->perm = perm; | ||
| 914 | else | ||
| 915 | acl->perm_high = (perm >> 16); | ||
| 916 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | ||
| 917 | acl->perm |= rw_mask; | ||
| 918 | acl->filename = saved_filename; | ||
| 919 | list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); | ||
| 920 | error = 0; | ||
| 921 | goto out; | ||
| 922 | delete: | ||
| 923 | error = -ENOENT; | ||
| 924 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | ||
| 925 | if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL) | ||
| 926 | continue; | ||
| 927 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | ||
| 928 | head); | ||
| 929 | if (acl->filename != saved_filename) | ||
| 930 | continue; | ||
| 931 | if (perm <= 0xFFFF) | 909 | if (perm <= 0xFFFF) |
| 932 | acl->perm &= ~perm; | 910 | entry->perm = perm; |
| 933 | else | 911 | else |
| 934 | acl->perm_high &= ~(perm >> 16); | 912 | entry->perm_high = (perm >> 16); |
| 935 | if ((acl->perm & rw_mask) != rw_mask) | 913 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) |
| 936 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); | 914 | entry->perm |= rw_mask; |
| 937 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) | 915 | entry->filename = saved_filename; |
| 938 | acl->perm &= ~rw_mask; | 916 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); |
| 917 | entry = NULL; | ||
| 939 | error = 0; | 918 | error = 0; |
| 940 | break; | ||
| 941 | } | 919 | } |
| 942 | out: | ||
| 943 | mutex_unlock(&tomoyo_policy_lock); | 920 | mutex_unlock(&tomoyo_policy_lock); |
| 921 | kfree(entry); | ||
| 944 | return error; | 922 | return error; |
| 945 | } | 923 | } |
| 946 | 924 | ||
| @@ -965,8 +943,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
| 965 | const struct tomoyo_path_info *saved_filename1; | 943 | const struct tomoyo_path_info *saved_filename1; |
| 966 | const struct tomoyo_path_info *saved_filename2; | 944 | const struct tomoyo_path_info *saved_filename2; |
| 967 | struct tomoyo_acl_info *ptr; | 945 | struct tomoyo_acl_info *ptr; |
| 968 | struct tomoyo_double_path_acl_record *acl; | 946 | struct tomoyo_double_path_acl_record *entry = NULL; |
| 969 | int error = -ENOMEM; | 947 | int error = is_delete ? -ENOENT : -ENOMEM; |
| 970 | const u8 perm = 1 << type; | 948 | const u8 perm = 1 << type; |
| 971 | 949 | ||
| 972 | if (!domain) | 950 | if (!domain) |
| @@ -977,52 +955,38 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
| 977 | saved_filename1 = tomoyo_save_name(filename1); | 955 | saved_filename1 = tomoyo_save_name(filename1); |
| 978 | saved_filename2 = tomoyo_save_name(filename2); | 956 | saved_filename2 = tomoyo_save_name(filename2); |
| 979 | if (!saved_filename1 || !saved_filename2) | 957 | if (!saved_filename1 || !saved_filename2) |
| 980 | return -ENOMEM; | 958 | goto out; |
| 959 | if (!is_delete) | ||
| 960 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
| 981 | mutex_lock(&tomoyo_policy_lock); | 961 | mutex_lock(&tomoyo_policy_lock); |
| 982 | if (is_delete) | ||
| 983 | goto delete; | ||
| 984 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 962 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
| 963 | struct tomoyo_double_path_acl_record *acl = | ||
| 964 | container_of(ptr, struct tomoyo_double_path_acl_record, | ||
| 965 | head); | ||
| 985 | if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) | 966 | if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) |
| 986 | continue; | 967 | continue; |
| 987 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | ||
| 988 | head); | ||
| 989 | if (acl->filename1 != saved_filename1 || | 968 | if (acl->filename1 != saved_filename1 || |
| 990 | acl->filename2 != saved_filename2) | 969 | acl->filename2 != saved_filename2) |
| 991 | continue; | 970 | continue; |
| 992 | acl->perm |= perm; | 971 | if (is_delete) |
| 972 | acl->perm &= ~perm; | ||
| 973 | else | ||
| 974 | acl->perm |= perm; | ||
| 993 | error = 0; | 975 | error = 0; |
| 994 | goto out; | 976 | break; |
| 995 | } | ||
| 996 | /* Not found. Append it to the tail. */ | ||
| 997 | acl = kmalloc(sizeof(*acl), GFP_KERNEL); | ||
| 998 | if (!tomoyo_memory_ok(acl)) { | ||
| 999 | kfree(acl); | ||
| 1000 | acl = NULL; | ||
| 1001 | goto out; | ||
| 1002 | } | 977 | } |
| 1003 | acl->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; | 978 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
| 1004 | acl->perm = perm; | 979 | entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL; |
| 1005 | acl->filename1 = saved_filename1; | 980 | entry->perm = perm; |
| 1006 | acl->filename2 = saved_filename2; | 981 | entry->filename1 = saved_filename1; |
| 1007 | list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); | 982 | entry->filename2 = saved_filename2; |
| 1008 | error = 0; | 983 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); |
| 1009 | goto out; | 984 | entry = NULL; |
| 1010 | delete: | ||
| 1011 | error = -ENOENT; | ||
| 1012 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | ||
| 1013 | if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL) | ||
| 1014 | continue; | ||
| 1015 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | ||
| 1016 | head); | ||
| 1017 | if (acl->filename1 != saved_filename1 || | ||
| 1018 | acl->filename2 != saved_filename2) | ||
| 1019 | continue; | ||
| 1020 | acl->perm &= ~perm; | ||
| 1021 | error = 0; | 985 | error = 0; |
| 1022 | break; | ||
| 1023 | } | 986 | } |
| 1024 | out: | ||
| 1025 | mutex_unlock(&tomoyo_policy_lock); | 987 | mutex_unlock(&tomoyo_policy_lock); |
| 988 | out: | ||
| 989 | kfree(entry); | ||
| 1026 | return error; | 990 | return error; |
| 1027 | } | 991 | } |
| 1028 | 992 | ||
