userns: Convert apparmor to use kuid and kgid where appropriate
[linux-3.10.git] / security / apparmor / domain.c
index 7c69599..60f0c76 100644 (file)
@@ -394,6 +394,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
                        new_profile = find_attach(ns, &ns->base.profiles, name);
                if (!new_profile)
                        goto cleanup;
+               /*
+                * NOTE: Domain transitions from unconfined are allowed
+                * even when no_new_privs is set because this aways results
+                * in a further reduction of permissions.
+                */
                goto apply;
        }
 
@@ -410,7 +415,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
                 * exec\0change_profile
                 */
                state = aa_dfa_null_transition(profile->file.dfa, state);
-               cp = change_profile_perms(profile, cxt->onexec->ns, name,
+               cp = change_profile_perms(profile, cxt->onexec->ns,
+                                         cxt->onexec->base.name,
                                          AA_MAY_ONEXEC, state);
 
                if (!(cp.allow & AA_MAY_ONEXEC))
@@ -454,6 +460,16 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
                /* fail exec */
                error = -EACCES;
 
+       /*
+        * Policy has specified a domain transition, if no_new_privs then
+        * fail the exec.
+        */
+       if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
+               aa_put_profile(new_profile);
+               error = -EPERM;
+               goto cleanup;
+       }
+
        if (!new_profile)
                goto audit;
 
@@ -608,6 +624,14 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
        const char *target = NULL, *info = NULL;
        int error = 0;
 
+       /*
+        * Fail explicitly requested domain transitions if no_new_privs.
+        * There is no exception for unconfined as change_hat is not
+        * available.
+        */
+       if (current->no_new_privs)
+               return -EPERM;
+
        /* released below */
        cred = get_current_cred();
        cxt = cred->security;
@@ -697,7 +721,7 @@ audit:
        if (!permtest)
                error = aa_audit_file(profile, &perms, GFP_KERNEL,
                                      OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL,
-                                     target, 0, info, error);
+                                     target, GLOBAL_ROOT_UID, info, error);
 
 out:
        aa_put_profile(hat);
@@ -749,6 +773,18 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
        cxt = cred->security;
        profile = aa_cred_profile(cred);
 
+       /*
+        * Fail explicitly requested domain transitions if no_new_privs
+        * and not unconfined.
+        * Domain transitions from unconfined are allowed even when
+        * no_new_privs is set because this aways results in a reduction
+        * of permissions.
+        */
+       if (current->no_new_privs && !unconfined(profile)) {
+               put_cred(cred);
+               return -EPERM;
+       }
+
        if (ns_name) {
                /* released below */
                ns = aa_find_namespace(profile->ns, ns_name);
@@ -812,7 +848,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
 audit:
        if (!permtest)
                error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request,
-                                     name, hname, 0, info, error);
+                                     name, hname, GLOBAL_ROOT_UID, info, error);
 
        aa_put_namespace(ns);
        aa_put_profile(target);