diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-06-26 10:17:10 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-06-28 19:31:20 -0400 |
commit | a238cf5b89ed5285be8de56335665d023972f7d5 (patch) | |
tree | cd2594f5c80345b5f880a3ccd445d15fb6b7d6cd /security/tomoyo/file.c | |
parent | 0df7e8b8f1c25c10820bdc679555f2fbfb897ca0 (diff) |
TOMOYO: Use struct for passing ACL line.
Use structure for passing ACL line, in preparation for supporting policy
namespace and conditional parameters.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo/file.c')
-rw-r--r-- | security/tomoyo/file.c | 237 |
1 files changed, 126 insertions, 111 deletions
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 4259e0a136d8..e60745f9f31e 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -428,29 +428,27 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, | |||
428 | /** | 428 | /** |
429 | * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. | 429 | * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. |
430 | * | 430 | * |
431 | * @type: Type of operation. | 431 | * @perm: Permission. |
432 | * @filename: Filename. | 432 | * @param: Pointer to "struct tomoyo_acl_param". |
433 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
434 | * @is_delete: True if it is a delete request. | ||
435 | * | 433 | * |
436 | * Returns 0 on success, negative value otherwise. | 434 | * Returns 0 on success, negative value otherwise. |
437 | * | 435 | * |
438 | * Caller holds tomoyo_read_lock(). | 436 | * Caller holds tomoyo_read_lock(). |
439 | */ | 437 | */ |
440 | static int tomoyo_update_path_acl(const u8 type, const char *filename, | 438 | static int tomoyo_update_path_acl(const u16 perm, |
441 | struct tomoyo_domain_info * const domain, | 439 | struct tomoyo_acl_param *param) |
442 | const bool is_delete) | ||
443 | { | 440 | { |
444 | struct tomoyo_path_acl e = { | 441 | struct tomoyo_path_acl e = { |
445 | .head.type = TOMOYO_TYPE_PATH_ACL, | 442 | .head.type = TOMOYO_TYPE_PATH_ACL, |
446 | .perm = 1 << type | 443 | .perm = perm |
447 | }; | 444 | }; |
448 | int error; | 445 | int error; |
449 | if (!tomoyo_parse_name_union(filename, &e.name)) | 446 | if (!tomoyo_parse_name_union(param, &e.name)) |
450 | return -EINVAL; | 447 | error = -EINVAL; |
451 | error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 448 | else |
452 | tomoyo_same_path_acl, | 449 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
453 | tomoyo_merge_path_acl); | 450 | tomoyo_same_path_acl, |
451 | tomoyo_merge_path_acl); | ||
454 | tomoyo_put_name_union(&e.name); | 452 | tomoyo_put_name_union(&e.name); |
455 | return error; | 453 | return error; |
456 | } | 454 | } |
@@ -503,37 +501,30 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, | |||
503 | /** | 501 | /** |
504 | * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. | 502 | * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. |
505 | * | 503 | * |
506 | * @type: Type of operation. | 504 | * @perm: Permission. |
507 | * @filename: Filename. | 505 | * @param: Pointer to "struct tomoyo_acl_param". |
508 | * @mode: Create mode. | ||
509 | * @major: Device major number. | ||
510 | * @minor: Device minor number. | ||
511 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
512 | * @is_delete: True if it is a delete request. | ||
513 | * | 506 | * |
514 | * Returns 0 on success, negative value otherwise. | 507 | * Returns 0 on success, negative value otherwise. |
515 | * | 508 | * |
516 | * Caller holds tomoyo_read_lock(). | 509 | * Caller holds tomoyo_read_lock(). |
517 | */ | 510 | */ |
518 | static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, | 511 | static int tomoyo_update_mkdev_acl(const u8 perm, |
519 | char *mode, char *major, char *minor, | 512 | struct tomoyo_acl_param *param) |
520 | struct tomoyo_domain_info * const domain, | ||
521 | const bool is_delete) | ||
522 | { | 513 | { |
523 | struct tomoyo_mkdev_acl e = { | 514 | struct tomoyo_mkdev_acl e = { |
524 | .head.type = TOMOYO_TYPE_MKDEV_ACL, | 515 | .head.type = TOMOYO_TYPE_MKDEV_ACL, |
525 | .perm = 1 << type | 516 | .perm = perm |
526 | }; | 517 | }; |
527 | int error = is_delete ? -ENOENT : -ENOMEM; | 518 | int error; |
528 | if (!tomoyo_parse_name_union(filename, &e.name) || | 519 | if (!tomoyo_parse_name_union(param, &e.name) || |
529 | !tomoyo_parse_number_union(mode, &e.mode) || | 520 | !tomoyo_parse_number_union(param, &e.mode) || |
530 | !tomoyo_parse_number_union(major, &e.major) || | 521 | !tomoyo_parse_number_union(param, &e.major) || |
531 | !tomoyo_parse_number_union(minor, &e.minor)) | 522 | !tomoyo_parse_number_union(param, &e.minor)) |
532 | goto out; | 523 | error = -EINVAL; |
533 | error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 524 | else |
534 | tomoyo_same_mkdev_acl, | 525 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
535 | tomoyo_merge_mkdev_acl); | 526 | tomoyo_same_mkdev_acl, |
536 | out: | 527 | tomoyo_merge_mkdev_acl); |
537 | tomoyo_put_name_union(&e.name); | 528 | tomoyo_put_name_union(&e.name); |
538 | tomoyo_put_number_union(&e.mode); | 529 | tomoyo_put_number_union(&e.mode); |
539 | tomoyo_put_number_union(&e.major); | 530 | tomoyo_put_number_union(&e.major); |
@@ -586,33 +577,28 @@ static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, | |||
586 | /** | 577 | /** |
587 | * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. | 578 | * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. |
588 | * | 579 | * |
589 | * @type: Type of operation. | 580 | * @perm: Permission. |
590 | * @filename1: First filename. | 581 | * @param: Pointer to "struct tomoyo_acl_param". |
591 | * @filename2: Second filename. | ||
592 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
593 | * @is_delete: True if it is a delete request. | ||
594 | * | 582 | * |
595 | * Returns 0 on success, negative value otherwise. | 583 | * Returns 0 on success, negative value otherwise. |
596 | * | 584 | * |
597 | * Caller holds tomoyo_read_lock(). | 585 | * Caller holds tomoyo_read_lock(). |
598 | */ | 586 | */ |
599 | static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | 587 | static int tomoyo_update_path2_acl(const u8 perm, |
600 | const char *filename2, | 588 | struct tomoyo_acl_param *param) |
601 | struct tomoyo_domain_info * const domain, | ||
602 | const bool is_delete) | ||
603 | { | 589 | { |
604 | struct tomoyo_path2_acl e = { | 590 | struct tomoyo_path2_acl e = { |
605 | .head.type = TOMOYO_TYPE_PATH2_ACL, | 591 | .head.type = TOMOYO_TYPE_PATH2_ACL, |
606 | .perm = 1 << type | 592 | .perm = perm |
607 | }; | 593 | }; |
608 | int error = is_delete ? -ENOENT : -ENOMEM; | 594 | int error; |
609 | if (!tomoyo_parse_name_union(filename1, &e.name1) || | 595 | if (!tomoyo_parse_name_union(param, &e.name1) || |
610 | !tomoyo_parse_name_union(filename2, &e.name2)) | 596 | !tomoyo_parse_name_union(param, &e.name2)) |
611 | goto out; | 597 | error = -EINVAL; |
612 | error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 598 | else |
613 | tomoyo_same_path2_acl, | 599 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
614 | tomoyo_merge_path2_acl); | 600 | tomoyo_same_path2_acl, |
615 | out: | 601 | tomoyo_merge_path2_acl); |
616 | tomoyo_put_name_union(&e.name1); | 602 | tomoyo_put_name_union(&e.name1); |
617 | tomoyo_put_name_union(&e.name2); | 603 | tomoyo_put_name_union(&e.name2); |
618 | return error; | 604 | return error; |
@@ -701,32 +687,26 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, | |||
701 | /** | 687 | /** |
702 | * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. | 688 | * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. |
703 | * | 689 | * |
704 | * @type: Type of operation. | 690 | * @perm: Permission. |
705 | * @filename: Filename. | 691 | * @param: Pointer to "struct tomoyo_acl_param". |
706 | * @number: Number. | ||
707 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
708 | * @is_delete: True if it is a delete request. | ||
709 | * | 692 | * |
710 | * Returns 0 on success, negative value otherwise. | 693 | * Returns 0 on success, negative value otherwise. |
711 | */ | 694 | */ |
712 | static int tomoyo_update_path_number_acl(const u8 type, const char *filename, | 695 | static int tomoyo_update_path_number_acl(const u8 perm, |
713 | char *number, | 696 | struct tomoyo_acl_param *param) |
714 | struct tomoyo_domain_info * const | ||
715 | domain, const bool is_delete) | ||
716 | { | 697 | { |
717 | struct tomoyo_path_number_acl e = { | 698 | struct tomoyo_path_number_acl e = { |
718 | .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, | 699 | .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, |
719 | .perm = 1 << type | 700 | .perm = perm |
720 | }; | 701 | }; |
721 | int error = is_delete ? -ENOENT : -ENOMEM; | 702 | int error; |
722 | if (!tomoyo_parse_name_union(filename, &e.name)) | 703 | if (!tomoyo_parse_name_union(param, &e.name) || |
723 | return -EINVAL; | 704 | !tomoyo_parse_number_union(param, &e.number)) |
724 | if (!tomoyo_parse_number_union(number, &e.number)) | 705 | error = -EINVAL; |
725 | goto out; | 706 | else |
726 | error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 707 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
727 | tomoyo_same_path_number_acl, | 708 | tomoyo_same_path_number_acl, |
728 | tomoyo_merge_path_number_acl); | 709 | tomoyo_merge_path_number_acl); |
729 | out: | ||
730 | tomoyo_put_name_union(&e.name); | 710 | tomoyo_put_name_union(&e.name); |
731 | tomoyo_put_number_union(&e.number); | 711 | tomoyo_put_number_union(&e.number); |
732 | return error; | 712 | return error; |
@@ -963,53 +943,88 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, | |||
963 | } | 943 | } |
964 | 944 | ||
965 | /** | 945 | /** |
946 | * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry. | ||
947 | * | ||
948 | * @a: Pointer to "struct tomoyo_acl_info". | ||
949 | * @b: Pointer to "struct tomoyo_acl_info". | ||
950 | * | ||
951 | * Returns true if @a == @b, false otherwise. | ||
952 | */ | ||
953 | static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, | ||
954 | const struct tomoyo_acl_info *b) | ||
955 | { | ||
956 | const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); | ||
957 | const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); | ||
958 | return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && | ||
959 | tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && | ||
960 | tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && | ||
961 | tomoyo_same_number_union(&p1->flags, &p2->flags); | ||
962 | } | ||
963 | |||
964 | /** | ||
965 | * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list. | ||
966 | * | ||
967 | * @param: Pointer to "struct tomoyo_acl_param". | ||
968 | * | ||
969 | * Returns 0 on success, negative value otherwise. | ||
970 | * | ||
971 | * Caller holds tomoyo_read_lock(). | ||
972 | */ | ||
973 | static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param) | ||
974 | { | ||
975 | struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; | ||
976 | int error; | ||
977 | if (!tomoyo_parse_name_union(param, &e.dev_name) || | ||
978 | !tomoyo_parse_name_union(param, &e.dir_name) || | ||
979 | !tomoyo_parse_name_union(param, &e.fs_type) || | ||
980 | !tomoyo_parse_number_union(param, &e.flags)) | ||
981 | error = -EINVAL; | ||
982 | else | ||
983 | error = tomoyo_update_domain(&e.head, sizeof(e), param, | ||
984 | tomoyo_same_mount_acl, NULL); | ||
985 | tomoyo_put_name_union(&e.dev_name); | ||
986 | tomoyo_put_name_union(&e.dir_name); | ||
987 | tomoyo_put_name_union(&e.fs_type); | ||
988 | tomoyo_put_number_union(&e.flags); | ||
989 | return error; | ||
990 | } | ||
991 | |||
992 | /** | ||
966 | * tomoyo_write_file - Update file related list. | 993 | * tomoyo_write_file - Update file related list. |
967 | * | 994 | * |
968 | * @data: String to parse. | 995 | * @param: Pointer to "struct tomoyo_acl_param". |
969 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
970 | * @is_delete: True if it is a delete request. | ||
971 | * | 996 | * |
972 | * Returns 0 on success, negative value otherwise. | 997 | * Returns 0 on success, negative value otherwise. |
973 | * | 998 | * |
974 | * Caller holds tomoyo_read_lock(). | 999 | * Caller holds tomoyo_read_lock(). |
975 | */ | 1000 | */ |
976 | int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, | 1001 | int tomoyo_write_file(struct tomoyo_acl_param *param) |
977 | const bool is_delete) | ||
978 | { | 1002 | { |
979 | char *w[5]; | 1003 | u16 perm = 0; |
980 | u8 type; | 1004 | u8 type; |
981 | if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) | 1005 | const char *operation = tomoyo_read_token(param); |
982 | return -EINVAL; | 1006 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) |
983 | if (strncmp(w[0], "allow_", 6)) | 1007 | if (tomoyo_permstr(operation, tomoyo_path_keyword[type])) |
984 | goto out; | 1008 | perm |= 1 << type; |
985 | w[0] += 6; | 1009 | if (perm) |
986 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { | 1010 | return tomoyo_update_path_acl(perm, param); |
987 | if (strcmp(w[0], tomoyo_path_keyword[type])) | 1011 | for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) |
988 | continue; | 1012 | if (tomoyo_permstr(operation, tomoyo_path2_keyword[type])) |
989 | return tomoyo_update_path_acl(type, w[1], domain, is_delete); | 1013 | perm |= 1 << type; |
990 | } | 1014 | if (perm) |
991 | if (!w[2][0]) | 1015 | return tomoyo_update_path2_acl(perm, param); |
992 | goto out; | 1016 | for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) |
993 | for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { | 1017 | if (tomoyo_permstr(operation, |
994 | if (strcmp(w[0], tomoyo_path2_keyword[type])) | 1018 | tomoyo_path_number_keyword[type])) |
995 | continue; | 1019 | perm |= 1 << type; |
996 | return tomoyo_update_path2_acl(type, w[1], w[2], domain, | 1020 | if (perm) |
997 | is_delete); | 1021 | return tomoyo_update_path_number_acl(perm, param); |
998 | } | 1022 | for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) |
999 | for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) { | 1023 | if (tomoyo_permstr(operation, tomoyo_mkdev_keyword[type])) |
1000 | if (strcmp(w[0], tomoyo_path_number_keyword[type])) | 1024 | perm |= 1 << type; |
1001 | continue; | 1025 | if (perm) |
1002 | return tomoyo_update_path_number_acl(type, w[1], w[2], domain, | 1026 | return tomoyo_update_mkdev_acl(perm, param); |
1003 | is_delete); | 1027 | if (tomoyo_permstr(operation, "mount")) |
1004 | } | 1028 | return tomoyo_update_mount_acl(param); |
1005 | if (!w[3][0] || !w[4][0]) | ||
1006 | goto out; | ||
1007 | for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) { | ||
1008 | if (strcmp(w[0], tomoyo_mkdev_keyword[type])) | ||
1009 | continue; | ||
1010 | return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3], | ||
1011 | w[4], domain, is_delete); | ||
1012 | } | ||
1013 | out: | ||
1014 | return -EINVAL; | 1029 | return -EINVAL; |
1015 | } | 1030 | } |