diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-09-10 02:22:48 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-09-13 18:27:05 -0400 |
commit | d58e0da854376841ac99defeb117a83f086715c6 (patch) | |
tree | b6e37d1030180680a7801ecb295d8d3990930375 /security/tomoyo | |
parent | 5dbe3040c74eef18e66951347eda05b153e69328 (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')
-rw-r--r-- | security/tomoyo/Makefile | 2 | ||||
-rw-r--r-- | security/tomoyo/common.c | 20 | ||||
-rw-r--r-- | security/tomoyo/common.h | 14 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 95 | ||||
-rw-r--r-- | security/tomoyo/environ.c | 122 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 9 | ||||
-rw-r--r-- | security/tomoyo/util.c | 14 |
7 files changed, 266 insertions, 10 deletions
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 95278b71fc21..f7ade960f6cf 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | obj-y = audit.o common.o condition.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o | 1 | obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o |
2 | 2 | ||
3 | $(obj)/policy/profile.conf: | 3 | $(obj)/policy/profile.conf: |
4 | @mkdir -p $(obj)/policy/ | 4 | @mkdir -p $(obj)/policy/ |
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index c8439cf2a448..d116e1ece3e6 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -20,6 +20,7 @@ const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE] = { | |||
20 | /* String table for /sys/kernel/security/tomoyo/profile */ | 20 | /* String table for /sys/kernel/security/tomoyo/profile */ |
21 | const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX | 21 | const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX |
22 | + TOMOYO_MAX_MAC_CATEGORY_INDEX] = { | 22 | + TOMOYO_MAX_MAC_CATEGORY_INDEX] = { |
23 | /* CONFIG::file group */ | ||
23 | [TOMOYO_MAC_FILE_EXECUTE] = "execute", | 24 | [TOMOYO_MAC_FILE_EXECUTE] = "execute", |
24 | [TOMOYO_MAC_FILE_OPEN] = "open", | 25 | [TOMOYO_MAC_FILE_OPEN] = "open", |
25 | [TOMOYO_MAC_FILE_CREATE] = "create", | 26 | [TOMOYO_MAC_FILE_CREATE] = "create", |
@@ -43,7 +44,11 @@ const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX | |||
43 | [TOMOYO_MAC_FILE_MOUNT] = "mount", | 44 | [TOMOYO_MAC_FILE_MOUNT] = "mount", |
44 | [TOMOYO_MAC_FILE_UMOUNT] = "unmount", | 45 | [TOMOYO_MAC_FILE_UMOUNT] = "unmount", |
45 | [TOMOYO_MAC_FILE_PIVOT_ROOT] = "pivot_root", | 46 | [TOMOYO_MAC_FILE_PIVOT_ROOT] = "pivot_root", |
47 | /* CONFIG::misc group */ | ||
48 | [TOMOYO_MAC_ENVIRON] = "env", | ||
49 | /* CONFIG group */ | ||
46 | [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", | 50 | [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", |
51 | [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_MISC] = "misc", | ||
47 | }; | 52 | }; |
48 | 53 | ||
49 | /* String table for conditions. */ | 54 | /* String table for conditions. */ |
@@ -133,7 +138,8 @@ const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { | |||
133 | /* String table for categories. */ | 138 | /* String table for categories. */ |
134 | static const char * const tomoyo_category_keywords | 139 | static const char * const tomoyo_category_keywords |
135 | [TOMOYO_MAX_MAC_CATEGORY_INDEX] = { | 140 | [TOMOYO_MAX_MAC_CATEGORY_INDEX] = { |
136 | [TOMOYO_MAC_CATEGORY_FILE] = "file", | 141 | [TOMOYO_MAC_CATEGORY_FILE] = "file", |
142 | [TOMOYO_MAC_CATEGORY_MISC] = "misc", | ||
137 | }; | 143 | }; |
138 | 144 | ||
139 | /* Permit policy management by non-root user? */ | 145 | /* Permit policy management by non-root user? */ |
@@ -1036,11 +1042,13 @@ static int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns, | |||
1036 | static const struct { | 1042 | static const struct { |
1037 | const char *keyword; | 1043 | const char *keyword; |
1038 | int (*write) (struct tomoyo_acl_param *); | 1044 | int (*write) (struct tomoyo_acl_param *); |
1039 | } tomoyo_callback[1] = { | 1045 | } tomoyo_callback[2] = { |
1040 | { "file ", tomoyo_write_file }, | 1046 | { "file ", tomoyo_write_file }, |
1047 | { "misc ", tomoyo_write_misc }, | ||
1041 | }; | 1048 | }; |
1042 | u8 i; | 1049 | u8 i; |
1043 | for (i = 0; i < 1; i++) { | 1050 | |
1051 | for (i = 0; i < ARRAY_SIZE(tomoyo_callback); i++) { | ||
1044 | if (!tomoyo_str_starts(¶m.data, | 1052 | if (!tomoyo_str_starts(¶m.data, |
1045 | tomoyo_callback[i].keyword)) | 1053 | tomoyo_callback[i].keyword)) |
1046 | continue; | 1054 | continue; |
@@ -1375,6 +1383,12 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
1375 | tomoyo_print_name_union(head, &ptr->dir_name); | 1383 | tomoyo_print_name_union(head, &ptr->dir_name); |
1376 | tomoyo_print_name_union(head, &ptr->fs_type); | 1384 | tomoyo_print_name_union(head, &ptr->fs_type); |
1377 | tomoyo_print_number_union(head, &ptr->flags); | 1385 | tomoyo_print_number_union(head, &ptr->flags); |
1386 | } else if (acl_type == TOMOYO_TYPE_ENV_ACL) { | ||
1387 | struct tomoyo_env_acl *ptr = | ||
1388 | container_of(acl, typeof(*ptr), head); | ||
1389 | |||
1390 | tomoyo_set_group(head, "misc env "); | ||
1391 | tomoyo_set_string(head, ptr->env->name); | ||
1378 | } | 1392 | } |
1379 | if (acl->cond) { | 1393 | if (acl->cond) { |
1380 | head->r.print_cond_part = true; | 1394 | head->r.print_cond_part = true; |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f7fbaa66e443..63720a328edd 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -196,6 +196,7 @@ enum tomoyo_acl_entry_type_index { | |||
196 | TOMOYO_TYPE_PATH_NUMBER_ACL, | 196 | TOMOYO_TYPE_PATH_NUMBER_ACL, |
197 | TOMOYO_TYPE_MKDEV_ACL, | 197 | TOMOYO_TYPE_MKDEV_ACL, |
198 | TOMOYO_TYPE_MOUNT_ACL, | 198 | TOMOYO_TYPE_MOUNT_ACL, |
199 | TOMOYO_TYPE_ENV_ACL, | ||
199 | }; | 200 | }; |
200 | 201 | ||
201 | /* Index numbers for access controls with one pathname. */ | 202 | /* Index numbers for access controls with one pathname. */ |
@@ -300,12 +301,14 @@ enum tomoyo_mac_index { | |||
300 | TOMOYO_MAC_FILE_MOUNT, | 301 | TOMOYO_MAC_FILE_MOUNT, |
301 | TOMOYO_MAC_FILE_UMOUNT, | 302 | TOMOYO_MAC_FILE_UMOUNT, |
302 | TOMOYO_MAC_FILE_PIVOT_ROOT, | 303 | TOMOYO_MAC_FILE_PIVOT_ROOT, |
304 | TOMOYO_MAC_ENVIRON, | ||
303 | TOMOYO_MAX_MAC_INDEX | 305 | TOMOYO_MAX_MAC_INDEX |
304 | }; | 306 | }; |
305 | 307 | ||
306 | /* Index numbers for category of functionality. */ | 308 | /* Index numbers for category of functionality. */ |
307 | enum tomoyo_mac_category_index { | 309 | enum tomoyo_mac_category_index { |
308 | TOMOYO_MAC_CATEGORY_FILE, | 310 | TOMOYO_MAC_CATEGORY_FILE, |
311 | TOMOYO_MAC_CATEGORY_MISC, | ||
309 | TOMOYO_MAX_MAC_CATEGORY_INDEX | 312 | TOMOYO_MAX_MAC_CATEGORY_INDEX |
310 | }; | 313 | }; |
311 | 314 | ||
@@ -397,6 +400,9 @@ struct tomoyo_request_info { | |||
397 | u8 operation; | 400 | u8 operation; |
398 | } path_number; | 401 | } path_number; |
399 | struct { | 402 | struct { |
403 | const struct tomoyo_path_info *name; | ||
404 | } environ; | ||
405 | struct { | ||
400 | const struct tomoyo_path_info *type; | 406 | const struct tomoyo_path_info *type; |
401 | const struct tomoyo_path_info *dir; | 407 | const struct tomoyo_path_info *dir; |
402 | const struct tomoyo_path_info *dev; | 408 | const struct tomoyo_path_info *dev; |
@@ -638,6 +644,12 @@ struct tomoyo_mount_acl { | |||
638 | struct tomoyo_number_union flags; | 644 | struct tomoyo_number_union flags; |
639 | }; | 645 | }; |
640 | 646 | ||
647 | /* Structure for "misc env" directive in domain policy. */ | ||
648 | struct tomoyo_env_acl { | ||
649 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_ENV_ACL */ | ||
650 | const struct tomoyo_path_info *env; /* environment variable */ | ||
651 | }; | ||
652 | |||
641 | /* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */ | 653 | /* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */ |
642 | struct tomoyo_acl_param { | 654 | struct tomoyo_acl_param { |
643 | char *data; | 655 | char *data; |
@@ -820,6 +832,7 @@ const struct tomoyo_path_info *tomoyo_path_matches_group | |||
820 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | 832 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, |
821 | struct path *path, const int flag); | 833 | struct path *path, const int flag); |
822 | int tomoyo_close_control(struct tomoyo_io_buffer *head); | 834 | int tomoyo_close_control(struct tomoyo_io_buffer *head); |
835 | int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env); | ||
823 | int tomoyo_find_next_domain(struct linux_binprm *bprm); | 836 | int tomoyo_find_next_domain(struct linux_binprm *bprm); |
824 | int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, | 837 | int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, |
825 | const u8 index); | 838 | const u8 index); |
@@ -860,6 +873,7 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, | |||
860 | int tomoyo_write_aggregator(struct tomoyo_acl_param *param); | 873 | int tomoyo_write_aggregator(struct tomoyo_acl_param *param); |
861 | int tomoyo_write_file(struct tomoyo_acl_param *param); | 874 | int tomoyo_write_file(struct tomoyo_acl_param *param); |
862 | int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type); | 875 | int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type); |
876 | int tomoyo_write_misc(struct tomoyo_acl_param *param); | ||
863 | int tomoyo_write_transition_control(struct tomoyo_acl_param *param, | 877 | int tomoyo_write_transition_control(struct tomoyo_acl_param *param, |
864 | const u8 type); | 878 | const u8 type); |
865 | ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, | 879 | ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, |
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 | */ | ||
572 | static 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 | } | ||
643 | out: | ||
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); |
diff --git a/security/tomoyo/environ.c b/security/tomoyo/environ.c new file mode 100644 index 000000000000..ad4c6e18a437 --- /dev/null +++ b/security/tomoyo/environ.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * security/tomoyo/environ.c | ||
3 | * | ||
4 | * Copyright (C) 2005-2011 NTT DATA CORPORATION | ||
5 | */ | ||
6 | |||
7 | #include "common.h" | ||
8 | |||
9 | /** | ||
10 | * tomoyo_check_env_acl - Check permission for environment variable's name. | ||
11 | * | ||
12 | * @r: Pointer to "struct tomoyo_request_info". | ||
13 | * @ptr: Pointer to "struct tomoyo_acl_info". | ||
14 | * | ||
15 | * Returns true if granted, false otherwise. | ||
16 | */ | ||
17 | static bool tomoyo_check_env_acl(struct tomoyo_request_info *r, | ||
18 | const struct tomoyo_acl_info *ptr) | ||
19 | { | ||
20 | const struct tomoyo_env_acl *acl = | ||
21 | container_of(ptr, typeof(*acl), head); | ||
22 | |||
23 | return tomoyo_path_matches_pattern(r->param.environ.name, acl->env); | ||
24 | } | ||
25 | |||
26 | /** | ||
27 | * tomoyo_audit_env_log - Audit environment variable name log. | ||
28 | * | ||
29 | * @r: Pointer to "struct tomoyo_request_info". | ||
30 | * | ||
31 | * Returns 0 on success, negative value otherwise. | ||
32 | */ | ||
33 | static int tomoyo_audit_env_log(struct tomoyo_request_info *r) | ||
34 | { | ||
35 | return tomoyo_supervisor(r, "misc env %s\n", | ||
36 | r->param.environ.name->name); | ||
37 | } | ||
38 | |||
39 | /** | ||
40 | * tomoyo_env_perm - Check permission for environment variable's name. | ||
41 | * | ||
42 | * @r: Pointer to "struct tomoyo_request_info". | ||
43 | * @env: The name of environment variable. | ||
44 | * | ||
45 | * Returns 0 on success, negative value otherwise. | ||
46 | * | ||
47 | * Caller holds tomoyo_read_lock(). | ||
48 | */ | ||
49 | int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env) | ||
50 | { | ||
51 | struct tomoyo_path_info environ; | ||
52 | int error; | ||
53 | |||
54 | if (!env || !*env) | ||
55 | return 0; | ||
56 | environ.name = env; | ||
57 | tomoyo_fill_path_info(&environ); | ||
58 | r->param_type = TOMOYO_TYPE_ENV_ACL; | ||
59 | r->param.environ.name = &environ; | ||
60 | do { | ||
61 | tomoyo_check_acl(r, tomoyo_check_env_acl); | ||
62 | error = tomoyo_audit_env_log(r); | ||
63 | } while (error == TOMOYO_RETRY_REQUEST); | ||
64 | return error; | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * tomoyo_same_env_acl - Check for duplicated "struct tomoyo_env_acl" entry. | ||
69 | * | ||
70 | * @a: Pointer to "struct tomoyo_acl_info". | ||
71 | * @b: Pointer to "struct tomoyo_acl_info". | ||
72 | * | ||
73 | * Returns true if @a == @b, false otherwise. | ||
74 | */ | ||
75 | static bool tomoyo_same_env_acl(const struct tomoyo_acl_info *a, | ||
76 | const struct tomoyo_acl_info *b) | ||
77 | { | ||
78 | const struct tomoyo_env_acl *p1 = container_of(a, typeof(*p1), head); | ||
79 | const struct tomoyo_env_acl *p2 = container_of(b, typeof(*p2), head); | ||
80 | |||
81 | return p1->env == p2->env; | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * tomoyo_write_env - Write "struct tomoyo_env_acl" list. | ||
86 | * | ||
87 | * @param: Pointer to "struct tomoyo_acl_param". | ||
88 | * | ||
89 | * Returns 0 on success, negative value otherwise. | ||
90 | * | ||
91 | * Caller holds tomoyo_read_lock(). | ||
92 | */ | ||
93 | static int tomoyo_write_env(struct tomoyo_acl_param *param) | ||
94 | { | ||
95 | struct tomoyo_env_acl e = { .head.type = TOMOYO_TYPE_ENV_ACL }; | ||
96 | int error = -ENOMEM; | ||
97 | const char *data = tomoyo_read_token(param); | ||
98 | |||
99 | if (!tomoyo_correct_word(data) || strchr(data, '=')) | ||
100 | return -EINVAL; | ||
101 | e.env = tomoyo_get_name(data); | ||
102 | if (!e.env) | ||
103 | return error; | ||
104 | error = tomoyo_update_domain(&e.head, sizeof(e), param, | ||
105 | tomoyo_same_env_acl, NULL); | ||
106 | tomoyo_put_name(e.env); | ||
107 | return error; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * tomoyo_write_misc - Update environment variable list. | ||
112 | * | ||
113 | * @param: Pointer to "struct tomoyo_acl_param". | ||
114 | * | ||
115 | * Returns 0 on success, negative value otherwise. | ||
116 | */ | ||
117 | int tomoyo_write_misc(struct tomoyo_acl_param *param) | ||
118 | { | ||
119 | if (tomoyo_str_starts(¶m->data, "env ")) | ||
120 | return tomoyo_write_env(param); | ||
121 | return -EINVAL; | ||
122 | } | ||
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 5295b5caaa21..818b07998111 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -36,6 +36,7 @@ static const u8 tomoyo_acl_size[] = { | |||
36 | [TOMOYO_TYPE_PATH_NUMBER_ACL] = sizeof(struct tomoyo_path_number_acl), | 36 | [TOMOYO_TYPE_PATH_NUMBER_ACL] = sizeof(struct tomoyo_path_number_acl), |
37 | [TOMOYO_TYPE_MKDEV_ACL] = sizeof(struct tomoyo_mkdev_acl), | 37 | [TOMOYO_TYPE_MKDEV_ACL] = sizeof(struct tomoyo_mkdev_acl), |
38 | [TOMOYO_TYPE_MOUNT_ACL] = sizeof(struct tomoyo_mount_acl), | 38 | [TOMOYO_TYPE_MOUNT_ACL] = sizeof(struct tomoyo_mount_acl), |
39 | [TOMOYO_TYPE_ENV_ACL] = sizeof(struct tomoyo_env_acl), | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | /** | 42 | /** |
@@ -293,6 +294,14 @@ static void tomoyo_del_acl(struct list_head *element) | |||
293 | tomoyo_put_number_union(&entry->flags); | 294 | tomoyo_put_number_union(&entry->flags); |
294 | } | 295 | } |
295 | break; | 296 | break; |
297 | case TOMOYO_TYPE_ENV_ACL: | ||
298 | { | ||
299 | struct tomoyo_env_acl *entry = | ||
300 | container_of(acl, typeof(*entry), head); | ||
301 | |||
302 | tomoyo_put_name(entry->env); | ||
303 | } | ||
304 | break; | ||
296 | } | 305 | } |
297 | } | 306 | } |
298 | 307 | ||
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 6a4195a4b93c..cb7d507b6312 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
@@ -42,6 +42,8 @@ const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = { | |||
42 | [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE, | 42 | [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE, |
43 | [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE, | 43 | [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE, |
44 | [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE, | 44 | [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE, |
45 | /* CONFIG::misc group */ | ||
46 | [TOMOYO_MAC_ENVIRON] = TOMOYO_MAC_CATEGORY_MISC, | ||
45 | }; | 47 | }; |
46 | 48 | ||
47 | /** | 49 | /** |
@@ -920,15 +922,17 @@ int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, | |||
920 | const u8 index) | 922 | const u8 index) |
921 | { | 923 | { |
922 | u8 mode; | 924 | u8 mode; |
923 | const u8 category = TOMOYO_MAC_CATEGORY_FILE; | 925 | struct tomoyo_profile *p; |
926 | |||
924 | if (!tomoyo_policy_loaded) | 927 | if (!tomoyo_policy_loaded) |
925 | return TOMOYO_CONFIG_DISABLED; | 928 | return TOMOYO_CONFIG_DISABLED; |
926 | mode = tomoyo_profile(ns, profile)->config[index]; | 929 | p = tomoyo_profile(ns, profile); |
930 | mode = p->config[index]; | ||
927 | if (mode == TOMOYO_CONFIG_USE_DEFAULT) | 931 | if (mode == TOMOYO_CONFIG_USE_DEFAULT) |
928 | mode = tomoyo_profile(ns, profile)->config | 932 | mode = p->config[tomoyo_index2category[index] |
929 | [category + TOMOYO_MAX_MAC_INDEX]; | 933 | + TOMOYO_MAX_MAC_INDEX]; |
930 | if (mode == TOMOYO_CONFIG_USE_DEFAULT) | 934 | if (mode == TOMOYO_CONFIG_USE_DEFAULT) |
931 | mode = tomoyo_profile(ns, profile)->default_config; | 935 | mode = p->default_config; |
932 | return mode & 3; | 936 | return mode & 3; |
933 | } | 937 | } |
934 | 938 | ||