diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2009-12-07 19:34:43 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-12-14 23:46:31 -0500 |
commit | fdb8ebb729bbb640e64028a4f579a02ebc405727 (patch) | |
tree | 9dfca7422cb858cd05208734affab31d980030fe | |
parent | 86fc80f16e8a2449d5827bf1a9838b7fd9f70097 (diff) |
TOMOYO: Use RCU primitives for list operation
Replace list operation with RCU primitives and replace
down_read()/up_read() with srcu_read_lock()/srcu_read_unlock().
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r-- | security/tomoyo/common.c | 90 | ||||
-rw-r--r-- | security/tomoyo/common.h | 28 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 63 | ||||
-rw-r--r-- | security/tomoyo/file.c | 110 | ||||
-rw-r--r-- | security/tomoyo/realpath.c | 8 | ||||
-rw-r--r-- | security/tomoyo/tomoyo.c | 20 |
6 files changed, 207 insertions, 112 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 6c6061682438..f01b9364db2d 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -365,10 +365,9 @@ bool tomoyo_is_domain_def(const unsigned char *buffer) | |||
365 | * | 365 | * |
366 | * @domainname: The domainname to find. | 366 | * @domainname: The domainname to find. |
367 | * | 367 | * |
368 | * Caller must call down_read(&tomoyo_domain_list_lock); or | ||
369 | * down_write(&tomoyo_domain_list_lock); . | ||
370 | * | ||
371 | * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. | 368 | * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. |
369 | * | ||
370 | * Caller holds tomoyo_read_lock(). | ||
372 | */ | 371 | */ |
373 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) | 372 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) |
374 | { | 373 | { |
@@ -377,7 +376,7 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) | |||
377 | 376 | ||
378 | name.name = domainname; | 377 | name.name = domainname; |
379 | tomoyo_fill_path_info(&name); | 378 | tomoyo_fill_path_info(&name); |
380 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | 379 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
381 | if (!domain->is_deleted && | 380 | if (!domain->is_deleted && |
382 | !tomoyo_pathcmp(&name, domain->domainname)) | 381 | !tomoyo_pathcmp(&name, domain->domainname)) |
383 | return domain; | 382 | return domain; |
@@ -829,6 +828,8 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain) | |||
829 | * @domain: Pointer to "struct tomoyo_domain_info". | 828 | * @domain: Pointer to "struct tomoyo_domain_info". |
830 | * | 829 | * |
831 | * Returns true if the domain is not exceeded quota, false otherwise. | 830 | * Returns true if the domain is not exceeded quota, false otherwise. |
831 | * | ||
832 | * Caller holds tomoyo_read_lock(). | ||
832 | */ | 833 | */ |
833 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) | 834 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) |
834 | { | 835 | { |
@@ -837,8 +838,7 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) | |||
837 | 838 | ||
838 | if (!domain) | 839 | if (!domain) |
839 | return true; | 840 | return true; |
840 | down_read(&tomoyo_domain_acl_info_list_lock); | 841 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
841 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
842 | if (ptr->type & TOMOYO_ACL_DELETED) | 842 | if (ptr->type & TOMOYO_ACL_DELETED) |
843 | continue; | 843 | continue; |
844 | switch (tomoyo_acl_type2(ptr)) { | 844 | switch (tomoyo_acl_type2(ptr)) { |
@@ -866,7 +866,6 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) | |||
866 | break; | 866 | break; |
867 | } | 867 | } |
868 | } | 868 | } |
869 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
870 | if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) | 869 | if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) |
871 | return true; | 870 | return true; |
872 | if (!domain->quota_warned) { | 871 | if (!domain->quota_warned) { |
@@ -1096,6 +1095,8 @@ static DECLARE_RWSEM(tomoyo_policy_manager_list_lock); | |||
1096 | * @is_delete: True if it is a delete request. | 1095 | * @is_delete: True if it is a delete request. |
1097 | * | 1096 | * |
1098 | * Returns 0 on success, negative value otherwise. | 1097 | * Returns 0 on success, negative value otherwise. |
1098 | * | ||
1099 | * Caller holds tomoyo_read_lock(). | ||
1099 | */ | 1100 | */ |
1100 | static int tomoyo_update_manager_entry(const char *manager, | 1101 | static int tomoyo_update_manager_entry(const char *manager, |
1101 | const bool is_delete) | 1102 | const bool is_delete) |
@@ -1118,7 +1119,7 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1118 | if (!saved_manager) | 1119 | if (!saved_manager) |
1119 | return -ENOMEM; | 1120 | return -ENOMEM; |
1120 | down_write(&tomoyo_policy_manager_list_lock); | 1121 | down_write(&tomoyo_policy_manager_list_lock); |
1121 | list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { | 1122 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { |
1122 | if (ptr->manager != saved_manager) | 1123 | if (ptr->manager != saved_manager) |
1123 | continue; | 1124 | continue; |
1124 | ptr->is_deleted = is_delete; | 1125 | ptr->is_deleted = is_delete; |
@@ -1134,7 +1135,7 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1134 | goto out; | 1135 | goto out; |
1135 | new_entry->manager = saved_manager; | 1136 | new_entry->manager = saved_manager; |
1136 | new_entry->is_domain = is_domain; | 1137 | new_entry->is_domain = is_domain; |
1137 | list_add_tail(&new_entry->list, &tomoyo_policy_manager_list); | 1138 | list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list); |
1138 | error = 0; | 1139 | error = 0; |
1139 | out: | 1140 | out: |
1140 | up_write(&tomoyo_policy_manager_list_lock); | 1141 | up_write(&tomoyo_policy_manager_list_lock); |
@@ -1147,6 +1148,8 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1147 | * @head: Pointer to "struct tomoyo_io_buffer". | 1148 | * @head: Pointer to "struct tomoyo_io_buffer". |
1148 | * | 1149 | * |
1149 | * Returns 0 on success, negative value otherwise. | 1150 | * Returns 0 on success, negative value otherwise. |
1151 | * | ||
1152 | * Caller holds tomoyo_read_lock(). | ||
1150 | */ | 1153 | */ |
1151 | static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) | 1154 | static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) |
1152 | { | 1155 | { |
@@ -1166,6 +1169,8 @@ static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) | |||
1166 | * @head: Pointer to "struct tomoyo_io_buffer". | 1169 | * @head: Pointer to "struct tomoyo_io_buffer". |
1167 | * | 1170 | * |
1168 | * Returns 0. | 1171 | * Returns 0. |
1172 | * | ||
1173 | * Caller holds tomoyo_read_lock(). | ||
1169 | */ | 1174 | */ |
1170 | static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) | 1175 | static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) |
1171 | { | 1176 | { |
@@ -1174,7 +1179,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) | |||
1174 | 1179 | ||
1175 | if (head->read_eof) | 1180 | if (head->read_eof) |
1176 | return 0; | 1181 | return 0; |
1177 | down_read(&tomoyo_policy_manager_list_lock); | ||
1178 | list_for_each_cookie(pos, head->read_var2, | 1182 | list_for_each_cookie(pos, head->read_var2, |
1179 | &tomoyo_policy_manager_list) { | 1183 | &tomoyo_policy_manager_list) { |
1180 | struct tomoyo_policy_manager_entry *ptr; | 1184 | struct tomoyo_policy_manager_entry *ptr; |
@@ -1186,7 +1190,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) | |||
1186 | if (!done) | 1190 | if (!done) |
1187 | break; | 1191 | break; |
1188 | } | 1192 | } |
1189 | up_read(&tomoyo_policy_manager_list_lock); | ||
1190 | head->read_eof = done; | 1193 | head->read_eof = done; |
1191 | return 0; | 1194 | return 0; |
1192 | } | 1195 | } |
@@ -1196,6 +1199,8 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) | |||
1196 | * | 1199 | * |
1197 | * Returns true if the current process is permitted to modify policy | 1200 | * Returns true if the current process is permitted to modify policy |
1198 | * via /sys/kernel/security/tomoyo/ interface. | 1201 | * via /sys/kernel/security/tomoyo/ interface. |
1202 | * | ||
1203 | * Caller holds tomoyo_read_lock(). | ||
1199 | */ | 1204 | */ |
1200 | static bool tomoyo_is_policy_manager(void) | 1205 | static bool tomoyo_is_policy_manager(void) |
1201 | { | 1206 | { |
@@ -1209,29 +1214,25 @@ static bool tomoyo_is_policy_manager(void) | |||
1209 | return true; | 1214 | return true; |
1210 | if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) | 1215 | if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) |
1211 | return false; | 1216 | return false; |
1212 | down_read(&tomoyo_policy_manager_list_lock); | 1217 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { |
1213 | list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { | ||
1214 | if (!ptr->is_deleted && ptr->is_domain | 1218 | if (!ptr->is_deleted && ptr->is_domain |
1215 | && !tomoyo_pathcmp(domainname, ptr->manager)) { | 1219 | && !tomoyo_pathcmp(domainname, ptr->manager)) { |
1216 | found = true; | 1220 | found = true; |
1217 | break; | 1221 | break; |
1218 | } | 1222 | } |
1219 | } | 1223 | } |
1220 | up_read(&tomoyo_policy_manager_list_lock); | ||
1221 | if (found) | 1224 | if (found) |
1222 | return true; | 1225 | return true; |
1223 | exe = tomoyo_get_exe(); | 1226 | exe = tomoyo_get_exe(); |
1224 | if (!exe) | 1227 | if (!exe) |
1225 | return false; | 1228 | return false; |
1226 | down_read(&tomoyo_policy_manager_list_lock); | 1229 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { |
1227 | list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { | ||
1228 | if (!ptr->is_deleted && !ptr->is_domain | 1230 | if (!ptr->is_deleted && !ptr->is_domain |
1229 | && !strcmp(exe, ptr->manager->name)) { | 1231 | && !strcmp(exe, ptr->manager->name)) { |
1230 | found = true; | 1232 | found = true; |
1231 | break; | 1233 | break; |
1232 | } | 1234 | } |
1233 | } | 1235 | } |
1234 | up_read(&tomoyo_policy_manager_list_lock); | ||
1235 | if (!found) { /* Reduce error messages. */ | 1236 | if (!found) { /* Reduce error messages. */ |
1236 | static pid_t last_pid; | 1237 | static pid_t last_pid; |
1237 | const pid_t pid = current->pid; | 1238 | const pid_t pid = current->pid; |
@@ -1252,6 +1253,8 @@ static bool tomoyo_is_policy_manager(void) | |||
1252 | * @data: String to parse. | 1253 | * @data: String to parse. |
1253 | * | 1254 | * |
1254 | * Returns true on success, false otherwise. | 1255 | * Returns true on success, false otherwise. |
1256 | * | ||
1257 | * Caller holds tomoyo_read_lock(). | ||
1255 | */ | 1258 | */ |
1256 | static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | 1259 | static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, |
1257 | const char *data) | 1260 | const char *data) |
@@ -1267,11 +1270,8 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | |||
1267 | domain = tomoyo_real_domain(p); | 1270 | domain = tomoyo_real_domain(p); |
1268 | read_unlock(&tasklist_lock); | 1271 | read_unlock(&tasklist_lock); |
1269 | } else if (!strncmp(data, "domain=", 7)) { | 1272 | } else if (!strncmp(data, "domain=", 7)) { |
1270 | if (tomoyo_is_domain_def(data + 7)) { | 1273 | if (tomoyo_is_domain_def(data + 7)) |
1271 | down_read(&tomoyo_domain_list_lock); | ||
1272 | domain = tomoyo_find_domain(data + 7); | 1274 | domain = tomoyo_find_domain(data + 7); |
1273 | up_read(&tomoyo_domain_list_lock); | ||
1274 | } | ||
1275 | } else | 1275 | } else |
1276 | return false; | 1276 | return false; |
1277 | head->write_var1 = domain; | 1277 | head->write_var1 = domain; |
@@ -1285,13 +1285,11 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | |||
1285 | if (domain) { | 1285 | if (domain) { |
1286 | struct tomoyo_domain_info *d; | 1286 | struct tomoyo_domain_info *d; |
1287 | head->read_var1 = NULL; | 1287 | head->read_var1 = NULL; |
1288 | down_read(&tomoyo_domain_list_lock); | 1288 | list_for_each_entry_rcu(d, &tomoyo_domain_list, list) { |
1289 | list_for_each_entry(d, &tomoyo_domain_list, list) { | ||
1290 | if (d == domain) | 1289 | if (d == domain) |
1291 | break; | 1290 | break; |
1292 | head->read_var1 = &d->list; | 1291 | head->read_var1 = &d->list; |
1293 | } | 1292 | } |
1294 | up_read(&tomoyo_domain_list_lock); | ||
1295 | head->read_var2 = NULL; | 1293 | head->read_var2 = NULL; |
1296 | head->read_bit = 0; | 1294 | head->read_bit = 0; |
1297 | head->read_step = 0; | 1295 | head->read_step = 0; |
@@ -1307,6 +1305,8 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | |||
1307 | * @domainname: The name of domain. | 1305 | * @domainname: The name of domain. |
1308 | * | 1306 | * |
1309 | * Returns 0. | 1307 | * Returns 0. |
1308 | * | ||
1309 | * Caller holds tomoyo_read_lock(). | ||
1310 | */ | 1310 | */ |
1311 | static int tomoyo_delete_domain(char *domainname) | 1311 | static int tomoyo_delete_domain(char *domainname) |
1312 | { | 1312 | { |
@@ -1317,7 +1317,7 @@ static int tomoyo_delete_domain(char *domainname) | |||
1317 | tomoyo_fill_path_info(&name); | 1317 | tomoyo_fill_path_info(&name); |
1318 | down_write(&tomoyo_domain_list_lock); | 1318 | down_write(&tomoyo_domain_list_lock); |
1319 | /* Is there an active domain? */ | 1319 | /* Is there an active domain? */ |
1320 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | 1320 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
1321 | /* Never delete tomoyo_kernel_domain */ | 1321 | /* Never delete tomoyo_kernel_domain */ |
1322 | if (domain == &tomoyo_kernel_domain) | 1322 | if (domain == &tomoyo_kernel_domain) |
1323 | continue; | 1323 | continue; |
@@ -1337,6 +1337,8 @@ static int tomoyo_delete_domain(char *domainname) | |||
1337 | * @head: Pointer to "struct tomoyo_io_buffer". | 1337 | * @head: Pointer to "struct tomoyo_io_buffer". |
1338 | * | 1338 | * |
1339 | * Returns 0 on success, negative value otherwise. | 1339 | * Returns 0 on success, negative value otherwise. |
1340 | * | ||
1341 | * Caller holds tomoyo_read_lock(). | ||
1340 | */ | 1342 | */ |
1341 | static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) | 1343 | static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) |
1342 | { | 1344 | { |
@@ -1359,11 +1361,9 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) | |||
1359 | domain = NULL; | 1361 | domain = NULL; |
1360 | if (is_delete) | 1362 | if (is_delete) |
1361 | tomoyo_delete_domain(data); | 1363 | tomoyo_delete_domain(data); |
1362 | else if (is_select) { | 1364 | else if (is_select) |
1363 | down_read(&tomoyo_domain_list_lock); | ||
1364 | domain = tomoyo_find_domain(data); | 1365 | domain = tomoyo_find_domain(data); |
1365 | up_read(&tomoyo_domain_list_lock); | 1366 | else |
1366 | } else | ||
1367 | domain = tomoyo_find_or_assign_new_domain(data, 0); | 1367 | domain = tomoyo_find_or_assign_new_domain(data, 0); |
1368 | head->write_var1 = domain; | 1368 | head->write_var1 = domain; |
1369 | return 0; | 1369 | return 0; |
@@ -1508,6 +1508,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
1508 | * @head: Pointer to "struct tomoyo_io_buffer". | 1508 | * @head: Pointer to "struct tomoyo_io_buffer". |
1509 | * | 1509 | * |
1510 | * Returns 0. | 1510 | * Returns 0. |
1511 | * | ||
1512 | * Caller holds tomoyo_read_lock(). | ||
1511 | */ | 1513 | */ |
1512 | static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) | 1514 | static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) |
1513 | { | 1515 | { |
@@ -1519,7 +1521,6 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) | |||
1519 | return 0; | 1521 | return 0; |
1520 | if (head->read_step == 0) | 1522 | if (head->read_step == 0) |
1521 | head->read_step = 1; | 1523 | head->read_step = 1; |
1522 | down_read(&tomoyo_domain_list_lock); | ||
1523 | list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) { | 1524 | list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) { |
1524 | struct tomoyo_domain_info *domain; | 1525 | struct tomoyo_domain_info *domain; |
1525 | const char *quota_exceeded = ""; | 1526 | const char *quota_exceeded = ""; |
@@ -1552,7 +1553,6 @@ acl_loop: | |||
1552 | if (head->read_step == 3) | 1553 | if (head->read_step == 3) |
1553 | goto tail_mark; | 1554 | goto tail_mark; |
1554 | /* Print ACL entries in the domain. */ | 1555 | /* Print ACL entries in the domain. */ |
1555 | down_read(&tomoyo_domain_acl_info_list_lock); | ||
1556 | list_for_each_cookie(apos, head->read_var2, | 1556 | list_for_each_cookie(apos, head->read_var2, |
1557 | &domain->acl_info_list) { | 1557 | &domain->acl_info_list) { |
1558 | struct tomoyo_acl_info *ptr | 1558 | struct tomoyo_acl_info *ptr |
@@ -1562,7 +1562,6 @@ acl_loop: | |||
1562 | if (!done) | 1562 | if (!done) |
1563 | break; | 1563 | break; |
1564 | } | 1564 | } |
1565 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
1566 | if (!done) | 1565 | if (!done) |
1567 | break; | 1566 | break; |
1568 | head->read_step = 3; | 1567 | head->read_step = 3; |
@@ -1574,7 +1573,6 @@ tail_mark: | |||
1574 | if (head->read_single_domain) | 1573 | if (head->read_single_domain) |
1575 | break; | 1574 | break; |
1576 | } | 1575 | } |
1577 | up_read(&tomoyo_domain_list_lock); | ||
1578 | head->read_eof = done; | 1576 | head->read_eof = done; |
1579 | return 0; | 1577 | return 0; |
1580 | } | 1578 | } |
@@ -1590,6 +1588,8 @@ tail_mark: | |||
1590 | * | 1588 | * |
1591 | * ( echo "select " $domainname; echo "use_profile " $profile ) | | 1589 | * ( echo "select " $domainname; echo "use_profile " $profile ) | |
1592 | * /usr/lib/ccs/loadpolicy -d | 1590 | * /usr/lib/ccs/loadpolicy -d |
1591 | * | ||
1592 | * Caller holds tomoyo_read_lock(). | ||
1593 | */ | 1593 | */ |
1594 | static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) | 1594 | static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) |
1595 | { | 1595 | { |
@@ -1601,9 +1601,7 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) | |||
1601 | if (!cp) | 1601 | if (!cp) |
1602 | return -EINVAL; | 1602 | return -EINVAL; |
1603 | *cp = '\0'; | 1603 | *cp = '\0'; |
1604 | down_read(&tomoyo_domain_list_lock); | ||
1605 | domain = tomoyo_find_domain(cp + 1); | 1604 | domain = tomoyo_find_domain(cp + 1); |
1606 | up_read(&tomoyo_domain_list_lock); | ||
1607 | if (strict_strtoul(data, 10, &profile)) | 1605 | if (strict_strtoul(data, 10, &profile)) |
1608 | return -EINVAL; | 1606 | return -EINVAL; |
1609 | if (domain && profile < TOMOYO_MAX_PROFILES | 1607 | if (domain && profile < TOMOYO_MAX_PROFILES |
@@ -1625,6 +1623,8 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) | |||
1625 | * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" ) | 1623 | * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" ) |
1626 | * domainname = $0; } else if ( $1 == "use_profile" ) { | 1624 | * domainname = $0; } else if ( $1 == "use_profile" ) { |
1627 | * print $2 " " domainname; domainname = ""; } } ; ' | 1625 | * print $2 " " domainname; domainname = ""; } } ; ' |
1626 | * | ||
1627 | * Caller holds tomoyo_read_lock(). | ||
1628 | */ | 1628 | */ |
1629 | static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) | 1629 | static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) |
1630 | { | 1630 | { |
@@ -1633,7 +1633,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) | |||
1633 | 1633 | ||
1634 | if (head->read_eof) | 1634 | if (head->read_eof) |
1635 | return 0; | 1635 | return 0; |
1636 | down_read(&tomoyo_domain_list_lock); | ||
1637 | list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) { | 1636 | list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) { |
1638 | struct tomoyo_domain_info *domain; | 1637 | struct tomoyo_domain_info *domain; |
1639 | domain = list_entry(pos, struct tomoyo_domain_info, list); | 1638 | domain = list_entry(pos, struct tomoyo_domain_info, list); |
@@ -1644,7 +1643,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) | |||
1644 | if (!done) | 1643 | if (!done) |
1645 | break; | 1644 | break; |
1646 | } | 1645 | } |
1647 | up_read(&tomoyo_domain_list_lock); | ||
1648 | head->read_eof = done; | 1646 | head->read_eof = done; |
1649 | return 0; | 1647 | return 0; |
1650 | } | 1648 | } |
@@ -1701,6 +1699,8 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head) | |||
1701 | * @head: Pointer to "struct tomoyo_io_buffer". | 1699 | * @head: Pointer to "struct tomoyo_io_buffer". |
1702 | * | 1700 | * |
1703 | * Returns 0 on success, negative value otherwise. | 1701 | * Returns 0 on success, negative value otherwise. |
1702 | * | ||
1703 | * Caller holds tomoyo_read_lock(). | ||
1704 | */ | 1704 | */ |
1705 | static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) | 1705 | static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) |
1706 | { | 1706 | { |
@@ -1735,6 +1735,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) | |||
1735 | * @head: Pointer to "struct tomoyo_io_buffer". | 1735 | * @head: Pointer to "struct tomoyo_io_buffer". |
1736 | * | 1736 | * |
1737 | * Returns 0 on success, -EINVAL otherwise. | 1737 | * Returns 0 on success, -EINVAL otherwise. |
1738 | * | ||
1739 | * Caller holds tomoyo_read_lock(). | ||
1738 | */ | 1740 | */ |
1739 | static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) | 1741 | static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) |
1740 | { | 1742 | { |
@@ -1864,15 +1866,13 @@ void tomoyo_load_policy(const char *filename) | |||
1864 | tomoyo_policy_loaded = true; | 1866 | tomoyo_policy_loaded = true; |
1865 | { /* Check all profiles currently assigned to domains are defined. */ | 1867 | { /* Check all profiles currently assigned to domains are defined. */ |
1866 | struct tomoyo_domain_info *domain; | 1868 | struct tomoyo_domain_info *domain; |
1867 | down_read(&tomoyo_domain_list_lock); | 1869 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
1868 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | ||
1869 | const u8 profile = domain->profile; | 1870 | const u8 profile = domain->profile; |
1870 | if (tomoyo_profile_ptr[profile]) | 1871 | if (tomoyo_profile_ptr[profile]) |
1871 | continue; | 1872 | continue; |
1872 | panic("Profile %u (used by '%s') not defined.\n", | 1873 | panic("Profile %u (used by '%s') not defined.\n", |
1873 | profile, domain->domainname->name); | 1874 | profile, domain->domainname->name); |
1874 | } | 1875 | } |
1875 | up_read(&tomoyo_domain_list_lock); | ||
1876 | } | 1876 | } |
1877 | } | 1877 | } |
1878 | 1878 | ||
@@ -1920,6 +1920,8 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head) | |||
1920 | * @file: Pointer to "struct file". | 1920 | * @file: Pointer to "struct file". |
1921 | * | 1921 | * |
1922 | * Associates policy handler and returns 0 on success, -ENOMEM otherwise. | 1922 | * Associates policy handler and returns 0 on success, -ENOMEM otherwise. |
1923 | * | ||
1924 | * Caller acquires tomoyo_read_lock(). | ||
1923 | */ | 1925 | */ |
1924 | static int tomoyo_open_control(const u8 type, struct file *file) | 1926 | static int tomoyo_open_control(const u8 type, struct file *file) |
1925 | { | 1927 | { |
@@ -2005,6 +2007,7 @@ static int tomoyo_open_control(const u8 type, struct file *file) | |||
2005 | return -ENOMEM; | 2007 | return -ENOMEM; |
2006 | } | 2008 | } |
2007 | } | 2009 | } |
2010 | head->reader_idx = tomoyo_read_lock(); | ||
2008 | file->private_data = head; | 2011 | file->private_data = head; |
2009 | /* | 2012 | /* |
2010 | * Call the handler now if the file is | 2013 | * Call the handler now if the file is |
@@ -2026,6 +2029,8 @@ static int tomoyo_open_control(const u8 type, struct file *file) | |||
2026 | * @buffer_len: Size of @buffer. | 2029 | * @buffer_len: Size of @buffer. |
2027 | * | 2030 | * |
2028 | * Returns bytes read on success, negative value otherwise. | 2031 | * Returns bytes read on success, negative value otherwise. |
2032 | * | ||
2033 | * Caller holds tomoyo_read_lock(). | ||
2029 | */ | 2034 | */ |
2030 | static int tomoyo_read_control(struct file *file, char __user *buffer, | 2035 | static int tomoyo_read_control(struct file *file, char __user *buffer, |
2031 | const int buffer_len) | 2036 | const int buffer_len) |
@@ -2069,6 +2074,8 @@ static int tomoyo_read_control(struct file *file, char __user *buffer, | |||
2069 | * @buffer_len: Size of @buffer. | 2074 | * @buffer_len: Size of @buffer. |
2070 | * | 2075 | * |
2071 | * Returns @buffer_len on success, negative value otherwise. | 2076 | * Returns @buffer_len on success, negative value otherwise. |
2077 | * | ||
2078 | * Caller holds tomoyo_read_lock(). | ||
2072 | */ | 2079 | */ |
2073 | static int tomoyo_write_control(struct file *file, const char __user *buffer, | 2080 | static int tomoyo_write_control(struct file *file, const char __user *buffer, |
2074 | const int buffer_len) | 2081 | const int buffer_len) |
@@ -2119,11 +2126,14 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer, | |||
2119 | * @file: Pointer to "struct file". | 2126 | * @file: Pointer to "struct file". |
2120 | * | 2127 | * |
2121 | * Releases memory and returns 0. | 2128 | * Releases memory and returns 0. |
2129 | * | ||
2130 | * Caller looses tomoyo_read_lock(). | ||
2122 | */ | 2131 | */ |
2123 | static int tomoyo_close_control(struct file *file) | 2132 | static int tomoyo_close_control(struct file *file) |
2124 | { | 2133 | { |
2125 | struct tomoyo_io_buffer *head = file->private_data; | 2134 | struct tomoyo_io_buffer *head = file->private_data; |
2126 | 2135 | ||
2136 | tomoyo_read_unlock(head->reader_idx); | ||
2127 | /* Release memory used for policy I/O. */ | 2137 | /* Release memory used for policy I/O. */ |
2128 | tomoyo_free(head->read_buf); | 2138 | tomoyo_free(head->read_buf); |
2129 | head->read_buf = NULL; | 2139 | head->read_buf = NULL; |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index bd10f9fa3511..c6f13925472a 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -269,6 +269,8 @@ struct tomoyo_io_buffer { | |||
269 | int (*write) (struct tomoyo_io_buffer *); | 269 | int (*write) (struct tomoyo_io_buffer *); |
270 | /* Exclusive lock for this structure. */ | 270 | /* Exclusive lock for this structure. */ |
271 | struct mutex io_sem; | 271 | struct mutex io_sem; |
272 | /* Index returned by tomoyo_read_lock(). */ | ||
273 | int reader_idx; | ||
272 | /* The position currently reading from. */ | 274 | /* The position currently reading from. */ |
273 | struct list_head *read_var1; | 275 | struct list_head *read_var1; |
274 | /* Extra variables for reading. */ | 276 | /* Extra variables for reading. */ |
@@ -446,16 +448,28 @@ extern struct tomoyo_domain_info tomoyo_kernel_domain; | |||
446 | * @cookie: the &struct list_head to use as a cookie. | 448 | * @cookie: the &struct list_head to use as a cookie. |
447 | * @head: the head for your list. | 449 | * @head: the head for your list. |
448 | * | 450 | * |
449 | * Same with list_for_each() except that this primitive uses @cookie | 451 | * Same with list_for_each_rcu() except that this primitive uses @cookie |
450 | * so that we can continue iteration. | 452 | * so that we can continue iteration. |
451 | * @cookie must be NULL when iteration starts, and @cookie will become | 453 | * @cookie must be NULL when iteration starts, and @cookie will become |
452 | * NULL when iteration finishes. | 454 | * NULL when iteration finishes. |
453 | */ | 455 | */ |
454 | #define list_for_each_cookie(pos, cookie, head) \ | 456 | #define list_for_each_cookie(pos, cookie, head) \ |
455 | for (({ if (!cookie) \ | 457 | for (({ if (!cookie) \ |
456 | cookie = head; }), \ | 458 | cookie = head; }), \ |
457 | pos = (cookie)->next; \ | 459 | pos = rcu_dereference((cookie)->next); \ |
458 | prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ | 460 | prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ |
459 | (cookie) = pos, pos = pos->next) | 461 | (cookie) = pos, pos = rcu_dereference(pos->next)) |
462 | |||
463 | extern struct srcu_struct tomoyo_ss; | ||
464 | |||
465 | static inline int tomoyo_read_lock(void) | ||
466 | { | ||
467 | return srcu_read_lock(&tomoyo_ss); | ||
468 | } | ||
469 | |||
470 | static inline void tomoyo_read_unlock(int idx) | ||
471 | { | ||
472 | srcu_read_unlock(&tomoyo_ss, idx); | ||
473 | } | ||
460 | 474 | ||
461 | #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ | 475 | #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index fcf52accce2b..2fd190168b7e 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -217,6 +217,8 @@ static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock); | |||
217 | * @is_delete: True if it is a delete request. | 217 | * @is_delete: True if it is a delete request. |
218 | * | 218 | * |
219 | * Returns 0 on success, negative value otherwise. | 219 | * Returns 0 on success, negative value otherwise. |
220 | * | ||
221 | * Caller holds tomoyo_read_lock(). | ||
220 | */ | 222 | */ |
221 | static int tomoyo_update_domain_initializer_entry(const char *domainname, | 223 | static int tomoyo_update_domain_initializer_entry(const char *domainname, |
222 | const char *program, | 224 | const char *program, |
@@ -246,7 +248,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
246 | if (!saved_program) | 248 | if (!saved_program) |
247 | return -ENOMEM; | 249 | return -ENOMEM; |
248 | down_write(&tomoyo_domain_initializer_list_lock); | 250 | down_write(&tomoyo_domain_initializer_list_lock); |
249 | list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { | 251 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { |
250 | if (ptr->is_not != is_not || | 252 | if (ptr->is_not != is_not || |
251 | ptr->domainname != saved_domainname || | 253 | ptr->domainname != saved_domainname || |
252 | ptr->program != saved_program) | 254 | ptr->program != saved_program) |
@@ -266,7 +268,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
266 | new_entry->program = saved_program; | 268 | new_entry->program = saved_program; |
267 | new_entry->is_not = is_not; | 269 | new_entry->is_not = is_not; |
268 | new_entry->is_last_name = is_last_name; | 270 | new_entry->is_last_name = is_last_name; |
269 | list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list); | 271 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); |
270 | error = 0; | 272 | error = 0; |
271 | out: | 273 | out: |
272 | up_write(&tomoyo_domain_initializer_list_lock); | 274 | up_write(&tomoyo_domain_initializer_list_lock); |
@@ -279,13 +281,14 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
279 | * @head: Pointer to "struct tomoyo_io_buffer". | 281 | * @head: Pointer to "struct tomoyo_io_buffer". |
280 | * | 282 | * |
281 | * Returns true on success, false otherwise. | 283 | * Returns true on success, false otherwise. |
284 | * | ||
285 | * Caller holds tomoyo_read_lock(). | ||
282 | */ | 286 | */ |
283 | bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) | 287 | bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) |
284 | { | 288 | { |
285 | struct list_head *pos; | 289 | struct list_head *pos; |
286 | bool done = true; | 290 | bool done = true; |
287 | 291 | ||
288 | down_read(&tomoyo_domain_initializer_list_lock); | ||
289 | list_for_each_cookie(pos, head->read_var2, | 292 | list_for_each_cookie(pos, head->read_var2, |
290 | &tomoyo_domain_initializer_list) { | 293 | &tomoyo_domain_initializer_list) { |
291 | const char *no; | 294 | const char *no; |
@@ -308,7 +311,6 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) | |||
308 | if (!done) | 311 | if (!done) |
309 | break; | 312 | break; |
310 | } | 313 | } |
311 | up_read(&tomoyo_domain_initializer_list_lock); | ||
312 | return done; | 314 | return done; |
313 | } | 315 | } |
314 | 316 | ||
@@ -320,6 +322,8 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) | |||
320 | * @is_delete: True if it is a delete request. | 322 | * @is_delete: True if it is a delete request. |
321 | * | 323 | * |
322 | * Returns 0 on success, negative value otherwise. | 324 | * Returns 0 on success, negative value otherwise. |
325 | * | ||
326 | * Caller holds tomoyo_read_lock(). | ||
323 | */ | 327 | */ |
324 | int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, | 328 | int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, |
325 | const bool is_delete) | 329 | const bool is_delete) |
@@ -345,6 +349,8 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, | |||
345 | * | 349 | * |
346 | * Returns true if executing @program reinitializes domain transition, | 350 | * Returns true if executing @program reinitializes domain transition, |
347 | * false otherwise. | 351 | * false otherwise. |
352 | * | ||
353 | * Caller holds tomoyo_read_lock(). | ||
348 | */ | 354 | */ |
349 | static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | 355 | static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * |
350 | domainname, | 356 | domainname, |
@@ -355,8 +361,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | |||
355 | struct tomoyo_domain_initializer_entry *ptr; | 361 | struct tomoyo_domain_initializer_entry *ptr; |
356 | bool flag = false; | 362 | bool flag = false; |
357 | 363 | ||
358 | down_read(&tomoyo_domain_initializer_list_lock); | 364 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { |
359 | list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { | ||
360 | if (ptr->is_deleted) | 365 | if (ptr->is_deleted) |
361 | continue; | 366 | continue; |
362 | if (ptr->domainname) { | 367 | if (ptr->domainname) { |
@@ -376,7 +381,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | |||
376 | } | 381 | } |
377 | flag = true; | 382 | flag = true; |
378 | } | 383 | } |
379 | up_read(&tomoyo_domain_initializer_list_lock); | ||
380 | return flag; | 384 | return flag; |
381 | } | 385 | } |
382 | 386 | ||
@@ -430,6 +434,8 @@ static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock); | |||
430 | * @is_delete: True if it is a delete request. | 434 | * @is_delete: True if it is a delete request. |
431 | * | 435 | * |
432 | * Returns 0 on success, negative value otherwise. | 436 | * Returns 0 on success, negative value otherwise. |
437 | * | ||
438 | * Caller holds tomoyo_read_lock(). | ||
433 | */ | 439 | */ |
434 | static int tomoyo_update_domain_keeper_entry(const char *domainname, | 440 | static int tomoyo_update_domain_keeper_entry(const char *domainname, |
435 | const char *program, | 441 | const char *program, |
@@ -459,7 +465,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
459 | if (!saved_domainname) | 465 | if (!saved_domainname) |
460 | return -ENOMEM; | 466 | return -ENOMEM; |
461 | down_write(&tomoyo_domain_keeper_list_lock); | 467 | down_write(&tomoyo_domain_keeper_list_lock); |
462 | list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { | 468 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { |
463 | if (ptr->is_not != is_not || | 469 | if (ptr->is_not != is_not || |
464 | ptr->domainname != saved_domainname || | 470 | ptr->domainname != saved_domainname || |
465 | ptr->program != saved_program) | 471 | ptr->program != saved_program) |
@@ -479,7 +485,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
479 | new_entry->program = saved_program; | 485 | new_entry->program = saved_program; |
480 | new_entry->is_not = is_not; | 486 | new_entry->is_not = is_not; |
481 | new_entry->is_last_name = is_last_name; | 487 | new_entry->is_last_name = is_last_name; |
482 | list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list); | 488 | list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); |
483 | error = 0; | 489 | error = 0; |
484 | out: | 490 | out: |
485 | up_write(&tomoyo_domain_keeper_list_lock); | 491 | up_write(&tomoyo_domain_keeper_list_lock); |
@@ -493,6 +499,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
493 | * @is_not: True if it is "no_keep_domain" entry. | 499 | * @is_not: True if it is "no_keep_domain" entry. |
494 | * @is_delete: True if it is a delete request. | 500 | * @is_delete: True if it is a delete request. |
495 | * | 501 | * |
502 | * Caller holds tomoyo_read_lock(). | ||
496 | */ | 503 | */ |
497 | int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, | 504 | int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, |
498 | const bool is_delete) | 505 | const bool is_delete) |
@@ -513,13 +520,14 @@ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, | |||
513 | * @head: Pointer to "struct tomoyo_io_buffer". | 520 | * @head: Pointer to "struct tomoyo_io_buffer". |
514 | * | 521 | * |
515 | * Returns true on success, false otherwise. | 522 | * Returns true on success, false otherwise. |
523 | * | ||
524 | * Caller holds tomoyo_read_lock(). | ||
516 | */ | 525 | */ |
517 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) | 526 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) |
518 | { | 527 | { |
519 | struct list_head *pos; | 528 | struct list_head *pos; |
520 | bool done = true; | 529 | bool done = true; |
521 | 530 | ||
522 | down_read(&tomoyo_domain_keeper_list_lock); | ||
523 | list_for_each_cookie(pos, head->read_var2, | 531 | list_for_each_cookie(pos, head->read_var2, |
524 | &tomoyo_domain_keeper_list) { | 532 | &tomoyo_domain_keeper_list) { |
525 | struct tomoyo_domain_keeper_entry *ptr; | 533 | struct tomoyo_domain_keeper_entry *ptr; |
@@ -542,7 +550,6 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) | |||
542 | if (!done) | 550 | if (!done) |
543 | break; | 551 | break; |
544 | } | 552 | } |
545 | up_read(&tomoyo_domain_keeper_list_lock); | ||
546 | return done; | 553 | return done; |
547 | } | 554 | } |
548 | 555 | ||
@@ -555,6 +562,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) | |||
555 | * | 562 | * |
556 | * Returns true if executing @program supresses domain transition, | 563 | * Returns true if executing @program supresses domain transition, |
557 | * false otherwise. | 564 | * false otherwise. |
565 | * | ||
566 | * Caller holds tomoyo_read_lock(). | ||
558 | */ | 567 | */ |
559 | static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | 568 | static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, |
560 | const struct tomoyo_path_info *program, | 569 | const struct tomoyo_path_info *program, |
@@ -563,8 +572,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | |||
563 | struct tomoyo_domain_keeper_entry *ptr; | 572 | struct tomoyo_domain_keeper_entry *ptr; |
564 | bool flag = false; | 573 | bool flag = false; |
565 | 574 | ||
566 | down_read(&tomoyo_domain_keeper_list_lock); | 575 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { |
567 | list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { | ||
568 | if (ptr->is_deleted) | 576 | if (ptr->is_deleted) |
569 | continue; | 577 | continue; |
570 | if (!ptr->is_last_name) { | 578 | if (!ptr->is_last_name) { |
@@ -582,7 +590,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | |||
582 | } | 590 | } |
583 | flag = true; | 591 | flag = true; |
584 | } | 592 | } |
585 | up_read(&tomoyo_domain_keeper_list_lock); | ||
586 | return flag; | 593 | return flag; |
587 | } | 594 | } |
588 | 595 | ||
@@ -627,6 +634,8 @@ static DECLARE_RWSEM(tomoyo_alias_list_lock); | |||
627 | * @is_delete: True if it is a delete request. | 634 | * @is_delete: True if it is a delete request. |
628 | * | 635 | * |
629 | * Returns 0 on success, negative value otherwise. | 636 | * Returns 0 on success, negative value otherwise. |
637 | * | ||
638 | * Caller holds tomoyo_read_lock(). | ||
630 | */ | 639 | */ |
631 | static int tomoyo_update_alias_entry(const char *original_name, | 640 | static int tomoyo_update_alias_entry(const char *original_name, |
632 | const char *aliased_name, | 641 | const char *aliased_name, |
@@ -646,7 +655,7 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
646 | if (!saved_original_name || !saved_aliased_name) | 655 | if (!saved_original_name || !saved_aliased_name) |
647 | return -ENOMEM; | 656 | return -ENOMEM; |
648 | down_write(&tomoyo_alias_list_lock); | 657 | down_write(&tomoyo_alias_list_lock); |
649 | list_for_each_entry(ptr, &tomoyo_alias_list, list) { | 658 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { |
650 | if (ptr->original_name != saved_original_name || | 659 | if (ptr->original_name != saved_original_name || |
651 | ptr->aliased_name != saved_aliased_name) | 660 | ptr->aliased_name != saved_aliased_name) |
652 | continue; | 661 | continue; |
@@ -663,7 +672,7 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
663 | goto out; | 672 | goto out; |
664 | new_entry->original_name = saved_original_name; | 673 | new_entry->original_name = saved_original_name; |
665 | new_entry->aliased_name = saved_aliased_name; | 674 | new_entry->aliased_name = saved_aliased_name; |
666 | list_add_tail(&new_entry->list, &tomoyo_alias_list); | 675 | list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); |
667 | error = 0; | 676 | error = 0; |
668 | out: | 677 | out: |
669 | up_write(&tomoyo_alias_list_lock); | 678 | up_write(&tomoyo_alias_list_lock); |
@@ -676,13 +685,14 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
676 | * @head: Pointer to "struct tomoyo_io_buffer". | 685 | * @head: Pointer to "struct tomoyo_io_buffer". |
677 | * | 686 | * |
678 | * Returns true on success, false otherwise. | 687 | * Returns true on success, false otherwise. |
688 | * | ||
689 | * Caller holds tomoyo_read_lock(). | ||
679 | */ | 690 | */ |
680 | bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) | 691 | bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) |
681 | { | 692 | { |
682 | struct list_head *pos; | 693 | struct list_head *pos; |
683 | bool done = true; | 694 | bool done = true; |
684 | 695 | ||
685 | down_read(&tomoyo_alias_list_lock); | ||
686 | list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { | 696 | list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { |
687 | struct tomoyo_alias_entry *ptr; | 697 | struct tomoyo_alias_entry *ptr; |
688 | 698 | ||
@@ -695,7 +705,6 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) | |||
695 | if (!done) | 705 | if (!done) |
696 | break; | 706 | break; |
697 | } | 707 | } |
698 | up_read(&tomoyo_alias_list_lock); | ||
699 | return done; | 708 | return done; |
700 | } | 709 | } |
701 | 710 | ||
@@ -706,6 +715,8 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) | |||
706 | * @is_delete: True if it is a delete request. | 715 | * @is_delete: True if it is a delete request. |
707 | * | 716 | * |
708 | * Returns 0 on success, negative value otherwise. | 717 | * Returns 0 on success, negative value otherwise. |
718 | * | ||
719 | * Caller holds tomoyo_read_lock(). | ||
709 | */ | 720 | */ |
710 | int tomoyo_write_alias_policy(char *data, const bool is_delete) | 721 | int tomoyo_write_alias_policy(char *data, const bool is_delete) |
711 | { | 722 | { |
@@ -724,6 +735,8 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete) | |||
724 | * @profile: Profile number to assign if the domain was newly created. | 735 | * @profile: Profile number to assign if the domain was newly created. |
725 | * | 736 | * |
726 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. | 737 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. |
738 | * | ||
739 | * Caller holds tomoyo_read_lock(). | ||
727 | */ | 740 | */ |
728 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | 741 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * |
729 | domainname, | 742 | domainname, |
@@ -742,7 +755,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
742 | if (!saved_domainname) | 755 | if (!saved_domainname) |
743 | goto out; | 756 | goto out; |
744 | /* Can I reuse memory of deleted domain? */ | 757 | /* Can I reuse memory of deleted domain? */ |
745 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | 758 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
746 | struct task_struct *p; | 759 | struct task_struct *p; |
747 | struct tomoyo_acl_info *ptr; | 760 | struct tomoyo_acl_info *ptr; |
748 | bool flag; | 761 | bool flag; |
@@ -760,7 +773,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
760 | read_unlock(&tasklist_lock); | 773 | read_unlock(&tasklist_lock); |
761 | if (flag) | 774 | if (flag) |
762 | continue; | 775 | continue; |
763 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 776 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
764 | ptr->type |= TOMOYO_ACL_DELETED; | 777 | ptr->type |= TOMOYO_ACL_DELETED; |
765 | } | 778 | } |
766 | tomoyo_set_domain_flag(domain, true, domain->flags); | 779 | tomoyo_set_domain_flag(domain, true, domain->flags); |
@@ -776,7 +789,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
776 | INIT_LIST_HEAD(&domain->acl_info_list); | 789 | INIT_LIST_HEAD(&domain->acl_info_list); |
777 | domain->domainname = saved_domainname; | 790 | domain->domainname = saved_domainname; |
778 | domain->profile = profile; | 791 | domain->profile = profile; |
779 | list_add_tail(&domain->list, &tomoyo_domain_list); | 792 | list_add_tail_rcu(&domain->list, &tomoyo_domain_list); |
780 | } | 793 | } |
781 | out: | 794 | out: |
782 | up_write(&tomoyo_domain_list_lock); | 795 | up_write(&tomoyo_domain_list_lock); |
@@ -789,6 +802,8 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
789 | * @bprm: Pointer to "struct linux_binprm". | 802 | * @bprm: Pointer to "struct linux_binprm". |
790 | * | 803 | * |
791 | * Returns 0 on success, negative value otherwise. | 804 | * Returns 0 on success, negative value otherwise. |
805 | * | ||
806 | * Caller holds tomoyo_read_lock(). | ||
792 | */ | 807 | */ |
793 | int tomoyo_find_next_domain(struct linux_binprm *bprm) | 808 | int tomoyo_find_next_domain(struct linux_binprm *bprm) |
794 | { | 809 | { |
@@ -849,8 +864,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
849 | if (tomoyo_pathcmp(&r, &s)) { | 864 | if (tomoyo_pathcmp(&r, &s)) { |
850 | struct tomoyo_alias_entry *ptr; | 865 | struct tomoyo_alias_entry *ptr; |
851 | /* Is this program allowed to be called via symbolic links? */ | 866 | /* Is this program allowed to be called via symbolic links? */ |
852 | down_read(&tomoyo_alias_list_lock); | 867 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { |
853 | list_for_each_entry(ptr, &tomoyo_alias_list, list) { | ||
854 | if (ptr->is_deleted || | 868 | if (ptr->is_deleted || |
855 | tomoyo_pathcmp(&r, ptr->original_name) || | 869 | tomoyo_pathcmp(&r, ptr->original_name) || |
856 | tomoyo_pathcmp(&s, ptr->aliased_name)) | 870 | tomoyo_pathcmp(&s, ptr->aliased_name)) |
@@ -861,7 +875,6 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
861 | tomoyo_fill_path_info(&r); | 875 | tomoyo_fill_path_info(&r); |
862 | break; | 876 | break; |
863 | } | 877 | } |
864 | up_read(&tomoyo_alias_list_lock); | ||
865 | } | 878 | } |
866 | 879 | ||
867 | /* Check execute permission. */ | 880 | /* Check execute permission. */ |
@@ -892,9 +905,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
892 | } | 905 | } |
893 | if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) | 906 | if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) |
894 | goto done; | 907 | goto done; |
895 | down_read(&tomoyo_domain_list_lock); | ||
896 | domain = tomoyo_find_domain(new_domain_name); | 908 | domain = tomoyo_find_domain(new_domain_name); |
897 | up_read(&tomoyo_domain_list_lock); | ||
898 | if (domain) | 909 | if (domain) |
899 | goto done; | 910 | goto done; |
900 | if (is_enforce) | 911 | if (is_enforce) |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 482f0e7ed997..3c472867634f 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -213,6 +213,8 @@ static DECLARE_RWSEM(tomoyo_globally_readable_list_lock); | |||
213 | * @is_delete: True if it is a delete request. | 213 | * @is_delete: True if it is a delete request. |
214 | * | 214 | * |
215 | * Returns 0 on success, negative value otherwise. | 215 | * Returns 0 on success, negative value otherwise. |
216 | * | ||
217 | * Caller holds tomoyo_read_lock(). | ||
216 | */ | 218 | */ |
217 | static int tomoyo_update_globally_readable_entry(const char *filename, | 219 | static int tomoyo_update_globally_readable_entry(const char *filename, |
218 | const bool is_delete) | 220 | const bool is_delete) |
@@ -228,7 +230,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
228 | if (!saved_filename) | 230 | if (!saved_filename) |
229 | return -ENOMEM; | 231 | return -ENOMEM; |
230 | down_write(&tomoyo_globally_readable_list_lock); | 232 | down_write(&tomoyo_globally_readable_list_lock); |
231 | list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { | 233 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { |
232 | if (ptr->filename != saved_filename) | 234 | if (ptr->filename != saved_filename) |
233 | continue; | 235 | continue; |
234 | ptr->is_deleted = is_delete; | 236 | ptr->is_deleted = is_delete; |
@@ -243,7 +245,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
243 | if (!new_entry) | 245 | if (!new_entry) |
244 | goto out; | 246 | goto out; |
245 | new_entry->filename = saved_filename; | 247 | new_entry->filename = saved_filename; |
246 | list_add_tail(&new_entry->list, &tomoyo_globally_readable_list); | 248 | list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list); |
247 | error = 0; | 249 | error = 0; |
248 | out: | 250 | out: |
249 | up_write(&tomoyo_globally_readable_list_lock); | 251 | up_write(&tomoyo_globally_readable_list_lock); |
@@ -256,21 +258,22 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
256 | * @filename: The filename to check. | 258 | * @filename: The filename to check. |
257 | * | 259 | * |
258 | * Returns true if any domain can open @filename for reading, false otherwise. | 260 | * Returns true if any domain can open @filename for reading, false otherwise. |
261 | * | ||
262 | * Caller holds tomoyo_read_lock(). | ||
259 | */ | 263 | */ |
260 | static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * | 264 | static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * |
261 | filename) | 265 | filename) |
262 | { | 266 | { |
263 | struct tomoyo_globally_readable_file_entry *ptr; | 267 | struct tomoyo_globally_readable_file_entry *ptr; |
264 | bool found = false; | 268 | bool found = false; |
265 | down_read(&tomoyo_globally_readable_list_lock); | 269 | |
266 | list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { | 270 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { |
267 | if (!ptr->is_deleted && | 271 | if (!ptr->is_deleted && |
268 | tomoyo_path_matches_pattern(filename, ptr->filename)) { | 272 | tomoyo_path_matches_pattern(filename, ptr->filename)) { |
269 | found = true; | 273 | found = true; |
270 | break; | 274 | break; |
271 | } | 275 | } |
272 | } | 276 | } |
273 | up_read(&tomoyo_globally_readable_list_lock); | ||
274 | return found; | 277 | return found; |
275 | } | 278 | } |
276 | 279 | ||
@@ -281,6 +284,8 @@ static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * | |||
281 | * @is_delete: True if it is a delete request. | 284 | * @is_delete: True if it is a delete request. |
282 | * | 285 | * |
283 | * Returns 0 on success, negative value otherwise. | 286 | * Returns 0 on success, negative value otherwise. |
287 | * | ||
288 | * Caller holds tomoyo_read_lock(). | ||
284 | */ | 289 | */ |
285 | int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) | 290 | int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) |
286 | { | 291 | { |
@@ -293,13 +298,14 @@ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) | |||
293 | * @head: Pointer to "struct tomoyo_io_buffer". | 298 | * @head: Pointer to "struct tomoyo_io_buffer". |
294 | * | 299 | * |
295 | * Returns true on success, false otherwise. | 300 | * Returns true on success, false otherwise. |
301 | * | ||
302 | * Caller holds tomoyo_read_lock(). | ||
296 | */ | 303 | */ |
297 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) | 304 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) |
298 | { | 305 | { |
299 | struct list_head *pos; | 306 | struct list_head *pos; |
300 | bool done = true; | 307 | bool done = true; |
301 | 308 | ||
302 | down_read(&tomoyo_globally_readable_list_lock); | ||
303 | list_for_each_cookie(pos, head->read_var2, | 309 | list_for_each_cookie(pos, head->read_var2, |
304 | &tomoyo_globally_readable_list) { | 310 | &tomoyo_globally_readable_list) { |
305 | struct tomoyo_globally_readable_file_entry *ptr; | 311 | struct tomoyo_globally_readable_file_entry *ptr; |
@@ -313,7 +319,6 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) | |||
313 | if (!done) | 319 | if (!done) |
314 | break; | 320 | break; |
315 | } | 321 | } |
316 | up_read(&tomoyo_globally_readable_list_lock); | ||
317 | return done; | 322 | return done; |
318 | } | 323 | } |
319 | 324 | ||
@@ -356,6 +361,8 @@ static DECLARE_RWSEM(tomoyo_pattern_list_lock); | |||
356 | * @is_delete: True if it is a delete request. | 361 | * @is_delete: True if it is a delete request. |
357 | * | 362 | * |
358 | * Returns 0 on success, negative value otherwise. | 363 | * Returns 0 on success, negative value otherwise. |
364 | * | ||
365 | * Caller holds tomoyo_read_lock(). | ||
359 | */ | 366 | */ |
360 | static int tomoyo_update_file_pattern_entry(const char *pattern, | 367 | static int tomoyo_update_file_pattern_entry(const char *pattern, |
361 | const bool is_delete) | 368 | const bool is_delete) |
@@ -371,7 +378,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
371 | if (!saved_pattern) | 378 | if (!saved_pattern) |
372 | return -ENOMEM; | 379 | return -ENOMEM; |
373 | down_write(&tomoyo_pattern_list_lock); | 380 | down_write(&tomoyo_pattern_list_lock); |
374 | list_for_each_entry(ptr, &tomoyo_pattern_list, list) { | 381 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { |
375 | if (saved_pattern != ptr->pattern) | 382 | if (saved_pattern != ptr->pattern) |
376 | continue; | 383 | continue; |
377 | ptr->is_deleted = is_delete; | 384 | ptr->is_deleted = is_delete; |
@@ -386,7 +393,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
386 | if (!new_entry) | 393 | if (!new_entry) |
387 | goto out; | 394 | goto out; |
388 | new_entry->pattern = saved_pattern; | 395 | new_entry->pattern = saved_pattern; |
389 | list_add_tail(&new_entry->list, &tomoyo_pattern_list); | 396 | list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list); |
390 | error = 0; | 397 | error = 0; |
391 | out: | 398 | out: |
392 | up_write(&tomoyo_pattern_list_lock); | 399 | up_write(&tomoyo_pattern_list_lock); |
@@ -399,6 +406,8 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
399 | * @filename: The filename to find patterned pathname. | 406 | * @filename: The filename to find patterned pathname. |
400 | * | 407 | * |
401 | * Returns pointer to pathname pattern if matched, @filename otherwise. | 408 | * Returns pointer to pathname pattern if matched, @filename otherwise. |
409 | * | ||
410 | * Caller holds tomoyo_read_lock(). | ||
402 | */ | 411 | */ |
403 | static const struct tomoyo_path_info * | 412 | static const struct tomoyo_path_info * |
404 | tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | 413 | tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) |
@@ -406,8 +415,7 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | |||
406 | struct tomoyo_pattern_entry *ptr; | 415 | struct tomoyo_pattern_entry *ptr; |
407 | const struct tomoyo_path_info *pattern = NULL; | 416 | const struct tomoyo_path_info *pattern = NULL; |
408 | 417 | ||
409 | down_read(&tomoyo_pattern_list_lock); | 418 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { |
410 | list_for_each_entry(ptr, &tomoyo_pattern_list, list) { | ||
411 | if (ptr->is_deleted) | 419 | if (ptr->is_deleted) |
412 | continue; | 420 | continue; |
413 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | 421 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) |
@@ -420,7 +428,6 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | |||
420 | break; | 428 | break; |
421 | } | 429 | } |
422 | } | 430 | } |
423 | up_read(&tomoyo_pattern_list_lock); | ||
424 | if (pattern) | 431 | if (pattern) |
425 | filename = pattern; | 432 | filename = pattern; |
426 | return filename; | 433 | return filename; |
@@ -433,6 +440,8 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | |||
433 | * @is_delete: True if it is a delete request. | 440 | * @is_delete: True if it is a delete request. |
434 | * | 441 | * |
435 | * Returns 0 on success, negative value otherwise. | 442 | * Returns 0 on success, negative value otherwise. |
443 | * | ||
444 | * Caller holds tomoyo_read_lock(). | ||
436 | */ | 445 | */ |
437 | int tomoyo_write_pattern_policy(char *data, const bool is_delete) | 446 | int tomoyo_write_pattern_policy(char *data, const bool is_delete) |
438 | { | 447 | { |
@@ -445,13 +454,14 @@ int tomoyo_write_pattern_policy(char *data, const bool is_delete) | |||
445 | * @head: Pointer to "struct tomoyo_io_buffer". | 454 | * @head: Pointer to "struct tomoyo_io_buffer". |
446 | * | 455 | * |
447 | * Returns true on success, false otherwise. | 456 | * Returns true on success, false otherwise. |
457 | * | ||
458 | * Caller holds tomoyo_read_lock(). | ||
448 | */ | 459 | */ |
449 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) | 460 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) |
450 | { | 461 | { |
451 | struct list_head *pos; | 462 | struct list_head *pos; |
452 | bool done = true; | 463 | bool done = true; |
453 | 464 | ||
454 | down_read(&tomoyo_pattern_list_lock); | ||
455 | list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) { | 465 | list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) { |
456 | struct tomoyo_pattern_entry *ptr; | 466 | struct tomoyo_pattern_entry *ptr; |
457 | ptr = list_entry(pos, struct tomoyo_pattern_entry, list); | 467 | ptr = list_entry(pos, struct tomoyo_pattern_entry, list); |
@@ -462,7 +472,6 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) | |||
462 | if (!done) | 472 | if (!done) |
463 | break; | 473 | break; |
464 | } | 474 | } |
465 | up_read(&tomoyo_pattern_list_lock); | ||
466 | return done; | 475 | return done; |
467 | } | 476 | } |
468 | 477 | ||
@@ -505,6 +514,8 @@ static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock); | |||
505 | * @is_delete: True if it is a delete request. | 514 | * @is_delete: True if it is a delete request. |
506 | * | 515 | * |
507 | * Returns 0 on success, negative value otherwise. | 516 | * Returns 0 on success, negative value otherwise. |
517 | * | ||
518 | * Caller holds tomoyo_read_lock(). | ||
508 | */ | 519 | */ |
509 | static int tomoyo_update_no_rewrite_entry(const char *pattern, | 520 | static int tomoyo_update_no_rewrite_entry(const char *pattern, |
510 | const bool is_delete) | 521 | const bool is_delete) |
@@ -519,7 +530,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
519 | if (!saved_pattern) | 530 | if (!saved_pattern) |
520 | return -ENOMEM; | 531 | return -ENOMEM; |
521 | down_write(&tomoyo_no_rewrite_list_lock); | 532 | down_write(&tomoyo_no_rewrite_list_lock); |
522 | list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { | 533 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { |
523 | if (ptr->pattern != saved_pattern) | 534 | if (ptr->pattern != saved_pattern) |
524 | continue; | 535 | continue; |
525 | ptr->is_deleted = is_delete; | 536 | ptr->is_deleted = is_delete; |
@@ -534,7 +545,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
534 | if (!new_entry) | 545 | if (!new_entry) |
535 | goto out; | 546 | goto out; |
536 | new_entry->pattern = saved_pattern; | 547 | new_entry->pattern = saved_pattern; |
537 | list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list); | 548 | list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list); |
538 | error = 0; | 549 | error = 0; |
539 | out: | 550 | out: |
540 | up_write(&tomoyo_no_rewrite_list_lock); | 551 | up_write(&tomoyo_no_rewrite_list_lock); |
@@ -548,14 +559,15 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
548 | * | 559 | * |
549 | * Returns true if @filename is specified by "deny_rewrite" directive, | 560 | * Returns true if @filename is specified by "deny_rewrite" directive, |
550 | * false otherwise. | 561 | * false otherwise. |
562 | * | ||
563 | * Caller holds tomoyo_read_lock(). | ||
551 | */ | 564 | */ |
552 | static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) | 565 | static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) |
553 | { | 566 | { |
554 | struct tomoyo_no_rewrite_entry *ptr; | 567 | struct tomoyo_no_rewrite_entry *ptr; |
555 | bool found = false; | 568 | bool found = false; |
556 | 569 | ||
557 | down_read(&tomoyo_no_rewrite_list_lock); | 570 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { |
558 | list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { | ||
559 | if (ptr->is_deleted) | 571 | if (ptr->is_deleted) |
560 | continue; | 572 | continue; |
561 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | 573 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) |
@@ -563,7 +575,6 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) | |||
563 | found = true; | 575 | found = true; |
564 | break; | 576 | break; |
565 | } | 577 | } |
566 | up_read(&tomoyo_no_rewrite_list_lock); | ||
567 | return found; | 578 | return found; |
568 | } | 579 | } |
569 | 580 | ||
@@ -574,6 +585,8 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) | |||
574 | * @is_delete: True if it is a delete request. | 585 | * @is_delete: True if it is a delete request. |
575 | * | 586 | * |
576 | * Returns 0 on success, negative value otherwise. | 587 | * Returns 0 on success, negative value otherwise. |
588 | * | ||
589 | * Caller holds tomoyo_read_lock(). | ||
577 | */ | 590 | */ |
578 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) | 591 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) |
579 | { | 592 | { |
@@ -586,13 +599,14 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) | |||
586 | * @head: Pointer to "struct tomoyo_io_buffer". | 599 | * @head: Pointer to "struct tomoyo_io_buffer". |
587 | * | 600 | * |
588 | * Returns true on success, false otherwise. | 601 | * Returns true on success, false otherwise. |
602 | * | ||
603 | * Caller holds tomoyo_read_lock(). | ||
589 | */ | 604 | */ |
590 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | 605 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) |
591 | { | 606 | { |
592 | struct list_head *pos; | 607 | struct list_head *pos; |
593 | bool done = true; | 608 | bool done = true; |
594 | 609 | ||
595 | down_read(&tomoyo_no_rewrite_list_lock); | ||
596 | list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { | 610 | list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { |
597 | struct tomoyo_no_rewrite_entry *ptr; | 611 | struct tomoyo_no_rewrite_entry *ptr; |
598 | ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); | 612 | ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); |
@@ -603,7 +617,6 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | |||
603 | if (!done) | 617 | if (!done) |
604 | break; | 618 | break; |
605 | } | 619 | } |
606 | up_read(&tomoyo_no_rewrite_list_lock); | ||
607 | return done; | 620 | return done; |
608 | } | 621 | } |
609 | 622 | ||
@@ -621,6 +634,8 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | |||
621 | * Current policy syntax uses "allow_read/write" instead of "6", | 634 | * Current policy syntax uses "allow_read/write" instead of "6", |
622 | * "allow_read" instead of "4", "allow_write" instead of "2", | 635 | * "allow_read" instead of "4", "allow_write" instead of "2", |
623 | * "allow_execute" instead of "1". | 636 | * "allow_execute" instead of "1". |
637 | * | ||
638 | * Caller holds tomoyo_read_lock(). | ||
624 | */ | 639 | */ |
625 | static int tomoyo_update_file_acl(const char *filename, u8 perm, | 640 | static int tomoyo_update_file_acl(const char *filename, u8 perm, |
626 | struct tomoyo_domain_info * const domain, | 641 | struct tomoyo_domain_info * const domain, |
@@ -658,6 +673,8 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, | |||
658 | * @may_use_pattern: True if patterned ACL is permitted. | 673 | * @may_use_pattern: True if patterned ACL is permitted. |
659 | * | 674 | * |
660 | * Returns 0 on success, -EPERM otherwise. | 675 | * Returns 0 on success, -EPERM otherwise. |
676 | * | ||
677 | * Caller holds tomoyo_read_lock(). | ||
661 | */ | 678 | */ |
662 | static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | 679 | static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * |
663 | domain, | 680 | domain, |
@@ -669,8 +686,7 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | |||
669 | struct tomoyo_acl_info *ptr; | 686 | struct tomoyo_acl_info *ptr; |
670 | int error = -EPERM; | 687 | int error = -EPERM; |
671 | 688 | ||
672 | down_read(&tomoyo_domain_acl_info_list_lock); | 689 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
673 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
674 | struct tomoyo_single_path_acl_record *acl; | 690 | struct tomoyo_single_path_acl_record *acl; |
675 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | 691 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) |
676 | continue; | 692 | continue; |
@@ -693,7 +709,6 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | |||
693 | error = 0; | 709 | error = 0; |
694 | break; | 710 | break; |
695 | } | 711 | } |
696 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
697 | return error; | 712 | return error; |
698 | } | 713 | } |
699 | 714 | ||
@@ -705,6 +720,8 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | |||
705 | * @operation: Mode ("read" or "write" or "read/write" or "execute"). | 720 | * @operation: Mode ("read" or "write" or "read/write" or "execute"). |
706 | * | 721 | * |
707 | * Returns 0 on success, -EPERM otherwise. | 722 | * Returns 0 on success, -EPERM otherwise. |
723 | * | ||
724 | * Caller holds tomoyo_read_lock(). | ||
708 | */ | 725 | */ |
709 | static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, | 726 | static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, |
710 | const struct tomoyo_path_info *filename, | 727 | const struct tomoyo_path_info *filename, |
@@ -738,6 +755,8 @@ static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, | |||
738 | * @mode: Access control mode. | 755 | * @mode: Access control mode. |
739 | * | 756 | * |
740 | * Returns 0 on success, negative value otherwise. | 757 | * Returns 0 on success, negative value otherwise. |
758 | * | ||
759 | * Caller holds tomoyo_read_lock(). | ||
741 | */ | 760 | */ |
742 | static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | 761 | static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, |
743 | const struct tomoyo_path_info *filename, | 762 | const struct tomoyo_path_info *filename, |
@@ -791,6 +810,8 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | |||
791 | * @is_delete: True if it is a delete request. | 810 | * @is_delete: True if it is a delete request. |
792 | * | 811 | * |
793 | * Returns 0 on success, negative value otherwise. | 812 | * Returns 0 on success, negative value otherwise. |
813 | * | ||
814 | * Caller holds tomoyo_read_lock(). | ||
794 | */ | 815 | */ |
795 | int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | 816 | int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, |
796 | const bool is_delete) | 817 | const bool is_delete) |
@@ -838,6 +859,8 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | |||
838 | * @is_delete: True if it is a delete request. | 859 | * @is_delete: True if it is a delete request. |
839 | * | 860 | * |
840 | * Returns 0 on success, negative value otherwise. | 861 | * Returns 0 on success, negative value otherwise. |
862 | * | ||
863 | * Caller holds tomoyo_read_lock(). | ||
841 | */ | 864 | */ |
842 | static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | 865 | static int tomoyo_update_single_path_acl(const u8 type, const char *filename, |
843 | struct tomoyo_domain_info * | 866 | struct tomoyo_domain_info * |
@@ -861,7 +884,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
861 | down_write(&tomoyo_domain_acl_info_list_lock); | 884 | down_write(&tomoyo_domain_acl_info_list_lock); |
862 | if (is_delete) | 885 | if (is_delete) |
863 | goto delete; | 886 | goto delete; |
864 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 887 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
865 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | 888 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) |
866 | continue; | 889 | continue; |
867 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | 890 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, |
@@ -894,12 +917,12 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
894 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | 917 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) |
895 | acl->perm |= rw_mask; | 918 | acl->perm |= rw_mask; |
896 | acl->filename = saved_filename; | 919 | acl->filename = saved_filename; |
897 | list_add_tail(&acl->head.list, &domain->acl_info_list); | 920 | list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); |
898 | error = 0; | 921 | error = 0; |
899 | goto out; | 922 | goto out; |
900 | delete: | 923 | delete: |
901 | error = -ENOENT; | 924 | error = -ENOENT; |
902 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 925 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
903 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | 926 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) |
904 | continue; | 927 | continue; |
905 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | 928 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, |
@@ -934,6 +957,8 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
934 | * @is_delete: True if it is a delete request. | 957 | * @is_delete: True if it is a delete request. |
935 | * | 958 | * |
936 | * Returns 0 on success, negative value otherwise. | 959 | * Returns 0 on success, negative value otherwise. |
960 | * | ||
961 | * Caller holds tomoyo_read_lock(). | ||
937 | */ | 962 | */ |
938 | static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | 963 | static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, |
939 | const char *filename2, | 964 | const char *filename2, |
@@ -959,7 +984,7 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
959 | down_write(&tomoyo_domain_acl_info_list_lock); | 984 | down_write(&tomoyo_domain_acl_info_list_lock); |
960 | if (is_delete) | 985 | if (is_delete) |
961 | goto delete; | 986 | goto delete; |
962 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 987 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
963 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | 988 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) |
964 | continue; | 989 | continue; |
965 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | 990 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, |
@@ -982,12 +1007,12 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
982 | acl->perm = perm; | 1007 | acl->perm = perm; |
983 | acl->filename1 = saved_filename1; | 1008 | acl->filename1 = saved_filename1; |
984 | acl->filename2 = saved_filename2; | 1009 | acl->filename2 = saved_filename2; |
985 | list_add_tail(&acl->head.list, &domain->acl_info_list); | 1010 | list_add_tail_rcu(&acl->head.list, &domain->acl_info_list); |
986 | error = 0; | 1011 | error = 0; |
987 | goto out; | 1012 | goto out; |
988 | delete: | 1013 | delete: |
989 | error = -ENOENT; | 1014 | error = -ENOENT; |
990 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 1015 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
991 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | 1016 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) |
992 | continue; | 1017 | continue; |
993 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | 1018 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, |
@@ -1014,6 +1039,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | |||
1014 | * @filename: Filename to check. | 1039 | * @filename: Filename to check. |
1015 | * | 1040 | * |
1016 | * Returns 0 on success, negative value otherwise. | 1041 | * Returns 0 on success, negative value otherwise. |
1042 | * | ||
1043 | * Caller holds tomoyo_read_lock(). | ||
1017 | */ | 1044 | */ |
1018 | static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, | 1045 | static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, |
1019 | const u8 type, | 1046 | const u8 type, |
@@ -1033,6 +1060,8 @@ static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, | |||
1033 | * @filename2: Second filename to check. | 1060 | * @filename2: Second filename to check. |
1034 | * | 1061 | * |
1035 | * Returns 0 on success, -EPERM otherwise. | 1062 | * Returns 0 on success, -EPERM otherwise. |
1063 | * | ||
1064 | * Caller holds tomoyo_read_lock(). | ||
1036 | */ | 1065 | */ |
1037 | static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | 1066 | static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, |
1038 | const u8 type, | 1067 | const u8 type, |
@@ -1047,8 +1076,7 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1047 | 1076 | ||
1048 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | 1077 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) |
1049 | return 0; | 1078 | return 0; |
1050 | down_read(&tomoyo_domain_acl_info_list_lock); | 1079 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
1051 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
1052 | struct tomoyo_double_path_acl_record *acl; | 1080 | struct tomoyo_double_path_acl_record *acl; |
1053 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | 1081 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) |
1054 | continue; | 1082 | continue; |
@@ -1063,7 +1091,6 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1063 | error = 0; | 1091 | error = 0; |
1064 | break; | 1092 | break; |
1065 | } | 1093 | } |
1066 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
1067 | return error; | 1094 | return error; |
1068 | } | 1095 | } |
1069 | 1096 | ||
@@ -1076,6 +1103,8 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1076 | * @mode: Access control mode. | 1103 | * @mode: Access control mode. |
1077 | * | 1104 | * |
1078 | * Returns 0 on success, negative value otherwise. | 1105 | * Returns 0 on success, negative value otherwise. |
1106 | * | ||
1107 | * Caller holds tomoyo_read_lock(). | ||
1079 | */ | 1108 | */ |
1080 | static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | 1109 | static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * |
1081 | const domain, u8 operation, | 1110 | const domain, u8 operation, |
@@ -1124,6 +1153,8 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | |||
1124 | * @filename: Check permission for "execute". | 1153 | * @filename: Check permission for "execute". |
1125 | * | 1154 | * |
1126 | * Returns 0 on success, negativevalue otherwise. | 1155 | * Returns 0 on success, negativevalue otherwise. |
1156 | * | ||
1157 | * Caller holds tomoyo_read_lock(). | ||
1127 | */ | 1158 | */ |
1128 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | 1159 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, |
1129 | const struct tomoyo_path_info *filename) | 1160 | const struct tomoyo_path_info *filename) |
@@ -1152,6 +1183,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1152 | struct tomoyo_path_info *buf; | 1183 | struct tomoyo_path_info *buf; |
1153 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1184 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1154 | const bool is_enforce = (mode == 3); | 1185 | const bool is_enforce = (mode == 3); |
1186 | int idx; | ||
1155 | 1187 | ||
1156 | if (!mode || !path->mnt) | 1188 | if (!mode || !path->mnt) |
1157 | return 0; | 1189 | return 0; |
@@ -1163,6 +1195,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1163 | * don't call me. | 1195 | * don't call me. |
1164 | */ | 1196 | */ |
1165 | return 0; | 1197 | return 0; |
1198 | idx = tomoyo_read_lock(); | ||
1166 | buf = tomoyo_get_path(path); | 1199 | buf = tomoyo_get_path(path); |
1167 | if (!buf) | 1200 | if (!buf) |
1168 | goto out; | 1201 | goto out; |
@@ -1188,6 +1221,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1188 | buf, mode); | 1221 | buf, mode); |
1189 | out: | 1222 | out: |
1190 | tomoyo_free(buf); | 1223 | tomoyo_free(buf); |
1224 | tomoyo_read_unlock(idx); | ||
1191 | if (!is_enforce) | 1225 | if (!is_enforce) |
1192 | error = 0; | 1226 | error = 0; |
1193 | return error; | 1227 | return error; |
@@ -1209,9 +1243,11 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, | |||
1209 | struct tomoyo_path_info *buf; | 1243 | struct tomoyo_path_info *buf; |
1210 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1244 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1211 | const bool is_enforce = (mode == 3); | 1245 | const bool is_enforce = (mode == 3); |
1246 | int idx; | ||
1212 | 1247 | ||
1213 | if (!mode || !path->mnt) | 1248 | if (!mode || !path->mnt) |
1214 | return 0; | 1249 | return 0; |
1250 | idx = tomoyo_read_lock(); | ||
1215 | buf = tomoyo_get_path(path); | 1251 | buf = tomoyo_get_path(path); |
1216 | if (!buf) | 1252 | if (!buf) |
1217 | goto out; | 1253 | goto out; |
@@ -1231,6 +1267,7 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, | |||
1231 | mode); | 1267 | mode); |
1232 | out: | 1268 | out: |
1233 | tomoyo_free(buf); | 1269 | tomoyo_free(buf); |
1270 | tomoyo_read_unlock(idx); | ||
1234 | if (!is_enforce) | 1271 | if (!is_enforce) |
1235 | error = 0; | 1272 | error = 0; |
1236 | return error; | 1273 | return error; |
@@ -1251,9 +1288,12 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, | |||
1251 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1288 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1252 | const bool is_enforce = (mode == 3); | 1289 | const bool is_enforce = (mode == 3); |
1253 | struct tomoyo_path_info *buf; | 1290 | struct tomoyo_path_info *buf; |
1291 | int idx; | ||
1254 | 1292 | ||
1255 | if (!mode || !filp->f_path.mnt) | 1293 | if (!mode || !filp->f_path.mnt) |
1256 | return 0; | 1294 | return 0; |
1295 | |||
1296 | idx = tomoyo_read_lock(); | ||
1257 | buf = tomoyo_get_path(&filp->f_path); | 1297 | buf = tomoyo_get_path(&filp->f_path); |
1258 | if (!buf) | 1298 | if (!buf) |
1259 | goto out; | 1299 | goto out; |
@@ -1266,6 +1306,7 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, | |||
1266 | buf, mode); | 1306 | buf, mode); |
1267 | out: | 1307 | out: |
1268 | tomoyo_free(buf); | 1308 | tomoyo_free(buf); |
1309 | tomoyo_read_unlock(idx); | ||
1269 | if (!is_enforce) | 1310 | if (!is_enforce) |
1270 | error = 0; | 1311 | error = 0; |
1271 | return error; | 1312 | return error; |
@@ -1290,9 +1331,11 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, | |||
1290 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1331 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1291 | const bool is_enforce = (mode == 3); | 1332 | const bool is_enforce = (mode == 3); |
1292 | const char *msg; | 1333 | const char *msg; |
1334 | int idx; | ||
1293 | 1335 | ||
1294 | if (!mode || !path1->mnt || !path2->mnt) | 1336 | if (!mode || !path1->mnt || !path2->mnt) |
1295 | return 0; | 1337 | return 0; |
1338 | idx = tomoyo_read_lock(); | ||
1296 | buf1 = tomoyo_get_path(path1); | 1339 | buf1 = tomoyo_get_path(path1); |
1297 | buf2 = tomoyo_get_path(path2); | 1340 | buf2 = tomoyo_get_path(path2); |
1298 | if (!buf1 || !buf2) | 1341 | if (!buf1 || !buf2) |
@@ -1331,6 +1374,7 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, | |||
1331 | out: | 1374 | out: |
1332 | tomoyo_free(buf1); | 1375 | tomoyo_free(buf1); |
1333 | tomoyo_free(buf2); | 1376 | tomoyo_free(buf2); |
1377 | tomoyo_read_unlock(idx); | ||
1334 | if (!is_enforce) | 1378 | if (!is_enforce) |
1335 | error = 0; | 1379 | error = 0; |
1336 | return error; | 1380 | return error; |
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index e3c7aa0fb706..62363b3bc716 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c | |||
@@ -402,11 +402,13 @@ void __init tomoyo_realpath_init(void) | |||
402 | INIT_LIST_HEAD(&tomoyo_name_list[i]); | 402 | INIT_LIST_HEAD(&tomoyo_name_list[i]); |
403 | INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); | 403 | INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); |
404 | tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME); | 404 | tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME); |
405 | list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list); | 405 | /* |
406 | down_read(&tomoyo_domain_list_lock); | 406 | * tomoyo_read_lock() is not needed because this function is |
407 | * called before the first "delete" request. | ||
408 | */ | ||
409 | list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); | ||
407 | if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) | 410 | if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) |
408 | panic("Can't register tomoyo_kernel_domain"); | 411 | panic("Can't register tomoyo_kernel_domain"); |
409 | up_read(&tomoyo_domain_list_lock); | ||
410 | } | 412 | } |
411 | 413 | ||
412 | /* Memory allocated for temporary purpose. */ | 414 | /* Memory allocated for temporary purpose. */ |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index ad9555fc3765..714daa34d493 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -76,8 +76,18 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | |||
76 | * Execute permission is checked against pathname passed to do_execve() | 76 | * Execute permission is checked against pathname passed to do_execve() |
77 | * using current domain. | 77 | * using current domain. |
78 | */ | 78 | */ |
79 | if (!domain) | 79 | if (!domain) { |
80 | return tomoyo_find_next_domain(bprm); | 80 | /* |
81 | * We will need to protect whole execve() operation when GC | ||
82 | * starts kfree()ing "struct tomoyo_domain_info" because | ||
83 | * bprm->cred->security points to "struct tomoyo_domain_info" | ||
84 | * but "struct tomoyo_domain_info" does not have a refcounter. | ||
85 | */ | ||
86 | const int idx = tomoyo_read_lock(); | ||
87 | const int err = tomoyo_find_next_domain(bprm); | ||
88 | tomoyo_read_unlock(idx); | ||
89 | return err; | ||
90 | } | ||
81 | /* | 91 | /* |
82 | * Read permission is checked against interpreters using next domain. | 92 | * Read permission is checked against interpreters using next domain. |
83 | * '1' is the result of open_to_namei_flags(O_RDONLY). | 93 | * '1' is the result of open_to_namei_flags(O_RDONLY). |
@@ -278,6 +288,9 @@ static struct security_operations tomoyo_security_ops = { | |||
278 | .sb_pivotroot = tomoyo_sb_pivotroot, | 288 | .sb_pivotroot = tomoyo_sb_pivotroot, |
279 | }; | 289 | }; |
280 | 290 | ||
291 | /* Lock for GC. */ | ||
292 | struct srcu_struct tomoyo_ss; | ||
293 | |||
281 | static int __init tomoyo_init(void) | 294 | static int __init tomoyo_init(void) |
282 | { | 295 | { |
283 | struct cred *cred = (struct cred *) current_cred(); | 296 | struct cred *cred = (struct cred *) current_cred(); |
@@ -285,7 +298,8 @@ static int __init tomoyo_init(void) | |||
285 | if (!security_module_enable(&tomoyo_security_ops)) | 298 | if (!security_module_enable(&tomoyo_security_ops)) |
286 | return 0; | 299 | return 0; |
287 | /* register ourselves with the security framework */ | 300 | /* register ourselves with the security framework */ |
288 | if (register_security(&tomoyo_security_ops)) | 301 | if (register_security(&tomoyo_security_ops) || |
302 | init_srcu_struct(&tomoyo_ss)) | ||
289 | panic("Failure registering TOMOYO Linux"); | 303 | panic("Failure registering TOMOYO Linux"); |
290 | printk(KERN_INFO "TOMOYO Linux initialized\n"); | 304 | printk(KERN_INFO "TOMOYO Linux initialized\n"); |
291 | cred->security = &tomoyo_kernel_domain; | 305 | cred->security = &tomoyo_kernel_domain; |