diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2010-05-16 21:09:15 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2010-08-02 01:33:37 -0400 |
commit | a1f9bb6a375a8dbf7797ffbd6739c46b338a77f7 (patch) | |
tree | 44df8f05e6ad6bd7cf9ce398c99efbd7cff24c20 /security/tomoyo | |
parent | cb0abe6a5b58499bd4bc1403f4987af9ead0642c (diff) |
TOMOYO: Split file access control functions by type of parameters.
Check numeric parameters for operations that deal them
(e.g. chmod/chown/ioctl).
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')
-rw-r--r-- | security/tomoyo/common.c | 105 | ||||
-rw-r--r-- | security/tomoyo/common.h | 126 | ||||
-rw-r--r-- | security/tomoyo/file.c | 588 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 35 | ||||
-rw-r--r-- | security/tomoyo/tomoyo.c | 21 |
5 files changed, 752 insertions, 123 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 34d65871096c..0706b175fdb1 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -1043,12 +1043,11 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) | |||
1043 | return true; | 1043 | return true; |
1044 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 1044 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
1045 | switch (ptr->type) { | 1045 | switch (ptr->type) { |
1046 | struct tomoyo_path_acl *acl; | 1046 | u16 perm; |
1047 | u32 perm; | ||
1048 | u8 i; | 1047 | u8 i; |
1049 | case TOMOYO_TYPE_PATH_ACL: | 1048 | case TOMOYO_TYPE_PATH_ACL: |
1050 | acl = container_of(ptr, struct tomoyo_path_acl, head); | 1049 | perm = container_of(ptr, struct tomoyo_path_acl, head) |
1051 | perm = acl->perm | (((u32) acl->perm_high) << 16); | 1050 | ->perm; |
1052 | for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++) | 1051 | for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++) |
1053 | if (perm & (1 << i)) | 1052 | if (perm & (1 << i)) |
1054 | count++; | 1053 | count++; |
@@ -1062,6 +1061,20 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) | |||
1062 | if (perm & (1 << i)) | 1061 | if (perm & (1 << i)) |
1063 | count++; | 1062 | count++; |
1064 | break; | 1063 | break; |
1064 | case TOMOYO_TYPE_PATH_NUMBER_ACL: | ||
1065 | perm = container_of(ptr, struct tomoyo_path_number_acl, | ||
1066 | head)->perm; | ||
1067 | for (i = 0; i < TOMOYO_MAX_PATH_NUMBER_OPERATION; i++) | ||
1068 | if (perm & (1 << i)) | ||
1069 | count++; | ||
1070 | break; | ||
1071 | case TOMOYO_TYPE_PATH_NUMBER3_ACL: | ||
1072 | perm = container_of(ptr, struct tomoyo_path_number3_acl, | ||
1073 | head)->perm; | ||
1074 | for (i = 0; i < TOMOYO_MAX_PATH_NUMBER3_OPERATION; i++) | ||
1075 | if (perm & (1 << i)) | ||
1076 | count++; | ||
1077 | break; | ||
1065 | } | 1078 | } |
1066 | } | 1079 | } |
1067 | if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) | 1080 | if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) |
@@ -1579,7 +1592,7 @@ static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head, | |||
1579 | { | 1592 | { |
1580 | int pos; | 1593 | int pos; |
1581 | u8 bit; | 1594 | u8 bit; |
1582 | const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); | 1595 | const u16 perm = ptr->perm; |
1583 | 1596 | ||
1584 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { | 1597 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { |
1585 | if (!(perm & (1 << bit))) | 1598 | if (!(perm & (1 << bit))) |
@@ -1638,6 +1651,76 @@ static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head, | |||
1638 | } | 1651 | } |
1639 | 1652 | ||
1640 | /** | 1653 | /** |
1654 | * tomoyo_print_path_number_acl - Print a path_number ACL entry. | ||
1655 | * | ||
1656 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
1657 | * @ptr: Pointer to "struct tomoyo_path_number_acl". | ||
1658 | * | ||
1659 | * Returns true on success, false otherwise. | ||
1660 | */ | ||
1661 | static bool tomoyo_print_path_number_acl(struct tomoyo_io_buffer *head, | ||
1662 | struct tomoyo_path_number_acl *ptr) | ||
1663 | { | ||
1664 | int pos; | ||
1665 | u8 bit; | ||
1666 | const u8 perm = ptr->perm; | ||
1667 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_NUMBER_OPERATION; | ||
1668 | bit++) { | ||
1669 | if (!(perm & (1 << bit))) | ||
1670 | continue; | ||
1671 | pos = head->read_avail; | ||
1672 | if (!tomoyo_io_printf(head, "allow_%s", | ||
1673 | tomoyo_path_number2keyword(bit)) || | ||
1674 | !tomoyo_print_name_union(head, &ptr->name) || | ||
1675 | !tomoyo_print_number_union(head, &ptr->number) || | ||
1676 | !tomoyo_io_printf(head, "\n")) | ||
1677 | goto out; | ||
1678 | } | ||
1679 | head->read_bit = 0; | ||
1680 | return true; | ||
1681 | out: | ||
1682 | head->read_bit = bit; | ||
1683 | head->read_avail = pos; | ||
1684 | return false; | ||
1685 | } | ||
1686 | |||
1687 | /** | ||
1688 | * tomoyo_print_path_number3_acl - Print a path_number3 ACL entry. | ||
1689 | * | ||
1690 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
1691 | * @ptr: Pointer to "struct tomoyo_path_number3_acl". | ||
1692 | * | ||
1693 | * Returns true on success, false otherwise. | ||
1694 | */ | ||
1695 | static bool tomoyo_print_path_number3_acl(struct tomoyo_io_buffer *head, | ||
1696 | struct tomoyo_path_number3_acl *ptr) | ||
1697 | { | ||
1698 | int pos; | ||
1699 | u8 bit; | ||
1700 | const u16 perm = ptr->perm; | ||
1701 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_NUMBER3_OPERATION; | ||
1702 | bit++) { | ||
1703 | if (!(perm & (1 << bit))) | ||
1704 | continue; | ||
1705 | pos = head->read_avail; | ||
1706 | if (!tomoyo_io_printf(head, "allow_%s", | ||
1707 | tomoyo_path_number32keyword(bit)) || | ||
1708 | !tomoyo_print_name_union(head, &ptr->name) || | ||
1709 | !tomoyo_print_number_union(head, &ptr->mode) || | ||
1710 | !tomoyo_print_number_union(head, &ptr->major) || | ||
1711 | !tomoyo_print_number_union(head, &ptr->minor) || | ||
1712 | !tomoyo_io_printf(head, "\n")) | ||
1713 | goto out; | ||
1714 | } | ||
1715 | head->read_bit = 0; | ||
1716 | return true; | ||
1717 | out: | ||
1718 | head->read_bit = bit; | ||
1719 | head->read_avail = pos; | ||
1720 | return false; | ||
1721 | } | ||
1722 | |||
1723 | /** | ||
1641 | * tomoyo_print_entry - Print an ACL entry. | 1724 | * tomoyo_print_entry - Print an ACL entry. |
1642 | * | 1725 | * |
1643 | * @head: Pointer to "struct tomoyo_io_buffer". | 1726 | * @head: Pointer to "struct tomoyo_io_buffer". |
@@ -1660,6 +1743,18 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
1660 | = container_of(ptr, struct tomoyo_path2_acl, head); | 1743 | = container_of(ptr, struct tomoyo_path2_acl, head); |
1661 | return tomoyo_print_path2_acl(head, acl); | 1744 | return tomoyo_print_path2_acl(head, acl); |
1662 | } | 1745 | } |
1746 | if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) { | ||
1747 | struct tomoyo_path_number_acl *acl | ||
1748 | = container_of(ptr, struct tomoyo_path_number_acl, | ||
1749 | head); | ||
1750 | return tomoyo_print_path_number_acl(head, acl); | ||
1751 | } | ||
1752 | if (acl_type == TOMOYO_TYPE_PATH_NUMBER3_ACL) { | ||
1753 | struct tomoyo_path_number3_acl *acl | ||
1754 | = container_of(ptr, struct tomoyo_path_number3_acl, | ||
1755 | head); | ||
1756 | return tomoyo_print_path_number3_acl(head, acl); | ||
1757 | } | ||
1663 | BUG(); /* This must not happen. */ | 1758 | BUG(); /* This must not happen. */ |
1664 | return false; | 1759 | return false; |
1665 | } | 1760 | } |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 91e2bcfd56e3..565a1c11da53 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -88,17 +88,21 @@ enum tomoyo_mac_index { | |||
88 | enum tomoyo_acl_entry_type_index { | 88 | enum tomoyo_acl_entry_type_index { |
89 | TOMOYO_TYPE_PATH_ACL, | 89 | TOMOYO_TYPE_PATH_ACL, |
90 | TOMOYO_TYPE_PATH2_ACL, | 90 | TOMOYO_TYPE_PATH2_ACL, |
91 | TOMOYO_TYPE_PATH_NUMBER_ACL, | ||
92 | TOMOYO_TYPE_PATH_NUMBER3_ACL, | ||
91 | }; | 93 | }; |
92 | 94 | ||
93 | /* Index numbers for File Controls. */ | 95 | /* Index numbers for File Controls. */ |
94 | 96 | ||
95 | /* | 97 | /* |
96 | * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set | 98 | * TOMOYO_TYPE_READ_WRITE is special. TOMOYO_TYPE_READ_WRITE is automatically |
97 | * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and | 99 | * set if both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are set. |
98 | * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set. | 100 | * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically set if |
99 | * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or | 101 | * TOMOYO_TYPE_READ_WRITE is set. |
100 | * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are | 102 | * TOMOYO_TYPE_READ_WRITE is automatically cleared if either TOMOYO_TYPE_READ |
101 | * automatically cleared if TYPE_READ_WRITE_ACL is cleared. | 103 | * or TOMOYO_TYPE_WRITE is cleared. |
104 | * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically cleared if | ||
105 | * TOMOYO_TYPE_READ_WRITE is cleared. | ||
102 | */ | 106 | */ |
103 | 107 | ||
104 | enum tomoyo_path_acl_index { | 108 | enum tomoyo_path_acl_index { |
@@ -106,27 +110,23 @@ enum tomoyo_path_acl_index { | |||
106 | TOMOYO_TYPE_EXECUTE, | 110 | TOMOYO_TYPE_EXECUTE, |
107 | TOMOYO_TYPE_READ, | 111 | TOMOYO_TYPE_READ, |
108 | TOMOYO_TYPE_WRITE, | 112 | TOMOYO_TYPE_WRITE, |
109 | TOMOYO_TYPE_CREATE, | ||
110 | TOMOYO_TYPE_UNLINK, | 113 | TOMOYO_TYPE_UNLINK, |
111 | TOMOYO_TYPE_MKDIR, | ||
112 | TOMOYO_TYPE_RMDIR, | 114 | TOMOYO_TYPE_RMDIR, |
113 | TOMOYO_TYPE_MKFIFO, | ||
114 | TOMOYO_TYPE_MKSOCK, | ||
115 | TOMOYO_TYPE_MKBLOCK, | ||
116 | TOMOYO_TYPE_MKCHAR, | ||
117 | TOMOYO_TYPE_TRUNCATE, | 115 | TOMOYO_TYPE_TRUNCATE, |
118 | TOMOYO_TYPE_SYMLINK, | 116 | TOMOYO_TYPE_SYMLINK, |
119 | TOMOYO_TYPE_REWRITE, | 117 | TOMOYO_TYPE_REWRITE, |
120 | TOMOYO_TYPE_IOCTL, | ||
121 | TOMOYO_TYPE_CHMOD, | ||
122 | TOMOYO_TYPE_CHOWN, | ||
123 | TOMOYO_TYPE_CHGRP, | ||
124 | TOMOYO_TYPE_CHROOT, | 118 | TOMOYO_TYPE_CHROOT, |
125 | TOMOYO_TYPE_MOUNT, | 119 | TOMOYO_TYPE_MOUNT, |
126 | TOMOYO_TYPE_UMOUNT, | 120 | TOMOYO_TYPE_UMOUNT, |
127 | TOMOYO_MAX_PATH_OPERATION | 121 | TOMOYO_MAX_PATH_OPERATION |
128 | }; | 122 | }; |
129 | 123 | ||
124 | enum tomoyo_path_number3_acl_index { | ||
125 | TOMOYO_TYPE_MKBLOCK, | ||
126 | TOMOYO_TYPE_MKCHAR, | ||
127 | TOMOYO_MAX_PATH_NUMBER3_OPERATION | ||
128 | }; | ||
129 | |||
130 | enum tomoyo_path2_acl_index { | 130 | enum tomoyo_path2_acl_index { |
131 | TOMOYO_TYPE_LINK, | 131 | TOMOYO_TYPE_LINK, |
132 | TOMOYO_TYPE_RENAME, | 132 | TOMOYO_TYPE_RENAME, |
@@ -134,6 +134,18 @@ enum tomoyo_path2_acl_index { | |||
134 | TOMOYO_MAX_PATH2_OPERATION | 134 | TOMOYO_MAX_PATH2_OPERATION |
135 | }; | 135 | }; |
136 | 136 | ||
137 | enum tomoyo_path_number_acl_index { | ||
138 | TOMOYO_TYPE_CREATE, | ||
139 | TOMOYO_TYPE_MKDIR, | ||
140 | TOMOYO_TYPE_MKFIFO, | ||
141 | TOMOYO_TYPE_MKSOCK, | ||
142 | TOMOYO_TYPE_IOCTL, | ||
143 | TOMOYO_TYPE_CHMOD, | ||
144 | TOMOYO_TYPE_CHOWN, | ||
145 | TOMOYO_TYPE_CHGRP, | ||
146 | TOMOYO_MAX_PATH_NUMBER_OPERATION | ||
147 | }; | ||
148 | |||
137 | enum tomoyo_securityfs_interface_index { | 149 | enum tomoyo_securityfs_interface_index { |
138 | TOMOYO_DOMAINPOLICY, | 150 | TOMOYO_DOMAINPOLICY, |
139 | TOMOYO_EXCEPTIONPOLICY, | 151 | TOMOYO_EXCEPTIONPOLICY, |
@@ -347,20 +359,62 @@ struct tomoyo_domain_info { | |||
347 | * (3) "name" is the pathname. | 359 | * (3) "name" is the pathname. |
348 | * | 360 | * |
349 | * Directives held by this structure are "allow_read/write", "allow_execute", | 361 | * Directives held by this structure are "allow_read/write", "allow_execute", |
350 | * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", | 362 | * "allow_read", "allow_write", "allow_unlink", "allow_rmdir", |
351 | * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock", | 363 | * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_chroot", |
352 | * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite", | ||
353 | * "allow_ioctl", "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", | ||
354 | * "allow_mount" and "allow_unmount". | 364 | * "allow_mount" and "allow_unmount". |
355 | */ | 365 | */ |
356 | struct tomoyo_path_acl { | 366 | struct tomoyo_path_acl { |
357 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ | 367 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ |
358 | u8 perm_high; | ||
359 | u16 perm; | 368 | u16 perm; |
360 | struct tomoyo_name_union name; | 369 | struct tomoyo_name_union name; |
361 | }; | 370 | }; |
362 | 371 | ||
363 | /* | 372 | /* |
373 | * tomoyo_path_number_acl is a structure which is used for holding an | ||
374 | * entry with one pathname and one number operation. | ||
375 | * It has following fields. | ||
376 | * | ||
377 | * (1) "head" which is a "struct tomoyo_acl_info". | ||
378 | * (2) "perm" which is a bitmask of permitted operations. | ||
379 | * (3) "name" is the pathname. | ||
380 | * (4) "number" is the numeric value. | ||
381 | * | ||
382 | * Directives held by this structure are "allow_create", "allow_mkdir", | ||
383 | * "allow_ioctl", "allow_mkfifo", "allow_mksock", "allow_chmod", "allow_chown" | ||
384 | * and "allow_chgrp". | ||
385 | * | ||
386 | */ | ||
387 | struct tomoyo_path_number_acl { | ||
388 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_NUMBER_ACL */ | ||
389 | u8 perm; | ||
390 | struct tomoyo_name_union name; | ||
391 | struct tomoyo_number_union number; | ||
392 | }; | ||
393 | |||
394 | /* | ||
395 | * tomoyo_path_number3_acl is a structure which is used for holding an | ||
396 | * entry with one pathname and three numbers operation. | ||
397 | * It has following fields. | ||
398 | * | ||
399 | * (1) "head" which is a "struct tomoyo_acl_info". | ||
400 | * (2) "perm" which is a bitmask of permitted operations. | ||
401 | * (3) "mode" is the create mode. | ||
402 | * (4) "major" is the major number of device node. | ||
403 | * (5) "minor" is the minor number of device node. | ||
404 | * | ||
405 | * Directives held by this structure are "allow_mkchar", "allow_mkblock". | ||
406 | * | ||
407 | */ | ||
408 | struct tomoyo_path_number3_acl { | ||
409 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_NUMBER3_ACL */ | ||
410 | u8 perm; | ||
411 | struct tomoyo_name_union name; | ||
412 | struct tomoyo_number_union mode; | ||
413 | struct tomoyo_number_union major; | ||
414 | struct tomoyo_number_union minor; | ||
415 | }; | ||
416 | |||
417 | /* | ||
364 | * tomoyo_path2_acl is a structure which is used for holding an | 418 | * tomoyo_path2_acl is a structure which is used for holding an |
365 | * entry with two pathnames operation (i.e. link(), rename() and pivot_root()). | 419 | * entry with two pathnames operation (i.e. link(), rename() and pivot_root()). |
366 | * It has following fields. | 420 | * It has following fields. |
@@ -639,6 +693,8 @@ bool tomoyo_tokenize(char *buffer, char *w[], size_t size); | |||
639 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); | 693 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); |
640 | /* Convert double path operation to operation name. */ | 694 | /* Convert double path operation to operation name. */ |
641 | const char *tomoyo_path22keyword(const u8 operation); | 695 | const char *tomoyo_path22keyword(const u8 operation); |
696 | const char *tomoyo_path_number2keyword(const u8 operation); | ||
697 | const char *tomoyo_path_number32keyword(const u8 operation); | ||
642 | /* Get the last component of the given domainname. */ | 698 | /* Get the last component of the given domainname. */ |
643 | const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); | 699 | const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); |
644 | /* Convert single path operation to operation name. */ | 700 | /* Convert single path operation to operation name. */ |
@@ -736,11 +792,18 @@ int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | |||
736 | const struct tomoyo_path_info *filename); | 792 | const struct tomoyo_path_info *filename); |
737 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | 793 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, |
738 | struct path *path, const int flag); | 794 | struct path *path, const int flag); |
795 | int tomoyo_path_number_perm(const u8 operation, struct path *path, | ||
796 | unsigned long number); | ||
797 | int tomoyo_path_number3_perm(const u8 operation, struct path *path, | ||
798 | const unsigned int mode, unsigned int dev); | ||
739 | int tomoyo_path_perm(const u8 operation, struct path *path); | 799 | int tomoyo_path_perm(const u8 operation, struct path *path); |
740 | int tomoyo_path2_perm(const u8 operation, struct path *path1, | 800 | int tomoyo_path2_perm(const u8 operation, struct path *path1, |
741 | struct path *path2); | 801 | struct path *path2); |
742 | int tomoyo_find_next_domain(struct linux_binprm *bprm); | 802 | int tomoyo_find_next_domain(struct linux_binprm *bprm); |
743 | 803 | ||
804 | void tomoyo_print_ulong(char *buffer, const int buffer_len, | ||
805 | const unsigned long value, const u8 type); | ||
806 | |||
744 | /* Drop refcount on tomoyo_name_union. */ | 807 | /* Drop refcount on tomoyo_name_union. */ |
745 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr); | 808 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr); |
746 | 809 | ||
@@ -880,6 +943,18 @@ static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, | |||
880 | tomoyo_is_same_name_union(&p1->name, &p2->name); | 943 | tomoyo_is_same_name_union(&p1->name, &p2->name); |
881 | } | 944 | } |
882 | 945 | ||
946 | static inline bool tomoyo_is_same_path_number3_acl | ||
947 | (const struct tomoyo_path_number3_acl *p1, | ||
948 | const struct tomoyo_path_number3_acl *p2) | ||
949 | { | ||
950 | return tomoyo_is_same_acl_head(&p1->head, &p2->head) | ||
951 | && tomoyo_is_same_name_union(&p1->name, &p2->name) | ||
952 | && tomoyo_is_same_number_union(&p1->mode, &p2->mode) | ||
953 | && tomoyo_is_same_number_union(&p1->major, &p2->major) | ||
954 | && tomoyo_is_same_number_union(&p1->minor, &p2->minor); | ||
955 | } | ||
956 | |||
957 | |||
883 | static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1, | 958 | static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1, |
884 | const struct tomoyo_path2_acl *p2) | 959 | const struct tomoyo_path2_acl *p2) |
885 | { | 960 | { |
@@ -888,6 +963,15 @@ static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1, | |||
888 | tomoyo_is_same_name_union(&p1->name2, &p2->name2); | 963 | tomoyo_is_same_name_union(&p1->name2, &p2->name2); |
889 | } | 964 | } |
890 | 965 | ||
966 | static inline bool tomoyo_is_same_path_number_acl | ||
967 | (const struct tomoyo_path_number_acl *p1, | ||
968 | const struct tomoyo_path_number_acl *p2) | ||
969 | { | ||
970 | return tomoyo_is_same_acl_head(&p1->head, &p2->head) | ||
971 | && tomoyo_is_same_name_union(&p1->name, &p2->name) | ||
972 | && tomoyo_is_same_number_union(&p1->number, &p2->number); | ||
973 | } | ||
974 | |||
891 | static inline bool tomoyo_is_same_domain_initializer_entry | 975 | static inline bool tomoyo_is_same_domain_initializer_entry |
892 | (const struct tomoyo_domain_initializer_entry *p1, | 976 | (const struct tomoyo_domain_initializer_entry *p1, |
893 | const struct tomoyo_domain_initializer_entry *p2) | 977 | const struct tomoyo_domain_initializer_entry *p2) |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index f1d2adfd33bc..727cc723f87d 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -12,39 +12,49 @@ | |||
12 | #include "common.h" | 12 | #include "common.h" |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | 14 | ||
15 | /* Keyword array for single path operations. */ | 15 | /* Keyword array for operations with one pathname. */ |
16 | static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { | 16 | static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { |
17 | [TOMOYO_TYPE_READ_WRITE] = "read/write", | 17 | [TOMOYO_TYPE_READ_WRITE] = "read/write", |
18 | [TOMOYO_TYPE_EXECUTE] = "execute", | 18 | [TOMOYO_TYPE_EXECUTE] = "execute", |
19 | [TOMOYO_TYPE_READ] = "read", | 19 | [TOMOYO_TYPE_READ] = "read", |
20 | [TOMOYO_TYPE_WRITE] = "write", | 20 | [TOMOYO_TYPE_WRITE] = "write", |
21 | [TOMOYO_TYPE_CREATE] = "create", | ||
22 | [TOMOYO_TYPE_UNLINK] = "unlink", | 21 | [TOMOYO_TYPE_UNLINK] = "unlink", |
23 | [TOMOYO_TYPE_MKDIR] = "mkdir", | ||
24 | [TOMOYO_TYPE_RMDIR] = "rmdir", | 22 | [TOMOYO_TYPE_RMDIR] = "rmdir", |
25 | [TOMOYO_TYPE_MKFIFO] = "mkfifo", | ||
26 | [TOMOYO_TYPE_MKSOCK] = "mksock", | ||
27 | [TOMOYO_TYPE_MKBLOCK] = "mkblock", | ||
28 | [TOMOYO_TYPE_MKCHAR] = "mkchar", | ||
29 | [TOMOYO_TYPE_TRUNCATE] = "truncate", | 23 | [TOMOYO_TYPE_TRUNCATE] = "truncate", |
30 | [TOMOYO_TYPE_SYMLINK] = "symlink", | 24 | [TOMOYO_TYPE_SYMLINK] = "symlink", |
31 | [TOMOYO_TYPE_REWRITE] = "rewrite", | 25 | [TOMOYO_TYPE_REWRITE] = "rewrite", |
32 | [TOMOYO_TYPE_IOCTL] = "ioctl", | ||
33 | [TOMOYO_TYPE_CHMOD] = "chmod", | ||
34 | [TOMOYO_TYPE_CHOWN] = "chown", | ||
35 | [TOMOYO_TYPE_CHGRP] = "chgrp", | ||
36 | [TOMOYO_TYPE_CHROOT] = "chroot", | 26 | [TOMOYO_TYPE_CHROOT] = "chroot", |
37 | [TOMOYO_TYPE_MOUNT] = "mount", | 27 | [TOMOYO_TYPE_MOUNT] = "mount", |
38 | [TOMOYO_TYPE_UMOUNT] = "unmount", | 28 | [TOMOYO_TYPE_UMOUNT] = "unmount", |
39 | }; | 29 | }; |
40 | 30 | ||
41 | /* Keyword array for double path operations. */ | 31 | /* Keyword array for operations with one pathname and three numbers. */ |
32 | static const char *tomoyo_path_number3_keyword | ||
33 | [TOMOYO_MAX_PATH_NUMBER3_OPERATION] = { | ||
34 | [TOMOYO_TYPE_MKBLOCK] = "mkblock", | ||
35 | [TOMOYO_TYPE_MKCHAR] = "mkchar", | ||
36 | }; | ||
37 | |||
38 | /* Keyword array for operations with two pathnames. */ | ||
42 | static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { | 39 | static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { |
43 | [TOMOYO_TYPE_LINK] = "link", | 40 | [TOMOYO_TYPE_LINK] = "link", |
44 | [TOMOYO_TYPE_RENAME] = "rename", | 41 | [TOMOYO_TYPE_RENAME] = "rename", |
45 | [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", | 42 | [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", |
46 | }; | 43 | }; |
47 | 44 | ||
45 | /* Keyword array for operations with one pathname and one number. */ | ||
46 | static const char *tomoyo_path_number_keyword | ||
47 | [TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | ||
48 | [TOMOYO_TYPE_CREATE] = "create", | ||
49 | [TOMOYO_TYPE_MKDIR] = "mkdir", | ||
50 | [TOMOYO_TYPE_MKFIFO] = "mkfifo", | ||
51 | [TOMOYO_TYPE_MKSOCK] = "mksock", | ||
52 | [TOMOYO_TYPE_IOCTL] = "ioctl", | ||
53 | [TOMOYO_TYPE_CHMOD] = "chmod", | ||
54 | [TOMOYO_TYPE_CHOWN] = "chown", | ||
55 | [TOMOYO_TYPE_CHGRP] = "chgrp", | ||
56 | }; | ||
57 | |||
48 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) | 58 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) |
49 | { | 59 | { |
50 | if (!ptr) | 60 | if (!ptr) |
@@ -159,6 +169,19 @@ const char *tomoyo_path2keyword(const u8 operation) | |||
159 | } | 169 | } |
160 | 170 | ||
161 | /** | 171 | /** |
172 | * tomoyo_path_number32keyword - Get the name of path/number/number/number operations. | ||
173 | * | ||
174 | * @operation: Type of operation. | ||
175 | * | ||
176 | * Returns the name of path/number/number/number operation. | ||
177 | */ | ||
178 | const char *tomoyo_path_number32keyword(const u8 operation) | ||
179 | { | ||
180 | return (operation < TOMOYO_MAX_PATH_NUMBER3_OPERATION) | ||
181 | ? tomoyo_path_number3_keyword[operation] : NULL; | ||
182 | } | ||
183 | |||
184 | /** | ||
162 | * tomoyo_path22keyword - Get the name of double path operation. | 185 | * tomoyo_path22keyword - Get the name of double path operation. |
163 | * | 186 | * |
164 | * @operation: Type of operation. | 187 | * @operation: Type of operation. |
@@ -172,6 +195,19 @@ const char *tomoyo_path22keyword(const u8 operation) | |||
172 | } | 195 | } |
173 | 196 | ||
174 | /** | 197 | /** |
198 | * tomoyo_path_number2keyword - Get the name of path/number operations. | ||
199 | * | ||
200 | * @operation: Type of operation. | ||
201 | * | ||
202 | * Returns the name of path/number operation. | ||
203 | */ | ||
204 | const char *tomoyo_path_number2keyword(const u8 operation) | ||
205 | { | ||
206 | return (operation < TOMOYO_MAX_PATH_NUMBER_OPERATION) | ||
207 | ? tomoyo_path_number_keyword[operation] : NULL; | ||
208 | } | ||
209 | |||
210 | /** | ||
175 | * tomoyo_strendswith - Check whether the token ends with the given token. | 211 | * tomoyo_strendswith - Check whether the token ends with the given token. |
176 | * | 212 | * |
177 | * @name: The token to check. | 213 | * @name: The token to check. |
@@ -665,8 +701,8 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | |||
665 | /** | 701 | /** |
666 | * tomoyo_update_file_acl - Update file's read/write/execute ACL. | 702 | * tomoyo_update_file_acl - Update file's read/write/execute ACL. |
667 | * | 703 | * |
668 | * @filename: Filename. | ||
669 | * @perm: Permission (between 1 to 7). | 704 | * @perm: Permission (between 1 to 7). |
705 | * @filename: Filename. | ||
670 | * @domain: Pointer to "struct tomoyo_domain_info". | 706 | * @domain: Pointer to "struct tomoyo_domain_info". |
671 | * @is_delete: True if it is a delete request. | 707 | * @is_delete: True if it is a delete request. |
672 | * | 708 | * |
@@ -679,7 +715,7 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | |||
679 | * | 715 | * |
680 | * Caller holds tomoyo_read_lock(). | 716 | * Caller holds tomoyo_read_lock(). |
681 | */ | 717 | */ |
682 | static int tomoyo_update_file_acl(const char *filename, u8 perm, | 718 | static int tomoyo_update_file_acl(u8 perm, const char *filename, |
683 | struct tomoyo_domain_info * const domain, | 719 | struct tomoyo_domain_info * const domain, |
684 | const bool is_delete) | 720 | const bool is_delete) |
685 | { | 721 | { |
@@ -731,14 +767,8 @@ static int tomoyo_path_acl(const struct tomoyo_request_info *r, | |||
731 | if (ptr->type != TOMOYO_TYPE_PATH_ACL) | 767 | if (ptr->type != TOMOYO_TYPE_PATH_ACL) |
732 | continue; | 768 | continue; |
733 | acl = container_of(ptr, struct tomoyo_path_acl, head); | 769 | acl = container_of(ptr, struct tomoyo_path_acl, head); |
734 | if (perm <= 0xFFFF) { | 770 | if (!(acl->perm & perm) || |
735 | if (!(acl->perm & perm)) | 771 | !tomoyo_compare_name_union_pattern(filename, &acl->name, |
736 | continue; | ||
737 | } else { | ||
738 | if (!(acl->perm_high & (perm >> 16))) | ||
739 | continue; | ||
740 | } | ||
741 | if (!tomoyo_compare_name_union_pattern(filename, &acl->name, | ||
742 | may_use_pattern)) | 772 | may_use_pattern)) |
743 | continue; | 773 | continue; |
744 | error = 0; | 774 | error = 0; |
@@ -796,61 +826,13 @@ static int tomoyo_file_perm(struct tomoyo_request_info *r, | |||
796 | /* Don't use patterns for execute permission. */ | 826 | /* Don't use patterns for execute permission. */ |
797 | const struct tomoyo_path_info *patterned_file = (mode != 1) ? | 827 | const struct tomoyo_path_info *patterned_file = (mode != 1) ? |
798 | tomoyo_get_file_pattern(filename) : filename; | 828 | tomoyo_get_file_pattern(filename) : filename; |
799 | tomoyo_update_file_acl(patterned_file->name, mode, | 829 | tomoyo_update_file_acl(mode, patterned_file->name, r->domain, |
800 | r->domain, false); | 830 | false); |
801 | } | 831 | } |
802 | return 0; | 832 | return 0; |
803 | } | 833 | } |
804 | 834 | ||
805 | /** | 835 | /** |
806 | * tomoyo_write_file_policy - Update file related list. | ||
807 | * | ||
808 | * @data: String to parse. | ||
809 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
810 | * @is_delete: True if it is a delete request. | ||
811 | * | ||
812 | * Returns 0 on success, negative value otherwise. | ||
813 | * | ||
814 | * Caller holds tomoyo_read_lock(). | ||
815 | */ | ||
816 | int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | ||
817 | const bool is_delete) | ||
818 | { | ||
819 | char *filename = strchr(data, ' '); | ||
820 | char *filename2; | ||
821 | unsigned int perm; | ||
822 | u8 type; | ||
823 | |||
824 | if (!filename) | ||
825 | return -EINVAL; | ||
826 | *filename++ = '\0'; | ||
827 | if (sscanf(data, "%u", &perm) == 1) | ||
828 | return tomoyo_update_file_acl(filename, (u8) perm, domain, | ||
829 | is_delete); | ||
830 | if (strncmp(data, "allow_", 6)) | ||
831 | goto out; | ||
832 | data += 6; | ||
833 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { | ||
834 | if (strcmp(data, tomoyo_path_keyword[type])) | ||
835 | continue; | ||
836 | return tomoyo_update_path_acl(type, filename, domain, | ||
837 | is_delete); | ||
838 | } | ||
839 | filename2 = strchr(filename, ' '); | ||
840 | if (!filename2) | ||
841 | goto out; | ||
842 | *filename2++ = '\0'; | ||
843 | for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { | ||
844 | if (strcmp(data, tomoyo_path2_keyword[type])) | ||
845 | continue; | ||
846 | return tomoyo_update_path2_acl(type, filename, filename2, | ||
847 | domain, is_delete); | ||
848 | } | ||
849 | out: | ||
850 | return -EINVAL; | ||
851 | } | ||
852 | |||
853 | /** | ||
854 | * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. | 836 | * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. |
855 | * | 837 | * |
856 | * @type: Type of operation. | 838 | * @type: Type of operation. |
@@ -866,13 +848,12 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, | |||
866 | struct tomoyo_domain_info *const domain, | 848 | struct tomoyo_domain_info *const domain, |
867 | const bool is_delete) | 849 | const bool is_delete) |
868 | { | 850 | { |
869 | static const u32 tomoyo_rw_mask = | 851 | static const u16 tomoyo_rw_mask = |
870 | (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); | 852 | (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); |
871 | const u32 perm = 1 << type; | 853 | const u16 perm = 1 << type; |
872 | struct tomoyo_acl_info *ptr; | 854 | struct tomoyo_acl_info *ptr; |
873 | struct tomoyo_path_acl e = { | 855 | struct tomoyo_path_acl e = { |
874 | .head.type = TOMOYO_TYPE_PATH_ACL, | 856 | .head.type = TOMOYO_TYPE_PATH_ACL, |
875 | .perm_high = perm >> 16, | ||
876 | .perm = perm | 857 | .perm = perm |
877 | }; | 858 | }; |
878 | int error = is_delete ? -ENOENT : -ENOMEM; | 859 | int error = is_delete ? -ENOENT : -ENOMEM; |
@@ -891,19 +872,13 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, | |||
891 | if (!tomoyo_is_same_path_acl(acl, &e)) | 872 | if (!tomoyo_is_same_path_acl(acl, &e)) |
892 | continue; | 873 | continue; |
893 | if (is_delete) { | 874 | if (is_delete) { |
894 | if (perm <= 0xFFFF) | 875 | acl->perm &= ~perm; |
895 | acl->perm &= ~perm; | ||
896 | else | ||
897 | acl->perm_high &= ~(perm >> 16); | ||
898 | if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask) | 876 | if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask) |
899 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); | 877 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); |
900 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) | 878 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) |
901 | acl->perm &= ~tomoyo_rw_mask; | 879 | acl->perm &= ~tomoyo_rw_mask; |
902 | } else { | 880 | } else { |
903 | if (perm <= 0xFFFF) | 881 | acl->perm |= perm; |
904 | acl->perm |= perm; | ||
905 | else | ||
906 | acl->perm_high |= (perm >> 16); | ||
907 | if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask) | 882 | if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask) |
908 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; | 883 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; |
909 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) | 884 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) |
@@ -928,6 +903,71 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, | |||
928 | } | 903 | } |
929 | 904 | ||
930 | /** | 905 | /** |
906 | * tomoyo_update_path_number3_acl - Update "struct tomoyo_path_number3_acl" list. | ||
907 | * | ||
908 | * @type: Type of operation. | ||
909 | * @filename: Filename. | ||
910 | * @mode: Create mode. | ||
911 | * @major: Device major number. | ||
912 | * @minor: Device minor number. | ||
913 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
914 | * @is_delete: True if it is a delete request. | ||
915 | * | ||
916 | * Returns 0 on success, negative value otherwise. | ||
917 | */ | ||
918 | static inline int tomoyo_update_path_number3_acl(const u8 type, | ||
919 | const char *filename, | ||
920 | char *mode, | ||
921 | char *major, char *minor, | ||
922 | struct tomoyo_domain_info * | ||
923 | const domain, | ||
924 | const bool is_delete) | ||
925 | { | ||
926 | const u8 perm = 1 << type; | ||
927 | struct tomoyo_acl_info *ptr; | ||
928 | struct tomoyo_path_number3_acl e = { | ||
929 | .head.type = TOMOYO_TYPE_PATH_NUMBER3_ACL, | ||
930 | .perm = perm | ||
931 | }; | ||
932 | int error = is_delete ? -ENOENT : -ENOMEM; | ||
933 | if (!tomoyo_parse_name_union(filename, &e.name) || | ||
934 | !tomoyo_parse_number_union(mode, &e.mode) || | ||
935 | !tomoyo_parse_number_union(major, &e.major) || | ||
936 | !tomoyo_parse_number_union(minor, &e.minor)) | ||
937 | goto out; | ||
938 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
939 | goto out; | ||
940 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | ||
941 | struct tomoyo_path_number3_acl *acl = | ||
942 | container_of(ptr, struct tomoyo_path_number3_acl, head); | ||
943 | if (!tomoyo_is_same_path_number3_acl(acl, &e)) | ||
944 | continue; | ||
945 | if (is_delete) | ||
946 | acl->perm &= ~perm; | ||
947 | else | ||
948 | acl->perm |= perm; | ||
949 | error = 0; | ||
950 | break; | ||
951 | } | ||
952 | if (!is_delete && error) { | ||
953 | struct tomoyo_path_number3_acl *entry = | ||
954 | tomoyo_commit_ok(&e, sizeof(e)); | ||
955 | if (entry) { | ||
956 | list_add_tail_rcu(&entry->head.list, | ||
957 | &domain->acl_info_list); | ||
958 | error = 0; | ||
959 | } | ||
960 | } | ||
961 | mutex_unlock(&tomoyo_policy_lock); | ||
962 | out: | ||
963 | tomoyo_put_name_union(&e.name); | ||
964 | tomoyo_put_number_union(&e.mode); | ||
965 | tomoyo_put_number_union(&e.major); | ||
966 | tomoyo_put_number_union(&e.minor); | ||
967 | return error; | ||
968 | } | ||
969 | |||
970 | /** | ||
931 | * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. | 971 | * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. |
932 | * | 972 | * |
933 | * @type: Type of operation. | 973 | * @type: Type of operation. |
@@ -989,6 +1029,50 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | |||
989 | } | 1029 | } |
990 | 1030 | ||
991 | /** | 1031 | /** |
1032 | * tomoyo_path_number3_acl - Check permission for path/number/number/number operation. | ||
1033 | * | ||
1034 | * @r: Pointer to "struct tomoyo_request_info". | ||
1035 | * @filename: Filename to check. | ||
1036 | * @perm: Permission. | ||
1037 | * @mode: Create mode. | ||
1038 | * @major: Device major number. | ||
1039 | * @minor: Device minor number. | ||
1040 | * | ||
1041 | * Returns 0 on success, -EPERM otherwise. | ||
1042 | * | ||
1043 | * Caller holds tomoyo_read_lock(). | ||
1044 | */ | ||
1045 | static int tomoyo_path_number3_acl(struct tomoyo_request_info *r, | ||
1046 | const struct tomoyo_path_info *filename, | ||
1047 | const u16 perm, const unsigned int mode, | ||
1048 | const unsigned int major, | ||
1049 | const unsigned int minor) | ||
1050 | { | ||
1051 | struct tomoyo_domain_info *domain = r->domain; | ||
1052 | struct tomoyo_acl_info *ptr; | ||
1053 | int error = -EPERM; | ||
1054 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | ||
1055 | struct tomoyo_path_number3_acl *acl; | ||
1056 | if (ptr->type != TOMOYO_TYPE_PATH_NUMBER3_ACL) | ||
1057 | continue; | ||
1058 | acl = container_of(ptr, struct tomoyo_path_number3_acl, head); | ||
1059 | if (!tomoyo_compare_number_union(mode, &acl->mode)) | ||
1060 | continue; | ||
1061 | if (!tomoyo_compare_number_union(major, &acl->major)) | ||
1062 | continue; | ||
1063 | if (!tomoyo_compare_number_union(minor, &acl->minor)) | ||
1064 | continue; | ||
1065 | if (!(acl->perm & perm)) | ||
1066 | continue; | ||
1067 | if (!tomoyo_compare_name_union(filename, &acl->name)) | ||
1068 | continue; | ||
1069 | error = 0; | ||
1070 | break; | ||
1071 | } | ||
1072 | return error; | ||
1073 | } | ||
1074 | |||
1075 | /** | ||
992 | * tomoyo_path2_acl - Check permission for double path operation. | 1076 | * tomoyo_path2_acl - Check permission for double path operation. |
993 | * | 1077 | * |
994 | * @r: Pointer to "struct tomoyo_request_info". | 1078 | * @r: Pointer to "struct tomoyo_request_info". |
@@ -1069,6 +1153,195 @@ static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |||
1069 | } | 1153 | } |
1070 | 1154 | ||
1071 | /** | 1155 | /** |
1156 | * tomoyo_path_number_acl - Check permission for ioctl/chmod/chown/chgrp operation. | ||
1157 | * | ||
1158 | * @r: Pointer to "struct tomoyo_request_info". | ||
1159 | * @type: Operation. | ||
1160 | * @filename: Filename to check. | ||
1161 | * @number: Number. | ||
1162 | * | ||
1163 | * Returns 0 on success, -EPERM otherwise. | ||
1164 | * | ||
1165 | * Caller holds tomoyo_read_lock(). | ||
1166 | */ | ||
1167 | static int tomoyo_path_number_acl(struct tomoyo_request_info *r, const u8 type, | ||
1168 | const struct tomoyo_path_info *filename, | ||
1169 | const unsigned long number) | ||
1170 | { | ||
1171 | struct tomoyo_domain_info *domain = r->domain; | ||
1172 | struct tomoyo_acl_info *ptr; | ||
1173 | const u8 perm = 1 << type; | ||
1174 | int error = -EPERM; | ||
1175 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | ||
1176 | struct tomoyo_path_number_acl *acl; | ||
1177 | if (ptr->type != TOMOYO_TYPE_PATH_NUMBER_ACL) | ||
1178 | continue; | ||
1179 | acl = container_of(ptr, struct tomoyo_path_number_acl, | ||
1180 | head); | ||
1181 | if (!(acl->perm & perm) || | ||
1182 | !tomoyo_compare_number_union(number, &acl->number) || | ||
1183 | !tomoyo_compare_name_union(filename, &acl->name)) | ||
1184 | continue; | ||
1185 | error = 0; | ||
1186 | break; | ||
1187 | } | ||
1188 | return error; | ||
1189 | } | ||
1190 | |||
1191 | /** | ||
1192 | * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. | ||
1193 | * | ||
1194 | * @type: Type of operation. | ||
1195 | * @filename: Filename. | ||
1196 | * @number: Number. | ||
1197 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1198 | * @is_delete: True if it is a delete request. | ||
1199 | * | ||
1200 | * Returns 0 on success, negative value otherwise. | ||
1201 | */ | ||
1202 | static inline int tomoyo_update_path_number_acl(const u8 type, | ||
1203 | const char *filename, | ||
1204 | char *number, | ||
1205 | struct tomoyo_domain_info * | ||
1206 | const domain, | ||
1207 | const bool is_delete) | ||
1208 | { | ||
1209 | const u8 perm = 1 << type; | ||
1210 | struct tomoyo_acl_info *ptr; | ||
1211 | struct tomoyo_path_number_acl e = { | ||
1212 | .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, | ||
1213 | .perm = perm | ||
1214 | }; | ||
1215 | int error = is_delete ? -ENOENT : -ENOMEM; | ||
1216 | if (!domain) | ||
1217 | return -EINVAL; | ||
1218 | if (!tomoyo_parse_name_union(filename, &e.name)) | ||
1219 | return -EINVAL; | ||
1220 | if (!tomoyo_parse_number_union(number, &e.number)) | ||
1221 | goto out; | ||
1222 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | ||
1223 | goto out; | ||
1224 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | ||
1225 | struct tomoyo_path_number_acl *acl = | ||
1226 | container_of(ptr, struct tomoyo_path_number_acl, head); | ||
1227 | if (!tomoyo_is_same_path_number_acl(acl, &e)) | ||
1228 | continue; | ||
1229 | if (is_delete) | ||
1230 | acl->perm &= ~perm; | ||
1231 | else | ||
1232 | acl->perm |= perm; | ||
1233 | error = 0; | ||
1234 | break; | ||
1235 | } | ||
1236 | if (!is_delete && error) { | ||
1237 | struct tomoyo_path_number_acl *entry = | ||
1238 | tomoyo_commit_ok(&e, sizeof(e)); | ||
1239 | if (entry) { | ||
1240 | list_add_tail_rcu(&entry->head.list, | ||
1241 | &domain->acl_info_list); | ||
1242 | error = 0; | ||
1243 | } | ||
1244 | } | ||
1245 | mutex_unlock(&tomoyo_policy_lock); | ||
1246 | out: | ||
1247 | tomoyo_put_name_union(&e.name); | ||
1248 | tomoyo_put_number_union(&e.number); | ||
1249 | return error; | ||
1250 | } | ||
1251 | |||
1252 | /** | ||
1253 | * tomoyo_path_number_perm2 - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". | ||
1254 | * | ||
1255 | * @r: Pointer to "strct tomoyo_request_info". | ||
1256 | * @filename: Filename to check. | ||
1257 | * @number: Number. | ||
1258 | * | ||
1259 | * Returns 0 on success, negative value otherwise. | ||
1260 | * | ||
1261 | * Caller holds tomoyo_read_lock(). | ||
1262 | */ | ||
1263 | static int tomoyo_path_number_perm2(struct tomoyo_request_info *r, | ||
1264 | const u8 type, | ||
1265 | const struct tomoyo_path_info *filename, | ||
1266 | const unsigned long number) | ||
1267 | { | ||
1268 | char buffer[64]; | ||
1269 | int error; | ||
1270 | u8 radix; | ||
1271 | |||
1272 | if (!filename) | ||
1273 | return 0; | ||
1274 | switch (type) { | ||
1275 | case TOMOYO_TYPE_CREATE: | ||
1276 | case TOMOYO_TYPE_MKDIR: | ||
1277 | case TOMOYO_TYPE_MKFIFO: | ||
1278 | case TOMOYO_TYPE_MKSOCK: | ||
1279 | case TOMOYO_TYPE_CHMOD: | ||
1280 | radix = TOMOYO_VALUE_TYPE_OCTAL; | ||
1281 | break; | ||
1282 | case TOMOYO_TYPE_IOCTL: | ||
1283 | radix = TOMOYO_VALUE_TYPE_HEXADECIMAL; | ||
1284 | break; | ||
1285 | default: | ||
1286 | radix = TOMOYO_VALUE_TYPE_DECIMAL; | ||
1287 | break; | ||
1288 | } | ||
1289 | tomoyo_print_ulong(buffer, sizeof(buffer), number, radix); | ||
1290 | error = tomoyo_path_number_acl(r, type, filename, number); | ||
1291 | if (!error) | ||
1292 | return 0; | ||
1293 | tomoyo_warn_log(r, "%s %s %s", tomoyo_path_number2keyword(type), | ||
1294 | filename->name, buffer); | ||
1295 | if (tomoyo_domain_quota_is_ok(r)) | ||
1296 | tomoyo_update_path_number_acl(type, | ||
1297 | tomoyo_get_file_pattern(filename) | ||
1298 | ->name, buffer, r->domain, false); | ||
1299 | if (r->mode != TOMOYO_CONFIG_ENFORCING) | ||
1300 | error = 0; | ||
1301 | return error; | ||
1302 | } | ||
1303 | |||
1304 | /** | ||
1305 | * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". | ||
1306 | * | ||
1307 | * @type: Type of operation. | ||
1308 | * @path: Pointer to "struct path". | ||
1309 | * @number: Number. | ||
1310 | * | ||
1311 | * Returns 0 on success, negative value otherwise. | ||
1312 | */ | ||
1313 | int tomoyo_path_number_perm(const u8 type, struct path *path, | ||
1314 | unsigned long number) | ||
1315 | { | ||
1316 | struct tomoyo_request_info r; | ||
1317 | int error = -ENOMEM; | ||
1318 | struct tomoyo_path_info *buf; | ||
1319 | int idx; | ||
1320 | |||
1321 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || | ||
1322 | !path->mnt || !path->dentry) | ||
1323 | return 0; | ||
1324 | idx = tomoyo_read_lock(); | ||
1325 | buf = tomoyo_get_path(path); | ||
1326 | if (!buf) | ||
1327 | goto out; | ||
1328 | if (type == TOMOYO_TYPE_MKDIR && !buf->is_dir) { | ||
1329 | /* | ||
1330 | * tomoyo_get_path() reserves space for appending "/." | ||
1331 | */ | ||
1332 | strcat((char *) buf->name, "/"); | ||
1333 | tomoyo_fill_path_info(buf); | ||
1334 | } | ||
1335 | error = tomoyo_path_number_perm2(&r, type, buf, number); | ||
1336 | out: | ||
1337 | kfree(buf); | ||
1338 | tomoyo_read_unlock(idx); | ||
1339 | if (r.mode != TOMOYO_CONFIG_ENFORCING) | ||
1340 | error = 0; | ||
1341 | return error; | ||
1342 | } | ||
1343 | |||
1344 | /** | ||
1072 | * tomoyo_check_exec_perm - Check permission for "execute". | 1345 | * tomoyo_check_exec_perm - Check permission for "execute". |
1073 | * | 1346 | * |
1074 | * @domain: Pointer to "struct tomoyo_domain_info". | 1347 | * @domain: Pointer to "struct tomoyo_domain_info". |
@@ -1145,7 +1418,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1145 | } | 1418 | } |
1146 | 1419 | ||
1147 | /** | 1420 | /** |
1148 | * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "rewrite", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount". | 1421 | * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot", "mount" and "unmount". |
1149 | * | 1422 | * |
1150 | * @operation: Type of operation. | 1423 | * @operation: Type of operation. |
1151 | * @path: Pointer to "struct path". | 1424 | * @path: Pointer to "struct path". |
@@ -1173,7 +1446,6 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1173 | goto out; | 1446 | goto out; |
1174 | } | 1447 | } |
1175 | break; | 1448 | break; |
1176 | case TOMOYO_TYPE_MKDIR: | ||
1177 | case TOMOYO_TYPE_RMDIR: | 1449 | case TOMOYO_TYPE_RMDIR: |
1178 | case TOMOYO_TYPE_CHROOT: | 1450 | case TOMOYO_TYPE_CHROOT: |
1179 | if (!buf->is_dir) { | 1451 | if (!buf->is_dir) { |
@@ -1194,6 +1466,91 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1194 | } | 1466 | } |
1195 | 1467 | ||
1196 | /** | 1468 | /** |
1469 | * tomoyo_path_number3_perm2 - Check permission for path/number/number/number operation. | ||
1470 | * | ||
1471 | * @r: Pointer to "struct tomoyo_request_info". | ||
1472 | * @operation: Type of operation. | ||
1473 | * @filename: Filename to check. | ||
1474 | * @mode: Create mode. | ||
1475 | * @dev: Device number. | ||
1476 | * | ||
1477 | * Returns 0 on success, negative value otherwise. | ||
1478 | * | ||
1479 | * Caller holds tomoyo_read_lock(). | ||
1480 | */ | ||
1481 | static int tomoyo_path_number3_perm2(struct tomoyo_request_info *r, | ||
1482 | const u8 operation, | ||
1483 | const struct tomoyo_path_info *filename, | ||
1484 | const unsigned int mode, | ||
1485 | const unsigned int dev) | ||
1486 | { | ||
1487 | int error; | ||
1488 | const unsigned int major = MAJOR(dev); | ||
1489 | const unsigned int minor = MINOR(dev); | ||
1490 | |||
1491 | error = tomoyo_path_number3_acl(r, filename, 1 << operation, mode, | ||
1492 | major, minor); | ||
1493 | if (!error) | ||
1494 | return 0; | ||
1495 | tomoyo_warn_log(r, "%s %s 0%o %u %u", | ||
1496 | tomoyo_path_number32keyword(operation), | ||
1497 | filename->name, mode, major, minor); | ||
1498 | if (tomoyo_domain_quota_is_ok(r)) { | ||
1499 | char mode_buf[64]; | ||
1500 | char major_buf[64]; | ||
1501 | char minor_buf[64]; | ||
1502 | memset(mode_buf, 0, sizeof(mode_buf)); | ||
1503 | memset(major_buf, 0, sizeof(major_buf)); | ||
1504 | memset(minor_buf, 0, sizeof(minor_buf)); | ||
1505 | snprintf(mode_buf, sizeof(mode_buf) - 1, "0%o", mode); | ||
1506 | snprintf(major_buf, sizeof(major_buf) - 1, "%u", major); | ||
1507 | snprintf(minor_buf, sizeof(minor_buf) - 1, "%u", minor); | ||
1508 | tomoyo_update_path_number3_acl(operation, | ||
1509 | tomoyo_get_file_pattern(filename) | ||
1510 | ->name, mode_buf, major_buf, | ||
1511 | minor_buf, r->domain, false); | ||
1512 | } | ||
1513 | if (r->mode != TOMOYO_CONFIG_ENFORCING) | ||
1514 | error = 0; | ||
1515 | return error; | ||
1516 | } | ||
1517 | |||
1518 | /** | ||
1519 | * tomoyo_path_number3_perm - Check permission for "mkblock" and "mkchar". | ||
1520 | * | ||
1521 | * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) | ||
1522 | * @path: Pointer to "struct path". | ||
1523 | * @mode: Create mode. | ||
1524 | * @dev: Device number. | ||
1525 | * | ||
1526 | * Returns 0 on success, negative value otherwise. | ||
1527 | */ | ||
1528 | int tomoyo_path_number3_perm(const u8 operation, struct path *path, | ||
1529 | const unsigned int mode, unsigned int dev) | ||
1530 | { | ||
1531 | struct tomoyo_request_info r; | ||
1532 | int error = -ENOMEM; | ||
1533 | struct tomoyo_path_info *buf; | ||
1534 | int idx; | ||
1535 | |||
1536 | if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || | ||
1537 | !path->mnt) | ||
1538 | return 0; | ||
1539 | idx = tomoyo_read_lock(); | ||
1540 | error = -ENOMEM; | ||
1541 | buf = tomoyo_get_path(path); | ||
1542 | if (buf) { | ||
1543 | error = tomoyo_path_number3_perm2(&r, operation, buf, mode, | ||
1544 | new_decode_dev(dev)); | ||
1545 | kfree(buf); | ||
1546 | } | ||
1547 | tomoyo_read_unlock(idx); | ||
1548 | if (r.mode != TOMOYO_CONFIG_ENFORCING) | ||
1549 | error = 0; | ||
1550 | return error; | ||
1551 | } | ||
1552 | |||
1553 | /** | ||
1197 | * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". | 1554 | * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". |
1198 | * | 1555 | * |
1199 | * @operation: Type of operation. | 1556 | * @operation: Type of operation. |
@@ -1254,3 +1611,60 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, | |||
1254 | error = 0; | 1611 | error = 0; |
1255 | return error; | 1612 | return error; |
1256 | } | 1613 | } |
1614 | |||
1615 | /** | ||
1616 | * tomoyo_write_file_policy - Update file related list. | ||
1617 | * | ||
1618 | * @data: String to parse. | ||
1619 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1620 | * @is_delete: True if it is a delete request. | ||
1621 | * | ||
1622 | * Returns 0 on success, negative value otherwise. | ||
1623 | * | ||
1624 | * Caller holds tomoyo_read_lock(). | ||
1625 | */ | ||
1626 | int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | ||
1627 | const bool is_delete) | ||
1628 | { | ||
1629 | char *w[5]; | ||
1630 | u8 type; | ||
1631 | if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) | ||
1632 | return -EINVAL; | ||
1633 | if (strncmp(w[0], "allow_", 6)) { | ||
1634 | unsigned int perm; | ||
1635 | if (sscanf(w[0], "%u", &perm) == 1) | ||
1636 | return tomoyo_update_file_acl((u8) perm, w[1], domain, | ||
1637 | is_delete); | ||
1638 | goto out; | ||
1639 | } | ||
1640 | w[0] += 6; | ||
1641 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { | ||
1642 | if (strcmp(w[0], tomoyo_path_keyword[type])) | ||
1643 | continue; | ||
1644 | return tomoyo_update_path_acl(type, w[1], domain, is_delete); | ||
1645 | } | ||
1646 | if (!w[2][0]) | ||
1647 | goto out; | ||
1648 | for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { | ||
1649 | if (strcmp(w[0], tomoyo_path2_keyword[type])) | ||
1650 | continue; | ||
1651 | return tomoyo_update_path2_acl(type, w[1], w[2], domain, | ||
1652 | is_delete); | ||
1653 | } | ||
1654 | for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) { | ||
1655 | if (strcmp(w[0], tomoyo_path_number_keyword[type])) | ||
1656 | continue; | ||
1657 | return tomoyo_update_path_number_acl(type, w[1], w[2], domain, | ||
1658 | is_delete); | ||
1659 | } | ||
1660 | if (!w[3][0] || !w[4][0]) | ||
1661 | goto out; | ||
1662 | for (type = 0; type < TOMOYO_MAX_PATH_NUMBER3_OPERATION; type++) { | ||
1663 | if (strcmp(w[0], tomoyo_path_number3_keyword[type])) | ||
1664 | continue; | ||
1665 | return tomoyo_update_path_number3_acl(type, w[1], w[2], w[3], | ||
1666 | w[4], domain, is_delete); | ||
1667 | } | ||
1668 | out: | ||
1669 | return -EINVAL; | ||
1670 | } | ||
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 6a48197f6ce5..78100180d23d 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -106,6 +106,24 @@ static void tomoyo_del_acl(struct tomoyo_acl_info *acl) | |||
106 | tomoyo_put_name_union(&entry->name2); | 106 | tomoyo_put_name_union(&entry->name2); |
107 | } | 107 | } |
108 | break; | 108 | break; |
109 | case TOMOYO_TYPE_PATH_NUMBER_ACL: | ||
110 | { | ||
111 | struct tomoyo_path_number_acl *entry | ||
112 | = container_of(acl, typeof(*entry), head); | ||
113 | tomoyo_put_name_union(&entry->name); | ||
114 | tomoyo_put_number_union(&entry->number); | ||
115 | } | ||
116 | break; | ||
117 | case TOMOYO_TYPE_PATH_NUMBER3_ACL: | ||
118 | { | ||
119 | struct tomoyo_path_number3_acl *entry | ||
120 | = container_of(acl, typeof(*entry), head); | ||
121 | tomoyo_put_name_union(&entry->name); | ||
122 | tomoyo_put_number_union(&entry->mode); | ||
123 | tomoyo_put_number_union(&entry->major); | ||
124 | tomoyo_put_number_union(&entry->minor); | ||
125 | } | ||
126 | break; | ||
109 | default: | 127 | default: |
110 | printk(KERN_WARNING "Unknown type\n"); | 128 | printk(KERN_WARNING "Unknown type\n"); |
111 | break; | 129 | break; |
@@ -268,10 +286,7 @@ static void tomoyo_collect_entry(void) | |||
268 | case TOMOYO_TYPE_PATH_ACL: | 286 | case TOMOYO_TYPE_PATH_ACL: |
269 | if (container_of(acl, | 287 | if (container_of(acl, |
270 | struct tomoyo_path_acl, | 288 | struct tomoyo_path_acl, |
271 | head)->perm || | 289 | head)->perm) |
272 | container_of(acl, | ||
273 | struct tomoyo_path_acl, | ||
274 | head)->perm_high) | ||
275 | continue; | 290 | continue; |
276 | break; | 291 | break; |
277 | case TOMOYO_TYPE_PATH2_ACL: | 292 | case TOMOYO_TYPE_PATH2_ACL: |
@@ -280,6 +295,18 @@ static void tomoyo_collect_entry(void) | |||
280 | head)->perm) | 295 | head)->perm) |
281 | continue; | 296 | continue; |
282 | break; | 297 | break; |
298 | case TOMOYO_TYPE_PATH_NUMBER_ACL: | ||
299 | if (container_of(acl, | ||
300 | struct tomoyo_path_number_acl, | ||
301 | head)->perm) | ||
302 | continue; | ||
303 | break; | ||
304 | case TOMOYO_TYPE_PATH_NUMBER3_ACL: | ||
305 | if (container_of(acl, | ||
306 | struct tomoyo_path_number3_acl, | ||
307 | head)->perm) | ||
308 | continue; | ||
309 | break; | ||
283 | default: | 310 | default: |
284 | continue; | 311 | continue; |
285 | } | 312 | } |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 4120f5a0e1bc..bbe00429b3f5 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -112,7 +112,8 @@ static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, | |||
112 | int mode) | 112 | int mode) |
113 | { | 113 | { |
114 | struct path path = { parent->mnt, dentry }; | 114 | struct path path = { parent->mnt, dentry }; |
115 | return tomoyo_path_perm(TOMOYO_TYPE_MKDIR, &path); | 115 | return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, |
116 | mode & S_IALLUGO); | ||
116 | } | 117 | } |
117 | 118 | ||
118 | static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) | 119 | static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) |
@@ -133,6 +134,7 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, | |||
133 | { | 134 | { |
134 | struct path path = { parent->mnt, dentry }; | 135 | struct path path = { parent->mnt, dentry }; |
135 | int type = TOMOYO_TYPE_CREATE; | 136 | int type = TOMOYO_TYPE_CREATE; |
137 | const unsigned int perm = mode & S_IALLUGO; | ||
136 | 138 | ||
137 | switch (mode & S_IFMT) { | 139 | switch (mode & S_IFMT) { |
138 | case S_IFCHR: | 140 | case S_IFCHR: |
@@ -141,6 +143,12 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, | |||
141 | case S_IFBLK: | 143 | case S_IFBLK: |
142 | type = TOMOYO_TYPE_MKBLOCK; | 144 | type = TOMOYO_TYPE_MKBLOCK; |
143 | break; | 145 | break; |
146 | default: | ||
147 | goto no_dev; | ||
148 | } | ||
149 | return tomoyo_path_number3_perm(type, &path, perm, dev); | ||
150 | no_dev: | ||
151 | switch (mode & S_IFMT) { | ||
144 | case S_IFIFO: | 152 | case S_IFIFO: |
145 | type = TOMOYO_TYPE_MKFIFO; | 153 | type = TOMOYO_TYPE_MKFIFO; |
146 | break; | 154 | break; |
@@ -148,7 +156,7 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, | |||
148 | type = TOMOYO_TYPE_MKSOCK; | 156 | type = TOMOYO_TYPE_MKSOCK; |
149 | break; | 157 | break; |
150 | } | 158 | } |
151 | return tomoyo_path_perm(type, &path); | 159 | return tomoyo_path_number_perm(type, &path, perm); |
152 | } | 160 | } |
153 | 161 | ||
154 | static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, | 162 | static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, |
@@ -189,23 +197,24 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred) | |||
189 | static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, | 197 | static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, |
190 | unsigned long arg) | 198 | unsigned long arg) |
191 | { | 199 | { |
192 | return tomoyo_path_perm(TOMOYO_TYPE_IOCTL, &file->f_path); | 200 | return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd); |
193 | } | 201 | } |
194 | 202 | ||
195 | static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, | 203 | static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, |
196 | mode_t mode) | 204 | mode_t mode) |
197 | { | 205 | { |
198 | struct path path = { mnt, dentry }; | 206 | struct path path = { mnt, dentry }; |
199 | return tomoyo_path_perm(TOMOYO_TYPE_CHMOD, &path); | 207 | return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, &path, |
208 | mode & S_IALLUGO); | ||
200 | } | 209 | } |
201 | 210 | ||
202 | static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) | 211 | static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) |
203 | { | 212 | { |
204 | int error = 0; | 213 | int error = 0; |
205 | if (uid != (uid_t) -1) | 214 | if (uid != (uid_t) -1) |
206 | error = tomoyo_path_perm(TOMOYO_TYPE_CHOWN, path); | 215 | error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, uid); |
207 | if (!error && gid != (gid_t) -1) | 216 | if (!error && gid != (gid_t) -1) |
208 | error = tomoyo_path_perm(TOMOYO_TYPE_CHGRP, path); | 217 | error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, gid); |
209 | return error; | 218 | return error; |
210 | } | 219 | } |
211 | 220 | ||