aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/domain.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo/domain.c')
-rw-r--r--security/tomoyo/domain.c147
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 */
512LIST_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 */
525static 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 */
575bool 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 */
605int 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)