diff options
Diffstat (limited to 'security/tomoyo/file.c')
-rw-r--r-- | security/tomoyo/file.c | 110 |
1 files changed, 77 insertions, 33 deletions
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; |