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 | ||