diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2010-06-14 20:23:26 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-08-02 01:34:29 -0400 |
commit | 36f5e1ffbf2bb951105ae4e261bcc1de3eaf510c (patch) | |
tree | 80e01278296477b4d30288081267d35ff771d720 /security/tomoyo/domain.c | |
parent | 82e0f001a4c1112dcff9cafa9812a33889ad9b8a (diff) |
TOMOYO: Use callback for updating entries.
Use common code for elements using "struct list_head" + "bool" structure.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo/domain.c')
-rw-r--r-- | security/tomoyo/domain.c | 184 |
1 files changed, 103 insertions, 81 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 60297da6adcf..fe621af46c2e 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -16,6 +16,49 @@ | |||
16 | struct tomoyo_domain_info tomoyo_kernel_domain; | 16 | struct tomoyo_domain_info tomoyo_kernel_domain; |
17 | 17 | ||
18 | /** | 18 | /** |
19 | * tomoyo_update_policy - Update an entry for exception policy. | ||
20 | * | ||
21 | * @new_entry: Pointer to "struct tomoyo_acl_info". | ||
22 | * @size: Size of @new_entry in bytes. | ||
23 | * @is_delete: True if it is a delete request. | ||
24 | * @list: Pointer to "struct list_head". | ||
25 | * @check_duplicate: Callback function to find duplicated entry. | ||
26 | * | ||
27 | * Returns 0 on success, negative value otherwise. | ||
28 | * | ||
29 | * Caller holds tomoyo_read_lock(). | ||
30 | */ | ||
31 | int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, | ||
32 | bool is_delete, struct list_head *list, | ||
33 | bool (*check_duplicate) (const struct tomoyo_acl_head | ||
34 | *, | ||
35 | const struct tomoyo_acl_head | ||
36 | *)) | ||
37 | { | ||
38 | int error = is_delete ? -ENOENT : -ENOMEM; | ||
39 | struct tomoyo_acl_head *entry; | ||
40 | |||
41 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
42 | return -ENOMEM; | ||
43 | list_for_each_entry_rcu(entry, list, list) { | ||
44 | if (!check_duplicate(entry, new_entry)) | ||
45 | continue; | ||
46 | entry->is_deleted = is_delete; | ||
47 | error = 0; | ||
48 | break; | ||
49 | } | ||
50 | if (error && !is_delete) { | ||
51 | entry = tomoyo_commit_ok(new_entry, size); | ||
52 | if (entry) { | ||
53 | list_add_tail_rcu(&entry->list, list); | ||
54 | error = 0; | ||
55 | } | ||
56 | } | ||
57 | mutex_unlock(&tomoyo_policy_lock); | ||
58 | return error; | ||
59 | } | ||
60 | |||
61 | /** | ||
19 | * tomoyo_update_domain - Update an entry for domain policy. | 62 | * tomoyo_update_domain - Update an entry for domain policy. |
20 | * | 63 | * |
21 | * @new_entry: Pointer to "struct tomoyo_acl_info". | 64 | * @new_entry: Pointer to "struct tomoyo_acl_info". |
@@ -161,6 +204,20 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) | |||
161 | */ | 204 | */ |
162 | LIST_HEAD(tomoyo_domain_initializer_list); | 205 | LIST_HEAD(tomoyo_domain_initializer_list); |
163 | 206 | ||
207 | static bool tomoyo_same_domain_initializer_entry(const struct tomoyo_acl_head * | ||
208 | a, | ||
209 | const struct tomoyo_acl_head * | ||
210 | b) | ||
211 | { | ||
212 | const struct tomoyo_domain_initializer_entry *p1 = | ||
213 | container_of(a, typeof(*p1), head); | ||
214 | const struct tomoyo_domain_initializer_entry *p2 = | ||
215 | container_of(b, typeof(*p2), head); | ||
216 | return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name | ||
217 | && p1->domainname == p2->domainname | ||
218 | && p1->program == p2->program; | ||
219 | } | ||
220 | |||
164 | /** | 221 | /** |
165 | * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. | 222 | * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. |
166 | * | 223 | * |
@@ -178,7 +235,6 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
178 | const bool is_not, | 235 | const bool is_not, |
179 | const bool is_delete) | 236 | const bool is_delete) |
180 | { | 237 | { |
181 | struct tomoyo_domain_initializer_entry *ptr; | ||
182 | struct tomoyo_domain_initializer_entry e = { .is_not = is_not }; | 238 | struct tomoyo_domain_initializer_entry e = { .is_not = is_not }; |
183 | int error = is_delete ? -ENOENT : -ENOMEM; | 239 | int error = is_delete ? -ENOENT : -ENOMEM; |
184 | 240 | ||
@@ -197,26 +253,9 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
197 | e.program = tomoyo_get_name(program); | 253 | e.program = tomoyo_get_name(program); |
198 | if (!e.program) | 254 | if (!e.program) |
199 | goto out; | 255 | goto out; |
200 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 256 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, |
201 | goto out; | 257 | &tomoyo_domain_initializer_list, |
202 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, | 258 | tomoyo_same_domain_initializer_entry); |
203 | head.list) { | ||
204 | if (!tomoyo_is_same_domain_initializer_entry(ptr, &e)) | ||
205 | continue; | ||
206 | ptr->head.is_deleted = is_delete; | ||
207 | error = 0; | ||
208 | break; | ||
209 | } | ||
210 | if (!is_delete && error) { | ||
211 | struct tomoyo_domain_initializer_entry *entry = | ||
212 | tomoyo_commit_ok(&e, sizeof(e)); | ||
213 | if (entry) { | ||
214 | list_add_tail_rcu(&entry->head.list, | ||
215 | &tomoyo_domain_initializer_list); | ||
216 | error = 0; | ||
217 | } | ||
218 | } | ||
219 | mutex_unlock(&tomoyo_policy_lock); | ||
220 | out: | 259 | out: |
221 | tomoyo_put_name(e.domainname); | 260 | tomoyo_put_name(e.domainname); |
222 | tomoyo_put_name(e.program); | 261 | tomoyo_put_name(e.program); |
@@ -373,6 +412,18 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | |||
373 | */ | 412 | */ |
374 | LIST_HEAD(tomoyo_domain_keeper_list); | 413 | LIST_HEAD(tomoyo_domain_keeper_list); |
375 | 414 | ||
415 | static bool tomoyo_same_domain_keeper_entry(const struct tomoyo_acl_head *a, | ||
416 | const struct tomoyo_acl_head *b) | ||
417 | { | ||
418 | const struct tomoyo_domain_keeper_entry *p1 = | ||
419 | container_of(a, typeof(*p1), head); | ||
420 | const struct tomoyo_domain_keeper_entry *p2 = | ||
421 | container_of(b, typeof(*p2), head); | ||
422 | return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name | ||
423 | && p1->domainname == p2->domainname | ||
424 | && p1->program == p2->program; | ||
425 | } | ||
426 | |||
376 | /** | 427 | /** |
377 | * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. | 428 | * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. |
378 | * | 429 | * |
@@ -390,7 +441,6 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
390 | const bool is_not, | 441 | const bool is_not, |
391 | const bool is_delete) | 442 | const bool is_delete) |
392 | { | 443 | { |
393 | struct tomoyo_domain_keeper_entry *ptr; | ||
394 | struct tomoyo_domain_keeper_entry e = { .is_not = is_not }; | 444 | struct tomoyo_domain_keeper_entry e = { .is_not = is_not }; |
395 | int error = is_delete ? -ENOENT : -ENOMEM; | 445 | int error = is_delete ? -ENOENT : -ENOMEM; |
396 | 446 | ||
@@ -409,25 +459,9 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
409 | e.domainname = tomoyo_get_name(domainname); | 459 | e.domainname = tomoyo_get_name(domainname); |
410 | if (!e.domainname) | 460 | if (!e.domainname) |
411 | goto out; | 461 | goto out; |
412 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 462 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, |
413 | goto out; | 463 | &tomoyo_domain_keeper_list, |
414 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, head.list) { | 464 | tomoyo_same_domain_keeper_entry); |
415 | if (!tomoyo_is_same_domain_keeper_entry(ptr, &e)) | ||
416 | continue; | ||
417 | ptr->head.is_deleted = is_delete; | ||
418 | error = 0; | ||
419 | break; | ||
420 | } | ||
421 | if (!is_delete && error) { | ||
422 | struct tomoyo_domain_keeper_entry *entry = | ||
423 | tomoyo_commit_ok(&e, sizeof(e)); | ||
424 | if (entry) { | ||
425 | list_add_tail_rcu(&entry->head.list, | ||
426 | &tomoyo_domain_keeper_list); | ||
427 | error = 0; | ||
428 | } | ||
429 | } | ||
430 | mutex_unlock(&tomoyo_policy_lock); | ||
431 | out: | 465 | out: |
432 | tomoyo_put_name(e.domainname); | 466 | tomoyo_put_name(e.domainname); |
433 | tomoyo_put_name(e.program); | 467 | tomoyo_put_name(e.program); |
@@ -565,6 +599,17 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | |||
565 | */ | 599 | */ |
566 | LIST_HEAD(tomoyo_aggregator_list); | 600 | LIST_HEAD(tomoyo_aggregator_list); |
567 | 601 | ||
602 | static bool tomoyo_same_aggregator_entry(const struct tomoyo_acl_head *a, | ||
603 | const struct tomoyo_acl_head *b) | ||
604 | { | ||
605 | const struct tomoyo_aggregator_entry *p1 = container_of(a, typeof(*p1), | ||
606 | head); | ||
607 | const struct tomoyo_aggregator_entry *p2 = container_of(b, typeof(*p2), | ||
608 | head); | ||
609 | return p1->original_name == p2->original_name && | ||
610 | p1->aggregated_name == p2->aggregated_name; | ||
611 | } | ||
612 | |||
568 | /** | 613 | /** |
569 | * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator_entry" list. | 614 | * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator_entry" list. |
570 | * | 615 | * |
@@ -580,7 +625,6 @@ static int tomoyo_update_aggregator_entry(const char *original_name, | |||
580 | const char *aggregated_name, | 625 | const char *aggregated_name, |
581 | const bool is_delete) | 626 | const bool is_delete) |
582 | { | 627 | { |
583 | struct tomoyo_aggregator_entry *ptr; | ||
584 | struct tomoyo_aggregator_entry e = { }; | 628 | struct tomoyo_aggregator_entry e = { }; |
585 | int error = is_delete ? -ENOENT : -ENOMEM; | 629 | int error = is_delete ? -ENOENT : -ENOMEM; |
586 | 630 | ||
@@ -592,25 +636,9 @@ static int tomoyo_update_aggregator_entry(const char *original_name, | |||
592 | if (!e.original_name || !e.aggregated_name || | 636 | if (!e.original_name || !e.aggregated_name || |
593 | e.aggregated_name->is_patterned) /* No patterns allowed. */ | 637 | e.aggregated_name->is_patterned) /* No patterns allowed. */ |
594 | goto out; | 638 | goto out; |
595 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 639 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, |
596 | goto out; | 640 | &tomoyo_aggregator_list, |
597 | list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list, head.list) { | 641 | tomoyo_same_aggregator_entry); |
598 | if (!tomoyo_is_same_aggregator_entry(ptr, &e)) | ||
599 | continue; | ||
600 | ptr->head.is_deleted = is_delete; | ||
601 | error = 0; | ||
602 | break; | ||
603 | } | ||
604 | if (!is_delete && error) { | ||
605 | struct tomoyo_aggregator_entry *entry = | ||
606 | tomoyo_commit_ok(&e, sizeof(e)); | ||
607 | if (entry) { | ||
608 | list_add_tail_rcu(&entry->head.list, | ||
609 | &tomoyo_aggregator_list); | ||
610 | error = 0; | ||
611 | } | ||
612 | } | ||
613 | mutex_unlock(&tomoyo_policy_lock); | ||
614 | out: | 642 | out: |
615 | tomoyo_put_name(e.original_name); | 643 | tomoyo_put_name(e.original_name); |
616 | tomoyo_put_name(e.aggregated_name); | 644 | tomoyo_put_name(e.aggregated_name); |
@@ -699,6 +727,17 @@ int tomoyo_write_aggregator_policy(char *data, const bool is_delete) | |||
699 | */ | 727 | */ |
700 | LIST_HEAD(tomoyo_alias_list); | 728 | LIST_HEAD(tomoyo_alias_list); |
701 | 729 | ||
730 | static bool tomoyo_same_alias_entry(const struct tomoyo_acl_head *a, | ||
731 | const struct tomoyo_acl_head *b) | ||
732 | { | ||
733 | const struct tomoyo_alias_entry *p1 = container_of(a, typeof(*p1), | ||
734 | head); | ||
735 | const struct tomoyo_alias_entry *p2 = container_of(b, typeof(*p2), | ||
736 | head); | ||
737 | return p1->original_name == p2->original_name && | ||
738 | p1->aliased_name == p2->aliased_name; | ||
739 | } | ||
740 | |||
702 | /** | 741 | /** |
703 | * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. | 742 | * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. |
704 | * | 743 | * |
@@ -714,7 +753,6 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
714 | const char *aliased_name, | 753 | const char *aliased_name, |
715 | const bool is_delete) | 754 | const bool is_delete) |
716 | { | 755 | { |
717 | struct tomoyo_alias_entry *ptr; | ||
718 | struct tomoyo_alias_entry e = { }; | 756 | struct tomoyo_alias_entry e = { }; |
719 | int error = is_delete ? -ENOENT : -ENOMEM; | 757 | int error = is_delete ? -ENOENT : -ENOMEM; |
720 | 758 | ||
@@ -726,25 +764,9 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
726 | if (!e.original_name || !e.aliased_name || | 764 | if (!e.original_name || !e.aliased_name || |
727 | e.original_name->is_patterned || e.aliased_name->is_patterned) | 765 | e.original_name->is_patterned || e.aliased_name->is_patterned) |
728 | goto out; /* No patterns allowed. */ | 766 | goto out; /* No patterns allowed. */ |
729 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 767 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, |
730 | goto out; | 768 | &tomoyo_alias_list, |
731 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, head.list) { | 769 | tomoyo_same_alias_entry); |
732 | if (!tomoyo_is_same_alias_entry(ptr, &e)) | ||
733 | continue; | ||
734 | ptr->head.is_deleted = is_delete; | ||
735 | error = 0; | ||
736 | break; | ||
737 | } | ||
738 | if (!is_delete && error) { | ||
739 | struct tomoyo_alias_entry *entry = | ||
740 | tomoyo_commit_ok(&e, sizeof(e)); | ||
741 | if (entry) { | ||
742 | list_add_tail_rcu(&entry->head.list, | ||
743 | &tomoyo_alias_list); | ||
744 | error = 0; | ||
745 | } | ||
746 | } | ||
747 | mutex_unlock(&tomoyo_policy_lock); | ||
748 | out: | 770 | out: |
749 | tomoyo_put_name(e.original_name); | 771 | tomoyo_put_name(e.original_name); |
750 | tomoyo_put_name(e.aliased_name); | 772 | tomoyo_put_name(e.aliased_name); |