aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2009-12-07 19:34:43 -0500
committerJames Morris <jmorris@namei.org>2009-12-14 23:46:31 -0500
commitfdb8ebb729bbb640e64028a4f579a02ebc405727 (patch)
tree9dfca7422cb858cd05208734affab31d980030fe
parent86fc80f16e8a2449d5827bf1a9838b7fd9f70097 (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.c90
-rw-r--r--security/tomoyo/common.h28
-rw-r--r--security/tomoyo/domain.c63
-rw-r--r--security/tomoyo/file.c110
-rw-r--r--security/tomoyo/realpath.c8
-rw-r--r--security/tomoyo/tomoyo.c20
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 */
373struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) 372struct 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 */
833bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) 834bool 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 */
1100static int tomoyo_update_manager_entry(const char *manager, 1101static 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 */
1151static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) 1154static 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 */
1170static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) 1175static 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 */
1200static bool tomoyo_is_policy_manager(void) 1205static 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 */
1256static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, 1259static 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 */
1311static int tomoyo_delete_domain(char *domainname) 1311static 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 */
1341static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) 1343static 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 */
1512static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) 1514static 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 */
1594static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) 1594static 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 */
1629static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) 1629static 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 */
1705static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) 1705static 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 */
1739static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) 1741static 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 */
1924static int tomoyo_open_control(const u8 type, struct file *file) 1926static 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 */
2030static int tomoyo_read_control(struct file *file, char __user *buffer, 2035static 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 */
2073static int tomoyo_write_control(struct file *file, const char __user *buffer, 2080static 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 */
2123static int tomoyo_close_control(struct file *file) 2132static 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
463extern struct srcu_struct tomoyo_ss;
464
465static inline int tomoyo_read_lock(void)
466{
467 return srcu_read_lock(&tomoyo_ss);
468}
469
470static 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 */
221static int tomoyo_update_domain_initializer_entry(const char *domainname, 223static 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 */
283bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 287bool 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 */
324int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 328int 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 */
349static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * 355static 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 */
434static int tomoyo_update_domain_keeper_entry(const char *domainname, 440static 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 */
497int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 504int 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 */
517bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 526bool 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 */
559static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, 568static 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 */
631static int tomoyo_update_alias_entry(const char *original_name, 640static 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 */
680bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) 691bool 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 */
710int tomoyo_write_alias_policy(char *data, const bool is_delete) 721int 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 */
728struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 741struct 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 */
793int tomoyo_find_next_domain(struct linux_binprm *bprm) 808int 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 */
217static int tomoyo_update_globally_readable_entry(const char *filename, 219static 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 */
260static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * 264static 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 */
285int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) 290int 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 */
297bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) 304bool 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 */
360static int tomoyo_update_file_pattern_entry(const char *pattern, 367static 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 */
403static const struct tomoyo_path_info * 412static const struct tomoyo_path_info *
404tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) 413tomoyo_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 */
437int tomoyo_write_pattern_policy(char *data, const bool is_delete) 446int 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 */
449bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) 460bool 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 */
509static int tomoyo_update_no_rewrite_entry(const char *pattern, 520static 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 */
552static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) 565static 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 */
578int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) 591int 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 */
590bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) 605bool 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 */
625static int tomoyo_update_file_acl(const char *filename, u8 perm, 640static 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 */
662static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * 679static 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 */
709static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, 726static 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 */
742static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, 761static 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 */
795int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 816int 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 */
842static int tomoyo_update_single_path_acl(const u8 type, const char *filename, 865static 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 */
938static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, 963static 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 */
1018static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, 1045static 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 */
1037static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, 1066static 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 */
1080static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * 1109static 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 */
1128int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 1159int 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. */
292struct srcu_struct tomoyo_ss;
293
281static int __init tomoyo_init(void) 294static 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;