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 /security | |
| 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>
Diffstat (limited to 'security')
| -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; |
