aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/domain.c
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2011-09-10 02:22:48 -0400
committerJames Morris <jmorris@namei.org>2011-09-13 18:27:05 -0400
commitd58e0da854376841ac99defeb117a83f086715c6 (patch)
treeb6e37d1030180680a7801ecb295d8d3990930375 /security/tomoyo/domain.c
parent5dbe3040c74eef18e66951347eda05b153e69328 (diff)
TOMOYO: Add environment variable name restriction support.
This patch adds support for checking environment variable's names. Although TOMOYO already provides ability to check argv[]/envp[] passed to execve() requests, file execute /bin/sh exec.envp["LD_LIBRARY_PATH"]="bar" will reject execution of /bin/sh if environment variable LD_LIBRARY_PATH is not defined. To grant execution of /bin/sh if LD_LIBRARY_PATH is not defined, administrators have to specify like file execute /bin/sh exec.envp["LD_LIBRARY_PATH"]="/system/lib" file execute /bin/sh exec.envp["LD_LIBRARY_PATH"]=NULL . Since there are many environment variables whereas conditional checks are applied as "&&", it is difficult to cover all combinations. Therefore, this patch supports conditional checks that are applied as "||", by specifying like file execute /bin/sh misc env LD_LIBRARY_PATH exec.envp["LD_LIBRARY_PATH"]="/system/lib" which means "grant execution of /bin/sh if environment variable is not defined or is defined and its value is /system/lib". 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.c95
1 files changed, 94 insertions, 1 deletions
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index cd0f92d88bb4..5931fb1c04d5 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -563,6 +563,92 @@ out:
563} 563}
564 564
565/** 565/**
566 * tomoyo_environ - Check permission for environment variable names.
567 *
568 * @ee: Pointer to "struct tomoyo_execve".
569 *
570 * Returns 0 on success, negative value otherwise.
571 */
572static int tomoyo_environ(struct tomoyo_execve *ee)
573{
574 struct tomoyo_request_info *r = &ee->r;
575 struct linux_binprm *bprm = ee->bprm;
576 /* env_page.data is allocated by tomoyo_dump_page(). */
577 struct tomoyo_page_dump env_page = { };
578 char *arg_ptr; /* Size is TOMOYO_EXEC_TMPSIZE bytes */
579 int arg_len = 0;
580 unsigned long pos = bprm->p;
581 int offset = pos % PAGE_SIZE;
582 int argv_count = bprm->argc;
583 int envp_count = bprm->envc;
584 int error = -ENOMEM;
585
586 ee->r.type = TOMOYO_MAC_ENVIRON;
587 ee->r.profile = r->domain->profile;
588 ee->r.mode = tomoyo_get_mode(r->domain->ns, ee->r.profile,
589 TOMOYO_MAC_ENVIRON);
590 if (!r->mode || !envp_count)
591 return 0;
592 arg_ptr = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
593 if (!arg_ptr)
594 goto out;
595 while (error == -ENOMEM) {
596 if (!tomoyo_dump_page(bprm, pos, &env_page))
597 goto out;
598 pos += PAGE_SIZE - offset;
599 /* Read. */
600 while (argv_count && offset < PAGE_SIZE) {
601 if (!env_page.data[offset++])
602 argv_count--;
603 }
604 if (argv_count) {
605 offset = 0;
606 continue;
607 }
608 while (offset < PAGE_SIZE) {
609 const unsigned char c = env_page.data[offset++];
610
611 if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
612 if (c == '=') {
613 arg_ptr[arg_len++] = '\0';
614 } else if (c == '\\') {
615 arg_ptr[arg_len++] = '\\';
616 arg_ptr[arg_len++] = '\\';
617 } else if (c > ' ' && c < 127) {
618 arg_ptr[arg_len++] = c;
619 } else {
620 arg_ptr[arg_len++] = '\\';
621 arg_ptr[arg_len++] = (c >> 6) + '0';
622 arg_ptr[arg_len++]
623 = ((c >> 3) & 7) + '0';
624 arg_ptr[arg_len++] = (c & 7) + '0';
625 }
626 } else {
627 arg_ptr[arg_len] = '\0';
628 }
629 if (c)
630 continue;
631 if (tomoyo_env_perm(r, arg_ptr)) {
632 error = -EPERM;
633 break;
634 }
635 if (!--envp_count) {
636 error = 0;
637 break;
638 }
639 arg_len = 0;
640 }
641 offset = 0;
642 }
643out:
644 if (r->mode != TOMOYO_CONFIG_ENFORCING)
645 error = 0;
646 kfree(env_page.data);
647 kfree(arg_ptr);
648 return error;
649}
650
651/**
566 * tomoyo_find_next_domain - Find a domain. 652 * tomoyo_find_next_domain - Find a domain.
567 * 653 *
568 * @bprm: Pointer to "struct linux_binprm". 654 * @bprm: Pointer to "struct linux_binprm".
@@ -581,6 +667,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
581 bool reject_on_transition_failure = false; 667 bool reject_on_transition_failure = false;
582 struct tomoyo_path_info rn = { }; /* real name */ 668 struct tomoyo_path_info rn = { }; /* real name */
583 struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS); 669 struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS);
670
584 if (!ee) 671 if (!ee)
585 return -ENOMEM; 672 return -ENOMEM;
586 ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); 673 ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
@@ -713,6 +800,10 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
713 bprm->cred->security = domain; 800 bprm->cred->security = domain;
714 if (need_kfree) 801 if (need_kfree)
715 kfree(rn.name); 802 kfree(rn.name);
803 if (!retval) {
804 ee->r.domain = domain;
805 retval = tomoyo_environ(ee);
806 }
716 kfree(ee->tmp); 807 kfree(ee->tmp);
717 kfree(ee->dump.data); 808 kfree(ee->dump.data);
718 kfree(ee); 809 kfree(ee);
@@ -732,7 +823,8 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
732 struct tomoyo_page_dump *dump) 823 struct tomoyo_page_dump *dump)
733{ 824{
734 struct page *page; 825 struct page *page;
735 /* dump->data is released by tomoyo_finish_execve(). */ 826
827 /* dump->data is released by tomoyo_find_next_domain(). */
736 if (!dump->data) { 828 if (!dump->data) {
737 dump->data = kzalloc(PAGE_SIZE, GFP_NOFS); 829 dump->data = kzalloc(PAGE_SIZE, GFP_NOFS);
738 if (!dump->data) 830 if (!dump->data)
@@ -753,6 +845,7 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
753 * So do I. 845 * So do I.
754 */ 846 */
755 char *kaddr = kmap_atomic(page, KM_USER0); 847 char *kaddr = kmap_atomic(page, KM_USER0);
848
756 dump->page = page; 849 dump->page = page;
757 memcpy(dump->data + offset, kaddr + offset, 850 memcpy(dump->data + offset, kaddr + offset,
758 PAGE_SIZE - offset); 851 PAGE_SIZE - offset);