diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/apparmor/Kconfig | 2 | ||||
-rw-r--r-- | security/apparmor/include/resource.h | 4 | ||||
-rw-r--r-- | security/apparmor/lib.c | 2 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 42 | ||||
-rw-r--r-- | security/apparmor/path.c | 47 | ||||
-rw-r--r-- | security/apparmor/policy.c | 6 | ||||
-rw-r--r-- | security/apparmor/resource.c | 20 | ||||
-rw-r--r-- | security/capability.c | 3 | ||||
-rw-r--r-- | security/commoncap.c | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 1 | ||||
-rw-r--r-- | security/integrity/ima/ima_iint.c | 4 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 8 | ||||
-rw-r--r-- | security/keys/internal.h | 5 | ||||
-rw-r--r-- | security/keys/keyctl.c | 6 | ||||
-rw-r--r-- | security/keys/request_key.c | 2 | ||||
-rw-r--r-- | security/security.c | 21 | ||||
-rw-r--r-- | security/selinux/Makefile | 2 | ||||
-rw-r--r-- | security/selinux/hooks.c | 21 | ||||
-rw-r--r-- | security/tomoyo/common.c | 6 | ||||
-rw-r--r-- | security/tomoyo/common.h | 3 |
20 files changed, 116 insertions, 91 deletions
diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig index 72555b9ca7d6..9b9013b2e321 100644 --- a/security/apparmor/Kconfig +++ b/security/apparmor/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SECURITY_APPARMOR | 1 | config SECURITY_APPARMOR |
2 | bool "AppArmor support" | 2 | bool "AppArmor support" |
3 | depends on SECURITY | 3 | depends on SECURITY && NET |
4 | select AUDIT | 4 | select AUDIT |
5 | select SECURITY_PATH | 5 | select SECURITY_PATH |
6 | select SECURITYFS | 6 | select SECURITYFS |
diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h index 3c88be946494..02baec732bb5 100644 --- a/security/apparmor/include/resource.h +++ b/security/apparmor/include/resource.h | |||
@@ -33,8 +33,8 @@ struct aa_rlimit { | |||
33 | }; | 33 | }; |
34 | 34 | ||
35 | int aa_map_resource(int resource); | 35 | int aa_map_resource(int resource); |
36 | int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, | 36 | int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, |
37 | struct rlimit *new_rlim); | 37 | unsigned int resource, struct rlimit *new_rlim); |
38 | 38 | ||
39 | void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); | 39 | void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); |
40 | 40 | ||
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 6e85cdb4303f..506d2baf6147 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c | |||
@@ -40,6 +40,7 @@ char *aa_split_fqname(char *fqname, char **ns_name) | |||
40 | *ns_name = NULL; | 40 | *ns_name = NULL; |
41 | if (name[0] == ':') { | 41 | if (name[0] == ':') { |
42 | char *split = strchr(&name[1], ':'); | 42 | char *split = strchr(&name[1], ':'); |
43 | *ns_name = skip_spaces(&name[1]); | ||
43 | if (split) { | 44 | if (split) { |
44 | /* overwrite ':' with \0 */ | 45 | /* overwrite ':' with \0 */ |
45 | *split = 0; | 46 | *split = 0; |
@@ -47,7 +48,6 @@ char *aa_split_fqname(char *fqname, char **ns_name) | |||
47 | } else | 48 | } else |
48 | /* a ns name without a following profile is allowed */ | 49 | /* a ns name without a following profile is allowed */ |
49 | name = NULL; | 50 | name = NULL; |
50 | *ns_name = &name[1]; | ||
51 | } | 51 | } |
52 | if (name && *name == 0) | 52 | if (name && *name == 0) |
53 | name = NULL; | 53 | name = NULL; |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 8db33a8b50c4..cf1de4462ccd 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
@@ -607,14 +607,14 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, | |||
607 | return error; | 607 | return error; |
608 | } | 608 | } |
609 | 609 | ||
610 | static int apparmor_task_setrlimit(unsigned int resource, | 610 | static int apparmor_task_setrlimit(struct task_struct *task, |
611 | struct rlimit *new_rlim) | 611 | unsigned int resource, struct rlimit *new_rlim) |
612 | { | 612 | { |
613 | struct aa_profile *profile = aa_current_profile(); | 613 | struct aa_profile *profile = aa_current_profile(); |
614 | int error = 0; | 614 | int error = 0; |
615 | 615 | ||
616 | if (!unconfined(profile)) | 616 | if (!unconfined(profile)) |
617 | error = aa_task_setrlimit(profile, resource, new_rlim); | 617 | error = aa_task_setrlimit(profile, task, resource, new_rlim); |
618 | 618 | ||
619 | return error; | 619 | return error; |
620 | } | 620 | } |
@@ -667,17 +667,29 @@ static struct security_operations apparmor_ops = { | |||
667 | * AppArmor sysfs module parameters | 667 | * AppArmor sysfs module parameters |
668 | */ | 668 | */ |
669 | 669 | ||
670 | static int param_set_aabool(const char *val, struct kernel_param *kp); | 670 | static int param_set_aabool(const char *val, const struct kernel_param *kp); |
671 | static int param_get_aabool(char *buffer, struct kernel_param *kp); | 671 | static int param_get_aabool(char *buffer, const struct kernel_param *kp); |
672 | #define param_check_aabool(name, p) __param_check(name, p, int) | 672 | #define param_check_aabool(name, p) __param_check(name, p, int) |
673 | static struct kernel_param_ops param_ops_aabool = { | ||
674 | .set = param_set_aabool, | ||
675 | .get = param_get_aabool | ||
676 | }; | ||
673 | 677 | ||
674 | static int param_set_aauint(const char *val, struct kernel_param *kp); | 678 | static int param_set_aauint(const char *val, const struct kernel_param *kp); |
675 | static int param_get_aauint(char *buffer, struct kernel_param *kp); | 679 | static int param_get_aauint(char *buffer, const struct kernel_param *kp); |
676 | #define param_check_aauint(name, p) __param_check(name, p, int) | 680 | #define param_check_aauint(name, p) __param_check(name, p, int) |
681 | static struct kernel_param_ops param_ops_aauint = { | ||
682 | .set = param_set_aauint, | ||
683 | .get = param_get_aauint | ||
684 | }; | ||
677 | 685 | ||
678 | static int param_set_aalockpolicy(const char *val, struct kernel_param *kp); | 686 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp); |
679 | static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp); | 687 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); |
680 | #define param_check_aalockpolicy(name, p) __param_check(name, p, int) | 688 | #define param_check_aalockpolicy(name, p) __param_check(name, p, int) |
689 | static struct kernel_param_ops param_ops_aalockpolicy = { | ||
690 | .set = param_set_aalockpolicy, | ||
691 | .get = param_get_aalockpolicy | ||
692 | }; | ||
681 | 693 | ||
682 | static int param_set_audit(const char *val, struct kernel_param *kp); | 694 | static int param_set_audit(const char *val, struct kernel_param *kp); |
683 | static int param_get_audit(char *buffer, struct kernel_param *kp); | 695 | static int param_get_audit(char *buffer, struct kernel_param *kp); |
@@ -751,7 +763,7 @@ static int __init apparmor_enabled_setup(char *str) | |||
751 | __setup("apparmor=", apparmor_enabled_setup); | 763 | __setup("apparmor=", apparmor_enabled_setup); |
752 | 764 | ||
753 | /* set global flag turning off the ability to load policy */ | 765 | /* set global flag turning off the ability to load policy */ |
754 | static int param_set_aalockpolicy(const char *val, struct kernel_param *kp) | 766 | static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) |
755 | { | 767 | { |
756 | if (!capable(CAP_MAC_ADMIN)) | 768 | if (!capable(CAP_MAC_ADMIN)) |
757 | return -EPERM; | 769 | return -EPERM; |
@@ -760,35 +772,35 @@ static int param_set_aalockpolicy(const char *val, struct kernel_param *kp) | |||
760 | return param_set_bool(val, kp); | 772 | return param_set_bool(val, kp); |
761 | } | 773 | } |
762 | 774 | ||
763 | static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp) | 775 | static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) |
764 | { | 776 | { |
765 | if (!capable(CAP_MAC_ADMIN)) | 777 | if (!capable(CAP_MAC_ADMIN)) |
766 | return -EPERM; | 778 | return -EPERM; |
767 | return param_get_bool(buffer, kp); | 779 | return param_get_bool(buffer, kp); |
768 | } | 780 | } |
769 | 781 | ||
770 | static int param_set_aabool(const char *val, struct kernel_param *kp) | 782 | static int param_set_aabool(const char *val, const struct kernel_param *kp) |
771 | { | 783 | { |
772 | if (!capable(CAP_MAC_ADMIN)) | 784 | if (!capable(CAP_MAC_ADMIN)) |
773 | return -EPERM; | 785 | return -EPERM; |
774 | return param_set_bool(val, kp); | 786 | return param_set_bool(val, kp); |
775 | } | 787 | } |
776 | 788 | ||
777 | static int param_get_aabool(char *buffer, struct kernel_param *kp) | 789 | static int param_get_aabool(char *buffer, const struct kernel_param *kp) |
778 | { | 790 | { |
779 | if (!capable(CAP_MAC_ADMIN)) | 791 | if (!capable(CAP_MAC_ADMIN)) |
780 | return -EPERM; | 792 | return -EPERM; |
781 | return param_get_bool(buffer, kp); | 793 | return param_get_bool(buffer, kp); |
782 | } | 794 | } |
783 | 795 | ||
784 | static int param_set_aauint(const char *val, struct kernel_param *kp) | 796 | static int param_set_aauint(const char *val, const struct kernel_param *kp) |
785 | { | 797 | { |
786 | if (!capable(CAP_MAC_ADMIN)) | 798 | if (!capable(CAP_MAC_ADMIN)) |
787 | return -EPERM; | 799 | return -EPERM; |
788 | return param_set_uint(val, kp); | 800 | return param_set_uint(val, kp); |
789 | } | 801 | } |
790 | 802 | ||
791 | static int param_get_aauint(char *buffer, struct kernel_param *kp) | 803 | static int param_get_aauint(char *buffer, const struct kernel_param *kp) |
792 | { | 804 | { |
793 | if (!capable(CAP_MAC_ADMIN)) | 805 | if (!capable(CAP_MAC_ADMIN)) |
794 | return -EPERM; | 806 | return -EPERM; |
diff --git a/security/apparmor/path.c b/security/apparmor/path.c index 96bab9469d48..82396050f186 100644 --- a/security/apparmor/path.c +++ b/security/apparmor/path.c | |||
@@ -59,39 +59,22 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, | |||
59 | { | 59 | { |
60 | struct path root, tmp; | 60 | struct path root, tmp; |
61 | char *res; | 61 | char *res; |
62 | int deleted, connected; | 62 | int connected, error = 0; |
63 | int error = 0; | ||
64 | 63 | ||
65 | /* Get the root we want to resolve too */ | 64 | /* Get the root we want to resolve too, released below */ |
66 | if (flags & PATH_CHROOT_REL) { | 65 | if (flags & PATH_CHROOT_REL) { |
67 | /* resolve paths relative to chroot */ | 66 | /* resolve paths relative to chroot */ |
68 | read_lock(¤t->fs->lock); | 67 | get_fs_root(current->fs, &root); |
69 | root = current->fs->root; | ||
70 | /* released below */ | ||
71 | path_get(&root); | ||
72 | read_unlock(¤t->fs->lock); | ||
73 | } else { | 68 | } else { |
74 | /* resolve paths relative to namespace */ | 69 | /* resolve paths relative to namespace */ |
75 | root.mnt = current->nsproxy->mnt_ns->root; | 70 | root.mnt = current->nsproxy->mnt_ns->root; |
76 | root.dentry = root.mnt->mnt_root; | 71 | root.dentry = root.mnt->mnt_root; |
77 | /* released below */ | ||
78 | path_get(&root); | 72 | path_get(&root); |
79 | } | 73 | } |
80 | 74 | ||
81 | spin_lock(&dcache_lock); | 75 | spin_lock(&dcache_lock); |
82 | /* There is a race window between path lookup here and the | 76 | tmp = root; |
83 | * need to strip the " (deleted) string that __d_path applies | 77 | res = __d_path(path, &tmp, buf, buflen); |
84 | * Detect the race and relookup the path | ||
85 | * | ||
86 | * The stripping of (deleted) is a hack that could be removed | ||
87 | * with an updated __d_path | ||
88 | */ | ||
89 | do { | ||
90 | tmp = root; | ||
91 | deleted = d_unlinked(path->dentry); | ||
92 | res = __d_path(path, &tmp, buf, buflen); | ||
93 | |||
94 | } while (deleted != d_unlinked(path->dentry)); | ||
95 | spin_unlock(&dcache_lock); | 78 | spin_unlock(&dcache_lock); |
96 | 79 | ||
97 | *name = res; | 80 | *name = res; |
@@ -103,21 +86,17 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, | |||
103 | *name = buf; | 86 | *name = buf; |
104 | goto out; | 87 | goto out; |
105 | } | 88 | } |
106 | if (deleted) { | ||
107 | /* On some filesystems, newly allocated dentries appear to the | ||
108 | * security_path hooks as a deleted dentry except without an | ||
109 | * inode allocated. | ||
110 | * | ||
111 | * Remove the appended deleted text and return as string for | ||
112 | * normal mediation, or auditing. The (deleted) string is | ||
113 | * guaranteed to be added in this case, so just strip it. | ||
114 | */ | ||
115 | buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */ | ||
116 | 89 | ||
117 | if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) { | 90 | /* Handle two cases: |
91 | * 1. A deleted dentry && profile is not allowing mediation of deleted | ||
92 | * 2. On some filesystems, newly allocated dentries appear to the | ||
93 | * security_path hooks as a deleted dentry except without an inode | ||
94 | * allocated. | ||
95 | */ | ||
96 | if (d_unlinked(path->dentry) && path->dentry->d_inode && | ||
97 | !(flags & PATH_MEDIATE_DELETED)) { | ||
118 | error = -ENOENT; | 98 | error = -ENOENT; |
119 | goto out; | 99 | goto out; |
120 | } | ||
121 | } | 100 | } |
122 | 101 | ||
123 | /* Determine if the path is connected to the expected root */ | 102 | /* Determine if the path is connected to the expected root */ |
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 3cdc1ad0787e..52cc865f1464 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
@@ -1151,12 +1151,14 @@ ssize_t aa_remove_profiles(char *fqname, size_t size) | |||
1151 | /* released below */ | 1151 | /* released below */ |
1152 | ns = aa_get_namespace(root); | 1152 | ns = aa_get_namespace(root); |
1153 | 1153 | ||
1154 | write_lock(&ns->lock); | ||
1155 | if (!name) { | 1154 | if (!name) { |
1156 | /* remove namespace - can only happen if fqname[0] == ':' */ | 1155 | /* remove namespace - can only happen if fqname[0] == ':' */ |
1156 | write_lock(&ns->parent->lock); | ||
1157 | __remove_namespace(ns); | 1157 | __remove_namespace(ns); |
1158 | write_unlock(&ns->parent->lock); | ||
1158 | } else { | 1159 | } else { |
1159 | /* remove profile */ | 1160 | /* remove profile */ |
1161 | write_lock(&ns->lock); | ||
1160 | profile = aa_get_profile(__lookup_profile(&ns->base, name)); | 1162 | profile = aa_get_profile(__lookup_profile(&ns->base, name)); |
1161 | if (!profile) { | 1163 | if (!profile) { |
1162 | error = -ENOENT; | 1164 | error = -ENOENT; |
@@ -1165,8 +1167,8 @@ ssize_t aa_remove_profiles(char *fqname, size_t size) | |||
1165 | } | 1167 | } |
1166 | name = profile->base.hname; | 1168 | name = profile->base.hname; |
1167 | __remove_profile(profile); | 1169 | __remove_profile(profile); |
1170 | write_unlock(&ns->lock); | ||
1168 | } | 1171 | } |
1169 | write_unlock(&ns->lock); | ||
1170 | 1172 | ||
1171 | /* don't fail removal if audit fails */ | 1173 | /* don't fail removal if audit fails */ |
1172 | (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error); | 1174 | (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error); |
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index 4a368f1fd36d..a4136c10b1c6 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c | |||
@@ -72,6 +72,7 @@ int aa_map_resource(int resource) | |||
72 | /** | 72 | /** |
73 | * aa_task_setrlimit - test permission to set an rlimit | 73 | * aa_task_setrlimit - test permission to set an rlimit |
74 | * @profile - profile confining the task (NOT NULL) | 74 | * @profile - profile confining the task (NOT NULL) |
75 | * @task - task the resource is being set on | ||
75 | * @resource - the resource being set | 76 | * @resource - the resource being set |
76 | * @new_rlim - the new resource limit (NOT NULL) | 77 | * @new_rlim - the new resource limit (NOT NULL) |
77 | * | 78 | * |
@@ -79,18 +80,21 @@ int aa_map_resource(int resource) | |||
79 | * | 80 | * |
80 | * Returns: 0 or error code if setting resource failed | 81 | * Returns: 0 or error code if setting resource failed |
81 | */ | 82 | */ |
82 | int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource, | 83 | int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, |
83 | struct rlimit *new_rlim) | 84 | unsigned int resource, struct rlimit *new_rlim) |
84 | { | 85 | { |
85 | int error = 0; | 86 | int error = 0; |
86 | 87 | ||
87 | if (profile->rlimits.mask & (1 << resource) && | 88 | /* TODO: extend resource control to handle other (non current) |
88 | new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) | 89 | * processes. AppArmor rules currently have the implicit assumption |
89 | 90 | * that the task is setting the resource of the current process | |
90 | error = audit_resource(profile, resource, new_rlim->rlim_max, | 91 | */ |
91 | -EACCES); | 92 | if ((task != current->group_leader) || |
93 | (profile->rlimits.mask & (1 << resource) && | ||
94 | new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)) | ||
95 | error = -EACCES; | ||
92 | 96 | ||
93 | return error; | 97 | return audit_resource(profile, resource, new_rlim->rlim_max, error); |
94 | } | 98 | } |
95 | 99 | ||
96 | /** | 100 | /** |
diff --git a/security/capability.c b/security/capability.c index a0bbf30fb6dc..95a6599a37bb 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -411,7 +411,8 @@ static int cap_task_getioprio(struct task_struct *p) | |||
411 | return 0; | 411 | return 0; |
412 | } | 412 | } |
413 | 413 | ||
414 | static int cap_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) | 414 | static int cap_task_setrlimit(struct task_struct *p, unsigned int resource, |
415 | struct rlimit *new_rlim) | ||
415 | { | 416 | { |
416 | return 0; | 417 | return 0; |
417 | } | 418 | } |
diff --git a/security/commoncap.c b/security/commoncap.c index 4e015996dd4d..9d172e6e330c 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -40,7 +40,7 @@ | |||
40 | * | 40 | * |
41 | * Warn if that happens, once per boot. | 41 | * Warn if that happens, once per boot. |
42 | */ | 42 | */ |
43 | static void warn_setuid_and_fcaps_mixed(char *fname) | 43 | static void warn_setuid_and_fcaps_mixed(const char *fname) |
44 | { | 44 | { |
45 | static int warned; | 45 | static int warned; |
46 | if (!warned) { | 46 | if (!warned) { |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 16d100d3fc38..3fbcd1dda0ef 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -35,6 +35,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; | |||
35 | #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) | 35 | #define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS) |
36 | 36 | ||
37 | /* set during initialization */ | 37 | /* set during initialization */ |
38 | extern int iint_initialized; | ||
38 | extern int ima_initialized; | 39 | extern int ima_initialized; |
39 | extern int ima_used_chip; | 40 | extern int ima_used_chip; |
40 | extern char *ima_hash; | 41 | extern char *ima_hash; |
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index 7625b85c2274..afba4aef812f 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c | |||
@@ -22,9 +22,10 @@ | |||
22 | 22 | ||
23 | RADIX_TREE(ima_iint_store, GFP_ATOMIC); | 23 | RADIX_TREE(ima_iint_store, GFP_ATOMIC); |
24 | DEFINE_SPINLOCK(ima_iint_lock); | 24 | DEFINE_SPINLOCK(ima_iint_lock); |
25 | |||
26 | static struct kmem_cache *iint_cache __read_mostly; | 25 | static struct kmem_cache *iint_cache __read_mostly; |
27 | 26 | ||
27 | int iint_initialized = 0; | ||
28 | |||
28 | /* ima_iint_find_get - return the iint associated with an inode | 29 | /* ima_iint_find_get - return the iint associated with an inode |
29 | * | 30 | * |
30 | * ima_iint_find_get gets a reference to the iint. Caller must | 31 | * ima_iint_find_get gets a reference to the iint. Caller must |
@@ -141,6 +142,7 @@ static int __init ima_iintcache_init(void) | |||
141 | iint_cache = | 142 | iint_cache = |
142 | kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, | 143 | kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, |
143 | SLAB_PANIC, init_once); | 144 | SLAB_PANIC, init_once); |
145 | iint_initialized = 1; | ||
144 | return 0; | 146 | return 0; |
145 | } | 147 | } |
146 | security_initcall(ima_iintcache_init); | 148 | security_initcall(ima_iintcache_init); |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index f93641382e9f..e662b89d4079 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -148,12 +148,14 @@ void ima_counts_get(struct file *file) | |||
148 | struct ima_iint_cache *iint; | 148 | struct ima_iint_cache *iint; |
149 | int rc; | 149 | int rc; |
150 | 150 | ||
151 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 151 | if (!iint_initialized || !S_ISREG(inode->i_mode)) |
152 | return; | 152 | return; |
153 | iint = ima_iint_find_get(inode); | 153 | iint = ima_iint_find_get(inode); |
154 | if (!iint) | 154 | if (!iint) |
155 | return; | 155 | return; |
156 | mutex_lock(&iint->mutex); | 156 | mutex_lock(&iint->mutex); |
157 | if (!ima_initialized) | ||
158 | goto out; | ||
157 | rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); | 159 | rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); |
158 | if (rc < 0) | 160 | if (rc < 0) |
159 | goto out; | 161 | goto out; |
@@ -213,7 +215,7 @@ void ima_file_free(struct file *file) | |||
213 | struct inode *inode = file->f_dentry->d_inode; | 215 | struct inode *inode = file->f_dentry->d_inode; |
214 | struct ima_iint_cache *iint; | 216 | struct ima_iint_cache *iint; |
215 | 217 | ||
216 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 218 | if (!iint_initialized || !S_ISREG(inode->i_mode)) |
217 | return; | 219 | return; |
218 | iint = ima_iint_find_get(inode); | 220 | iint = ima_iint_find_get(inode); |
219 | if (!iint) | 221 | if (!iint) |
@@ -230,7 +232,7 @@ static int process_measurement(struct file *file, const unsigned char *filename, | |||
230 | { | 232 | { |
231 | struct inode *inode = file->f_dentry->d_inode; | 233 | struct inode *inode = file->f_dentry->d_inode; |
232 | struct ima_iint_cache *iint; | 234 | struct ima_iint_cache *iint; |
233 | int rc; | 235 | int rc = 0; |
234 | 236 | ||
235 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 237 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
236 | return 0; | 238 | return 0; |
diff --git a/security/keys/internal.h b/security/keys/internal.h index addb67b169f4..56a133d8f37d 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -15,11 +15,6 @@ | |||
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/key-type.h> | 16 | #include <linux/key-type.h> |
17 | 17 | ||
18 | static inline __attribute__((format(printf, 1, 2))) | ||
19 | void no_printk(const char *fmt, ...) | ||
20 | { | ||
21 | } | ||
22 | |||
23 | #ifdef __KDEBUG | 18 | #ifdef __KDEBUG |
24 | #define kenter(FMT, ...) \ | 19 | #define kenter(FMT, ...) \ |
25 | printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) | 20 | printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index b2b0998d6abd..60924f6a52db 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1272,6 +1272,7 @@ long keyctl_session_to_parent(void) | |||
1272 | keyring_r = NULL; | 1272 | keyring_r = NULL; |
1273 | 1273 | ||
1274 | me = current; | 1274 | me = current; |
1275 | rcu_read_lock(); | ||
1275 | write_lock_irq(&tasklist_lock); | 1276 | write_lock_irq(&tasklist_lock); |
1276 | 1277 | ||
1277 | parent = me->real_parent; | 1278 | parent = me->real_parent; |
@@ -1304,7 +1305,8 @@ long keyctl_session_to_parent(void) | |||
1304 | goto not_permitted; | 1305 | goto not_permitted; |
1305 | 1306 | ||
1306 | /* the keyrings must have the same UID */ | 1307 | /* the keyrings must have the same UID */ |
1307 | if (pcred->tgcred->session_keyring->uid != mycred->euid || | 1308 | if ((pcred->tgcred->session_keyring && |
1309 | pcred->tgcred->session_keyring->uid != mycred->euid) || | ||
1308 | mycred->tgcred->session_keyring->uid != mycred->euid) | 1310 | mycred->tgcred->session_keyring->uid != mycred->euid) |
1309 | goto not_permitted; | 1311 | goto not_permitted; |
1310 | 1312 | ||
@@ -1319,6 +1321,7 @@ long keyctl_session_to_parent(void) | |||
1319 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); | 1321 | set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME); |
1320 | 1322 | ||
1321 | write_unlock_irq(&tasklist_lock); | 1323 | write_unlock_irq(&tasklist_lock); |
1324 | rcu_read_unlock(); | ||
1322 | if (oldcred) | 1325 | if (oldcred) |
1323 | put_cred(oldcred); | 1326 | put_cred(oldcred); |
1324 | return 0; | 1327 | return 0; |
@@ -1327,6 +1330,7 @@ already_same: | |||
1327 | ret = 0; | 1330 | ret = 0; |
1328 | not_permitted: | 1331 | not_permitted: |
1329 | write_unlock_irq(&tasklist_lock); | 1332 | write_unlock_irq(&tasklist_lock); |
1333 | rcu_read_unlock(); | ||
1330 | put_cred(cred); | 1334 | put_cred(cred); |
1331 | return ret; | 1335 | return ret; |
1332 | 1336 | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 0d26f689bd77..0088dd8bf68a 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -537,6 +537,8 @@ int wait_for_key_construction(struct key *key, bool intr) | |||
537 | intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); | 537 | intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); |
538 | if (ret < 0) | 538 | if (ret < 0) |
539 | return ret; | 539 | return ret; |
540 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) | ||
541 | return -ENOKEY; | ||
540 | return key_validate(key); | 542 | return key_validate(key); |
541 | } | 543 | } |
542 | EXPORT_SYMBOL(wait_for_key_construction); | 544 | EXPORT_SYMBOL(wait_for_key_construction); |
diff --git a/security/security.c b/security/security.c index e8c87b8601b4..c53949f17d9e 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -619,7 +619,13 @@ void security_inode_getsecid(const struct inode *inode, u32 *secid) | |||
619 | 619 | ||
620 | int security_file_permission(struct file *file, int mask) | 620 | int security_file_permission(struct file *file, int mask) |
621 | { | 621 | { |
622 | return security_ops->file_permission(file, mask); | 622 | int ret; |
623 | |||
624 | ret = security_ops->file_permission(file, mask); | ||
625 | if (ret) | ||
626 | return ret; | ||
627 | |||
628 | return fsnotify_perm(file, mask); | ||
623 | } | 629 | } |
624 | 630 | ||
625 | int security_file_alloc(struct file *file) | 631 | int security_file_alloc(struct file *file) |
@@ -683,7 +689,13 @@ int security_file_receive(struct file *file) | |||
683 | 689 | ||
684 | int security_dentry_open(struct file *file, const struct cred *cred) | 690 | int security_dentry_open(struct file *file, const struct cred *cred) |
685 | { | 691 | { |
686 | return security_ops->dentry_open(file, cred); | 692 | int ret; |
693 | |||
694 | ret = security_ops->dentry_open(file, cred); | ||
695 | if (ret) | ||
696 | return ret; | ||
697 | |||
698 | return fsnotify_perm(file, MAY_OPEN); | ||
687 | } | 699 | } |
688 | 700 | ||
689 | int security_task_create(unsigned long clone_flags) | 701 | int security_task_create(unsigned long clone_flags) |
@@ -768,9 +780,10 @@ int security_task_getioprio(struct task_struct *p) | |||
768 | return security_ops->task_getioprio(p); | 780 | return security_ops->task_getioprio(p); |
769 | } | 781 | } |
770 | 782 | ||
771 | int security_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) | 783 | int security_task_setrlimit(struct task_struct *p, unsigned int resource, |
784 | struct rlimit *new_rlim) | ||
772 | { | 785 | { |
773 | return security_ops->task_setrlimit(resource, new_rlim); | 786 | return security_ops->task_setrlimit(p, resource, new_rlim); |
774 | } | 787 | } |
775 | 788 | ||
776 | int security_task_setscheduler(struct task_struct *p, | 789 | int security_task_setscheduler(struct task_struct *p, |
diff --git a/security/selinux/Makefile b/security/selinux/Makefile index f013982df417..58d80f3bd6f6 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile | |||
@@ -25,6 +25,6 @@ $(obj)/avc.o: $(obj)/flask.h | |||
25 | quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h | 25 | quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h |
26 | cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h | 26 | cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h |
27 | 27 | ||
28 | targets += flask.h | 28 | targets += flask.h av_permissions.h |
29 | $(obj)/flask.h: $(src)/include/classmap.h FORCE | 29 | $(obj)/flask.h: $(src)/include/classmap.h FORCE |
30 | $(call if_changed,flask) | 30 | $(call if_changed,flask) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9b40f4c0ac70..4796ddd4e721 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -2170,8 +2170,9 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2170 | 2170 | ||
2171 | tty = get_current_tty(); | 2171 | tty = get_current_tty(); |
2172 | if (tty) { | 2172 | if (tty) { |
2173 | file_list_lock(); | 2173 | spin_lock(&tty_files_lock); |
2174 | if (!list_empty(&tty->tty_files)) { | 2174 | if (!list_empty(&tty->tty_files)) { |
2175 | struct tty_file_private *file_priv; | ||
2175 | struct inode *inode; | 2176 | struct inode *inode; |
2176 | 2177 | ||
2177 | /* Revalidate access to controlling tty. | 2178 | /* Revalidate access to controlling tty. |
@@ -2179,14 +2180,16 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2179 | than using file_has_perm, as this particular open | 2180 | than using file_has_perm, as this particular open |
2180 | file may belong to another process and we are only | 2181 | file may belong to another process and we are only |
2181 | interested in the inode-based check here. */ | 2182 | interested in the inode-based check here. */ |
2182 | file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list); | 2183 | file_priv = list_first_entry(&tty->tty_files, |
2184 | struct tty_file_private, list); | ||
2185 | file = file_priv->file; | ||
2183 | inode = file->f_path.dentry->d_inode; | 2186 | inode = file->f_path.dentry->d_inode; |
2184 | if (inode_has_perm(cred, inode, | 2187 | if (inode_has_perm(cred, inode, |
2185 | FILE__READ | FILE__WRITE, NULL)) { | 2188 | FILE__READ | FILE__WRITE, NULL)) { |
2186 | drop_tty = 1; | 2189 | drop_tty = 1; |
2187 | } | 2190 | } |
2188 | } | 2191 | } |
2189 | file_list_unlock(); | 2192 | spin_unlock(&tty_files_lock); |
2190 | tty_kref_put(tty); | 2193 | tty_kref_put(tty); |
2191 | } | 2194 | } |
2192 | /* Reset controlling tty. */ | 2195 | /* Reset controlling tty. */ |
@@ -2284,12 +2287,15 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | |||
2284 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, | 2287 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, |
2285 | PROCESS__RLIMITINH, NULL); | 2288 | PROCESS__RLIMITINH, NULL); |
2286 | if (rc) { | 2289 | if (rc) { |
2290 | /* protect against do_prlimit() */ | ||
2291 | task_lock(current); | ||
2287 | for (i = 0; i < RLIM_NLIMITS; i++) { | 2292 | for (i = 0; i < RLIM_NLIMITS; i++) { |
2288 | rlim = current->signal->rlim + i; | 2293 | rlim = current->signal->rlim + i; |
2289 | initrlim = init_task.signal->rlim + i; | 2294 | initrlim = init_task.signal->rlim + i; |
2290 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2295 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
2291 | } | 2296 | } |
2292 | update_rlimit_cpu(current->signal->rlim[RLIMIT_CPU].rlim_cur); | 2297 | task_unlock(current); |
2298 | update_rlimit_cpu(current, rlimit(RLIMIT_CPU)); | ||
2293 | } | 2299 | } |
2294 | } | 2300 | } |
2295 | 2301 | ||
@@ -3333,16 +3339,17 @@ static int selinux_task_getioprio(struct task_struct *p) | |||
3333 | return current_has_perm(p, PROCESS__GETSCHED); | 3339 | return current_has_perm(p, PROCESS__GETSCHED); |
3334 | } | 3340 | } |
3335 | 3341 | ||
3336 | static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) | 3342 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, |
3343 | struct rlimit *new_rlim) | ||
3337 | { | 3344 | { |
3338 | struct rlimit *old_rlim = current->signal->rlim + resource; | 3345 | struct rlimit *old_rlim = p->signal->rlim + resource; |
3339 | 3346 | ||
3340 | /* Control the ability to change the hard limit (whether | 3347 | /* Control the ability to change the hard limit (whether |
3341 | lowering or raising it), so that the hard limit can | 3348 | lowering or raising it), so that the hard limit can |
3342 | later be used as a safe reset point for the soft limit | 3349 | later be used as a safe reset point for the soft limit |
3343 | upon context transitions. See selinux_bprm_committing_creds. */ | 3350 | upon context transitions. See selinux_bprm_committing_creds. */ |
3344 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3351 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
3345 | return current_has_perm(current, PROCESS__SETRLIMIT); | 3352 | return current_has_perm(p, PROCESS__SETRLIMIT); |
3346 | 3353 | ||
3347 | return 0; | 3354 | return 0; |
3348 | } | 3355 | } |
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ef43995119a4..c668b447c725 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -1416,15 +1416,19 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r) | |||
1416 | const pid_t gpid = task_pid_nr(current); | 1416 | const pid_t gpid = task_pid_nr(current); |
1417 | static const int tomoyo_buffer_len = 4096; | 1417 | static const int tomoyo_buffer_len = 4096; |
1418 | char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); | 1418 | char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); |
1419 | pid_t ppid; | ||
1419 | if (!buffer) | 1420 | if (!buffer) |
1420 | return NULL; | 1421 | return NULL; |
1421 | do_gettimeofday(&tv); | 1422 | do_gettimeofday(&tv); |
1423 | rcu_read_lock(); | ||
1424 | ppid = task_tgid_vnr(current->real_parent); | ||
1425 | rcu_read_unlock(); | ||
1422 | snprintf(buffer, tomoyo_buffer_len - 1, | 1426 | snprintf(buffer, tomoyo_buffer_len - 1, |
1423 | "#timestamp=%lu profile=%u mode=%s (global-pid=%u)" | 1427 | "#timestamp=%lu profile=%u mode=%s (global-pid=%u)" |
1424 | " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u" | 1428 | " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u" |
1425 | " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", | 1429 | " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", |
1426 | tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid, | 1430 | tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid, |
1427 | (pid_t) sys_getpid(), (pid_t) sys_getppid(), | 1431 | task_tgid_vnr(current), ppid, |
1428 | current_uid(), current_gid(), current_euid(), | 1432 | current_uid(), current_gid(), current_euid(), |
1429 | current_egid(), current_suid(), current_sgid(), | 1433 | current_egid(), current_suid(), current_sgid(), |
1430 | current_fsuid(), current_fsgid()); | 1434 | current_fsuid(), current_fsgid()); |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 04454cb7b24a..7c66bd898782 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -689,9 +689,6 @@ struct tomoyo_profile { | |||
689 | 689 | ||
690 | /********** Function prototypes. **********/ | 690 | /********** Function prototypes. **********/ |
691 | 691 | ||
692 | extern asmlinkage long sys_getpid(void); | ||
693 | extern asmlinkage long sys_getppid(void); | ||
694 | |||
695 | /* Check whether the given string starts with the given keyword. */ | 692 | /* Check whether the given string starts with the given keyword. */ |
696 | bool tomoyo_str_starts(char **src, const char *find); | 693 | bool tomoyo_str_starts(char **src, const char *find); |
697 | /* Get tomoyo_realpath() of current process. */ | 694 | /* Get tomoyo_realpath() of current process. */ |