Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

apparmor: switch from profiles to using labels on contexts

Begin the actual switch to using domain labels by storing them on
the context and converting the label to a singular profile where
possible.

Signed-off-by: John Johansen <john.johansen@canonical.com>

+686 -529
+1 -1
security/apparmor/Makefile
··· 4 4 5 5 apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ 6 6 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ 7 - resource.o secid.o file.o policy_ns.o 7 + resource.o secid.o file.o policy_ns.o label.o 8 8 apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o 9 9 10 10 clean-files := capability_names.h rlim_names.h
+70 -58
security/apparmor/apparmorfs.c
··· 405 405 static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, 406 406 loff_t *pos, struct aa_ns *ns) 407 407 { 408 - ssize_t error; 409 408 struct aa_loaddata *data; 410 - struct aa_profile *profile; 409 + struct aa_label *label; 410 + ssize_t error; 411 411 412 - profile = begin_current_profile_crit_section(); 412 + label = begin_current_label_crit_section(); 413 413 414 414 /* high level check about policy management - fine grained in 415 415 * below after unpack 416 416 */ 417 - error = aa_may_manage_policy(profile, ns, mask); 417 + error = aa_may_manage_policy(label, ns, mask); 418 418 if (error) 419 419 return error; 420 420 421 421 data = aa_simple_write_to_buffer(buf, size, size, pos); 422 422 error = PTR_ERR(data); 423 423 if (!IS_ERR(data)) { 424 - error = aa_replace_profiles(ns, profile, mask, data); 424 + error = aa_replace_profiles(ns, label, mask, data); 425 425 aa_put_loaddata(data); 426 426 } 427 - end_current_profile_crit_section(profile); 427 + end_current_label_crit_section(label); 428 428 429 429 return error; 430 430 } ··· 468 468 size_t size, loff_t *pos) 469 469 { 470 470 struct aa_loaddata *data; 471 - struct aa_profile *profile; 471 + struct aa_label *label; 472 472 ssize_t error; 473 473 struct aa_ns *ns = aa_get_ns(f->f_inode->i_private); 474 474 475 - profile = begin_current_profile_crit_section(); 475 + label = begin_current_label_crit_section(); 476 476 /* high level check about policy management - fine grained in 477 477 * below after unpack 478 478 */ 479 - error = aa_may_manage_policy(profile, ns, AA_MAY_REMOVE_POLICY); 479 + error = aa_may_manage_policy(label, ns, AA_MAY_REMOVE_POLICY); 480 480 if (error) 481 481 goto out; 482 482 ··· 489 489 error = PTR_ERR(data); 490 490 if (!IS_ERR(data)) { 491 491 data->data[size] = 0; 492 - error = aa_remove_profiles(ns, profile, data->data, size); 492 + error = aa_remove_profiles(ns, label, data->data, size); 493 493 aa_put_loaddata(data); 494 494 } 495 495 out: 496 - end_current_profile_crit_section(profile); 496 + end_current_label_crit_section(label); 497 497 aa_put_ns(ns); 498 498 return error; 499 499 } ··· 605 605 struct aa_dfa *dfa; 606 606 unsigned int state = 0; 607 607 608 - if (unconfined(profile)) 608 + if (profile_unconfined(profile)) 609 609 return; 610 610 if (profile->file.dfa && *match_str == AA_CLASS_FILE) { 611 611 dfa = profile->file.dfa; ··· 655 655 { 656 656 char *out; 657 657 const char *key; 658 - struct aa_profile *profile, *curr; 658 + struct aa_label *label, *curr; 659 659 struct aa_data *data; 660 660 u32 bytes, blocks; 661 661 __le32 outle32; ··· 672 672 if (buf_len < sizeof(bytes) + sizeof(blocks)) 673 673 return -EINVAL; /* not enough space */ 674 674 675 - curr = begin_current_profile_crit_section(); 676 - profile = aa_fqlookupn_profile(curr, query, strnlen(query, query_len)); 677 - end_current_profile_crit_section(curr); 678 - if (!profile) 679 - return -ENOENT; 675 + curr = begin_current_label_crit_section(); 676 + label = aa_label_parse(curr, query, GFP_KERNEL, false, false); 677 + end_current_label_crit_section(curr); 678 + if (IS_ERR(label)) 679 + return PTR_ERR(label); 680 680 681 681 /* We are going to leave space for two numbers. The first is the total 682 682 * number of bytes we are writing after the first number. This is so ··· 690 690 out = buf + sizeof(bytes) + sizeof(blocks); 691 691 692 692 blocks = 0; 693 - if (profile->data) { 694 - data = rhashtable_lookup_fast(profile->data, &key, 695 - profile->data->p); 693 + if (labels_profile(label)->data) { 694 + data = rhashtable_lookup_fast(labels_profile(label)->data, &key, 695 + labels_profile(label)->data->p); 696 696 697 697 if (data) { 698 - if (out + sizeof(outle32) + data->size > buf + buf_len) 698 + if (out + sizeof(outle32) + data->size > 699 + buf + buf_len) { 700 + aa_put_label(label); 699 701 return -EINVAL; /* not enough space */ 702 + } 700 703 outle32 = __cpu_to_le32(data->size); 701 704 memcpy(out, &outle32, sizeof(outle32)); 702 705 out += sizeof(outle32); ··· 708 705 blocks++; 709 706 } 710 707 } 711 - aa_put_profile(profile); 708 + aa_put_label(label); 712 709 713 710 outle32 = __cpu_to_le32(out - buf - sizeof(bytes)); 714 711 memcpy(buf, &outle32, sizeof(outle32)); ··· 741 738 static ssize_t query_label(char *buf, size_t buf_len, 742 739 char *query, size_t query_len, bool view_only) 743 740 { 744 - struct aa_profile *profile, *curr; 741 + struct aa_label *label, *curr; 745 742 char *label_name, *match_str; 746 743 size_t label_name_len, match_len; 747 744 struct aa_perms perms; ··· 763 760 match_str = label_name + label_name_len + 1; 764 761 match_len = query_len - label_name_len - 1; 765 762 766 - curr = begin_current_profile_crit_section(); 767 - profile = aa_fqlookupn_profile(curr, label_name, label_name_len); 768 - end_current_profile_crit_section(curr); 769 - if (!profile) 770 - return -ENOENT; 763 + curr = begin_current_label_crit_section(); 764 + label = aa_label_parse(curr, label_name, GFP_KERNEL, false, false); 765 + end_current_label_crit_section(curr); 766 + if (IS_ERR(label)) 767 + return PTR_ERR(label); 771 768 772 769 perms = allperms; 773 - profile_query_cb(profile, &perms, match_str, match_len); 770 + profile_query_cb(labels_profile(label), &perms, match_str, match_len); 774 771 775 772 return scnprintf(buf, buf_len, 776 773 "allow 0x%08x\ndeny 0x%08x\naudit 0x%08x\nquiet 0x%08x\n", ··· 1029 1026 static int seq_profile_name_show(struct seq_file *seq, void *v) 1030 1027 { 1031 1028 struct aa_proxy *proxy = seq->private; 1032 - struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); 1029 + struct aa_label *label = aa_get_label_rcu(&proxy->label); 1030 + struct aa_profile *profile = labels_profile(label); 1033 1031 seq_printf(seq, "%s\n", profile->base.name); 1034 - aa_put_profile(profile); 1032 + aa_put_label(label); 1035 1033 1036 1034 return 0; 1037 1035 } ··· 1040 1036 static int seq_profile_mode_show(struct seq_file *seq, void *v) 1041 1037 { 1042 1038 struct aa_proxy *proxy = seq->private; 1043 - struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); 1039 + struct aa_label *label = aa_get_label_rcu(&proxy->label); 1040 + struct aa_profile *profile = labels_profile(label); 1044 1041 seq_printf(seq, "%s\n", aa_profile_mode_names[profile->mode]); 1045 - aa_put_profile(profile); 1042 + aa_put_label(label); 1046 1043 1047 1044 return 0; 1048 1045 } ··· 1051 1046 static int seq_profile_attach_show(struct seq_file *seq, void *v) 1052 1047 { 1053 1048 struct aa_proxy *proxy = seq->private; 1054 - struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); 1049 + struct aa_label *label = aa_get_label_rcu(&proxy->label); 1050 + struct aa_profile *profile = labels_profile(label); 1055 1051 if (profile->attach) 1056 1052 seq_printf(seq, "%s\n", profile->attach); 1057 1053 else if (profile->xmatch) 1058 1054 seq_puts(seq, "<unknown>\n"); 1059 1055 else 1060 1056 seq_printf(seq, "%s\n", profile->base.name); 1061 - aa_put_profile(profile); 1057 + aa_put_label(label); 1062 1058 1063 1059 return 0; 1064 1060 } ··· 1067 1061 static int seq_profile_hash_show(struct seq_file *seq, void *v) 1068 1062 { 1069 1063 struct aa_proxy *proxy = seq->private; 1070 - struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile); 1064 + struct aa_label *label = aa_get_label_rcu(&proxy->label); 1065 + struct aa_profile *profile = labels_profile(label); 1071 1066 unsigned int i, size = aa_hash_size(); 1072 1067 1073 1068 if (profile->hash) { ··· 1076 1069 seq_printf(seq, "%.2x", profile->hash[i]); 1077 1070 seq_putc(seq, '\n'); 1078 1071 } 1079 - aa_put_profile(profile); 1072 + aa_put_label(label); 1080 1073 1081 1074 return 0; 1082 1075 } ··· 1108 1101 1109 1102 static int seq_ns_level_show(struct seq_file *seq, void *v) 1110 1103 { 1111 - struct aa_profile *profile; 1104 + struct aa_label *label; 1112 1105 1113 - profile = begin_current_profile_crit_section(); 1114 - seq_printf(seq, "%d\n", profile->ns->level); 1115 - end_current_profile_crit_section(profile); 1106 + label = begin_current_label_crit_section(); 1107 + seq_printf(seq, "%d\n", labels_ns(label)->level); 1108 + end_current_label_crit_section(label); 1116 1109 1117 1110 return 0; 1118 1111 } 1119 1112 1120 1113 static int seq_ns_name_show(struct seq_file *seq, void *v) 1121 1114 { 1122 - struct aa_profile *profile; 1115 + struct aa_label *label = begin_current_label_crit_section(); 1123 1116 1124 - profile = begin_current_profile_crit_section(); 1125 - seq_printf(seq, "%s\n", aa_ns_name(profile->ns, profile->ns, true)); 1126 - end_current_profile_crit_section(profile); 1117 + seq_printf(seq, "%s\n", aa_ns_name(labels_ns(label), 1118 + labels_ns(label), true)); 1119 + end_current_label_crit_section(label); 1127 1120 1128 1121 return 0; 1129 1122 } ··· 1387 1380 struct aa_profile *profile, 1388 1381 const struct file_operations *fops) 1389 1382 { 1390 - struct aa_proxy *proxy = aa_get_proxy(profile->proxy); 1383 + struct aa_proxy *proxy = aa_get_proxy(profile->label.proxy); 1391 1384 struct dentry *dent; 1392 1385 1393 1386 dent = aafs_create_file(name, S_IFREG | 0444, dir, proxy, fops); ··· 1548 1541 { 1549 1542 struct aa_ns *ns, *parent; 1550 1543 /* TODO: improve permission check */ 1551 - struct aa_profile *profile = begin_current_profile_crit_section(); 1552 - int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY); 1553 - end_current_profile_crit_section(profile); 1544 + struct aa_label *label; 1545 + int error; 1546 + 1547 + label = begin_current_label_crit_section(); 1548 + error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY); 1549 + end_current_label_crit_section(label); 1554 1550 if (error) 1555 1551 return error; 1556 1552 ··· 1597 1587 { 1598 1588 struct aa_ns *ns, *parent; 1599 1589 /* TODO: improve permission check */ 1600 - struct aa_profile *profile = begin_current_profile_crit_section(); 1601 - int error = aa_may_manage_policy(profile, NULL, AA_MAY_LOAD_POLICY); 1602 - end_current_profile_crit_section(profile); 1590 + struct aa_label *label; 1591 + int error; 1592 + 1593 + label = begin_current_label_crit_section(); 1594 + error = aa_may_manage_policy(label, NULL, AA_MAY_LOAD_POLICY); 1595 + end_current_label_crit_section(label); 1603 1596 if (error) 1604 1597 return error; 1605 1598 1606 - parent = aa_get_ns(dir->i_private); 1599 + parent = aa_get_ns(dir->i_private); 1607 1600 /* rmdir calls the generic securityfs functions to remove files 1608 1601 * from the apparmor dir. It is up to the apparmor ns locking 1609 1602 * to avoid races. ··· 2012 1999 struct aa_profile *profile = (struct aa_profile *)p; 2013 2000 struct aa_ns *root = f->private; 2014 2001 2015 - if (profile->ns != root) 2016 - seq_printf(f, ":%s://", aa_ns_name(root, profile->ns, true)); 2017 - seq_printf(f, "%s (%s)\n", profile->base.hname, 2018 - aa_profile_mode_names[profile->mode]); 2002 + aa_label_seq_xprint(f, root, &profile->label, 2003 + FLAG_SHOW_MODE | FLAG_VIEW_SUBNS, GFP_KERNEL); 2004 + seq_putc(f, '\n'); 2019 2005 2020 2006 return 0; 2021 2007 }
+18 -9
security/apparmor/audit.c
··· 77 77 audit_log_format(ab, " error=%d", aad(sa)->error); 78 78 } 79 79 80 - if (aad(sa)->profile) { 81 - struct aa_profile *profile = aad(sa)->profile; 82 - if (profile->ns != root_ns) { 83 - audit_log_format(ab, " namespace="); 84 - audit_log_untrustedstring(ab, profile->ns->base.hname); 80 + if (aad(sa)->label) { 81 + struct aa_label *label = aad(sa)->label; 82 + 83 + if (label_isprofile(label)) { 84 + struct aa_profile *profile = labels_profile(label); 85 + 86 + if (profile->ns != root_ns) { 87 + audit_log_format(ab, " namespace="); 88 + audit_log_untrustedstring(ab, 89 + profile->ns->base.hname); 90 + } 91 + audit_log_format(ab, " profile="); 92 + audit_log_untrustedstring(ab, profile->base.hname); 93 + } else { 94 + audit_log_format(ab, " label="); 95 + aa_label_xaudit(ab, root_ns, label, FLAG_VIEW_SUBNS, 96 + GFP_ATOMIC); 85 97 } 86 - audit_log_format(ab, " profile="); 87 - audit_log_untrustedstring(ab, profile->base.hname); 88 98 } 89 99 90 100 if (aad(sa)->name) { ··· 149 139 if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) 150 140 type = AUDIT_APPARMOR_KILL; 151 141 152 - if (!unconfined(profile)) 153 - aad(sa)->profile = profile; 142 + aad(sa)->label = &profile->label; 154 143 155 144 aa_audit_msg(type, sa, cb); 156 145
+44 -43
security/apparmor/context.c
··· 14 14 * 15 15 * 16 16 * AppArmor sets confinement on every task, via the the aa_task_ctx and 17 - * the aa_task_ctx.profile, both of which are required and are not allowed 17 + * the aa_task_ctx.label, both of which are required and are not allowed 18 18 * to be NULL. The aa_task_ctx is not reference counted and is unique 19 - * to each cred (which is reference count). The profile pointed to by 19 + * to each cred (which is reference count). The label pointed to by 20 20 * the task_ctx is reference counted. 21 21 * 22 22 * TODO ··· 47 47 void aa_free_task_context(struct aa_task_ctx *ctx) 48 48 { 49 49 if (ctx) { 50 - aa_put_profile(ctx->profile); 51 - aa_put_profile(ctx->previous); 52 - aa_put_profile(ctx->onexec); 50 + aa_put_label(ctx->label); 51 + aa_put_label(ctx->previous); 52 + aa_put_label(ctx->onexec); 53 53 54 54 kzfree(ctx); 55 55 } ··· 63 63 void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old) 64 64 { 65 65 *new = *old; 66 - aa_get_profile(new->profile); 67 - aa_get_profile(new->previous); 68 - aa_get_profile(new->onexec); 66 + aa_get_label(new->label); 67 + aa_get_label(new->previous); 68 + aa_get_label(new->onexec); 69 69 } 70 70 71 71 /** 72 - * aa_get_task_profile - Get another task's profile 72 + * aa_get_task_label - Get another task's label 73 73 * @task: task to query (NOT NULL) 74 74 * 75 - * Returns: counted reference to @task's profile 75 + * Returns: counted reference to @task's label 76 76 */ 77 - struct aa_profile *aa_get_task_profile(struct task_struct *task) 77 + struct aa_label *aa_get_task_label(struct task_struct *task) 78 78 { 79 - struct aa_profile *p; 79 + struct aa_label *p; 80 80 81 81 rcu_read_lock(); 82 - p = aa_get_newest_profile(__aa_task_raw_profile(task)); 82 + p = aa_get_newest_label(__aa_task_raw_label(task)); 83 83 rcu_read_unlock(); 84 84 85 85 return p; 86 86 } 87 87 88 88 /** 89 - * aa_replace_current_profile - replace the current tasks profiles 90 - * @profile: new profile (NOT NULL) 89 + * aa_replace_current_label - replace the current tasks label 90 + * @label: new label (NOT NULL) 91 91 * 92 92 * Returns: 0 or error on failure 93 93 */ 94 - int aa_replace_current_profile(struct aa_profile *profile) 94 + int aa_replace_current_label(struct aa_label *label) 95 95 { 96 96 struct aa_task_ctx *ctx = current_ctx(); 97 97 struct cred *new; 98 - AA_BUG(!profile); 98 + AA_BUG(!label); 99 99 100 - if (ctx->profile == profile) 100 + if (ctx->label == label) 101 101 return 0; 102 102 103 103 if (current_cred() != current_real_cred()) ··· 108 108 return -ENOMEM; 109 109 110 110 ctx = cred_ctx(new); 111 - if (unconfined(profile) || (ctx->profile->ns != profile->ns)) 112 - /* if switching to unconfined or a different profile namespace 111 + if (unconfined(label) || (labels_ns(ctx->label) != labels_ns(label))) 112 + /* if switching to unconfined or a different label namespace 113 113 * clear out context state 114 114 */ 115 115 aa_clear_task_ctx_trans(ctx); ··· 120 120 * keeping @profile valid, so make sure to get its reference before 121 121 * dropping the reference on ctx->profile 122 122 */ 123 - aa_get_profile(profile); 124 - aa_put_profile(ctx->profile); 125 - ctx->profile = profile; 123 + aa_get_label(label); 124 + aa_put_label(ctx->label); 125 + ctx->label = label; 126 126 127 127 commit_creds(new); 128 128 return 0; ··· 130 130 131 131 /** 132 132 * aa_set_current_onexec - set the tasks change_profile to happen onexec 133 - * @profile: system profile to set at exec (MAYBE NULL to clear value) 134 - * 133 + * @label: system label to set at exec (MAYBE NULL to clear value) 134 + * @stack: whether stacking should be done 135 135 * Returns: 0 or error on failure 136 136 */ 137 - int aa_set_current_onexec(struct aa_profile *profile) 137 + int aa_set_current_onexec(struct aa_label *label, bool stack) 138 138 { 139 139 struct aa_task_ctx *ctx; 140 140 struct cred *new = prepare_creds(); ··· 142 142 return -ENOMEM; 143 143 144 144 ctx = cred_ctx(new); 145 - aa_get_profile(profile); 146 - aa_put_profile(ctx->onexec); 147 - ctx->onexec = profile; 145 + aa_get_label(label); 146 + aa_clear_task_ctx_trans(ctx); 147 + ctx->onexec = label; 148 + ctx->token = stack; 148 149 149 150 commit_creds(new); 150 151 return 0; ··· 153 152 154 153 /** 155 154 * aa_set_current_hat - set the current tasks hat 156 - * @profile: profile to set as the current hat (NOT NULL) 155 + * @label: label to set as the current hat (NOT NULL) 157 156 * @token: token value that must be specified to change from the hat 158 157 * 159 158 * Do switch of tasks hat. If the task is currently in a hat ··· 161 160 * 162 161 * Returns: 0 or error on failure 163 162 */ 164 - int aa_set_current_hat(struct aa_profile *profile, u64 token) 163 + int aa_set_current_hat(struct aa_label *label, u64 token) 165 164 { 166 165 struct aa_task_ctx *ctx; 167 166 struct cred *new = prepare_creds(); 168 167 if (!new) 169 168 return -ENOMEM; 170 - AA_BUG(!profile); 169 + AA_BUG(!label); 171 170 172 171 ctx = cred_ctx(new); 173 172 if (!ctx->previous) { 174 173 /* transfer refcount */ 175 - ctx->previous = ctx->profile; 174 + ctx->previous = ctx->label; 176 175 ctx->token = token; 177 176 } else if (ctx->token == token) { 178 - aa_put_profile(ctx->profile); 177 + aa_put_label(ctx->label); 179 178 } else { 180 179 /* previous_profile && ctx->token != token */ 181 180 abort_creds(new); 182 181 return -EACCES; 183 182 } 184 - ctx->profile = aa_get_newest_profile(profile); 183 + ctx->label = aa_get_newest_label(label); 185 184 /* clear exec on switching context */ 186 - aa_put_profile(ctx->onexec); 185 + aa_put_label(ctx->onexec); 187 186 ctx->onexec = NULL; 188 187 189 188 commit_creds(new); ··· 191 190 } 192 191 193 192 /** 194 - * aa_restore_previous_profile - exit from hat context restoring the profile 193 + * aa_restore_previous_label - exit from hat context restoring previous label 195 194 * @token: the token that must be matched to exit hat context 196 195 * 197 - * Attempt to return out of a hat to the previous profile. The token 196 + * Attempt to return out of a hat to the previous label. The token 198 197 * must match the stored token value. 199 198 * 200 199 * Returns: 0 or error of failure 201 200 */ 202 - int aa_restore_previous_profile(u64 token) 201 + int aa_restore_previous_label(u64 token) 203 202 { 204 203 struct aa_task_ctx *ctx; 205 204 struct cred *new = prepare_creds(); ··· 211 210 abort_creds(new); 212 211 return -EACCES; 213 212 } 214 - /* ignore restores when there is no saved profile */ 213 + /* ignore restores when there is no saved label */ 215 214 if (!ctx->previous) { 216 215 abort_creds(new); 217 216 return 0; 218 217 } 219 218 220 - aa_put_profile(ctx->profile); 221 - ctx->profile = aa_get_newest_profile(ctx->previous); 222 - AA_BUG(!ctx->profile); 219 + aa_put_label(ctx->label); 220 + ctx->label = aa_get_newest_label(ctx->previous); 221 + AA_BUG(!ctx->label); 223 222 /* clear exec && prev information when restoring to previous context */ 224 223 aa_clear_task_ctx_trans(ctx); 225 224
+42 -35
security/apparmor/domain.c
··· 61 61 static int may_change_ptraced_domain(struct aa_profile *to_profile) 62 62 { 63 63 struct task_struct *tracer; 64 - struct aa_profile *tracerp = NULL; 64 + struct aa_label *tracerl = NULL; 65 65 int error = 0; 66 66 67 67 rcu_read_lock(); 68 68 tracer = ptrace_parent(current); 69 69 if (tracer) 70 70 /* released below */ 71 - tracerp = aa_get_task_profile(tracer); 71 + tracerl = aa_get_task_label(tracer); 72 72 73 73 /* not ptraced */ 74 - if (!tracer || unconfined(tracerp)) 74 + if (!tracer || unconfined(tracerl)) 75 75 goto out; 76 76 77 - error = aa_may_ptrace(tracerp, to_profile, PTRACE_MODE_ATTACH); 77 + error = aa_may_ptrace(labels_profile(tracerl), to_profile, 78 + PTRACE_MODE_ATTACH); 78 79 79 80 out: 80 81 rcu_read_unlock(); 81 - aa_put_profile(tracerp); 82 + aa_put_label(tracerl); 82 83 83 84 return error; 84 85 } ··· 103 102 struct path_cond cond = { }; 104 103 unsigned int state; 105 104 106 - if (unconfined(profile)) { 105 + if (profile_unconfined(profile)) { 107 106 perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; 108 107 perms.audit = perms.quiet = perms.kill = 0; 109 108 return perms; ··· 145 144 struct aa_profile *profile, *candidate = NULL; 146 145 147 146 list_for_each_entry_rcu(profile, head, base.list) { 148 - if (profile->flags & PFLAG_NULL) 147 + if (profile->label.flags & FLAG_NULL) 149 148 continue; 150 149 if (profile->xmatch && profile->xmatch_len > len) { 151 150 unsigned int state = aa_dfa_match(profile->xmatch, ··· 339 338 int apparmor_bprm_set_creds(struct linux_binprm *bprm) 340 339 { 341 340 struct aa_task_ctx *ctx; 341 + struct aa_label *label; 342 342 struct aa_profile *profile, *new_profile = NULL; 343 343 struct aa_ns *ns; 344 344 char *buffer = NULL; ··· 358 356 ctx = cred_ctx(bprm->cred); 359 357 AA_BUG(!ctx); 360 358 361 - profile = aa_get_newest_profile(ctx->profile); 359 + label = aa_get_newest_label(ctx->label); 360 + profile = labels_profile(label); 362 361 363 362 /* buffer freed below, name is pointer into buffer */ 364 363 get_buffers(buffer); ··· 373 370 error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer, 374 371 &name, &info, profile->disconnected); 375 372 if (error) { 376 - if (unconfined(profile) || 377 - (profile->flags & PFLAG_IX_ON_NAME_ERROR)) 373 + if (profile_unconfined(profile) || 374 + (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) 378 375 error = 0; 379 376 name = bprm->filename; 380 377 goto audit; ··· 383 380 /* Test for onexec first as onexec directives override other 384 381 * x transitions. 385 382 */ 386 - if (unconfined(profile)) { 383 + if (profile_unconfined(profile)) { 387 384 /* unconfined task */ 388 385 if (ctx->onexec) 389 386 /* change_profile on exec already been granted */ 390 - new_profile = aa_get_profile(ctx->onexec); 387 + new_profile = labels_profile(aa_get_label(ctx->onexec)); 391 388 else 392 389 new_profile = find_attach(ns, &ns->base.profiles, name); 393 390 if (!new_profile) ··· 405 402 if (ctx->onexec) { 406 403 struct aa_perms cp; 407 404 info = "change_profile onexec"; 408 - new_profile = aa_get_newest_profile(ctx->onexec); 405 + new_profile = labels_profile(aa_get_newest_label(ctx->onexec)); 409 406 if (!(perms.allow & AA_MAY_ONEXEC)) 410 407 goto audit; 411 408 ··· 414 411 * exec\0change_profile 415 412 */ 416 413 state = aa_dfa_null_transition(profile->file.dfa, state); 417 - cp = change_profile_perms(profile, ctx->onexec->ns, 418 - ctx->onexec->base.name, 419 - AA_MAY_ONEXEC, state); 414 + cp = change_profile_perms(profile, labels_ns(ctx->onexec), 415 + labels_profile(ctx->onexec)->base.name, 416 + AA_MAY_ONEXEC, state); 420 417 421 418 if (!(cp.allow & AA_MAY_ONEXEC)) 422 419 goto audit; ··· 504 501 bprm->per_clear |= PER_CLEAR_ON_SETID; 505 502 506 503 x_clear: 507 - aa_put_profile(ctx->profile); 504 + aa_put_label(ctx->label); 508 505 /* transfer new profile reference will be released when ctx is freed */ 509 - ctx->profile = new_profile; 506 + ctx->label = &new_profile->label; 510 507 new_profile = NULL; 511 508 512 509 /* clear out all temporary/transitional state from the context */ ··· 519 516 520 517 cleanup: 521 518 aa_put_profile(new_profile); 522 - aa_put_profile(profile); 519 + aa_put_label(label); 523 520 put_buffers(buffer); 524 521 525 522 return error; ··· 579 576 { 580 577 const struct cred *cred; 581 578 struct aa_task_ctx *ctx; 582 - struct aa_profile *profile, *previous_profile, *hat = NULL; 579 + struct aa_label *label, *previous_label; 580 + struct aa_profile *profile, *hat = NULL; 583 581 char *name = NULL; 584 582 int i; 585 583 struct aa_perms perms = {}; ··· 598 594 /* released below */ 599 595 cred = get_current_cred(); 600 596 ctx = cred_ctx(cred); 601 - profile = aa_get_newest_cred_profile(cred); 602 - previous_profile = aa_get_newest_profile(ctx->previous); 597 + label = aa_get_newest_cred_label(cred); 598 + previous_label = aa_get_newest_label(ctx->previous); 599 + profile = labels_profile(label); 603 600 604 - if (unconfined(profile)) { 601 + if (unconfined(label)) { 605 602 info = "unconfined"; 606 603 error = -EPERM; 607 604 goto audit; ··· 669 664 } 670 665 671 666 if (!(flags & AA_CHANGE_TEST)) { 672 - error = aa_set_current_hat(hat, token); 667 + error = aa_set_current_hat(&hat->label, token); 673 668 if (error == -EACCES) 674 669 /* kill task in case of brute force attacks */ 675 670 perms.kill = AA_MAY_CHANGEHAT; ··· 677 672 /* reset error for learning of new hats */ 678 673 error = -ENOENT; 679 674 } 680 - } else if (previous_profile) { 675 + } else if (previous_label) { 681 676 /* Return to saved profile. Kill task if restore fails 682 677 * to avoid brute force attacks 683 678 */ 684 - target = previous_profile->base.hname; 685 - error = aa_restore_previous_profile(token); 679 + target = previous_label->hname; 680 + error = aa_restore_previous_label(token); 686 681 perms.kill = AA_MAY_CHANGEHAT; 687 682 } else 688 683 /* ignore restores when there is no saved profile */ ··· 697 692 out: 698 693 aa_put_profile(hat); 699 694 kfree(name); 700 - aa_put_profile(profile); 701 - aa_put_profile(previous_profile); 695 + aa_put_label(label); 696 + aa_put_label(previous_label); 702 697 put_cred(cred); 703 698 704 699 return error; ··· 721 716 int aa_change_profile(const char *fqname, int flags) 722 717 { 723 718 const struct cred *cred; 719 + struct aa_label *label; 724 720 struct aa_profile *profile, *target = NULL; 725 721 struct aa_perms perms = {}; 726 722 const char *info = NULL, *op; ··· 742 736 } 743 737 744 738 cred = get_current_cred(); 745 - profile = aa_get_newest_cred_profile(cred); 739 + label = aa_get_newest_cred_label(cred); 740 + profile = labels_profile(label); 746 741 747 742 /* 748 743 * Fail explicitly requested domain transitions if no_new_privs ··· 752 745 * no_new_privs is set because this aways results in a reduction 753 746 * of permissions. 754 747 */ 755 - if (task_no_new_privs(current) && !unconfined(profile)) { 748 + if (task_no_new_privs(current) && !profile_unconfined(profile)) { 756 749 put_cred(cred); 757 750 return -EPERM; 758 751 } 759 752 760 - target = aa_fqlookupn_profile(profile, fqname, strlen(fqname)); 753 + target = aa_fqlookupn_profile(label, fqname, strlen(fqname)); 761 754 if (!target) { 762 755 info = "profile not found"; 763 756 error = -ENOENT; ··· 792 785 goto audit; 793 786 794 787 if (flags & AA_CHANGE_ONEXEC) 795 - error = aa_set_current_onexec(target); 788 + error = aa_set_current_onexec(&target->label, 0); 796 789 else 797 - error = aa_replace_current_profile(target); 790 + error = aa_replace_current_label(&target->label); 798 791 799 792 audit: 800 793 if (!(flags & AA_CHANGE_TEST)) ··· 802 795 fqname, GLOBAL_ROOT_UID, info, error); 803 796 804 797 aa_put_profile(target); 805 - aa_put_profile(profile); 798 + aa_put_label(label); 806 799 put_cred(cred); 807 800 808 801 return error;
+9 -9
security/apparmor/file.c
··· 451 451 request, &cond); 452 452 } 453 453 454 - static void revalidate_tty(struct aa_profile *profile) 454 + static void revalidate_tty(struct aa_label *label) 455 455 { 456 456 struct tty_struct *tty; 457 457 int drop_tty = 0; ··· 469 469 struct tty_file_private, list); 470 470 file = file_priv->file; 471 471 472 - if (aa_file_perm(OP_INHERIT, profile, file, 472 + if (aa_file_perm(OP_INHERIT, labels_profile(label), file, 473 473 MAY_READ | MAY_WRITE)) 474 474 drop_tty = 1; 475 475 } ··· 482 482 483 483 static int match_file(const void *p, struct file *file, unsigned int fd) 484 484 { 485 - struct aa_profile *profile = (struct aa_profile *)p; 485 + struct aa_label *label = (struct aa_label *)p; 486 486 487 - if (aa_file_perm(OP_INHERIT, profile, file, 487 + if (aa_file_perm(OP_INHERIT, labels_profile(label), file, 488 488 aa_map_file_to_perms(file))) 489 489 return fd + 1; 490 490 return 0; ··· 494 494 /* based on selinux's flush_unauthorized_files */ 495 495 void aa_inherit_files(const struct cred *cred, struct files_struct *files) 496 496 { 497 - struct aa_profile *profile = aa_get_newest_cred_profile(cred); 497 + struct aa_label *label = aa_get_newest_cred_label(cred); 498 498 struct file *devnull = NULL; 499 499 unsigned int n; 500 500 501 - revalidate_tty(profile); 501 + revalidate_tty(label); 502 502 503 503 /* Revalidate access to inherited open files. */ 504 - n = iterate_fd(files, 0, match_file, profile); 504 + n = iterate_fd(files, 0, match_file, label); 505 505 if (!n) /* none found? */ 506 506 goto out; 507 507 ··· 511 511 /* replace all the matching ones with this */ 512 512 do { 513 513 replace_fd(n - 1, devnull, 0); 514 - } while ((n = iterate_fd(files, n, match_file, profile)) != 0); 514 + } while ((n = iterate_fd(files, n, match_file, label)) != 0); 515 515 if (devnull) 516 516 fput(devnull); 517 517 out: 518 - aa_put_profile(profile); 518 + aa_put_label(label); 519 519 }
+3 -2
security/apparmor/include/apparmor.h
··· 4 4 * This file contains AppArmor basic global 5 5 * 6 6 * Copyright (C) 1998-2008 Novell/SUSE 7 - * Copyright 2009-2010 Canonical Ltd. 7 + * Copyright 2009-2017 Canonical Ltd. 8 8 * 9 9 * This program is free software; you can redistribute it and/or 10 10 * modify it under the terms of the GNU General Public License as ··· 27 27 #define AA_CLASS_NET 4 28 28 #define AA_CLASS_RLIMITS 5 29 29 #define AA_CLASS_DOMAIN 6 30 + #define AA_CLASS_LABEL 16 30 31 31 - #define AA_CLASS_LAST AA_CLASS_DOMAIN 32 + #define AA_CLASS_LAST AA_CLASS_LABEL 32 33 33 34 /* Control parameters settable through module/boot flags */ 34 35 extern enum audit_mode aa_g_audit;
+4 -5
security/apparmor/include/audit.h
··· 22 22 #include <linux/slab.h> 23 23 24 24 #include "file.h" 25 - 26 - struct aa_profile; 25 + #include "label.h" 27 26 28 27 extern const char *const audit_mode_names[]; 29 28 #define AUDIT_MAX_INDEX 5 ··· 102 103 103 104 struct apparmor_audit_data { 104 105 int error; 105 - const char *op; 106 106 int type; 107 - void *profile; 107 + const char *op; 108 + struct aa_label *label; 108 109 const char *name; 109 110 const char *info; 110 111 u32 request; ··· 112 113 union { 113 114 /* these entries require a custom callback fn */ 114 115 struct { 115 - struct aa_profile *peer; 116 + struct aa_label *peer; 116 117 struct { 117 118 const char *target; 118 119 kuid_t ouid;
+78 -80
security/apparmor/include/context.h
··· 19 19 #include <linux/slab.h> 20 20 #include <linux/sched.h> 21 21 22 - #include "policy.h" 22 + #include "label.h" 23 23 #include "policy_ns.h" 24 24 25 25 #define cred_ctx(X) ((X)->security) ··· 27 27 28 28 /** 29 29 * struct aa_task_ctx - primary label for confined tasks 30 - * @profile: the current profile (NOT NULL) 31 - * @exec: profile to transition to on next exec (MAYBE NULL) 32 - * @previous: profile the task may return to (MAYBE NULL) 33 - * @token: magic value the task must know for returning to @previous_profile 30 + * @label: the current label (NOT NULL) 31 + * @exec: label to transition to on next exec (MAYBE NULL) 32 + * @previous: label the task may return to (MAYBE NULL) 33 + * @token: magic value the task must know for returning to @previous 34 34 * 35 - * Contains the task's current profile (which could change due to 35 + * Contains the task's current label (which could change due to 36 36 * change_hat). Plus the hat_magic needed during change_hat. 37 37 * 38 38 * TODO: make so a task can be confined by a stack of contexts 39 39 */ 40 40 struct aa_task_ctx { 41 - struct aa_profile *profile; 42 - struct aa_profile *onexec; 43 - struct aa_profile *previous; 41 + struct aa_label *label; 42 + struct aa_label *onexec; 43 + struct aa_label *previous; 44 44 u64 token; 45 45 }; 46 46 ··· 48 48 void aa_free_task_context(struct aa_task_ctx *ctx); 49 49 void aa_dup_task_context(struct aa_task_ctx *new, 50 50 const struct aa_task_ctx *old); 51 - int aa_replace_current_profile(struct aa_profile *profile); 52 - int aa_set_current_onexec(struct aa_profile *profile); 53 - int aa_set_current_hat(struct aa_profile *profile, u64 token); 54 - int aa_restore_previous_profile(u64 cookie); 55 - struct aa_profile *aa_get_task_profile(struct task_struct *task); 51 + int aa_replace_current_label(struct aa_label *label); 52 + int aa_set_current_onexec(struct aa_label *label, bool stack); 53 + int aa_set_current_hat(struct aa_label *label, u64 token); 54 + int aa_restore_previous_label(u64 cookie); 55 + struct aa_label *aa_get_task_label(struct task_struct *task); 56 56 57 57 58 58 /** 59 - * aa_cred_raw_profile - obtain cred's profiles 60 - * @cred: cred to obtain profiles from (NOT NULL) 59 + * aa_cred_raw_label - obtain cred's label 60 + * @cred: cred to obtain label from (NOT NULL) 61 61 * 62 - * Returns: confining profile 62 + * Returns: confining label 63 63 * 64 64 * does NOT increment reference count 65 65 */ 66 - static inline struct aa_profile *aa_cred_raw_profile(const struct cred *cred) 66 + static inline struct aa_label *aa_cred_raw_label(const struct cred *cred) 67 67 { 68 68 struct aa_task_ctx *ctx = cred_ctx(cred); 69 69 70 - AA_BUG(!ctx || !ctx->profile); 71 - return ctx->profile; 70 + AA_BUG(!ctx || !ctx->label); 71 + return ctx->label; 72 72 } 73 73 74 74 /** 75 - * aa_get_newest_cred_profile - obtain the newest profile on a cred 76 - * @cred: cred to obtain profile from (NOT NULL) 75 + * aa_get_newest_cred_label - obtain the newest label on a cred 76 + * @cred: cred to obtain label from (NOT NULL) 77 77 * 78 - * Returns: newest version of confining profile 78 + * Returns: newest version of confining label 79 79 */ 80 - static inline 81 - struct aa_profile *aa_get_newest_cred_profile(const struct cred *cred) 80 + static inline struct aa_label *aa_get_newest_cred_label(const struct cred *cred) 82 81 { 83 - return aa_get_newest_profile(aa_cred_raw_profile(cred)); 82 + return aa_get_newest_label(aa_cred_raw_label(cred)); 84 83 } 85 84 86 85 /** 87 - * __aa_task_raw_profile - retrieve another task's profile 86 + * __aa_task_raw_label - retrieve another task's label 88 87 * @task: task to query (NOT NULL) 89 88 * 90 - * Returns: @task's profile without incrementing its ref count 89 + * Returns: @task's label without incrementing its ref count 91 90 * 92 91 * If @task != current needs to be called in RCU safe critical section 93 92 */ 94 - static inline struct aa_profile *__aa_task_raw_profile(struct task_struct *task) 93 + static inline struct aa_label *__aa_task_raw_label(struct task_struct *task) 95 94 { 96 - return aa_cred_raw_profile(__task_cred(task)); 95 + return aa_cred_raw_label(__task_cred(task)); 97 96 } 98 97 99 98 /** ··· 103 104 */ 104 105 static inline bool __aa_task_is_confined(struct task_struct *task) 105 106 { 106 - return !unconfined(__aa_task_raw_profile(task)); 107 + return !unconfined(__aa_task_raw_label(task)); 107 108 } 108 109 109 110 /** 110 - * aa_current_raw_profile - find the current tasks confining profile 111 + * aa_current_raw_label - find the current tasks confining label 111 112 * 112 - * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) 113 + * Returns: up to date confining label or the ns unconfined label (NOT NULL) 113 114 * 114 115 * This fn will not update the tasks cred to the most up to date version 115 - * of the profile so it is safe to call when inside of locks. 116 + * of the label so it is safe to call when inside of locks. 116 117 */ 117 - static inline struct aa_profile *aa_current_raw_profile(void) 118 + static inline struct aa_label *aa_current_raw_label(void) 118 119 { 119 - return aa_cred_raw_profile(current_cred()); 120 + return aa_cred_raw_label(current_cred()); 120 121 } 121 122 122 123 /** 123 - * aa_get_current_profile - get the newest version of the current tasks profile 124 + * aa_get_current_label - get the newest version of the current tasks label 124 125 * 125 - * Returns: newest version of confining profile (NOT NULL) 126 + * Returns: newest version of confining label (NOT NULL) 126 127 * 127 128 * This fn will not update the tasks cred, so it is safe inside of locks 128 129 * 129 - * The returned reference must be put with aa_put_profile() 130 + * The returned reference must be put with aa_put_label() 130 131 */ 131 - static inline struct aa_profile *aa_get_current_profile(void) 132 + static inline struct aa_label *aa_get_current_label(void) 132 133 { 133 - struct aa_profile *p = aa_current_raw_profile(); 134 + struct aa_label *l = aa_current_raw_label(); 134 135 135 - if (profile_is_stale(p)) 136 - return aa_get_newest_profile(p); 137 - return aa_get_profile(p); 136 + if (label_is_stale(l)) 137 + return aa_get_newest_label(l); 138 + return aa_get_label(l); 138 139 } 139 140 140 - #define __end_current_profile_crit_section(X) \ 141 - end_current_profile_crit_section(X) 141 + #define __end_current_label_crit_section(X) end_current_label_crit_section(X) 142 142 143 143 /** 144 - * end_profile_crit_section - put a reference found with begin_current_profile.. 145 - * @profile: profile reference to put 144 + * end_label_crit_section - put a reference found with begin_current_label.. 145 + * @label: label reference to put 146 146 * 147 147 * Should only be used with a reference obtained with 148 - * begin_current_profile_crit_section and never used in situations where the 148 + * begin_current_label_crit_section and never used in situations where the 149 149 * task cred may be updated 150 150 */ 151 - static inline void end_current_profile_crit_section(struct aa_profile *profile) 151 + static inline void end_current_label_crit_section(struct aa_label *label) 152 152 { 153 - if (profile != aa_current_raw_profile()) 154 - aa_put_profile(profile); 153 + if (label != aa_current_raw_label()) 154 + aa_put_label(label); 155 155 } 156 156 157 157 /** 158 - * __begin_current_profile_crit_section - current's confining profile 158 + * __begin_current_label_crit_section - current's confining label 159 159 * 160 - * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) 160 + * Returns: up to date confining label or the ns unconfined label (NOT NULL) 161 161 * 162 162 * safe to call inside locks 163 163 * 164 - * The returned reference must be put with __end_current_profile_crit_section() 164 + * The returned reference must be put with __end_current_label_crit_section() 165 165 * This must NOT be used if the task cred could be updated within the 166 - * critical section between __begin_current_profile_crit_section() .. 167 - * __end_current_profile_crit_section() 166 + * critical section between __begin_current_label_crit_section() .. 167 + * __end_current_label_crit_section() 168 168 */ 169 - static inline struct aa_profile *__begin_current_profile_crit_section(void) 169 + static inline struct aa_label *__begin_current_label_crit_section(void) 170 170 { 171 - struct aa_profile *profile = aa_current_raw_profile(); 171 + struct aa_label *label = aa_current_raw_label(); 172 172 173 - if (profile_is_stale(profile)) 174 - profile = aa_get_newest_profile(profile); 173 + if (label_is_stale(label)) 174 + label = aa_get_newest_label(label); 175 175 176 - return profile; 176 + return label; 177 177 } 178 178 179 179 /** 180 - * begin_current_profile_crit_section - current's profile and update if needed 180 + * begin_current_label_crit_section - current's confining label and update it 181 181 * 182 - * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) 182 + * Returns: up to date confining label or the ns unconfined label (NOT NULL) 183 183 * 184 184 * Not safe to call inside locks 185 185 * 186 - * The returned reference must be put with end_current_profile_crit_section() 186 + * The returned reference must be put with end_current_label_crit_section() 187 187 * This must NOT be used if the task cred could be updated within the 188 - * critical section between begin_current_profile_crit_section() .. 189 - * end_current_profile_crit_section() 188 + * critical section between begin_current_label_crit_section() .. 189 + * end_current_label_crit_section() 190 190 */ 191 - static inline struct aa_profile *begin_current_profile_crit_section(void) 191 + static inline struct aa_label *begin_current_label_crit_section(void) 192 192 { 193 - struct aa_profile *profile = aa_current_raw_profile(); 193 + struct aa_label *label = aa_current_raw_label(); 194 194 195 - if (profile_is_stale(profile)) { 196 - profile = aa_get_newest_profile(profile); 197 - if (aa_replace_current_profile(profile) == 0) 195 + if (label_is_stale(label)) { 196 + label = aa_get_newest_label(label); 197 + if (aa_replace_current_label(label) == 0) 198 198 /* task cred will keep the reference */ 199 - aa_put_profile(profile); 199 + aa_put_label(label); 200 200 } 201 201 202 - return profile; 202 + return label; 203 203 } 204 204 205 205 static inline struct aa_ns *aa_get_current_ns(void) 206 206 { 207 - struct aa_profile *profile; 207 + struct aa_label *label; 208 208 struct aa_ns *ns; 209 209 210 - profile = __begin_current_profile_crit_section(); 211 - ns = aa_get_ns(profile->ns); 212 - __end_current_profile_crit_section(profile); 210 + label = __begin_current_label_crit_section(); 211 + ns = aa_get_ns(labels_ns(label)); 212 + __end_current_label_crit_section(label); 213 213 214 214 return ns; 215 215 } ··· 219 221 */ 220 222 static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) 221 223 { 222 - aa_put_profile(ctx->previous); 223 - aa_put_profile(ctx->onexec); 224 + aa_put_label(ctx->previous); 225 + aa_put_label(ctx->onexec); 224 226 ctx->previous = NULL; 225 227 ctx->onexec = NULL; 226 228 ctx->token = 0;
+11 -1
security/apparmor/include/perms.h
··· 15 15 #define __AA_PERM_H 16 16 17 17 #include <linux/fs.h> 18 + #include "label.h" 18 19 19 20 #define AA_MAY_EXEC MAY_EXEC 20 21 #define AA_MAY_WRITE MAY_WRITE ··· 102 101 struct aa_perms *perms); 103 102 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, 104 103 struct aa_perms *perms); 105 - 104 + void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend); 105 + void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend); 106 + void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, 107 + int type, u32 request, struct aa_perms *perms); 108 + int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, 109 + u32 request, int type, u32 *deny, 110 + struct common_audit_data *sa); 111 + int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, 112 + u32 request, struct common_audit_data *sa, 113 + void (*cb)(struct audit_buffer *, void *)); 106 114 #endif /* __AA_PERM_H */
+32 -78
security/apparmor/include/policy.h
··· 29 29 #include "domain.h" 30 30 #include "file.h" 31 31 #include "lib.h" 32 + #include "label.h" 32 33 #include "perms.h" 33 34 #include "resource.h" 34 35 ··· 49 48 50 49 #define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL) 51 50 52 - #define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) 51 + #define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT) 53 52 54 - #define profile_is_stale(_profile) ((_profile)->flags & PFLAG_STALE) 53 + #define profile_is_stale(_profile) (label_is_stale(&(_profile)->label)) 55 54 56 55 #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) 57 56 ··· 68 67 APPARMOR_UNCONFINED, /* profile set to unconfined */ 69 68 }; 70 69 71 - enum profile_flags { 72 - PFLAG_HAT = 1, /* profile is a hat */ 73 - PFLAG_NULL = 4, /* profile is null learning profile */ 74 - PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */ 75 - PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */ 76 - PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */ 77 - PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */ 78 - PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */ 79 - PFLAG_STALE = 0x200, /* profile replaced/removed */ 80 - PFLAG_NS_COUNT = 0x400, /* carries NS ref count */ 81 - 82 - /* These flags must correspond with PATH_flags */ 83 - PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */ 84 - }; 85 - 86 - struct aa_profile; 87 70 88 71 /* struct aa_policydb - match engine for a policy 89 72 * dfa: dfa pattern match ··· 78 93 struct aa_dfa *dfa; 79 94 unsigned int start[AA_CLASS_LAST + 1]; 80 95 81 - }; 82 - 83 - struct aa_proxy { 84 - struct kref count; 85 - struct aa_profile __rcu *profile; 86 96 }; 87 97 88 98 /* struct aa_data - generic data structure ··· 96 116 97 117 /* struct aa_profile - basic confinement data 98 118 * @base - base components of the profile (name, refcount, lists, lock ...) 99 - * @count: reference count of the obj 100 - * @rcu: rcu head used when removing from @list 119 + * @label - label this profile is an extension of 101 120 * @parent: parent of profile 102 121 * @ns: namespace the profile is in 103 - * @proxy: is set to the profile that replaced this profile 104 122 * @rename: optional profile name that this profile renamed 105 123 * @attach: human readable attachment string 106 124 * @xmatch: optional extended matching for unconfined executables names 107 125 * @xmatch_len: xmatch prefix len, used to determine xmatch priority 108 126 * @audit: the auditing mode of the profile 109 127 * @mode: the enforcement mode of the profile 110 - * @flags: flags controlling profile behavior 111 128 * @path_flags: flags controlling path generation behavior 112 129 * @disconnected: what to prepend if attach_disconnected is specified 113 130 * @size: the memory consumed by this profiles rules ··· 122 145 * used to determine profile attachment against unconfined tasks. All other 123 146 * attachments are determined by profile X transition rules. 124 147 * 125 - * The @proxy struct is write protected by the profile lock. 126 - * 127 148 * Profiles have a hierarchy where hats and children profiles keep 128 149 * a reference to their parent. 129 150 * ··· 131 156 */ 132 157 struct aa_profile { 133 158 struct aa_policy base; 134 - struct kref count; 135 - struct rcu_head rcu; 136 159 struct aa_profile __rcu *parent; 137 160 138 161 struct aa_ns *ns; 139 - struct aa_proxy *proxy; 140 162 const char *rename; 141 163 142 164 const char *attach; ··· 141 169 int xmatch_len; 142 170 enum audit_mode audit; 143 171 long mode; 144 - long flags; 145 172 u32 path_flags; 146 173 const char *disconnected; 147 174 int size; ··· 155 184 char *dirname; 156 185 struct dentry *dents[AAFS_PROF_SIZEOF]; 157 186 struct rhashtable *data; 187 + struct aa_label label; 158 188 }; 159 189 160 190 extern enum profile_mode aa_g_profile_mode; ··· 164 192 #define AA_MAY_REPLACE_POLICY AA_MAY_WRITE 165 193 #define AA_MAY_REMOVE_POLICY AA_MAY_DELETE 166 194 167 - void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new); 195 + #define profiles_ns(P) ((P)->ns) 196 + #define name_is_shared(A, B) ((A)->hname && (A)->hname == (B)->hname) 168 197 169 198 void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); 170 199 171 200 172 201 void aa_free_proxy_kref(struct kref *kref); 173 - struct aa_profile *aa_alloc_profile(const char *name, gfp_t gfp); 202 + struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy, 203 + gfp_t gfp); 174 204 struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, 175 205 const char *base, gfp_t gfp); 176 206 void aa_free_profile(struct aa_profile *profile); ··· 181 207 struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, 182 208 size_t n); 183 209 struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); 184 - struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, 210 + struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, 185 211 const char *fqname, size_t n); 186 212 struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); 187 213 188 - ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, 214 + ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_label *label, 189 215 u32 mask, struct aa_loaddata *udata); 190 - ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *profile, 191 - char *name, size_t size); 216 + ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label, 217 + char *name, size_t size); 192 218 void __aa_profile_list_release(struct list_head *head); 193 219 194 220 #define PROF_ADD 1 195 221 #define PROF_REPLACE 0 196 222 197 - #define unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) 223 + #define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) 224 + 225 + /** 226 + * aa_get_newest_profile - simple wrapper fn to wrap the label version 227 + * @p: profile (NOT NULL) 228 + * 229 + * Returns refcount to newest version of the profile (maybe @p) 230 + * 231 + * Requires: @p must be held with a valid refcount 232 + */ 233 + static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) 234 + { 235 + return labels_profile(aa_get_newest_label(&p->label)); 236 + } 198 237 199 238 #define PROFILE_MEDIATES(P, T) ((P)->policy.start[(T)]) 200 239 /* safe version of POLICY_MEDIATES for full range input */ ··· 230 243 static inline struct aa_profile *aa_get_profile(struct aa_profile *p) 231 244 { 232 245 if (p) 233 - kref_get(&(p->count)); 246 + kref_get(&(p->label.count)); 234 247 235 248 return p; 236 249 } ··· 244 257 */ 245 258 static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p) 246 259 { 247 - if (p && kref_get_unless_zero(&p->count)) 260 + if (p && kref_get_unless_zero(&p->label.count)) 248 261 return p; 249 262 250 263 return NULL; ··· 264 277 rcu_read_lock(); 265 278 do { 266 279 c = rcu_dereference(*p); 267 - } while (c && !kref_get_unless_zero(&c->count)); 280 + } while (c && !kref_get_unless_zero(&c->label.count)); 268 281 rcu_read_unlock(); 269 282 270 283 return c; 271 - } 272 - 273 - /** 274 - * aa_get_newest_profile - find the newest version of @profile 275 - * @profile: the profile to check for newer versions of 276 - * 277 - * Returns: refcounted newest version of @profile taking into account 278 - * replacement, renames and removals 279 - * return @profile. 280 - */ 281 - static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) 282 - { 283 - if (!p) 284 - return NULL; 285 - 286 - if (profile_is_stale(p)) 287 - return aa_get_profile_rcu(&p->proxy->profile); 288 - 289 - return aa_get_profile(p); 290 284 } 291 285 292 286 /** ··· 277 309 static inline void aa_put_profile(struct aa_profile *p) 278 310 { 279 311 if (p) 280 - kref_put(&p->count, aa_free_profile_kref); 281 - } 282 - 283 - static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *p) 284 - { 285 - if (p) 286 - kref_get(&(p->count)); 287 - 288 - return p; 289 - } 290 - 291 - static inline void aa_put_proxy(struct aa_proxy *p) 292 - { 293 - if (p) 294 - kref_put(&p->count, aa_free_proxy_kref); 312 + kref_put(&p->label.count, aa_label_kref); 295 313 } 296 314 297 315 static inline int AUDIT_MODE(struct aa_profile *profile) ··· 290 336 291 337 bool policy_view_capable(struct aa_ns *ns); 292 338 bool policy_admin_capable(struct aa_ns *ns); 293 - int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, 339 + int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, 294 340 u32 mask); 295 341 296 342 #endif /* __AA_POLICY_H */
+4
security/apparmor/include/policy_ns.h
··· 19 19 20 20 #include "apparmor.h" 21 21 #include "apparmorfs.h" 22 + #include "label.h" 22 23 #include "policy.h" 23 24 24 25 ··· 72 71 long revision; 73 72 wait_queue_head_t wait; 74 73 74 + struct aa_labelset labels; 75 75 struct list_head rawdata_list; 76 76 77 77 struct dentry *dents[AAFS_NS_SIZEOF]; ··· 81 79 extern struct aa_ns *root_ns; 82 80 83 81 extern const char *aa_hidden_ns_name; 82 + 83 + #define ns_unconfined(NS) (&(NS)->unconfined->label) 84 84 85 85 bool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns); 86 86 const char *aa_ns_name(struct aa_ns *parent, struct aa_ns *child, bool subns);
+17 -12
security/apparmor/ipc.c
··· 22 22 #include "include/ipc.h" 23 23 24 24 /* call back to audit ptrace fields */ 25 - static void audit_cb(struct audit_buffer *ab, void *va) 25 + static void audit_ptrace_cb(struct audit_buffer *ab, void *va) 26 26 { 27 27 struct common_audit_data *sa = va; 28 28 audit_log_format(ab, " peer="); 29 - audit_log_untrustedstring(ab, aad(sa)->peer->base.hname); 29 + aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 30 + FLAGS_NONE, GFP_ATOMIC); 30 31 } 31 32 32 33 /** ··· 43 42 { 44 43 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE); 45 44 46 - aad(&sa)->peer = target; 45 + aad(&sa)->peer = &target->label; 47 46 aad(&sa)->error = error; 48 47 49 - return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_cb); 48 + return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_ptrace_cb); 50 49 } 51 50 52 51 /** ··· 65 64 * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH 66 65 */ 67 66 68 - if (unconfined(tracer) || tracer == tracee) 67 + if (profile_unconfined(tracer) || tracer == tracee) 69 68 return 0; 70 69 /* log this capability request */ 71 70 return aa_capable(tracer, CAP_SYS_PTRACE, 1); ··· 91 90 * - tracer profile has CAP_SYS_PTRACE 92 91 */ 93 92 94 - struct aa_profile *tracer_p = aa_get_task_profile(tracer); 93 + struct aa_label *tracer_l = aa_get_task_label(tracer); 95 94 int error = 0; 96 95 97 - if (!unconfined(tracer_p)) { 98 - struct aa_profile *tracee_p = aa_get_task_profile(tracee); 96 + if (!unconfined(tracer_l)) { 97 + struct aa_label *tracee_l = aa_get_task_label(tracee); 99 98 100 - error = aa_may_ptrace(tracer_p, tracee_p, mode); 101 - error = aa_audit_ptrace(tracer_p, tracee_p, error); 99 + error = aa_may_ptrace(labels_profile(tracer_l), 100 + labels_profile(tracee_l), 101 + mode); 102 + error = aa_audit_ptrace(labels_profile(tracer_l), 103 + labels_profile(tracee_l), 104 + error); 102 105 103 - aa_put_profile(tracee_p); 106 + aa_put_label(tracee_l); 104 107 } 105 - aa_put_profile(tracer_p); 108 + aa_put_label(tracer_l); 106 109 107 110 return error; 108 111 }
+163
security/apparmor/lib.c
··· 247 247 } 248 248 249 249 /** 250 + * aa_audit_perms_cb - generic callback fn for auditing perms 251 + * @ab: audit buffer (NOT NULL) 252 + * @va: audit struct to audit values of (NOT NULL) 253 + */ 254 + static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) 255 + { 256 + struct common_audit_data *sa = va; 257 + 258 + if (aad(sa)->request) { 259 + audit_log_format(ab, " requested_mask="); 260 + aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs, 261 + PERMS_CHRS_MASK, aa_file_perm_names, 262 + PERMS_NAMES_MASK); 263 + } 264 + if (aad(sa)->denied) { 265 + audit_log_format(ab, "denied_mask="); 266 + aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs, 267 + PERMS_CHRS_MASK, aa_file_perm_names, 268 + PERMS_NAMES_MASK); 269 + } 270 + audit_log_format(ab, " peer="); 271 + aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, 272 + FLAGS_NONE, GFP_ATOMIC); 273 + } 274 + 275 + /** 250 276 * aa_apply_modes_to_perms - apply namespace and profile flags to perms 251 277 * @profile: that perms where computed from 252 278 * @perms: perms to apply mode modifiers to ··· 334 308 perms->quiet |= map_other(dfa_other_quiet(dfa, state)); 335 309 // perms->xindex = dfa_user_xindex(dfa, state); 336 310 } 311 + 312 + /** 313 + * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms 314 + * @accum - perms struct to accumulate into 315 + * @addend - perms struct to add to @accum 316 + */ 317 + void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend) 318 + { 319 + accum->deny |= addend->deny; 320 + accum->allow &= addend->allow & ~addend->deny; 321 + accum->audit |= addend->audit & addend->allow; 322 + accum->quiet &= addend->quiet & ~addend->allow; 323 + accum->kill |= addend->kill & ~addend->allow; 324 + accum->stop |= addend->stop & ~addend->allow; 325 + accum->complain |= addend->complain & ~addend->allow & ~addend->deny; 326 + accum->cond |= addend->cond & ~addend->allow & ~addend->deny; 327 + accum->hide &= addend->hide & ~addend->allow; 328 + accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny; 329 + } 330 + 331 + /** 332 + * aa_perms_accum - accumulate perms, masking off overlapping perms 333 + * @accum - perms struct to accumulate into 334 + * @addend - perms struct to add to @accum 335 + */ 336 + void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend) 337 + { 338 + accum->deny |= addend->deny; 339 + accum->allow &= addend->allow & ~accum->deny; 340 + accum->audit |= addend->audit & accum->allow; 341 + accum->quiet &= addend->quiet & ~accum->allow; 342 + accum->kill |= addend->kill & ~accum->allow; 343 + accum->stop |= addend->stop & ~accum->allow; 344 + accum->complain |= addend->complain & ~accum->allow & ~accum->deny; 345 + accum->cond |= addend->cond & ~accum->allow & ~accum->deny; 346 + accum->hide &= addend->hide & ~accum->allow; 347 + accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny; 348 + } 349 + 350 + void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, 351 + int type, u32 request, struct aa_perms *perms) 352 + { 353 + /* TODO: doesn't yet handle extended types */ 354 + unsigned int state; 355 + 356 + state = aa_dfa_next(profile->policy.dfa, 357 + profile->policy.start[AA_CLASS_LABEL], 358 + type); 359 + aa_label_match(profile, label, state, false, request, perms); 360 + } 361 + 362 + 363 + /* currently unused */ 364 + int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, 365 + u32 request, int type, u32 *deny, 366 + struct common_audit_data *sa) 367 + { 368 + struct aa_perms perms; 369 + 370 + aad(sa)->label = &profile->label; 371 + aad(sa)->peer = &target->label; 372 + aad(sa)->request = request; 373 + 374 + aa_profile_match_label(profile, &target->label, type, request, &perms); 375 + aa_apply_modes_to_perms(profile, &perms); 376 + *deny |= request & perms.deny; 377 + return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb); 378 + } 379 + 380 + /** 381 + * aa_check_perms - do audit mode selection based on perms set 382 + * @profile: profile being checked 383 + * @perms: perms computed for the request 384 + * @request: requested perms 385 + * @deny: Returns: explicit deny set 386 + * @sa: initialized audit structure (MAY BE NULL if not auditing) 387 + * @cb: callback fn for tpye specific fields (MAY BE NULL) 388 + * 389 + * Returns: 0 if permission else error code 390 + * 391 + * Note: profile audit modes need to be set before calling by setting the 392 + * perm masks appropriately. 393 + * 394 + * If not auditing then complain mode is not enabled and the 395 + * error code will indicate whether there was an explicit deny 396 + * with a positive value. 397 + */ 398 + int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, 399 + u32 request, struct common_audit_data *sa, 400 + void (*cb)(struct audit_buffer *, void *)) 401 + { 402 + int type, error; 403 + bool stop = false; 404 + u32 denied = request & (~perms->allow | perms->deny); 405 + 406 + if (likely(!denied)) { 407 + /* mask off perms that are not being force audited */ 408 + request &= perms->audit; 409 + if (!request || !sa) 410 + return 0; 411 + 412 + type = AUDIT_APPARMOR_AUDIT; 413 + error = 0; 414 + } else { 415 + error = -EACCES; 416 + 417 + if (denied & perms->kill) 418 + type = AUDIT_APPARMOR_KILL; 419 + else if (denied == (denied & perms->complain)) 420 + type = AUDIT_APPARMOR_ALLOWED; 421 + else 422 + type = AUDIT_APPARMOR_DENIED; 423 + 424 + if (denied & perms->stop) 425 + stop = true; 426 + if (denied == (denied & perms->hide)) 427 + error = -ENOENT; 428 + 429 + denied &= ~perms->quiet; 430 + if (!sa || !denied) 431 + return error; 432 + } 433 + 434 + if (sa) { 435 + aad(sa)->label = &profile->label; 436 + aad(sa)->request = request; 437 + aad(sa)->denied = denied; 438 + aad(sa)->error = error; 439 + aa_audit_msg(type, sa, cb); 440 + } 441 + 442 + if (type == AUDIT_APPARMOR_ALLOWED) 443 + error = 0; 444 + 445 + return error; 446 + } 447 + 337 448 338 449 /** 339 450 * aa_policy_init - initialize a policy structure
+72 -62
security/apparmor/lsm.c
··· 34 34 #include "include/file.h" 35 35 #include "include/ipc.h" 36 36 #include "include/path.h" 37 + #include "include/label.h" 37 38 #include "include/policy.h" 38 39 #include "include/policy_ns.h" 39 40 #include "include/procattr.h" ··· 50 49 */ 51 50 52 51 /* 53 - * free the associated aa_task_ctx and put its profiles 52 + * free the associated aa_task_ctx and put its labels 54 53 */ 55 54 static void apparmor_cred_free(struct cred *cred) 56 55 { ··· 116 115 static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, 117 116 kernel_cap_t *inheritable, kernel_cap_t *permitted) 118 117 { 118 + struct aa_label *label; 119 119 struct aa_profile *profile; 120 120 const struct cred *cred; 121 121 122 122 rcu_read_lock(); 123 123 cred = __task_cred(target); 124 - profile = aa_get_newest_cred_profile(cred); 125 - 124 + label = aa_get_newest_cred_label(cred); 125 + profile = labels_profile(label); 126 126 /* 127 127 * cap_capget is stacked ahead of this and will 128 128 * initialize effective and permitted. 129 129 */ 130 - if (!unconfined(profile) && !COMPLAIN_MODE(profile)) { 130 + if (!profile_unconfined(profile) && !COMPLAIN_MODE(profile)) { 131 131 *effective = cap_intersect(*effective, profile->caps.allow); 132 132 *permitted = cap_intersect(*permitted, profile->caps.allow); 133 133 } 134 134 rcu_read_unlock(); 135 - aa_put_profile(profile); 135 + aa_put_label(label); 136 136 137 137 return 0; 138 138 } ··· 141 139 static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, 142 140 int cap, int audit) 143 141 { 144 - struct aa_profile *profile; 142 + struct aa_label *label; 145 143 int error = 0; 146 144 147 - profile = aa_get_newest_cred_profile(cred); 148 - if (!unconfined(profile)) 149 - error = aa_capable(profile, cap, audit); 150 - aa_put_profile(profile); 145 + label = aa_get_newest_cred_label(cred); 146 + if (!unconfined(label)) 147 + error = aa_capable(labels_profile(label), cap, audit); 148 + aa_put_label(label); 151 149 152 150 return error; 153 151 } ··· 164 162 static int common_perm(const char *op, const struct path *path, u32 mask, 165 163 struct path_cond *cond) 166 164 { 167 - struct aa_profile *profile; 165 + struct aa_label *label; 168 166 int error = 0; 169 167 170 - profile = __begin_current_profile_crit_section(); 171 - if (!unconfined(profile)) 172 - error = aa_path_perm(op, profile, path, 0, mask, cond); 173 - __end_current_profile_crit_section(profile); 168 + label = __begin_current_label_crit_section(); 169 + if (!unconfined(label)) 170 + error = aa_path_perm(op, labels_profile(label), path, 0, mask, 171 + cond); 172 + __end_current_label_crit_section(label); 174 173 175 174 return error; 176 175 } ··· 298 295 static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_dir, 299 296 struct dentry *new_dentry) 300 297 { 301 - struct aa_profile *profile; 298 + struct aa_label *label; 302 299 int error = 0; 303 300 304 301 if (!path_mediated_fs(old_dentry)) 305 302 return 0; 306 303 307 - profile = begin_current_profile_crit_section(); 308 - if (!unconfined(profile)) 309 - error = aa_path_link(profile, old_dentry, new_dir, new_dentry); 310 - end_current_profile_crit_section(profile); 304 + label = begin_current_label_crit_section(); 305 + if (!unconfined(label)) 306 + error = aa_path_link(labels_profile(label), old_dentry, new_dir, 307 + new_dentry); 308 + end_current_label_crit_section(label); 311 309 312 310 return error; 313 311 } ··· 316 312 static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_dentry, 317 313 const struct path *new_dir, struct dentry *new_dentry) 318 314 { 319 - struct aa_profile *profile; 315 + struct aa_label *label; 320 316 int error = 0; 321 317 322 318 if (!path_mediated_fs(old_dentry)) 323 319 return 0; 324 320 325 - profile = begin_current_profile_crit_section(); 326 - if (!unconfined(profile)) { 321 + label = begin_current_label_crit_section(); 322 + if (!unconfined(label)) { 327 323 struct path old_path = { .mnt = old_dir->mnt, 328 324 .dentry = old_dentry }; 329 325 struct path new_path = { .mnt = new_dir->mnt, ··· 332 328 d_backing_inode(old_dentry)->i_mode 333 329 }; 334 330 335 - error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0, 331 + error = aa_path_perm(OP_RENAME_SRC, labels_profile(label), 332 + &old_path, 0, 336 333 MAY_READ | AA_MAY_GETATTR | MAY_WRITE | 337 334 AA_MAY_SETATTR | AA_MAY_DELETE, 338 335 &cond); 339 336 if (!error) 340 - error = aa_path_perm(OP_RENAME_DEST, profile, &new_path, 337 + error = aa_path_perm(OP_RENAME_DEST, 338 + labels_profile(label), 339 + &new_path, 341 340 0, MAY_WRITE | AA_MAY_SETATTR | 342 341 AA_MAY_CREATE, &cond); 343 342 344 343 } 345 - end_current_profile_crit_section(profile); 344 + end_current_label_crit_section(label); 346 345 347 346 return error; 348 347 } ··· 367 360 368 361 static int apparmor_file_open(struct file *file, const struct cred *cred) 369 362 { 370 - struct aa_file_ctx *fctx = file->f_security; 371 - struct aa_profile *profile; 363 + struct aa_file_ctx *fctx = file_ctx(file); 364 + struct aa_label *label; 372 365 int error = 0; 373 366 374 367 if (!path_mediated_fs(file->f_path.dentry)) ··· 384 377 return 0; 385 378 } 386 379 387 - profile = aa_get_newest_cred_profile(cred); 388 - if (!unconfined(profile)) { 380 + label = aa_get_newest_cred_label(cred); 381 + if (!unconfined(label)) { 389 382 struct inode *inode = file_inode(file); 390 383 struct path_cond cond = { inode->i_uid, inode->i_mode }; 391 384 392 - error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0, 385 + error = aa_path_perm(OP_OPEN, labels_profile(label), 386 + &file->f_path, 0, 393 387 aa_map_file_to_perms(file), &cond); 394 388 /* todo cache full allowed permissions set and state */ 395 389 fctx->allow = aa_map_file_to_perms(file); 396 390 } 397 - aa_put_profile(profile); 391 + aa_put_label(label); 398 392 399 393 return error; 400 394 } ··· 405 397 int error = 0; 406 398 407 399 /* freed by apparmor_file_free_security */ 408 - struct aa_profile *profile = begin_current_profile_crit_section(); 400 + struct aa_label *label = begin_current_label_crit_section(); 409 401 file->f_security = aa_alloc_file_ctx(GFP_KERNEL); 410 402 if (!file_ctx(file)) 411 403 error = -ENOMEM; 412 - end_current_profile_crit_section(profile); 404 + end_current_label_crit_section(label); 413 405 414 406 return error; 415 407 } ··· 422 414 static int common_file_perm(const char *op, struct file *file, u32 mask) 423 415 { 424 416 struct aa_file_ctx *fctx = file->f_security; 425 - struct aa_profile *profile, *fprofile; 417 + struct aa_label *label, *flabel; 426 418 int error = 0; 427 419 428 420 /* don't reaudit files closed during inheritance */ 429 421 if (file->f_path.dentry == aa_null.dentry) 430 422 return -EACCES; 431 423 432 - fprofile = aa_cred_raw_profile(file->f_cred); 433 - AA_BUG(!fprofile); 424 + flabel = aa_cred_raw_label(file->f_cred); 425 + AA_BUG(!flabel); 434 426 435 427 if (!file->f_path.mnt || 436 428 !path_mediated_fs(file->f_path.dentry)) 437 429 return 0; 438 430 439 - profile = __begin_current_profile_crit_section(); 431 + label = __begin_current_label_crit_section(); 440 432 441 433 /* revalidate access, if task is unconfined, or the cached cred 442 434 * doesn't match or if the request is for more permissions than ··· 445 437 * Note: the test for !unconfined(fprofile) is to handle file 446 438 * delegation from unconfined tasks 447 439 */ 448 - if (!unconfined(profile) && !unconfined(fprofile) && 449 - ((fprofile != profile) || (mask & ~fctx->allow))) 450 - error = aa_file_perm(op, profile, file, mask); 451 - __end_current_profile_crit_section(profile); 440 + if (!unconfined(label) && !unconfined(flabel) && 441 + ((flabel != label) || (mask & ~fctx->allow))) 442 + error = aa_file_perm(op, labels_profile(label), file, mask); 443 + __end_current_label_crit_section(label); 452 444 453 445 return error; 454 446 } ··· 473 465 { 474 466 int mask = 0; 475 467 476 - if (!file || !file->f_security) 468 + if (!file || !file_ctx(file)) 477 469 return 0; 478 470 479 471 if (prot & PROT_READ) ··· 510 502 /* released below */ 511 503 const struct cred *cred = get_task_cred(task); 512 504 struct aa_task_ctx *ctx = cred_ctx(cred); 513 - struct aa_profile *profile = NULL; 505 + struct aa_label *label = NULL; 514 506 515 507 if (strcmp(name, "current") == 0) 516 - profile = aa_get_newest_profile(ctx->profile); 508 + label = aa_get_newest_label(ctx->label); 517 509 else if (strcmp(name, "prev") == 0 && ctx->previous) 518 - profile = aa_get_newest_profile(ctx->previous); 510 + label = aa_get_newest_label(ctx->previous); 519 511 else if (strcmp(name, "exec") == 0 && ctx->onexec) 520 - profile = aa_get_newest_profile(ctx->onexec); 512 + label = aa_get_newest_label(ctx->onexec); 521 513 else 522 514 error = -EINVAL; 523 515 524 - if (profile) 525 - error = aa_getprocattr(profile, value); 516 + if (label) 517 + error = aa_getprocattr(labels_profile(label), value); 526 518 527 - aa_put_profile(profile); 519 + aa_put_label(label); 528 520 put_cred(cred); 529 521 530 522 return error; ··· 590 582 return error; 591 583 592 584 fail: 593 - aad(&sa)->profile = begin_current_profile_crit_section(); 585 + aad(&sa)->label = begin_current_label_crit_section(); 594 586 aad(&sa)->info = name; 595 587 aad(&sa)->error = error = -EINVAL; 596 588 aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); 597 - end_current_profile_crit_section(aad(&sa)->profile); 589 + end_current_label_crit_section(aad(&sa)->label); 598 590 goto out; 599 591 } 600 592 ··· 604 596 */ 605 597 static void apparmor_bprm_committing_creds(struct linux_binprm *bprm) 606 598 { 607 - struct aa_profile *profile = aa_current_raw_profile(); 599 + struct aa_label *label = aa_current_raw_label(); 608 600 struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred); 609 601 610 602 /* bail out if unconfined or not changing profile */ 611 - if ((new_ctx->profile == profile) || 612 - (unconfined(new_ctx->profile))) 603 + if ((new_ctx->label->proxy == label->proxy) || 604 + (unconfined(new_ctx->label))) 613 605 return; 614 606 615 607 aa_inherit_files(bprm->cred, current->files); 616 608 617 609 current->pdeath_signal = 0; 618 610 619 - /* reset soft limits and set hard limits for the new profile */ 620 - __aa_transition_rlimits(profile, new_ctx->profile); 611 + /* reset soft limits and set hard limits for the new label */ 612 + __aa_transition_rlimits(labels_profile(label), 613 + labels_profile(new_ctx->label)); 621 614 } 622 615 623 616 /** ··· 634 625 static int apparmor_task_setrlimit(struct task_struct *task, 635 626 unsigned int resource, struct rlimit *new_rlim) 636 627 { 637 - struct aa_profile *profile = __begin_current_profile_crit_section(); 628 + struct aa_label *label = __begin_current_label_crit_section(); 638 629 int error = 0; 639 630 640 - if (!unconfined(profile)) 641 - error = aa_task_setrlimit(profile, task, resource, new_rlim); 642 - __end_current_profile_crit_section(profile); 631 + if (!unconfined(label)) 632 + error = aa_task_setrlimit(labels_profile(label), task, 633 + resource, new_rlim); 634 + __end_current_label_crit_section(label); 643 635 644 636 return error; 645 637 } ··· 934 924 if (!ctx) 935 925 return -ENOMEM; 936 926 937 - ctx->profile = aa_get_profile(root_ns->unconfined); 927 + ctx->label = aa_get_label(ns_unconfined(root_ns)); 938 928 cred_ctx(cred) = ctx; 939 929 940 930 return 0;
+90 -118
security/apparmor/policy.c
··· 101 101 "unconfined", 102 102 }; 103 103 104 - /* requires profile list write lock held */ 105 - void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new) 106 - { 107 - struct aa_profile *tmp; 108 - 109 - tmp = rcu_dereference_protected(orig->proxy->profile, 110 - mutex_is_locked(&orig->ns->lock)); 111 - rcu_assign_pointer(orig->proxy->profile, aa_get_profile(new)); 112 - orig->flags |= PFLAG_STALE; 113 - aa_put_profile(tmp); 114 - } 115 104 116 105 /** 117 - * __list_add_profile - add a profile to a list 106 + * __add_profile - add a profiles to list and label tree 118 107 * @list: list to add it to (NOT NULL) 119 108 * @profile: the profile to add (NOT NULL) 120 109 * ··· 111 122 * 112 123 * Requires: namespace lock be held, or list not be shared 113 124 */ 114 - static void __list_add_profile(struct list_head *list, 115 - struct aa_profile *profile) 125 + static void __add_profile(struct list_head *list, struct aa_profile *profile) 116 126 { 127 + struct aa_label *l; 128 + 129 + AA_BUG(!list); 130 + AA_BUG(!profile); 131 + AA_BUG(!profile->ns); 132 + AA_BUG(!mutex_is_locked(&profile->ns->lock)); 133 + 117 134 list_add_rcu(&profile->base.list, list); 118 135 /* get list reference */ 119 136 aa_get_profile(profile); 137 + l = aa_label_insert(&profile->ns->labels, &profile->label); 138 + AA_BUG(l != &profile->label); 139 + aa_put_label(l); 120 140 } 121 141 122 142 /** ··· 142 144 */ 143 145 static void __list_remove_profile(struct aa_profile *profile) 144 146 { 147 + AA_BUG(!profile); 148 + AA_BUG(!profile->ns); 149 + AA_BUG(!mutex_is_locked(&profile->ns->lock)); 150 + 145 151 list_del_rcu(&profile->base.list); 146 152 aa_put_profile(profile); 147 153 } ··· 158 156 */ 159 157 static void __remove_profile(struct aa_profile *profile) 160 158 { 159 + AA_BUG(!profile); 160 + AA_BUG(!profile->ns); 161 + AA_BUG(!mutex_is_locked(&profile->ns->lock)); 162 + 161 163 /* release any children lists first */ 162 164 __aa_profile_list_release(&profile->base.profiles); 163 165 /* released by free_profile */ 164 - __aa_update_proxy(profile, profile->ns->unconfined); 166 + aa_label_remove(&profile->label); 165 167 __aafs_profile_rmdir(profile); 166 168 __list_remove_profile(profile); 167 169 } ··· 181 175 struct aa_profile *profile, *tmp; 182 176 list_for_each_entry_safe(profile, tmp, head, base.list) 183 177 __remove_profile(profile); 184 - } 185 - 186 - 187 - static void free_proxy(struct aa_proxy *p) 188 - { 189 - if (p) { 190 - /* r->profile will not be updated any more as r is dead */ 191 - aa_put_profile(rcu_dereference_protected(p->profile, true)); 192 - kzfree(p); 193 - } 194 - } 195 - 196 - 197 - void aa_free_proxy_kref(struct kref *kref) 198 - { 199 - struct aa_proxy *p = container_of(kref, struct aa_proxy, count); 200 - 201 - free_proxy(p); 202 178 } 203 179 204 180 /** ··· 230 242 kzfree(profile->dirname); 231 243 aa_put_dfa(profile->xmatch); 232 244 aa_put_dfa(profile->policy.dfa); 233 - aa_put_proxy(profile->proxy); 234 245 235 246 if (profile->data) { 236 247 rht = profile->data; ··· 240 253 241 254 kzfree(profile->hash); 242 255 aa_put_loaddata(profile->rawdata); 256 + 243 257 kzfree(profile); 244 - } 245 - 246 - /** 247 - * aa_free_profile_rcu - free aa_profile by rcu (called by aa_free_profile_kref) 248 - * @head: rcu_head callback for freeing of a profile (NOT NULL) 249 - */ 250 - static void aa_free_profile_rcu(struct rcu_head *head) 251 - { 252 - struct aa_profile *p = container_of(head, struct aa_profile, rcu); 253 - if (p->flags & PFLAG_NS_COUNT) 254 - aa_free_ns(p->ns); 255 - else 256 - aa_free_profile(p); 257 - } 258 - 259 - /** 260 - * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile) 261 - * @kr: kref callback for freeing of a profile (NOT NULL) 262 - */ 263 - void aa_free_profile_kref(struct kref *kref) 264 - { 265 - struct aa_profile *p = container_of(kref, struct aa_profile, count); 266 - call_rcu(&p->rcu, aa_free_profile_rcu); 267 258 } 268 259 269 260 /** ··· 251 286 * 252 287 * Returns: refcount profile or NULL on failure 253 288 */ 254 - struct aa_profile *aa_alloc_profile(const char *hname, gfp_t gfp) 289 + struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy, 290 + gfp_t gfp) 255 291 { 256 292 struct aa_profile *profile; 257 293 258 294 /* freed by free_profile - usually through aa_put_profile */ 259 - profile = kzalloc(sizeof(*profile), gfp); 295 + profile = kzalloc(sizeof(*profile) + sizeof(struct aa_profile *) * 2, 296 + gfp); 260 297 if (!profile) 261 298 return NULL; 262 299 263 - profile->proxy = kzalloc(sizeof(struct aa_proxy), gfp); 264 - if (!profile->proxy) 265 - goto fail; 266 - kref_init(&profile->proxy->count); 267 - 268 300 if (!aa_policy_init(&profile->base, NULL, hname, gfp)) 269 301 goto fail; 270 - kref_init(&profile->count); 302 + if (!aa_label_init(&profile->label, 1)) 303 + goto fail; 304 + 305 + /* update being set needed by fs interface */ 306 + if (!proxy) { 307 + proxy = aa_alloc_proxy(&profile->label, gfp); 308 + if (!proxy) 309 + goto fail; 310 + } else 311 + aa_get_proxy(proxy); 312 + profile->label.proxy = proxy; 313 + 314 + profile->label.hname = profile->base.hname; 315 + profile->label.flags |= FLAG_PROFILE; 316 + profile->label.vec[0] = profile; 271 317 272 318 /* refcount released by caller */ 273 319 return profile; 274 320 275 321 fail: 276 - kzfree(profile->proxy); 277 - kzfree(profile); 322 + aa_free_profile(profile); 278 323 279 324 return NULL; 280 325 } ··· 337 362 if (profile) 338 363 goto out; 339 364 340 - profile = aa_alloc_profile(name, gfp); 365 + profile = aa_alloc_profile(name, NULL, gfp); 341 366 if (!profile) 342 367 goto fail; 343 368 344 369 profile->mode = APPARMOR_COMPLAIN; 345 - profile->flags |= PFLAG_NULL; 370 + profile->label.flags |= FLAG_NULL; 346 371 if (hat) 347 - profile->flags |= PFLAG_HAT; 372 + profile->label.flags |= FLAG_HAT; 348 373 profile->path_flags = parent->path_flags; 349 374 350 375 /* released on free_profile */ ··· 354 379 profile->policy.dfa = aa_get_dfa(nulldfa); 355 380 356 381 mutex_lock(&profile->ns->lock); 357 - __list_add_profile(&parent->base.profiles, profile); 382 + __add_profile(&parent->base.profiles, profile); 358 383 mutex_unlock(&profile->ns->lock); 359 384 360 385 /* refcount released by caller */ ··· 364 389 return profile; 365 390 366 391 fail: 367 - kfree(name); 368 392 aa_free_profile(profile); 369 393 return NULL; 370 394 } ··· 530 556 return aa_lookupn_profile(ns, hname, strlen(hname)); 531 557 } 532 558 533 - struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, 559 + struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, 534 560 const char *fqname, size_t n) 535 561 { 536 562 struct aa_profile *profile; ··· 540 566 541 567 name = aa_splitn_fqname(fqname, n, &ns_name, &ns_len); 542 568 if (ns_name) { 543 - ns = aa_lookupn_ns(base->ns, ns_name, ns_len); 569 + ns = aa_lookupn_ns(labels_ns(base), ns_name, ns_len); 544 570 if (!ns) 545 571 return NULL; 546 572 } else 547 - ns = aa_get_ns(base->ns); 573 + ns = aa_get_ns(labels_ns(base)); 548 574 549 575 if (name) 550 576 profile = aa_lookupn_profile(ns, name, n - (name - fqname)); ··· 570 596 const char **info) 571 597 { 572 598 if (profile) { 573 - if (profile->flags & PFLAG_IMMUTABLE) { 599 + if (profile->label.flags & FLAG_IMMUTIBLE) { 574 600 *info = "cannot replace immutible profile"; 575 601 return -EPERM; 576 602 } else if (noreplace) { ··· 593 619 } 594 620 595 621 /** 596 - * aa_audit_policy - Do auditing of policy changes 597 - * @profile: profile to check if it can manage policy 622 + * audit_policy - Do auditing of policy changes 623 + * @label: label to check if it can manage policy 598 624 * @op: policy operation being performed 599 - * @gfp: memory allocation flags 600 - * @nsname: name of the ns being manipulated (MAY BE NULL) 625 + * @ns_name: name of namespace being manipulated 601 626 * @name: name of profile being manipulated (NOT NULL) 602 627 * @info: any extra information to be audited (MAYBE NULL) 603 628 * @error: error code 604 629 * 605 630 * Returns: the error to be returned after audit is done 606 631 */ 607 - static int audit_policy(struct aa_profile *profile, const char *op, 608 - const char *nsname, const char *name, 632 + static int audit_policy(struct aa_label *label, const char *op, 633 + const char *ns_name, const char *name, 609 634 const char *info, int error) 610 635 { 611 636 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op); 612 637 613 - aad(&sa)->iface.ns = nsname; 638 + aad(&sa)->iface.ns = ns_name; 614 639 aad(&sa)->name = name; 615 640 aad(&sa)->info = info; 616 641 aad(&sa)->error = error; 642 + aad(&sa)->label = label; 617 643 618 - return aa_audit(AUDIT_APPARMOR_STATUS, profile, &sa, audit_cb); 644 + aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, audit_cb); 645 + 646 + return error; 619 647 } 620 648 621 649 /** ··· 661 685 662 686 /** 663 687 * aa_may_manage_policy - can the current task manage policy 664 - * @profile: profile to check if it can manage policy 688 + * @label: label to check if it can manage policy 665 689 * @op: the policy manipulation operation being done 666 690 * 667 691 * Returns: 0 if the task is allowed to manipulate policy else error 668 692 */ 669 - int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, u32 mask) 693 + int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask) 670 694 { 671 695 const char *op; 672 696 ··· 679 703 680 704 /* check if loading policy is locked out */ 681 705 if (aa_g_lock_policy) 682 - return audit_policy(profile, op, NULL, NULL, "policy_locked", 706 + return audit_policy(label, op, NULL, NULL, "policy_locked", 683 707 -EACCES); 684 708 685 709 if (!policy_admin_capable(ns)) 686 - return audit_policy(profile, op, NULL, NULL, "not policy admin", 710 + return audit_policy(label, op, NULL, NULL, "not policy admin", 687 711 -EACCES); 688 712 689 713 /* TODO: add fine grained mediation of policy loads */ ··· 726 750 * 727 751 * Requires: namespace list lock be held, or list not be shared 728 752 */ 729 - static void __replace_profile(struct aa_profile *old, struct aa_profile *new, 730 - bool share_proxy) 753 + static void __replace_profile(struct aa_profile *old, struct aa_profile *new) 731 754 { 732 755 struct aa_profile *child, *tmp; 733 756 ··· 741 766 p = __find_child(&new->base.profiles, child->base.name); 742 767 if (p) { 743 768 /* @p replaces @child */ 744 - __replace_profile(child, p, share_proxy); 769 + __replace_profile(child, p); 745 770 continue; 746 771 } 747 772 ··· 759 784 struct aa_profile *parent = aa_deref_parent(old); 760 785 rcu_assign_pointer(new->parent, aa_get_profile(parent)); 761 786 } 762 - __aa_update_proxy(old, new); 763 - if (share_proxy) { 764 - aa_put_proxy(new->proxy); 765 - new->proxy = aa_get_proxy(old->proxy); 766 - } else if (!rcu_access_pointer(new->proxy->profile)) 767 - /* aafs interface uses proxy */ 768 - rcu_assign_pointer(new->proxy->profile, 769 - aa_get_profile(new)); 787 + aa_label_replace(&old->label, &new->label); 788 + /* migrate dents must come after label replacement b/c update */ 770 789 __aafs_profile_migrate_dents(old, new); 771 790 772 791 if (list_empty(&new->base.list)) { ··· 804 835 aa_get_str(old->base.hname); 805 836 new->base.hname = old->base.hname; 806 837 new->base.name = old->base.name; 838 + new->label.hname = old->label.hname; 807 839 } 808 840 809 841 /* Update to newest version of parent after previous replacements ··· 841 871 * 842 872 * Returns: size of data consumed else error code on failure. 843 873 */ 844 - ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, 874 + ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label, 845 875 u32 mask, struct aa_loaddata *udata) 846 876 { 847 877 const char *ns_name, *info = NULL; ··· 884 914 count++; 885 915 } 886 916 if (ns_name) { 887 - ns = aa_prepare_ns(policy_ns ? policy_ns : profile->ns, 917 + ns = aa_prepare_ns(policy_ns ? policy_ns : labels_ns(label), 888 918 ns_name); 889 919 if (IS_ERR(ns)) { 890 920 op = OP_PROF_LOAD; ··· 895 925 goto fail; 896 926 } 897 927 } else 898 - ns = aa_get_ns(policy_ns ? policy_ns : profile->ns); 928 + ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(label)); 899 929 900 930 mutex_lock(&ns->lock); 901 931 /* check for duplicate rawdata blobs: space and file dedup */ ··· 925 955 926 956 if (ent->new->rename) { 927 957 error = __lookup_replace(ns, ent->new->rename, 928 - !(mask & AA_MAY_REPLACE_POLICY), 929 - &ent->rename, &info); 958 + !(mask & AA_MAY_REPLACE_POLICY), 959 + &ent->rename, &info); 930 960 if (error) 931 961 goto fail_lock; 932 962 } ··· 991 1021 992 1022 if (ent->old && ent->old->rawdata == ent->new->rawdata) { 993 1023 /* dedup actual profile replacement */ 994 - audit_policy(profile, op, ns_name, ent->new->base.hname, 1024 + audit_policy(label, op, ns_name, ent->new->base.hname, 995 1025 "same as current profile, skipping", 996 1026 error); 997 1027 goto skip; ··· 1001 1031 * TODO: finer dedup based on profile range in data. Load set 1002 1032 * can differ but profile may remain unchanged 1003 1033 */ 1004 - audit_policy(profile, op, NULL, ent->new->base.hname, 1005 - NULL, error); 1034 + audit_policy(label, op, ns_name, ent->new->base.hname, NULL, 1035 + error); 1006 1036 1007 1037 if (ent->old) { 1008 1038 share_name(ent->old, ent->new); 1009 - __replace_profile(ent->old, ent->new, 1); 1039 + __replace_profile(ent->old, ent->new); 1010 1040 } else { 1011 1041 struct list_head *lh; 1012 1042 ··· 1017 1047 lh = &parent->base.profiles; 1018 1048 } else 1019 1049 lh = &ns->base.profiles; 1020 - __list_add_profile(lh, ent->new); 1050 + __add_profile(lh, ent->new); 1021 1051 } 1022 1052 skip: 1023 1053 aa_load_ent_free(ent); 1024 1054 } 1055 + __aa_labelset_update_subtree(ns); 1025 1056 mutex_unlock(&ns->lock); 1026 1057 1027 1058 out: ··· 1039 1068 /* audit cause of failure */ 1040 1069 op = (ent && !ent->old) ? OP_PROF_LOAD : OP_PROF_REPL; 1041 1070 fail: 1042 - audit_policy(profile, op, ns_name, ent ? ent->new->base.hname : NULL, 1043 - info, error); 1071 + audit_policy(label, op, ns_name, ent ? ent->new->base.hname : NULL, 1072 + info, error); 1044 1073 /* audit status that rest of profiles in the atomic set failed too */ 1045 1074 info = "valid profile in failed atomic policy load"; 1046 1075 list_for_each_entry(tmp, &lh, list) { ··· 1050 1079 continue; 1051 1080 } 1052 1081 op = (!tmp->old) ? OP_PROF_LOAD : OP_PROF_REPL; 1053 - audit_policy(profile, op, ns_name, 1054 - tmp->new->base.hname, info, error); 1082 + audit_policy(label, op, ns_name, tmp->new->base.hname, info, 1083 + error); 1055 1084 } 1056 1085 list_for_each_entry_safe(ent, tmp, &lh, list) { 1057 1086 list_del_init(&ent->list); ··· 1064 1093 /** 1065 1094 * aa_remove_profiles - remove profile(s) from the system 1066 1095 * @policy_ns: namespace the remove is being done from 1067 - * @subj: profile attempting to remove policy 1096 + * @subj: label attempting to remove policy 1068 1097 * @fqname: name of the profile or namespace to remove (NOT NULL) 1069 1098 * @size: size of the name 1070 1099 * ··· 1075 1104 * 1076 1105 * Returns: size of data consume else error code if fails 1077 1106 */ 1078 - ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_profile *subj, 1107 + ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj, 1079 1108 char *fqname, size_t size) 1080 1109 { 1081 1110 struct aa_ns *ns = NULL; ··· 1095 1124 1096 1125 name = aa_splitn_fqname(fqname, size, &ns_name, &ns_len); 1097 1126 /* released below */ 1098 - ns = aa_lookupn_ns(policy_ns ? policy_ns : subj->ns, ns_name, 1099 - ns_len); 1127 + ns = aa_lookupn_ns(policy_ns ? policy_ns : labels_ns(subj), 1128 + ns_name, ns_len); 1100 1129 if (!ns) { 1101 1130 info = "namespace does not exist"; 1102 1131 error = -ENOENT; ··· 1104 1133 } 1105 1134 } else 1106 1135 /* released below */ 1107 - ns = aa_get_ns(policy_ns ? policy_ns : subj->ns); 1136 + ns = aa_get_ns(policy_ns ? policy_ns : labels_ns(subj)); 1108 1137 1109 1138 if (!name) { 1110 1139 /* remove namespace - can only happen if fqname[0] == ':' */ ··· 1123 1152 } 1124 1153 name = profile->base.hname; 1125 1154 __remove_profile(profile); 1155 + __aa_labelset_update_subtree(ns); 1126 1156 __aa_bump_ns_revision(ns); 1127 1157 mutex_unlock(&ns->lock); 1128 1158 }
+15 -5
security/apparmor/policy_ns.c
··· 23 23 #include "include/apparmor.h" 24 24 #include "include/context.h" 25 25 #include "include/policy_ns.h" 26 + #include "include/label.h" 26 27 #include "include/policy.h" 27 28 28 29 /* root profile namespace */ ··· 105 104 init_waitqueue_head(&ns->wait); 106 105 107 106 /* released by aa_free_ns() */ 108 - ns->unconfined = aa_alloc_profile("unconfined", GFP_KERNEL); 107 + ns->unconfined = aa_alloc_profile("unconfined", NULL, GFP_KERNEL); 109 108 if (!ns->unconfined) 110 109 goto fail_unconfined; 111 110 112 - ns->unconfined->flags = PFLAG_IX_ON_NAME_ERROR | 113 - PFLAG_IMMUTABLE | PFLAG_NS_COUNT; 111 + ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR | 112 + FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; 114 113 ns->unconfined->mode = APPARMOR_UNCONFINED; 115 114 116 115 /* ns and ns->unconfined share ns->unconfined refcount */ 117 116 ns->unconfined->ns = ns; 118 117 119 118 atomic_set(&ns->uniq_null, 0); 119 + 120 + aa_labelset_init(&ns->labels); 120 121 121 122 return ns; 122 123 ··· 142 139 return; 143 140 144 141 aa_policy_destroy(&ns->base); 142 + aa_labelset_destroy(&ns->labels); 145 143 aa_put_ns(ns->parent); 146 144 147 145 ns->unconfined->ns = NULL; ··· 341 337 /* release all sub namespaces */ 342 338 __ns_list_release(&ns->sub_ns); 343 339 344 - if (ns->parent) 345 - __aa_update_proxy(ns->unconfined, ns->parent->unconfined); 340 + if (ns->parent) { 341 + unsigned long flags; 342 + 343 + write_lock_irqsave(&ns->labels.lock, flags); 344 + __aa_proxy_redirect(ns_unconfined(ns), 345 + ns_unconfined(ns->parent)); 346 + write_unlock_irqrestore(&ns->labels.lock, flags); 347 + } 346 348 __aafs_ns_rmdir(ns); 347 349 mutex_unlock(&ns->lock); 348 350 }
+7 -5
security/apparmor/policy_unpack.c
··· 26 26 #include "include/context.h" 27 27 #include "include/crypto.h" 28 28 #include "include/match.h" 29 + #include "include/path.h" 29 30 #include "include/policy.h" 30 31 #include "include/policy_unpack.h" 31 32 ··· 108 107 const char *name, const char *info, struct aa_ext *e, 109 108 int error) 110 109 { 111 - struct aa_profile *profile = aa_current_raw_profile(); 110 + struct aa_profile *profile = labels_profile(aa_current_raw_label()); 112 111 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL); 113 112 if (e) 114 113 aad(&sa)->iface.pos = e->pos - e->start; ··· 603 602 name = tmpname; 604 603 } 605 604 606 - profile = aa_alloc_profile(name, GFP_KERNEL); 605 + profile = aa_alloc_profile(name, NULL, GFP_KERNEL); 607 606 if (!profile) 608 607 return ERR_PTR(-ENOMEM); 609 608 ··· 636 635 if (!unpack_u32(e, &tmp, NULL)) 637 636 goto fail; 638 637 if (tmp & PACKED_FLAG_HAT) 639 - profile->flags |= PFLAG_HAT; 638 + profile->label.flags |= FLAG_HAT; 640 639 if (!unpack_u32(e, &tmp, NULL)) 641 640 goto fail; 642 641 if (tmp == PACKED_MODE_COMPLAIN || (e->version & FORCE_COMPLAIN_FLAG)) ··· 655 654 656 655 /* path_flags is optional */ 657 656 if (unpack_u32(e, &profile->path_flags, "path_flags")) 658 - profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED; 657 + profile->path_flags |= profile->label.flags & 658 + PATH_MEDIATE_DELETED; 659 659 else 660 660 /* set a default value if path_flags field is not present */ 661 - profile->path_flags = PFLAG_MEDIATE_DELETED; 661 + profile->path_flags = PATH_MEDIATE_DELETED; 662 662 663 663 if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) 664 664 goto fail;
+2 -2
security/apparmor/procattr.c
··· 55 55 ns_len += 4; 56 56 57 57 /* unconfined profiles don't have a mode string appended */ 58 - if (!unconfined(profile)) 58 + if (!profile_unconfined(profile)) 59 59 mode_len = strlen(mode_str) + 3; /* + 3 for _() */ 60 60 61 61 name_len = strlen(profile->base.hname); ··· 69 69 sprintf(s, ":%s://", ns_name); 70 70 s += ns_len; 71 71 } 72 - if (unconfined(profile)) 72 + if (profile_unconfined(profile)) 73 73 /* mode string not being appended */ 74 74 sprintf(s, "%s\n", profile->base.hname); 75 75 else
+4 -4
security/apparmor/resource.c
··· 86 86 int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, 87 87 unsigned int resource, struct rlimit *new_rlim) 88 88 { 89 - struct aa_profile *task_profile; 89 + struct aa_label *task_label; 90 90 int error = 0; 91 91 92 92 rcu_read_lock(); 93 - task_profile = aa_get_newest_cred_profile((__task_cred(task))); 93 + task_label = aa_get_newest_cred_label((__task_cred(task))); 94 94 rcu_read_unlock(); 95 95 96 96 /* TODO: extend resource control to handle other (non current) ··· 99 99 * the same profile or that the task setting the resource of another 100 100 * task has CAP_SYS_RESOURCE. 101 101 */ 102 - if ((profile != task_profile && 102 + if ((profile != labels_profile(task_label) && 103 103 aa_capable(profile, CAP_SYS_RESOURCE, 1)) || 104 104 (profile->rlimits.mask & (1 << resource) && 105 105 new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)) 106 106 error = -EACCES; 107 107 108 - aa_put_profile(task_profile); 108 + aa_put_label(task_label); 109 109 110 110 return audit_resource(profile, resource, new_rlim->rlim_max, error); 111 111 }