Commit 237ab459f12cb98eadd3fe7b85343e183a1076a4

Authored by Tetsuo Handa
Committed by James Morris
1 parent 927942aabb

TOMOYO: Use callback for updating entries.

Use common "struct list_head" + "bool" + "u8" structure and
use common code for elements using that structure.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>

Showing 7 changed files with 253 additions and 312 deletions Side-by-side Diff

security/tomoyo/common.c
... ... @@ -950,8 +950,6 @@
950 950 struct tomoyo_mount_acl *ptr)
951 951 {
952 952 const int pos = head->read_avail;
953   - if (ptr->is_deleted)
954   - return true;
955 953 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_MOUNT) ||
956 954 !tomoyo_print_name_union(head, &ptr->dev_name) ||
957 955 !tomoyo_print_name_union(head, &ptr->dir_name) ||
... ... @@ -977,6 +975,8 @@
977 975 {
978 976 const u8 acl_type = ptr->type;
979 977  
  978 + if (ptr->is_deleted)
  979 + return true;
980 980 if (acl_type == TOMOYO_TYPE_PATH_ACL) {
981 981 struct tomoyo_path_acl *acl
982 982 = container_of(ptr, struct tomoyo_path_acl, head);
security/tomoyo/common.h
... ... @@ -112,6 +112,8 @@
112 112 TOMOYO_MAX_PATH_OPERATION
113 113 };
114 114  
  115 +#define TOMOYO_RW_MASK ((1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE))
  116 +
115 117 enum tomoyo_path_number3_acl_index {
116 118 TOMOYO_TYPE_MKBLOCK,
117 119 TOMOYO_TYPE_MKCHAR,
118 120  
119 121  
... ... @@ -289,17 +291,19 @@
289 291 *
290 292 * (1) "list" which is linked to the ->acl_info_list of
291 293 * "struct tomoyo_domain_info"
292   - * (2) "type" which tells type of the entry (either
293   - * "struct tomoyo_path_acl" or "struct tomoyo_path2_acl").
  294 + * (2) "is_deleted" is a bool which is true if this domain is marked as
  295 + * "deleted", false otherwise.
  296 + * (3) "type" which tells type of the entry.
294 297 *
295 298 * Packing "struct tomoyo_acl_info" allows
296   - * "struct tomoyo_path_acl" to embed "u8" + "u16" and
297   - * "struct tomoyo_path2_acl" to embed "u8"
298   - * without enlarging their structure size.
  299 + * "struct tomoyo_path_acl" to embed "u16" and "struct tomoyo_path2_acl"
  300 + * "struct tomoyo_path_number_acl" "struct tomoyo_path_number3_acl" to embed
  301 + * "u8" without enlarging their structure size.
299 302 */
300 303 struct tomoyo_acl_info {
301 304 struct list_head list;
302   - u8 type;
  305 + bool is_deleted;
  306 + u8 type; /* = one of values in "enum tomoyo_acl_entry_type_index". */
303 307 } __packed;
304 308  
305 309 /*
306 310  
307 311  
... ... @@ -438,17 +442,15 @@
438 442 * It has following fields.
439 443 *
440 444 * (1) "head" which is a "struct tomoyo_acl_info".
441   - * (2) "is_deleted" is boolean.
442   - * (3) "dev_name" is the device name.
443   - * (4) "dir_name" is the mount point.
  445 + * (2) "dev_name" is the device name.
  446 + * (3) "dir_name" is the mount point.
  447 + * (4) "fs_type" is the filesystem type.
444 448 * (5) "flags" is the mount flags.
445 449 *
446   - * Directives held by this structure are "allow_rename", "allow_link" and
447   - * "allow_pivot_root".
  450 + * Directive held by this structure is "allow_mount".
448 451 */
449 452 struct tomoyo_mount_acl {
450 453 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */
451   - bool is_deleted;
452 454 struct tomoyo_name_union dev_name;
453 455 struct tomoyo_name_union dir_name;
454 456 struct tomoyo_name_union fs_type;
... ... @@ -914,6 +916,16 @@
914 916  
915 917 void tomoyo_memory_free(void *ptr);
916 918  
  919 +int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
  920 + bool is_delete, struct tomoyo_domain_info *domain,
  921 + bool (*check_duplicate) (const struct tomoyo_acl_info
  922 + *,
  923 + const struct tomoyo_acl_info
  924 + *),
  925 + bool (*merge_duplicate) (struct tomoyo_acl_info *,
  926 + struct tomoyo_acl_info *,
  927 + const bool));
  928 +
917 929 /********** External variable definitions. **********/
918 930  
919 931 /* Lock for GC. */
... ... @@ -1040,52 +1052,6 @@
1040 1052 return p1->values[0] == p2->values[0] && p1->values[1] == p2->values[1]
1041 1053 && p1->group == p2->group && p1->min_type == p2->min_type &&
1042 1054 p1->max_type == p2->max_type && p1->is_group == p2->is_group;
1043   -}
1044   -
1045   -static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1,
1046   - const struct tomoyo_path_acl *p2)
1047   -{
1048   - return tomoyo_is_same_acl_head(&p1->head, &p2->head) &&
1049   - tomoyo_is_same_name_union(&p1->name, &p2->name);
1050   -}
1051   -
1052   -static inline bool tomoyo_is_same_path_number3_acl
1053   -(const struct tomoyo_path_number3_acl *p1,
1054   - const struct tomoyo_path_number3_acl *p2)
1055   -{
1056   - return tomoyo_is_same_acl_head(&p1->head, &p2->head)
1057   - && tomoyo_is_same_name_union(&p1->name, &p2->name)
1058   - && tomoyo_is_same_number_union(&p1->mode, &p2->mode)
1059   - && tomoyo_is_same_number_union(&p1->major, &p2->major)
1060   - && tomoyo_is_same_number_union(&p1->minor, &p2->minor);
1061   -}
1062   -
1063   -
1064   -static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1,
1065   - const struct tomoyo_path2_acl *p2)
1066   -{
1067   - return tomoyo_is_same_acl_head(&p1->head, &p2->head) &&
1068   - tomoyo_is_same_name_union(&p1->name1, &p2->name1) &&
1069   - tomoyo_is_same_name_union(&p1->name2, &p2->name2);
1070   -}
1071   -
1072   -static inline bool tomoyo_is_same_path_number_acl
1073   -(const struct tomoyo_path_number_acl *p1,
1074   - const struct tomoyo_path_number_acl *p2)
1075   -{
1076   - return tomoyo_is_same_acl_head(&p1->head, &p2->head)
1077   - && tomoyo_is_same_name_union(&p1->name, &p2->name)
1078   - && tomoyo_is_same_number_union(&p1->number, &p2->number);
1079   -}
1080   -
1081   -static inline bool tomoyo_is_same_mount_acl(const struct tomoyo_mount_acl *p1,
1082   - const struct tomoyo_mount_acl *p2)
1083   -{
1084   - return tomoyo_is_same_acl_head(&p1->head, &p2->head) &&
1085   - tomoyo_is_same_name_union(&p1->dev_name, &p2->dev_name) &&
1086   - tomoyo_is_same_name_union(&p1->dir_name, &p2->dir_name) &&
1087   - tomoyo_is_same_name_union(&p1->fs_type, &p2->fs_type) &&
1088   - tomoyo_is_same_number_union(&p1->flags, &p2->flags);
1089 1055 }
1090 1056  
1091 1057 static inline bool tomoyo_is_same_domain_initializer_entry
security/tomoyo/domain.c
... ... @@ -15,6 +15,57 @@
15 15 /* The initial domain. */
16 16 struct tomoyo_domain_info tomoyo_kernel_domain;
17 17  
  18 +/**
  19 + * tomoyo_update_domain - Update an entry for domain policy.
  20 + *
  21 + * @new_entry: Pointer to "struct tomoyo_acl_info".
  22 + * @size: Size of @new_entry in bytes.
  23 + * @is_delete: True if it is a delete request.
  24 + * @domain: Pointer to "struct tomoyo_domain_info".
  25 + * @check_duplicate: Callback function to find duplicated entry.
  26 + * @merge_duplicate: Callback function to merge duplicated entry.
  27 + *
  28 + * Returns 0 on success, negative value otherwise.
  29 + *
  30 + * Caller holds tomoyo_read_lock().
  31 + */
  32 +int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
  33 + bool is_delete, struct tomoyo_domain_info *domain,
  34 + bool (*check_duplicate) (const struct tomoyo_acl_info
  35 + *,
  36 + const struct tomoyo_acl_info
  37 + *),
  38 + bool (*merge_duplicate) (struct tomoyo_acl_info *,
  39 + struct tomoyo_acl_info *,
  40 + const bool))
  41 +{
  42 + int error = is_delete ? -ENOENT : -ENOMEM;
  43 + struct tomoyo_acl_info *entry;
  44 +
  45 + if (mutex_lock_interruptible(&tomoyo_policy_lock))
  46 + return error;
  47 + list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
  48 + if (!check_duplicate(entry, new_entry))
  49 + continue;
  50 + if (merge_duplicate)
  51 + entry->is_deleted = merge_duplicate(entry, new_entry,
  52 + is_delete);
  53 + else
  54 + entry->is_deleted = is_delete;
  55 + error = 0;
  56 + break;
  57 + }
  58 + if (error && !is_delete) {
  59 + entry = tomoyo_commit_ok(new_entry, size);
  60 + if (entry) {
  61 + list_add_tail_rcu(&entry->list, &domain->acl_info_list);
  62 + error = 0;
  63 + }
  64 + }
  65 + mutex_unlock(&tomoyo_policy_lock);
  66 + return error;
  67 +}
  68 +
18 69 /*
19 70 * tomoyo_domain_list is used for holding list of domains.
20 71 * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding
security/tomoyo/file.c
... ... @@ -665,50 +665,6 @@
665 665 }
666 666  
667 667 /**
668   - * tomoyo_update_file_acl - Update file's read/write/execute ACL.
669   - *
670   - * @perm: Permission (between 1 to 7).
671   - * @filename: Filename.
672   - * @domain: Pointer to "struct tomoyo_domain_info".
673   - * @is_delete: True if it is a delete request.
674   - *
675   - * Returns 0 on success, negative value otherwise.
676   - *
677   - * This is legacy support interface for older policy syntax.
678   - * Current policy syntax uses "allow_read/write" instead of "6",
679   - * "allow_read" instead of "4", "allow_write" instead of "2",
680   - * "allow_execute" instead of "1".
681   - *
682   - * Caller holds tomoyo_read_lock().
683   - */
684   -static int tomoyo_update_file_acl(u8 perm, const char *filename,
685   - struct tomoyo_domain_info * const domain,
686   - const bool is_delete)
687   -{
688   - if (perm > 7 || !perm) {
689   - printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
690   - __func__, perm, filename);
691   - return -EINVAL;
692   - }
693   - if (filename[0] != '@' && tomoyo_strendswith(filename, "/"))
694   - /*
695   - * Only 'allow_mkdir' and 'allow_rmdir' are valid for
696   - * directory permissions.
697   - */
698   - return 0;
699   - if (perm & 4)
700   - tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain,
701   - is_delete);
702   - if (perm & 2)
703   - tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain,
704   - is_delete);
705   - if (perm & 1)
706   - tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain,
707   - is_delete);
708   - return 0;
709   -}
710   -
711   -/**
712 668 * tomoyo_path_acl - Check permission for single path operation.
713 669 *
714 670 * @r: Pointer to "struct tomoyo_request_info".
... ... @@ -797,6 +753,40 @@
797 753 return error;
798 754 }
799 755  
  756 +static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
  757 + const struct tomoyo_acl_info *b)
  758 +{
  759 + const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
  760 + const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
  761 + return tomoyo_is_same_acl_head(&p1->head, &p2->head) &&
  762 + tomoyo_is_same_name_union(&p1->name, &p2->name);
  763 +}
  764 +
  765 +static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
  766 + struct tomoyo_acl_info *b,
  767 + const bool is_delete)
  768 +{
  769 + u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
  770 + ->perm;
  771 + u16 perm = *a_perm;
  772 + const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
  773 + if (is_delete) {
  774 + perm &= ~b_perm;
  775 + if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK)
  776 + perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
  777 + else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE)))
  778 + perm &= ~TOMOYO_RW_MASK;
  779 + } else {
  780 + perm |= b_perm;
  781 + if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK)
  782 + perm |= (1 << TOMOYO_TYPE_READ_WRITE);
  783 + else if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
  784 + perm |= TOMOYO_RW_MASK;
  785 + }
  786 + *a_perm = perm;
  787 + return !perm;
  788 +}
  789 +
800 790 /**
801 791 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
802 792 *
803 793  
804 794  
805 795  
806 796  
807 797  
... ... @@ -810,63 +800,56 @@
810 800 * Caller holds tomoyo_read_lock().
811 801 */
812 802 static int tomoyo_update_path_acl(const u8 type, const char *filename,
813   - struct tomoyo_domain_info *const domain,
  803 + struct tomoyo_domain_info * const domain,
814 804 const bool is_delete)
815 805 {
816   - static const u16 tomoyo_rw_mask =
817   - (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
818   - const u16 perm = 1 << type;
819   - struct tomoyo_acl_info *ptr;
820 806 struct tomoyo_path_acl e = {
821 807 .head.type = TOMOYO_TYPE_PATH_ACL,
822   - .perm = perm
  808 + .perm = 1 << type
823 809 };
824   - int error = is_delete ? -ENOENT : -ENOMEM;
825   -
826   - if (type == TOMOYO_TYPE_READ_WRITE)
827   - e.perm |= tomoyo_rw_mask;
828   - if (!domain)
829   - return -EINVAL;
  810 + int error;
  811 + if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE))
  812 + e.perm |= TOMOYO_RW_MASK;
830 813 if (!tomoyo_parse_name_union(filename, &e.name))
831 814 return -EINVAL;
832   - if (mutex_lock_interruptible(&tomoyo_policy_lock))
833   - goto out;
834   - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
835   - struct tomoyo_path_acl *acl =
836   - container_of(ptr, struct tomoyo_path_acl, head);
837   - if (!tomoyo_is_same_path_acl(acl, &e))
838   - continue;
839   - if (is_delete) {
840   - acl->perm &= ~perm;
841   - if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask)
842   - acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
843   - else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
844   - acl->perm &= ~tomoyo_rw_mask;
845   - } else {
846   - acl->perm |= perm;
847   - if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask)
848   - acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
849   - else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
850   - acl->perm |= tomoyo_rw_mask;
851   - }
852   - error = 0;
853   - break;
854   - }
855   - if (!is_delete && error) {
856   - struct tomoyo_path_acl *entry =
857   - tomoyo_commit_ok(&e, sizeof(e));
858   - if (entry) {
859   - list_add_tail_rcu(&entry->head.list,
860   - &domain->acl_info_list);
861   - error = 0;
862   - }
863   - }
864   - mutex_unlock(&tomoyo_policy_lock);
865   - out:
  815 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
  816 + tomoyo_same_path_acl,
  817 + tomoyo_merge_path_acl);
866 818 tomoyo_put_name_union(&e.name);
867 819 return error;
868 820 }
869 821  
  822 +static bool tomoyo_same_path_number3_acl(const struct tomoyo_acl_info *a,
  823 + const struct tomoyo_acl_info *b)
  824 +{
  825 + const struct tomoyo_path_number3_acl *p1 = container_of(a, typeof(*p1),
  826 + head);
  827 + const struct tomoyo_path_number3_acl *p2 = container_of(b, typeof(*p2),
  828 + head);
  829 + return tomoyo_is_same_acl_head(&p1->head, &p2->head)
  830 + && tomoyo_is_same_name_union(&p1->name, &p2->name)
  831 + && tomoyo_is_same_number_union(&p1->mode, &p2->mode)
  832 + && tomoyo_is_same_number_union(&p1->major, &p2->major)
  833 + && tomoyo_is_same_number_union(&p1->minor, &p2->minor);
  834 +}
  835 +
  836 +static bool tomoyo_merge_path_number3_acl(struct tomoyo_acl_info *a,
  837 + struct tomoyo_acl_info *b,
  838 + const bool is_delete)
  839 +{
  840 + u8 *const a_perm = &container_of(a, struct tomoyo_path_number3_acl,
  841 + head)->perm;
  842 + u8 perm = *a_perm;
  843 + const u8 b_perm = container_of(b, struct tomoyo_path_number3_acl, head)
  844 + ->perm;
  845 + if (is_delete)
  846 + perm &= ~b_perm;
  847 + else
  848 + perm |= b_perm;
  849 + *a_perm = perm;
  850 + return !perm;
  851 +}
  852 +
870 853 /**
871 854 * tomoyo_update_path_number3_acl - Update "struct tomoyo_path_number3_acl" list.
872 855 *
873 856  
874 857  
875 858  
... ... @@ -879,20 +862,17 @@
879 862 * @is_delete: True if it is a delete request.
880 863 *
881 864 * Returns 0 on success, negative value otherwise.
  865 + *
  866 + * Caller holds tomoyo_read_lock().
882 867 */
883   -static inline int tomoyo_update_path_number3_acl(const u8 type,
884   - const char *filename,
885   - char *mode,
886   - char *major, char *minor,
887   - struct tomoyo_domain_info *
888   - const domain,
889   - const bool is_delete)
  868 +static int tomoyo_update_path_number3_acl(const u8 type, const char *filename,
  869 + char *mode, char *major, char *minor,
  870 + struct tomoyo_domain_info * const
  871 + domain, const bool is_delete)
890 872 {
891   - const u8 perm = 1 << type;
892   - struct tomoyo_acl_info *ptr;
893 873 struct tomoyo_path_number3_acl e = {
894 874 .head.type = TOMOYO_TYPE_PATH_NUMBER3_ACL,
895   - .perm = perm
  875 + .perm = 1 << type
896 876 };
897 877 int error = is_delete ? -ENOENT : -ENOMEM;
898 878 if (!tomoyo_parse_name_union(filename, &e.name) ||
... ... @@ -900,30 +880,9 @@
900 880 !tomoyo_parse_number_union(major, &e.major) ||
901 881 !tomoyo_parse_number_union(minor, &e.minor))
902 882 goto out;
903   - if (mutex_lock_interruptible(&tomoyo_policy_lock))
904   - goto out;
905   - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
906   - struct tomoyo_path_number3_acl *acl =
907   - container_of(ptr, struct tomoyo_path_number3_acl, head);
908   - if (!tomoyo_is_same_path_number3_acl(acl, &e))
909   - continue;
910   - if (is_delete)
911   - acl->perm &= ~perm;
912   - else
913   - acl->perm |= perm;
914   - error = 0;
915   - break;
916   - }
917   - if (!is_delete && error) {
918   - struct tomoyo_path_number3_acl *entry =
919   - tomoyo_commit_ok(&e, sizeof(e));
920   - if (entry) {
921   - list_add_tail_rcu(&entry->head.list,
922   - &domain->acl_info_list);
923   - error = 0;
924   - }
925   - }
926   - mutex_unlock(&tomoyo_policy_lock);
  883 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
  884 + tomoyo_same_path_number3_acl,
  885 + tomoyo_merge_path_number3_acl);
927 886 out:
928 887 tomoyo_put_name_union(&e.name);
929 888 tomoyo_put_number_union(&e.mode);
... ... @@ -932,6 +891,32 @@
932 891 return error;
933 892 }
934 893  
  894 +static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
  895 + const struct tomoyo_acl_info *b)
  896 +{
  897 + const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
  898 + const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
  899 + return tomoyo_is_same_acl_head(&p1->head, &p2->head)
  900 + && tomoyo_is_same_name_union(&p1->name1, &p2->name1)
  901 + && tomoyo_is_same_name_union(&p1->name2, &p2->name2);
  902 +}
  903 +
  904 +static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
  905 + struct tomoyo_acl_info *b,
  906 + const bool is_delete)
  907 +{
  908 + u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
  909 + ->perm;
  910 + u8 perm = *a_perm;
  911 + const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
  912 + if (is_delete)
  913 + perm &= ~b_perm;
  914 + else
  915 + perm |= b_perm;
  916 + *a_perm = perm;
  917 + return !perm;
  918 +}
  919 +
935 920 /**
936 921 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
937 922 *
938 923  
939 924  
940 925  
941 926  
942 927  
... ... @@ -947,46 +932,20 @@
947 932 */
948 933 static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
949 934 const char *filename2,
950   - struct tomoyo_domain_info *const domain,
  935 + struct tomoyo_domain_info * const domain,
951 936 const bool is_delete)
952 937 {
953   - const u8 perm = 1 << type;
954 938 struct tomoyo_path2_acl e = {
955 939 .head.type = TOMOYO_TYPE_PATH2_ACL,
956   - .perm = perm
  940 + .perm = 1 << type
957 941 };
958   - struct tomoyo_acl_info *ptr;
959 942 int error = is_delete ? -ENOENT : -ENOMEM;
960   -
961   - if (!domain)
962   - return -EINVAL;
963 943 if (!tomoyo_parse_name_union(filename1, &e.name1) ||
964 944 !tomoyo_parse_name_union(filename2, &e.name2))
965 945 goto out;
966   - if (mutex_lock_interruptible(&tomoyo_policy_lock))
967   - goto out;
968   - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
969   - struct tomoyo_path2_acl *acl =
970   - container_of(ptr, struct tomoyo_path2_acl, head);
971   - if (!tomoyo_is_same_path2_acl(acl, &e))
972   - continue;
973   - if (is_delete)
974   - acl->perm &= ~perm;
975   - else
976   - acl->perm |= perm;
977   - error = 0;
978   - break;
979   - }
980   - if (!is_delete && error) {
981   - struct tomoyo_path2_acl *entry =
982   - tomoyo_commit_ok(&e, sizeof(e));
983   - if (entry) {
984   - list_add_tail_rcu(&entry->head.list,
985   - &domain->acl_info_list);
986   - error = 0;
987   - }
988   - }
989   - mutex_unlock(&tomoyo_policy_lock);
  946 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
  947 + tomoyo_same_path2_acl,
  948 + tomoyo_merge_path2_acl);
990 949 out:
991 950 tomoyo_put_name_union(&e.name1);
992 951 tomoyo_put_name_union(&e.name2);
... ... @@ -1157,6 +1116,35 @@
1157 1116 return error;
1158 1117 }
1159 1118  
  1119 +static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
  1120 + const struct tomoyo_acl_info *b)
  1121 +{
  1122 + const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
  1123 + head);
  1124 + const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
  1125 + head);
  1126 + return tomoyo_is_same_acl_head(&p1->head, &p2->head)
  1127 + && tomoyo_is_same_name_union(&p1->name, &p2->name)
  1128 + && tomoyo_is_same_number_union(&p1->number, &p2->number);
  1129 +}
  1130 +
  1131 +static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
  1132 + struct tomoyo_acl_info *b,
  1133 + const bool is_delete)
  1134 +{
  1135 + u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
  1136 + head)->perm;
  1137 + u8 perm = *a_perm;
  1138 + const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
  1139 + ->perm;
  1140 + if (is_delete)
  1141 + perm &= ~b_perm;
  1142 + else
  1143 + perm |= b_perm;
  1144 + *a_perm = perm;
  1145 + return !perm;
  1146 +}
  1147 +
1160 1148 /**
1161 1149 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
1162 1150 *
1163 1151  
1164 1152  
1165 1153  
1166 1154  
... ... @@ -1168,50 +1156,24 @@
1168 1156 *
1169 1157 * Returns 0 on success, negative value otherwise.
1170 1158 */
1171   -static inline int tomoyo_update_path_number_acl(const u8 type,
1172   - const char *filename,
1173   - char *number,
1174   - struct tomoyo_domain_info *
1175   - const domain,
1176   - const bool is_delete)
  1159 +static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
  1160 + char *number,
  1161 + struct tomoyo_domain_info * const
  1162 + domain,
  1163 + const bool is_delete)
1177 1164 {
1178   - const u8 perm = 1 << type;
1179   - struct tomoyo_acl_info *ptr;
1180 1165 struct tomoyo_path_number_acl e = {
1181 1166 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
1182   - .perm = perm
  1167 + .perm = 1 << type
1183 1168 };
1184 1169 int error = is_delete ? -ENOENT : -ENOMEM;
1185   - if (!domain)
1186   - return -EINVAL;
1187 1170 if (!tomoyo_parse_name_union(filename, &e.name))
1188 1171 return -EINVAL;
1189 1172 if (!tomoyo_parse_number_union(number, &e.number))
1190 1173 goto out;
1191   - if (mutex_lock_interruptible(&tomoyo_policy_lock))
1192   - goto out;
1193   - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1194   - struct tomoyo_path_number_acl *acl =
1195   - container_of(ptr, struct tomoyo_path_number_acl, head);
1196   - if (!tomoyo_is_same_path_number_acl(acl, &e))
1197   - continue;
1198   - if (is_delete)
1199   - acl->perm &= ~perm;
1200   - else
1201   - acl->perm |= perm;
1202   - error = 0;
1203   - break;
1204   - }
1205   - if (!is_delete && error) {
1206   - struct tomoyo_path_number_acl *entry =
1207   - tomoyo_commit_ok(&e, sizeof(e));
1208   - if (entry) {
1209   - list_add_tail_rcu(&entry->head.list,
1210   - &domain->acl_info_list);
1211   - error = 0;
1212   - }
1213   - }
1214   - mutex_unlock(&tomoyo_policy_lock);
  1174 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
  1175 + tomoyo_same_path_number_acl,
  1176 + tomoyo_merge_path_number_acl);
1215 1177 out:
1216 1178 tomoyo_put_name_union(&e.name);
1217 1179 tomoyo_put_number_union(&e.number);
1218 1180  
... ... @@ -1585,13 +1547,8 @@
1585 1547 u8 type;
1586 1548 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
1587 1549 return -EINVAL;
1588   - if (strncmp(w[0], "allow_", 6)) {
1589   - unsigned int perm;
1590   - if (sscanf(w[0], "%u", &perm) == 1)
1591   - return tomoyo_update_file_acl((u8) perm, w[1], domain,
1592   - is_delete);
  1550 + if (strncmp(w[0], "allow_", 6))
1593 1551 goto out;
1594   - }
1595 1552 w[0] += 6;
1596 1553 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
1597 1554 if (strcmp(w[0], tomoyo_path_keyword[type]))
security/tomoyo/gc.c
... ... @@ -310,34 +310,8 @@
310 310 struct tomoyo_acl_info *acl;
311 311 list_for_each_entry_rcu(acl, &domain->acl_info_list,
312 312 list) {
313   - switch (acl->type) {
314   - case TOMOYO_TYPE_PATH_ACL:
315   - if (container_of(acl,
316   - struct tomoyo_path_acl,
317   - head)->perm)
318   - continue;
319   - break;
320   - case TOMOYO_TYPE_PATH2_ACL:
321   - if (container_of(acl,
322   - struct tomoyo_path2_acl,
323   - head)->perm)
324   - continue;
325   - break;
326   - case TOMOYO_TYPE_PATH_NUMBER_ACL:
327   - if (container_of(acl,
328   - struct tomoyo_path_number_acl,
329   - head)->perm)
330   - continue;
331   - break;
332   - case TOMOYO_TYPE_PATH_NUMBER3_ACL:
333   - if (container_of(acl,
334   - struct tomoyo_path_number3_acl,
335   - head)->perm)
336   - continue;
337   - break;
338   - default:
  313 + if (!acl->is_deleted)
339 314 continue;
340   - }
341 315 if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl))
342 316 list_del_rcu(&acl->list);
343 317 else
security/tomoyo/mount.c
... ... @@ -114,11 +114,10 @@
114 114 tomoyo_fill_path_info(&rdev);
115 115 list_for_each_entry_rcu(ptr, &r->domain->acl_info_list, list) {
116 116 struct tomoyo_mount_acl *acl;
117   - if (ptr->type != TOMOYO_TYPE_MOUNT_ACL)
  117 + if (ptr->is_deleted || ptr->type != TOMOYO_TYPE_MOUNT_ACL)
118 118 continue;
119 119 acl = container_of(ptr, struct tomoyo_mount_acl, head);
120   - if (acl->is_deleted ||
121   - !tomoyo_compare_number_union(flags, &acl->flags) ||
  120 + if (!tomoyo_compare_number_union(flags, &acl->flags) ||
122 121 !tomoyo_compare_name_union(&rtype, &acl->fs_type) ||
123 122 !tomoyo_compare_name_union(&rdir, &acl->dir_name) ||
124 123 (need_dev &&
... ... @@ -259,6 +258,18 @@
259 258 return error;
260 259 }
261 260  
  261 +static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
  262 + const struct tomoyo_acl_info *b)
  263 +{
  264 + const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
  265 + const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
  266 + return tomoyo_is_same_acl_head(&p1->head, &p2->head) &&
  267 + tomoyo_is_same_name_union(&p1->dev_name, &p2->dev_name) &&
  268 + tomoyo_is_same_name_union(&p1->dir_name, &p2->dir_name) &&
  269 + tomoyo_is_same_name_union(&p1->fs_type, &p2->fs_type) &&
  270 + tomoyo_is_same_number_union(&p1->flags, &p2->flags);
  271 +}
  272 +
262 273 /**
263 274 * tomoyo_write_mount_policy - Write "struct tomoyo_mount_acl" list.
264 275 *
265 276  
... ... @@ -267,11 +278,12 @@
267 278 * @is_delete: True if it is a delete request.
268 279 *
269 280 * Returns 0 on success, negative value otherwise.
  281 + *
  282 + * Caller holds tomoyo_read_lock().
270 283 */
271 284 int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain,
272 285 const bool is_delete)
273 286 {
274   - struct tomoyo_acl_info *ptr;
275 287 struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
276 288 int error = is_delete ? -ENOENT : -ENOMEM;
277 289 char *w[4];
... ... @@ -282,27 +294,8 @@
282 294 !tomoyo_parse_name_union(w[2], &e.fs_type) ||
283 295 !tomoyo_parse_number_union(w[3], &e.flags))
284 296 goto out;
285   - if (mutex_lock_interruptible(&tomoyo_policy_lock))
286   - goto out;
287   - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
288   - struct tomoyo_mount_acl *acl =
289   - container_of(ptr, struct tomoyo_mount_acl, head);
290   - if (!tomoyo_is_same_mount_acl(acl, &e))
291   - continue;
292   - acl->is_deleted = is_delete;
293   - error = 0;
294   - break;
295   - }
296   - if (!is_delete && error) {
297   - struct tomoyo_mount_acl *entry =
298   - tomoyo_commit_ok(&e, sizeof(e));
299   - if (entry) {
300   - list_add_tail_rcu(&entry->head.list,
301   - &domain->acl_info_list);
302   - error = 0;
303   - }
304   - }
305   - mutex_unlock(&tomoyo_policy_lock);
  297 + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
  298 + tomoyo_same_mount_acl, NULL);
306 299 out:
307 300 tomoyo_put_name_union(&e.dev_name);
308 301 tomoyo_put_name_union(&e.dir_name);
security/tomoyo/util.c
... ... @@ -911,6 +911,8 @@
911 911 if (!domain)
912 912 return true;
913 913 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
  914 + if (!ptr->is_deleted)
  915 + continue;
914 916 switch (ptr->type) {
915 917 u16 perm;
916 918 u8 i;
... ... @@ -944,10 +946,8 @@
944 946 if (perm & (1 << i))
945 947 count++;
946 948 break;
947   - case TOMOYO_TYPE_MOUNT_ACL:
948   - if (!container_of(ptr, struct tomoyo_mount_acl, head)->
949   - is_deleted)
950   - count++;
  949 + default:
  950 + count++;
951 951 }
952 952 }
953 953 if (count < tomoyo_profile(domain->profile)->learning->