diff options
author | John Johansen <john.johansen@canonical.com> | 2012-04-12 17:47:51 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2012-04-13 21:13:18 -0400 |
commit | c29bceb3967398cf2ac8bf8edf9634fdb722df7d (patch) | |
tree | 9feaa5a8b78812e48fa9b4e9b8b939f06390bee8 | |
parent | 259e5e6c75a910f3b5e656151dc602f53f9d7548 (diff) |
Fix execve behavior apparmor for PR_{GET,SET}_NO_NEW_PRIVS
Add support for AppArmor to explicitly fail requested domain transitions
if NO_NEW_PRIVS is set and the task is not unconfined.
Transitions from unconfined are still allowed because this always results
in a reduction of privileges.
Acked-by: Eric Paris <eparis@redhat.com>
Signed-off-by: Will Drewry <wad@chromium.org>
Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
v18: new acked-by, new description
Signed-off-by: James Morris <james.l.morris@oracle.com>
-rw-r--r-- | security/apparmor/domain.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 18c88d06e881..b81ea10a17a3 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c | |||
@@ -360,10 +360,6 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) | |||
360 | if (bprm->cred_prepared) | 360 | if (bprm->cred_prepared) |
361 | return 0; | 361 | return 0; |
362 | 362 | ||
363 | /* XXX: no_new_privs is not usable with AppArmor yet */ | ||
364 | if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) | ||
365 | return -EPERM; | ||
366 | |||
367 | cxt = bprm->cred->security; | 363 | cxt = bprm->cred->security; |
368 | BUG_ON(!cxt); | 364 | BUG_ON(!cxt); |
369 | 365 | ||
@@ -398,6 +394,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) | |||
398 | new_profile = find_attach(ns, &ns->base.profiles, name); | 394 | new_profile = find_attach(ns, &ns->base.profiles, name); |
399 | if (!new_profile) | 395 | if (!new_profile) |
400 | 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 | */ | ||
401 | goto apply; | 402 | goto apply; |
402 | } | 403 | } |
403 | 404 | ||
@@ -459,6 +460,16 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) | |||
459 | /* fail exec */ | 460 | /* fail exec */ |
460 | error = -EACCES; | 461 | error = -EACCES; |
461 | 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 | |||
462 | if (!new_profile) | 473 | if (!new_profile) |
463 | goto audit; | 474 | goto audit; |
464 | 475 | ||
@@ -613,6 +624,14 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) | |||
613 | const char *target = NULL, *info = NULL; | 624 | const char *target = NULL, *info = NULL; |
614 | int error = 0; | 625 | int error = 0; |
615 | 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 | |||
616 | /* released below */ | 635 | /* released below */ |
617 | cred = get_current_cred(); | 636 | cred = get_current_cred(); |
618 | cxt = cred->security; | 637 | cxt = cred->security; |
@@ -754,6 +773,18 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec, | |||
754 | cxt = cred->security; | 773 | cxt = cred->security; |
755 | profile = aa_cred_profile(cred); | 774 | profile = aa_cred_profile(cred); |
756 | 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 | |||
757 | if (ns_name) { | 788 | if (ns_name) { |
758 | /* released below */ | 789 | /* released below */ |
759 | ns = aa_find_namespace(profile->ns, ns_name); | 790 | ns = aa_find_namespace(profile->ns, ns_name); |