Commit 97fb35e413f256ded07b88c73b3d932ec31ea84e
Committed by
James Morris
1 parent
5b636857fe
Exists in
master
and in
4 other branches
TOMOYO: Enable conditional ACL.
Enable conditional ACL by passing object's pointers. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
Showing 5 changed files with 80 additions and 33 deletions Inline Diff
security/tomoyo/common.h
1 | /* | 1 | /* |
2 | * security/tomoyo/common.h | 2 | * security/tomoyo/common.h |
3 | * | 3 | * |
4 | * Header file for TOMOYO. | 4 | * Header file for TOMOYO. |
5 | * | 5 | * |
6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION | 6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifndef _SECURITY_TOMOYO_COMMON_H | 9 | #ifndef _SECURITY_TOMOYO_COMMON_H |
10 | #define _SECURITY_TOMOYO_COMMON_H | 10 | #define _SECURITY_TOMOYO_COMMON_H |
11 | 11 | ||
12 | #include <linux/ctype.h> | 12 | #include <linux/ctype.h> |
13 | #include <linux/string.h> | 13 | #include <linux/string.h> |
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/file.h> | 15 | #include <linux/file.h> |
16 | #include <linux/kmod.h> | 16 | #include <linux/kmod.h> |
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/namei.h> | 19 | #include <linux/namei.h> |
20 | #include <linux/mount.h> | 20 | #include <linux/mount.h> |
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/cred.h> | 22 | #include <linux/cred.h> |
23 | #include <linux/poll.h> | 23 | #include <linux/poll.h> |
24 | #include <linux/binfmts.h> | 24 | #include <linux/binfmts.h> |
25 | #include <linux/highmem.h> | 25 | #include <linux/highmem.h> |
26 | 26 | ||
27 | /********** Constants definitions. **********/ | 27 | /********** Constants definitions. **********/ |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * TOMOYO uses this hash only when appending a string into the string | 30 | * TOMOYO uses this hash only when appending a string into the string |
31 | * table. Frequency of appending strings is very low. So we don't need | 31 | * table. Frequency of appending strings is very low. So we don't need |
32 | * large (e.g. 64k) hash size. 256 will be sufficient. | 32 | * large (e.g. 64k) hash size. 256 will be sufficient. |
33 | */ | 33 | */ |
34 | #define TOMOYO_HASH_BITS 8 | 34 | #define TOMOYO_HASH_BITS 8 |
35 | #define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) | 35 | #define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) |
36 | 36 | ||
37 | #define TOMOYO_EXEC_TMPSIZE 4096 | 37 | #define TOMOYO_EXEC_TMPSIZE 4096 |
38 | 38 | ||
39 | /* Profile number is an integer between 0 and 255. */ | 39 | /* Profile number is an integer between 0 and 255. */ |
40 | #define TOMOYO_MAX_PROFILES 256 | 40 | #define TOMOYO_MAX_PROFILES 256 |
41 | 41 | ||
42 | /* Group number is an integer between 0 and 255. */ | 42 | /* Group number is an integer between 0 and 255. */ |
43 | #define TOMOYO_MAX_ACL_GROUPS 256 | 43 | #define TOMOYO_MAX_ACL_GROUPS 256 |
44 | 44 | ||
45 | /* Index numbers for "struct tomoyo_condition". */ | 45 | /* Index numbers for "struct tomoyo_condition". */ |
46 | enum tomoyo_conditions_index { | 46 | enum tomoyo_conditions_index { |
47 | TOMOYO_TASK_UID, /* current_uid() */ | 47 | TOMOYO_TASK_UID, /* current_uid() */ |
48 | TOMOYO_TASK_EUID, /* current_euid() */ | 48 | TOMOYO_TASK_EUID, /* current_euid() */ |
49 | TOMOYO_TASK_SUID, /* current_suid() */ | 49 | TOMOYO_TASK_SUID, /* current_suid() */ |
50 | TOMOYO_TASK_FSUID, /* current_fsuid() */ | 50 | TOMOYO_TASK_FSUID, /* current_fsuid() */ |
51 | TOMOYO_TASK_GID, /* current_gid() */ | 51 | TOMOYO_TASK_GID, /* current_gid() */ |
52 | TOMOYO_TASK_EGID, /* current_egid() */ | 52 | TOMOYO_TASK_EGID, /* current_egid() */ |
53 | TOMOYO_TASK_SGID, /* current_sgid() */ | 53 | TOMOYO_TASK_SGID, /* current_sgid() */ |
54 | TOMOYO_TASK_FSGID, /* current_fsgid() */ | 54 | TOMOYO_TASK_FSGID, /* current_fsgid() */ |
55 | TOMOYO_TASK_PID, /* sys_getpid() */ | 55 | TOMOYO_TASK_PID, /* sys_getpid() */ |
56 | TOMOYO_TASK_PPID, /* sys_getppid() */ | 56 | TOMOYO_TASK_PPID, /* sys_getppid() */ |
57 | TOMOYO_EXEC_ARGC, /* "struct linux_binprm *"->argc */ | 57 | TOMOYO_EXEC_ARGC, /* "struct linux_binprm *"->argc */ |
58 | TOMOYO_EXEC_ENVC, /* "struct linux_binprm *"->envc */ | 58 | TOMOYO_EXEC_ENVC, /* "struct linux_binprm *"->envc */ |
59 | TOMOYO_TYPE_IS_SOCKET, /* S_IFSOCK */ | 59 | TOMOYO_TYPE_IS_SOCKET, /* S_IFSOCK */ |
60 | TOMOYO_TYPE_IS_SYMLINK, /* S_IFLNK */ | 60 | TOMOYO_TYPE_IS_SYMLINK, /* S_IFLNK */ |
61 | TOMOYO_TYPE_IS_FILE, /* S_IFREG */ | 61 | TOMOYO_TYPE_IS_FILE, /* S_IFREG */ |
62 | TOMOYO_TYPE_IS_BLOCK_DEV, /* S_IFBLK */ | 62 | TOMOYO_TYPE_IS_BLOCK_DEV, /* S_IFBLK */ |
63 | TOMOYO_TYPE_IS_DIRECTORY, /* S_IFDIR */ | 63 | TOMOYO_TYPE_IS_DIRECTORY, /* S_IFDIR */ |
64 | TOMOYO_TYPE_IS_CHAR_DEV, /* S_IFCHR */ | 64 | TOMOYO_TYPE_IS_CHAR_DEV, /* S_IFCHR */ |
65 | TOMOYO_TYPE_IS_FIFO, /* S_IFIFO */ | 65 | TOMOYO_TYPE_IS_FIFO, /* S_IFIFO */ |
66 | TOMOYO_MODE_SETUID, /* S_ISUID */ | 66 | TOMOYO_MODE_SETUID, /* S_ISUID */ |
67 | TOMOYO_MODE_SETGID, /* S_ISGID */ | 67 | TOMOYO_MODE_SETGID, /* S_ISGID */ |
68 | TOMOYO_MODE_STICKY, /* S_ISVTX */ | 68 | TOMOYO_MODE_STICKY, /* S_ISVTX */ |
69 | TOMOYO_MODE_OWNER_READ, /* S_IRUSR */ | 69 | TOMOYO_MODE_OWNER_READ, /* S_IRUSR */ |
70 | TOMOYO_MODE_OWNER_WRITE, /* S_IWUSR */ | 70 | TOMOYO_MODE_OWNER_WRITE, /* S_IWUSR */ |
71 | TOMOYO_MODE_OWNER_EXECUTE, /* S_IXUSR */ | 71 | TOMOYO_MODE_OWNER_EXECUTE, /* S_IXUSR */ |
72 | TOMOYO_MODE_GROUP_READ, /* S_IRGRP */ | 72 | TOMOYO_MODE_GROUP_READ, /* S_IRGRP */ |
73 | TOMOYO_MODE_GROUP_WRITE, /* S_IWGRP */ | 73 | TOMOYO_MODE_GROUP_WRITE, /* S_IWGRP */ |
74 | TOMOYO_MODE_GROUP_EXECUTE, /* S_IXGRP */ | 74 | TOMOYO_MODE_GROUP_EXECUTE, /* S_IXGRP */ |
75 | TOMOYO_MODE_OTHERS_READ, /* S_IROTH */ | 75 | TOMOYO_MODE_OTHERS_READ, /* S_IROTH */ |
76 | TOMOYO_MODE_OTHERS_WRITE, /* S_IWOTH */ | 76 | TOMOYO_MODE_OTHERS_WRITE, /* S_IWOTH */ |
77 | TOMOYO_MODE_OTHERS_EXECUTE, /* S_IXOTH */ | 77 | TOMOYO_MODE_OTHERS_EXECUTE, /* S_IXOTH */ |
78 | TOMOYO_EXEC_REALPATH, | 78 | TOMOYO_EXEC_REALPATH, |
79 | TOMOYO_SYMLINK_TARGET, | 79 | TOMOYO_SYMLINK_TARGET, |
80 | TOMOYO_PATH1_UID, | 80 | TOMOYO_PATH1_UID, |
81 | TOMOYO_PATH1_GID, | 81 | TOMOYO_PATH1_GID, |
82 | TOMOYO_PATH1_INO, | 82 | TOMOYO_PATH1_INO, |
83 | TOMOYO_PATH1_MAJOR, | 83 | TOMOYO_PATH1_MAJOR, |
84 | TOMOYO_PATH1_MINOR, | 84 | TOMOYO_PATH1_MINOR, |
85 | TOMOYO_PATH1_PERM, | 85 | TOMOYO_PATH1_PERM, |
86 | TOMOYO_PATH1_TYPE, | 86 | TOMOYO_PATH1_TYPE, |
87 | TOMOYO_PATH1_DEV_MAJOR, | 87 | TOMOYO_PATH1_DEV_MAJOR, |
88 | TOMOYO_PATH1_DEV_MINOR, | 88 | TOMOYO_PATH1_DEV_MINOR, |
89 | TOMOYO_PATH2_UID, | 89 | TOMOYO_PATH2_UID, |
90 | TOMOYO_PATH2_GID, | 90 | TOMOYO_PATH2_GID, |
91 | TOMOYO_PATH2_INO, | 91 | TOMOYO_PATH2_INO, |
92 | TOMOYO_PATH2_MAJOR, | 92 | TOMOYO_PATH2_MAJOR, |
93 | TOMOYO_PATH2_MINOR, | 93 | TOMOYO_PATH2_MINOR, |
94 | TOMOYO_PATH2_PERM, | 94 | TOMOYO_PATH2_PERM, |
95 | TOMOYO_PATH2_TYPE, | 95 | TOMOYO_PATH2_TYPE, |
96 | TOMOYO_PATH2_DEV_MAJOR, | 96 | TOMOYO_PATH2_DEV_MAJOR, |
97 | TOMOYO_PATH2_DEV_MINOR, | 97 | TOMOYO_PATH2_DEV_MINOR, |
98 | TOMOYO_PATH1_PARENT_UID, | 98 | TOMOYO_PATH1_PARENT_UID, |
99 | TOMOYO_PATH1_PARENT_GID, | 99 | TOMOYO_PATH1_PARENT_GID, |
100 | TOMOYO_PATH1_PARENT_INO, | 100 | TOMOYO_PATH1_PARENT_INO, |
101 | TOMOYO_PATH1_PARENT_PERM, | 101 | TOMOYO_PATH1_PARENT_PERM, |
102 | TOMOYO_PATH2_PARENT_UID, | 102 | TOMOYO_PATH2_PARENT_UID, |
103 | TOMOYO_PATH2_PARENT_GID, | 103 | TOMOYO_PATH2_PARENT_GID, |
104 | TOMOYO_PATH2_PARENT_INO, | 104 | TOMOYO_PATH2_PARENT_INO, |
105 | TOMOYO_PATH2_PARENT_PERM, | 105 | TOMOYO_PATH2_PARENT_PERM, |
106 | TOMOYO_MAX_CONDITION_KEYWORD, | 106 | TOMOYO_MAX_CONDITION_KEYWORD, |
107 | TOMOYO_NUMBER_UNION, | 107 | TOMOYO_NUMBER_UNION, |
108 | TOMOYO_NAME_UNION, | 108 | TOMOYO_NAME_UNION, |
109 | TOMOYO_ARGV_ENTRY, | 109 | TOMOYO_ARGV_ENTRY, |
110 | TOMOYO_ENVP_ENTRY, | 110 | TOMOYO_ENVP_ENTRY, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | 113 | ||
114 | /* Index numbers for stat(). */ | 114 | /* Index numbers for stat(). */ |
115 | enum tomoyo_path_stat_index { | 115 | enum tomoyo_path_stat_index { |
116 | /* Do not change this order. */ | 116 | /* Do not change this order. */ |
117 | TOMOYO_PATH1, | 117 | TOMOYO_PATH1, |
118 | TOMOYO_PATH1_PARENT, | 118 | TOMOYO_PATH1_PARENT, |
119 | TOMOYO_PATH2, | 119 | TOMOYO_PATH2, |
120 | TOMOYO_PATH2_PARENT, | 120 | TOMOYO_PATH2_PARENT, |
121 | TOMOYO_MAX_PATH_STAT | 121 | TOMOYO_MAX_PATH_STAT |
122 | }; | 122 | }; |
123 | 123 | ||
124 | /* Index numbers for operation mode. */ | 124 | /* Index numbers for operation mode. */ |
125 | enum tomoyo_mode_index { | 125 | enum tomoyo_mode_index { |
126 | TOMOYO_CONFIG_DISABLED, | 126 | TOMOYO_CONFIG_DISABLED, |
127 | TOMOYO_CONFIG_LEARNING, | 127 | TOMOYO_CONFIG_LEARNING, |
128 | TOMOYO_CONFIG_PERMISSIVE, | 128 | TOMOYO_CONFIG_PERMISSIVE, |
129 | TOMOYO_CONFIG_ENFORCING, | 129 | TOMOYO_CONFIG_ENFORCING, |
130 | TOMOYO_CONFIG_MAX_MODE, | 130 | TOMOYO_CONFIG_MAX_MODE, |
131 | TOMOYO_CONFIG_WANT_REJECT_LOG = 64, | 131 | TOMOYO_CONFIG_WANT_REJECT_LOG = 64, |
132 | TOMOYO_CONFIG_WANT_GRANT_LOG = 128, | 132 | TOMOYO_CONFIG_WANT_GRANT_LOG = 128, |
133 | TOMOYO_CONFIG_USE_DEFAULT = 255, | 133 | TOMOYO_CONFIG_USE_DEFAULT = 255, |
134 | }; | 134 | }; |
135 | 135 | ||
136 | /* Index numbers for entry type. */ | 136 | /* Index numbers for entry type. */ |
137 | enum tomoyo_policy_id { | 137 | enum tomoyo_policy_id { |
138 | TOMOYO_ID_GROUP, | 138 | TOMOYO_ID_GROUP, |
139 | TOMOYO_ID_PATH_GROUP, | 139 | TOMOYO_ID_PATH_GROUP, |
140 | TOMOYO_ID_NUMBER_GROUP, | 140 | TOMOYO_ID_NUMBER_GROUP, |
141 | TOMOYO_ID_TRANSITION_CONTROL, | 141 | TOMOYO_ID_TRANSITION_CONTROL, |
142 | TOMOYO_ID_AGGREGATOR, | 142 | TOMOYO_ID_AGGREGATOR, |
143 | TOMOYO_ID_MANAGER, | 143 | TOMOYO_ID_MANAGER, |
144 | TOMOYO_ID_CONDITION, | 144 | TOMOYO_ID_CONDITION, |
145 | TOMOYO_ID_NAME, | 145 | TOMOYO_ID_NAME, |
146 | TOMOYO_ID_ACL, | 146 | TOMOYO_ID_ACL, |
147 | TOMOYO_ID_DOMAIN, | 147 | TOMOYO_ID_DOMAIN, |
148 | TOMOYO_MAX_POLICY | 148 | TOMOYO_MAX_POLICY |
149 | }; | 149 | }; |
150 | 150 | ||
151 | /* Index numbers for domain's attributes. */ | 151 | /* Index numbers for domain's attributes. */ |
152 | enum tomoyo_domain_info_flags_index { | 152 | enum tomoyo_domain_info_flags_index { |
153 | /* Quota warnning flag. */ | 153 | /* Quota warnning flag. */ |
154 | TOMOYO_DIF_QUOTA_WARNED, | 154 | TOMOYO_DIF_QUOTA_WARNED, |
155 | /* | 155 | /* |
156 | * This domain was unable to create a new domain at | 156 | * This domain was unable to create a new domain at |
157 | * tomoyo_find_next_domain() because the name of the domain to be | 157 | * tomoyo_find_next_domain() because the name of the domain to be |
158 | * created was too long or it could not allocate memory. | 158 | * created was too long or it could not allocate memory. |
159 | * More than one process continued execve() without domain transition. | 159 | * More than one process continued execve() without domain transition. |
160 | */ | 160 | */ |
161 | TOMOYO_DIF_TRANSITION_FAILED, | 161 | TOMOYO_DIF_TRANSITION_FAILED, |
162 | TOMOYO_MAX_DOMAIN_INFO_FLAGS | 162 | TOMOYO_MAX_DOMAIN_INFO_FLAGS |
163 | }; | 163 | }; |
164 | 164 | ||
165 | /* Index numbers for group entries. */ | 165 | /* Index numbers for group entries. */ |
166 | enum tomoyo_group_id { | 166 | enum tomoyo_group_id { |
167 | TOMOYO_PATH_GROUP, | 167 | TOMOYO_PATH_GROUP, |
168 | TOMOYO_NUMBER_GROUP, | 168 | TOMOYO_NUMBER_GROUP, |
169 | TOMOYO_MAX_GROUP | 169 | TOMOYO_MAX_GROUP |
170 | }; | 170 | }; |
171 | 171 | ||
172 | /* Index numbers for type of numeric values. */ | 172 | /* Index numbers for type of numeric values. */ |
173 | enum tomoyo_value_type { | 173 | enum tomoyo_value_type { |
174 | TOMOYO_VALUE_TYPE_INVALID, | 174 | TOMOYO_VALUE_TYPE_INVALID, |
175 | TOMOYO_VALUE_TYPE_DECIMAL, | 175 | TOMOYO_VALUE_TYPE_DECIMAL, |
176 | TOMOYO_VALUE_TYPE_OCTAL, | 176 | TOMOYO_VALUE_TYPE_OCTAL, |
177 | TOMOYO_VALUE_TYPE_HEXADECIMAL, | 177 | TOMOYO_VALUE_TYPE_HEXADECIMAL, |
178 | }; | 178 | }; |
179 | 179 | ||
180 | /* Index numbers for domain transition control keywords. */ | 180 | /* Index numbers for domain transition control keywords. */ |
181 | enum tomoyo_transition_type { | 181 | enum tomoyo_transition_type { |
182 | /* Do not change this order, */ | 182 | /* Do not change this order, */ |
183 | TOMOYO_TRANSITION_CONTROL_NO_RESET, | 183 | TOMOYO_TRANSITION_CONTROL_NO_RESET, |
184 | TOMOYO_TRANSITION_CONTROL_RESET, | 184 | TOMOYO_TRANSITION_CONTROL_RESET, |
185 | TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE, | 185 | TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE, |
186 | TOMOYO_TRANSITION_CONTROL_INITIALIZE, | 186 | TOMOYO_TRANSITION_CONTROL_INITIALIZE, |
187 | TOMOYO_TRANSITION_CONTROL_NO_KEEP, | 187 | TOMOYO_TRANSITION_CONTROL_NO_KEEP, |
188 | TOMOYO_TRANSITION_CONTROL_KEEP, | 188 | TOMOYO_TRANSITION_CONTROL_KEEP, |
189 | TOMOYO_MAX_TRANSITION_TYPE | 189 | TOMOYO_MAX_TRANSITION_TYPE |
190 | }; | 190 | }; |
191 | 191 | ||
192 | /* Index numbers for Access Controls. */ | 192 | /* Index numbers for Access Controls. */ |
193 | enum tomoyo_acl_entry_type_index { | 193 | enum tomoyo_acl_entry_type_index { |
194 | TOMOYO_TYPE_PATH_ACL, | 194 | TOMOYO_TYPE_PATH_ACL, |
195 | TOMOYO_TYPE_PATH2_ACL, | 195 | TOMOYO_TYPE_PATH2_ACL, |
196 | TOMOYO_TYPE_PATH_NUMBER_ACL, | 196 | TOMOYO_TYPE_PATH_NUMBER_ACL, |
197 | TOMOYO_TYPE_MKDEV_ACL, | 197 | TOMOYO_TYPE_MKDEV_ACL, |
198 | TOMOYO_TYPE_MOUNT_ACL, | 198 | TOMOYO_TYPE_MOUNT_ACL, |
199 | }; | 199 | }; |
200 | 200 | ||
201 | /* Index numbers for access controls with one pathname. */ | 201 | /* Index numbers for access controls with one pathname. */ |
202 | enum tomoyo_path_acl_index { | 202 | enum tomoyo_path_acl_index { |
203 | TOMOYO_TYPE_EXECUTE, | 203 | TOMOYO_TYPE_EXECUTE, |
204 | TOMOYO_TYPE_READ, | 204 | TOMOYO_TYPE_READ, |
205 | TOMOYO_TYPE_WRITE, | 205 | TOMOYO_TYPE_WRITE, |
206 | TOMOYO_TYPE_APPEND, | 206 | TOMOYO_TYPE_APPEND, |
207 | TOMOYO_TYPE_UNLINK, | 207 | TOMOYO_TYPE_UNLINK, |
208 | TOMOYO_TYPE_GETATTR, | 208 | TOMOYO_TYPE_GETATTR, |
209 | TOMOYO_TYPE_RMDIR, | 209 | TOMOYO_TYPE_RMDIR, |
210 | TOMOYO_TYPE_TRUNCATE, | 210 | TOMOYO_TYPE_TRUNCATE, |
211 | TOMOYO_TYPE_SYMLINK, | 211 | TOMOYO_TYPE_SYMLINK, |
212 | TOMOYO_TYPE_CHROOT, | 212 | TOMOYO_TYPE_CHROOT, |
213 | TOMOYO_TYPE_UMOUNT, | 213 | TOMOYO_TYPE_UMOUNT, |
214 | TOMOYO_MAX_PATH_OPERATION | 214 | TOMOYO_MAX_PATH_OPERATION |
215 | }; | 215 | }; |
216 | 216 | ||
217 | /* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ | 217 | /* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ |
218 | enum tomoyo_memory_stat_type { | 218 | enum tomoyo_memory_stat_type { |
219 | TOMOYO_MEMORY_POLICY, | 219 | TOMOYO_MEMORY_POLICY, |
220 | TOMOYO_MEMORY_AUDIT, | 220 | TOMOYO_MEMORY_AUDIT, |
221 | TOMOYO_MEMORY_QUERY, | 221 | TOMOYO_MEMORY_QUERY, |
222 | TOMOYO_MAX_MEMORY_STAT | 222 | TOMOYO_MAX_MEMORY_STAT |
223 | }; | 223 | }; |
224 | 224 | ||
225 | enum tomoyo_mkdev_acl_index { | 225 | enum tomoyo_mkdev_acl_index { |
226 | TOMOYO_TYPE_MKBLOCK, | 226 | TOMOYO_TYPE_MKBLOCK, |
227 | TOMOYO_TYPE_MKCHAR, | 227 | TOMOYO_TYPE_MKCHAR, |
228 | TOMOYO_MAX_MKDEV_OPERATION | 228 | TOMOYO_MAX_MKDEV_OPERATION |
229 | }; | 229 | }; |
230 | 230 | ||
231 | /* Index numbers for access controls with two pathnames. */ | 231 | /* Index numbers for access controls with two pathnames. */ |
232 | enum tomoyo_path2_acl_index { | 232 | enum tomoyo_path2_acl_index { |
233 | TOMOYO_TYPE_LINK, | 233 | TOMOYO_TYPE_LINK, |
234 | TOMOYO_TYPE_RENAME, | 234 | TOMOYO_TYPE_RENAME, |
235 | TOMOYO_TYPE_PIVOT_ROOT, | 235 | TOMOYO_TYPE_PIVOT_ROOT, |
236 | TOMOYO_MAX_PATH2_OPERATION | 236 | TOMOYO_MAX_PATH2_OPERATION |
237 | }; | 237 | }; |
238 | 238 | ||
239 | /* Index numbers for access controls with one pathname and one number. */ | 239 | /* Index numbers for access controls with one pathname and one number. */ |
240 | enum tomoyo_path_number_acl_index { | 240 | enum tomoyo_path_number_acl_index { |
241 | TOMOYO_TYPE_CREATE, | 241 | TOMOYO_TYPE_CREATE, |
242 | TOMOYO_TYPE_MKDIR, | 242 | TOMOYO_TYPE_MKDIR, |
243 | TOMOYO_TYPE_MKFIFO, | 243 | TOMOYO_TYPE_MKFIFO, |
244 | TOMOYO_TYPE_MKSOCK, | 244 | TOMOYO_TYPE_MKSOCK, |
245 | TOMOYO_TYPE_IOCTL, | 245 | TOMOYO_TYPE_IOCTL, |
246 | TOMOYO_TYPE_CHMOD, | 246 | TOMOYO_TYPE_CHMOD, |
247 | TOMOYO_TYPE_CHOWN, | 247 | TOMOYO_TYPE_CHOWN, |
248 | TOMOYO_TYPE_CHGRP, | 248 | TOMOYO_TYPE_CHGRP, |
249 | TOMOYO_MAX_PATH_NUMBER_OPERATION | 249 | TOMOYO_MAX_PATH_NUMBER_OPERATION |
250 | }; | 250 | }; |
251 | 251 | ||
252 | /* Index numbers for /sys/kernel/security/tomoyo/ interfaces. */ | 252 | /* Index numbers for /sys/kernel/security/tomoyo/ interfaces. */ |
253 | enum tomoyo_securityfs_interface_index { | 253 | enum tomoyo_securityfs_interface_index { |
254 | TOMOYO_DOMAINPOLICY, | 254 | TOMOYO_DOMAINPOLICY, |
255 | TOMOYO_EXCEPTIONPOLICY, | 255 | TOMOYO_EXCEPTIONPOLICY, |
256 | TOMOYO_PROCESS_STATUS, | 256 | TOMOYO_PROCESS_STATUS, |
257 | TOMOYO_STAT, | 257 | TOMOYO_STAT, |
258 | TOMOYO_SELFDOMAIN, | 258 | TOMOYO_SELFDOMAIN, |
259 | TOMOYO_AUDIT, | 259 | TOMOYO_AUDIT, |
260 | TOMOYO_VERSION, | 260 | TOMOYO_VERSION, |
261 | TOMOYO_PROFILE, | 261 | TOMOYO_PROFILE, |
262 | TOMOYO_QUERY, | 262 | TOMOYO_QUERY, |
263 | TOMOYO_MANAGER | 263 | TOMOYO_MANAGER |
264 | }; | 264 | }; |
265 | 265 | ||
266 | /* Index numbers for special mount operations. */ | 266 | /* Index numbers for special mount operations. */ |
267 | enum tomoyo_special_mount { | 267 | enum tomoyo_special_mount { |
268 | TOMOYO_MOUNT_BIND, /* mount --bind /source /dest */ | 268 | TOMOYO_MOUNT_BIND, /* mount --bind /source /dest */ |
269 | TOMOYO_MOUNT_MOVE, /* mount --move /old /new */ | 269 | TOMOYO_MOUNT_MOVE, /* mount --move /old /new */ |
270 | TOMOYO_MOUNT_REMOUNT, /* mount -o remount /dir */ | 270 | TOMOYO_MOUNT_REMOUNT, /* mount -o remount /dir */ |
271 | TOMOYO_MOUNT_MAKE_UNBINDABLE, /* mount --make-unbindable /dir */ | 271 | TOMOYO_MOUNT_MAKE_UNBINDABLE, /* mount --make-unbindable /dir */ |
272 | TOMOYO_MOUNT_MAKE_PRIVATE, /* mount --make-private /dir */ | 272 | TOMOYO_MOUNT_MAKE_PRIVATE, /* mount --make-private /dir */ |
273 | TOMOYO_MOUNT_MAKE_SLAVE, /* mount --make-slave /dir */ | 273 | TOMOYO_MOUNT_MAKE_SLAVE, /* mount --make-slave /dir */ |
274 | TOMOYO_MOUNT_MAKE_SHARED, /* mount --make-shared /dir */ | 274 | TOMOYO_MOUNT_MAKE_SHARED, /* mount --make-shared /dir */ |
275 | TOMOYO_MAX_SPECIAL_MOUNT | 275 | TOMOYO_MAX_SPECIAL_MOUNT |
276 | }; | 276 | }; |
277 | 277 | ||
278 | /* Index numbers for functionality. */ | 278 | /* Index numbers for functionality. */ |
279 | enum tomoyo_mac_index { | 279 | enum tomoyo_mac_index { |
280 | TOMOYO_MAC_FILE_EXECUTE, | 280 | TOMOYO_MAC_FILE_EXECUTE, |
281 | TOMOYO_MAC_FILE_OPEN, | 281 | TOMOYO_MAC_FILE_OPEN, |
282 | TOMOYO_MAC_FILE_CREATE, | 282 | TOMOYO_MAC_FILE_CREATE, |
283 | TOMOYO_MAC_FILE_UNLINK, | 283 | TOMOYO_MAC_FILE_UNLINK, |
284 | TOMOYO_MAC_FILE_GETATTR, | 284 | TOMOYO_MAC_FILE_GETATTR, |
285 | TOMOYO_MAC_FILE_MKDIR, | 285 | TOMOYO_MAC_FILE_MKDIR, |
286 | TOMOYO_MAC_FILE_RMDIR, | 286 | TOMOYO_MAC_FILE_RMDIR, |
287 | TOMOYO_MAC_FILE_MKFIFO, | 287 | TOMOYO_MAC_FILE_MKFIFO, |
288 | TOMOYO_MAC_FILE_MKSOCK, | 288 | TOMOYO_MAC_FILE_MKSOCK, |
289 | TOMOYO_MAC_FILE_TRUNCATE, | 289 | TOMOYO_MAC_FILE_TRUNCATE, |
290 | TOMOYO_MAC_FILE_SYMLINK, | 290 | TOMOYO_MAC_FILE_SYMLINK, |
291 | TOMOYO_MAC_FILE_MKBLOCK, | 291 | TOMOYO_MAC_FILE_MKBLOCK, |
292 | TOMOYO_MAC_FILE_MKCHAR, | 292 | TOMOYO_MAC_FILE_MKCHAR, |
293 | TOMOYO_MAC_FILE_LINK, | 293 | TOMOYO_MAC_FILE_LINK, |
294 | TOMOYO_MAC_FILE_RENAME, | 294 | TOMOYO_MAC_FILE_RENAME, |
295 | TOMOYO_MAC_FILE_CHMOD, | 295 | TOMOYO_MAC_FILE_CHMOD, |
296 | TOMOYO_MAC_FILE_CHOWN, | 296 | TOMOYO_MAC_FILE_CHOWN, |
297 | TOMOYO_MAC_FILE_CHGRP, | 297 | TOMOYO_MAC_FILE_CHGRP, |
298 | TOMOYO_MAC_FILE_IOCTL, | 298 | TOMOYO_MAC_FILE_IOCTL, |
299 | TOMOYO_MAC_FILE_CHROOT, | 299 | TOMOYO_MAC_FILE_CHROOT, |
300 | TOMOYO_MAC_FILE_MOUNT, | 300 | TOMOYO_MAC_FILE_MOUNT, |
301 | TOMOYO_MAC_FILE_UMOUNT, | 301 | TOMOYO_MAC_FILE_UMOUNT, |
302 | TOMOYO_MAC_FILE_PIVOT_ROOT, | 302 | TOMOYO_MAC_FILE_PIVOT_ROOT, |
303 | TOMOYO_MAX_MAC_INDEX | 303 | TOMOYO_MAX_MAC_INDEX |
304 | }; | 304 | }; |
305 | 305 | ||
306 | /* Index numbers for category of functionality. */ | 306 | /* Index numbers for category of functionality. */ |
307 | enum tomoyo_mac_category_index { | 307 | enum tomoyo_mac_category_index { |
308 | TOMOYO_MAC_CATEGORY_FILE, | 308 | TOMOYO_MAC_CATEGORY_FILE, |
309 | TOMOYO_MAX_MAC_CATEGORY_INDEX | 309 | TOMOYO_MAX_MAC_CATEGORY_INDEX |
310 | }; | 310 | }; |
311 | 311 | ||
312 | /* | 312 | /* |
313 | * Retry this request. Returned by tomoyo_supervisor() if policy violation has | 313 | * Retry this request. Returned by tomoyo_supervisor() if policy violation has |
314 | * occurred in enforcing mode and the userspace daemon decided to retry. | 314 | * occurred in enforcing mode and the userspace daemon decided to retry. |
315 | * | 315 | * |
316 | * We must choose a positive value in order to distinguish "granted" (which is | 316 | * We must choose a positive value in order to distinguish "granted" (which is |
317 | * 0) and "rejected" (which is a negative value) and "retry". | 317 | * 0) and "rejected" (which is a negative value) and "retry". |
318 | */ | 318 | */ |
319 | #define TOMOYO_RETRY_REQUEST 1 | 319 | #define TOMOYO_RETRY_REQUEST 1 |
320 | 320 | ||
321 | /* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ | 321 | /* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ |
322 | enum tomoyo_policy_stat_type { | 322 | enum tomoyo_policy_stat_type { |
323 | /* Do not change this order. */ | 323 | /* Do not change this order. */ |
324 | TOMOYO_STAT_POLICY_UPDATES, | 324 | TOMOYO_STAT_POLICY_UPDATES, |
325 | TOMOYO_STAT_POLICY_LEARNING, /* == TOMOYO_CONFIG_LEARNING */ | 325 | TOMOYO_STAT_POLICY_LEARNING, /* == TOMOYO_CONFIG_LEARNING */ |
326 | TOMOYO_STAT_POLICY_PERMISSIVE, /* == TOMOYO_CONFIG_PERMISSIVE */ | 326 | TOMOYO_STAT_POLICY_PERMISSIVE, /* == TOMOYO_CONFIG_PERMISSIVE */ |
327 | TOMOYO_STAT_POLICY_ENFORCING, /* == TOMOYO_CONFIG_ENFORCING */ | 327 | TOMOYO_STAT_POLICY_ENFORCING, /* == TOMOYO_CONFIG_ENFORCING */ |
328 | TOMOYO_MAX_POLICY_STAT | 328 | TOMOYO_MAX_POLICY_STAT |
329 | }; | 329 | }; |
330 | 330 | ||
331 | /* Index numbers for profile's PREFERENCE values. */ | 331 | /* Index numbers for profile's PREFERENCE values. */ |
332 | enum tomoyo_pref_index { | 332 | enum tomoyo_pref_index { |
333 | TOMOYO_PREF_MAX_AUDIT_LOG, | 333 | TOMOYO_PREF_MAX_AUDIT_LOG, |
334 | TOMOYO_PREF_MAX_LEARNING_ENTRY, | 334 | TOMOYO_PREF_MAX_LEARNING_ENTRY, |
335 | TOMOYO_MAX_PREF | 335 | TOMOYO_MAX_PREF |
336 | }; | 336 | }; |
337 | 337 | ||
338 | /********** Structure definitions. **********/ | 338 | /********** Structure definitions. **********/ |
339 | 339 | ||
340 | /* Common header for holding ACL entries. */ | 340 | /* Common header for holding ACL entries. */ |
341 | struct tomoyo_acl_head { | 341 | struct tomoyo_acl_head { |
342 | struct list_head list; | 342 | struct list_head list; |
343 | bool is_deleted; | 343 | bool is_deleted; |
344 | } __packed; | 344 | } __packed; |
345 | 345 | ||
346 | /* Common header for shared entries. */ | 346 | /* Common header for shared entries. */ |
347 | struct tomoyo_shared_acl_head { | 347 | struct tomoyo_shared_acl_head { |
348 | struct list_head list; | 348 | struct list_head list; |
349 | atomic_t users; | 349 | atomic_t users; |
350 | } __packed; | 350 | } __packed; |
351 | 351 | ||
352 | struct tomoyo_policy_namespace; | 352 | struct tomoyo_policy_namespace; |
353 | 353 | ||
354 | /* Structure for request info. */ | 354 | /* Structure for request info. */ |
355 | struct tomoyo_request_info { | 355 | struct tomoyo_request_info { |
356 | /* | 356 | /* |
357 | * For holding parameters specific to operations which deal files. | 357 | * For holding parameters specific to operations which deal files. |
358 | * NULL if not dealing files. | 358 | * NULL if not dealing files. |
359 | */ | 359 | */ |
360 | struct tomoyo_obj_info *obj; | 360 | struct tomoyo_obj_info *obj; |
361 | /* | 361 | /* |
362 | * For holding parameters specific to execve() request. | 362 | * For holding parameters specific to execve() request. |
363 | * NULL if not dealing do_execve(). | 363 | * NULL if not dealing do_execve(). |
364 | */ | 364 | */ |
365 | struct tomoyo_execve *ee; | 365 | struct tomoyo_execve *ee; |
366 | struct tomoyo_domain_info *domain; | 366 | struct tomoyo_domain_info *domain; |
367 | /* For holding parameters. */ | 367 | /* For holding parameters. */ |
368 | union { | 368 | union { |
369 | struct { | 369 | struct { |
370 | const struct tomoyo_path_info *filename; | 370 | const struct tomoyo_path_info *filename; |
371 | /* For using wildcards at tomoyo_find_next_domain(). */ | 371 | /* For using wildcards at tomoyo_find_next_domain(). */ |
372 | const struct tomoyo_path_info *matched_path; | 372 | const struct tomoyo_path_info *matched_path; |
373 | /* One of values in "enum tomoyo_path_acl_index". */ | 373 | /* One of values in "enum tomoyo_path_acl_index". */ |
374 | u8 operation; | 374 | u8 operation; |
375 | } path; | 375 | } path; |
376 | struct { | 376 | struct { |
377 | const struct tomoyo_path_info *filename1; | 377 | const struct tomoyo_path_info *filename1; |
378 | const struct tomoyo_path_info *filename2; | 378 | const struct tomoyo_path_info *filename2; |
379 | /* One of values in "enum tomoyo_path2_acl_index". */ | 379 | /* One of values in "enum tomoyo_path2_acl_index". */ |
380 | u8 operation; | 380 | u8 operation; |
381 | } path2; | 381 | } path2; |
382 | struct { | 382 | struct { |
383 | const struct tomoyo_path_info *filename; | 383 | const struct tomoyo_path_info *filename; |
384 | unsigned int mode; | 384 | unsigned int mode; |
385 | unsigned int major; | 385 | unsigned int major; |
386 | unsigned int minor; | 386 | unsigned int minor; |
387 | /* One of values in "enum tomoyo_mkdev_acl_index". */ | 387 | /* One of values in "enum tomoyo_mkdev_acl_index". */ |
388 | u8 operation; | 388 | u8 operation; |
389 | } mkdev; | 389 | } mkdev; |
390 | struct { | 390 | struct { |
391 | const struct tomoyo_path_info *filename; | 391 | const struct tomoyo_path_info *filename; |
392 | unsigned long number; | 392 | unsigned long number; |
393 | /* | 393 | /* |
394 | * One of values in | 394 | * One of values in |
395 | * "enum tomoyo_path_number_acl_index". | 395 | * "enum tomoyo_path_number_acl_index". |
396 | */ | 396 | */ |
397 | u8 operation; | 397 | u8 operation; |
398 | } path_number; | 398 | } path_number; |
399 | struct { | 399 | struct { |
400 | const struct tomoyo_path_info *type; | 400 | const struct tomoyo_path_info *type; |
401 | const struct tomoyo_path_info *dir; | 401 | const struct tomoyo_path_info *dir; |
402 | const struct tomoyo_path_info *dev; | 402 | const struct tomoyo_path_info *dev; |
403 | unsigned long flags; | 403 | unsigned long flags; |
404 | int need_dev; | 404 | int need_dev; |
405 | } mount; | 405 | } mount; |
406 | } param; | 406 | } param; |
407 | u8 param_type; | 407 | u8 param_type; |
408 | bool granted; | 408 | bool granted; |
409 | u8 retry; | 409 | u8 retry; |
410 | u8 profile; | 410 | u8 profile; |
411 | u8 mode; /* One of tomoyo_mode_index . */ | 411 | u8 mode; /* One of tomoyo_mode_index . */ |
412 | u8 type; | 412 | u8 type; |
413 | }; | 413 | }; |
414 | 414 | ||
415 | /* Structure for holding a token. */ | 415 | /* Structure for holding a token. */ |
416 | struct tomoyo_path_info { | 416 | struct tomoyo_path_info { |
417 | const char *name; | 417 | const char *name; |
418 | u32 hash; /* = full_name_hash(name, strlen(name)) */ | 418 | u32 hash; /* = full_name_hash(name, strlen(name)) */ |
419 | u16 const_len; /* = tomoyo_const_part_length(name) */ | 419 | u16 const_len; /* = tomoyo_const_part_length(name) */ |
420 | bool is_dir; /* = tomoyo_strendswith(name, "/") */ | 420 | bool is_dir; /* = tomoyo_strendswith(name, "/") */ |
421 | bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ | 421 | bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ |
422 | }; | 422 | }; |
423 | 423 | ||
424 | /* Structure for holding string data. */ | 424 | /* Structure for holding string data. */ |
425 | struct tomoyo_name { | 425 | struct tomoyo_name { |
426 | struct tomoyo_shared_acl_head head; | 426 | struct tomoyo_shared_acl_head head; |
427 | struct tomoyo_path_info entry; | 427 | struct tomoyo_path_info entry; |
428 | }; | 428 | }; |
429 | 429 | ||
430 | /* Structure for holding a word. */ | 430 | /* Structure for holding a word. */ |
431 | struct tomoyo_name_union { | 431 | struct tomoyo_name_union { |
432 | /* Either @filename or @group is NULL. */ | 432 | /* Either @filename or @group is NULL. */ |
433 | const struct tomoyo_path_info *filename; | 433 | const struct tomoyo_path_info *filename; |
434 | struct tomoyo_group *group; | 434 | struct tomoyo_group *group; |
435 | }; | 435 | }; |
436 | 436 | ||
437 | /* Structure for holding a number. */ | 437 | /* Structure for holding a number. */ |
438 | struct tomoyo_number_union { | 438 | struct tomoyo_number_union { |
439 | unsigned long values[2]; | 439 | unsigned long values[2]; |
440 | struct tomoyo_group *group; /* Maybe NULL. */ | 440 | struct tomoyo_group *group; /* Maybe NULL. */ |
441 | /* One of values in "enum tomoyo_value_type". */ | 441 | /* One of values in "enum tomoyo_value_type". */ |
442 | u8 value_type[2]; | 442 | u8 value_type[2]; |
443 | }; | 443 | }; |
444 | 444 | ||
445 | /* Structure for "path_group"/"number_group" directive. */ | 445 | /* Structure for "path_group"/"number_group" directive. */ |
446 | struct tomoyo_group { | 446 | struct tomoyo_group { |
447 | struct tomoyo_shared_acl_head head; | 447 | struct tomoyo_shared_acl_head head; |
448 | const struct tomoyo_path_info *group_name; | 448 | const struct tomoyo_path_info *group_name; |
449 | struct list_head member_list; | 449 | struct list_head member_list; |
450 | }; | 450 | }; |
451 | 451 | ||
452 | /* Structure for "path_group" directive. */ | 452 | /* Structure for "path_group" directive. */ |
453 | struct tomoyo_path_group { | 453 | struct tomoyo_path_group { |
454 | struct tomoyo_acl_head head; | 454 | struct tomoyo_acl_head head; |
455 | const struct tomoyo_path_info *member_name; | 455 | const struct tomoyo_path_info *member_name; |
456 | }; | 456 | }; |
457 | 457 | ||
458 | /* Structure for "number_group" directive. */ | 458 | /* Structure for "number_group" directive. */ |
459 | struct tomoyo_number_group { | 459 | struct tomoyo_number_group { |
460 | struct tomoyo_acl_head head; | 460 | struct tomoyo_acl_head head; |
461 | struct tomoyo_number_union number; | 461 | struct tomoyo_number_union number; |
462 | }; | 462 | }; |
463 | 463 | ||
464 | /* Subset of "struct stat". Used by conditional ACL and audit logs. */ | 464 | /* Subset of "struct stat". Used by conditional ACL and audit logs. */ |
465 | struct tomoyo_mini_stat { | 465 | struct tomoyo_mini_stat { |
466 | uid_t uid; | 466 | uid_t uid; |
467 | gid_t gid; | 467 | gid_t gid; |
468 | ino_t ino; | 468 | ino_t ino; |
469 | mode_t mode; | 469 | mode_t mode; |
470 | dev_t dev; | 470 | dev_t dev; |
471 | dev_t rdev; | 471 | dev_t rdev; |
472 | }; | 472 | }; |
473 | 473 | ||
474 | /* Structure for dumping argv[] and envp[] of "struct linux_binprm". */ | 474 | /* Structure for dumping argv[] and envp[] of "struct linux_binprm". */ |
475 | struct tomoyo_page_dump { | 475 | struct tomoyo_page_dump { |
476 | struct page *page; /* Previously dumped page. */ | 476 | struct page *page; /* Previously dumped page. */ |
477 | char *data; /* Contents of "page". Size is PAGE_SIZE. */ | 477 | char *data; /* Contents of "page". Size is PAGE_SIZE. */ |
478 | }; | 478 | }; |
479 | 479 | ||
480 | /* Structure for attribute checks in addition to pathname checks. */ | 480 | /* Structure for attribute checks in addition to pathname checks. */ |
481 | struct tomoyo_obj_info { | 481 | struct tomoyo_obj_info { |
482 | /* | 482 | /* |
483 | * True if tomoyo_get_attributes() was already called, false otherwise. | 483 | * True if tomoyo_get_attributes() was already called, false otherwise. |
484 | */ | 484 | */ |
485 | bool validate_done; | 485 | bool validate_done; |
486 | /* True if @stat[] is valid. */ | 486 | /* True if @stat[] is valid. */ |
487 | bool stat_valid[TOMOYO_MAX_PATH_STAT]; | 487 | bool stat_valid[TOMOYO_MAX_PATH_STAT]; |
488 | /* First pathname. Initialized with { NULL, NULL } if no path. */ | 488 | /* First pathname. Initialized with { NULL, NULL } if no path. */ |
489 | struct path path1; | 489 | struct path path1; |
490 | /* Second pathname. Initialized with { NULL, NULL } if no path. */ | 490 | /* Second pathname. Initialized with { NULL, NULL } if no path. */ |
491 | struct path path2; | 491 | struct path path2; |
492 | /* | 492 | /* |
493 | * Information on @path1, @path1's parent directory, @path2, @path2's | 493 | * Information on @path1, @path1's parent directory, @path2, @path2's |
494 | * parent directory. | 494 | * parent directory. |
495 | */ | 495 | */ |
496 | struct tomoyo_mini_stat stat[TOMOYO_MAX_PATH_STAT]; | 496 | struct tomoyo_mini_stat stat[TOMOYO_MAX_PATH_STAT]; |
497 | /* | 497 | /* |
498 | * Content of symbolic link to be created. NULL for operations other | 498 | * Content of symbolic link to be created. NULL for operations other |
499 | * than symlink(). | 499 | * than symlink(). |
500 | */ | 500 | */ |
501 | struct tomoyo_path_info *symlink_target; | 501 | struct tomoyo_path_info *symlink_target; |
502 | }; | 502 | }; |
503 | 503 | ||
504 | /* Structure for argv[]. */ | 504 | /* Structure for argv[]. */ |
505 | struct tomoyo_argv { | 505 | struct tomoyo_argv { |
506 | unsigned long index; | 506 | unsigned long index; |
507 | const struct tomoyo_path_info *value; | 507 | const struct tomoyo_path_info *value; |
508 | bool is_not; | 508 | bool is_not; |
509 | }; | 509 | }; |
510 | 510 | ||
511 | /* Structure for envp[]. */ | 511 | /* Structure for envp[]. */ |
512 | struct tomoyo_envp { | 512 | struct tomoyo_envp { |
513 | const struct tomoyo_path_info *name; | 513 | const struct tomoyo_path_info *name; |
514 | const struct tomoyo_path_info *value; | 514 | const struct tomoyo_path_info *value; |
515 | bool is_not; | 515 | bool is_not; |
516 | }; | 516 | }; |
517 | 517 | ||
518 | /* Structure for execve() operation. */ | 518 | /* Structure for execve() operation. */ |
519 | struct tomoyo_execve { | 519 | struct tomoyo_execve { |
520 | struct tomoyo_request_info r; | 520 | struct tomoyo_request_info r; |
521 | struct tomoyo_obj_info obj; | 521 | struct tomoyo_obj_info obj; |
522 | struct linux_binprm *bprm; | 522 | struct linux_binprm *bprm; |
523 | /* For dumping argv[] and envp[]. */ | 523 | /* For dumping argv[] and envp[]. */ |
524 | struct tomoyo_page_dump dump; | 524 | struct tomoyo_page_dump dump; |
525 | /* For temporary use. */ | 525 | /* For temporary use. */ |
526 | char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ | 526 | char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ |
527 | }; | 527 | }; |
528 | 528 | ||
529 | /* Structure for entries which follows "struct tomoyo_condition". */ | 529 | /* Structure for entries which follows "struct tomoyo_condition". */ |
530 | struct tomoyo_condition_element { | 530 | struct tomoyo_condition_element { |
531 | /* | 531 | /* |
532 | * Left hand operand. A "struct tomoyo_argv" for TOMOYO_ARGV_ENTRY, a | 532 | * Left hand operand. A "struct tomoyo_argv" for TOMOYO_ARGV_ENTRY, a |
533 | * "struct tomoyo_envp" for TOMOYO_ENVP_ENTRY is attached to the tail | 533 | * "struct tomoyo_envp" for TOMOYO_ENVP_ENTRY is attached to the tail |
534 | * of the array of this struct. | 534 | * of the array of this struct. |
535 | */ | 535 | */ |
536 | u8 left; | 536 | u8 left; |
537 | /* | 537 | /* |
538 | * Right hand operand. A "struct tomoyo_number_union" for | 538 | * Right hand operand. A "struct tomoyo_number_union" for |
539 | * TOMOYO_NUMBER_UNION, a "struct tomoyo_name_union" for | 539 | * TOMOYO_NUMBER_UNION, a "struct tomoyo_name_union" for |
540 | * TOMOYO_NAME_UNION is attached to the tail of the array of this | 540 | * TOMOYO_NAME_UNION is attached to the tail of the array of this |
541 | * struct. | 541 | * struct. |
542 | */ | 542 | */ |
543 | u8 right; | 543 | u8 right; |
544 | /* Equation operator. True if equals or overlaps, false otherwise. */ | 544 | /* Equation operator. True if equals or overlaps, false otherwise. */ |
545 | bool equals; | 545 | bool equals; |
546 | }; | 546 | }; |
547 | 547 | ||
548 | /* Structure for optional arguments. */ | 548 | /* Structure for optional arguments. */ |
549 | struct tomoyo_condition { | 549 | struct tomoyo_condition { |
550 | struct tomoyo_shared_acl_head head; | 550 | struct tomoyo_shared_acl_head head; |
551 | u32 size; /* Memory size allocated for this entry. */ | 551 | u32 size; /* Memory size allocated for this entry. */ |
552 | u16 condc; /* Number of conditions in this struct. */ | 552 | u16 condc; /* Number of conditions in this struct. */ |
553 | u16 numbers_count; /* Number of "struct tomoyo_number_union values". */ | 553 | u16 numbers_count; /* Number of "struct tomoyo_number_union values". */ |
554 | u16 names_count; /* Number of "struct tomoyo_name_union names". */ | 554 | u16 names_count; /* Number of "struct tomoyo_name_union names". */ |
555 | u16 argc; /* Number of "struct tomoyo_argv". */ | 555 | u16 argc; /* Number of "struct tomoyo_argv". */ |
556 | u16 envc; /* Number of "struct tomoyo_envp". */ | 556 | u16 envc; /* Number of "struct tomoyo_envp". */ |
557 | /* | 557 | /* |
558 | * struct tomoyo_condition_element condition[condc]; | 558 | * struct tomoyo_condition_element condition[condc]; |
559 | * struct tomoyo_number_union values[numbers_count]; | 559 | * struct tomoyo_number_union values[numbers_count]; |
560 | * struct tomoyo_name_union names[names_count]; | 560 | * struct tomoyo_name_union names[names_count]; |
561 | * struct tomoyo_argv argv[argc]; | 561 | * struct tomoyo_argv argv[argc]; |
562 | * struct tomoyo_envp envp[envc]; | 562 | * struct tomoyo_envp envp[envc]; |
563 | */ | 563 | */ |
564 | }; | 564 | }; |
565 | 565 | ||
566 | /* Common header for individual entries. */ | 566 | /* Common header for individual entries. */ |
567 | struct tomoyo_acl_info { | 567 | struct tomoyo_acl_info { |
568 | struct list_head list; | 568 | struct list_head list; |
569 | struct tomoyo_condition *cond; /* Maybe NULL. */ | 569 | struct tomoyo_condition *cond; /* Maybe NULL. */ |
570 | bool is_deleted; | 570 | bool is_deleted; |
571 | u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */ | 571 | u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */ |
572 | } __packed; | 572 | } __packed; |
573 | 573 | ||
574 | /* Structure for domain information. */ | 574 | /* Structure for domain information. */ |
575 | struct tomoyo_domain_info { | 575 | struct tomoyo_domain_info { |
576 | struct list_head list; | 576 | struct list_head list; |
577 | struct list_head acl_info_list; | 577 | struct list_head acl_info_list; |
578 | /* Name of this domain. Never NULL. */ | 578 | /* Name of this domain. Never NULL. */ |
579 | const struct tomoyo_path_info *domainname; | 579 | const struct tomoyo_path_info *domainname; |
580 | /* Namespace for this domain. Never NULL. */ | 580 | /* Namespace for this domain. Never NULL. */ |
581 | struct tomoyo_policy_namespace *ns; | 581 | struct tomoyo_policy_namespace *ns; |
582 | u8 profile; /* Profile number to use. */ | 582 | u8 profile; /* Profile number to use. */ |
583 | u8 group; /* Group number to use. */ | 583 | u8 group; /* Group number to use. */ |
584 | bool is_deleted; /* Delete flag. */ | 584 | bool is_deleted; /* Delete flag. */ |
585 | bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; | 585 | bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; |
586 | atomic_t users; /* Number of referring credentials. */ | 586 | atomic_t users; /* Number of referring credentials. */ |
587 | }; | 587 | }; |
588 | 588 | ||
589 | /* | 589 | /* |
590 | * Structure for "file execute", "file read", "file write", "file append", | 590 | * Structure for "file execute", "file read", "file write", "file append", |
591 | * "file unlink", "file getattr", "file rmdir", "file truncate", | 591 | * "file unlink", "file getattr", "file rmdir", "file truncate", |
592 | * "file symlink", "file chroot" and "file unmount" directive. | 592 | * "file symlink", "file chroot" and "file unmount" directive. |
593 | */ | 593 | */ |
594 | struct tomoyo_path_acl { | 594 | struct tomoyo_path_acl { |
595 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ | 595 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ |
596 | u16 perm; /* Bitmask of values in "enum tomoyo_path_acl_index". */ | 596 | u16 perm; /* Bitmask of values in "enum tomoyo_path_acl_index". */ |
597 | struct tomoyo_name_union name; | 597 | struct tomoyo_name_union name; |
598 | }; | 598 | }; |
599 | 599 | ||
600 | /* | 600 | /* |
601 | * Structure for "file create", "file mkdir", "file mkfifo", "file mksock", | 601 | * Structure for "file create", "file mkdir", "file mkfifo", "file mksock", |
602 | * "file ioctl", "file chmod", "file chown" and "file chgrp" directive. | 602 | * "file ioctl", "file chmod", "file chown" and "file chgrp" directive. |
603 | */ | 603 | */ |
604 | struct tomoyo_path_number_acl { | 604 | struct tomoyo_path_number_acl { |
605 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_NUMBER_ACL */ | 605 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_NUMBER_ACL */ |
606 | /* Bitmask of values in "enum tomoyo_path_number_acl_index". */ | 606 | /* Bitmask of values in "enum tomoyo_path_number_acl_index". */ |
607 | u8 perm; | 607 | u8 perm; |
608 | struct tomoyo_name_union name; | 608 | struct tomoyo_name_union name; |
609 | struct tomoyo_number_union number; | 609 | struct tomoyo_number_union number; |
610 | }; | 610 | }; |
611 | 611 | ||
612 | /* Structure for "file mkblock" and "file mkchar" directive. */ | 612 | /* Structure for "file mkblock" and "file mkchar" directive. */ |
613 | struct tomoyo_mkdev_acl { | 613 | struct tomoyo_mkdev_acl { |
614 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MKDEV_ACL */ | 614 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MKDEV_ACL */ |
615 | u8 perm; /* Bitmask of values in "enum tomoyo_mkdev_acl_index". */ | 615 | u8 perm; /* Bitmask of values in "enum tomoyo_mkdev_acl_index". */ |
616 | struct tomoyo_name_union name; | 616 | struct tomoyo_name_union name; |
617 | struct tomoyo_number_union mode; | 617 | struct tomoyo_number_union mode; |
618 | struct tomoyo_number_union major; | 618 | struct tomoyo_number_union major; |
619 | struct tomoyo_number_union minor; | 619 | struct tomoyo_number_union minor; |
620 | }; | 620 | }; |
621 | 621 | ||
622 | /* | 622 | /* |
623 | * Structure for "file rename", "file link" and "file pivot_root" directive. | 623 | * Structure for "file rename", "file link" and "file pivot_root" directive. |
624 | */ | 624 | */ |
625 | struct tomoyo_path2_acl { | 625 | struct tomoyo_path2_acl { |
626 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ | 626 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ |
627 | u8 perm; /* Bitmask of values in "enum tomoyo_path2_acl_index". */ | 627 | u8 perm; /* Bitmask of values in "enum tomoyo_path2_acl_index". */ |
628 | struct tomoyo_name_union name1; | 628 | struct tomoyo_name_union name1; |
629 | struct tomoyo_name_union name2; | 629 | struct tomoyo_name_union name2; |
630 | }; | 630 | }; |
631 | 631 | ||
632 | /* Structure for "file mount" directive. */ | 632 | /* Structure for "file mount" directive. */ |
633 | struct tomoyo_mount_acl { | 633 | struct tomoyo_mount_acl { |
634 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */ | 634 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */ |
635 | struct tomoyo_name_union dev_name; | 635 | struct tomoyo_name_union dev_name; |
636 | struct tomoyo_name_union dir_name; | 636 | struct tomoyo_name_union dir_name; |
637 | struct tomoyo_name_union fs_type; | 637 | struct tomoyo_name_union fs_type; |
638 | struct tomoyo_number_union flags; | 638 | struct tomoyo_number_union flags; |
639 | }; | 639 | }; |
640 | 640 | ||
641 | /* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */ | 641 | /* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */ |
642 | struct tomoyo_acl_param { | 642 | struct tomoyo_acl_param { |
643 | char *data; | 643 | char *data; |
644 | struct list_head *list; | 644 | struct list_head *list; |
645 | struct tomoyo_policy_namespace *ns; | 645 | struct tomoyo_policy_namespace *ns; |
646 | bool is_delete; | 646 | bool is_delete; |
647 | }; | 647 | }; |
648 | 648 | ||
649 | #define TOMOYO_MAX_IO_READ_QUEUE 64 | 649 | #define TOMOYO_MAX_IO_READ_QUEUE 64 |
650 | 650 | ||
651 | /* | 651 | /* |
652 | * Structure for reading/writing policy via /sys/kernel/security/tomoyo | 652 | * Structure for reading/writing policy via /sys/kernel/security/tomoyo |
653 | * interfaces. | 653 | * interfaces. |
654 | */ | 654 | */ |
655 | struct tomoyo_io_buffer { | 655 | struct tomoyo_io_buffer { |
656 | void (*read) (struct tomoyo_io_buffer *); | 656 | void (*read) (struct tomoyo_io_buffer *); |
657 | int (*write) (struct tomoyo_io_buffer *); | 657 | int (*write) (struct tomoyo_io_buffer *); |
658 | int (*poll) (struct file *file, poll_table *wait); | 658 | int (*poll) (struct file *file, poll_table *wait); |
659 | /* Exclusive lock for this structure. */ | 659 | /* Exclusive lock for this structure. */ |
660 | struct mutex io_sem; | 660 | struct mutex io_sem; |
661 | char __user *read_user_buf; | 661 | char __user *read_user_buf; |
662 | size_t read_user_buf_avail; | 662 | size_t read_user_buf_avail; |
663 | struct { | 663 | struct { |
664 | struct list_head *ns; | 664 | struct list_head *ns; |
665 | struct list_head *domain; | 665 | struct list_head *domain; |
666 | struct list_head *group; | 666 | struct list_head *group; |
667 | struct list_head *acl; | 667 | struct list_head *acl; |
668 | size_t avail; | 668 | size_t avail; |
669 | unsigned int step; | 669 | unsigned int step; |
670 | unsigned int query_index; | 670 | unsigned int query_index; |
671 | u16 index; | 671 | u16 index; |
672 | u16 cond_index; | 672 | u16 cond_index; |
673 | u8 acl_group_index; | 673 | u8 acl_group_index; |
674 | u8 cond_step; | 674 | u8 cond_step; |
675 | u8 bit; | 675 | u8 bit; |
676 | u8 w_pos; | 676 | u8 w_pos; |
677 | bool eof; | 677 | bool eof; |
678 | bool print_this_domain_only; | 678 | bool print_this_domain_only; |
679 | bool print_transition_related_only; | 679 | bool print_transition_related_only; |
680 | bool print_cond_part; | 680 | bool print_cond_part; |
681 | const char *w[TOMOYO_MAX_IO_READ_QUEUE]; | 681 | const char *w[TOMOYO_MAX_IO_READ_QUEUE]; |
682 | } r; | 682 | } r; |
683 | struct { | 683 | struct { |
684 | struct tomoyo_policy_namespace *ns; | 684 | struct tomoyo_policy_namespace *ns; |
685 | /* The position currently writing to. */ | 685 | /* The position currently writing to. */ |
686 | struct tomoyo_domain_info *domain; | 686 | struct tomoyo_domain_info *domain; |
687 | /* Bytes available for writing. */ | 687 | /* Bytes available for writing. */ |
688 | size_t avail; | 688 | size_t avail; |
689 | bool is_delete; | 689 | bool is_delete; |
690 | } w; | 690 | } w; |
691 | /* Buffer for reading. */ | 691 | /* Buffer for reading. */ |
692 | char *read_buf; | 692 | char *read_buf; |
693 | /* Size of read buffer. */ | 693 | /* Size of read buffer. */ |
694 | size_t readbuf_size; | 694 | size_t readbuf_size; |
695 | /* Buffer for writing. */ | 695 | /* Buffer for writing. */ |
696 | char *write_buf; | 696 | char *write_buf; |
697 | /* Size of write buffer. */ | 697 | /* Size of write buffer. */ |
698 | size_t writebuf_size; | 698 | size_t writebuf_size; |
699 | /* Type of this interface. */ | 699 | /* Type of this interface. */ |
700 | enum tomoyo_securityfs_interface_index type; | 700 | enum tomoyo_securityfs_interface_index type; |
701 | /* Users counter protected by tomoyo_io_buffer_list_lock. */ | 701 | /* Users counter protected by tomoyo_io_buffer_list_lock. */ |
702 | u8 users; | 702 | u8 users; |
703 | /* List for telling GC not to kfree() elements. */ | 703 | /* List for telling GC not to kfree() elements. */ |
704 | struct list_head list; | 704 | struct list_head list; |
705 | }; | 705 | }; |
706 | 706 | ||
707 | /* | 707 | /* |
708 | * Structure for "initialize_domain"/"no_initialize_domain"/"keep_domain"/ | 708 | * Structure for "initialize_domain"/"no_initialize_domain"/"keep_domain"/ |
709 | * "no_keep_domain" keyword. | 709 | * "no_keep_domain" keyword. |
710 | */ | 710 | */ |
711 | struct tomoyo_transition_control { | 711 | struct tomoyo_transition_control { |
712 | struct tomoyo_acl_head head; | 712 | struct tomoyo_acl_head head; |
713 | u8 type; /* One of values in "enum tomoyo_transition_type". */ | 713 | u8 type; /* One of values in "enum tomoyo_transition_type". */ |
714 | /* True if the domainname is tomoyo_get_last_name(). */ | 714 | /* True if the domainname is tomoyo_get_last_name(). */ |
715 | bool is_last_name; | 715 | bool is_last_name; |
716 | const struct tomoyo_path_info *domainname; /* Maybe NULL */ | 716 | const struct tomoyo_path_info *domainname; /* Maybe NULL */ |
717 | const struct tomoyo_path_info *program; /* Maybe NULL */ | 717 | const struct tomoyo_path_info *program; /* Maybe NULL */ |
718 | }; | 718 | }; |
719 | 719 | ||
720 | /* Structure for "aggregator" keyword. */ | 720 | /* Structure for "aggregator" keyword. */ |
721 | struct tomoyo_aggregator { | 721 | struct tomoyo_aggregator { |
722 | struct tomoyo_acl_head head; | 722 | struct tomoyo_acl_head head; |
723 | const struct tomoyo_path_info *original_name; | 723 | const struct tomoyo_path_info *original_name; |
724 | const struct tomoyo_path_info *aggregated_name; | 724 | const struct tomoyo_path_info *aggregated_name; |
725 | }; | 725 | }; |
726 | 726 | ||
727 | /* Structure for policy manager. */ | 727 | /* Structure for policy manager. */ |
728 | struct tomoyo_manager { | 728 | struct tomoyo_manager { |
729 | struct tomoyo_acl_head head; | 729 | struct tomoyo_acl_head head; |
730 | bool is_domain; /* True if manager is a domainname. */ | 730 | bool is_domain; /* True if manager is a domainname. */ |
731 | /* A path to program or a domainname. */ | 731 | /* A path to program or a domainname. */ |
732 | const struct tomoyo_path_info *manager; | 732 | const struct tomoyo_path_info *manager; |
733 | }; | 733 | }; |
734 | 734 | ||
735 | struct tomoyo_preference { | 735 | struct tomoyo_preference { |
736 | unsigned int learning_max_entry; | 736 | unsigned int learning_max_entry; |
737 | bool enforcing_verbose; | 737 | bool enforcing_verbose; |
738 | bool learning_verbose; | 738 | bool learning_verbose; |
739 | bool permissive_verbose; | 739 | bool permissive_verbose; |
740 | }; | 740 | }; |
741 | 741 | ||
742 | /* Structure for /sys/kernel/security/tomnoyo/profile interface. */ | 742 | /* Structure for /sys/kernel/security/tomnoyo/profile interface. */ |
743 | struct tomoyo_profile { | 743 | struct tomoyo_profile { |
744 | const struct tomoyo_path_info *comment; | 744 | const struct tomoyo_path_info *comment; |
745 | struct tomoyo_preference *learning; | 745 | struct tomoyo_preference *learning; |
746 | struct tomoyo_preference *permissive; | 746 | struct tomoyo_preference *permissive; |
747 | struct tomoyo_preference *enforcing; | 747 | struct tomoyo_preference *enforcing; |
748 | struct tomoyo_preference preference; | 748 | struct tomoyo_preference preference; |
749 | u8 default_config; | 749 | u8 default_config; |
750 | u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX]; | 750 | u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX]; |
751 | unsigned int pref[TOMOYO_MAX_PREF]; | 751 | unsigned int pref[TOMOYO_MAX_PREF]; |
752 | }; | 752 | }; |
753 | 753 | ||
754 | /* Structure for representing YYYY/MM/DD hh/mm/ss. */ | 754 | /* Structure for representing YYYY/MM/DD hh/mm/ss. */ |
755 | struct tomoyo_time { | 755 | struct tomoyo_time { |
756 | u16 year; | 756 | u16 year; |
757 | u8 month; | 757 | u8 month; |
758 | u8 day; | 758 | u8 day; |
759 | u8 hour; | 759 | u8 hour; |
760 | u8 min; | 760 | u8 min; |
761 | u8 sec; | 761 | u8 sec; |
762 | }; | 762 | }; |
763 | 763 | ||
764 | /* Structure for policy namespace. */ | 764 | /* Structure for policy namespace. */ |
765 | struct tomoyo_policy_namespace { | 765 | struct tomoyo_policy_namespace { |
766 | /* Profile table. Memory is allocated as needed. */ | 766 | /* Profile table. Memory is allocated as needed. */ |
767 | struct tomoyo_profile *profile_ptr[TOMOYO_MAX_PROFILES]; | 767 | struct tomoyo_profile *profile_ptr[TOMOYO_MAX_PROFILES]; |
768 | /* List of "struct tomoyo_group". */ | 768 | /* List of "struct tomoyo_group". */ |
769 | struct list_head group_list[TOMOYO_MAX_GROUP]; | 769 | struct list_head group_list[TOMOYO_MAX_GROUP]; |
770 | /* List of policy. */ | 770 | /* List of policy. */ |
771 | struct list_head policy_list[TOMOYO_MAX_POLICY]; | 771 | struct list_head policy_list[TOMOYO_MAX_POLICY]; |
772 | /* The global ACL referred by "use_group" keyword. */ | 772 | /* The global ACL referred by "use_group" keyword. */ |
773 | struct list_head acl_group[TOMOYO_MAX_ACL_GROUPS]; | 773 | struct list_head acl_group[TOMOYO_MAX_ACL_GROUPS]; |
774 | /* List for connecting to tomoyo_namespace_list list. */ | 774 | /* List for connecting to tomoyo_namespace_list list. */ |
775 | struct list_head namespace_list; | 775 | struct list_head namespace_list; |
776 | /* Profile version. Currently only 20100903 is defined. */ | 776 | /* Profile version. Currently only 20100903 is defined. */ |
777 | unsigned int profile_version; | 777 | unsigned int profile_version; |
778 | /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */ | 778 | /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */ |
779 | const char *name; | 779 | const char *name; |
780 | }; | 780 | }; |
781 | 781 | ||
782 | /********** Function prototypes. **********/ | 782 | /********** Function prototypes. **********/ |
783 | 783 | ||
784 | bool tomoyo_compare_number_union(const unsigned long value, | 784 | bool tomoyo_compare_number_union(const unsigned long value, |
785 | const struct tomoyo_number_union *ptr); | 785 | const struct tomoyo_number_union *ptr); |
786 | bool tomoyo_condition(struct tomoyo_request_info *r, | 786 | bool tomoyo_condition(struct tomoyo_request_info *r, |
787 | const struct tomoyo_condition *cond); | 787 | const struct tomoyo_condition *cond); |
788 | bool tomoyo_correct_domain(const unsigned char *domainname); | 788 | bool tomoyo_correct_domain(const unsigned char *domainname); |
789 | bool tomoyo_correct_path(const char *filename); | 789 | bool tomoyo_correct_path(const char *filename); |
790 | bool tomoyo_correct_word(const char *string); | 790 | bool tomoyo_correct_word(const char *string); |
791 | bool tomoyo_domain_def(const unsigned char *buffer); | 791 | bool tomoyo_domain_def(const unsigned char *buffer); |
792 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); | 792 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); |
793 | bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, | 793 | bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, |
794 | struct tomoyo_page_dump *dump); | 794 | struct tomoyo_page_dump *dump); |
795 | bool tomoyo_memory_ok(void *ptr); | 795 | bool tomoyo_memory_ok(void *ptr); |
796 | bool tomoyo_number_matches_group(const unsigned long min, | 796 | bool tomoyo_number_matches_group(const unsigned long min, |
797 | const unsigned long max, | 797 | const unsigned long max, |
798 | const struct tomoyo_group *group); | 798 | const struct tomoyo_group *group); |
799 | bool tomoyo_parse_name_union(struct tomoyo_acl_param *param, | 799 | bool tomoyo_parse_name_union(struct tomoyo_acl_param *param, |
800 | struct tomoyo_name_union *ptr); | 800 | struct tomoyo_name_union *ptr); |
801 | bool tomoyo_parse_number_union(struct tomoyo_acl_param *param, | 801 | bool tomoyo_parse_number_union(struct tomoyo_acl_param *param, |
802 | struct tomoyo_number_union *ptr); | 802 | struct tomoyo_number_union *ptr); |
803 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, | 803 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, |
804 | const struct tomoyo_path_info *pattern); | 804 | const struct tomoyo_path_info *pattern); |
805 | bool tomoyo_permstr(const char *string, const char *keyword); | 805 | bool tomoyo_permstr(const char *string, const char *keyword); |
806 | bool tomoyo_str_starts(char **src, const char *find); | 806 | bool tomoyo_str_starts(char **src, const char *find); |
807 | char *tomoyo_encode(const char *str); | 807 | char *tomoyo_encode(const char *str); |
808 | char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | 808 | char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, |
809 | va_list args); | 809 | va_list args); |
810 | char *tomoyo_read_token(struct tomoyo_acl_param *param); | 810 | char *tomoyo_read_token(struct tomoyo_acl_param *param); |
811 | char *tomoyo_realpath_from_path(struct path *path); | 811 | char *tomoyo_realpath_from_path(struct path *path); |
812 | char *tomoyo_realpath_nofollow(const char *pathname); | 812 | char *tomoyo_realpath_nofollow(const char *pathname); |
813 | const char *tomoyo_get_exe(void); | 813 | const char *tomoyo_get_exe(void); |
814 | const char *tomoyo_yesno(const unsigned int value); | 814 | const char *tomoyo_yesno(const unsigned int value); |
815 | const struct tomoyo_path_info *tomoyo_compare_name_union | 815 | const struct tomoyo_path_info *tomoyo_compare_name_union |
816 | (const struct tomoyo_path_info *name, const struct tomoyo_name_union *ptr); | 816 | (const struct tomoyo_path_info *name, const struct tomoyo_name_union *ptr); |
817 | const struct tomoyo_path_info *tomoyo_get_name(const char *name); | 817 | const struct tomoyo_path_info *tomoyo_get_name(const char *name); |
818 | const struct tomoyo_path_info *tomoyo_path_matches_group | 818 | const struct tomoyo_path_info *tomoyo_path_matches_group |
819 | (const struct tomoyo_path_info *pathname, const struct tomoyo_group *group); | 819 | (const struct tomoyo_path_info *pathname, const struct tomoyo_group *group); |
820 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | 820 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, |
821 | struct path *path, const int flag); | 821 | struct path *path, const int flag); |
822 | int tomoyo_close_control(struct tomoyo_io_buffer *head); | 822 | int tomoyo_close_control(struct tomoyo_io_buffer *head); |
823 | int tomoyo_find_next_domain(struct linux_binprm *bprm); | 823 | int tomoyo_find_next_domain(struct linux_binprm *bprm); |
824 | int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, | 824 | int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, |
825 | const u8 index); | 825 | const u8 index); |
826 | int tomoyo_init_request_info(struct tomoyo_request_info *r, | 826 | int tomoyo_init_request_info(struct tomoyo_request_info *r, |
827 | struct tomoyo_domain_info *domain, | 827 | struct tomoyo_domain_info *domain, |
828 | const u8 index); | 828 | const u8 index); |
829 | int tomoyo_mkdev_perm(const u8 operation, struct path *path, | 829 | int tomoyo_mkdev_perm(const u8 operation, struct path *path, |
830 | const unsigned int mode, unsigned int dev); | 830 | const unsigned int mode, unsigned int dev); |
831 | int tomoyo_mount_permission(char *dev_name, struct path *path, | 831 | int tomoyo_mount_permission(char *dev_name, struct path *path, |
832 | const char *type, unsigned long flags, | 832 | const char *type, unsigned long flags, |
833 | void *data_page); | 833 | void *data_page); |
834 | int tomoyo_open_control(const u8 type, struct file *file); | 834 | int tomoyo_open_control(const u8 type, struct file *file); |
835 | int tomoyo_path2_perm(const u8 operation, struct path *path1, | 835 | int tomoyo_path2_perm(const u8 operation, struct path *path1, |
836 | struct path *path2); | 836 | struct path *path2); |
837 | int tomoyo_path_number_perm(const u8 operation, struct path *path, | 837 | int tomoyo_path_number_perm(const u8 operation, struct path *path, |
838 | unsigned long number); | 838 | unsigned long number); |
839 | int tomoyo_path_perm(const u8 operation, struct path *path); | 839 | int tomoyo_path_perm(const u8 operation, struct path *path, |
840 | const char *target); | ||
840 | int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | 841 | int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, |
841 | const struct tomoyo_path_info *filename); | 842 | const struct tomoyo_path_info *filename); |
842 | int tomoyo_poll_control(struct file *file, poll_table *wait); | 843 | int tomoyo_poll_control(struct file *file, poll_table *wait); |
843 | int tomoyo_poll_log(struct file *file, poll_table *wait); | 844 | int tomoyo_poll_log(struct file *file, poll_table *wait); |
844 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) | 845 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) |
845 | __printf(2, 3); | 846 | __printf(2, 3); |
846 | int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, | 847 | int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, |
847 | struct tomoyo_acl_param *param, | 848 | struct tomoyo_acl_param *param, |
848 | bool (*check_duplicate) | 849 | bool (*check_duplicate) |
849 | (const struct tomoyo_acl_info *, | 850 | (const struct tomoyo_acl_info *, |
850 | const struct tomoyo_acl_info *), | 851 | const struct tomoyo_acl_info *), |
851 | bool (*merge_duplicate) | 852 | bool (*merge_duplicate) |
852 | (struct tomoyo_acl_info *, struct tomoyo_acl_info *, | 853 | (struct tomoyo_acl_info *, struct tomoyo_acl_info *, |
853 | const bool)); | 854 | const bool)); |
854 | int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, | 855 | int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, |
855 | struct tomoyo_acl_param *param, | 856 | struct tomoyo_acl_param *param, |
856 | bool (*check_duplicate) | 857 | bool (*check_duplicate) |
857 | (const struct tomoyo_acl_head *, | 858 | (const struct tomoyo_acl_head *, |
858 | const struct tomoyo_acl_head *)); | 859 | const struct tomoyo_acl_head *)); |
859 | int tomoyo_write_aggregator(struct tomoyo_acl_param *param); | 860 | int tomoyo_write_aggregator(struct tomoyo_acl_param *param); |
860 | int tomoyo_write_file(struct tomoyo_acl_param *param); | 861 | int tomoyo_write_file(struct tomoyo_acl_param *param); |
861 | int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type); | 862 | int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type); |
862 | int tomoyo_write_transition_control(struct tomoyo_acl_param *param, | 863 | int tomoyo_write_transition_control(struct tomoyo_acl_param *param, |
863 | const u8 type); | 864 | const u8 type); |
864 | ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, | 865 | ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, |
865 | const int buffer_len); | 866 | const int buffer_len); |
866 | ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, | 867 | ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, |
867 | const char __user *buffer, const int buffer_len); | 868 | const char __user *buffer, const int buffer_len); |
868 | struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param); | 869 | struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param); |
869 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | 870 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, |
870 | const bool transit); | 871 | const bool transit); |
871 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | 872 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); |
872 | struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, | 873 | struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, |
873 | const u8 idx); | 874 | const u8 idx); |
874 | struct tomoyo_policy_namespace *tomoyo_assign_namespace | 875 | struct tomoyo_policy_namespace *tomoyo_assign_namespace |
875 | (const char *domainname); | 876 | (const char *domainname); |
876 | struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, | 877 | struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, |
877 | const u8 profile); | 878 | const u8 profile); |
878 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | 879 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, |
879 | const u8 index); | 880 | const u8 index); |
880 | u8 tomoyo_parse_ulong(unsigned long *result, char **str); | 881 | u8 tomoyo_parse_ulong(unsigned long *result, char **str); |
881 | void *tomoyo_commit_ok(void *data, const unsigned int size); | 882 | void *tomoyo_commit_ok(void *data, const unsigned int size); |
882 | void __init tomoyo_load_builtin_policy(void); | 883 | void __init tomoyo_load_builtin_policy(void); |
883 | void __init tomoyo_mm_init(void); | 884 | void __init tomoyo_mm_init(void); |
884 | void tomoyo_check_acl(struct tomoyo_request_info *r, | 885 | void tomoyo_check_acl(struct tomoyo_request_info *r, |
885 | bool (*check_entry) (struct tomoyo_request_info *, | 886 | bool (*check_entry) (struct tomoyo_request_info *, |
886 | const struct tomoyo_acl_info *)); | 887 | const struct tomoyo_acl_info *)); |
887 | void tomoyo_check_profile(void); | 888 | void tomoyo_check_profile(void); |
888 | void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp); | 889 | void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp); |
889 | void tomoyo_del_condition(struct list_head *element); | 890 | void tomoyo_del_condition(struct list_head *element); |
890 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | 891 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); |
891 | void tomoyo_get_attributes(struct tomoyo_obj_info *obj); | 892 | void tomoyo_get_attributes(struct tomoyo_obj_info *obj); |
892 | void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns); | 893 | void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns); |
893 | void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) | 894 | void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) |
894 | __printf(2, 3); | 895 | __printf(2, 3); |
895 | void tomoyo_load_policy(const char *filename); | 896 | void tomoyo_load_policy(const char *filename); |
896 | void tomoyo_memory_free(void *ptr); | 897 | void tomoyo_memory_free(void *ptr); |
897 | void tomoyo_normalize_line(unsigned char *buffer); | 898 | void tomoyo_normalize_line(unsigned char *buffer); |
898 | void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register); | 899 | void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register); |
899 | void tomoyo_print_ulong(char *buffer, const int buffer_len, | 900 | void tomoyo_print_ulong(char *buffer, const int buffer_len, |
900 | const unsigned long value, const u8 type); | 901 | const unsigned long value, const u8 type); |
901 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr); | 902 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr); |
902 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr); | 903 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr); |
903 | void tomoyo_read_log(struct tomoyo_io_buffer *head); | 904 | void tomoyo_read_log(struct tomoyo_io_buffer *head); |
904 | void tomoyo_update_stat(const u8 index); | 905 | void tomoyo_update_stat(const u8 index); |
905 | void tomoyo_warn_oom(const char *function); | 906 | void tomoyo_warn_oom(const char *function); |
906 | void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) | 907 | void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) |
907 | __printf(2, 3); | 908 | __printf(2, 3); |
908 | void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, | 909 | void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, |
909 | va_list args); | 910 | va_list args); |
910 | 911 | ||
911 | /********** External variable definitions. **********/ | 912 | /********** External variable definitions. **********/ |
912 | 913 | ||
913 | extern bool tomoyo_policy_loaded; | 914 | extern bool tomoyo_policy_loaded; |
914 | extern const char * const tomoyo_condition_keyword | 915 | extern const char * const tomoyo_condition_keyword |
915 | [TOMOYO_MAX_CONDITION_KEYWORD]; | 916 | [TOMOYO_MAX_CONDITION_KEYWORD]; |
916 | extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; | 917 | extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; |
917 | extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX | 918 | extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX |
918 | + TOMOYO_MAX_MAC_CATEGORY_INDEX]; | 919 | + TOMOYO_MAX_MAC_CATEGORY_INDEX]; |
919 | extern const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE]; | 920 | extern const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE]; |
920 | extern const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION]; | 921 | extern const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION]; |
921 | extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX]; | 922 | extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX]; |
922 | extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; | 923 | extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; |
923 | extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; | 924 | extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; |
924 | extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION]; | 925 | extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION]; |
925 | extern struct list_head tomoyo_condition_list; | 926 | extern struct list_head tomoyo_condition_list; |
926 | extern struct list_head tomoyo_domain_list; | 927 | extern struct list_head tomoyo_domain_list; |
927 | extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; | 928 | extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; |
928 | extern struct list_head tomoyo_namespace_list; | 929 | extern struct list_head tomoyo_namespace_list; |
929 | extern struct mutex tomoyo_policy_lock; | 930 | extern struct mutex tomoyo_policy_lock; |
930 | extern struct srcu_struct tomoyo_ss; | 931 | extern struct srcu_struct tomoyo_ss; |
931 | extern struct tomoyo_domain_info tomoyo_kernel_domain; | 932 | extern struct tomoyo_domain_info tomoyo_kernel_domain; |
932 | extern struct tomoyo_policy_namespace tomoyo_kernel_namespace; | 933 | extern struct tomoyo_policy_namespace tomoyo_kernel_namespace; |
933 | extern unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; | 934 | extern unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; |
934 | extern unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; | 935 | extern unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; |
935 | 936 | ||
936 | /********** Inlined functions. **********/ | 937 | /********** Inlined functions. **********/ |
937 | 938 | ||
938 | /** | 939 | /** |
939 | * tomoyo_read_lock - Take lock for protecting policy. | 940 | * tomoyo_read_lock - Take lock for protecting policy. |
940 | * | 941 | * |
941 | * Returns index number for tomoyo_read_unlock(). | 942 | * Returns index number for tomoyo_read_unlock(). |
942 | */ | 943 | */ |
943 | static inline int tomoyo_read_lock(void) | 944 | static inline int tomoyo_read_lock(void) |
944 | { | 945 | { |
945 | return srcu_read_lock(&tomoyo_ss); | 946 | return srcu_read_lock(&tomoyo_ss); |
946 | } | 947 | } |
947 | 948 | ||
948 | /** | 949 | /** |
949 | * tomoyo_read_unlock - Release lock for protecting policy. | 950 | * tomoyo_read_unlock - Release lock for protecting policy. |
950 | * | 951 | * |
951 | * @idx: Index number returned by tomoyo_read_lock(). | 952 | * @idx: Index number returned by tomoyo_read_lock(). |
952 | * | 953 | * |
953 | * Returns nothing. | 954 | * Returns nothing. |
954 | */ | 955 | */ |
955 | static inline void tomoyo_read_unlock(int idx) | 956 | static inline void tomoyo_read_unlock(int idx) |
956 | { | 957 | { |
957 | srcu_read_unlock(&tomoyo_ss, idx); | 958 | srcu_read_unlock(&tomoyo_ss, idx); |
958 | } | 959 | } |
959 | 960 | ||
960 | /** | 961 | /** |
961 | * tomoyo_sys_getppid - Copy of getppid(). | 962 | * tomoyo_sys_getppid - Copy of getppid(). |
962 | * | 963 | * |
963 | * Returns parent process's PID. | 964 | * Returns parent process's PID. |
964 | * | 965 | * |
965 | * Alpha does not have getppid() defined. To be able to build this module on | 966 | * Alpha does not have getppid() defined. To be able to build this module on |
966 | * Alpha, I have to copy getppid() from kernel/timer.c. | 967 | * Alpha, I have to copy getppid() from kernel/timer.c. |
967 | */ | 968 | */ |
968 | static inline pid_t tomoyo_sys_getppid(void) | 969 | static inline pid_t tomoyo_sys_getppid(void) |
969 | { | 970 | { |
970 | pid_t pid; | 971 | pid_t pid; |
971 | rcu_read_lock(); | 972 | rcu_read_lock(); |
972 | pid = task_tgid_vnr(current->real_parent); | 973 | pid = task_tgid_vnr(current->real_parent); |
973 | rcu_read_unlock(); | 974 | rcu_read_unlock(); |
974 | return pid; | 975 | return pid; |
975 | } | 976 | } |
976 | 977 | ||
977 | /** | 978 | /** |
978 | * tomoyo_sys_getpid - Copy of getpid(). | 979 | * tomoyo_sys_getpid - Copy of getpid(). |
979 | * | 980 | * |
980 | * Returns current thread's PID. | 981 | * Returns current thread's PID. |
981 | * | 982 | * |
982 | * Alpha does not have getpid() defined. To be able to build this module on | 983 | * Alpha does not have getpid() defined. To be able to build this module on |
983 | * Alpha, I have to copy getpid() from kernel/timer.c. | 984 | * Alpha, I have to copy getpid() from kernel/timer.c. |
984 | */ | 985 | */ |
985 | static inline pid_t tomoyo_sys_getpid(void) | 986 | static inline pid_t tomoyo_sys_getpid(void) |
986 | { | 987 | { |
987 | return task_tgid_vnr(current); | 988 | return task_tgid_vnr(current); |
988 | } | 989 | } |
989 | 990 | ||
990 | /** | 991 | /** |
991 | * tomoyo_pathcmp - strcmp() for "struct tomoyo_path_info" structure. | 992 | * tomoyo_pathcmp - strcmp() for "struct tomoyo_path_info" structure. |
992 | * | 993 | * |
993 | * @a: Pointer to "struct tomoyo_path_info". | 994 | * @a: Pointer to "struct tomoyo_path_info". |
994 | * @b: Pointer to "struct tomoyo_path_info". | 995 | * @b: Pointer to "struct tomoyo_path_info". |
995 | * | 996 | * |
996 | * Returns true if @a == @b, false otherwise. | 997 | * Returns true if @a == @b, false otherwise. |
997 | */ | 998 | */ |
998 | static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, | 999 | static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, |
999 | const struct tomoyo_path_info *b) | 1000 | const struct tomoyo_path_info *b) |
1000 | { | 1001 | { |
1001 | return a->hash != b->hash || strcmp(a->name, b->name); | 1002 | return a->hash != b->hash || strcmp(a->name, b->name); |
1002 | } | 1003 | } |
1003 | 1004 | ||
1004 | /** | 1005 | /** |
1005 | * tomoyo_put_name - Drop reference on "struct tomoyo_name". | 1006 | * tomoyo_put_name - Drop reference on "struct tomoyo_name". |
1006 | * | 1007 | * |
1007 | * @name: Pointer to "struct tomoyo_path_info". Maybe NULL. | 1008 | * @name: Pointer to "struct tomoyo_path_info". Maybe NULL. |
1008 | * | 1009 | * |
1009 | * Returns nothing. | 1010 | * Returns nothing. |
1010 | */ | 1011 | */ |
1011 | static inline void tomoyo_put_name(const struct tomoyo_path_info *name) | 1012 | static inline void tomoyo_put_name(const struct tomoyo_path_info *name) |
1012 | { | 1013 | { |
1013 | if (name) { | 1014 | if (name) { |
1014 | struct tomoyo_name *ptr = | 1015 | struct tomoyo_name *ptr = |
1015 | container_of(name, typeof(*ptr), entry); | 1016 | container_of(name, typeof(*ptr), entry); |
1016 | atomic_dec(&ptr->head.users); | 1017 | atomic_dec(&ptr->head.users); |
1017 | } | 1018 | } |
1018 | } | 1019 | } |
1019 | 1020 | ||
1020 | /** | 1021 | /** |
1021 | * tomoyo_put_condition - Drop reference on "struct tomoyo_condition". | 1022 | * tomoyo_put_condition - Drop reference on "struct tomoyo_condition". |
1022 | * | 1023 | * |
1023 | * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. | 1024 | * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. |
1024 | * | 1025 | * |
1025 | * Returns nothing. | 1026 | * Returns nothing. |
1026 | */ | 1027 | */ |
1027 | static inline void tomoyo_put_condition(struct tomoyo_condition *cond) | 1028 | static inline void tomoyo_put_condition(struct tomoyo_condition *cond) |
1028 | { | 1029 | { |
1029 | if (cond) | 1030 | if (cond) |
1030 | atomic_dec(&cond->head.users); | 1031 | atomic_dec(&cond->head.users); |
1031 | } | 1032 | } |
1032 | 1033 | ||
1033 | /** | 1034 | /** |
1034 | * tomoyo_put_group - Drop reference on "struct tomoyo_group". | 1035 | * tomoyo_put_group - Drop reference on "struct tomoyo_group". |
1035 | * | 1036 | * |
1036 | * @group: Pointer to "struct tomoyo_group". Maybe NULL. | 1037 | * @group: Pointer to "struct tomoyo_group". Maybe NULL. |
1037 | * | 1038 | * |
1038 | * Returns nothing. | 1039 | * Returns nothing. |
1039 | */ | 1040 | */ |
1040 | static inline void tomoyo_put_group(struct tomoyo_group *group) | 1041 | static inline void tomoyo_put_group(struct tomoyo_group *group) |
1041 | { | 1042 | { |
1042 | if (group) | 1043 | if (group) |
1043 | atomic_dec(&group->head.users); | 1044 | atomic_dec(&group->head.users); |
1044 | } | 1045 | } |
1045 | 1046 | ||
1046 | /** | 1047 | /** |
1047 | * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. | 1048 | * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. |
1048 | * | 1049 | * |
1049 | * Returns pointer to "struct tomoyo_domain_info" for current thread. | 1050 | * Returns pointer to "struct tomoyo_domain_info" for current thread. |
1050 | */ | 1051 | */ |
1051 | static inline struct tomoyo_domain_info *tomoyo_domain(void) | 1052 | static inline struct tomoyo_domain_info *tomoyo_domain(void) |
1052 | { | 1053 | { |
1053 | return current_cred()->security; | 1054 | return current_cred()->security; |
1054 | } | 1055 | } |
1055 | 1056 | ||
1056 | /** | 1057 | /** |
1057 | * tomoyo_real_domain - Get "struct tomoyo_domain_info" for specified thread. | 1058 | * tomoyo_real_domain - Get "struct tomoyo_domain_info" for specified thread. |
1058 | * | 1059 | * |
1059 | * @task: Pointer to "struct task_struct". | 1060 | * @task: Pointer to "struct task_struct". |
1060 | * | 1061 | * |
1061 | * Returns pointer to "struct tomoyo_security" for specified thread. | 1062 | * Returns pointer to "struct tomoyo_security" for specified thread. |
1062 | */ | 1063 | */ |
1063 | static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct | 1064 | static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct |
1064 | *task) | 1065 | *task) |
1065 | { | 1066 | { |
1066 | return task_cred_xxx(task, security); | 1067 | return task_cred_xxx(task, security); |
1067 | } | 1068 | } |
1068 | 1069 | ||
1069 | /** | 1070 | /** |
1070 | * tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry. | 1071 | * tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry. |
1071 | * | 1072 | * |
1072 | * @a: Pointer to "struct tomoyo_name_union". | 1073 | * @a: Pointer to "struct tomoyo_name_union". |
1073 | * @b: Pointer to "struct tomoyo_name_union". | 1074 | * @b: Pointer to "struct tomoyo_name_union". |
1074 | * | 1075 | * |
1075 | * Returns true if @a == @b, false otherwise. | 1076 | * Returns true if @a == @b, false otherwise. |
1076 | */ | 1077 | */ |
1077 | static inline bool tomoyo_same_name_union | 1078 | static inline bool tomoyo_same_name_union |
1078 | (const struct tomoyo_name_union *a, const struct tomoyo_name_union *b) | 1079 | (const struct tomoyo_name_union *a, const struct tomoyo_name_union *b) |
1079 | { | 1080 | { |
1080 | return a->filename == b->filename && a->group == b->group; | 1081 | return a->filename == b->filename && a->group == b->group; |
1081 | } | 1082 | } |
1082 | 1083 | ||
1083 | /** | 1084 | /** |
1084 | * tomoyo_same_number_union - Check for duplicated "struct tomoyo_number_union" entry. | 1085 | * tomoyo_same_number_union - Check for duplicated "struct tomoyo_number_union" entry. |
1085 | * | 1086 | * |
1086 | * @a: Pointer to "struct tomoyo_number_union". | 1087 | * @a: Pointer to "struct tomoyo_number_union". |
1087 | * @b: Pointer to "struct tomoyo_number_union". | 1088 | * @b: Pointer to "struct tomoyo_number_union". |
1088 | * | 1089 | * |
1089 | * Returns true if @a == @b, false otherwise. | 1090 | * Returns true if @a == @b, false otherwise. |
1090 | */ | 1091 | */ |
1091 | static inline bool tomoyo_same_number_union | 1092 | static inline bool tomoyo_same_number_union |
1092 | (const struct tomoyo_number_union *a, const struct tomoyo_number_union *b) | 1093 | (const struct tomoyo_number_union *a, const struct tomoyo_number_union *b) |
1093 | { | 1094 | { |
1094 | return a->values[0] == b->values[0] && a->values[1] == b->values[1] && | 1095 | return a->values[0] == b->values[0] && a->values[1] == b->values[1] && |
1095 | a->group == b->group && a->value_type[0] == b->value_type[0] && | 1096 | a->group == b->group && a->value_type[0] == b->value_type[0] && |
1096 | a->value_type[1] == b->value_type[1]; | 1097 | a->value_type[1] == b->value_type[1]; |
1097 | } | 1098 | } |
1098 | 1099 | ||
1099 | /** | 1100 | /** |
1100 | * tomoyo_current_namespace - Get "struct tomoyo_policy_namespace" for current thread. | 1101 | * tomoyo_current_namespace - Get "struct tomoyo_policy_namespace" for current thread. |
1101 | * | 1102 | * |
1102 | * Returns pointer to "struct tomoyo_policy_namespace" for current thread. | 1103 | * Returns pointer to "struct tomoyo_policy_namespace" for current thread. |
1103 | */ | 1104 | */ |
1104 | static inline struct tomoyo_policy_namespace *tomoyo_current_namespace(void) | 1105 | static inline struct tomoyo_policy_namespace *tomoyo_current_namespace(void) |
1105 | { | 1106 | { |
1106 | return tomoyo_domain()->ns; | 1107 | return tomoyo_domain()->ns; |
1107 | } | 1108 | } |
1108 | 1109 | ||
1109 | #if defined(CONFIG_SLOB) | 1110 | #if defined(CONFIG_SLOB) |
1110 | 1111 | ||
1111 | /** | 1112 | /** |
1112 | * tomoyo_round2 - Round up to power of 2 for calculating memory usage. | 1113 | * tomoyo_round2 - Round up to power of 2 for calculating memory usage. |
1113 | * | 1114 | * |
1114 | * @size: Size to be rounded up. | 1115 | * @size: Size to be rounded up. |
1115 | * | 1116 | * |
1116 | * Returns @size. | 1117 | * Returns @size. |
1117 | * | 1118 | * |
1118 | * Since SLOB does not round up, this function simply returns @size. | 1119 | * Since SLOB does not round up, this function simply returns @size. |
1119 | */ | 1120 | */ |
1120 | static inline int tomoyo_round2(size_t size) | 1121 | static inline int tomoyo_round2(size_t size) |
1121 | { | 1122 | { |
1122 | return size; | 1123 | return size; |
1123 | } | 1124 | } |
1124 | 1125 | ||
1125 | #else | 1126 | #else |
1126 | 1127 | ||
1127 | /** | 1128 | /** |
1128 | * tomoyo_round2 - Round up to power of 2 for calculating memory usage. | 1129 | * tomoyo_round2 - Round up to power of 2 for calculating memory usage. |
1129 | * | 1130 | * |
1130 | * @size: Size to be rounded up. | 1131 | * @size: Size to be rounded up. |
1131 | * | 1132 | * |
1132 | * Returns rounded size. | 1133 | * Returns rounded size. |
1133 | * | 1134 | * |
1134 | * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of | 1135 | * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of |
1135 | * (e.g.) 128 bytes. | 1136 | * (e.g.) 128 bytes. |
1136 | */ | 1137 | */ |
1137 | static inline int tomoyo_round2(size_t size) | 1138 | static inline int tomoyo_round2(size_t size) |
1138 | { | 1139 | { |
1139 | #if PAGE_SIZE == 4096 | 1140 | #if PAGE_SIZE == 4096 |
1140 | size_t bsize = 32; | 1141 | size_t bsize = 32; |
1141 | #else | 1142 | #else |
1142 | size_t bsize = 64; | 1143 | size_t bsize = 64; |
1143 | #endif | 1144 | #endif |
1144 | if (!size) | 1145 | if (!size) |
1145 | return 0; | 1146 | return 0; |
1146 | while (size > bsize) | 1147 | while (size > bsize) |
1147 | bsize <<= 1; | 1148 | bsize <<= 1; |
1148 | return bsize; | 1149 | return bsize; |
1149 | } | 1150 | } |
1150 | 1151 | ||
1151 | #endif | 1152 | #endif |
1152 | 1153 | ||
1153 | /** | 1154 | /** |
1154 | * list_for_each_cookie - iterate over a list with cookie. | 1155 | * list_for_each_cookie - iterate over a list with cookie. |
1155 | * @pos: the &struct list_head to use as a loop cursor. | 1156 | * @pos: the &struct list_head to use as a loop cursor. |
1156 | * @head: the head for your list. | 1157 | * @head: the head for your list. |
1157 | */ | 1158 | */ |
1158 | #define list_for_each_cookie(pos, head) \ | 1159 | #define list_for_each_cookie(pos, head) \ |
1159 | if (!pos) \ | 1160 | if (!pos) \ |
1160 | pos = srcu_dereference((head)->next, &tomoyo_ss); \ | 1161 | pos = srcu_dereference((head)->next, &tomoyo_ss); \ |
1161 | for ( ; pos != (head); pos = srcu_dereference(pos->next, &tomoyo_ss)) | 1162 | for ( ; pos != (head); pos = srcu_dereference(pos->next, &tomoyo_ss)) |
1162 | 1163 | ||
1163 | #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ | 1164 | #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ |
1164 | 1165 |
security/tomoyo/domain.c
1 | /* | 1 | /* |
2 | * security/tomoyo/domain.c | 2 | * security/tomoyo/domain.c |
3 | * | 3 | * |
4 | * Domain transition functions for TOMOYO. | 4 | * Domain transition functions for TOMOYO. |
5 | * | 5 | * |
6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION | 6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "common.h" | 9 | #include "common.h" |
10 | #include <linux/binfmts.h> | 10 | #include <linux/binfmts.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | 12 | ||
13 | /* Variables definitions.*/ | 13 | /* Variables definitions.*/ |
14 | 14 | ||
15 | /* The initial domain. */ | 15 | /* The initial domain. */ |
16 | struct tomoyo_domain_info tomoyo_kernel_domain; | 16 | struct tomoyo_domain_info tomoyo_kernel_domain; |
17 | 17 | ||
18 | /** | 18 | /** |
19 | * tomoyo_update_policy - Update an entry for exception policy. | 19 | * tomoyo_update_policy - Update an entry for exception policy. |
20 | * | 20 | * |
21 | * @new_entry: Pointer to "struct tomoyo_acl_info". | 21 | * @new_entry: Pointer to "struct tomoyo_acl_info". |
22 | * @size: Size of @new_entry in bytes. | 22 | * @size: Size of @new_entry in bytes. |
23 | * @param: Pointer to "struct tomoyo_acl_param". | 23 | * @param: Pointer to "struct tomoyo_acl_param". |
24 | * @check_duplicate: Callback function to find duplicated entry. | 24 | * @check_duplicate: Callback function to find duplicated entry. |
25 | * | 25 | * |
26 | * Returns 0 on success, negative value otherwise. | 26 | * Returns 0 on success, negative value otherwise. |
27 | * | 27 | * |
28 | * Caller holds tomoyo_read_lock(). | 28 | * Caller holds tomoyo_read_lock(). |
29 | */ | 29 | */ |
30 | int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, | 30 | int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, |
31 | struct tomoyo_acl_param *param, | 31 | struct tomoyo_acl_param *param, |
32 | bool (*check_duplicate) (const struct tomoyo_acl_head | 32 | bool (*check_duplicate) (const struct tomoyo_acl_head |
33 | *, | 33 | *, |
34 | const struct tomoyo_acl_head | 34 | const struct tomoyo_acl_head |
35 | *)) | 35 | *)) |
36 | { | 36 | { |
37 | int error = param->is_delete ? -ENOENT : -ENOMEM; | 37 | int error = param->is_delete ? -ENOENT : -ENOMEM; |
38 | struct tomoyo_acl_head *entry; | 38 | struct tomoyo_acl_head *entry; |
39 | struct list_head *list = param->list; | 39 | struct list_head *list = param->list; |
40 | 40 | ||
41 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 41 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
42 | return -ENOMEM; | 42 | return -ENOMEM; |
43 | list_for_each_entry_rcu(entry, list, list) { | 43 | list_for_each_entry_rcu(entry, list, list) { |
44 | if (!check_duplicate(entry, new_entry)) | 44 | if (!check_duplicate(entry, new_entry)) |
45 | continue; | 45 | continue; |
46 | entry->is_deleted = param->is_delete; | 46 | entry->is_deleted = param->is_delete; |
47 | error = 0; | 47 | error = 0; |
48 | break; | 48 | break; |
49 | } | 49 | } |
50 | if (error && !param->is_delete) { | 50 | if (error && !param->is_delete) { |
51 | entry = tomoyo_commit_ok(new_entry, size); | 51 | entry = tomoyo_commit_ok(new_entry, size); |
52 | if (entry) { | 52 | if (entry) { |
53 | list_add_tail_rcu(&entry->list, list); | 53 | list_add_tail_rcu(&entry->list, list); |
54 | error = 0; | 54 | error = 0; |
55 | } | 55 | } |
56 | } | 56 | } |
57 | mutex_unlock(&tomoyo_policy_lock); | 57 | mutex_unlock(&tomoyo_policy_lock); |
58 | return error; | 58 | return error; |
59 | } | 59 | } |
60 | 60 | ||
61 | /** | 61 | /** |
62 | * tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry. | 62 | * tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry. |
63 | * | 63 | * |
64 | * @a: Pointer to "struct tomoyo_acl_info". | 64 | * @a: Pointer to "struct tomoyo_acl_info". |
65 | * @b: Pointer to "struct tomoyo_acl_info". | 65 | * @b: Pointer to "struct tomoyo_acl_info". |
66 | * | 66 | * |
67 | * Returns true if @a == @b, false otherwise. | 67 | * Returns true if @a == @b, false otherwise. |
68 | */ | 68 | */ |
69 | static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, | 69 | static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, |
70 | const struct tomoyo_acl_info *b) | 70 | const struct tomoyo_acl_info *b) |
71 | { | 71 | { |
72 | return a->type == b->type && a->cond == b->cond; | 72 | return a->type == b->type && a->cond == b->cond; |
73 | } | 73 | } |
74 | 74 | ||
75 | /** | 75 | /** |
76 | * tomoyo_update_domain - Update an entry for domain policy. | 76 | * tomoyo_update_domain - Update an entry for domain policy. |
77 | * | 77 | * |
78 | * @new_entry: Pointer to "struct tomoyo_acl_info". | 78 | * @new_entry: Pointer to "struct tomoyo_acl_info". |
79 | * @size: Size of @new_entry in bytes. | 79 | * @size: Size of @new_entry in bytes. |
80 | * @param: Pointer to "struct tomoyo_acl_param". | 80 | * @param: Pointer to "struct tomoyo_acl_param". |
81 | * @check_duplicate: Callback function to find duplicated entry. | 81 | * @check_duplicate: Callback function to find duplicated entry. |
82 | * @merge_duplicate: Callback function to merge duplicated entry. | 82 | * @merge_duplicate: Callback function to merge duplicated entry. |
83 | * | 83 | * |
84 | * Returns 0 on success, negative value otherwise. | 84 | * Returns 0 on success, negative value otherwise. |
85 | * | 85 | * |
86 | * Caller holds tomoyo_read_lock(). | 86 | * Caller holds tomoyo_read_lock(). |
87 | */ | 87 | */ |
88 | int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, | 88 | int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, |
89 | struct tomoyo_acl_param *param, | 89 | struct tomoyo_acl_param *param, |
90 | bool (*check_duplicate) (const struct tomoyo_acl_info | 90 | bool (*check_duplicate) (const struct tomoyo_acl_info |
91 | *, | 91 | *, |
92 | const struct tomoyo_acl_info | 92 | const struct tomoyo_acl_info |
93 | *), | 93 | *), |
94 | bool (*merge_duplicate) (struct tomoyo_acl_info *, | 94 | bool (*merge_duplicate) (struct tomoyo_acl_info *, |
95 | struct tomoyo_acl_info *, | 95 | struct tomoyo_acl_info *, |
96 | const bool)) | 96 | const bool)) |
97 | { | 97 | { |
98 | const bool is_delete = param->is_delete; | 98 | const bool is_delete = param->is_delete; |
99 | int error = is_delete ? -ENOENT : -ENOMEM; | 99 | int error = is_delete ? -ENOENT : -ENOMEM; |
100 | struct tomoyo_acl_info *entry; | 100 | struct tomoyo_acl_info *entry; |
101 | struct list_head * const list = param->list; | 101 | struct list_head * const list = param->list; |
102 | 102 | ||
103 | if (param->data[0]) { | 103 | if (param->data[0]) { |
104 | new_entry->cond = tomoyo_get_condition(param); | 104 | new_entry->cond = tomoyo_get_condition(param); |
105 | if (!new_entry->cond) | 105 | if (!new_entry->cond) |
106 | return -EINVAL; | 106 | return -EINVAL; |
107 | } | 107 | } |
108 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 108 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
109 | goto out; | 109 | goto out; |
110 | list_for_each_entry_rcu(entry, list, list) { | 110 | list_for_each_entry_rcu(entry, list, list) { |
111 | if (!tomoyo_same_acl_head(entry, new_entry) || | 111 | if (!tomoyo_same_acl_head(entry, new_entry) || |
112 | !check_duplicate(entry, new_entry)) | 112 | !check_duplicate(entry, new_entry)) |
113 | continue; | 113 | continue; |
114 | if (merge_duplicate) | 114 | if (merge_duplicate) |
115 | entry->is_deleted = merge_duplicate(entry, new_entry, | 115 | entry->is_deleted = merge_duplicate(entry, new_entry, |
116 | is_delete); | 116 | is_delete); |
117 | else | 117 | else |
118 | entry->is_deleted = is_delete; | 118 | entry->is_deleted = is_delete; |
119 | error = 0; | 119 | error = 0; |
120 | break; | 120 | break; |
121 | } | 121 | } |
122 | if (error && !is_delete) { | 122 | if (error && !is_delete) { |
123 | entry = tomoyo_commit_ok(new_entry, size); | 123 | entry = tomoyo_commit_ok(new_entry, size); |
124 | if (entry) { | 124 | if (entry) { |
125 | list_add_tail_rcu(&entry->list, list); | 125 | list_add_tail_rcu(&entry->list, list); |
126 | error = 0; | 126 | error = 0; |
127 | } | 127 | } |
128 | } | 128 | } |
129 | mutex_unlock(&tomoyo_policy_lock); | 129 | mutex_unlock(&tomoyo_policy_lock); |
130 | out: | 130 | out: |
131 | tomoyo_put_condition(new_entry->cond); | 131 | tomoyo_put_condition(new_entry->cond); |
132 | return error; | 132 | return error; |
133 | } | 133 | } |
134 | 134 | ||
135 | /** | 135 | /** |
136 | * tomoyo_check_acl - Do permission check. | 136 | * tomoyo_check_acl - Do permission check. |
137 | * | 137 | * |
138 | * @r: Pointer to "struct tomoyo_request_info". | 138 | * @r: Pointer to "struct tomoyo_request_info". |
139 | * @check_entry: Callback function to check type specific parameters. | 139 | * @check_entry: Callback function to check type specific parameters. |
140 | * | 140 | * |
141 | * Returns 0 on success, negative value otherwise. | 141 | * Returns 0 on success, negative value otherwise. |
142 | * | 142 | * |
143 | * Caller holds tomoyo_read_lock(). | 143 | * Caller holds tomoyo_read_lock(). |
144 | */ | 144 | */ |
145 | void tomoyo_check_acl(struct tomoyo_request_info *r, | 145 | void tomoyo_check_acl(struct tomoyo_request_info *r, |
146 | bool (*check_entry) (struct tomoyo_request_info *, | 146 | bool (*check_entry) (struct tomoyo_request_info *, |
147 | const struct tomoyo_acl_info *)) | 147 | const struct tomoyo_acl_info *)) |
148 | { | 148 | { |
149 | const struct tomoyo_domain_info *domain = r->domain; | 149 | const struct tomoyo_domain_info *domain = r->domain; |
150 | struct tomoyo_acl_info *ptr; | 150 | struct tomoyo_acl_info *ptr; |
151 | bool retried = false; | 151 | bool retried = false; |
152 | const struct list_head *list = &domain->acl_info_list; | 152 | const struct list_head *list = &domain->acl_info_list; |
153 | 153 | ||
154 | retry: | 154 | retry: |
155 | list_for_each_entry_rcu(ptr, list, list) { | 155 | list_for_each_entry_rcu(ptr, list, list) { |
156 | if (ptr->is_deleted || ptr->type != r->param_type) | 156 | if (ptr->is_deleted || ptr->type != r->param_type) |
157 | continue; | 157 | continue; |
158 | if (!check_entry(r, ptr)) | 158 | if (!check_entry(r, ptr)) |
159 | continue; | 159 | continue; |
160 | if (!tomoyo_condition(r, ptr->cond)) | 160 | if (!tomoyo_condition(r, ptr->cond)) |
161 | continue; | 161 | continue; |
162 | r->granted = true; | 162 | r->granted = true; |
163 | return; | 163 | return; |
164 | } | 164 | } |
165 | if (!retried) { | 165 | if (!retried) { |
166 | retried = true; | 166 | retried = true; |
167 | list = &domain->ns->acl_group[domain->group]; | 167 | list = &domain->ns->acl_group[domain->group]; |
168 | goto retry; | 168 | goto retry; |
169 | } | 169 | } |
170 | r->granted = false; | 170 | r->granted = false; |
171 | } | 171 | } |
172 | 172 | ||
173 | /* The list for "struct tomoyo_domain_info". */ | 173 | /* The list for "struct tomoyo_domain_info". */ |
174 | LIST_HEAD(tomoyo_domain_list); | 174 | LIST_HEAD(tomoyo_domain_list); |
175 | 175 | ||
176 | /** | 176 | /** |
177 | * tomoyo_last_word - Get last component of a domainname. | 177 | * tomoyo_last_word - Get last component of a domainname. |
178 | * | 178 | * |
179 | * @name: Domainname to check. | 179 | * @name: Domainname to check. |
180 | * | 180 | * |
181 | * Returns the last word of @domainname. | 181 | * Returns the last word of @domainname. |
182 | */ | 182 | */ |
183 | static const char *tomoyo_last_word(const char *name) | 183 | static const char *tomoyo_last_word(const char *name) |
184 | { | 184 | { |
185 | const char *cp = strrchr(name, ' '); | 185 | const char *cp = strrchr(name, ' '); |
186 | if (cp) | 186 | if (cp) |
187 | return cp + 1; | 187 | return cp + 1; |
188 | return name; | 188 | return name; |
189 | } | 189 | } |
190 | 190 | ||
191 | /** | 191 | /** |
192 | * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry. | 192 | * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry. |
193 | * | 193 | * |
194 | * @a: Pointer to "struct tomoyo_acl_head". | 194 | * @a: Pointer to "struct tomoyo_acl_head". |
195 | * @b: Pointer to "struct tomoyo_acl_head". | 195 | * @b: Pointer to "struct tomoyo_acl_head". |
196 | * | 196 | * |
197 | * Returns true if @a == @b, false otherwise. | 197 | * Returns true if @a == @b, false otherwise. |
198 | */ | 198 | */ |
199 | static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, | 199 | static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, |
200 | const struct tomoyo_acl_head *b) | 200 | const struct tomoyo_acl_head *b) |
201 | { | 201 | { |
202 | const struct tomoyo_transition_control *p1 = container_of(a, | 202 | const struct tomoyo_transition_control *p1 = container_of(a, |
203 | typeof(*p1), | 203 | typeof(*p1), |
204 | head); | 204 | head); |
205 | const struct tomoyo_transition_control *p2 = container_of(b, | 205 | const struct tomoyo_transition_control *p2 = container_of(b, |
206 | typeof(*p2), | 206 | typeof(*p2), |
207 | head); | 207 | head); |
208 | return p1->type == p2->type && p1->is_last_name == p2->is_last_name | 208 | return p1->type == p2->type && p1->is_last_name == p2->is_last_name |
209 | && p1->domainname == p2->domainname | 209 | && p1->domainname == p2->domainname |
210 | && p1->program == p2->program; | 210 | && p1->program == p2->program; |
211 | } | 211 | } |
212 | 212 | ||
213 | /** | 213 | /** |
214 | * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list. | 214 | * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list. |
215 | * | 215 | * |
216 | * @param: Pointer to "struct tomoyo_acl_param". | 216 | * @param: Pointer to "struct tomoyo_acl_param". |
217 | * @type: Type of this entry. | 217 | * @type: Type of this entry. |
218 | * | 218 | * |
219 | * Returns 0 on success, negative value otherwise. | 219 | * Returns 0 on success, negative value otherwise. |
220 | */ | 220 | */ |
221 | int tomoyo_write_transition_control(struct tomoyo_acl_param *param, | 221 | int tomoyo_write_transition_control(struct tomoyo_acl_param *param, |
222 | const u8 type) | 222 | const u8 type) |
223 | { | 223 | { |
224 | struct tomoyo_transition_control e = { .type = type }; | 224 | struct tomoyo_transition_control e = { .type = type }; |
225 | int error = param->is_delete ? -ENOENT : -ENOMEM; | 225 | int error = param->is_delete ? -ENOENT : -ENOMEM; |
226 | char *program = param->data; | 226 | char *program = param->data; |
227 | char *domainname = strstr(program, " from "); | 227 | char *domainname = strstr(program, " from "); |
228 | if (domainname) { | 228 | if (domainname) { |
229 | *domainname = '\0'; | 229 | *domainname = '\0'; |
230 | domainname += 6; | 230 | domainname += 6; |
231 | } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP || | 231 | } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP || |
232 | type == TOMOYO_TRANSITION_CONTROL_KEEP) { | 232 | type == TOMOYO_TRANSITION_CONTROL_KEEP) { |
233 | domainname = program; | 233 | domainname = program; |
234 | program = NULL; | 234 | program = NULL; |
235 | } | 235 | } |
236 | if (program && strcmp(program, "any")) { | 236 | if (program && strcmp(program, "any")) { |
237 | if (!tomoyo_correct_path(program)) | 237 | if (!tomoyo_correct_path(program)) |
238 | return -EINVAL; | 238 | return -EINVAL; |
239 | e.program = tomoyo_get_name(program); | 239 | e.program = tomoyo_get_name(program); |
240 | if (!e.program) | 240 | if (!e.program) |
241 | goto out; | 241 | goto out; |
242 | } | 242 | } |
243 | if (domainname && strcmp(domainname, "any")) { | 243 | if (domainname && strcmp(domainname, "any")) { |
244 | if (!tomoyo_correct_domain(domainname)) { | 244 | if (!tomoyo_correct_domain(domainname)) { |
245 | if (!tomoyo_correct_path(domainname)) | 245 | if (!tomoyo_correct_path(domainname)) |
246 | goto out; | 246 | goto out; |
247 | e.is_last_name = true; | 247 | e.is_last_name = true; |
248 | } | 248 | } |
249 | e.domainname = tomoyo_get_name(domainname); | 249 | e.domainname = tomoyo_get_name(domainname); |
250 | if (!e.domainname) | 250 | if (!e.domainname) |
251 | goto out; | 251 | goto out; |
252 | } | 252 | } |
253 | param->list = ¶m->ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; | 253 | param->list = ¶m->ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; |
254 | error = tomoyo_update_policy(&e.head, sizeof(e), param, | 254 | error = tomoyo_update_policy(&e.head, sizeof(e), param, |
255 | tomoyo_same_transition_control); | 255 | tomoyo_same_transition_control); |
256 | out: | 256 | out: |
257 | tomoyo_put_name(e.domainname); | 257 | tomoyo_put_name(e.domainname); |
258 | tomoyo_put_name(e.program); | 258 | tomoyo_put_name(e.program); |
259 | return error; | 259 | return error; |
260 | } | 260 | } |
261 | 261 | ||
262 | /** | 262 | /** |
263 | * tomoyo_scan_transition - Try to find specific domain transition type. | 263 | * tomoyo_scan_transition - Try to find specific domain transition type. |
264 | * | 264 | * |
265 | * @list: Pointer to "struct list_head". | 265 | * @list: Pointer to "struct list_head". |
266 | * @domainname: The name of current domain. | 266 | * @domainname: The name of current domain. |
267 | * @program: The name of requested program. | 267 | * @program: The name of requested program. |
268 | * @last_name: The last component of @domainname. | 268 | * @last_name: The last component of @domainname. |
269 | * @type: One of values in "enum tomoyo_transition_type". | 269 | * @type: One of values in "enum tomoyo_transition_type". |
270 | * | 270 | * |
271 | * Returns true if found one, false otherwise. | 271 | * Returns true if found one, false otherwise. |
272 | * | 272 | * |
273 | * Caller holds tomoyo_read_lock(). | 273 | * Caller holds tomoyo_read_lock(). |
274 | */ | 274 | */ |
275 | static inline bool tomoyo_scan_transition | 275 | static inline bool tomoyo_scan_transition |
276 | (const struct list_head *list, const struct tomoyo_path_info *domainname, | 276 | (const struct list_head *list, const struct tomoyo_path_info *domainname, |
277 | const struct tomoyo_path_info *program, const char *last_name, | 277 | const struct tomoyo_path_info *program, const char *last_name, |
278 | const enum tomoyo_transition_type type) | 278 | const enum tomoyo_transition_type type) |
279 | { | 279 | { |
280 | const struct tomoyo_transition_control *ptr; | 280 | const struct tomoyo_transition_control *ptr; |
281 | list_for_each_entry_rcu(ptr, list, head.list) { | 281 | list_for_each_entry_rcu(ptr, list, head.list) { |
282 | if (ptr->head.is_deleted || ptr->type != type) | 282 | if (ptr->head.is_deleted || ptr->type != type) |
283 | continue; | 283 | continue; |
284 | if (ptr->domainname) { | 284 | if (ptr->domainname) { |
285 | if (!ptr->is_last_name) { | 285 | if (!ptr->is_last_name) { |
286 | if (ptr->domainname != domainname) | 286 | if (ptr->domainname != domainname) |
287 | continue; | 287 | continue; |
288 | } else { | 288 | } else { |
289 | /* | 289 | /* |
290 | * Use direct strcmp() since this is | 290 | * Use direct strcmp() since this is |
291 | * unlikely used. | 291 | * unlikely used. |
292 | */ | 292 | */ |
293 | if (strcmp(ptr->domainname->name, last_name)) | 293 | if (strcmp(ptr->domainname->name, last_name)) |
294 | continue; | 294 | continue; |
295 | } | 295 | } |
296 | } | 296 | } |
297 | if (ptr->program && tomoyo_pathcmp(ptr->program, program)) | 297 | if (ptr->program && tomoyo_pathcmp(ptr->program, program)) |
298 | continue; | 298 | continue; |
299 | return true; | 299 | return true; |
300 | } | 300 | } |
301 | return false; | 301 | return false; |
302 | } | 302 | } |
303 | 303 | ||
304 | /** | 304 | /** |
305 | * tomoyo_transition_type - Get domain transition type. | 305 | * tomoyo_transition_type - Get domain transition type. |
306 | * | 306 | * |
307 | * @ns: Pointer to "struct tomoyo_policy_namespace". | 307 | * @ns: Pointer to "struct tomoyo_policy_namespace". |
308 | * @domainname: The name of current domain. | 308 | * @domainname: The name of current domain. |
309 | * @program: The name of requested program. | 309 | * @program: The name of requested program. |
310 | * | 310 | * |
311 | * Returns TOMOYO_TRANSITION_CONTROL_TRANSIT if executing @program causes | 311 | * Returns TOMOYO_TRANSITION_CONTROL_TRANSIT if executing @program causes |
312 | * domain transition across namespaces, TOMOYO_TRANSITION_CONTROL_INITIALIZE if | 312 | * domain transition across namespaces, TOMOYO_TRANSITION_CONTROL_INITIALIZE if |
313 | * executing @program reinitializes domain transition within that namespace, | 313 | * executing @program reinitializes domain transition within that namespace, |
314 | * TOMOYO_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname , | 314 | * TOMOYO_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname , |
315 | * others otherwise. | 315 | * others otherwise. |
316 | * | 316 | * |
317 | * Caller holds tomoyo_read_lock(). | 317 | * Caller holds tomoyo_read_lock(). |
318 | */ | 318 | */ |
319 | static enum tomoyo_transition_type tomoyo_transition_type | 319 | static enum tomoyo_transition_type tomoyo_transition_type |
320 | (const struct tomoyo_policy_namespace *ns, | 320 | (const struct tomoyo_policy_namespace *ns, |
321 | const struct tomoyo_path_info *domainname, | 321 | const struct tomoyo_path_info *domainname, |
322 | const struct tomoyo_path_info *program) | 322 | const struct tomoyo_path_info *program) |
323 | { | 323 | { |
324 | const char *last_name = tomoyo_last_word(domainname->name); | 324 | const char *last_name = tomoyo_last_word(domainname->name); |
325 | enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET; | 325 | enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET; |
326 | while (type < TOMOYO_MAX_TRANSITION_TYPE) { | 326 | while (type < TOMOYO_MAX_TRANSITION_TYPE) { |
327 | const struct list_head * const list = | 327 | const struct list_head * const list = |
328 | &ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; | 328 | &ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; |
329 | if (!tomoyo_scan_transition(list, domainname, program, | 329 | if (!tomoyo_scan_transition(list, domainname, program, |
330 | last_name, type)) { | 330 | last_name, type)) { |
331 | type++; | 331 | type++; |
332 | continue; | 332 | continue; |
333 | } | 333 | } |
334 | if (type != TOMOYO_TRANSITION_CONTROL_NO_RESET && | 334 | if (type != TOMOYO_TRANSITION_CONTROL_NO_RESET && |
335 | type != TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) | 335 | type != TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) |
336 | break; | 336 | break; |
337 | /* | 337 | /* |
338 | * Do not check for reset_domain if no_reset_domain matched. | 338 | * Do not check for reset_domain if no_reset_domain matched. |
339 | * Do not check for initialize_domain if no_initialize_domain | 339 | * Do not check for initialize_domain if no_initialize_domain |
340 | * matched. | 340 | * matched. |
341 | */ | 341 | */ |
342 | type++; | 342 | type++; |
343 | type++; | 343 | type++; |
344 | } | 344 | } |
345 | return type; | 345 | return type; |
346 | } | 346 | } |
347 | 347 | ||
348 | /** | 348 | /** |
349 | * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry. | 349 | * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry. |
350 | * | 350 | * |
351 | * @a: Pointer to "struct tomoyo_acl_head". | 351 | * @a: Pointer to "struct tomoyo_acl_head". |
352 | * @b: Pointer to "struct tomoyo_acl_head". | 352 | * @b: Pointer to "struct tomoyo_acl_head". |
353 | * | 353 | * |
354 | * Returns true if @a == @b, false otherwise. | 354 | * Returns true if @a == @b, false otherwise. |
355 | */ | 355 | */ |
356 | static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, | 356 | static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, |
357 | const struct tomoyo_acl_head *b) | 357 | const struct tomoyo_acl_head *b) |
358 | { | 358 | { |
359 | const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), | 359 | const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), |
360 | head); | 360 | head); |
361 | const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), | 361 | const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), |
362 | head); | 362 | head); |
363 | return p1->original_name == p2->original_name && | 363 | return p1->original_name == p2->original_name && |
364 | p1->aggregated_name == p2->aggregated_name; | 364 | p1->aggregated_name == p2->aggregated_name; |
365 | } | 365 | } |
366 | 366 | ||
367 | /** | 367 | /** |
368 | * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list. | 368 | * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list. |
369 | * | 369 | * |
370 | * @param: Pointer to "struct tomoyo_acl_param". | 370 | * @param: Pointer to "struct tomoyo_acl_param". |
371 | * | 371 | * |
372 | * Returns 0 on success, negative value otherwise. | 372 | * Returns 0 on success, negative value otherwise. |
373 | * | 373 | * |
374 | * Caller holds tomoyo_read_lock(). | 374 | * Caller holds tomoyo_read_lock(). |
375 | */ | 375 | */ |
376 | int tomoyo_write_aggregator(struct tomoyo_acl_param *param) | 376 | int tomoyo_write_aggregator(struct tomoyo_acl_param *param) |
377 | { | 377 | { |
378 | struct tomoyo_aggregator e = { }; | 378 | struct tomoyo_aggregator e = { }; |
379 | int error = param->is_delete ? -ENOENT : -ENOMEM; | 379 | int error = param->is_delete ? -ENOENT : -ENOMEM; |
380 | const char *original_name = tomoyo_read_token(param); | 380 | const char *original_name = tomoyo_read_token(param); |
381 | const char *aggregated_name = tomoyo_read_token(param); | 381 | const char *aggregated_name = tomoyo_read_token(param); |
382 | if (!tomoyo_correct_word(original_name) || | 382 | if (!tomoyo_correct_word(original_name) || |
383 | !tomoyo_correct_path(aggregated_name)) | 383 | !tomoyo_correct_path(aggregated_name)) |
384 | return -EINVAL; | 384 | return -EINVAL; |
385 | e.original_name = tomoyo_get_name(original_name); | 385 | e.original_name = tomoyo_get_name(original_name); |
386 | e.aggregated_name = tomoyo_get_name(aggregated_name); | 386 | e.aggregated_name = tomoyo_get_name(aggregated_name); |
387 | if (!e.original_name || !e.aggregated_name || | 387 | if (!e.original_name || !e.aggregated_name || |
388 | e.aggregated_name->is_patterned) /* No patterns allowed. */ | 388 | e.aggregated_name->is_patterned) /* No patterns allowed. */ |
389 | goto out; | 389 | goto out; |
390 | param->list = ¶m->ns->policy_list[TOMOYO_ID_AGGREGATOR]; | 390 | param->list = ¶m->ns->policy_list[TOMOYO_ID_AGGREGATOR]; |
391 | error = tomoyo_update_policy(&e.head, sizeof(e), param, | 391 | error = tomoyo_update_policy(&e.head, sizeof(e), param, |
392 | tomoyo_same_aggregator); | 392 | tomoyo_same_aggregator); |
393 | out: | 393 | out: |
394 | tomoyo_put_name(e.original_name); | 394 | tomoyo_put_name(e.original_name); |
395 | tomoyo_put_name(e.aggregated_name); | 395 | tomoyo_put_name(e.aggregated_name); |
396 | return error; | 396 | return error; |
397 | } | 397 | } |
398 | 398 | ||
399 | /** | 399 | /** |
400 | * tomoyo_find_namespace - Find specified namespace. | 400 | * tomoyo_find_namespace - Find specified namespace. |
401 | * | 401 | * |
402 | * @name: Name of namespace to find. | 402 | * @name: Name of namespace to find. |
403 | * @len: Length of @name. | 403 | * @len: Length of @name. |
404 | * | 404 | * |
405 | * Returns pointer to "struct tomoyo_policy_namespace" if found, | 405 | * Returns pointer to "struct tomoyo_policy_namespace" if found, |
406 | * NULL otherwise. | 406 | * NULL otherwise. |
407 | * | 407 | * |
408 | * Caller holds tomoyo_read_lock(). | 408 | * Caller holds tomoyo_read_lock(). |
409 | */ | 409 | */ |
410 | static struct tomoyo_policy_namespace *tomoyo_find_namespace | 410 | static struct tomoyo_policy_namespace *tomoyo_find_namespace |
411 | (const char *name, const unsigned int len) | 411 | (const char *name, const unsigned int len) |
412 | { | 412 | { |
413 | struct tomoyo_policy_namespace *ns; | 413 | struct tomoyo_policy_namespace *ns; |
414 | list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { | 414 | list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { |
415 | if (strncmp(name, ns->name, len) || | 415 | if (strncmp(name, ns->name, len) || |
416 | (name[len] && name[len] != ' ')) | 416 | (name[len] && name[len] != ' ')) |
417 | continue; | 417 | continue; |
418 | return ns; | 418 | return ns; |
419 | } | 419 | } |
420 | return NULL; | 420 | return NULL; |
421 | } | 421 | } |
422 | 422 | ||
423 | /** | 423 | /** |
424 | * tomoyo_assign_namespace - Create a new namespace. | 424 | * tomoyo_assign_namespace - Create a new namespace. |
425 | * | 425 | * |
426 | * @domainname: Name of namespace to create. | 426 | * @domainname: Name of namespace to create. |
427 | * | 427 | * |
428 | * Returns pointer to "struct tomoyo_policy_namespace" on success, | 428 | * Returns pointer to "struct tomoyo_policy_namespace" on success, |
429 | * NULL otherwise. | 429 | * NULL otherwise. |
430 | * | 430 | * |
431 | * Caller holds tomoyo_read_lock(). | 431 | * Caller holds tomoyo_read_lock(). |
432 | */ | 432 | */ |
433 | struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) | 433 | struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) |
434 | { | 434 | { |
435 | struct tomoyo_policy_namespace *ptr; | 435 | struct tomoyo_policy_namespace *ptr; |
436 | struct tomoyo_policy_namespace *entry; | 436 | struct tomoyo_policy_namespace *entry; |
437 | const char *cp = domainname; | 437 | const char *cp = domainname; |
438 | unsigned int len = 0; | 438 | unsigned int len = 0; |
439 | while (*cp && *cp++ != ' ') | 439 | while (*cp && *cp++ != ' ') |
440 | len++; | 440 | len++; |
441 | ptr = tomoyo_find_namespace(domainname, len); | 441 | ptr = tomoyo_find_namespace(domainname, len); |
442 | if (ptr) | 442 | if (ptr) |
443 | return ptr; | 443 | return ptr; |
444 | if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname)) | 444 | if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname)) |
445 | return NULL; | 445 | return NULL; |
446 | entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS); | 446 | entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS); |
447 | if (!entry) | 447 | if (!entry) |
448 | return NULL; | 448 | return NULL; |
449 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 449 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
450 | goto out; | 450 | goto out; |
451 | ptr = tomoyo_find_namespace(domainname, len); | 451 | ptr = tomoyo_find_namespace(domainname, len); |
452 | if (!ptr && tomoyo_memory_ok(entry)) { | 452 | if (!ptr && tomoyo_memory_ok(entry)) { |
453 | char *name = (char *) (entry + 1); | 453 | char *name = (char *) (entry + 1); |
454 | ptr = entry; | 454 | ptr = entry; |
455 | memmove(name, domainname, len); | 455 | memmove(name, domainname, len); |
456 | name[len] = '\0'; | 456 | name[len] = '\0'; |
457 | entry->name = name; | 457 | entry->name = name; |
458 | tomoyo_init_policy_namespace(entry); | 458 | tomoyo_init_policy_namespace(entry); |
459 | entry = NULL; | 459 | entry = NULL; |
460 | } | 460 | } |
461 | mutex_unlock(&tomoyo_policy_lock); | 461 | mutex_unlock(&tomoyo_policy_lock); |
462 | out: | 462 | out: |
463 | kfree(entry); | 463 | kfree(entry); |
464 | return ptr; | 464 | return ptr; |
465 | } | 465 | } |
466 | 466 | ||
467 | /** | 467 | /** |
468 | * tomoyo_namespace_jump - Check for namespace jump. | 468 | * tomoyo_namespace_jump - Check for namespace jump. |
469 | * | 469 | * |
470 | * @domainname: Name of domain. | 470 | * @domainname: Name of domain. |
471 | * | 471 | * |
472 | * Returns true if namespace differs, false otherwise. | 472 | * Returns true if namespace differs, false otherwise. |
473 | */ | 473 | */ |
474 | static bool tomoyo_namespace_jump(const char *domainname) | 474 | static bool tomoyo_namespace_jump(const char *domainname) |
475 | { | 475 | { |
476 | const char *namespace = tomoyo_current_namespace()->name; | 476 | const char *namespace = tomoyo_current_namespace()->name; |
477 | const int len = strlen(namespace); | 477 | const int len = strlen(namespace); |
478 | return strncmp(domainname, namespace, len) || | 478 | return strncmp(domainname, namespace, len) || |
479 | (domainname[len] && domainname[len] != ' '); | 479 | (domainname[len] && domainname[len] != ' '); |
480 | } | 480 | } |
481 | 481 | ||
482 | /** | 482 | /** |
483 | * tomoyo_assign_domain - Create a domain or a namespace. | 483 | * tomoyo_assign_domain - Create a domain or a namespace. |
484 | * | 484 | * |
485 | * @domainname: The name of domain. | 485 | * @domainname: The name of domain. |
486 | * @transit: True if transit to domain found or created. | 486 | * @transit: True if transit to domain found or created. |
487 | * | 487 | * |
488 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. | 488 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. |
489 | * | 489 | * |
490 | * Caller holds tomoyo_read_lock(). | 490 | * Caller holds tomoyo_read_lock(). |
491 | */ | 491 | */ |
492 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | 492 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, |
493 | const bool transit) | 493 | const bool transit) |
494 | { | 494 | { |
495 | struct tomoyo_domain_info e = { }; | 495 | struct tomoyo_domain_info e = { }; |
496 | struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname); | 496 | struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname); |
497 | bool created = false; | 497 | bool created = false; |
498 | if (entry) { | 498 | if (entry) { |
499 | if (transit) { | 499 | if (transit) { |
500 | /* | 500 | /* |
501 | * Since namespace is created at runtime, profiles may | 501 | * Since namespace is created at runtime, profiles may |
502 | * not be created by the moment the process transits to | 502 | * not be created by the moment the process transits to |
503 | * that domain. Do not perform domain transition if | 503 | * that domain. Do not perform domain transition if |
504 | * profile for that domain is not yet created. | 504 | * profile for that domain is not yet created. |
505 | */ | 505 | */ |
506 | if (!entry->ns->profile_ptr[entry->profile]) | 506 | if (!entry->ns->profile_ptr[entry->profile]) |
507 | return NULL; | 507 | return NULL; |
508 | } | 508 | } |
509 | return entry; | 509 | return entry; |
510 | } | 510 | } |
511 | /* Requested domain does not exist. */ | 511 | /* Requested domain does not exist. */ |
512 | /* Don't create requested domain if domainname is invalid. */ | 512 | /* Don't create requested domain if domainname is invalid. */ |
513 | if (strlen(domainname) >= TOMOYO_EXEC_TMPSIZE - 10 || | 513 | if (strlen(domainname) >= TOMOYO_EXEC_TMPSIZE - 10 || |
514 | !tomoyo_correct_domain(domainname)) | 514 | !tomoyo_correct_domain(domainname)) |
515 | return NULL; | 515 | return NULL; |
516 | /* | 516 | /* |
517 | * Since definition of profiles and acl_groups may differ across | 517 | * Since definition of profiles and acl_groups may differ across |
518 | * namespaces, do not inherit "use_profile" and "use_group" settings | 518 | * namespaces, do not inherit "use_profile" and "use_group" settings |
519 | * by automatically creating requested domain upon domain transition. | 519 | * by automatically creating requested domain upon domain transition. |
520 | */ | 520 | */ |
521 | if (transit && tomoyo_namespace_jump(domainname)) | 521 | if (transit && tomoyo_namespace_jump(domainname)) |
522 | return NULL; | 522 | return NULL; |
523 | e.ns = tomoyo_assign_namespace(domainname); | 523 | e.ns = tomoyo_assign_namespace(domainname); |
524 | if (!e.ns) | 524 | if (!e.ns) |
525 | return NULL; | 525 | return NULL; |
526 | /* | 526 | /* |
527 | * "use_profile" and "use_group" settings for automatically created | 527 | * "use_profile" and "use_group" settings for automatically created |
528 | * domains are inherited from current domain. These are 0 for manually | 528 | * domains are inherited from current domain. These are 0 for manually |
529 | * created domains. | 529 | * created domains. |
530 | */ | 530 | */ |
531 | if (transit) { | 531 | if (transit) { |
532 | const struct tomoyo_domain_info *domain = tomoyo_domain(); | 532 | const struct tomoyo_domain_info *domain = tomoyo_domain(); |
533 | e.profile = domain->profile; | 533 | e.profile = domain->profile; |
534 | e.group = domain->group; | 534 | e.group = domain->group; |
535 | } | 535 | } |
536 | e.domainname = tomoyo_get_name(domainname); | 536 | e.domainname = tomoyo_get_name(domainname); |
537 | if (!e.domainname) | 537 | if (!e.domainname) |
538 | return NULL; | 538 | return NULL; |
539 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) | 539 | if (mutex_lock_interruptible(&tomoyo_policy_lock)) |
540 | goto out; | 540 | goto out; |
541 | entry = tomoyo_find_domain(domainname); | 541 | entry = tomoyo_find_domain(domainname); |
542 | if (!entry) { | 542 | if (!entry) { |
543 | entry = tomoyo_commit_ok(&e, sizeof(e)); | 543 | entry = tomoyo_commit_ok(&e, sizeof(e)); |
544 | if (entry) { | 544 | if (entry) { |
545 | INIT_LIST_HEAD(&entry->acl_info_list); | 545 | INIT_LIST_HEAD(&entry->acl_info_list); |
546 | list_add_tail_rcu(&entry->list, &tomoyo_domain_list); | 546 | list_add_tail_rcu(&entry->list, &tomoyo_domain_list); |
547 | created = true; | 547 | created = true; |
548 | } | 548 | } |
549 | } | 549 | } |
550 | mutex_unlock(&tomoyo_policy_lock); | 550 | mutex_unlock(&tomoyo_policy_lock); |
551 | out: | 551 | out: |
552 | tomoyo_put_name(e.domainname); | 552 | tomoyo_put_name(e.domainname); |
553 | if (entry && transit) { | 553 | if (entry && transit) { |
554 | if (created) { | 554 | if (created) { |
555 | struct tomoyo_request_info r; | 555 | struct tomoyo_request_info r; |
556 | tomoyo_init_request_info(&r, entry, | 556 | tomoyo_init_request_info(&r, entry, |
557 | TOMOYO_MAC_FILE_EXECUTE); | 557 | TOMOYO_MAC_FILE_EXECUTE); |
558 | r.granted = false; | 558 | r.granted = false; |
559 | tomoyo_write_log(&r, "use_profile %u\n", | 559 | tomoyo_write_log(&r, "use_profile %u\n", |
560 | entry->profile); | 560 | entry->profile); |
561 | tomoyo_write_log(&r, "use_group %u\n", entry->group); | 561 | tomoyo_write_log(&r, "use_group %u\n", entry->group); |
562 | } | 562 | } |
563 | } | 563 | } |
564 | return entry; | 564 | return entry; |
565 | } | 565 | } |
566 | 566 | ||
567 | /** | 567 | /** |
568 | * tomoyo_find_next_domain - Find a domain. | 568 | * tomoyo_find_next_domain - Find a domain. |
569 | * | 569 | * |
570 | * @bprm: Pointer to "struct linux_binprm". | 570 | * @bprm: Pointer to "struct linux_binprm". |
571 | * | 571 | * |
572 | * Returns 0 on success, negative value otherwise. | 572 | * Returns 0 on success, negative value otherwise. |
573 | * | 573 | * |
574 | * Caller holds tomoyo_read_lock(). | 574 | * Caller holds tomoyo_read_lock(). |
575 | */ | 575 | */ |
576 | int tomoyo_find_next_domain(struct linux_binprm *bprm) | 576 | int tomoyo_find_next_domain(struct linux_binprm *bprm) |
577 | { | 577 | { |
578 | struct tomoyo_request_info r; | ||
579 | char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); | ||
580 | struct tomoyo_domain_info *old_domain = tomoyo_domain(); | 578 | struct tomoyo_domain_info *old_domain = tomoyo_domain(); |
581 | struct tomoyo_domain_info *domain = NULL; | 579 | struct tomoyo_domain_info *domain = NULL; |
582 | const char *original_name = bprm->filename; | 580 | const char *original_name = bprm->filename; |
583 | u8 mode; | ||
584 | bool is_enforce; | ||
585 | int retval = -ENOMEM; | 581 | int retval = -ENOMEM; |
586 | bool need_kfree = false; | 582 | bool need_kfree = false; |
587 | bool reject_on_transition_failure = false; | 583 | bool reject_on_transition_failure = false; |
588 | struct tomoyo_path_info rn = { }; /* real name */ | 584 | struct tomoyo_path_info rn = { }; /* real name */ |
589 | 585 | struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS); | |
590 | mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); | 586 | if (!ee) |
591 | is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); | 587 | return -ENOMEM; |
592 | if (!tmp) | 588 | ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); |
593 | goto out; | 589 | if (!ee->tmp) { |
594 | 590 | kfree(ee); | |
591 | return -ENOMEM; | ||
592 | } | ||
593 | /* ee->dump->data is allocated by tomoyo_dump_page(). */ | ||
594 | tomoyo_init_request_info(&ee->r, NULL, TOMOYO_MAC_FILE_EXECUTE); | ||
595 | ee->r.ee = ee; | ||
596 | ee->bprm = bprm; | ||
597 | ee->r.obj = &ee->obj; | ||
598 | ee->obj.path1 = bprm->file->f_path; | ||
595 | retry: | 599 | retry: |
596 | if (need_kfree) { | 600 | if (need_kfree) { |
597 | kfree(rn.name); | 601 | kfree(rn.name); |
598 | need_kfree = false; | 602 | need_kfree = false; |
599 | } | 603 | } |
600 | /* Get symlink's pathname of program. */ | 604 | /* Get symlink's pathname of program. */ |
601 | retval = -ENOENT; | 605 | retval = -ENOENT; |
602 | rn.name = tomoyo_realpath_nofollow(original_name); | 606 | rn.name = tomoyo_realpath_nofollow(original_name); |
603 | if (!rn.name) | 607 | if (!rn.name) |
604 | goto out; | 608 | goto out; |
605 | tomoyo_fill_path_info(&rn); | 609 | tomoyo_fill_path_info(&rn); |
606 | need_kfree = true; | 610 | need_kfree = true; |
607 | 611 | ||
608 | /* Check 'aggregator' directive. */ | 612 | /* Check 'aggregator' directive. */ |
609 | { | 613 | { |
610 | struct tomoyo_aggregator *ptr; | 614 | struct tomoyo_aggregator *ptr; |
611 | struct list_head *list = | 615 | struct list_head *list = |
612 | &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; | 616 | &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; |
613 | /* Check 'aggregator' directive. */ | 617 | /* Check 'aggregator' directive. */ |
614 | list_for_each_entry_rcu(ptr, list, head.list) { | 618 | list_for_each_entry_rcu(ptr, list, head.list) { |
615 | if (ptr->head.is_deleted || | 619 | if (ptr->head.is_deleted || |
616 | !tomoyo_path_matches_pattern(&rn, | 620 | !tomoyo_path_matches_pattern(&rn, |
617 | ptr->original_name)) | 621 | ptr->original_name)) |
618 | continue; | 622 | continue; |
619 | kfree(rn.name); | 623 | kfree(rn.name); |
620 | need_kfree = false; | 624 | need_kfree = false; |
621 | /* This is OK because it is read only. */ | 625 | /* This is OK because it is read only. */ |
622 | rn = *ptr->aggregated_name; | 626 | rn = *ptr->aggregated_name; |
623 | break; | 627 | break; |
624 | } | 628 | } |
625 | } | 629 | } |
626 | 630 | ||
627 | /* Check execute permission. */ | 631 | /* Check execute permission. */ |
628 | retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn); | 632 | retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE, &rn); |
629 | if (retval == TOMOYO_RETRY_REQUEST) | 633 | if (retval == TOMOYO_RETRY_REQUEST) |
630 | goto retry; | 634 | goto retry; |
631 | if (retval < 0) | 635 | if (retval < 0) |
632 | goto out; | 636 | goto out; |
633 | /* | 637 | /* |
634 | * To be able to specify domainnames with wildcards, use the | 638 | * To be able to specify domainnames with wildcards, use the |
635 | * pathname specified in the policy (which may contain | 639 | * pathname specified in the policy (which may contain |
636 | * wildcard) rather than the pathname passed to execve() | 640 | * wildcard) rather than the pathname passed to execve() |
637 | * (which never contains wildcard). | 641 | * (which never contains wildcard). |
638 | */ | 642 | */ |
639 | if (r.param.path.matched_path) { | 643 | if (ee->r.param.path.matched_path) { |
640 | if (need_kfree) | 644 | if (need_kfree) |
641 | kfree(rn.name); | 645 | kfree(rn.name); |
642 | need_kfree = false; | 646 | need_kfree = false; |
643 | /* This is OK because it is read only. */ | 647 | /* This is OK because it is read only. */ |
644 | rn = *r.param.path.matched_path; | 648 | rn = *ee->r.param.path.matched_path; |
645 | } | 649 | } |
646 | 650 | ||
647 | /* Calculate domain to transit to. */ | 651 | /* Calculate domain to transit to. */ |
648 | switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname, | 652 | switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname, |
649 | &rn)) { | 653 | &rn)) { |
650 | case TOMOYO_TRANSITION_CONTROL_RESET: | 654 | case TOMOYO_TRANSITION_CONTROL_RESET: |
651 | /* Transit to the root of specified namespace. */ | 655 | /* Transit to the root of specified namespace. */ |
652 | snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name); | 656 | snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name); |
653 | /* | 657 | /* |
654 | * Make do_execve() fail if domain transition across namespaces | 658 | * Make do_execve() fail if domain transition across namespaces |
655 | * has failed. | 659 | * has failed. |
656 | */ | 660 | */ |
657 | reject_on_transition_failure = true; | 661 | reject_on_transition_failure = true; |
658 | break; | 662 | break; |
659 | case TOMOYO_TRANSITION_CONTROL_INITIALIZE: | 663 | case TOMOYO_TRANSITION_CONTROL_INITIALIZE: |
660 | /* Transit to the child of current namespace's root. */ | 664 | /* Transit to the child of current namespace's root. */ |
661 | snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", | 665 | snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", |
662 | old_domain->ns->name, rn.name); | 666 | old_domain->ns->name, rn.name); |
663 | break; | 667 | break; |
664 | case TOMOYO_TRANSITION_CONTROL_KEEP: | 668 | case TOMOYO_TRANSITION_CONTROL_KEEP: |
665 | /* Keep current domain. */ | 669 | /* Keep current domain. */ |
666 | domain = old_domain; | 670 | domain = old_domain; |
667 | break; | 671 | break; |
668 | default: | 672 | default: |
669 | if (old_domain == &tomoyo_kernel_domain && | 673 | if (old_domain == &tomoyo_kernel_domain && |
670 | !tomoyo_policy_loaded) { | 674 | !tomoyo_policy_loaded) { |
671 | /* | 675 | /* |
672 | * Needn't to transit from kernel domain before | 676 | * Needn't to transit from kernel domain before |
673 | * starting /sbin/init. But transit from kernel domain | 677 | * starting /sbin/init. But transit from kernel domain |
674 | * if executing initializers because they might start | 678 | * if executing initializers because they might start |
675 | * before /sbin/init. | 679 | * before /sbin/init. |
676 | */ | 680 | */ |
677 | domain = old_domain; | 681 | domain = old_domain; |
678 | } else { | 682 | } else { |
679 | /* Normal domain transition. */ | 683 | /* Normal domain transition. */ |
680 | snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", | 684 | snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", |
681 | old_domain->domainname->name, rn.name); | 685 | old_domain->domainname->name, rn.name); |
682 | } | 686 | } |
683 | break; | 687 | break; |
684 | } | 688 | } |
685 | if (!domain) | 689 | if (!domain) |
686 | domain = tomoyo_assign_domain(tmp, true); | 690 | domain = tomoyo_assign_domain(ee->tmp, true); |
687 | if (domain) | 691 | if (domain) |
688 | retval = 0; | 692 | retval = 0; |
689 | else if (reject_on_transition_failure) { | 693 | else if (reject_on_transition_failure) { |
690 | printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", tmp); | 694 | printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", |
695 | ee->tmp); | ||
691 | retval = -ENOMEM; | 696 | retval = -ENOMEM; |
692 | } else if (r.mode == TOMOYO_CONFIG_ENFORCING) | 697 | } else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING) |
693 | retval = -ENOMEM; | 698 | retval = -ENOMEM; |
694 | else { | 699 | else { |
695 | retval = 0; | 700 | retval = 0; |
696 | if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) { | 701 | if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) { |
697 | old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true; | 702 | old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true; |
698 | r.granted = false; | 703 | ee->r.granted = false; |
699 | tomoyo_write_log(&r, "%s", tomoyo_dif | 704 | tomoyo_write_log(&ee->r, "%s", tomoyo_dif |
700 | [TOMOYO_DIF_TRANSITION_FAILED]); | 705 | [TOMOYO_DIF_TRANSITION_FAILED]); |
701 | printk(KERN_WARNING | 706 | printk(KERN_WARNING |
702 | "ERROR: Domain '%s' not defined.\n", tmp); | 707 | "ERROR: Domain '%s' not defined.\n", ee->tmp); |
703 | } | 708 | } |
704 | } | 709 | } |
705 | out: | 710 | out: |
706 | if (!domain) | 711 | if (!domain) |
707 | domain = old_domain; | 712 | domain = old_domain; |
708 | /* Update reference count on "struct tomoyo_domain_info". */ | 713 | /* Update reference count on "struct tomoyo_domain_info". */ |
709 | atomic_inc(&domain->users); | 714 | atomic_inc(&domain->users); |
710 | bprm->cred->security = domain; | 715 | bprm->cred->security = domain; |
711 | if (need_kfree) | 716 | if (need_kfree) |
712 | kfree(rn.name); | 717 | kfree(rn.name); |
713 | kfree(tmp); | 718 | kfree(ee->tmp); |
719 | kfree(ee->dump.data); | ||
720 | kfree(ee); | ||
714 | return retval; | 721 | return retval; |
715 | } | 722 | } |
716 | 723 | ||
717 | /** | 724 | /** |
718 | * tomoyo_dump_page - Dump a page to buffer. | 725 | * tomoyo_dump_page - Dump a page to buffer. |
719 | * | 726 | * |
720 | * @bprm: Pointer to "struct linux_binprm". | 727 | * @bprm: Pointer to "struct linux_binprm". |
721 | * @pos: Location to dump. | 728 | * @pos: Location to dump. |
722 | * @dump: Poiner to "struct tomoyo_page_dump". | 729 | * @dump: Poiner to "struct tomoyo_page_dump". |
723 | * | 730 | * |
724 | * Returns true on success, false otherwise. | 731 | * Returns true on success, false otherwise. |
725 | */ | 732 | */ |
726 | bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, | 733 | bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, |
727 | struct tomoyo_page_dump *dump) | 734 | struct tomoyo_page_dump *dump) |
728 | { | 735 | { |
729 | struct page *page; | 736 | struct page *page; |
730 | /* dump->data is released by tomoyo_finish_execve(). */ | 737 | /* dump->data is released by tomoyo_finish_execve(). */ |
731 | if (!dump->data) { | 738 | if (!dump->data) { |
732 | dump->data = kzalloc(PAGE_SIZE, GFP_NOFS); | 739 | dump->data = kzalloc(PAGE_SIZE, GFP_NOFS); |
733 | if (!dump->data) | 740 | if (!dump->data) |
734 | return false; | 741 | return false; |
735 | } | 742 | } |
736 | /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */ | 743 | /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */ |
737 | #ifdef CONFIG_MMU | 744 | #ifdef CONFIG_MMU |
738 | if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0) | 745 | if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0) |
739 | return false; | 746 | return false; |
740 | #else | 747 | #else |
741 | page = bprm->page[pos / PAGE_SIZE]; | 748 | page = bprm->page[pos / PAGE_SIZE]; |
742 | #endif | 749 | #endif |
743 | if (page != dump->page) { | 750 | if (page != dump->page) { |
744 | const unsigned int offset = pos % PAGE_SIZE; | 751 | const unsigned int offset = pos % PAGE_SIZE; |
745 | /* | 752 | /* |
746 | * Maybe kmap()/kunmap() should be used here. | 753 | * Maybe kmap()/kunmap() should be used here. |
747 | * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic(). | 754 | * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic(). |
748 | * So do I. | 755 | * So do I. |
749 | */ | 756 | */ |
750 | char *kaddr = kmap_atomic(page, KM_USER0); | 757 | char *kaddr = kmap_atomic(page, KM_USER0); |
751 | dump->page = page; | 758 | dump->page = page; |
752 | memcpy(dump->data + offset, kaddr + offset, | 759 | memcpy(dump->data + offset, kaddr + offset, |
753 | PAGE_SIZE - offset); | 760 | PAGE_SIZE - offset); |
754 | kunmap_atomic(kaddr, KM_USER0); | 761 | kunmap_atomic(kaddr, KM_USER0); |
755 | } | 762 | } |
756 | /* Same with put_arg_page(page) in fs/exec.c */ | 763 | /* Same with put_arg_page(page) in fs/exec.c */ |
757 | #ifdef CONFIG_MMU | 764 | #ifdef CONFIG_MMU |
758 | put_page(page); | 765 | put_page(page); |
security/tomoyo/file.c
1 | /* | 1 | /* |
2 | * security/tomoyo/file.c | 2 | * security/tomoyo/file.c |
3 | * | 3 | * |
4 | * Pathname restriction functions. | 4 | * Pathname restriction functions. |
5 | * | 5 | * |
6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION | 6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include "common.h" | 9 | #include "common.h" |
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | 11 | ||
12 | /* | 12 | /* |
13 | * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index". | 13 | * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index". |
14 | */ | 14 | */ |
15 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { | 15 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { |
16 | [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, | 16 | [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, |
17 | [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, | 17 | [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, |
18 | [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, | 18 | [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, |
19 | [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN, | 19 | [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN, |
20 | [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, | 20 | [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, |
21 | [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR, | 21 | [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR, |
22 | [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, | 22 | [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, |
23 | [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, | 23 | [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, |
24 | [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, | 24 | [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, |
25 | [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, | 25 | [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, |
26 | [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, | 26 | [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index". | 30 | * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index". |
31 | */ | 31 | */ |
32 | const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { | 32 | const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { |
33 | [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, | 33 | [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, |
34 | [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, | 34 | [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index". | 38 | * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index". |
39 | */ | 39 | */ |
40 | const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { | 40 | const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { |
41 | [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, | 41 | [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, |
42 | [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, | 42 | [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, |
43 | [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, | 43 | [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, |
44 | }; | 44 | }; |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * Mapping table from "enum tomoyo_path_number_acl_index" to | 47 | * Mapping table from "enum tomoyo_path_number_acl_index" to |
48 | * "enum tomoyo_mac_index". | 48 | * "enum tomoyo_mac_index". |
49 | */ | 49 | */ |
50 | const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | 50 | const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { |
51 | [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, | 51 | [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, |
52 | [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, | 52 | [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, |
53 | [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO, | 53 | [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO, |
54 | [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK, | 54 | [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK, |
55 | [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL, | 55 | [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL, |
56 | [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD, | 56 | [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD, |
57 | [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN, | 57 | [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN, |
58 | [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, | 58 | [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, |
59 | }; | 59 | }; |
60 | 60 | ||
61 | /** | 61 | /** |
62 | * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union". | 62 | * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union". |
63 | * | 63 | * |
64 | * @ptr: Pointer to "struct tomoyo_name_union". | 64 | * @ptr: Pointer to "struct tomoyo_name_union". |
65 | * | 65 | * |
66 | * Returns nothing. | 66 | * Returns nothing. |
67 | */ | 67 | */ |
68 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) | 68 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) |
69 | { | 69 | { |
70 | tomoyo_put_group(ptr->group); | 70 | tomoyo_put_group(ptr->group); |
71 | tomoyo_put_name(ptr->filename); | 71 | tomoyo_put_name(ptr->filename); |
72 | } | 72 | } |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not. | 75 | * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not. |
76 | * | 76 | * |
77 | * @name: Pointer to "struct tomoyo_path_info". | 77 | * @name: Pointer to "struct tomoyo_path_info". |
78 | * @ptr: Pointer to "struct tomoyo_name_union". | 78 | * @ptr: Pointer to "struct tomoyo_name_union". |
79 | * | 79 | * |
80 | * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise. | 80 | * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise. |
81 | */ | 81 | */ |
82 | const struct tomoyo_path_info * | 82 | const struct tomoyo_path_info * |
83 | tomoyo_compare_name_union(const struct tomoyo_path_info *name, | 83 | tomoyo_compare_name_union(const struct tomoyo_path_info *name, |
84 | const struct tomoyo_name_union *ptr) | 84 | const struct tomoyo_name_union *ptr) |
85 | { | 85 | { |
86 | if (ptr->group) | 86 | if (ptr->group) |
87 | return tomoyo_path_matches_group(name, ptr->group); | 87 | return tomoyo_path_matches_group(name, ptr->group); |
88 | if (tomoyo_path_matches_pattern(name, ptr->filename)) | 88 | if (tomoyo_path_matches_pattern(name, ptr->filename)) |
89 | return ptr->filename; | 89 | return ptr->filename; |
90 | return NULL; | 90 | return NULL; |
91 | } | 91 | } |
92 | 92 | ||
93 | /** | 93 | /** |
94 | * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union". | 94 | * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union". |
95 | * | 95 | * |
96 | * @ptr: Pointer to "struct tomoyo_number_union". | 96 | * @ptr: Pointer to "struct tomoyo_number_union". |
97 | * | 97 | * |
98 | * Returns nothing. | 98 | * Returns nothing. |
99 | */ | 99 | */ |
100 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr) | 100 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr) |
101 | { | 101 | { |
102 | tomoyo_put_group(ptr->group); | 102 | tomoyo_put_group(ptr->group); |
103 | } | 103 | } |
104 | 104 | ||
105 | /** | 105 | /** |
106 | * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not. | 106 | * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not. |
107 | * | 107 | * |
108 | * @value: Number to check. | 108 | * @value: Number to check. |
109 | * @ptr: Pointer to "struct tomoyo_number_union". | 109 | * @ptr: Pointer to "struct tomoyo_number_union". |
110 | * | 110 | * |
111 | * Returns true if @value matches @ptr, false otherwise. | 111 | * Returns true if @value matches @ptr, false otherwise. |
112 | */ | 112 | */ |
113 | bool tomoyo_compare_number_union(const unsigned long value, | 113 | bool tomoyo_compare_number_union(const unsigned long value, |
114 | const struct tomoyo_number_union *ptr) | 114 | const struct tomoyo_number_union *ptr) |
115 | { | 115 | { |
116 | if (ptr->group) | 116 | if (ptr->group) |
117 | return tomoyo_number_matches_group(value, value, ptr->group); | 117 | return tomoyo_number_matches_group(value, value, ptr->group); |
118 | return value >= ptr->values[0] && value <= ptr->values[1]; | 118 | return value >= ptr->values[0] && value <= ptr->values[1]; |
119 | } | 119 | } |
120 | 120 | ||
121 | /** | 121 | /** |
122 | * tomoyo_add_slash - Add trailing '/' if needed. | 122 | * tomoyo_add_slash - Add trailing '/' if needed. |
123 | * | 123 | * |
124 | * @buf: Pointer to "struct tomoyo_path_info". | 124 | * @buf: Pointer to "struct tomoyo_path_info". |
125 | * | 125 | * |
126 | * Returns nothing. | 126 | * Returns nothing. |
127 | * | 127 | * |
128 | * @buf must be generated by tomoyo_encode() because this function does not | 128 | * @buf must be generated by tomoyo_encode() because this function does not |
129 | * allocate memory for adding '/'. | 129 | * allocate memory for adding '/'. |
130 | */ | 130 | */ |
131 | static void tomoyo_add_slash(struct tomoyo_path_info *buf) | 131 | static void tomoyo_add_slash(struct tomoyo_path_info *buf) |
132 | { | 132 | { |
133 | if (buf->is_dir) | 133 | if (buf->is_dir) |
134 | return; | 134 | return; |
135 | /* | 135 | /* |
136 | * This is OK because tomoyo_encode() reserves space for appending "/". | 136 | * This is OK because tomoyo_encode() reserves space for appending "/". |
137 | */ | 137 | */ |
138 | strcat((char *) buf->name, "/"); | 138 | strcat((char *) buf->name, "/"); |
139 | tomoyo_fill_path_info(buf); | 139 | tomoyo_fill_path_info(buf); |
140 | } | 140 | } |
141 | 141 | ||
142 | /** | 142 | /** |
143 | * tomoyo_get_realpath - Get realpath. | 143 | * tomoyo_get_realpath - Get realpath. |
144 | * | 144 | * |
145 | * @buf: Pointer to "struct tomoyo_path_info". | 145 | * @buf: Pointer to "struct tomoyo_path_info". |
146 | * @path: Pointer to "struct path". | 146 | * @path: Pointer to "struct path". |
147 | * | 147 | * |
148 | * Returns true on success, false otherwise. | 148 | * Returns true on success, false otherwise. |
149 | */ | 149 | */ |
150 | static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) | 150 | static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) |
151 | { | 151 | { |
152 | buf->name = tomoyo_realpath_from_path(path); | 152 | buf->name = tomoyo_realpath_from_path(path); |
153 | if (buf->name) { | 153 | if (buf->name) { |
154 | tomoyo_fill_path_info(buf); | 154 | tomoyo_fill_path_info(buf); |
155 | return true; | 155 | return true; |
156 | } | 156 | } |
157 | return false; | 157 | return false; |
158 | } | 158 | } |
159 | 159 | ||
160 | /** | 160 | /** |
161 | * tomoyo_audit_path_log - Audit path request log. | 161 | * tomoyo_audit_path_log - Audit path request log. |
162 | * | 162 | * |
163 | * @r: Pointer to "struct tomoyo_request_info". | 163 | * @r: Pointer to "struct tomoyo_request_info". |
164 | * | 164 | * |
165 | * Returns 0 on success, negative value otherwise. | 165 | * Returns 0 on success, negative value otherwise. |
166 | */ | 166 | */ |
167 | static int tomoyo_audit_path_log(struct tomoyo_request_info *r) | 167 | static int tomoyo_audit_path_log(struct tomoyo_request_info *r) |
168 | { | 168 | { |
169 | return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword | 169 | return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword |
170 | [r->param.path.operation], | 170 | [r->param.path.operation], |
171 | r->param.path.filename->name); | 171 | r->param.path.filename->name); |
172 | } | 172 | } |
173 | 173 | ||
174 | /** | 174 | /** |
175 | * tomoyo_audit_path2_log - Audit path/path request log. | 175 | * tomoyo_audit_path2_log - Audit path/path request log. |
176 | * | 176 | * |
177 | * @r: Pointer to "struct tomoyo_request_info". | 177 | * @r: Pointer to "struct tomoyo_request_info". |
178 | * | 178 | * |
179 | * Returns 0 on success, negative value otherwise. | 179 | * Returns 0 on success, negative value otherwise. |
180 | */ | 180 | */ |
181 | static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) | 181 | static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) |
182 | { | 182 | { |
183 | return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords | 183 | return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords |
184 | [tomoyo_pp2mac[r->param.path2.operation]], | 184 | [tomoyo_pp2mac[r->param.path2.operation]], |
185 | r->param.path2.filename1->name, | 185 | r->param.path2.filename1->name, |
186 | r->param.path2.filename2->name); | 186 | r->param.path2.filename2->name); |
187 | } | 187 | } |
188 | 188 | ||
189 | /** | 189 | /** |
190 | * tomoyo_audit_mkdev_log - Audit path/number/number/number request log. | 190 | * tomoyo_audit_mkdev_log - Audit path/number/number/number request log. |
191 | * | 191 | * |
192 | * @r: Pointer to "struct tomoyo_request_info". | 192 | * @r: Pointer to "struct tomoyo_request_info". |
193 | * | 193 | * |
194 | * Returns 0 on success, negative value otherwise. | 194 | * Returns 0 on success, negative value otherwise. |
195 | */ | 195 | */ |
196 | static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) | 196 | static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) |
197 | { | 197 | { |
198 | return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n", | 198 | return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n", |
199 | tomoyo_mac_keywords | 199 | tomoyo_mac_keywords |
200 | [tomoyo_pnnn2mac[r->param.mkdev.operation]], | 200 | [tomoyo_pnnn2mac[r->param.mkdev.operation]], |
201 | r->param.mkdev.filename->name, | 201 | r->param.mkdev.filename->name, |
202 | r->param.mkdev.mode, r->param.mkdev.major, | 202 | r->param.mkdev.mode, r->param.mkdev.major, |
203 | r->param.mkdev.minor); | 203 | r->param.mkdev.minor); |
204 | } | 204 | } |
205 | 205 | ||
206 | /** | 206 | /** |
207 | * tomoyo_audit_path_number_log - Audit path/number request log. | 207 | * tomoyo_audit_path_number_log - Audit path/number request log. |
208 | * | 208 | * |
209 | * @r: Pointer to "struct tomoyo_request_info". | 209 | * @r: Pointer to "struct tomoyo_request_info". |
210 | * | 210 | * |
211 | * Returns 0 on success, negative value otherwise. | 211 | * Returns 0 on success, negative value otherwise. |
212 | */ | 212 | */ |
213 | static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) | 213 | static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) |
214 | { | 214 | { |
215 | const u8 type = r->param.path_number.operation; | 215 | const u8 type = r->param.path_number.operation; |
216 | u8 radix; | 216 | u8 radix; |
217 | char buffer[64]; | 217 | char buffer[64]; |
218 | switch (type) { | 218 | switch (type) { |
219 | case TOMOYO_TYPE_CREATE: | 219 | case TOMOYO_TYPE_CREATE: |
220 | case TOMOYO_TYPE_MKDIR: | 220 | case TOMOYO_TYPE_MKDIR: |
221 | case TOMOYO_TYPE_MKFIFO: | 221 | case TOMOYO_TYPE_MKFIFO: |
222 | case TOMOYO_TYPE_MKSOCK: | 222 | case TOMOYO_TYPE_MKSOCK: |
223 | case TOMOYO_TYPE_CHMOD: | 223 | case TOMOYO_TYPE_CHMOD: |
224 | radix = TOMOYO_VALUE_TYPE_OCTAL; | 224 | radix = TOMOYO_VALUE_TYPE_OCTAL; |
225 | break; | 225 | break; |
226 | case TOMOYO_TYPE_IOCTL: | 226 | case TOMOYO_TYPE_IOCTL: |
227 | radix = TOMOYO_VALUE_TYPE_HEXADECIMAL; | 227 | radix = TOMOYO_VALUE_TYPE_HEXADECIMAL; |
228 | break; | 228 | break; |
229 | default: | 229 | default: |
230 | radix = TOMOYO_VALUE_TYPE_DECIMAL; | 230 | radix = TOMOYO_VALUE_TYPE_DECIMAL; |
231 | break; | 231 | break; |
232 | } | 232 | } |
233 | tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, | 233 | tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, |
234 | radix); | 234 | radix); |
235 | return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords | 235 | return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords |
236 | [tomoyo_pn2mac[type]], | 236 | [tomoyo_pn2mac[type]], |
237 | r->param.path_number.filename->name, buffer); | 237 | r->param.path_number.filename->name, buffer); |
238 | } | 238 | } |
239 | 239 | ||
240 | /** | 240 | /** |
241 | * tomoyo_check_path_acl - Check permission for path operation. | 241 | * tomoyo_check_path_acl - Check permission for path operation. |
242 | * | 242 | * |
243 | * @r: Pointer to "struct tomoyo_request_info". | 243 | * @r: Pointer to "struct tomoyo_request_info". |
244 | * @ptr: Pointer to "struct tomoyo_acl_info". | 244 | * @ptr: Pointer to "struct tomoyo_acl_info". |
245 | * | 245 | * |
246 | * Returns true if granted, false otherwise. | 246 | * Returns true if granted, false otherwise. |
247 | * | 247 | * |
248 | * To be able to use wildcard for domain transition, this function sets | 248 | * To be able to use wildcard for domain transition, this function sets |
249 | * matching entry on success. Since the caller holds tomoyo_read_lock(), | 249 | * matching entry on success. Since the caller holds tomoyo_read_lock(), |
250 | * it is safe to set matching entry. | 250 | * it is safe to set matching entry. |
251 | */ | 251 | */ |
252 | static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, | 252 | static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, |
253 | const struct tomoyo_acl_info *ptr) | 253 | const struct tomoyo_acl_info *ptr) |
254 | { | 254 | { |
255 | const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl), | 255 | const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl), |
256 | head); | 256 | head); |
257 | if (acl->perm & (1 << r->param.path.operation)) { | 257 | if (acl->perm & (1 << r->param.path.operation)) { |
258 | r->param.path.matched_path = | 258 | r->param.path.matched_path = |
259 | tomoyo_compare_name_union(r->param.path.filename, | 259 | tomoyo_compare_name_union(r->param.path.filename, |
260 | &acl->name); | 260 | &acl->name); |
261 | return r->param.path.matched_path != NULL; | 261 | return r->param.path.matched_path != NULL; |
262 | } | 262 | } |
263 | return false; | 263 | return false; |
264 | } | 264 | } |
265 | 265 | ||
266 | /** | 266 | /** |
267 | * tomoyo_check_path_number_acl - Check permission for path number operation. | 267 | * tomoyo_check_path_number_acl - Check permission for path number operation. |
268 | * | 268 | * |
269 | * @r: Pointer to "struct tomoyo_request_info". | 269 | * @r: Pointer to "struct tomoyo_request_info". |
270 | * @ptr: Pointer to "struct tomoyo_acl_info". | 270 | * @ptr: Pointer to "struct tomoyo_acl_info". |
271 | * | 271 | * |
272 | * Returns true if granted, false otherwise. | 272 | * Returns true if granted, false otherwise. |
273 | */ | 273 | */ |
274 | static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, | 274 | static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, |
275 | const struct tomoyo_acl_info *ptr) | 275 | const struct tomoyo_acl_info *ptr) |
276 | { | 276 | { |
277 | const struct tomoyo_path_number_acl *acl = | 277 | const struct tomoyo_path_number_acl *acl = |
278 | container_of(ptr, typeof(*acl), head); | 278 | container_of(ptr, typeof(*acl), head); |
279 | return (acl->perm & (1 << r->param.path_number.operation)) && | 279 | return (acl->perm & (1 << r->param.path_number.operation)) && |
280 | tomoyo_compare_number_union(r->param.path_number.number, | 280 | tomoyo_compare_number_union(r->param.path_number.number, |
281 | &acl->number) && | 281 | &acl->number) && |
282 | tomoyo_compare_name_union(r->param.path_number.filename, | 282 | tomoyo_compare_name_union(r->param.path_number.filename, |
283 | &acl->name); | 283 | &acl->name); |
284 | } | 284 | } |
285 | 285 | ||
286 | /** | 286 | /** |
287 | * tomoyo_check_path2_acl - Check permission for path path operation. | 287 | * tomoyo_check_path2_acl - Check permission for path path operation. |
288 | * | 288 | * |
289 | * @r: Pointer to "struct tomoyo_request_info". | 289 | * @r: Pointer to "struct tomoyo_request_info". |
290 | * @ptr: Pointer to "struct tomoyo_acl_info". | 290 | * @ptr: Pointer to "struct tomoyo_acl_info". |
291 | * | 291 | * |
292 | * Returns true if granted, false otherwise. | 292 | * Returns true if granted, false otherwise. |
293 | */ | 293 | */ |
294 | static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, | 294 | static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, |
295 | const struct tomoyo_acl_info *ptr) | 295 | const struct tomoyo_acl_info *ptr) |
296 | { | 296 | { |
297 | const struct tomoyo_path2_acl *acl = | 297 | const struct tomoyo_path2_acl *acl = |
298 | container_of(ptr, typeof(*acl), head); | 298 | container_of(ptr, typeof(*acl), head); |
299 | return (acl->perm & (1 << r->param.path2.operation)) && | 299 | return (acl->perm & (1 << r->param.path2.operation)) && |
300 | tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1) | 300 | tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1) |
301 | && tomoyo_compare_name_union(r->param.path2.filename2, | 301 | && tomoyo_compare_name_union(r->param.path2.filename2, |
302 | &acl->name2); | 302 | &acl->name2); |
303 | } | 303 | } |
304 | 304 | ||
305 | /** | 305 | /** |
306 | * tomoyo_check_mkdev_acl - Check permission for path number number number operation. | 306 | * tomoyo_check_mkdev_acl - Check permission for path number number number operation. |
307 | * | 307 | * |
308 | * @r: Pointer to "struct tomoyo_request_info". | 308 | * @r: Pointer to "struct tomoyo_request_info". |
309 | * @ptr: Pointer to "struct tomoyo_acl_info". | 309 | * @ptr: Pointer to "struct tomoyo_acl_info". |
310 | * | 310 | * |
311 | * Returns true if granted, false otherwise. | 311 | * Returns true if granted, false otherwise. |
312 | */ | 312 | */ |
313 | static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, | 313 | static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, |
314 | const struct tomoyo_acl_info *ptr) | 314 | const struct tomoyo_acl_info *ptr) |
315 | { | 315 | { |
316 | const struct tomoyo_mkdev_acl *acl = | 316 | const struct tomoyo_mkdev_acl *acl = |
317 | container_of(ptr, typeof(*acl), head); | 317 | container_of(ptr, typeof(*acl), head); |
318 | return (acl->perm & (1 << r->param.mkdev.operation)) && | 318 | return (acl->perm & (1 << r->param.mkdev.operation)) && |
319 | tomoyo_compare_number_union(r->param.mkdev.mode, | 319 | tomoyo_compare_number_union(r->param.mkdev.mode, |
320 | &acl->mode) && | 320 | &acl->mode) && |
321 | tomoyo_compare_number_union(r->param.mkdev.major, | 321 | tomoyo_compare_number_union(r->param.mkdev.major, |
322 | &acl->major) && | 322 | &acl->major) && |
323 | tomoyo_compare_number_union(r->param.mkdev.minor, | 323 | tomoyo_compare_number_union(r->param.mkdev.minor, |
324 | &acl->minor) && | 324 | &acl->minor) && |
325 | tomoyo_compare_name_union(r->param.mkdev.filename, | 325 | tomoyo_compare_name_union(r->param.mkdev.filename, |
326 | &acl->name); | 326 | &acl->name); |
327 | } | 327 | } |
328 | 328 | ||
329 | /** | 329 | /** |
330 | * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry. | 330 | * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry. |
331 | * | 331 | * |
332 | * @a: Pointer to "struct tomoyo_acl_info". | 332 | * @a: Pointer to "struct tomoyo_acl_info". |
333 | * @b: Pointer to "struct tomoyo_acl_info". | 333 | * @b: Pointer to "struct tomoyo_acl_info". |
334 | * | 334 | * |
335 | * Returns true if @a == @b except permission bits, false otherwise. | 335 | * Returns true if @a == @b except permission bits, false otherwise. |
336 | */ | 336 | */ |
337 | static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, | 337 | static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, |
338 | const struct tomoyo_acl_info *b) | 338 | const struct tomoyo_acl_info *b) |
339 | { | 339 | { |
340 | const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); | 340 | const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); |
341 | const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); | 341 | const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); |
342 | return tomoyo_same_name_union(&p1->name, &p2->name); | 342 | return tomoyo_same_name_union(&p1->name, &p2->name); |
343 | } | 343 | } |
344 | 344 | ||
345 | /** | 345 | /** |
346 | * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry. | 346 | * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry. |
347 | * | 347 | * |
348 | * @a: Pointer to "struct tomoyo_acl_info". | 348 | * @a: Pointer to "struct tomoyo_acl_info". |
349 | * @b: Pointer to "struct tomoyo_acl_info". | 349 | * @b: Pointer to "struct tomoyo_acl_info". |
350 | * @is_delete: True for @a &= ~@b, false for @a |= @b. | 350 | * @is_delete: True for @a &= ~@b, false for @a |= @b. |
351 | * | 351 | * |
352 | * Returns true if @a is empty, false otherwise. | 352 | * Returns true if @a is empty, false otherwise. |
353 | */ | 353 | */ |
354 | static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, | 354 | static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, |
355 | struct tomoyo_acl_info *b, | 355 | struct tomoyo_acl_info *b, |
356 | const bool is_delete) | 356 | const bool is_delete) |
357 | { | 357 | { |
358 | u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head) | 358 | u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head) |
359 | ->perm; | 359 | ->perm; |
360 | u16 perm = *a_perm; | 360 | u16 perm = *a_perm; |
361 | const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; | 361 | const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; |
362 | if (is_delete) | 362 | if (is_delete) |
363 | perm &= ~b_perm; | 363 | perm &= ~b_perm; |
364 | else | 364 | else |
365 | perm |= b_perm; | 365 | perm |= b_perm; |
366 | *a_perm = perm; | 366 | *a_perm = perm; |
367 | return !perm; | 367 | return !perm; |
368 | } | 368 | } |
369 | 369 | ||
370 | /** | 370 | /** |
371 | * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. | 371 | * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. |
372 | * | 372 | * |
373 | * @perm: Permission. | 373 | * @perm: Permission. |
374 | * @param: Pointer to "struct tomoyo_acl_param". | 374 | * @param: Pointer to "struct tomoyo_acl_param". |
375 | * | 375 | * |
376 | * Returns 0 on success, negative value otherwise. | 376 | * Returns 0 on success, negative value otherwise. |
377 | * | 377 | * |
378 | * Caller holds tomoyo_read_lock(). | 378 | * Caller holds tomoyo_read_lock(). |
379 | */ | 379 | */ |
380 | static int tomoyo_update_path_acl(const u16 perm, | 380 | static int tomoyo_update_path_acl(const u16 perm, |
381 | struct tomoyo_acl_param *param) | 381 | struct tomoyo_acl_param *param) |
382 | { | 382 | { |
383 | struct tomoyo_path_acl e = { | 383 | struct tomoyo_path_acl e = { |
384 | .head.type = TOMOYO_TYPE_PATH_ACL, | 384 | .head.type = TOMOYO_TYPE_PATH_ACL, |
385 | .perm = perm | 385 | .perm = perm |
386 | }; | 386 | }; |
387 | int error; | 387 | int error; |
388 | if (!tomoyo_parse_name_union(param, &e.name)) | 388 | if (!tomoyo_parse_name_union(param, &e.name)) |
389 | error = -EINVAL; | 389 | error = -EINVAL; |
390 | else | 390 | else |
391 | error = tomoyo_update_domain(&e.head, sizeof(e), param, | 391 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
392 | tomoyo_same_path_acl, | 392 | tomoyo_same_path_acl, |
393 | tomoyo_merge_path_acl); | 393 | tomoyo_merge_path_acl); |
394 | tomoyo_put_name_union(&e.name); | 394 | tomoyo_put_name_union(&e.name); |
395 | return error; | 395 | return error; |
396 | } | 396 | } |
397 | 397 | ||
398 | /** | 398 | /** |
399 | * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry. | 399 | * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry. |
400 | * | 400 | * |
401 | * @a: Pointer to "struct tomoyo_acl_info". | 401 | * @a: Pointer to "struct tomoyo_acl_info". |
402 | * @b: Pointer to "struct tomoyo_acl_info". | 402 | * @b: Pointer to "struct tomoyo_acl_info". |
403 | * | 403 | * |
404 | * Returns true if @a == @b except permission bits, false otherwise. | 404 | * Returns true if @a == @b except permission bits, false otherwise. |
405 | */ | 405 | */ |
406 | static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, | 406 | static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, |
407 | const struct tomoyo_acl_info *b) | 407 | const struct tomoyo_acl_info *b) |
408 | { | 408 | { |
409 | const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head); | 409 | const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head); |
410 | const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head); | 410 | const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head); |
411 | return tomoyo_same_name_union(&p1->name, &p2->name) && | 411 | return tomoyo_same_name_union(&p1->name, &p2->name) && |
412 | tomoyo_same_number_union(&p1->mode, &p2->mode) && | 412 | tomoyo_same_number_union(&p1->mode, &p2->mode) && |
413 | tomoyo_same_number_union(&p1->major, &p2->major) && | 413 | tomoyo_same_number_union(&p1->major, &p2->major) && |
414 | tomoyo_same_number_union(&p1->minor, &p2->minor); | 414 | tomoyo_same_number_union(&p1->minor, &p2->minor); |
415 | } | 415 | } |
416 | 416 | ||
417 | /** | 417 | /** |
418 | * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry. | 418 | * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry. |
419 | * | 419 | * |
420 | * @a: Pointer to "struct tomoyo_acl_info". | 420 | * @a: Pointer to "struct tomoyo_acl_info". |
421 | * @b: Pointer to "struct tomoyo_acl_info". | 421 | * @b: Pointer to "struct tomoyo_acl_info". |
422 | * @is_delete: True for @a &= ~@b, false for @a |= @b. | 422 | * @is_delete: True for @a &= ~@b, false for @a |= @b. |
423 | * | 423 | * |
424 | * Returns true if @a is empty, false otherwise. | 424 | * Returns true if @a is empty, false otherwise. |
425 | */ | 425 | */ |
426 | static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, | 426 | static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, |
427 | struct tomoyo_acl_info *b, | 427 | struct tomoyo_acl_info *b, |
428 | const bool is_delete) | 428 | const bool is_delete) |
429 | { | 429 | { |
430 | u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, | 430 | u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, |
431 | head)->perm; | 431 | head)->perm; |
432 | u8 perm = *a_perm; | 432 | u8 perm = *a_perm; |
433 | const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) | 433 | const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) |
434 | ->perm; | 434 | ->perm; |
435 | if (is_delete) | 435 | if (is_delete) |
436 | perm &= ~b_perm; | 436 | perm &= ~b_perm; |
437 | else | 437 | else |
438 | perm |= b_perm; | 438 | perm |= b_perm; |
439 | *a_perm = perm; | 439 | *a_perm = perm; |
440 | return !perm; | 440 | return !perm; |
441 | } | 441 | } |
442 | 442 | ||
443 | /** | 443 | /** |
444 | * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. | 444 | * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. |
445 | * | 445 | * |
446 | * @perm: Permission. | 446 | * @perm: Permission. |
447 | * @param: Pointer to "struct tomoyo_acl_param". | 447 | * @param: Pointer to "struct tomoyo_acl_param". |
448 | * | 448 | * |
449 | * Returns 0 on success, negative value otherwise. | 449 | * Returns 0 on success, negative value otherwise. |
450 | * | 450 | * |
451 | * Caller holds tomoyo_read_lock(). | 451 | * Caller holds tomoyo_read_lock(). |
452 | */ | 452 | */ |
453 | static int tomoyo_update_mkdev_acl(const u8 perm, | 453 | static int tomoyo_update_mkdev_acl(const u8 perm, |
454 | struct tomoyo_acl_param *param) | 454 | struct tomoyo_acl_param *param) |
455 | { | 455 | { |
456 | struct tomoyo_mkdev_acl e = { | 456 | struct tomoyo_mkdev_acl e = { |
457 | .head.type = TOMOYO_TYPE_MKDEV_ACL, | 457 | .head.type = TOMOYO_TYPE_MKDEV_ACL, |
458 | .perm = perm | 458 | .perm = perm |
459 | }; | 459 | }; |
460 | int error; | 460 | int error; |
461 | if (!tomoyo_parse_name_union(param, &e.name) || | 461 | if (!tomoyo_parse_name_union(param, &e.name) || |
462 | !tomoyo_parse_number_union(param, &e.mode) || | 462 | !tomoyo_parse_number_union(param, &e.mode) || |
463 | !tomoyo_parse_number_union(param, &e.major) || | 463 | !tomoyo_parse_number_union(param, &e.major) || |
464 | !tomoyo_parse_number_union(param, &e.minor)) | 464 | !tomoyo_parse_number_union(param, &e.minor)) |
465 | error = -EINVAL; | 465 | error = -EINVAL; |
466 | else | 466 | else |
467 | error = tomoyo_update_domain(&e.head, sizeof(e), param, | 467 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
468 | tomoyo_same_mkdev_acl, | 468 | tomoyo_same_mkdev_acl, |
469 | tomoyo_merge_mkdev_acl); | 469 | tomoyo_merge_mkdev_acl); |
470 | tomoyo_put_name_union(&e.name); | 470 | tomoyo_put_name_union(&e.name); |
471 | tomoyo_put_number_union(&e.mode); | 471 | tomoyo_put_number_union(&e.mode); |
472 | tomoyo_put_number_union(&e.major); | 472 | tomoyo_put_number_union(&e.major); |
473 | tomoyo_put_number_union(&e.minor); | 473 | tomoyo_put_number_union(&e.minor); |
474 | return error; | 474 | return error; |
475 | } | 475 | } |
476 | 476 | ||
477 | /** | 477 | /** |
478 | * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry. | 478 | * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry. |
479 | * | 479 | * |
480 | * @a: Pointer to "struct tomoyo_acl_info". | 480 | * @a: Pointer to "struct tomoyo_acl_info". |
481 | * @b: Pointer to "struct tomoyo_acl_info". | 481 | * @b: Pointer to "struct tomoyo_acl_info". |
482 | * | 482 | * |
483 | * Returns true if @a == @b except permission bits, false otherwise. | 483 | * Returns true if @a == @b except permission bits, false otherwise. |
484 | */ | 484 | */ |
485 | static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, | 485 | static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, |
486 | const struct tomoyo_acl_info *b) | 486 | const struct tomoyo_acl_info *b) |
487 | { | 487 | { |
488 | const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); | 488 | const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); |
489 | const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); | 489 | const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); |
490 | return tomoyo_same_name_union(&p1->name1, &p2->name1) && | 490 | return tomoyo_same_name_union(&p1->name1, &p2->name1) && |
491 | tomoyo_same_name_union(&p1->name2, &p2->name2); | 491 | tomoyo_same_name_union(&p1->name2, &p2->name2); |
492 | } | 492 | } |
493 | 493 | ||
494 | /** | 494 | /** |
495 | * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry. | 495 | * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry. |
496 | * | 496 | * |
497 | * @a: Pointer to "struct tomoyo_acl_info". | 497 | * @a: Pointer to "struct tomoyo_acl_info". |
498 | * @b: Pointer to "struct tomoyo_acl_info". | 498 | * @b: Pointer to "struct tomoyo_acl_info". |
499 | * @is_delete: True for @a &= ~@b, false for @a |= @b. | 499 | * @is_delete: True for @a &= ~@b, false for @a |= @b. |
500 | * | 500 | * |
501 | * Returns true if @a is empty, false otherwise. | 501 | * Returns true if @a is empty, false otherwise. |
502 | */ | 502 | */ |
503 | static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, | 503 | static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, |
504 | struct tomoyo_acl_info *b, | 504 | struct tomoyo_acl_info *b, |
505 | const bool is_delete) | 505 | const bool is_delete) |
506 | { | 506 | { |
507 | u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head) | 507 | u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head) |
508 | ->perm; | 508 | ->perm; |
509 | u8 perm = *a_perm; | 509 | u8 perm = *a_perm; |
510 | const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; | 510 | const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; |
511 | if (is_delete) | 511 | if (is_delete) |
512 | perm &= ~b_perm; | 512 | perm &= ~b_perm; |
513 | else | 513 | else |
514 | perm |= b_perm; | 514 | perm |= b_perm; |
515 | *a_perm = perm; | 515 | *a_perm = perm; |
516 | return !perm; | 516 | return !perm; |
517 | } | 517 | } |
518 | 518 | ||
519 | /** | 519 | /** |
520 | * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. | 520 | * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. |
521 | * | 521 | * |
522 | * @perm: Permission. | 522 | * @perm: Permission. |
523 | * @param: Pointer to "struct tomoyo_acl_param". | 523 | * @param: Pointer to "struct tomoyo_acl_param". |
524 | * | 524 | * |
525 | * Returns 0 on success, negative value otherwise. | 525 | * Returns 0 on success, negative value otherwise. |
526 | * | 526 | * |
527 | * Caller holds tomoyo_read_lock(). | 527 | * Caller holds tomoyo_read_lock(). |
528 | */ | 528 | */ |
529 | static int tomoyo_update_path2_acl(const u8 perm, | 529 | static int tomoyo_update_path2_acl(const u8 perm, |
530 | struct tomoyo_acl_param *param) | 530 | struct tomoyo_acl_param *param) |
531 | { | 531 | { |
532 | struct tomoyo_path2_acl e = { | 532 | struct tomoyo_path2_acl e = { |
533 | .head.type = TOMOYO_TYPE_PATH2_ACL, | 533 | .head.type = TOMOYO_TYPE_PATH2_ACL, |
534 | .perm = perm | 534 | .perm = perm |
535 | }; | 535 | }; |
536 | int error; | 536 | int error; |
537 | if (!tomoyo_parse_name_union(param, &e.name1) || | 537 | if (!tomoyo_parse_name_union(param, &e.name1) || |
538 | !tomoyo_parse_name_union(param, &e.name2)) | 538 | !tomoyo_parse_name_union(param, &e.name2)) |
539 | error = -EINVAL; | 539 | error = -EINVAL; |
540 | else | 540 | else |
541 | error = tomoyo_update_domain(&e.head, sizeof(e), param, | 541 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
542 | tomoyo_same_path2_acl, | 542 | tomoyo_same_path2_acl, |
543 | tomoyo_merge_path2_acl); | 543 | tomoyo_merge_path2_acl); |
544 | tomoyo_put_name_union(&e.name1); | 544 | tomoyo_put_name_union(&e.name1); |
545 | tomoyo_put_name_union(&e.name2); | 545 | tomoyo_put_name_union(&e.name2); |
546 | return error; | 546 | return error; |
547 | } | 547 | } |
548 | 548 | ||
549 | /** | 549 | /** |
550 | * tomoyo_path_permission - Check permission for single path operation. | 550 | * tomoyo_path_permission - Check permission for single path operation. |
551 | * | 551 | * |
552 | * @r: Pointer to "struct tomoyo_request_info". | 552 | * @r: Pointer to "struct tomoyo_request_info". |
553 | * @operation: Type of operation. | 553 | * @operation: Type of operation. |
554 | * @filename: Filename to check. | 554 | * @filename: Filename to check. |
555 | * | 555 | * |
556 | * Returns 0 on success, negative value otherwise. | 556 | * Returns 0 on success, negative value otherwise. |
557 | * | 557 | * |
558 | * Caller holds tomoyo_read_lock(). | 558 | * Caller holds tomoyo_read_lock(). |
559 | */ | 559 | */ |
560 | int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | 560 | int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, |
561 | const struct tomoyo_path_info *filename) | 561 | const struct tomoyo_path_info *filename) |
562 | { | 562 | { |
563 | int error; | 563 | int error; |
564 | 564 | ||
565 | r->type = tomoyo_p2mac[operation]; | 565 | r->type = tomoyo_p2mac[operation]; |
566 | r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type); | 566 | r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type); |
567 | if (r->mode == TOMOYO_CONFIG_DISABLED) | 567 | if (r->mode == TOMOYO_CONFIG_DISABLED) |
568 | return 0; | 568 | return 0; |
569 | r->param_type = TOMOYO_TYPE_PATH_ACL; | 569 | r->param_type = TOMOYO_TYPE_PATH_ACL; |
570 | r->param.path.filename = filename; | 570 | r->param.path.filename = filename; |
571 | r->param.path.operation = operation; | 571 | r->param.path.operation = operation; |
572 | do { | 572 | do { |
573 | tomoyo_check_acl(r, tomoyo_check_path_acl); | 573 | tomoyo_check_acl(r, tomoyo_check_path_acl); |
574 | error = tomoyo_audit_path_log(r); | 574 | error = tomoyo_audit_path_log(r); |
575 | /* | 575 | /* |
576 | * Do not retry for execute request, for alias may have | 576 | * Do not retry for execute request, for alias may have |
577 | * changed. | 577 | * changed. |
578 | */ | 578 | */ |
579 | } while (error == TOMOYO_RETRY_REQUEST && | 579 | } while (error == TOMOYO_RETRY_REQUEST && |
580 | operation != TOMOYO_TYPE_EXECUTE); | 580 | operation != TOMOYO_TYPE_EXECUTE); |
581 | return error; | 581 | return error; |
582 | } | 582 | } |
583 | 583 | ||
584 | /** | 584 | /** |
585 | * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry. | 585 | * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry. |
586 | * | 586 | * |
587 | * @a: Pointer to "struct tomoyo_acl_info". | 587 | * @a: Pointer to "struct tomoyo_acl_info". |
588 | * @b: Pointer to "struct tomoyo_acl_info". | 588 | * @b: Pointer to "struct tomoyo_acl_info". |
589 | * | 589 | * |
590 | * Returns true if @a == @b except permission bits, false otherwise. | 590 | * Returns true if @a == @b except permission bits, false otherwise. |
591 | */ | 591 | */ |
592 | static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, | 592 | static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, |
593 | const struct tomoyo_acl_info *b) | 593 | const struct tomoyo_acl_info *b) |
594 | { | 594 | { |
595 | const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1), | 595 | const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1), |
596 | head); | 596 | head); |
597 | const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), | 597 | const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), |
598 | head); | 598 | head); |
599 | return tomoyo_same_name_union(&p1->name, &p2->name) && | 599 | return tomoyo_same_name_union(&p1->name, &p2->name) && |
600 | tomoyo_same_number_union(&p1->number, &p2->number); | 600 | tomoyo_same_number_union(&p1->number, &p2->number); |
601 | } | 601 | } |
602 | 602 | ||
603 | /** | 603 | /** |
604 | * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry. | 604 | * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry. |
605 | * | 605 | * |
606 | * @a: Pointer to "struct tomoyo_acl_info". | 606 | * @a: Pointer to "struct tomoyo_acl_info". |
607 | * @b: Pointer to "struct tomoyo_acl_info". | 607 | * @b: Pointer to "struct tomoyo_acl_info". |
608 | * @is_delete: True for @a &= ~@b, false for @a |= @b. | 608 | * @is_delete: True for @a &= ~@b, false for @a |= @b. |
609 | * | 609 | * |
610 | * Returns true if @a is empty, false otherwise. | 610 | * Returns true if @a is empty, false otherwise. |
611 | */ | 611 | */ |
612 | static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, | 612 | static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, |
613 | struct tomoyo_acl_info *b, | 613 | struct tomoyo_acl_info *b, |
614 | const bool is_delete) | 614 | const bool is_delete) |
615 | { | 615 | { |
616 | u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl, | 616 | u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl, |
617 | head)->perm; | 617 | head)->perm; |
618 | u8 perm = *a_perm; | 618 | u8 perm = *a_perm; |
619 | const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) | 619 | const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) |
620 | ->perm; | 620 | ->perm; |
621 | if (is_delete) | 621 | if (is_delete) |
622 | perm &= ~b_perm; | 622 | perm &= ~b_perm; |
623 | else | 623 | else |
624 | perm |= b_perm; | 624 | perm |= b_perm; |
625 | *a_perm = perm; | 625 | *a_perm = perm; |
626 | return !perm; | 626 | return !perm; |
627 | } | 627 | } |
628 | 628 | ||
629 | /** | 629 | /** |
630 | * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. | 630 | * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. |
631 | * | 631 | * |
632 | * @perm: Permission. | 632 | * @perm: Permission. |
633 | * @param: Pointer to "struct tomoyo_acl_param". | 633 | * @param: Pointer to "struct tomoyo_acl_param". |
634 | * | 634 | * |
635 | * Returns 0 on success, negative value otherwise. | 635 | * Returns 0 on success, negative value otherwise. |
636 | */ | 636 | */ |
637 | static int tomoyo_update_path_number_acl(const u8 perm, | 637 | static int tomoyo_update_path_number_acl(const u8 perm, |
638 | struct tomoyo_acl_param *param) | 638 | struct tomoyo_acl_param *param) |
639 | { | 639 | { |
640 | struct tomoyo_path_number_acl e = { | 640 | struct tomoyo_path_number_acl e = { |
641 | .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, | 641 | .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, |
642 | .perm = perm | 642 | .perm = perm |
643 | }; | 643 | }; |
644 | int error; | 644 | int error; |
645 | if (!tomoyo_parse_name_union(param, &e.name) || | 645 | if (!tomoyo_parse_name_union(param, &e.name) || |
646 | !tomoyo_parse_number_union(param, &e.number)) | 646 | !tomoyo_parse_number_union(param, &e.number)) |
647 | error = -EINVAL; | 647 | error = -EINVAL; |
648 | else | 648 | else |
649 | error = tomoyo_update_domain(&e.head, sizeof(e), param, | 649 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
650 | tomoyo_same_path_number_acl, | 650 | tomoyo_same_path_number_acl, |
651 | tomoyo_merge_path_number_acl); | 651 | tomoyo_merge_path_number_acl); |
652 | tomoyo_put_name_union(&e.name); | 652 | tomoyo_put_name_union(&e.name); |
653 | tomoyo_put_number_union(&e.number); | 653 | tomoyo_put_number_union(&e.number); |
654 | return error; | 654 | return error; |
655 | } | 655 | } |
656 | 656 | ||
657 | /** | 657 | /** |
658 | * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". | 658 | * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". |
659 | * | 659 | * |
660 | * @type: Type of operation. | 660 | * @type: Type of operation. |
661 | * @path: Pointer to "struct path". | 661 | * @path: Pointer to "struct path". |
662 | * @number: Number. | 662 | * @number: Number. |
663 | * | 663 | * |
664 | * Returns 0 on success, negative value otherwise. | 664 | * Returns 0 on success, negative value otherwise. |
665 | */ | 665 | */ |
666 | int tomoyo_path_number_perm(const u8 type, struct path *path, | 666 | int tomoyo_path_number_perm(const u8 type, struct path *path, |
667 | unsigned long number) | 667 | unsigned long number) |
668 | { | 668 | { |
669 | struct tomoyo_request_info r; | 669 | struct tomoyo_request_info r; |
670 | struct tomoyo_obj_info obj = { | ||
671 | .path1 = *path, | ||
672 | }; | ||
670 | int error = -ENOMEM; | 673 | int error = -ENOMEM; |
671 | struct tomoyo_path_info buf; | 674 | struct tomoyo_path_info buf; |
672 | int idx; | 675 | int idx; |
673 | 676 | ||
674 | if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) | 677 | if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) |
675 | == TOMOYO_CONFIG_DISABLED || !path->dentry) | 678 | == TOMOYO_CONFIG_DISABLED || !path->dentry) |
676 | return 0; | 679 | return 0; |
677 | idx = tomoyo_read_lock(); | 680 | idx = tomoyo_read_lock(); |
678 | if (!tomoyo_get_realpath(&buf, path)) | 681 | if (!tomoyo_get_realpath(&buf, path)) |
679 | goto out; | 682 | goto out; |
683 | r.obj = &obj; | ||
680 | if (type == TOMOYO_TYPE_MKDIR) | 684 | if (type == TOMOYO_TYPE_MKDIR) |
681 | tomoyo_add_slash(&buf); | 685 | tomoyo_add_slash(&buf); |
682 | r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; | 686 | r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; |
683 | r.param.path_number.operation = type; | 687 | r.param.path_number.operation = type; |
684 | r.param.path_number.filename = &buf; | 688 | r.param.path_number.filename = &buf; |
685 | r.param.path_number.number = number; | 689 | r.param.path_number.number = number; |
686 | do { | 690 | do { |
687 | tomoyo_check_acl(&r, tomoyo_check_path_number_acl); | 691 | tomoyo_check_acl(&r, tomoyo_check_path_number_acl); |
688 | error = tomoyo_audit_path_number_log(&r); | 692 | error = tomoyo_audit_path_number_log(&r); |
689 | } while (error == TOMOYO_RETRY_REQUEST); | 693 | } while (error == TOMOYO_RETRY_REQUEST); |
690 | kfree(buf.name); | 694 | kfree(buf.name); |
691 | out: | 695 | out: |
692 | tomoyo_read_unlock(idx); | 696 | tomoyo_read_unlock(idx); |
693 | if (r.mode != TOMOYO_CONFIG_ENFORCING) | 697 | if (r.mode != TOMOYO_CONFIG_ENFORCING) |
694 | error = 0; | 698 | error = 0; |
695 | return error; | 699 | return error; |
696 | } | 700 | } |
697 | 701 | ||
698 | /** | 702 | /** |
699 | * tomoyo_check_open_permission - Check permission for "read" and "write". | 703 | * tomoyo_check_open_permission - Check permission for "read" and "write". |
700 | * | 704 | * |
701 | * @domain: Pointer to "struct tomoyo_domain_info". | 705 | * @domain: Pointer to "struct tomoyo_domain_info". |
702 | * @path: Pointer to "struct path". | 706 | * @path: Pointer to "struct path". |
703 | * @flag: Flags for open(). | 707 | * @flag: Flags for open(). |
704 | * | 708 | * |
705 | * Returns 0 on success, negative value otherwise. | 709 | * Returns 0 on success, negative value otherwise. |
706 | */ | 710 | */ |
707 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | 711 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, |
708 | struct path *path, const int flag) | 712 | struct path *path, const int flag) |
709 | { | 713 | { |
710 | const u8 acc_mode = ACC_MODE(flag); | 714 | const u8 acc_mode = ACC_MODE(flag); |
711 | int error = 0; | 715 | int error = 0; |
712 | struct tomoyo_path_info buf; | 716 | struct tomoyo_path_info buf; |
713 | struct tomoyo_request_info r; | 717 | struct tomoyo_request_info r; |
718 | struct tomoyo_obj_info obj = { | ||
719 | .path1 = *path, | ||
720 | }; | ||
714 | int idx; | 721 | int idx; |
715 | 722 | ||
716 | buf.name = NULL; | 723 | buf.name = NULL; |
717 | r.mode = TOMOYO_CONFIG_DISABLED; | 724 | r.mode = TOMOYO_CONFIG_DISABLED; |
718 | idx = tomoyo_read_lock(); | 725 | idx = tomoyo_read_lock(); |
719 | if (acc_mode && | 726 | if (acc_mode && |
720 | tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) | 727 | tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) |
721 | != TOMOYO_CONFIG_DISABLED) { | 728 | != TOMOYO_CONFIG_DISABLED) { |
722 | if (!tomoyo_get_realpath(&buf, path)) { | 729 | if (!tomoyo_get_realpath(&buf, path)) { |
723 | error = -ENOMEM; | 730 | error = -ENOMEM; |
724 | goto out; | 731 | goto out; |
725 | } | 732 | } |
733 | r.obj = &obj; | ||
726 | if (acc_mode & MAY_READ) | 734 | if (acc_mode & MAY_READ) |
727 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, | 735 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, |
728 | &buf); | 736 | &buf); |
729 | if (!error && (acc_mode & MAY_WRITE)) | 737 | if (!error && (acc_mode & MAY_WRITE)) |
730 | error = tomoyo_path_permission(&r, (flag & O_APPEND) ? | 738 | error = tomoyo_path_permission(&r, (flag & O_APPEND) ? |
731 | TOMOYO_TYPE_APPEND : | 739 | TOMOYO_TYPE_APPEND : |
732 | TOMOYO_TYPE_WRITE, | 740 | TOMOYO_TYPE_WRITE, |
733 | &buf); | 741 | &buf); |
734 | } | 742 | } |
735 | out: | 743 | out: |
736 | kfree(buf.name); | 744 | kfree(buf.name); |
737 | tomoyo_read_unlock(idx); | 745 | tomoyo_read_unlock(idx); |
738 | if (r.mode != TOMOYO_CONFIG_ENFORCING) | 746 | if (r.mode != TOMOYO_CONFIG_ENFORCING) |
739 | error = 0; | 747 | error = 0; |
740 | return error; | 748 | return error; |
741 | } | 749 | } |
742 | 750 | ||
743 | /** | 751 | /** |
744 | * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount". | 752 | * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount". |
745 | * | 753 | * |
746 | * @operation: Type of operation. | 754 | * @operation: Type of operation. |
747 | * @path: Pointer to "struct path". | 755 | * @path: Pointer to "struct path". |
756 | * @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK, | ||
757 | * NULL otherwise. | ||
748 | * | 758 | * |
749 | * Returns 0 on success, negative value otherwise. | 759 | * Returns 0 on success, negative value otherwise. |
750 | */ | 760 | */ |
751 | int tomoyo_path_perm(const u8 operation, struct path *path) | 761 | int tomoyo_path_perm(const u8 operation, struct path *path, const char *target) |
752 | { | 762 | { |
753 | struct tomoyo_request_info r; | 763 | struct tomoyo_request_info r; |
764 | struct tomoyo_obj_info obj = { | ||
765 | .path1 = *path, | ||
766 | }; | ||
754 | int error; | 767 | int error; |
755 | struct tomoyo_path_info buf; | 768 | struct tomoyo_path_info buf; |
756 | bool is_enforce; | 769 | bool is_enforce; |
770 | struct tomoyo_path_info symlink_target; | ||
757 | int idx; | 771 | int idx; |
758 | 772 | ||
759 | if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) | 773 | if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) |
760 | == TOMOYO_CONFIG_DISABLED) | 774 | == TOMOYO_CONFIG_DISABLED) |
761 | return 0; | 775 | return 0; |
762 | is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING); | 776 | is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING); |
763 | error = -ENOMEM; | 777 | error = -ENOMEM; |
764 | buf.name = NULL; | 778 | buf.name = NULL; |
765 | idx = tomoyo_read_lock(); | 779 | idx = tomoyo_read_lock(); |
766 | if (!tomoyo_get_realpath(&buf, path)) | 780 | if (!tomoyo_get_realpath(&buf, path)) |
767 | goto out; | 781 | goto out; |
782 | r.obj = &obj; | ||
768 | switch (operation) { | 783 | switch (operation) { |
769 | case TOMOYO_TYPE_RMDIR: | 784 | case TOMOYO_TYPE_RMDIR: |
770 | case TOMOYO_TYPE_CHROOT: | 785 | case TOMOYO_TYPE_CHROOT: |
771 | tomoyo_add_slash(&buf); | 786 | tomoyo_add_slash(&buf); |
772 | break; | 787 | break; |
788 | case TOMOYO_TYPE_SYMLINK: | ||
789 | symlink_target.name = tomoyo_encode(target); | ||
790 | if (!symlink_target.name) | ||
791 | goto out; | ||
792 | tomoyo_fill_path_info(&symlink_target); | ||
793 | obj.symlink_target = &symlink_target; | ||
794 | break; | ||
773 | } | 795 | } |
774 | error = tomoyo_path_permission(&r, operation, &buf); | 796 | error = tomoyo_path_permission(&r, operation, &buf); |
797 | if (operation == TOMOYO_TYPE_SYMLINK) | ||
798 | kfree(symlink_target.name); | ||
775 | out: | 799 | out: |
776 | kfree(buf.name); | 800 | kfree(buf.name); |
777 | tomoyo_read_unlock(idx); | 801 | tomoyo_read_unlock(idx); |
778 | if (!is_enforce) | 802 | if (!is_enforce) |
779 | error = 0; | 803 | error = 0; |
780 | return error; | 804 | return error; |
781 | } | 805 | } |
782 | 806 | ||
783 | /** | 807 | /** |
784 | * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar". | 808 | * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar". |
785 | * | 809 | * |
786 | * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) | 810 | * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) |
787 | * @path: Pointer to "struct path". | 811 | * @path: Pointer to "struct path". |
788 | * @mode: Create mode. | 812 | * @mode: Create mode. |
789 | * @dev: Device number. | 813 | * @dev: Device number. |
790 | * | 814 | * |
791 | * Returns 0 on success, negative value otherwise. | 815 | * Returns 0 on success, negative value otherwise. |
792 | */ | 816 | */ |
793 | int tomoyo_mkdev_perm(const u8 operation, struct path *path, | 817 | int tomoyo_mkdev_perm(const u8 operation, struct path *path, |
794 | const unsigned int mode, unsigned int dev) | 818 | const unsigned int mode, unsigned int dev) |
795 | { | 819 | { |
796 | struct tomoyo_request_info r; | 820 | struct tomoyo_request_info r; |
821 | struct tomoyo_obj_info obj = { | ||
822 | .path1 = *path, | ||
823 | }; | ||
797 | int error = -ENOMEM; | 824 | int error = -ENOMEM; |
798 | struct tomoyo_path_info buf; | 825 | struct tomoyo_path_info buf; |
799 | int idx; | 826 | int idx; |
800 | 827 | ||
801 | if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) | 828 | if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) |
802 | == TOMOYO_CONFIG_DISABLED) | 829 | == TOMOYO_CONFIG_DISABLED) |
803 | return 0; | 830 | return 0; |
804 | idx = tomoyo_read_lock(); | 831 | idx = tomoyo_read_lock(); |
805 | error = -ENOMEM; | 832 | error = -ENOMEM; |
806 | if (tomoyo_get_realpath(&buf, path)) { | 833 | if (tomoyo_get_realpath(&buf, path)) { |
834 | r.obj = &obj; | ||
807 | dev = new_decode_dev(dev); | 835 | dev = new_decode_dev(dev); |
808 | r.param_type = TOMOYO_TYPE_MKDEV_ACL; | 836 | r.param_type = TOMOYO_TYPE_MKDEV_ACL; |
809 | r.param.mkdev.filename = &buf; | 837 | r.param.mkdev.filename = &buf; |
810 | r.param.mkdev.operation = operation; | 838 | r.param.mkdev.operation = operation; |
811 | r.param.mkdev.mode = mode; | 839 | r.param.mkdev.mode = mode; |
812 | r.param.mkdev.major = MAJOR(dev); | 840 | r.param.mkdev.major = MAJOR(dev); |
813 | r.param.mkdev.minor = MINOR(dev); | 841 | r.param.mkdev.minor = MINOR(dev); |
814 | tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); | 842 | tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); |
815 | error = tomoyo_audit_mkdev_log(&r); | 843 | error = tomoyo_audit_mkdev_log(&r); |
816 | kfree(buf.name); | 844 | kfree(buf.name); |
817 | } | 845 | } |
818 | tomoyo_read_unlock(idx); | 846 | tomoyo_read_unlock(idx); |
819 | if (r.mode != TOMOYO_CONFIG_ENFORCING) | 847 | if (r.mode != TOMOYO_CONFIG_ENFORCING) |
820 | error = 0; | 848 | error = 0; |
821 | return error; | 849 | return error; |
822 | } | 850 | } |
823 | 851 | ||
824 | /** | 852 | /** |
825 | * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". | 853 | * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". |
826 | * | 854 | * |
827 | * @operation: Type of operation. | 855 | * @operation: Type of operation. |
828 | * @path1: Pointer to "struct path". | 856 | * @path1: Pointer to "struct path". |
829 | * @path2: Pointer to "struct path". | 857 | * @path2: Pointer to "struct path". |
830 | * | 858 | * |
831 | * Returns 0 on success, negative value otherwise. | 859 | * Returns 0 on success, negative value otherwise. |
832 | */ | 860 | */ |
833 | int tomoyo_path2_perm(const u8 operation, struct path *path1, | 861 | int tomoyo_path2_perm(const u8 operation, struct path *path1, |
834 | struct path *path2) | 862 | struct path *path2) |
835 | { | 863 | { |
836 | int error = -ENOMEM; | 864 | int error = -ENOMEM; |
837 | struct tomoyo_path_info buf1; | 865 | struct tomoyo_path_info buf1; |
838 | struct tomoyo_path_info buf2; | 866 | struct tomoyo_path_info buf2; |
839 | struct tomoyo_request_info r; | 867 | struct tomoyo_request_info r; |
868 | struct tomoyo_obj_info obj = { | ||
869 | .path1 = *path1, | ||
870 | .path2 = *path2, | ||
871 | }; | ||
840 | int idx; | 872 | int idx; |
841 | 873 | ||
842 | if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) | 874 | if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) |
843 | == TOMOYO_CONFIG_DISABLED) | 875 | == TOMOYO_CONFIG_DISABLED) |
844 | return 0; | 876 | return 0; |
845 | buf1.name = NULL; | 877 | buf1.name = NULL; |
846 | buf2.name = NULL; | 878 | buf2.name = NULL; |
847 | idx = tomoyo_read_lock(); | 879 | idx = tomoyo_read_lock(); |
848 | if (!tomoyo_get_realpath(&buf1, path1) || | 880 | if (!tomoyo_get_realpath(&buf1, path1) || |
849 | !tomoyo_get_realpath(&buf2, path2)) | 881 | !tomoyo_get_realpath(&buf2, path2)) |
850 | goto out; | 882 | goto out; |
851 | switch (operation) { | 883 | switch (operation) { |
852 | struct dentry *dentry; | 884 | struct dentry *dentry; |
853 | case TOMOYO_TYPE_RENAME: | 885 | case TOMOYO_TYPE_RENAME: |
854 | case TOMOYO_TYPE_LINK: | 886 | case TOMOYO_TYPE_LINK: |
855 | dentry = path1->dentry; | 887 | dentry = path1->dentry; |
856 | if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) | 888 | if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) |
857 | break; | 889 | break; |
858 | /* fall through */ | 890 | /* fall through */ |
859 | case TOMOYO_TYPE_PIVOT_ROOT: | 891 | case TOMOYO_TYPE_PIVOT_ROOT: |
860 | tomoyo_add_slash(&buf1); | 892 | tomoyo_add_slash(&buf1); |
861 | tomoyo_add_slash(&buf2); | 893 | tomoyo_add_slash(&buf2); |
862 | break; | 894 | break; |
863 | } | 895 | } |
896 | r.obj = &obj; | ||
864 | r.param_type = TOMOYO_TYPE_PATH2_ACL; | 897 | r.param_type = TOMOYO_TYPE_PATH2_ACL; |
865 | r.param.path2.operation = operation; | 898 | r.param.path2.operation = operation; |
866 | r.param.path2.filename1 = &buf1; | 899 | r.param.path2.filename1 = &buf1; |
867 | r.param.path2.filename2 = &buf2; | 900 | r.param.path2.filename2 = &buf2; |
868 | do { | 901 | do { |
869 | tomoyo_check_acl(&r, tomoyo_check_path2_acl); | 902 | tomoyo_check_acl(&r, tomoyo_check_path2_acl); |
870 | error = tomoyo_audit_path2_log(&r); | 903 | error = tomoyo_audit_path2_log(&r); |
871 | } while (error == TOMOYO_RETRY_REQUEST); | 904 | } while (error == TOMOYO_RETRY_REQUEST); |
872 | out: | 905 | out: |
873 | kfree(buf1.name); | 906 | kfree(buf1.name); |
874 | kfree(buf2.name); | 907 | kfree(buf2.name); |
875 | tomoyo_read_unlock(idx); | 908 | tomoyo_read_unlock(idx); |
876 | if (r.mode != TOMOYO_CONFIG_ENFORCING) | 909 | if (r.mode != TOMOYO_CONFIG_ENFORCING) |
877 | error = 0; | 910 | error = 0; |
878 | return error; | 911 | return error; |
879 | } | 912 | } |
880 | 913 | ||
881 | /** | 914 | /** |
882 | * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry. | 915 | * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry. |
883 | * | 916 | * |
884 | * @a: Pointer to "struct tomoyo_acl_info". | 917 | * @a: Pointer to "struct tomoyo_acl_info". |
885 | * @b: Pointer to "struct tomoyo_acl_info". | 918 | * @b: Pointer to "struct tomoyo_acl_info". |
886 | * | 919 | * |
887 | * Returns true if @a == @b, false otherwise. | 920 | * Returns true if @a == @b, false otherwise. |
888 | */ | 921 | */ |
889 | static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, | 922 | static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, |
890 | const struct tomoyo_acl_info *b) | 923 | const struct tomoyo_acl_info *b) |
891 | { | 924 | { |
892 | const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); | 925 | const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); |
893 | const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); | 926 | const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); |
894 | return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && | 927 | return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && |
895 | tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && | 928 | tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && |
896 | tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && | 929 | tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && |
897 | tomoyo_same_number_union(&p1->flags, &p2->flags); | 930 | tomoyo_same_number_union(&p1->flags, &p2->flags); |
898 | } | 931 | } |
899 | 932 | ||
900 | /** | 933 | /** |
901 | * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list. | 934 | * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list. |
902 | * | 935 | * |
903 | * @param: Pointer to "struct tomoyo_acl_param". | 936 | * @param: Pointer to "struct tomoyo_acl_param". |
904 | * | 937 | * |
905 | * Returns 0 on success, negative value otherwise. | 938 | * Returns 0 on success, negative value otherwise. |
906 | * | 939 | * |
907 | * Caller holds tomoyo_read_lock(). | 940 | * Caller holds tomoyo_read_lock(). |
908 | */ | 941 | */ |
909 | static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param) | 942 | static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param) |
910 | { | 943 | { |
911 | struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; | 944 | struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; |
912 | int error; | 945 | int error; |
913 | if (!tomoyo_parse_name_union(param, &e.dev_name) || | 946 | if (!tomoyo_parse_name_union(param, &e.dev_name) || |
914 | !tomoyo_parse_name_union(param, &e.dir_name) || | 947 | !tomoyo_parse_name_union(param, &e.dir_name) || |
915 | !tomoyo_parse_name_union(param, &e.fs_type) || | 948 | !tomoyo_parse_name_union(param, &e.fs_type) || |
916 | !tomoyo_parse_number_union(param, &e.flags)) | 949 | !tomoyo_parse_number_union(param, &e.flags)) |
917 | error = -EINVAL; | 950 | error = -EINVAL; |
918 | else | 951 | else |
919 | error = tomoyo_update_domain(&e.head, sizeof(e), param, | 952 | error = tomoyo_update_domain(&e.head, sizeof(e), param, |
920 | tomoyo_same_mount_acl, NULL); | 953 | tomoyo_same_mount_acl, NULL); |
921 | tomoyo_put_name_union(&e.dev_name); | 954 | tomoyo_put_name_union(&e.dev_name); |
922 | tomoyo_put_name_union(&e.dir_name); | 955 | tomoyo_put_name_union(&e.dir_name); |
923 | tomoyo_put_name_union(&e.fs_type); | 956 | tomoyo_put_name_union(&e.fs_type); |
924 | tomoyo_put_number_union(&e.flags); | 957 | tomoyo_put_number_union(&e.flags); |
925 | return error; | 958 | return error; |
926 | } | 959 | } |
927 | 960 | ||
928 | /** | 961 | /** |
929 | * tomoyo_write_file - Update file related list. | 962 | * tomoyo_write_file - Update file related list. |
930 | * | 963 | * |
931 | * @param: Pointer to "struct tomoyo_acl_param". | 964 | * @param: Pointer to "struct tomoyo_acl_param". |
932 | * | 965 | * |
933 | * Returns 0 on success, negative value otherwise. | 966 | * Returns 0 on success, negative value otherwise. |
934 | * | 967 | * |
935 | * Caller holds tomoyo_read_lock(). | 968 | * Caller holds tomoyo_read_lock(). |
936 | */ | 969 | */ |
937 | int tomoyo_write_file(struct tomoyo_acl_param *param) | 970 | int tomoyo_write_file(struct tomoyo_acl_param *param) |
938 | { | 971 | { |
939 | u16 perm = 0; | 972 | u16 perm = 0; |
940 | u8 type; | 973 | u8 type; |
941 | const char *operation = tomoyo_read_token(param); | 974 | const char *operation = tomoyo_read_token(param); |
942 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) | 975 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) |
943 | if (tomoyo_permstr(operation, tomoyo_path_keyword[type])) | 976 | if (tomoyo_permstr(operation, tomoyo_path_keyword[type])) |
944 | perm |= 1 << type; | 977 | perm |= 1 << type; |
945 | if (perm) | 978 | if (perm) |
946 | return tomoyo_update_path_acl(perm, param); | 979 | return tomoyo_update_path_acl(perm, param); |
947 | for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) | 980 | for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) |
948 | if (tomoyo_permstr(operation, | 981 | if (tomoyo_permstr(operation, |
949 | tomoyo_mac_keywords[tomoyo_pp2mac[type]])) | 982 | tomoyo_mac_keywords[tomoyo_pp2mac[type]])) |
950 | perm |= 1 << type; | 983 | perm |= 1 << type; |
951 | if (perm) | 984 | if (perm) |
952 | return tomoyo_update_path2_acl(perm, param); | 985 | return tomoyo_update_path2_acl(perm, param); |
953 | for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) | 986 | for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) |
954 | if (tomoyo_permstr(operation, | 987 | if (tomoyo_permstr(operation, |
955 | tomoyo_mac_keywords[tomoyo_pn2mac[type]])) | 988 | tomoyo_mac_keywords[tomoyo_pn2mac[type]])) |
956 | perm |= 1 << type; | 989 | perm |= 1 << type; |
957 | if (perm) | 990 | if (perm) |
958 | return tomoyo_update_path_number_acl(perm, param); | 991 | return tomoyo_update_path_number_acl(perm, param); |
959 | for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) | 992 | for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) |
960 | if (tomoyo_permstr(operation, | 993 | if (tomoyo_permstr(operation, |
961 | tomoyo_mac_keywords[tomoyo_pnnn2mac[type]])) | 994 | tomoyo_mac_keywords[tomoyo_pnnn2mac[type]])) |
962 | perm |= 1 << type; | 995 | perm |= 1 << type; |
963 | if (perm) | 996 | if (perm) |
964 | return tomoyo_update_mkdev_acl(perm, param); | 997 | return tomoyo_update_mkdev_acl(perm, param); |
965 | if (tomoyo_permstr(operation, | 998 | if (tomoyo_permstr(operation, |
966 | tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT])) | 999 | tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT])) |
967 | return tomoyo_update_mount_acl(param); | 1000 | return tomoyo_update_mount_acl(param); |
968 | return -EINVAL; | 1001 | return -EINVAL; |
969 | } | 1002 | } |
970 | 1003 |
security/tomoyo/mount.c
1 | /* | 1 | /* |
2 | * security/tomoyo/mount.c | 2 | * security/tomoyo/mount.c |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2010 NTT DATA CORPORATION | 4 | * Copyright (C) 2005-2010 NTT DATA CORPORATION |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
8 | #include "common.h" | 8 | #include "common.h" |
9 | 9 | ||
10 | /* String table for special mount operations. */ | 10 | /* String table for special mount operations. */ |
11 | static const char * const tomoyo_mounts[TOMOYO_MAX_SPECIAL_MOUNT] = { | 11 | static const char * const tomoyo_mounts[TOMOYO_MAX_SPECIAL_MOUNT] = { |
12 | [TOMOYO_MOUNT_BIND] = "--bind", | 12 | [TOMOYO_MOUNT_BIND] = "--bind", |
13 | [TOMOYO_MOUNT_MOVE] = "--move", | 13 | [TOMOYO_MOUNT_MOVE] = "--move", |
14 | [TOMOYO_MOUNT_REMOUNT] = "--remount", | 14 | [TOMOYO_MOUNT_REMOUNT] = "--remount", |
15 | [TOMOYO_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable", | 15 | [TOMOYO_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable", |
16 | [TOMOYO_MOUNT_MAKE_PRIVATE] = "--make-private", | 16 | [TOMOYO_MOUNT_MAKE_PRIVATE] = "--make-private", |
17 | [TOMOYO_MOUNT_MAKE_SLAVE] = "--make-slave", | 17 | [TOMOYO_MOUNT_MAKE_SLAVE] = "--make-slave", |
18 | [TOMOYO_MOUNT_MAKE_SHARED] = "--make-shared", | 18 | [TOMOYO_MOUNT_MAKE_SHARED] = "--make-shared", |
19 | }; | 19 | }; |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * tomoyo_audit_mount_log - Audit mount log. | 22 | * tomoyo_audit_mount_log - Audit mount log. |
23 | * | 23 | * |
24 | * @r: Pointer to "struct tomoyo_request_info". | 24 | * @r: Pointer to "struct tomoyo_request_info". |
25 | * | 25 | * |
26 | * Returns 0 on success, negative value otherwise. | 26 | * Returns 0 on success, negative value otherwise. |
27 | */ | 27 | */ |
28 | static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) | 28 | static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) |
29 | { | 29 | { |
30 | return tomoyo_supervisor(r, "file mount %s %s %s 0x%lX\n", | 30 | return tomoyo_supervisor(r, "file mount %s %s %s 0x%lX\n", |
31 | r->param.mount.dev->name, | 31 | r->param.mount.dev->name, |
32 | r->param.mount.dir->name, | 32 | r->param.mount.dir->name, |
33 | r->param.mount.type->name, | 33 | r->param.mount.type->name, |
34 | r->param.mount.flags); | 34 | r->param.mount.flags); |
35 | } | 35 | } |
36 | 36 | ||
37 | /** | 37 | /** |
38 | * tomoyo_check_mount_acl - Check permission for path path path number operation. | 38 | * tomoyo_check_mount_acl - Check permission for path path path number operation. |
39 | * | 39 | * |
40 | * @r: Pointer to "struct tomoyo_request_info". | 40 | * @r: Pointer to "struct tomoyo_request_info". |
41 | * @ptr: Pointer to "struct tomoyo_acl_info". | 41 | * @ptr: Pointer to "struct tomoyo_acl_info". |
42 | * | 42 | * |
43 | * Returns true if granted, false otherwise. | 43 | * Returns true if granted, false otherwise. |
44 | */ | 44 | */ |
45 | static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, | 45 | static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, |
46 | const struct tomoyo_acl_info *ptr) | 46 | const struct tomoyo_acl_info *ptr) |
47 | { | 47 | { |
48 | const struct tomoyo_mount_acl *acl = | 48 | const struct tomoyo_mount_acl *acl = |
49 | container_of(ptr, typeof(*acl), head); | 49 | container_of(ptr, typeof(*acl), head); |
50 | return tomoyo_compare_number_union(r->param.mount.flags, | 50 | return tomoyo_compare_number_union(r->param.mount.flags, |
51 | &acl->flags) && | 51 | &acl->flags) && |
52 | tomoyo_compare_name_union(r->param.mount.type, | 52 | tomoyo_compare_name_union(r->param.mount.type, |
53 | &acl->fs_type) && | 53 | &acl->fs_type) && |
54 | tomoyo_compare_name_union(r->param.mount.dir, | 54 | tomoyo_compare_name_union(r->param.mount.dir, |
55 | &acl->dir_name) && | 55 | &acl->dir_name) && |
56 | (!r->param.mount.need_dev || | 56 | (!r->param.mount.need_dev || |
57 | tomoyo_compare_name_union(r->param.mount.dev, | 57 | tomoyo_compare_name_union(r->param.mount.dev, |
58 | &acl->dev_name)); | 58 | &acl->dev_name)); |
59 | } | 59 | } |
60 | 60 | ||
61 | /** | 61 | /** |
62 | * tomoyo_mount_acl - Check permission for mount() operation. | 62 | * tomoyo_mount_acl - Check permission for mount() operation. |
63 | * | 63 | * |
64 | * @r: Pointer to "struct tomoyo_request_info". | 64 | * @r: Pointer to "struct tomoyo_request_info". |
65 | * @dev_name: Name of device file. | 65 | * @dev_name: Name of device file. |
66 | * @dir: Pointer to "struct path". | 66 | * @dir: Pointer to "struct path". |
67 | * @type: Name of filesystem type. | 67 | * @type: Name of filesystem type. |
68 | * @flags: Mount options. | 68 | * @flags: Mount options. |
69 | * | 69 | * |
70 | * Returns 0 on success, negative value otherwise. | 70 | * Returns 0 on success, negative value otherwise. |
71 | * | 71 | * |
72 | * Caller holds tomoyo_read_lock(). | 72 | * Caller holds tomoyo_read_lock(). |
73 | */ | 73 | */ |
74 | static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, | 74 | static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, |
75 | struct path *dir, const char *type, | 75 | struct path *dir, const char *type, |
76 | unsigned long flags) | 76 | unsigned long flags) |
77 | { | 77 | { |
78 | struct tomoyo_obj_info obj = { }; | ||
78 | struct path path; | 79 | struct path path; |
79 | struct file_system_type *fstype = NULL; | 80 | struct file_system_type *fstype = NULL; |
80 | const char *requested_type = NULL; | 81 | const char *requested_type = NULL; |
81 | const char *requested_dir_name = NULL; | 82 | const char *requested_dir_name = NULL; |
82 | const char *requested_dev_name = NULL; | 83 | const char *requested_dev_name = NULL; |
83 | struct tomoyo_path_info rtype; | 84 | struct tomoyo_path_info rtype; |
84 | struct tomoyo_path_info rdev; | 85 | struct tomoyo_path_info rdev; |
85 | struct tomoyo_path_info rdir; | 86 | struct tomoyo_path_info rdir; |
86 | int need_dev = 0; | 87 | int need_dev = 0; |
87 | int error = -ENOMEM; | 88 | int error = -ENOMEM; |
89 | r->obj = &obj; | ||
88 | 90 | ||
89 | /* Get fstype. */ | 91 | /* Get fstype. */ |
90 | requested_type = tomoyo_encode(type); | 92 | requested_type = tomoyo_encode(type); |
91 | if (!requested_type) | 93 | if (!requested_type) |
92 | goto out; | 94 | goto out; |
93 | rtype.name = requested_type; | 95 | rtype.name = requested_type; |
94 | tomoyo_fill_path_info(&rtype); | 96 | tomoyo_fill_path_info(&rtype); |
95 | 97 | ||
96 | /* Get mount point. */ | 98 | /* Get mount point. */ |
99 | obj.path2 = *dir; | ||
97 | requested_dir_name = tomoyo_realpath_from_path(dir); | 100 | requested_dir_name = tomoyo_realpath_from_path(dir); |
98 | if (!requested_dir_name) { | 101 | if (!requested_dir_name) { |
99 | error = -ENOMEM; | 102 | error = -ENOMEM; |
100 | goto out; | 103 | goto out; |
101 | } | 104 | } |
102 | rdir.name = requested_dir_name; | 105 | rdir.name = requested_dir_name; |
103 | tomoyo_fill_path_info(&rdir); | 106 | tomoyo_fill_path_info(&rdir); |
104 | 107 | ||
105 | /* Compare fs name. */ | 108 | /* Compare fs name. */ |
106 | if (type == tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]) { | 109 | if (type == tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]) { |
107 | /* dev_name is ignored. */ | 110 | /* dev_name is ignored. */ |
108 | } else if (type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE] || | 111 | } else if (type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE] || |
109 | type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE] || | 112 | type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE] || |
110 | type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE] || | 113 | type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE] || |
111 | type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]) { | 114 | type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]) { |
112 | /* dev_name is ignored. */ | 115 | /* dev_name is ignored. */ |
113 | } else if (type == tomoyo_mounts[TOMOYO_MOUNT_BIND] || | 116 | } else if (type == tomoyo_mounts[TOMOYO_MOUNT_BIND] || |
114 | type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) { | 117 | type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) { |
115 | need_dev = -1; /* dev_name is a directory */ | 118 | need_dev = -1; /* dev_name is a directory */ |
116 | } else { | 119 | } else { |
117 | fstype = get_fs_type(type); | 120 | fstype = get_fs_type(type); |
118 | if (!fstype) { | 121 | if (!fstype) { |
119 | error = -ENODEV; | 122 | error = -ENODEV; |
120 | goto out; | 123 | goto out; |
121 | } | 124 | } |
122 | if (fstype->fs_flags & FS_REQUIRES_DEV) | 125 | if (fstype->fs_flags & FS_REQUIRES_DEV) |
123 | /* dev_name is a block device file. */ | 126 | /* dev_name is a block device file. */ |
124 | need_dev = 1; | 127 | need_dev = 1; |
125 | } | 128 | } |
126 | if (need_dev) { | 129 | if (need_dev) { |
127 | /* Get mount point or device file. */ | 130 | /* Get mount point or device file. */ |
128 | if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) { | 131 | if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) { |
129 | error = -ENOENT; | 132 | error = -ENOENT; |
130 | goto out; | 133 | goto out; |
131 | } | 134 | } |
135 | obj.path1 = path; | ||
132 | requested_dev_name = tomoyo_realpath_from_path(&path); | 136 | requested_dev_name = tomoyo_realpath_from_path(&path); |
133 | path_put(&path); | ||
134 | if (!requested_dev_name) { | 137 | if (!requested_dev_name) { |
135 | error = -ENOENT; | 138 | error = -ENOENT; |
136 | goto out; | 139 | goto out; |
137 | } | 140 | } |
138 | } else { | 141 | } else { |
139 | /* Map dev_name to "<NULL>" if no dev_name given. */ | 142 | /* Map dev_name to "<NULL>" if no dev_name given. */ |
140 | if (!dev_name) | 143 | if (!dev_name) |
141 | dev_name = "<NULL>"; | 144 | dev_name = "<NULL>"; |
142 | requested_dev_name = tomoyo_encode(dev_name); | 145 | requested_dev_name = tomoyo_encode(dev_name); |
143 | if (!requested_dev_name) { | 146 | if (!requested_dev_name) { |
144 | error = -ENOMEM; | 147 | error = -ENOMEM; |
145 | goto out; | 148 | goto out; |
146 | } | 149 | } |
147 | } | 150 | } |
148 | rdev.name = requested_dev_name; | 151 | rdev.name = requested_dev_name; |
149 | tomoyo_fill_path_info(&rdev); | 152 | tomoyo_fill_path_info(&rdev); |
150 | r->param_type = TOMOYO_TYPE_MOUNT_ACL; | 153 | r->param_type = TOMOYO_TYPE_MOUNT_ACL; |
151 | r->param.mount.need_dev = need_dev; | 154 | r->param.mount.need_dev = need_dev; |
152 | r->param.mount.dev = &rdev; | 155 | r->param.mount.dev = &rdev; |
153 | r->param.mount.dir = &rdir; | 156 | r->param.mount.dir = &rdir; |
154 | r->param.mount.type = &rtype; | 157 | r->param.mount.type = &rtype; |
155 | r->param.mount.flags = flags; | 158 | r->param.mount.flags = flags; |
156 | do { | 159 | do { |
157 | tomoyo_check_acl(r, tomoyo_check_mount_acl); | 160 | tomoyo_check_acl(r, tomoyo_check_mount_acl); |
158 | error = tomoyo_audit_mount_log(r); | 161 | error = tomoyo_audit_mount_log(r); |
159 | } while (error == TOMOYO_RETRY_REQUEST); | 162 | } while (error == TOMOYO_RETRY_REQUEST); |
160 | out: | 163 | out: |
161 | kfree(requested_dev_name); | 164 | kfree(requested_dev_name); |
162 | kfree(requested_dir_name); | 165 | kfree(requested_dir_name); |
163 | if (fstype) | 166 | if (fstype) |
164 | put_filesystem(fstype); | 167 | put_filesystem(fstype); |
165 | kfree(requested_type); | 168 | kfree(requested_type); |
169 | /* Drop refcount obtained by kern_path(). */ | ||
170 | if (obj.path1.dentry) | ||
171 | path_put(&obj.path1); | ||
166 | return error; | 172 | return error; |
167 | } | 173 | } |
168 | 174 | ||
169 | /** | 175 | /** |
170 | * tomoyo_mount_permission - Check permission for mount() operation. | 176 | * tomoyo_mount_permission - Check permission for mount() operation. |
171 | * | 177 | * |
172 | * @dev_name: Name of device file. | 178 | * @dev_name: Name of device file. |
173 | * @path: Pointer to "struct path". | 179 | * @path: Pointer to "struct path". |
174 | * @type: Name of filesystem type. May be NULL. | 180 | * @type: Name of filesystem type. May be NULL. |
175 | * @flags: Mount options. | 181 | * @flags: Mount options. |
176 | * @data_page: Optional data. May be NULL. | 182 | * @data_page: Optional data. May be NULL. |
177 | * | 183 | * |
178 | * Returns 0 on success, negative value otherwise. | 184 | * Returns 0 on success, negative value otherwise. |
179 | */ | 185 | */ |
180 | int tomoyo_mount_permission(char *dev_name, struct path *path, | 186 | int tomoyo_mount_permission(char *dev_name, struct path *path, |
181 | const char *type, unsigned long flags, | 187 | const char *type, unsigned long flags, |
182 | void *data_page) | 188 | void *data_page) |
183 | { | 189 | { |
184 | struct tomoyo_request_info r; | 190 | struct tomoyo_request_info r; |
185 | int error; | 191 | int error; |
186 | int idx; | 192 | int idx; |
187 | 193 | ||
188 | if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_MOUNT) | 194 | if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_MOUNT) |
189 | == TOMOYO_CONFIG_DISABLED) | 195 | == TOMOYO_CONFIG_DISABLED) |
190 | return 0; | 196 | return 0; |
191 | if ((flags & MS_MGC_MSK) == MS_MGC_VAL) | 197 | if ((flags & MS_MGC_MSK) == MS_MGC_VAL) |
192 | flags &= ~MS_MGC_MSK; | 198 | flags &= ~MS_MGC_MSK; |
193 | if (flags & MS_REMOUNT) { | 199 | if (flags & MS_REMOUNT) { |
194 | type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]; | 200 | type = tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]; |
195 | flags &= ~MS_REMOUNT; | 201 | flags &= ~MS_REMOUNT; |
196 | } | 202 | } |
197 | if (flags & MS_MOVE) { | 203 | if (flags & MS_MOVE) { |
198 | type = tomoyo_mounts[TOMOYO_MOUNT_MOVE]; | 204 | type = tomoyo_mounts[TOMOYO_MOUNT_MOVE]; |
199 | flags &= ~MS_MOVE; | 205 | flags &= ~MS_MOVE; |
200 | } | 206 | } |
201 | if (flags & MS_BIND) { | 207 | if (flags & MS_BIND) { |
202 | type = tomoyo_mounts[TOMOYO_MOUNT_BIND]; | 208 | type = tomoyo_mounts[TOMOYO_MOUNT_BIND]; |
203 | flags &= ~MS_BIND; | 209 | flags &= ~MS_BIND; |
204 | } | 210 | } |
205 | if (flags & MS_UNBINDABLE) { | 211 | if (flags & MS_UNBINDABLE) { |
206 | type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE]; | 212 | type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE]; |
207 | flags &= ~MS_UNBINDABLE; | 213 | flags &= ~MS_UNBINDABLE; |
208 | } | 214 | } |
209 | if (flags & MS_PRIVATE) { | 215 | if (flags & MS_PRIVATE) { |
210 | type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE]; | 216 | type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE]; |
211 | flags &= ~MS_PRIVATE; | 217 | flags &= ~MS_PRIVATE; |
212 | } | 218 | } |
213 | if (flags & MS_SLAVE) { | 219 | if (flags & MS_SLAVE) { |
214 | type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE]; | 220 | type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE]; |
215 | flags &= ~MS_SLAVE; | 221 | flags &= ~MS_SLAVE; |
216 | } | 222 | } |
217 | if (flags & MS_SHARED) { | 223 | if (flags & MS_SHARED) { |
218 | type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]; | 224 | type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]; |
219 | flags &= ~MS_SHARED; | 225 | flags &= ~MS_SHARED; |
220 | } | 226 | } |
221 | if (!type) | 227 | if (!type) |
222 | type = "<NULL>"; | 228 | type = "<NULL>"; |
223 | idx = tomoyo_read_lock(); | 229 | idx = tomoyo_read_lock(); |
224 | error = tomoyo_mount_acl(&r, dev_name, path, type, flags); | 230 | error = tomoyo_mount_acl(&r, dev_name, path, type, flags); |
225 | tomoyo_read_unlock(idx); | 231 | tomoyo_read_unlock(idx); |
226 | return error; | 232 | return error; |
227 | } | 233 | } |
security/tomoyo/tomoyo.c
1 | /* | 1 | /* |
2 | * security/tomoyo/tomoyo.c | 2 | * security/tomoyo/tomoyo.c |
3 | * | 3 | * |
4 | * LSM hooks for TOMOYO Linux. | 4 | * LSM hooks for TOMOYO Linux. |
5 | * | 5 | * |
6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION | 6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/security.h> | 9 | #include <linux/security.h> |
10 | #include "common.h" | 10 | #include "common.h" |
11 | 11 | ||
12 | static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) | 12 | static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) |
13 | { | 13 | { |
14 | new->security = NULL; | 14 | new->security = NULL; |
15 | return 0; | 15 | return 0; |
16 | } | 16 | } |
17 | 17 | ||
18 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, | 18 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, |
19 | gfp_t gfp) | 19 | gfp_t gfp) |
20 | { | 20 | { |
21 | struct tomoyo_domain_info *domain = old->security; | 21 | struct tomoyo_domain_info *domain = old->security; |
22 | new->security = domain; | 22 | new->security = domain; |
23 | if (domain) | 23 | if (domain) |
24 | atomic_inc(&domain->users); | 24 | atomic_inc(&domain->users); |
25 | return 0; | 25 | return 0; |
26 | } | 26 | } |
27 | 27 | ||
28 | static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) | 28 | static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) |
29 | { | 29 | { |
30 | tomoyo_cred_prepare(new, old, 0); | 30 | tomoyo_cred_prepare(new, old, 0); |
31 | } | 31 | } |
32 | 32 | ||
33 | static void tomoyo_cred_free(struct cred *cred) | 33 | static void tomoyo_cred_free(struct cred *cred) |
34 | { | 34 | { |
35 | struct tomoyo_domain_info *domain = cred->security; | 35 | struct tomoyo_domain_info *domain = cred->security; |
36 | if (domain) | 36 | if (domain) |
37 | atomic_dec(&domain->users); | 37 | atomic_dec(&domain->users); |
38 | } | 38 | } |
39 | 39 | ||
40 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | 40 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) |
41 | { | 41 | { |
42 | int rc; | 42 | int rc; |
43 | 43 | ||
44 | rc = cap_bprm_set_creds(bprm); | 44 | rc = cap_bprm_set_creds(bprm); |
45 | if (rc) | 45 | if (rc) |
46 | return rc; | 46 | return rc; |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * Do only if this function is called for the first time of an execve | 49 | * Do only if this function is called for the first time of an execve |
50 | * operation. | 50 | * operation. |
51 | */ | 51 | */ |
52 | if (bprm->cred_prepared) | 52 | if (bprm->cred_prepared) |
53 | return 0; | 53 | return 0; |
54 | #ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER | 54 | #ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER |
55 | /* | 55 | /* |
56 | * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested | 56 | * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested |
57 | * for the first time. | 57 | * for the first time. |
58 | */ | 58 | */ |
59 | if (!tomoyo_policy_loaded) | 59 | if (!tomoyo_policy_loaded) |
60 | tomoyo_load_policy(bprm->filename); | 60 | tomoyo_load_policy(bprm->filename); |
61 | #endif | 61 | #endif |
62 | /* | 62 | /* |
63 | * Release reference to "struct tomoyo_domain_info" stored inside | 63 | * Release reference to "struct tomoyo_domain_info" stored inside |
64 | * "bprm->cred->security". New reference to "struct tomoyo_domain_info" | 64 | * "bprm->cred->security". New reference to "struct tomoyo_domain_info" |
65 | * stored inside "bprm->cred->security" will be acquired later inside | 65 | * stored inside "bprm->cred->security" will be acquired later inside |
66 | * tomoyo_find_next_domain(). | 66 | * tomoyo_find_next_domain(). |
67 | */ | 67 | */ |
68 | atomic_dec(&((struct tomoyo_domain_info *) | 68 | atomic_dec(&((struct tomoyo_domain_info *) |
69 | bprm->cred->security)->users); | 69 | bprm->cred->security)->users); |
70 | /* | 70 | /* |
71 | * Tell tomoyo_bprm_check_security() is called for the first time of an | 71 | * Tell tomoyo_bprm_check_security() is called for the first time of an |
72 | * execve operation. | 72 | * execve operation. |
73 | */ | 73 | */ |
74 | bprm->cred->security = NULL; | 74 | bprm->cred->security = NULL; |
75 | return 0; | 75 | return 0; |
76 | } | 76 | } |
77 | 77 | ||
78 | static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | 78 | static int tomoyo_bprm_check_security(struct linux_binprm *bprm) |
79 | { | 79 | { |
80 | struct tomoyo_domain_info *domain = bprm->cred->security; | 80 | struct tomoyo_domain_info *domain = bprm->cred->security; |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * Execute permission is checked against pathname passed to do_execve() | 83 | * Execute permission is checked against pathname passed to do_execve() |
84 | * using current domain. | 84 | * using current domain. |
85 | */ | 85 | */ |
86 | if (!domain) { | 86 | if (!domain) { |
87 | const int idx = tomoyo_read_lock(); | 87 | const int idx = tomoyo_read_lock(); |
88 | const int err = tomoyo_find_next_domain(bprm); | 88 | const int err = tomoyo_find_next_domain(bprm); |
89 | tomoyo_read_unlock(idx); | 89 | tomoyo_read_unlock(idx); |
90 | return err; | 90 | return err; |
91 | } | 91 | } |
92 | /* | 92 | /* |
93 | * Read permission is checked against interpreters using next domain. | 93 | * Read permission is checked against interpreters using next domain. |
94 | */ | 94 | */ |
95 | return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); | 95 | return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); |
96 | } | 96 | } |
97 | 97 | ||
98 | static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 98 | static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
99 | { | 99 | { |
100 | struct path path = { mnt, dentry }; | 100 | struct path path = { mnt, dentry }; |
101 | return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path); | 101 | return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL); |
102 | } | 102 | } |
103 | 103 | ||
104 | static int tomoyo_path_truncate(struct path *path) | 104 | static int tomoyo_path_truncate(struct path *path) |
105 | { | 105 | { |
106 | return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); | 106 | return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL); |
107 | } | 107 | } |
108 | 108 | ||
109 | static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) | 109 | static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) |
110 | { | 110 | { |
111 | struct path path = { parent->mnt, dentry }; | 111 | struct path path = { parent->mnt, dentry }; |
112 | return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path); | 112 | return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); |
113 | } | 113 | } |
114 | 114 | ||
115 | static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, | 115 | static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, |
116 | int mode) | 116 | int mode) |
117 | { | 117 | { |
118 | struct path path = { parent->mnt, dentry }; | 118 | struct path path = { parent->mnt, dentry }; |
119 | return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, | 119 | return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, |
120 | mode & S_IALLUGO); | 120 | mode & S_IALLUGO); |
121 | } | 121 | } |
122 | 122 | ||
123 | static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) | 123 | static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) |
124 | { | 124 | { |
125 | struct path path = { parent->mnt, dentry }; | 125 | struct path path = { parent->mnt, dentry }; |
126 | return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path); | 126 | return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); |
127 | } | 127 | } |
128 | 128 | ||
129 | static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, | 129 | static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, |
130 | const char *old_name) | 130 | const char *old_name) |
131 | { | 131 | { |
132 | struct path path = { parent->mnt, dentry }; | 132 | struct path path = { parent->mnt, dentry }; |
133 | return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path); | 133 | return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); |
134 | } | 134 | } |
135 | 135 | ||
136 | static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, | 136 | static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, |
137 | int mode, unsigned int dev) | 137 | int mode, unsigned int dev) |
138 | { | 138 | { |
139 | struct path path = { parent->mnt, dentry }; | 139 | struct path path = { parent->mnt, dentry }; |
140 | int type = TOMOYO_TYPE_CREATE; | 140 | int type = TOMOYO_TYPE_CREATE; |
141 | const unsigned int perm = mode & S_IALLUGO; | 141 | const unsigned int perm = mode & S_IALLUGO; |
142 | 142 | ||
143 | switch (mode & S_IFMT) { | 143 | switch (mode & S_IFMT) { |
144 | case S_IFCHR: | 144 | case S_IFCHR: |
145 | type = TOMOYO_TYPE_MKCHAR; | 145 | type = TOMOYO_TYPE_MKCHAR; |
146 | break; | 146 | break; |
147 | case S_IFBLK: | 147 | case S_IFBLK: |
148 | type = TOMOYO_TYPE_MKBLOCK; | 148 | type = TOMOYO_TYPE_MKBLOCK; |
149 | break; | 149 | break; |
150 | default: | 150 | default: |
151 | goto no_dev; | 151 | goto no_dev; |
152 | } | 152 | } |
153 | return tomoyo_mkdev_perm(type, &path, perm, dev); | 153 | return tomoyo_mkdev_perm(type, &path, perm, dev); |
154 | no_dev: | 154 | no_dev: |
155 | switch (mode & S_IFMT) { | 155 | switch (mode & S_IFMT) { |
156 | case S_IFIFO: | 156 | case S_IFIFO: |
157 | type = TOMOYO_TYPE_MKFIFO; | 157 | type = TOMOYO_TYPE_MKFIFO; |
158 | break; | 158 | break; |
159 | case S_IFSOCK: | 159 | case S_IFSOCK: |
160 | type = TOMOYO_TYPE_MKSOCK; | 160 | type = TOMOYO_TYPE_MKSOCK; |
161 | break; | 161 | break; |
162 | } | 162 | } |
163 | return tomoyo_path_number_perm(type, &path, perm); | 163 | return tomoyo_path_number_perm(type, &path, perm); |
164 | } | 164 | } |
165 | 165 | ||
166 | static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, | 166 | static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, |
167 | struct dentry *new_dentry) | 167 | struct dentry *new_dentry) |
168 | { | 168 | { |
169 | struct path path1 = { new_dir->mnt, old_dentry }; | 169 | struct path path1 = { new_dir->mnt, old_dentry }; |
170 | struct path path2 = { new_dir->mnt, new_dentry }; | 170 | struct path path2 = { new_dir->mnt, new_dentry }; |
171 | return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); | 171 | return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); |
172 | } | 172 | } |
173 | 173 | ||
174 | static int tomoyo_path_rename(struct path *old_parent, | 174 | static int tomoyo_path_rename(struct path *old_parent, |
175 | struct dentry *old_dentry, | 175 | struct dentry *old_dentry, |
176 | struct path *new_parent, | 176 | struct path *new_parent, |
177 | struct dentry *new_dentry) | 177 | struct dentry *new_dentry) |
178 | { | 178 | { |
179 | struct path path1 = { old_parent->mnt, old_dentry }; | 179 | struct path path1 = { old_parent->mnt, old_dentry }; |
180 | struct path path2 = { new_parent->mnt, new_dentry }; | 180 | struct path path2 = { new_parent->mnt, new_dentry }; |
181 | return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); | 181 | return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); |
182 | } | 182 | } |
183 | 183 | ||
184 | static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, | 184 | static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, |
185 | unsigned long arg) | 185 | unsigned long arg) |
186 | { | 186 | { |
187 | if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))) | 187 | if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))) |
188 | return 0; | 188 | return 0; |
189 | return tomoyo_check_open_permission(tomoyo_domain(), &file->f_path, | 189 | return tomoyo_check_open_permission(tomoyo_domain(), &file->f_path, |
190 | O_WRONLY | (arg & O_APPEND)); | 190 | O_WRONLY | (arg & O_APPEND)); |
191 | } | 191 | } |
192 | 192 | ||
193 | static int tomoyo_dentry_open(struct file *f, const struct cred *cred) | 193 | static int tomoyo_dentry_open(struct file *f, const struct cred *cred) |
194 | { | 194 | { |
195 | int flags = f->f_flags; | 195 | int flags = f->f_flags; |
196 | /* Don't check read permission here if called from do_execve(). */ | 196 | /* Don't check read permission here if called from do_execve(). */ |
197 | if (current->in_execve) | 197 | if (current->in_execve) |
198 | return 0; | 198 | return 0; |
199 | return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); | 199 | return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); |
200 | } | 200 | } |
201 | 201 | ||
202 | static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, | 202 | static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, |
203 | unsigned long arg) | 203 | unsigned long arg) |
204 | { | 204 | { |
205 | return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd); | 205 | return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd); |
206 | } | 206 | } |
207 | 207 | ||
208 | static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, | 208 | static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, |
209 | mode_t mode) | 209 | mode_t mode) |
210 | { | 210 | { |
211 | struct path path = { mnt, dentry }; | 211 | struct path path = { mnt, dentry }; |
212 | return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, &path, | 212 | return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, &path, |
213 | mode & S_IALLUGO); | 213 | mode & S_IALLUGO); |
214 | } | 214 | } |
215 | 215 | ||
216 | static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) | 216 | static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) |
217 | { | 217 | { |
218 | int error = 0; | 218 | int error = 0; |
219 | if (uid != (uid_t) -1) | 219 | if (uid != (uid_t) -1) |
220 | error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, uid); | 220 | error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, uid); |
221 | if (!error && gid != (gid_t) -1) | 221 | if (!error && gid != (gid_t) -1) |
222 | error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, gid); | 222 | error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, gid); |
223 | return error; | 223 | return error; |
224 | } | 224 | } |
225 | 225 | ||
226 | static int tomoyo_path_chroot(struct path *path) | 226 | static int tomoyo_path_chroot(struct path *path) |
227 | { | 227 | { |
228 | return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path); | 228 | return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL); |
229 | } | 229 | } |
230 | 230 | ||
231 | static int tomoyo_sb_mount(char *dev_name, struct path *path, | 231 | static int tomoyo_sb_mount(char *dev_name, struct path *path, |
232 | char *type, unsigned long flags, void *data) | 232 | char *type, unsigned long flags, void *data) |
233 | { | 233 | { |
234 | return tomoyo_mount_permission(dev_name, path, type, flags, data); | 234 | return tomoyo_mount_permission(dev_name, path, type, flags, data); |
235 | } | 235 | } |
236 | 236 | ||
237 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) | 237 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) |
238 | { | 238 | { |
239 | struct path path = { mnt, mnt->mnt_root }; | 239 | struct path path = { mnt, mnt->mnt_root }; |
240 | return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path); | 240 | return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); |
241 | } | 241 | } |
242 | 242 | ||
243 | static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) | 243 | static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) |
244 | { | 244 | { |
245 | return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); | 245 | return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); |
246 | } | 246 | } |
247 | 247 | ||
248 | /* | 248 | /* |
249 | * tomoyo_security_ops is a "struct security_operations" which is used for | 249 | * tomoyo_security_ops is a "struct security_operations" which is used for |
250 | * registering TOMOYO. | 250 | * registering TOMOYO. |
251 | */ | 251 | */ |
252 | static struct security_operations tomoyo_security_ops = { | 252 | static struct security_operations tomoyo_security_ops = { |
253 | .name = "tomoyo", | 253 | .name = "tomoyo", |
254 | .cred_alloc_blank = tomoyo_cred_alloc_blank, | 254 | .cred_alloc_blank = tomoyo_cred_alloc_blank, |
255 | .cred_prepare = tomoyo_cred_prepare, | 255 | .cred_prepare = tomoyo_cred_prepare, |
256 | .cred_transfer = tomoyo_cred_transfer, | 256 | .cred_transfer = tomoyo_cred_transfer, |
257 | .cred_free = tomoyo_cred_free, | 257 | .cred_free = tomoyo_cred_free, |
258 | .bprm_set_creds = tomoyo_bprm_set_creds, | 258 | .bprm_set_creds = tomoyo_bprm_set_creds, |
259 | .bprm_check_security = tomoyo_bprm_check_security, | 259 | .bprm_check_security = tomoyo_bprm_check_security, |
260 | .file_fcntl = tomoyo_file_fcntl, | 260 | .file_fcntl = tomoyo_file_fcntl, |
261 | .dentry_open = tomoyo_dentry_open, | 261 | .dentry_open = tomoyo_dentry_open, |
262 | .path_truncate = tomoyo_path_truncate, | 262 | .path_truncate = tomoyo_path_truncate, |
263 | .path_unlink = tomoyo_path_unlink, | 263 | .path_unlink = tomoyo_path_unlink, |
264 | .path_mkdir = tomoyo_path_mkdir, | 264 | .path_mkdir = tomoyo_path_mkdir, |
265 | .path_rmdir = tomoyo_path_rmdir, | 265 | .path_rmdir = tomoyo_path_rmdir, |
266 | .path_symlink = tomoyo_path_symlink, | 266 | .path_symlink = tomoyo_path_symlink, |
267 | .path_mknod = tomoyo_path_mknod, | 267 | .path_mknod = tomoyo_path_mknod, |
268 | .path_link = tomoyo_path_link, | 268 | .path_link = tomoyo_path_link, |
269 | .path_rename = tomoyo_path_rename, | 269 | .path_rename = tomoyo_path_rename, |
270 | .inode_getattr = tomoyo_inode_getattr, | 270 | .inode_getattr = tomoyo_inode_getattr, |
271 | .file_ioctl = tomoyo_file_ioctl, | 271 | .file_ioctl = tomoyo_file_ioctl, |
272 | .path_chmod = tomoyo_path_chmod, | 272 | .path_chmod = tomoyo_path_chmod, |
273 | .path_chown = tomoyo_path_chown, | 273 | .path_chown = tomoyo_path_chown, |
274 | .path_chroot = tomoyo_path_chroot, | 274 | .path_chroot = tomoyo_path_chroot, |
275 | .sb_mount = tomoyo_sb_mount, | 275 | .sb_mount = tomoyo_sb_mount, |
276 | .sb_umount = tomoyo_sb_umount, | 276 | .sb_umount = tomoyo_sb_umount, |
277 | .sb_pivotroot = tomoyo_sb_pivotroot, | 277 | .sb_pivotroot = tomoyo_sb_pivotroot, |
278 | }; | 278 | }; |
279 | 279 | ||
280 | /* Lock for GC. */ | 280 | /* Lock for GC. */ |
281 | struct srcu_struct tomoyo_ss; | 281 | struct srcu_struct tomoyo_ss; |
282 | 282 | ||
283 | static int __init tomoyo_init(void) | 283 | static int __init tomoyo_init(void) |
284 | { | 284 | { |
285 | struct cred *cred = (struct cred *) current_cred(); | 285 | struct cred *cred = (struct cred *) current_cred(); |
286 | 286 | ||
287 | if (!security_module_enable(&tomoyo_security_ops)) | 287 | if (!security_module_enable(&tomoyo_security_ops)) |
288 | return 0; | 288 | return 0; |
289 | /* register ourselves with the security framework */ | 289 | /* register ourselves with the security framework */ |
290 | if (register_security(&tomoyo_security_ops) || | 290 | if (register_security(&tomoyo_security_ops) || |
291 | init_srcu_struct(&tomoyo_ss)) | 291 | init_srcu_struct(&tomoyo_ss)) |
292 | panic("Failure registering TOMOYO Linux"); | 292 | panic("Failure registering TOMOYO Linux"); |
293 | printk(KERN_INFO "TOMOYO Linux initialized\n"); | 293 | printk(KERN_INFO "TOMOYO Linux initialized\n"); |
294 | cred->security = &tomoyo_kernel_domain; | 294 | cred->security = &tomoyo_kernel_domain; |
295 | tomoyo_mm_init(); | 295 | tomoyo_mm_init(); |
296 | return 0; | 296 | return 0; |
297 | } | 297 | } |
298 | 298 | ||
299 | security_initcall(tomoyo_init); | 299 | security_initcall(tomoyo_init); |
300 | 300 |