aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/tomoyo/common.c16
-rw-r--r--security/tomoyo/common.h53
-rw-r--r--security/tomoyo/domain.c25
-rw-r--r--security/tomoyo/file.c27
4 files changed, 25 insertions, 96 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index ef6622300a81..ae3ed7313ee0 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -842,9 +842,7 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
842 if (!domain) 842 if (!domain)
843 return true; 843 return true;
844 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 844 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
845 if (ptr->type & TOMOYO_ACL_DELETED) 845 switch (ptr->type) {
846 continue;
847 switch (tomoyo_acl_type2(ptr)) {
848 struct tomoyo_single_path_acl_record *acl; 846 struct tomoyo_single_path_acl_record *acl;
849 u32 perm; 847 u32 perm;
850 u8 i; 848 u8 i;
@@ -1384,8 +1382,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1384 return 0; 1382 return 0;
1385 } 1383 }
1386 if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { 1384 if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1387 tomoyo_set_domain_flag(domain, is_delete, 1385 domain->ignore_global_allow_read = !is_delete;
1388 TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
1389 return 0; 1386 return 0;
1390 } 1387 }
1391 return tomoyo_write_file_policy(data, domain, is_delete); 1388 return tomoyo_write_file_policy(data, domain, is_delete);
@@ -1486,10 +1483,8 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
1486static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, 1483static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1487 struct tomoyo_acl_info *ptr) 1484 struct tomoyo_acl_info *ptr)
1488{ 1485{
1489 const u8 acl_type = tomoyo_acl_type2(ptr); 1486 const u8 acl_type = ptr->type;
1490 1487
1491 if (acl_type & TOMOYO_ACL_DELETED)
1492 return true;
1493 if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) { 1488 if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) {
1494 struct tomoyo_single_path_acl_record *acl 1489 struct tomoyo_single_path_acl_record *acl
1495 = container_of(ptr, 1490 = container_of(ptr,
@@ -1540,10 +1535,9 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1540 /* Print domainname and flags. */ 1535 /* Print domainname and flags. */
1541 if (domain->quota_warned) 1536 if (domain->quota_warned)
1542 quota_exceeded = "quota_exceeded\n"; 1537 quota_exceeded = "quota_exceeded\n";
1543 if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED) 1538 if (domain->transition_failed)
1544 transition_failed = "transition_failed\n"; 1539 transition_failed = "transition_failed\n";
1545 if (domain->flags & 1540 if (domain->ignore_global_allow_read)
1546 TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
1547 ignore_global_allow_read 1541 ignore_global_allow_read
1548 = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; 1542 = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1549 done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE 1543 done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 8b59ec8fe11e..509ced9ce698 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -101,11 +101,9 @@ struct tomoyo_path_info_with_data {
101 * 101 *
102 * (1) "list" which is linked to the ->acl_info_list of 102 * (1) "list" which is linked to the ->acl_info_list of
103 * "struct tomoyo_domain_info" 103 * "struct tomoyo_domain_info"
104 * (2) "type" which tells 104 * (2) "type" which tells type of the entry (either
105 * (a) type & 0x7F : type of the entry (either 105 * "struct tomoyo_single_path_acl_record" or
106 * "struct tomoyo_single_path_acl_record" or 106 * "struct tomoyo_double_path_acl_record").
107 * "struct tomoyo_double_path_acl_record")
108 * (b) type & 0x80 : whether the entry is marked as "deleted".
109 * 107 *
110 * Packing "struct tomoyo_acl_info" allows 108 * Packing "struct tomoyo_acl_info" allows
111 * "struct tomoyo_single_path_acl_record" to embed "u8" + "u16" and 109 * "struct tomoyo_single_path_acl_record" to embed "u8" + "u16" and
@@ -114,17 +112,9 @@ struct tomoyo_path_info_with_data {
114 */ 112 */
115struct tomoyo_acl_info { 113struct tomoyo_acl_info {
116 struct list_head list; 114 struct list_head list;
117 /*
118 * Type of this ACL entry.
119 *
120 * MSB is is_deleted flag.
121 */
122 u8 type; 115 u8 type;
123} __packed; 116} __packed;
124 117
125/* This ACL entry is deleted. */
126#define TOMOYO_ACL_DELETED 0x80
127
128/* 118/*
129 * tomoyo_domain_info is a structure which is used for holding permissions 119 * tomoyo_domain_info is a structure which is used for holding permissions
130 * (e.g. "allow_read /lib/libc-2.5.so") given to each domain. 120 * (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
@@ -138,7 +128,13 @@ struct tomoyo_acl_info {
138 * "deleted", false otherwise. 128 * "deleted", false otherwise.
139 * (6) "quota_warned" is a bool which is used for suppressing warning message 129 * (6) "quota_warned" is a bool which is used for suppressing warning message
140 * when learning mode learned too much entries. 130 * when learning mode learned too much entries.
141 * (7) "flags" which remembers this domain's attributes. 131 * (7) "ignore_global_allow_read" is a bool which is true if this domain
132 * should ignore "allow_read" directive in exception policy.
133 * (8) "transition_failed" is a bool which is set to true when this domain was
134 * unable to create a new domain at tomoyo_find_next_domain() because the
135 * name of the domain to be created was too long or it could not allocate
136 * memory. If set to true, more than one process continued execve()
137 * without domain transition.
142 * 138 *
143 * A domain's lifecycle is an analogy of files on / directory. 139 * A domain's lifecycle is an analogy of files on / directory.
144 * Multiple domains with the same domainname cannot be created (as with 140 * Multiple domains with the same domainname cannot be created (as with
@@ -155,23 +151,13 @@ struct tomoyo_domain_info {
155 u8 profile; /* Profile number to use. */ 151 u8 profile; /* Profile number to use. */
156 bool is_deleted; /* Delete flag. */ 152 bool is_deleted; /* Delete flag. */
157 bool quota_warned; /* Quota warnning flag. */ 153 bool quota_warned; /* Quota warnning flag. */
158 /* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */ 154 bool ignore_global_allow_read; /* Ignore "allow_read" flag. */
159 u8 flags; 155 bool transition_failed; /* Domain transition failed flag. */
160}; 156};
161 157
162/* Profile number is an integer between 0 and 255. */ 158/* Profile number is an integer between 0 and 255. */
163#define TOMOYO_MAX_PROFILES 256 159#define TOMOYO_MAX_PROFILES 256
164 160
165/* Ignore "allow_read" directive in exception policy. */
166#define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1
167/*
168 * This domain was unable to create a new domain at tomoyo_find_next_domain()
169 * because the name of the domain to be created was too long or
170 * it could not allocate memory.
171 * More than one process continued execve() without domain transition.
172 */
173#define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED 2
174
175/* 161/*
176 * tomoyo_single_path_acl_record is a structure which is used for holding an 162 * tomoyo_single_path_acl_record is a structure which is used for holding an
177 * entry with one pathname operation (e.g. open(), mkdir()). 163 * entry with one pathname operation (e.g. open(), mkdir()).
@@ -380,9 +366,6 @@ unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
380void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); 366void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
381/* Run policy loader when /sbin/init starts. */ 367/* Run policy loader when /sbin/init starts. */
382void tomoyo_load_policy(const char *filename); 368void tomoyo_load_policy(const char *filename);
383/* Change "struct tomoyo_domain_info"->flags. */
384void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
385 const bool is_delete, const u8 flags);
386 369
387/* strcmp() for "struct tomoyo_path_info" structure. */ 370/* strcmp() for "struct tomoyo_path_info" structure. */
388static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, 371static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
@@ -391,18 +374,6 @@ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
391 return a->hash != b->hash || strcmp(a->name, b->name); 374 return a->hash != b->hash || strcmp(a->name, b->name);
392} 375}
393 376
394/* Get type of an ACL entry. */
395static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr)
396{
397 return ptr->type & ~TOMOYO_ACL_DELETED;
398}
399
400/* Get type of an ACL entry. */
401static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr)
402{
403 return ptr->type;
404}
405
406/** 377/**
407 * tomoyo_is_valid - Check whether the character is a valid char. 378 * tomoyo_is_valid - Check whether the character is a valid char.
408 * 379 *
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 34843971cc60..ec612ae87b51 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -130,28 +130,6 @@ struct tomoyo_alias_entry {
130}; 130};
131 131
132/** 132/**
133 * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
134 *
135 * @domain: Pointer to "struct tomoyo_domain_info".
136 * @is_delete: True if it is a delete request.
137 * @flags: Flags to set or clear.
138 *
139 * Returns nothing.
140 */
141void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
142 const bool is_delete, const u8 flags)
143{
144 /* We need to serialize because this is bitfield operation. */
145 static DEFINE_SPINLOCK(lock);
146 spin_lock(&lock);
147 if (!is_delete)
148 domain->flags |= flags;
149 else
150 domain->flags &= ~flags;
151 spin_unlock(&lock);
152}
153
154/**
155 * tomoyo_get_last_name - Get last component of a domainname. 133 * tomoyo_get_last_name - Get last component of a domainname.
156 * 134 *
157 * @domain: Pointer to "struct tomoyo_domain_info". 135 * @domain: Pointer to "struct tomoyo_domain_info".
@@ -896,8 +874,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
896 if (is_enforce) 874 if (is_enforce)
897 retval = -EPERM; 875 retval = -EPERM;
898 else 876 else
899 tomoyo_set_domain_flag(old_domain, false, 877 old_domain->transition_failed = true;
900 TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
901 out: 878 out:
902 if (!domain) 879 if (!domain)
903 domain = old_domain; 880 domain = old_domain;
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 24af081f1af9..84c821a245ca 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -688,7 +688,7 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
688 688
689 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 689 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
690 struct tomoyo_single_path_acl_record *acl; 690 struct tomoyo_single_path_acl_record *acl;
691 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) 691 if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL)
692 continue; 692 continue;
693 acl = container_of(ptr, struct tomoyo_single_path_acl_record, 693 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
694 head); 694 head);
@@ -770,8 +770,7 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
770 if (!filename) 770 if (!filename)
771 return 0; 771 return 0;
772 error = tomoyo_check_file_acl(domain, filename, perm); 772 error = tomoyo_check_file_acl(domain, filename, perm);
773 if (error && perm == 4 && 773 if (error && perm == 4 && !domain->ignore_global_allow_read
774 (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
775 && tomoyo_is_globally_readable_file(filename)) 774 && tomoyo_is_globally_readable_file(filename))
776 error = 0; 775 error = 0;
777 if (perm == 6) 776 if (perm == 6)
@@ -885,15 +884,12 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
885 if (is_delete) 884 if (is_delete)
886 goto delete; 885 goto delete;
887 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 886 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
888 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) 887 if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL)
889 continue; 888 continue;
890 acl = container_of(ptr, struct tomoyo_single_path_acl_record, 889 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
891 head); 890 head);
892 if (acl->filename != saved_filename) 891 if (acl->filename != saved_filename)
893 continue; 892 continue;
894 /* Special case. Clear all bits if marked as deleted. */
895 if (ptr->type & TOMOYO_ACL_DELETED)
896 acl->perm = 0;
897 if (perm <= 0xFFFF) 893 if (perm <= 0xFFFF)
898 acl->perm |= perm; 894 acl->perm |= perm;
899 else 895 else
@@ -902,7 +898,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
902 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; 898 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
903 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) 899 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
904 acl->perm |= rw_mask; 900 acl->perm |= rw_mask;
905 ptr->type &= ~TOMOYO_ACL_DELETED;
906 error = 0; 901 error = 0;
907 goto out; 902 goto out;
908 } 903 }
@@ -927,7 +922,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
927 delete: 922 delete:
928 error = -ENOENT; 923 error = -ENOENT;
929 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 924 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
930 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) 925 if (ptr->type != TOMOYO_TYPE_SINGLE_PATH_ACL)
931 continue; 926 continue;
932 acl = container_of(ptr, struct tomoyo_single_path_acl_record, 927 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
933 head); 928 head);
@@ -941,8 +936,6 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
941 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); 936 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
942 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) 937 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
943 acl->perm &= ~rw_mask; 938 acl->perm &= ~rw_mask;
944 if (!acl->perm && !acl->perm_high)
945 ptr->type |= TOMOYO_ACL_DELETED;
946 error = 0; 939 error = 0;
947 break; 940 break;
948 } 941 }
@@ -989,18 +982,14 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
989 if (is_delete) 982 if (is_delete)
990 goto delete; 983 goto delete;
991 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 984 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
992 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) 985 if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL)
993 continue; 986 continue;
994 acl = container_of(ptr, struct tomoyo_double_path_acl_record, 987 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
995 head); 988 head);
996 if (acl->filename1 != saved_filename1 || 989 if (acl->filename1 != saved_filename1 ||
997 acl->filename2 != saved_filename2) 990 acl->filename2 != saved_filename2)
998 continue; 991 continue;
999 /* Special case. Clear all bits if marked as deleted. */
1000 if (ptr->type & TOMOYO_ACL_DELETED)
1001 acl->perm = 0;
1002 acl->perm |= perm; 992 acl->perm |= perm;
1003 ptr->type &= ~TOMOYO_ACL_DELETED;
1004 error = 0; 993 error = 0;
1005 goto out; 994 goto out;
1006 } 995 }
@@ -1021,7 +1010,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
1021 delete: 1010 delete:
1022 error = -ENOENT; 1011 error = -ENOENT;
1023 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 1012 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1024 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) 1013 if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL)
1025 continue; 1014 continue;
1026 acl = container_of(ptr, struct tomoyo_double_path_acl_record, 1015 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
1027 head); 1016 head);
@@ -1029,8 +1018,6 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
1029 acl->filename2 != saved_filename2) 1018 acl->filename2 != saved_filename2)
1030 continue; 1019 continue;
1031 acl->perm &= ~perm; 1020 acl->perm &= ~perm;
1032 if (!acl->perm)
1033 ptr->type |= TOMOYO_ACL_DELETED;
1034 error = 0; 1021 error = 0;
1035 break; 1022 break;
1036 } 1023 }
@@ -1086,7 +1073,7 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
1086 return 0; 1073 return 0;
1087 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 1074 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1088 struct tomoyo_double_path_acl_record *acl; 1075 struct tomoyo_double_path_acl_record *acl;
1089 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) 1076 if (ptr->type != TOMOYO_TYPE_DOUBLE_PATH_ACL)
1090 continue; 1077 continue;
1091 acl = container_of(ptr, struct tomoyo_double_path_acl_record, 1078 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
1092 head); 1079 head);