diff options
author | John Johansen <john.johansen@canonical.com> | 2017-06-09 11:14:28 -0400 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2017-06-10 20:11:38 -0400 |
commit | 637f688dc3dc304a89f441d76f49a0e35bc49c08 (patch) | |
tree | 78fee8a7aa212140c4c6b6a9b722bbba61802cab | |
parent | f1bd904175e8190ce14aedee37e207ab51fe3b30 (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/Makefile | 2 | ||||
-rw-r--r-- | security/apparmor/apparmorfs.c | 128 | ||||
-rw-r--r-- | security/apparmor/audit.c | 27 | ||||
-rw-r--r-- | security/apparmor/context.c | 87 | ||||
-rw-r--r-- | security/apparmor/domain.c | 77 | ||||
-rw-r--r-- | security/apparmor/file.c | 18 | ||||
-rw-r--r-- | security/apparmor/include/apparmor.h | 5 | ||||
-rw-r--r-- | security/apparmor/include/audit.h | 9 | ||||
-rw-r--r-- | security/apparmor/include/context.h | 158 | ||||
-rw-r--r-- | security/apparmor/include/perms.h | 12 | ||||
-rw-r--r-- | security/apparmor/include/policy.h | 110 | ||||
-rw-r--r-- | security/apparmor/include/policy_ns.h | 4 | ||||
-rw-r--r-- | security/apparmor/ipc.c | 29 | ||||
-rw-r--r-- | security/apparmor/lib.c | 163 | ||||
-rw-r--r-- | security/apparmor/lsm.c | 134 | ||||
-rw-r--r-- | security/apparmor/policy.c | 208 | ||||
-rw-r--r-- | security/apparmor/policy_ns.c | 20 | ||||
-rw-r--r-- | security/apparmor/policy_unpack.c | 12 | ||||
-rw-r--r-- | security/apparmor/procattr.c | 4 | ||||
-rw-r--r-- | security/apparmor/resource.c | 8 |
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 | ||
5 | apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ | 5 | apparmor-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 |
8 | apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o | 8 | apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o |
9 | 9 | ||
10 | clean-files := capability_names.h rlim_names.h | 10 | clean-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, | |||
405 | static ssize_t policy_update(u32 mask, const char __user *buf, size_t size, | 405 | static 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, | |||
738 | static ssize_t query_label(char *buf, size_t buf_len, | 741 | static 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) | |||
1026 | static int seq_profile_name_show(struct seq_file *seq, void *v) | 1029 | static 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) | |||
1036 | static int seq_profile_mode_show(struct seq_file *seq, void *v) | 1040 | static 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) | |||
1046 | static int seq_profile_attach_show(struct seq_file *seq, void *v) | 1051 | static 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) | |||
1061 | static int seq_profile_hash_show(struct seq_file *seq, void *v) | 1067 | static 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 | ||
1102 | static int seq_ns_level_show(struct seq_file *seq, void *v) | 1109 | static 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 | ||
1113 | static int seq_ns_name_show(struct seq_file *seq, void *v) | 1120 | static 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) | |||
47 | void aa_free_task_context(struct aa_task_ctx *ctx) | 47 | void 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) | |||
63 | void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old) | 63 | void 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 | */ |
77 | struct aa_profile *aa_get_task_profile(struct task_struct *task) | 77 | struct aa_label *aa_get_task_label(struct task_struct *task) |
78 | { | 78 | { |
79 | struct aa_profile *p; | 79 | struct aa_label *p; |
80 | 80 | ||
81 | 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 | */ |
94 | int aa_replace_current_profile(struct aa_profile *profile) | 94 | int 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 | */ |
137 | int aa_set_current_onexec(struct aa_profile *profile) | 137 | int aa_set_current_onexec(struct aa_label *label, bool stack) |
138 | { | 138 | { |
139 | 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 | */ |
163 | int aa_set_current_hat(struct aa_profile *profile, u64 token) | 164 | int 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 | */ |
201 | int aa_restore_previous_profile(u64 token) | 202 | int 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) | |||
61 | static int may_change_ptraced_domain(struct aa_profile *to_profile) | 61 | static 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 | ||
79 | out: | 80 | out: |
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, | |||
338 | int apparmor_bprm_set_creds(struct linux_binprm *bprm) | 339 | int 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 | ||
503 | x_clear: | 506 | x_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 | ||
517 | cleanup: | 520 | cleanup: |
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: | |||
692 | out: | 697 | out: |
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: | |||
716 | int aa_change_profile(const char *fqname, int flags) | 721 | int 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 | ||
792 | audit: | 799 | audit: |
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 | ||
454 | static void revalidate_tty(struct aa_profile *profile) | 454 | static 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 | ||
483 | static int match_file(const void *p, struct file *file, unsigned int fd) | 483 | static int match_file(const void *p, struct file *file, unsigned int fd) |
484 | { | 484 | { |
485 | struct aa_profile *profile = (struct aa_profile *)p; | 485 | struct aa_label *label = (struct aa_label *)p; |
486 | 486 | ||
487 | if (aa_file_perm(OP_INHERIT, profile, file, | 487 | if (aa_file_perm(OP_INHERIT, labels_profile(label), file, |
488 | 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 */ |
495 | void aa_inherit_files(const struct cred *cred, struct files_struct *files) | 495 | void aa_inherit_files(const struct cred *cred, struct files_struct *files) |
496 | { | 496 | { |
497 | struct aa_profile *profile = aa_get_newest_cred_profile(cred); | 497 | struct aa_label *label = aa_get_newest_cred_label(cred); |
498 | 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); |
517 | out: | 517 | out: |
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 */ |
34 | extern enum audit_mode aa_g_audit; | 35 | extern 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" | |
26 | struct aa_profile; | ||
27 | 26 | ||
28 | extern const char *const audit_mode_names[]; | 27 | extern 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 | ||
104 | struct apparmor_audit_data { | 103 | struct 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 | */ |
40 | struct aa_task_ctx { | 40 | struct 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); | |||
48 | void aa_free_task_context(struct aa_task_ctx *ctx); | 48 | void aa_free_task_context(struct aa_task_ctx *ctx); |
49 | void aa_dup_task_context(struct aa_task_ctx *new, | 49 | void aa_dup_task_context(struct aa_task_ctx *new, |
50 | const struct aa_task_ctx *old); | 50 | const struct aa_task_ctx *old); |
51 | int aa_replace_current_profile(struct aa_profile *profile); | 51 | int aa_replace_current_label(struct aa_label *label); |
52 | int aa_set_current_onexec(struct aa_profile *profile); | 52 | int aa_set_current_onexec(struct aa_label *label, bool stack); |
53 | int aa_set_current_hat(struct aa_profile *profile, u64 token); | 53 | int aa_set_current_hat(struct aa_label *label, u64 token); |
54 | int aa_restore_previous_profile(u64 cookie); | 54 | int aa_restore_previous_label(u64 cookie); |
55 | struct aa_profile *aa_get_task_profile(struct task_struct *task); | 55 | struct aa_label *aa_get_task_label(struct task_struct *task); |
56 | 56 | ||
57 | 57 | ||
58 | /** | 58 | /** |
59 | * aa_cred_raw_profile - obtain cred's profiles | 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 | */ |
66 | static inline struct aa_profile *aa_cred_raw_profile(const struct cred *cred) | 66 | static inline struct aa_label *aa_cred_raw_label(const struct cred *cred) |
67 | { | 67 | { |
68 | 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 | */ |
80 | static inline | 80 | static inline struct aa_label *aa_get_newest_cred_label(const struct cred *cred) |
81 | struct 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 | */ |
94 | static inline struct aa_profile *__aa_task_raw_profile(struct task_struct *task) | 93 | static inline struct aa_label *__aa_task_raw_label(struct task_struct *task) |
95 | { | 94 | { |
96 | return aa_cred_raw_profile(__task_cred(task)); | 95 | return aa_cred_raw_label(__task_cred(task)); |
97 | } | 96 | } |
98 | 97 | ||
99 | /** | 98 | /** |
@@ -104,113 +103,112 @@ static inline struct aa_profile *__aa_task_raw_profile(struct task_struct *task) | |||
104 | */ | 103 | */ |
105 | static inline bool __aa_task_is_confined(struct task_struct *task) | 104 | static 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 | */ |
118 | static inline struct aa_profile *aa_current_raw_profile(void) | 117 | static 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 | */ |
132 | static inline struct aa_profile *aa_get_current_profile(void) | 131 | static 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 | */ |
152 | static inline void end_current_profile_crit_section(struct aa_profile *profile) | 150 | static 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 | */ |
170 | static inline struct aa_profile *__begin_current_profile_crit_section(void) | 168 | static 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 | */ |
192 | static inline struct aa_profile *begin_current_profile_crit_section(void) | 190 | static 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 | ||
206 | static inline struct aa_ns *aa_get_current_ns(void) | 204 | static 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 | */ |
222 | static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) | 220 | static 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); |
102 | void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, | 103 | void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, |
103 | struct aa_perms *perms); | 104 | struct aa_perms *perms); |
104 | 105 | void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend); | |
106 | void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend); | ||
107 | void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, | ||
108 | int type, u32 request, struct aa_perms *perms); | ||
109 | int 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); | ||
112 | int 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 | ||
70 | enum 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 | |||
85 | struct 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 | ||
98 | struct 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 | */ |
157 | struct aa_profile { | 132 | struct 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 | ||
189 | extern enum profile_mode aa_g_profile_mode; | 161 | extern 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 | ||
195 | void __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 | ||
197 | void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); | 170 | void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); |
198 | 171 | ||
199 | 172 | ||
200 | void aa_free_proxy_kref(struct kref *kref); | 173 | void aa_free_proxy_kref(struct kref *kref); |
201 | struct aa_profile *aa_alloc_profile(const char *name, gfp_t gfp); | 174 | struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy, |
175 | gfp_t gfp); | ||
202 | struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, | 176 | struct 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); |
204 | void aa_free_profile(struct aa_profile *profile); | 178 | void aa_free_profile(struct aa_profile *profile); |
@@ -207,20 +181,33 @@ struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); | |||
207 | struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, | 181 | struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, |
208 | size_t n); | 182 | size_t n); |
209 | struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); | 183 | struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); |
210 | struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, | 184 | struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, |
211 | const char *fqname, size_t n); | 185 | const char *fqname, size_t n); |
212 | struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); | 186 | struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); |
213 | 187 | ||
214 | ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, | 188 | ssize_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); |
216 | ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *profile, | 190 | ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label, |
217 | char *name, size_t size); | 191 | char *name, size_t size); |
218 | void __aa_profile_list_release(struct list_head *head); | 192 | void __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 | */ | ||
207 | static 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, | |||
243 | static inline struct aa_profile *aa_get_profile(struct aa_profile *p) | 230 | static 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 | */ |
258 | static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p) | 245 | static 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 | */ | ||
294 | static 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 | */ |
309 | static inline void aa_put_profile(struct aa_profile *p) | 277 | static 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 | |||
315 | static 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 | |||
323 | static 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 | ||
329 | static inline int AUDIT_MODE(struct aa_profile *profile) | 283 | static inline int AUDIT_MODE(struct aa_profile *profile) |
@@ -336,7 +290,7 @@ static inline int AUDIT_MODE(struct aa_profile *profile) | |||
336 | 290 | ||
337 | bool policy_view_capable(struct aa_ns *ns); | 291 | bool policy_view_capable(struct aa_ns *ns); |
338 | bool policy_admin_capable(struct aa_ns *ns); | 292 | bool policy_admin_capable(struct aa_ns *ns); |
339 | int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, | 293 | int 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 | ||
81 | extern const char *aa_hidden_ns_name; | 83 | extern const char *aa_hidden_ns_name; |
82 | 84 | ||
85 | #define ns_unconfined(NS) (&(NS)->unconfined->label) | ||
86 | |||
83 | bool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns); | 87 | bool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns); |
84 | const char *aa_ns_name(struct aa_ns *parent, struct aa_ns *child, bool subns); | 88 | const char *aa_ns_name(struct aa_ns *parent, struct aa_ns *child, bool subns); |
85 | void aa_free_ns(struct aa_ns *ns); | 89 | void 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 */ |
25 | static void audit_cb(struct audit_buffer *ab, void *va) | 25 | static void audit_ptrace_cb(struct audit_buffer *ab, void *va) |
26 | { | 26 | { |
27 | 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 | */ | ||
254 | static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) | ||
255 | { | ||
256 | struct common_audit_data *sa = va; | ||
257 | |||
258 | if (aad(sa)->request) { | ||
259 | audit_log_format(ab, " requested_mask="); | ||
260 | aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs, | ||
261 | PERMS_CHRS_MASK, aa_file_perm_names, | ||
262 | PERMS_NAMES_MASK); | ||
263 | } | ||
264 | if (aad(sa)->denied) { | ||
265 | audit_log_format(ab, "denied_mask="); | ||
266 | aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs, | ||
267 | PERMS_CHRS_MASK, aa_file_perm_names, | ||
268 | PERMS_NAMES_MASK); | ||
269 | } | ||
270 | audit_log_format(ab, " peer="); | ||
271 | aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer, | ||
272 | FLAGS_NONE, GFP_ATOMIC); | ||
273 | } | ||
274 | |||
275 | /** | ||
250 | * 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 | */ | ||
343 | void 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 | */ | ||
362 | void 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 | |||
376 | void 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 */ | ||
390 | int 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 | */ | ||
424 | int 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 | */ |
54 | static void apparmor_cred_free(struct cred *cred) | 55 | static void apparmor_cred_free(struct cred *cred) |
55 | { | 56 | { |
@@ -115,23 +116,24 @@ static int apparmor_ptrace_traceme(struct task_struct *parent) | |||
115 | static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, | 116 | static 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, | |||
139 | static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, | 141 | static 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, | |||
162 | static int common_perm(const char *op, const struct path *path, u32 mask, | 164 | static 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, | |||
295 | static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_dir, | 298 | static 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_ | |||
312 | static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_dentry, | 316 | static 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 | ||
361 | static int apparmor_file_open(struct file *file, const struct cred *cred) | 368 | static 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) | |||
414 | static int common_file_perm(const char *op, struct file *file, u32 mask) | 422 | static 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 | ||
584 | fail: | 592 | fail: |
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 | */ |
597 | static void apparmor_bprm_committing_creds(struct linux_binprm *bprm) | 605 | static 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) | |||
625 | static int apparmor_task_setrlimit(struct task_struct *task, | 634 | static 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 */ | ||
105 | void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new) | ||
106 | { | ||
107 | struct aa_profile *tmp; | ||
108 | |||
109 | tmp = rcu_dereference_protected(orig->proxy->profile, | ||
110 | mutex_is_locked(&orig->ns->lock)); | ||
111 | rcu_assign_pointer(orig->proxy->profile, aa_get_profile(new)); | ||
112 | orig->flags |= PFLAG_STALE; | ||
113 | aa_put_profile(tmp); | ||
114 | } | ||
115 | 104 | ||
116 | /** | 105 | /** |
117 | * __list_add_profile - add a profile to a list | 106 | * __add_profile - add a profiles to list and label tree |
118 | * @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 | */ |
125 | static void __list_add_profile(struct list_head *list, | 114 | static 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 | */ |
145 | static void __list_remove_profile(struct aa_profile *profile) | 143 | static 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 | */ |
157 | static void __remove_profile(struct aa_profile *profile) | 159 | static 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 | |||
181 | static 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 | |||
191 | void 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 | */ | ||
263 | static 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 | */ | ||
276 | void 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 | */ |
289 | struct aa_profile *aa_alloc_profile(const char *hname, gfp_t gfp) | 254 | struct 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 | ||
310 | fail: | 286 | fail: |
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 | ||
391 | fail: | 366 | fail: |
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 | ||
559 | struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, | 533 | struct 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 | */ |
633 | static int audit_policy(struct aa_profile *profile, const char *op, | 606 | static 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 | */ |
693 | int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, u32 mask) | 669 | int 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 | */ |
753 | static void __replace_profile(struct aa_profile *old, struct aa_profile *new, | 729 | static 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 | */ |
874 | ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_profile *profile, | 844 | ssize_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 | ||
1057 | out: | 1028 | out: |
@@ -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; |
1070 | fail: | 1041 | fail: |
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 | */ |
1107 | ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_profile *subj, | 1078 | ssize_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 | ||
122 | fail_unconfined: | 125 | fail_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) | |||
86 | int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, | 86 | int 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 | } |