aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor')
-rw-r--r--security/apparmor/domain.c35
-rw-r--r--security/apparmor/path.c2
-rw-r--r--security/apparmor/policy.c4
3 files changed, 41 insertions, 0 deletions
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 6327685c101e..b81ea10a17a3 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -394,6 +394,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
394 new_profile = find_attach(ns, &ns->base.profiles, name); 394 new_profile = find_attach(ns, &ns->base.profiles, name);
395 if (!new_profile) 395 if (!new_profile)
396 goto cleanup; 396 goto cleanup;
397 /*
398 * NOTE: Domain transitions from unconfined are allowed
399 * even when no_new_privs is set because this aways results
400 * in a further reduction of permissions.
401 */
397 goto apply; 402 goto apply;
398 } 403 }
399 404
@@ -455,6 +460,16 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
455 /* fail exec */ 460 /* fail exec */
456 error = -EACCES; 461 error = -EACCES;
457 462
463 /*
464 * Policy has specified a domain transition, if no_new_privs then
465 * fail the exec.
466 */
467 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
468 aa_put_profile(new_profile);
469 error = -EPERM;
470 goto cleanup;
471 }
472
458 if (!new_profile) 473 if (!new_profile)
459 goto audit; 474 goto audit;
460 475
@@ -609,6 +624,14 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
609 const char *target = NULL, *info = NULL; 624 const char *target = NULL, *info = NULL;
610 int error = 0; 625 int error = 0;
611 626
627 /*
628 * Fail explicitly requested domain transitions if no_new_privs.
629 * There is no exception for unconfined as change_hat is not
630 * available.
631 */
632 if (current->no_new_privs)
633 return -EPERM;
634
612 /* released below */ 635 /* released below */
613 cred = get_current_cred(); 636 cred = get_current_cred();
614 cxt = cred->security; 637 cxt = cred->security;
@@ -750,6 +773,18 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
750 cxt = cred->security; 773 cxt = cred->security;
751 profile = aa_cred_profile(cred); 774 profile = aa_cred_profile(cred);
752 775
776 /*
777 * Fail explicitly requested domain transitions if no_new_privs
778 * and not unconfined.
779 * Domain transitions from unconfined are allowed even when
780 * no_new_privs is set because this aways results in a reduction
781 * of permissions.
782 */
783 if (current->no_new_privs && !unconfined(profile)) {
784 put_cred(cred);
785 return -EPERM;
786 }
787
753 if (ns_name) { 788 if (ns_name) {
754 /* released below */ 789 /* released below */
755 ns = aa_find_namespace(profile->ns, ns_name); 790 ns = aa_find_namespace(profile->ns, ns_name);
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index 2daeea4f9266..e91ffee80162 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -94,6 +94,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
94 * be returned. 94 * be returned.
95 */ 95 */
96 if (!res || IS_ERR(res)) { 96 if (!res || IS_ERR(res)) {
97 if (PTR_ERR(res) == -ENAMETOOLONG)
98 return -ENAMETOOLONG;
97 connected = 0; 99 connected = 0;
98 res = dentry_path_raw(path->dentry, buf, buflen); 100 res = dentry_path_raw(path->dentry, buf, buflen);
99 if (IS_ERR(res)) { 101 if (IS_ERR(res)) {
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 421681c7c346..cf5fd220309b 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -903,6 +903,10 @@ struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname)
903 profile = aa_get_profile(__lookup_profile(&ns->base, hname)); 903 profile = aa_get_profile(__lookup_profile(&ns->base, hname));
904 read_unlock(&ns->lock); 904 read_unlock(&ns->lock);
905 905
906 /* the unconfined profile is not in the regular profile list */
907 if (!profile && strcmp(hname, "unconfined") == 0)
908 profile = aa_get_profile(ns->unconfined);
909
906 /* refcount released by caller */ 910 /* refcount released by caller */
907 return profile; 911 return profile;
908} 912}