summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/apparmor/apparmorfs.c1
-rw-r--r--security/apparmor/domain.c163
-rw-r--r--security/apparmor/include/task.h4
-rw-r--r--security/apparmor/task.c7
4 files changed, 110 insertions, 65 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 874c1bf6b84a..07623fb41e32 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -2156,6 +2156,7 @@ static struct aa_sfs_entry aa_sfs_entry_domain[] = {
2156 AA_SFS_FILE_BOOLEAN("change_profile", 1), 2156 AA_SFS_FILE_BOOLEAN("change_profile", 1),
2157 AA_SFS_FILE_BOOLEAN("stack", 1), 2157 AA_SFS_FILE_BOOLEAN("stack", 1),
2158 AA_SFS_FILE_BOOLEAN("fix_binfmt_elf_mmap", 1), 2158 AA_SFS_FILE_BOOLEAN("fix_binfmt_elf_mmap", 1),
2159 AA_SFS_FILE_BOOLEAN("post_nnp_subset", 1),
2159 AA_SFS_FILE_STRING("version", "1.2"), 2160 AA_SFS_FILE_STRING("version", "1.2"),
2160 { } 2161 { }
2161}; 2162};
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index cd58eef4eb8d..9d1936519cfd 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -592,22 +592,6 @@ static struct aa_label *profile_transition(struct aa_profile *profile,
592 if (!new) 592 if (!new)
593 goto audit; 593 goto audit;
594 594
595 /* Policy has specified a domain transitions. if no_new_privs and
596 * confined and not transitioning to the current domain fail.
597 *
598 * NOTE: Domain transitions from unconfined and to stritly stacked
599 * subsets are allowed even when no_new_privs is set because this
600 * aways results in a further reduction of permissions.
601 */
602 if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) &&
603 !profile_unconfined(profile) &&
604 !aa_label_is_subset(new, &profile->label)) {
605 error = -EPERM;
606 info = "no new privs";
607 nonewprivs = true;
608 perms.allow &= ~MAY_EXEC;
609 goto audit;
610 }
611 595
612 if (!(perms.xindex & AA_X_UNSAFE)) { 596 if (!(perms.xindex & AA_X_UNSAFE)) {
613 if (DEBUG_ON) { 597 if (DEBUG_ON) {
@@ -684,21 +668,6 @@ static int profile_onexec(struct aa_profile *profile, struct aa_label *onexec,
684 perms.allow &= ~AA_MAY_ONEXEC; 668 perms.allow &= ~AA_MAY_ONEXEC;
685 goto audit; 669 goto audit;
686 } 670 }
687 /* Policy has specified a domain transitions. if no_new_privs and
688 * confined and not transitioning to the current domain fail.
689 *
690 * NOTE: Domain transitions from unconfined and to stritly stacked
691 * subsets are allowed even when no_new_privs is set because this
692 * aways results in a further reduction of permissions.
693 */
694 if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) &&
695 !profile_unconfined(profile) &&
696 !aa_label_is_subset(onexec, &profile->label)) {
697 error = -EPERM;
698 info = "no new privs";
699 perms.allow &= ~AA_MAY_ONEXEC;
700 goto audit;
701 }
702 671
703 if (!(perms.xindex & AA_X_UNSAFE)) { 672 if (!(perms.xindex & AA_X_UNSAFE)) {
704 if (DEBUG_ON) { 673 if (DEBUG_ON) {
@@ -800,6 +769,17 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
800 769
801 label = aa_get_newest_label(cred_label(bprm->cred)); 770 label = aa_get_newest_label(cred_label(bprm->cred));
802 771
772 /*
773 * Detect no new privs being set, and store the label it
774 * occurred under. Ideally this would happen when nnp
775 * is set but there isn't a good way to do that yet.
776 *
777 * Testing for unconfined must be done before the subset test
778 */
779 if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && !unconfined(label) &&
780 !ctx->nnp)
781 ctx->nnp = aa_get_label(label);
782
803 /* buffer freed below, name is pointer into buffer */ 783 /* buffer freed below, name is pointer into buffer */
804 get_buffers(buffer); 784 get_buffers(buffer);
805 /* Test for onexec first as onexec override other x transitions. */ 785 /* Test for onexec first as onexec override other x transitions. */
@@ -820,7 +800,20 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
820 goto done; 800 goto done;
821 } 801 }
822 802
823 /* TODO: Add ns level no_new_privs subset test */ 803 /* Policy has specified a domain transitions. If no_new_privs and
804 * confined ensure the transition is to confinement that is subset
805 * of the confinement when the task entered no new privs.
806 *
807 * NOTE: Domain transitions from unconfined and to stacked
808 * subsets are allowed even when no_new_privs is set because this
809 * aways results in a further reduction of permissions.
810 */
811 if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) &&
812 !unconfined(label) && !aa_label_is_subset(new, ctx->nnp)) {
813 error = -EPERM;
814 info = "no new privs";
815 goto audit;
816 }
824 817
825 if (bprm->unsafe & LSM_UNSAFE_SHARE) { 818 if (bprm->unsafe & LSM_UNSAFE_SHARE) {
826 /* FIXME: currently don't mediate shared state */ 819 /* FIXME: currently don't mediate shared state */
@@ -1047,30 +1040,28 @@ build:
1047int aa_change_hat(const char *hats[], int count, u64 token, int flags) 1040int aa_change_hat(const char *hats[], int count, u64 token, int flags)
1048{ 1041{
1049 const struct cred *cred; 1042 const struct cred *cred;
1050 struct aa_task_ctx *ctx; 1043 struct aa_task_ctx *ctx = task_ctx(current);
1051 struct aa_label *label, *previous, *new = NULL, *target = NULL; 1044 struct aa_label *label, *previous, *new = NULL, *target = NULL;
1052 struct aa_profile *profile; 1045 struct aa_profile *profile;
1053 struct aa_perms perms = {}; 1046 struct aa_perms perms = {};
1054 const char *info = NULL; 1047 const char *info = NULL;
1055 int error = 0; 1048 int error = 0;
1056 1049
1057 /*
1058 * Fail explicitly requested domain transitions if no_new_privs.
1059 * There is no exception for unconfined as change_hat is not
1060 * available.
1061 */
1062 if (task_no_new_privs(current)) {
1063 /* not an apparmor denial per se, so don't log it */
1064 AA_DEBUG("no_new_privs - change_hat denied");
1065 return -EPERM;
1066 }
1067
1068 /* released below */ 1050 /* released below */
1069 cred = get_current_cred(); 1051 cred = get_current_cred();
1070 ctx = task_ctx(current);
1071 label = aa_get_newest_cred_label(cred); 1052 label = aa_get_newest_cred_label(cred);
1072 previous = aa_get_newest_label(ctx->previous); 1053 previous = aa_get_newest_label(ctx->previous);
1073 1054
1055 /*
1056 * Detect no new privs being set, and store the label it
1057 * occurred under. Ideally this would happen when nnp
1058 * is set but there isn't a good way to do that yet.
1059 *
1060 * Testing for unconfined must be done before the subset test
1061 */
1062 if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
1063 ctx->nnp = aa_get_label(label);
1064
1074 if (unconfined(label)) { 1065 if (unconfined(label)) {
1075 info = "unconfined can not change_hat"; 1066 info = "unconfined can not change_hat";
1076 error = -EPERM; 1067 error = -EPERM;
@@ -1091,6 +1082,18 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
1091 if (error) 1082 if (error)
1092 goto fail; 1083 goto fail;
1093 1084
1085 /*
1086 * no new privs prevents domain transitions that would
1087 * reduce restrictions.
1088 */
1089 if (task_no_new_privs(current) && !unconfined(label) &&
1090 !aa_label_is_subset(new, ctx->nnp)) {
1091 /* not an apparmor denial per se, so don't log it */
1092 AA_DEBUG("no_new_privs - change_hat denied");
1093 error = -EPERM;
1094 goto out;
1095 }
1096
1094 if (flags & AA_CHANGE_TEST) 1097 if (flags & AA_CHANGE_TEST)
1095 goto out; 1098 goto out;
1096 1099
@@ -1100,6 +1103,18 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
1100 /* kill task in case of brute force attacks */ 1103 /* kill task in case of brute force attacks */
1101 goto kill; 1104 goto kill;
1102 } else if (previous && !(flags & AA_CHANGE_TEST)) { 1105 } else if (previous && !(flags & AA_CHANGE_TEST)) {
1106 /*
1107 * no new privs prevents domain transitions that would
1108 * reduce restrictions.
1109 */
1110 if (task_no_new_privs(current) && !unconfined(label) &&
1111 !aa_label_is_subset(previous, ctx->nnp)) {
1112 /* not an apparmor denial per se, so don't log it */
1113 AA_DEBUG("no_new_privs - change_hat denied");
1114 error = -EPERM;
1115 goto out;
1116 }
1117
1103 /* Return to saved label. Kill task if restore fails 1118 /* Return to saved label. Kill task if restore fails
1104 * to avoid brute force attacks 1119 * to avoid brute force attacks
1105 */ 1120 */
@@ -1142,21 +1157,6 @@ static int change_profile_perms_wrapper(const char *op, const char *name,
1142 const char *info = NULL; 1157 const char *info = NULL;
1143 int error = 0; 1158 int error = 0;
1144 1159
1145 /*
1146 * Fail explicitly requested domain transitions when no_new_privs
1147 * and not unconfined OR the transition results in a stack on
1148 * the current label.
1149 * Stacking domain transitions and transitions from unconfined are
1150 * allowed even when no_new_privs is set because this aways results
1151 * in a reduction of permissions.
1152 */
1153 if (task_no_new_privs(current) && !stack &&
1154 !profile_unconfined(profile) &&
1155 !aa_label_is_subset(target, &profile->label)) {
1156 info = "no new privs";
1157 error = -EPERM;
1158 }
1159
1160 if (!error) 1160 if (!error)
1161 error = change_profile_perms(profile, target, stack, request, 1161 error = change_profile_perms(profile, target, stack, request,
1162 profile->file.start, perms); 1162 profile->file.start, perms);
@@ -1190,10 +1190,23 @@ int aa_change_profile(const char *fqname, int flags)
1190 const char *info = NULL; 1190 const char *info = NULL;
1191 const char *auditname = fqname; /* retain leading & if stack */ 1191 const char *auditname = fqname; /* retain leading & if stack */
1192 bool stack = flags & AA_CHANGE_STACK; 1192 bool stack = flags & AA_CHANGE_STACK;
1193 struct aa_task_ctx *ctx = task_ctx(current);
1193 int error = 0; 1194 int error = 0;
1194 char *op; 1195 char *op;
1195 u32 request; 1196 u32 request;
1196 1197
1198 label = aa_get_current_label();
1199
1200 /*
1201 * Detect no new privs being set, and store the label it
1202 * occurred under. Ideally this would happen when nnp
1203 * is set but there isn't a good way to do that yet.
1204 *
1205 * Testing for unconfined must be done before the subset test
1206 */
1207 if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
1208 ctx->nnp = aa_get_label(label);
1209
1197 if (!fqname || !*fqname) { 1210 if (!fqname || !*fqname) {
1198 AA_DEBUG("no profile name"); 1211 AA_DEBUG("no profile name");
1199 return -EINVAL; 1212 return -EINVAL;
@@ -1281,14 +1294,28 @@ check:
1281 if (flags & AA_CHANGE_TEST) 1294 if (flags & AA_CHANGE_TEST)
1282 goto out; 1295 goto out;
1283 1296
1297 /* stacking is always a subset, so only check the nonstack case */
1298 if (!stack) {
1299 new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
1300 aa_get_label(target),
1301 aa_get_label(&profile->label));
1302 /*
1303 * no new privs prevents domain transitions that would
1304 * reduce restrictions.
1305 */
1306 if (task_no_new_privs(current) && !unconfined(label) &&
1307 !aa_label_is_subset(new, ctx->nnp)) {
1308 /* not an apparmor denial per se, so don't log it */
1309 AA_DEBUG("no_new_privs - change_hat denied");
1310 error = -EPERM;
1311 goto out;
1312 }
1313 }
1314
1284 if (!(flags & AA_CHANGE_ONEXEC)) { 1315 if (!(flags & AA_CHANGE_ONEXEC)) {
1285 /* only transition profiles in the current ns */ 1316 /* only transition profiles in the current ns */
1286 if (stack) 1317 if (stack)
1287 new = aa_label_merge(label, target, GFP_KERNEL); 1318 new = aa_label_merge(label, target, GFP_KERNEL);
1288 else
1289 new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
1290 aa_get_label(target),
1291 aa_get_label(&profile->label));
1292 if (IS_ERR_OR_NULL(new)) { 1319 if (IS_ERR_OR_NULL(new)) {
1293 info = "failed to build target label"; 1320 info = "failed to build target label";
1294 error = PTR_ERR(new); 1321 error = PTR_ERR(new);
@@ -1297,9 +1324,15 @@ check:
1297 goto audit; 1324 goto audit;
1298 } 1325 }
1299 error = aa_replace_current_label(new); 1326 error = aa_replace_current_label(new);
1300 } else 1327 } else {
1328 if (new) {
1329 aa_put_label(new);
1330 new = NULL;
1331 }
1332
1301 /* full transition will be built in exec path */ 1333 /* full transition will be built in exec path */
1302 error = aa_set_current_onexec(target, stack); 1334 error = aa_set_current_onexec(target, stack);
1335 }
1303 1336
1304audit: 1337audit:
1305 error = fn_for_each_in_ns(label, profile, 1338 error = fn_for_each_in_ns(label, profile,
diff --git a/security/apparmor/include/task.h b/security/apparmor/include/task.h
index d222197db299..55edaa1d83f8 100644
--- a/security/apparmor/include/task.h
+++ b/security/apparmor/include/task.h
@@ -18,11 +18,13 @@
18 18
19/* 19/*
20 * struct aa_task_ctx - information for current task label change 20 * struct aa_task_ctx - information for current task label change
21 * @nnp: snapshot of label at time of no_new_privs
21 * @onexec: profile to transition to on next exec (MAY BE NULL) 22 * @onexec: profile to transition to on next exec (MAY BE NULL)
22 * @previous: profile the task may return to (MAY BE NULL) 23 * @previous: profile the task may return to (MAY BE NULL)
23 * @token: magic value the task must know for returning to @previous_profile 24 * @token: magic value the task must know for returning to @previous_profile
24 */ 25 */
25struct aa_task_ctx { 26struct aa_task_ctx {
27 struct aa_label *nnp;
26 struct aa_label *onexec; 28 struct aa_label *onexec;
27 struct aa_label *previous; 29 struct aa_label *previous;
28 u64 token; 30 u64 token;
@@ -52,6 +54,7 @@ static inline struct aa_task_ctx *aa_alloc_task_ctx(gfp_t flags)
52static inline void aa_free_task_ctx(struct aa_task_ctx *ctx) 54static inline void aa_free_task_ctx(struct aa_task_ctx *ctx)
53{ 55{
54 if (ctx) { 56 if (ctx) {
57 aa_put_label(ctx->nnp);
55 aa_put_label(ctx->previous); 58 aa_put_label(ctx->previous);
56 aa_put_label(ctx->onexec); 59 aa_put_label(ctx->onexec);
57 60
@@ -68,6 +71,7 @@ static inline void aa_dup_task_ctx(struct aa_task_ctx *new,
68 const struct aa_task_ctx *old) 71 const struct aa_task_ctx *old)
69{ 72{
70 *new = *old; 73 *new = *old;
74 aa_get_label(new->nnp);
71 aa_get_label(new->previous); 75 aa_get_label(new->previous);
72 aa_get_label(new->onexec); 76 aa_get_label(new->onexec);
73} 77}
diff --git a/security/apparmor/task.c b/security/apparmor/task.c
index 44b9b938e06d..c6b78a14da91 100644
--- a/security/apparmor/task.c
+++ b/security/apparmor/task.c
@@ -45,6 +45,7 @@ struct aa_label *aa_get_task_label(struct task_struct *task)
45int aa_replace_current_label(struct aa_label *label) 45int aa_replace_current_label(struct aa_label *label)
46{ 46{
47 struct aa_label *old = aa_current_raw_label(); 47 struct aa_label *old = aa_current_raw_label();
48 struct aa_task_ctx *ctx = task_ctx(current);
48 struct cred *new; 49 struct cred *new;
49 50
50 AA_BUG(!label); 51 AA_BUG(!label);
@@ -59,6 +60,12 @@ int aa_replace_current_label(struct aa_label *label)
59 if (!new) 60 if (!new)
60 return -ENOMEM; 61 return -ENOMEM;
61 62
63 if (ctx->nnp && label_is_stale(ctx->nnp)) {
64 struct aa_label *tmp = ctx->nnp;
65
66 ctx->nnp = aa_get_newest_label(tmp);
67 aa_put_label(tmp);
68 }
62 if (unconfined(label) || (labels_ns(old) != labels_ns(label))) 69 if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
63 /* 70 /*
64 * if switching to unconfined or a different label namespace 71 * if switching to unconfined or a different label namespace