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