aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2015-05-02 18:11:42 -0400
committerJames Morris <james.l.morris@oracle.com>2015-05-12 01:00:41 -0400
commitb1d9e6b0646d0e5ee5d9050bd236b6c65d66faef (patch)
treebefe73902cf0797dabb704cf6688b3fe335fc19e /security/apparmor
parente20b043a6902ecb61c2c84355c3bae5149f391db (diff)
LSM: Switch to lists of hooks
Instead of using a vector of security operations with explicit, special case stacking of the capability and yama hooks use lists of hooks with capability and yama hooks included as appropriate. The security_operations structure is no longer required. Instead, there is a union of the function pointers that allows all the hooks lists to use a common mechanism for list management while retaining typing. Each module supplies an array describing the hooks it provides instead of a sparsely populated security_operations structure. The description includes the element that gets put on the hook list, avoiding the issues surrounding individual element allocation. The method for registering security modules is changed to reflect the information available. The method for removing a module, currently only used by SELinux, has also changed. It should be generic now, however if there are potential race conditions based on ordering of hook removal that needs to be addressed by the calling module. The security hooks are called from the lists and the first failure is returned. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Acked-by: John Johansen <john.johansen@canonical.com> Acked-by: Kees Cook <keescook@chromium.org> Acked-by: Paul Moore <paul@paul-moore.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Acked-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <james.l.morris@oracle.com>
Diffstat (limited to 'security/apparmor')
-rw-r--r--security/apparmor/domain.c12
-rw-r--r--security/apparmor/lsm.c51
2 files changed, 18 insertions, 45 deletions
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index d97cba3e3849..dc0027b28b04 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -347,9 +347,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
347 file_inode(bprm->file)->i_mode 347 file_inode(bprm->file)->i_mode
348 }; 348 };
349 const char *name = NULL, *target = NULL, *info = NULL; 349 const char *name = NULL, *target = NULL, *info = NULL;
350 int error = cap_bprm_set_creds(bprm); 350 int error = 0;
351 if (error)
352 return error;
353 351
354 if (bprm->cred_prepared) 352 if (bprm->cred_prepared)
355 return 0; 353 return 0;
@@ -531,15 +529,13 @@ cleanup:
531 */ 529 */
532int apparmor_bprm_secureexec(struct linux_binprm *bprm) 530int apparmor_bprm_secureexec(struct linux_binprm *bprm)
533{ 531{
534 int ret = cap_bprm_secureexec(bprm);
535
536 /* the decision to use secure exec is computed in set_creds 532 /* the decision to use secure exec is computed in set_creds
537 * and stored in bprm->unsafe. 533 * and stored in bprm->unsafe.
538 */ 534 */
539 if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED)) 535 if (bprm->unsafe & AA_SECURE_X_NEEDED)
540 ret = 1; 536 return 1;
541 537
542 return ret; 538 return 0;
543} 539}
544 540
545/** 541/**
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index f54253258fb8..5696874e8062 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -96,19 +96,11 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
96static int apparmor_ptrace_access_check(struct task_struct *child, 96static int apparmor_ptrace_access_check(struct task_struct *child,
97 unsigned int mode) 97 unsigned int mode)
98{ 98{
99 int error = cap_ptrace_access_check(child, mode);
100 if (error)
101 return error;
102
103 return aa_ptrace(current, child, mode); 99 return aa_ptrace(current, child, mode);
104} 100}
105 101
106static int apparmor_ptrace_traceme(struct task_struct *parent) 102static int apparmor_ptrace_traceme(struct task_struct *parent)
107{ 103{
108 int error = cap_ptrace_traceme(parent);
109 if (error)
110 return error;
111
112 return aa_ptrace(parent, current, PTRACE_MODE_ATTACH); 104 return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
113} 105}
114 106
@@ -123,10 +115,10 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
123 cred = __task_cred(target); 115 cred = __task_cred(target);
124 profile = aa_cred_profile(cred); 116 profile = aa_cred_profile(cred);
125 117
126 *effective = cred->cap_effective; 118 /*
127 *inheritable = cred->cap_inheritable; 119 * cap_capget is stacked ahead of this and will
128 *permitted = cred->cap_permitted; 120 * initialize effective and permitted.
129 121 */
130 if (!unconfined(profile) && !COMPLAIN_MODE(profile)) { 122 if (!unconfined(profile) && !COMPLAIN_MODE(profile)) {
131 *effective = cap_intersect(*effective, profile->caps.allow); 123 *effective = cap_intersect(*effective, profile->caps.allow);
132 *permitted = cap_intersect(*permitted, profile->caps.allow); 124 *permitted = cap_intersect(*permitted, profile->caps.allow);
@@ -140,13 +132,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
140 int cap, int audit) 132 int cap, int audit)
141{ 133{
142 struct aa_profile *profile; 134 struct aa_profile *profile;
143 /* cap_capable returns 0 on success, else -EPERM */ 135 int error = 0;
144 int error = cap_capable(cred, ns, cap, audit); 136
145 if (!error) { 137 profile = aa_cred_profile(cred);
146 profile = aa_cred_profile(cred); 138 if (!unconfined(profile))
147 if (!unconfined(profile)) 139 error = aa_capable(profile, cap, audit);
148 error = aa_capable(profile, cap, audit);
149 }
150 return error; 140 return error;
151} 141}
152 142
@@ -615,9 +605,7 @@ static int apparmor_task_setrlimit(struct task_struct *task,
615 return error; 605 return error;
616} 606}
617 607
618static struct security_operations apparmor_ops = { 608static struct security_hook_list apparmor_hooks[] = {
619 LSM_HOOK_INIT(name, "apparmor"),
620
621 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), 609 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
622 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), 610 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
623 LSM_HOOK_INIT(capget, apparmor_capget), 611 LSM_HOOK_INIT(capget, apparmor_capget),
@@ -640,7 +628,6 @@ static struct security_operations apparmor_ops = {
640 LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security), 628 LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security),
641 LSM_HOOK_INIT(file_free_security, apparmor_file_free_security), 629 LSM_HOOK_INIT(file_free_security, apparmor_file_free_security),
642 LSM_HOOK_INIT(mmap_file, apparmor_mmap_file), 630 LSM_HOOK_INIT(mmap_file, apparmor_mmap_file),
643 LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
644 LSM_HOOK_INIT(file_mprotect, apparmor_file_mprotect), 631 LSM_HOOK_INIT(file_mprotect, apparmor_file_mprotect),
645 LSM_HOOK_INIT(file_lock, apparmor_file_lock), 632 LSM_HOOK_INIT(file_lock, apparmor_file_lock),
646 633
@@ -898,7 +885,7 @@ static int __init apparmor_init(void)
898{ 885{
899 int error; 886 int error;
900 887
901 if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) { 888 if (!apparmor_enabled || !security_module_enable("apparmor")) {
902 aa_info_message("AppArmor disabled by boot time parameter"); 889 aa_info_message("AppArmor disabled by boot time parameter");
903 apparmor_enabled = 0; 890 apparmor_enabled = 0;
904 return 0; 891 return 0;
@@ -913,17 +900,10 @@ static int __init apparmor_init(void)
913 error = set_init_cxt(); 900 error = set_init_cxt();
914 if (error) { 901 if (error) {
915 AA_ERROR("Failed to set context on init task\n"); 902 AA_ERROR("Failed to set context on init task\n");
916 goto register_security_out; 903 aa_free_root_ns();
917 } 904 goto alloc_out;
918
919 error = register_security(&apparmor_ops);
920 if (error) {
921 struct cred *cred = (struct cred *)current->real_cred;
922 aa_free_task_context(cred_cxt(cred));
923 cred_cxt(cred) = NULL;
924 AA_ERROR("Unable to register AppArmor\n");
925 goto register_security_out;
926 } 905 }
906 security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks));
927 907
928 /* Report that AppArmor successfully initialized */ 908 /* Report that AppArmor successfully initialized */
929 apparmor_initialized = 1; 909 apparmor_initialized = 1;
@@ -936,9 +916,6 @@ static int __init apparmor_init(void)
936 916
937 return error; 917 return error;
938 918
939register_security_out:
940 aa_free_root_ns();
941
942alloc_out: 919alloc_out:
943 aa_destroy_aafs(); 920 aa_destroy_aafs();
944 921