diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2010-06-03 07:38:03 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-08-02 01:33:42 -0400 |
commit | 1084307ca097745ed6e40a192329b133a49271ac (patch) | |
tree | f3b2e81705afb4ca3006ebb931aa0aad426ace02 /security/tomoyo/domain.c | |
parent | 3f629636320dfa65804779a3fc333f3147f3b064 (diff) |
TOMOYO: Add pathname aggregation support.
This patch allows users to aggregate programs which provide similar
functionality (e.g. /usr/bin/vi and /usr/bin/emacs ).
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 | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 50f6e7972174..a07ca6dc1a08 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -483,6 +483,136 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | |||
483 | } | 483 | } |
484 | 484 | ||
485 | /* | 485 | /* |
486 | * tomoyo_aggregator_list is used for holding list of rewrite table for | ||
487 | * execve() request. Some programs provides similar functionality. This keyword | ||
488 | * allows users to aggregate such programs. | ||
489 | * | ||
490 | * Entries are added by | ||
491 | * | ||
492 | * # echo 'aggregator /usr/bin/vi /./editor' > \ | ||
493 | * /sys/kernel/security/tomoyo/exception_policy | ||
494 | * # echo 'aggregator /usr/bin/emacs /./editor' > \ | ||
495 | * /sys/kernel/security/tomoyo/exception_policy | ||
496 | * | ||
497 | * and are deleted by | ||
498 | * | ||
499 | * # echo 'delete aggregator /usr/bin/vi /./editor' > \ | ||
500 | * /sys/kernel/security/tomoyo/exception_policy | ||
501 | * # echo 'delete aggregator /usr/bin/emacs /./editor' > \ | ||
502 | * /sys/kernel/security/tomoyo/exception_policy | ||
503 | * | ||
504 | * and all entries are retrieved by | ||
505 | * | ||
506 | * # grep ^aggregator /sys/kernel/security/tomoyo/exception_policy | ||
507 | * | ||
508 | * In the example above, if /usr/bin/vi or /usr/bin/emacs are executed, | ||
509 | * permission is checked for /./editor and domainname which the current process | ||
510 | * will belong to after execve() succeeds is calculated using /./editor . | ||
511 | */ | ||
512 | LIST_HEAD(tomoyo_aggregator_list); | ||
513 | |||
514 | /** | ||
515 | * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator_entry" list. | ||
516 | * | ||
517 | * @original_name: The original program's name. | ||
518 | * @aggregated_name: The program name to use. | ||
519 | * @is_delete: True if it is a delete request. | ||
520 | * | ||
521 | * Returns 0 on success, negative value otherwise. | ||
522 | * | ||
523 | * Caller holds tomoyo_read_lock(). | ||
524 | */ | ||
525 | static int tomoyo_update_aggregator_entry(const char *original_name, | ||
526 | const char *aggregated_name, | ||
527 | const bool is_delete) | ||
528 | { | ||
529 | struct tomoyo_aggregator_entry *ptr; | ||
530 | struct tomoyo_aggregator_entry e = { }; | ||
531 | int error = is_delete ? -ENOENT : -ENOMEM; | ||
532 | |||
533 | if (!tomoyo_is_correct_path(original_name) || | ||
534 | !tomoyo_is_correct_path(aggregated_name)) | ||
535 | return -EINVAL; | ||
536 | e.original_name = tomoyo_get_name(original_name); | ||
537 | e.aggregated_name = tomoyo_get_name(aggregated_name); | ||
538 | if (!e.original_name || !e.aggregated_name || | ||
539 | e.aggregated_name->is_patterned) /* No patterns allowed. */ | ||
540 | goto out; | ||
541 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
542 | goto out; | ||
543 | list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list, list) { | ||
544 | if (!tomoyo_is_same_aggregator_entry(ptr, &e)) | ||
545 | continue; | ||
546 | ptr->is_deleted = is_delete; | ||
547 | error = 0; | ||
548 | break; | ||
549 | } | ||
550 | if (!is_delete && error) { | ||
551 | struct tomoyo_aggregator_entry *entry = | ||
552 | tomoyo_commit_ok(&e, sizeof(e)); | ||
553 | if (entry) { | ||
554 | list_add_tail_rcu(&entry->list, | ||
555 | &tomoyo_aggregator_list); | ||
556 | error = 0; | ||
557 | } | ||
558 | } | ||
559 | mutex_unlock(&tomoyo_policy_lock); | ||
560 | out: | ||
561 | tomoyo_put_name(e.original_name); | ||
562 | tomoyo_put_name(e.aggregated_name); | ||
563 | return error; | ||
564 | } | ||
565 | |||
566 | /** | ||
567 | * tomoyo_read_aggregator_policy - Read "struct tomoyo_aggregator_entry" list. | ||
568 | * | ||
569 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
570 | * | ||
571 | * Returns true on success, false otherwise. | ||
572 | * | ||
573 | * Caller holds tomoyo_read_lock(). | ||
574 | */ | ||
575 | bool tomoyo_read_aggregator_policy(struct tomoyo_io_buffer *head) | ||
576 | { | ||
577 | struct list_head *pos; | ||
578 | bool done = true; | ||
579 | |||
580 | list_for_each_cookie(pos, head->read_var2, &tomoyo_aggregator_list) { | ||
581 | struct tomoyo_aggregator_entry *ptr; | ||
582 | |||
583 | ptr = list_entry(pos, struct tomoyo_aggregator_entry, list); | ||
584 | if (ptr->is_deleted) | ||
585 | continue; | ||
586 | done = tomoyo_io_printf(head, TOMOYO_KEYWORD_AGGREGATOR | ||
587 | "%s %s\n", ptr->original_name->name, | ||
588 | ptr->aggregated_name->name); | ||
589 | if (!done) | ||
590 | break; | ||
591 | } | ||
592 | return done; | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * tomoyo_write_aggregator_policy - Write "struct tomoyo_aggregator_entry" list. | ||
597 | * | ||
598 | * @data: String to parse. | ||
599 | * @is_delete: True if it is a delete request. | ||
600 | * | ||
601 | * Returns 0 on success, negative value otherwise. | ||
602 | * | ||
603 | * Caller holds tomoyo_read_lock(). | ||
604 | */ | ||
605 | int tomoyo_write_aggregator_policy(char *data, const bool is_delete) | ||
606 | { | ||
607 | char *cp = strchr(data, ' '); | ||
608 | |||
609 | if (!cp) | ||
610 | return -EINVAL; | ||
611 | *cp++ = '\0'; | ||
612 | return tomoyo_update_aggregator_entry(data, cp, is_delete); | ||
613 | } | ||
614 | |||
615 | /* | ||
486 | * tomoyo_alias_list is used for holding list of symlink's pathnames which are | 616 | * tomoyo_alias_list is used for holding list of symlink's pathnames which are |
487 | * allowed to be passed to an execve() request. Normally, the domainname which | 617 | * allowed to be passed to an execve() request. Normally, the domainname which |
488 | * the current process will belong to after execve() succeeds is calculated | 618 | * the current process will belong to after execve() succeeds is calculated |
@@ -732,6 +862,23 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
732 | } | 862 | } |
733 | } | 863 | } |
734 | 864 | ||
865 | /* Check 'aggregator' directive. */ | ||
866 | { | ||
867 | struct tomoyo_aggregator_entry *ptr; | ||
868 | list_for_each_entry_rcu(ptr, &tomoyo_aggregator_list, list) { | ||
869 | if (ptr->is_deleted || | ||
870 | !tomoyo_path_matches_pattern(&rn, | ||
871 | ptr->original_name)) | ||
872 | continue; | ||
873 | if (need_kfree) | ||
874 | kfree(rn.name); | ||
875 | need_kfree = false; | ||
876 | /* This is OK because it is read only. */ | ||
877 | rn = *ptr->aggregated_name; | ||
878 | break; | ||
879 | } | ||
880 | } | ||
881 | |||
735 | /* Check execute permission. */ | 882 | /* Check execute permission. */ |
736 | retval = tomoyo_check_exec_perm(old_domain, &rn); | 883 | retval = tomoyo_check_exec_perm(old_domain, &rn); |
737 | if (retval == TOMOYO_RETRY_REQUEST) | 884 | if (retval == TOMOYO_RETRY_REQUEST) |