diff options
Diffstat (limited to 'security/tomoyo/common.h')
-rw-r--r-- | security/tomoyo/common.h | 1197 |
1 files changed, 673 insertions, 524 deletions
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 7c66bd898782..f7fbaa66e443 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -21,7 +21,8 @@ | |||
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 | struct linux_binprm; | 24 | #include <linux/binfmts.h> |
25 | #include <linux/highmem.h> | ||
25 | 26 | ||
26 | /********** Constants definitions. **********/ | 27 | /********** Constants definitions. **********/ |
27 | 28 | ||
@@ -38,66 +39,149 @@ struct linux_binprm; | |||
38 | /* Profile number is an integer between 0 and 255. */ | 39 | /* Profile number is an integer between 0 and 255. */ |
39 | #define TOMOYO_MAX_PROFILES 256 | 40 | #define TOMOYO_MAX_PROFILES 256 |
40 | 41 | ||
42 | /* Group number is an integer between 0 and 255. */ | ||
43 | #define TOMOYO_MAX_ACL_GROUPS 256 | ||
44 | |||
45 | /* Index numbers for "struct tomoyo_condition". */ | ||
46 | enum tomoyo_conditions_index { | ||
47 | TOMOYO_TASK_UID, /* current_uid() */ | ||
48 | TOMOYO_TASK_EUID, /* current_euid() */ | ||
49 | TOMOYO_TASK_SUID, /* current_suid() */ | ||
50 | TOMOYO_TASK_FSUID, /* current_fsuid() */ | ||
51 | TOMOYO_TASK_GID, /* current_gid() */ | ||
52 | TOMOYO_TASK_EGID, /* current_egid() */ | ||
53 | TOMOYO_TASK_SGID, /* current_sgid() */ | ||
54 | TOMOYO_TASK_FSGID, /* current_fsgid() */ | ||
55 | TOMOYO_TASK_PID, /* sys_getpid() */ | ||
56 | TOMOYO_TASK_PPID, /* sys_getppid() */ | ||
57 | TOMOYO_EXEC_ARGC, /* "struct linux_binprm *"->argc */ | ||
58 | TOMOYO_EXEC_ENVC, /* "struct linux_binprm *"->envc */ | ||
59 | TOMOYO_TYPE_IS_SOCKET, /* S_IFSOCK */ | ||
60 | TOMOYO_TYPE_IS_SYMLINK, /* S_IFLNK */ | ||
61 | TOMOYO_TYPE_IS_FILE, /* S_IFREG */ | ||
62 | TOMOYO_TYPE_IS_BLOCK_DEV, /* S_IFBLK */ | ||
63 | TOMOYO_TYPE_IS_DIRECTORY, /* S_IFDIR */ | ||
64 | TOMOYO_TYPE_IS_CHAR_DEV, /* S_IFCHR */ | ||
65 | TOMOYO_TYPE_IS_FIFO, /* S_IFIFO */ | ||
66 | TOMOYO_MODE_SETUID, /* S_ISUID */ | ||
67 | TOMOYO_MODE_SETGID, /* S_ISGID */ | ||
68 | TOMOYO_MODE_STICKY, /* S_ISVTX */ | ||
69 | TOMOYO_MODE_OWNER_READ, /* S_IRUSR */ | ||
70 | TOMOYO_MODE_OWNER_WRITE, /* S_IWUSR */ | ||
71 | TOMOYO_MODE_OWNER_EXECUTE, /* S_IXUSR */ | ||
72 | TOMOYO_MODE_GROUP_READ, /* S_IRGRP */ | ||
73 | TOMOYO_MODE_GROUP_WRITE, /* S_IWGRP */ | ||
74 | TOMOYO_MODE_GROUP_EXECUTE, /* S_IXGRP */ | ||
75 | TOMOYO_MODE_OTHERS_READ, /* S_IROTH */ | ||
76 | TOMOYO_MODE_OTHERS_WRITE, /* S_IWOTH */ | ||
77 | TOMOYO_MODE_OTHERS_EXECUTE, /* S_IXOTH */ | ||
78 | TOMOYO_EXEC_REALPATH, | ||
79 | TOMOYO_SYMLINK_TARGET, | ||
80 | TOMOYO_PATH1_UID, | ||
81 | TOMOYO_PATH1_GID, | ||
82 | TOMOYO_PATH1_INO, | ||
83 | TOMOYO_PATH1_MAJOR, | ||
84 | TOMOYO_PATH1_MINOR, | ||
85 | TOMOYO_PATH1_PERM, | ||
86 | TOMOYO_PATH1_TYPE, | ||
87 | TOMOYO_PATH1_DEV_MAJOR, | ||
88 | TOMOYO_PATH1_DEV_MINOR, | ||
89 | TOMOYO_PATH2_UID, | ||
90 | TOMOYO_PATH2_GID, | ||
91 | TOMOYO_PATH2_INO, | ||
92 | TOMOYO_PATH2_MAJOR, | ||
93 | TOMOYO_PATH2_MINOR, | ||
94 | TOMOYO_PATH2_PERM, | ||
95 | TOMOYO_PATH2_TYPE, | ||
96 | TOMOYO_PATH2_DEV_MAJOR, | ||
97 | TOMOYO_PATH2_DEV_MINOR, | ||
98 | TOMOYO_PATH1_PARENT_UID, | ||
99 | TOMOYO_PATH1_PARENT_GID, | ||
100 | TOMOYO_PATH1_PARENT_INO, | ||
101 | TOMOYO_PATH1_PARENT_PERM, | ||
102 | TOMOYO_PATH2_PARENT_UID, | ||
103 | TOMOYO_PATH2_PARENT_GID, | ||
104 | TOMOYO_PATH2_PARENT_INO, | ||
105 | TOMOYO_PATH2_PARENT_PERM, | ||
106 | TOMOYO_MAX_CONDITION_KEYWORD, | ||
107 | TOMOYO_NUMBER_UNION, | ||
108 | TOMOYO_NAME_UNION, | ||
109 | TOMOYO_ARGV_ENTRY, | ||
110 | TOMOYO_ENVP_ENTRY, | ||
111 | }; | ||
112 | |||
113 | |||
114 | /* Index numbers for stat(). */ | ||
115 | enum tomoyo_path_stat_index { | ||
116 | /* Do not change this order. */ | ||
117 | TOMOYO_PATH1, | ||
118 | TOMOYO_PATH1_PARENT, | ||
119 | TOMOYO_PATH2, | ||
120 | TOMOYO_PATH2_PARENT, | ||
121 | TOMOYO_MAX_PATH_STAT | ||
122 | }; | ||
123 | |||
124 | /* Index numbers for operation mode. */ | ||
41 | enum tomoyo_mode_index { | 125 | enum tomoyo_mode_index { |
42 | TOMOYO_CONFIG_DISABLED, | 126 | TOMOYO_CONFIG_DISABLED, |
43 | TOMOYO_CONFIG_LEARNING, | 127 | TOMOYO_CONFIG_LEARNING, |
44 | TOMOYO_CONFIG_PERMISSIVE, | 128 | TOMOYO_CONFIG_PERMISSIVE, |
45 | TOMOYO_CONFIG_ENFORCING, | 129 | TOMOYO_CONFIG_ENFORCING, |
46 | TOMOYO_CONFIG_USE_DEFAULT = 255 | 130 | TOMOYO_CONFIG_MAX_MODE, |
131 | TOMOYO_CONFIG_WANT_REJECT_LOG = 64, | ||
132 | TOMOYO_CONFIG_WANT_GRANT_LOG = 128, | ||
133 | TOMOYO_CONFIG_USE_DEFAULT = 255, | ||
47 | }; | 134 | }; |
48 | 135 | ||
136 | /* Index numbers for entry type. */ | ||
49 | enum tomoyo_policy_id { | 137 | enum tomoyo_policy_id { |
50 | TOMOYO_ID_GROUP, | 138 | TOMOYO_ID_GROUP, |
51 | TOMOYO_ID_PATH_GROUP, | 139 | TOMOYO_ID_PATH_GROUP, |
52 | TOMOYO_ID_NUMBER_GROUP, | 140 | TOMOYO_ID_NUMBER_GROUP, |
53 | TOMOYO_ID_TRANSITION_CONTROL, | 141 | TOMOYO_ID_TRANSITION_CONTROL, |
54 | TOMOYO_ID_AGGREGATOR, | 142 | TOMOYO_ID_AGGREGATOR, |
55 | TOMOYO_ID_GLOBALLY_READABLE, | ||
56 | TOMOYO_ID_PATTERN, | ||
57 | TOMOYO_ID_NO_REWRITE, | ||
58 | TOMOYO_ID_MANAGER, | 143 | TOMOYO_ID_MANAGER, |
144 | TOMOYO_ID_CONDITION, | ||
59 | TOMOYO_ID_NAME, | 145 | TOMOYO_ID_NAME, |
60 | TOMOYO_ID_ACL, | 146 | TOMOYO_ID_ACL, |
61 | TOMOYO_ID_DOMAIN, | 147 | TOMOYO_ID_DOMAIN, |
62 | TOMOYO_MAX_POLICY | 148 | TOMOYO_MAX_POLICY |
63 | }; | 149 | }; |
64 | 150 | ||
151 | /* Index numbers for domain's attributes. */ | ||
152 | enum tomoyo_domain_info_flags_index { | ||
153 | /* Quota warnning flag. */ | ||
154 | TOMOYO_DIF_QUOTA_WARNED, | ||
155 | /* | ||
156 | * This domain was unable to create a new domain at | ||
157 | * tomoyo_find_next_domain() because the name of the domain to be | ||
158 | * created was too long or it could not allocate memory. | ||
159 | * More than one process continued execve() without domain transition. | ||
160 | */ | ||
161 | TOMOYO_DIF_TRANSITION_FAILED, | ||
162 | TOMOYO_MAX_DOMAIN_INFO_FLAGS | ||
163 | }; | ||
164 | |||
165 | /* Index numbers for group entries. */ | ||
65 | enum tomoyo_group_id { | 166 | enum tomoyo_group_id { |
66 | TOMOYO_PATH_GROUP, | 167 | TOMOYO_PATH_GROUP, |
67 | TOMOYO_NUMBER_GROUP, | 168 | TOMOYO_NUMBER_GROUP, |
68 | TOMOYO_MAX_GROUP | 169 | TOMOYO_MAX_GROUP |
69 | }; | 170 | }; |
70 | 171 | ||
71 | /* Keywords for ACLs. */ | 172 | /* Index numbers for type of numeric values. */ |
72 | #define TOMOYO_KEYWORD_AGGREGATOR "aggregator " | 173 | enum tomoyo_value_type { |
73 | #define TOMOYO_KEYWORD_ALLOW_MOUNT "allow_mount " | 174 | TOMOYO_VALUE_TYPE_INVALID, |
74 | #define TOMOYO_KEYWORD_ALLOW_READ "allow_read " | 175 | TOMOYO_VALUE_TYPE_DECIMAL, |
75 | #define TOMOYO_KEYWORD_DELETE "delete " | 176 | TOMOYO_VALUE_TYPE_OCTAL, |
76 | #define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite " | 177 | TOMOYO_VALUE_TYPE_HEXADECIMAL, |
77 | #define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern " | 178 | }; |
78 | #define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain " | ||
79 | #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " | ||
80 | #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " | ||
81 | #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " | ||
82 | #define TOMOYO_KEYWORD_PATH_GROUP "path_group " | ||
83 | #define TOMOYO_KEYWORD_NUMBER_GROUP "number_group " | ||
84 | #define TOMOYO_KEYWORD_SELECT "select " | ||
85 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " | ||
86 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" | ||
87 | #define TOMOYO_KEYWORD_QUOTA_EXCEEDED "quota_exceeded" | ||
88 | #define TOMOYO_KEYWORD_TRANSITION_FAILED "transition_failed" | ||
89 | /* A domain definition starts with <kernel>. */ | ||
90 | #define TOMOYO_ROOT_NAME "<kernel>" | ||
91 | #define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) | ||
92 | |||
93 | /* Value type definition. */ | ||
94 | #define TOMOYO_VALUE_TYPE_INVALID 0 | ||
95 | #define TOMOYO_VALUE_TYPE_DECIMAL 1 | ||
96 | #define TOMOYO_VALUE_TYPE_OCTAL 2 | ||
97 | #define TOMOYO_VALUE_TYPE_HEXADECIMAL 3 | ||
98 | 179 | ||
180 | /* Index numbers for domain transition control keywords. */ | ||
99 | enum tomoyo_transition_type { | 181 | enum tomoyo_transition_type { |
100 | /* Do not change this order, */ | 182 | /* Do not change this order, */ |
183 | TOMOYO_TRANSITION_CONTROL_NO_RESET, | ||
184 | TOMOYO_TRANSITION_CONTROL_RESET, | ||
101 | TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE, | 185 | TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE, |
102 | TOMOYO_TRANSITION_CONTROL_INITIALIZE, | 186 | TOMOYO_TRANSITION_CONTROL_INITIALIZE, |
103 | TOMOYO_TRANSITION_CONTROL_NO_KEEP, | 187 | TOMOYO_TRANSITION_CONTROL_NO_KEEP, |
@@ -114,35 +198,29 @@ enum tomoyo_acl_entry_type_index { | |||
114 | TOMOYO_TYPE_MOUNT_ACL, | 198 | TOMOYO_TYPE_MOUNT_ACL, |
115 | }; | 199 | }; |
116 | 200 | ||
117 | /* Index numbers for File Controls. */ | 201 | /* Index numbers for access controls with one pathname. */ |
118 | |||
119 | /* | ||
120 | * TOMOYO_TYPE_READ_WRITE is special. TOMOYO_TYPE_READ_WRITE is automatically | ||
121 | * set if both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are set. | ||
122 | * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically set if | ||
123 | * TOMOYO_TYPE_READ_WRITE is set. | ||
124 | * TOMOYO_TYPE_READ_WRITE is automatically cleared if either TOMOYO_TYPE_READ | ||
125 | * or TOMOYO_TYPE_WRITE is cleared. | ||
126 | * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically cleared if | ||
127 | * TOMOYO_TYPE_READ_WRITE is cleared. | ||
128 | */ | ||
129 | |||
130 | enum tomoyo_path_acl_index { | 202 | enum tomoyo_path_acl_index { |
131 | TOMOYO_TYPE_READ_WRITE, | ||
132 | TOMOYO_TYPE_EXECUTE, | 203 | TOMOYO_TYPE_EXECUTE, |
133 | TOMOYO_TYPE_READ, | 204 | TOMOYO_TYPE_READ, |
134 | TOMOYO_TYPE_WRITE, | 205 | TOMOYO_TYPE_WRITE, |
206 | TOMOYO_TYPE_APPEND, | ||
135 | TOMOYO_TYPE_UNLINK, | 207 | TOMOYO_TYPE_UNLINK, |
208 | TOMOYO_TYPE_GETATTR, | ||
136 | TOMOYO_TYPE_RMDIR, | 209 | TOMOYO_TYPE_RMDIR, |
137 | TOMOYO_TYPE_TRUNCATE, | 210 | TOMOYO_TYPE_TRUNCATE, |
138 | TOMOYO_TYPE_SYMLINK, | 211 | TOMOYO_TYPE_SYMLINK, |
139 | TOMOYO_TYPE_REWRITE, | ||
140 | TOMOYO_TYPE_CHROOT, | 212 | TOMOYO_TYPE_CHROOT, |
141 | TOMOYO_TYPE_UMOUNT, | 213 | TOMOYO_TYPE_UMOUNT, |
142 | TOMOYO_MAX_PATH_OPERATION | 214 | TOMOYO_MAX_PATH_OPERATION |
143 | }; | 215 | }; |
144 | 216 | ||
145 | #define TOMOYO_RW_MASK ((1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE)) | 217 | /* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ |
218 | enum tomoyo_memory_stat_type { | ||
219 | TOMOYO_MEMORY_POLICY, | ||
220 | TOMOYO_MEMORY_AUDIT, | ||
221 | TOMOYO_MEMORY_QUERY, | ||
222 | TOMOYO_MAX_MEMORY_STAT | ||
223 | }; | ||
146 | 224 | ||
147 | enum tomoyo_mkdev_acl_index { | 225 | enum tomoyo_mkdev_acl_index { |
148 | TOMOYO_TYPE_MKBLOCK, | 226 | TOMOYO_TYPE_MKBLOCK, |
@@ -150,6 +228,7 @@ enum tomoyo_mkdev_acl_index { | |||
150 | TOMOYO_MAX_MKDEV_OPERATION | 228 | TOMOYO_MAX_MKDEV_OPERATION |
151 | }; | 229 | }; |
152 | 230 | ||
231 | /* Index numbers for access controls with two pathnames. */ | ||
153 | enum tomoyo_path2_acl_index { | 232 | enum tomoyo_path2_acl_index { |
154 | TOMOYO_TYPE_LINK, | 233 | TOMOYO_TYPE_LINK, |
155 | TOMOYO_TYPE_RENAME, | 234 | TOMOYO_TYPE_RENAME, |
@@ -157,6 +236,7 @@ enum tomoyo_path2_acl_index { | |||
157 | TOMOYO_MAX_PATH2_OPERATION | 236 | TOMOYO_MAX_PATH2_OPERATION |
158 | }; | 237 | }; |
159 | 238 | ||
239 | /* Index numbers for access controls with one pathname and one number. */ | ||
160 | enum tomoyo_path_number_acl_index { | 240 | enum tomoyo_path_number_acl_index { |
161 | TOMOYO_TYPE_CREATE, | 241 | TOMOYO_TYPE_CREATE, |
162 | TOMOYO_TYPE_MKDIR, | 242 | TOMOYO_TYPE_MKDIR, |
@@ -169,31 +249,45 @@ enum tomoyo_path_number_acl_index { | |||
169 | TOMOYO_MAX_PATH_NUMBER_OPERATION | 249 | TOMOYO_MAX_PATH_NUMBER_OPERATION |
170 | }; | 250 | }; |
171 | 251 | ||
252 | /* Index numbers for /sys/kernel/security/tomoyo/ interfaces. */ | ||
172 | enum tomoyo_securityfs_interface_index { | 253 | enum tomoyo_securityfs_interface_index { |
173 | TOMOYO_DOMAINPOLICY, | 254 | TOMOYO_DOMAINPOLICY, |
174 | TOMOYO_EXCEPTIONPOLICY, | 255 | TOMOYO_EXCEPTIONPOLICY, |
175 | TOMOYO_DOMAIN_STATUS, | ||
176 | TOMOYO_PROCESS_STATUS, | 256 | TOMOYO_PROCESS_STATUS, |
177 | TOMOYO_MEMINFO, | 257 | TOMOYO_STAT, |
178 | TOMOYO_SELFDOMAIN, | 258 | TOMOYO_SELFDOMAIN, |
259 | TOMOYO_AUDIT, | ||
179 | TOMOYO_VERSION, | 260 | TOMOYO_VERSION, |
180 | TOMOYO_PROFILE, | 261 | TOMOYO_PROFILE, |
181 | TOMOYO_QUERY, | 262 | TOMOYO_QUERY, |
182 | TOMOYO_MANAGER | 263 | TOMOYO_MANAGER |
183 | }; | 264 | }; |
184 | 265 | ||
266 | /* Index numbers for special mount operations. */ | ||
267 | enum tomoyo_special_mount { | ||
268 | TOMOYO_MOUNT_BIND, /* mount --bind /source /dest */ | ||
269 | TOMOYO_MOUNT_MOVE, /* mount --move /old /new */ | ||
270 | TOMOYO_MOUNT_REMOUNT, /* mount -o remount /dir */ | ||
271 | TOMOYO_MOUNT_MAKE_UNBINDABLE, /* mount --make-unbindable /dir */ | ||
272 | TOMOYO_MOUNT_MAKE_PRIVATE, /* mount --make-private /dir */ | ||
273 | TOMOYO_MOUNT_MAKE_SLAVE, /* mount --make-slave /dir */ | ||
274 | TOMOYO_MOUNT_MAKE_SHARED, /* mount --make-shared /dir */ | ||
275 | TOMOYO_MAX_SPECIAL_MOUNT | ||
276 | }; | ||
277 | |||
278 | /* Index numbers for functionality. */ | ||
185 | enum tomoyo_mac_index { | 279 | enum tomoyo_mac_index { |
186 | TOMOYO_MAC_FILE_EXECUTE, | 280 | TOMOYO_MAC_FILE_EXECUTE, |
187 | TOMOYO_MAC_FILE_OPEN, | 281 | TOMOYO_MAC_FILE_OPEN, |
188 | TOMOYO_MAC_FILE_CREATE, | 282 | TOMOYO_MAC_FILE_CREATE, |
189 | TOMOYO_MAC_FILE_UNLINK, | 283 | TOMOYO_MAC_FILE_UNLINK, |
284 | TOMOYO_MAC_FILE_GETATTR, | ||
190 | TOMOYO_MAC_FILE_MKDIR, | 285 | TOMOYO_MAC_FILE_MKDIR, |
191 | TOMOYO_MAC_FILE_RMDIR, | 286 | TOMOYO_MAC_FILE_RMDIR, |
192 | TOMOYO_MAC_FILE_MKFIFO, | 287 | TOMOYO_MAC_FILE_MKFIFO, |
193 | TOMOYO_MAC_FILE_MKSOCK, | 288 | TOMOYO_MAC_FILE_MKSOCK, |
194 | TOMOYO_MAC_FILE_TRUNCATE, | 289 | TOMOYO_MAC_FILE_TRUNCATE, |
195 | TOMOYO_MAC_FILE_SYMLINK, | 290 | TOMOYO_MAC_FILE_SYMLINK, |
196 | TOMOYO_MAC_FILE_REWRITE, | ||
197 | TOMOYO_MAC_FILE_MKBLOCK, | 291 | TOMOYO_MAC_FILE_MKBLOCK, |
198 | TOMOYO_MAC_FILE_MKCHAR, | 292 | TOMOYO_MAC_FILE_MKCHAR, |
199 | TOMOYO_MAC_FILE_LINK, | 293 | TOMOYO_MAC_FILE_LINK, |
@@ -209,38 +303,66 @@ enum tomoyo_mac_index { | |||
209 | TOMOYO_MAX_MAC_INDEX | 303 | TOMOYO_MAX_MAC_INDEX |
210 | }; | 304 | }; |
211 | 305 | ||
306 | /* Index numbers for category of functionality. */ | ||
212 | enum tomoyo_mac_category_index { | 307 | enum tomoyo_mac_category_index { |
213 | TOMOYO_MAC_CATEGORY_FILE, | 308 | TOMOYO_MAC_CATEGORY_FILE, |
214 | TOMOYO_MAX_MAC_CATEGORY_INDEX | 309 | TOMOYO_MAX_MAC_CATEGORY_INDEX |
215 | }; | 310 | }; |
216 | 311 | ||
217 | #define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */ | ||
218 | |||
219 | /********** Structure definitions. **********/ | ||
220 | |||
221 | /* | 312 | /* |
222 | * tomoyo_acl_head is a structure which is used for holding elements not in | 313 | * Retry this request. Returned by tomoyo_supervisor() if policy violation has |
223 | * domain policy. | 314 | * occurred in enforcing mode and the userspace daemon decided to retry. |
224 | * It has following fields. | ||
225 | * | 315 | * |
226 | * (1) "list" which is linked to tomoyo_policy_list[] . | 316 | * We must choose a positive value in order to distinguish "granted" (which is |
227 | * (2) "is_deleted" is a bool which is true if marked as deleted, false | 317 | * 0) and "rejected" (which is a negative value) and "retry". |
228 | * otherwise. | ||
229 | */ | 318 | */ |
319 | #define TOMOYO_RETRY_REQUEST 1 | ||
320 | |||
321 | /* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ | ||
322 | enum tomoyo_policy_stat_type { | ||
323 | /* Do not change this order. */ | ||
324 | TOMOYO_STAT_POLICY_UPDATES, | ||
325 | TOMOYO_STAT_POLICY_LEARNING, /* == TOMOYO_CONFIG_LEARNING */ | ||
326 | TOMOYO_STAT_POLICY_PERMISSIVE, /* == TOMOYO_CONFIG_PERMISSIVE */ | ||
327 | TOMOYO_STAT_POLICY_ENFORCING, /* == TOMOYO_CONFIG_ENFORCING */ | ||
328 | TOMOYO_MAX_POLICY_STAT | ||
329 | }; | ||
330 | |||
331 | /* Index numbers for profile's PREFERENCE values. */ | ||
332 | enum tomoyo_pref_index { | ||
333 | TOMOYO_PREF_MAX_AUDIT_LOG, | ||
334 | TOMOYO_PREF_MAX_LEARNING_ENTRY, | ||
335 | TOMOYO_MAX_PREF | ||
336 | }; | ||
337 | |||
338 | /********** Structure definitions. **********/ | ||
339 | |||
340 | /* Common header for holding ACL entries. */ | ||
230 | struct tomoyo_acl_head { | 341 | struct tomoyo_acl_head { |
231 | struct list_head list; | 342 | struct list_head list; |
232 | bool is_deleted; | 343 | bool is_deleted; |
233 | } __packed; | 344 | } __packed; |
234 | 345 | ||
235 | /* | 346 | /* Common header for shared entries. */ |
236 | * tomoyo_request_info is a structure which is used for holding | 347 | struct tomoyo_shared_acl_head { |
237 | * | 348 | struct list_head list; |
238 | * (1) Domain information of current process. | 349 | atomic_t users; |
239 | * (2) How many retries are made for this request. | 350 | } __packed; |
240 | * (3) Profile number used for this request. | 351 | |
241 | * (4) Access control mode of the profile. | 352 | struct tomoyo_policy_namespace; |
242 | */ | 353 | |
354 | /* Structure for request info. */ | ||
243 | struct tomoyo_request_info { | 355 | struct tomoyo_request_info { |
356 | /* | ||
357 | * For holding parameters specific to operations which deal files. | ||
358 | * NULL if not dealing files. | ||
359 | */ | ||
360 | struct tomoyo_obj_info *obj; | ||
361 | /* | ||
362 | * For holding parameters specific to execve() request. | ||
363 | * NULL if not dealing do_execve(). | ||
364 | */ | ||
365 | struct tomoyo_execve *ee; | ||
244 | struct tomoyo_domain_info *domain; | 366 | struct tomoyo_domain_info *domain; |
245 | /* For holding parameters. */ | 367 | /* For holding parameters. */ |
246 | union { | 368 | union { |
@@ -248,11 +370,13 @@ struct tomoyo_request_info { | |||
248 | const struct tomoyo_path_info *filename; | 370 | const struct tomoyo_path_info *filename; |
249 | /* For using wildcards at tomoyo_find_next_domain(). */ | 371 | /* For using wildcards at tomoyo_find_next_domain(). */ |
250 | 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". */ | ||
251 | u8 operation; | 374 | u8 operation; |
252 | } path; | 375 | } path; |
253 | struct { | 376 | struct { |
254 | const struct tomoyo_path_info *filename1; | 377 | const struct tomoyo_path_info *filename1; |
255 | const struct tomoyo_path_info *filename2; | 378 | const struct tomoyo_path_info *filename2; |
379 | /* One of values in "enum tomoyo_path2_acl_index". */ | ||
256 | u8 operation; | 380 | u8 operation; |
257 | } path2; | 381 | } path2; |
258 | struct { | 382 | struct { |
@@ -260,11 +384,16 @@ struct tomoyo_request_info { | |||
260 | unsigned int mode; | 384 | unsigned int mode; |
261 | unsigned int major; | 385 | unsigned int major; |
262 | unsigned int minor; | 386 | unsigned int minor; |
387 | /* One of values in "enum tomoyo_mkdev_acl_index". */ | ||
263 | u8 operation; | 388 | u8 operation; |
264 | } mkdev; | 389 | } mkdev; |
265 | struct { | 390 | struct { |
266 | const struct tomoyo_path_info *filename; | 391 | const struct tomoyo_path_info *filename; |
267 | unsigned long number; | 392 | unsigned long number; |
393 | /* | ||
394 | * One of values in | ||
395 | * "enum tomoyo_path_number_acl_index". | ||
396 | */ | ||
268 | u8 operation; | 397 | u8 operation; |
269 | } path_number; | 398 | } path_number; |
270 | struct { | 399 | struct { |
@@ -283,26 +412,7 @@ struct tomoyo_request_info { | |||
283 | u8 type; | 412 | u8 type; |
284 | }; | 413 | }; |
285 | 414 | ||
286 | /* | 415 | /* Structure for holding a token. */ |
287 | * tomoyo_path_info is a structure which is used for holding a string data | ||
288 | * used by TOMOYO. | ||
289 | * This structure has several fields for supporting pattern matching. | ||
290 | * | ||
291 | * (1) "name" is the '\0' terminated string data. | ||
292 | * (2) "hash" is full_name_hash(name, strlen(name)). | ||
293 | * This allows tomoyo_pathcmp() to compare by hash before actually compare | ||
294 | * using strcmp(). | ||
295 | * (3) "const_len" is the length of the initial segment of "name" which | ||
296 | * consists entirely of non wildcard characters. In other words, the length | ||
297 | * which we can compare two strings using strncmp(). | ||
298 | * (4) "is_dir" is a bool which is true if "name" ends with "/", | ||
299 | * false otherwise. | ||
300 | * TOMOYO distinguishes directory and non-directory. A directory ends with | ||
301 | * "/" and non-directory does not end with "/". | ||
302 | * (5) "is_patterned" is a bool which is true if "name" contains wildcard | ||
303 | * characters, false otherwise. This allows TOMOYO to use "hash" and | ||
304 | * strcmp() for string comparison if "is_patterned" is false. | ||
305 | */ | ||
306 | struct tomoyo_path_info { | 416 | struct tomoyo_path_info { |
307 | const char *name; | 417 | const char *name; |
308 | u32 hash; /* = full_name_hash(name, strlen(name)) */ | 418 | u32 hash; /* = full_name_hash(name, strlen(name)) */ |
@@ -311,36 +421,32 @@ struct tomoyo_path_info { | |||
311 | bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ | 421 | bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ |
312 | }; | 422 | }; |
313 | 423 | ||
314 | /* | 424 | /* Structure for holding string data. */ |
315 | * tomoyo_name is a structure which is used for linking | ||
316 | * "struct tomoyo_path_info" into tomoyo_name_list . | ||
317 | */ | ||
318 | struct tomoyo_name { | 425 | struct tomoyo_name { |
319 | struct list_head list; | 426 | struct tomoyo_shared_acl_head head; |
320 | atomic_t users; | ||
321 | struct tomoyo_path_info entry; | 427 | struct tomoyo_path_info entry; |
322 | }; | 428 | }; |
323 | 429 | ||
430 | /* Structure for holding a word. */ | ||
324 | struct tomoyo_name_union { | 431 | struct tomoyo_name_union { |
432 | /* Either @filename or @group is NULL. */ | ||
325 | const struct tomoyo_path_info *filename; | 433 | const struct tomoyo_path_info *filename; |
326 | struct tomoyo_group *group; | 434 | struct tomoyo_group *group; |
327 | u8 is_group; | ||
328 | }; | 435 | }; |
329 | 436 | ||
437 | /* Structure for holding a number. */ | ||
330 | struct tomoyo_number_union { | 438 | struct tomoyo_number_union { |
331 | unsigned long values[2]; | 439 | unsigned long values[2]; |
332 | struct tomoyo_group *group; | 440 | struct tomoyo_group *group; /* Maybe NULL. */ |
333 | u8 min_type; | 441 | /* One of values in "enum tomoyo_value_type". */ |
334 | u8 max_type; | 442 | u8 value_type[2]; |
335 | u8 is_group; | ||
336 | }; | 443 | }; |
337 | 444 | ||
338 | /* Structure for "path_group"/"number_group" directive. */ | 445 | /* Structure for "path_group"/"number_group" directive. */ |
339 | struct tomoyo_group { | 446 | struct tomoyo_group { |
340 | struct list_head list; | 447 | struct tomoyo_shared_acl_head head; |
341 | const struct tomoyo_path_info *group_name; | 448 | const struct tomoyo_path_info *group_name; |
342 | struct list_head member_list; | 449 | struct list_head member_list; |
343 | atomic_t users; | ||
344 | }; | 450 | }; |
345 | 451 | ||
346 | /* Structure for "path_group" directive. */ | 452 | /* Structure for "path_group" directive. */ |
@@ -355,130 +461,158 @@ struct tomoyo_number_group { | |||
355 | struct tomoyo_number_union number; | 461 | struct tomoyo_number_union number; |
356 | }; | 462 | }; |
357 | 463 | ||
358 | /* | 464 | /* Subset of "struct stat". Used by conditional ACL and audit logs. */ |
359 | * tomoyo_acl_info is a structure which is used for holding | 465 | struct tomoyo_mini_stat { |
360 | * | 466 | uid_t uid; |
361 | * (1) "list" which is linked to the ->acl_info_list of | 467 | gid_t gid; |
362 | * "struct tomoyo_domain_info" | 468 | ino_t ino; |
363 | * (2) "is_deleted" is a bool which is true if this domain is marked as | 469 | mode_t mode; |
364 | * "deleted", false otherwise. | 470 | dev_t dev; |
365 | * (3) "type" which tells type of the entry. | 471 | dev_t rdev; |
366 | * | 472 | }; |
367 | * Packing "struct tomoyo_acl_info" allows | 473 | |
368 | * "struct tomoyo_path_acl" to embed "u16" and "struct tomoyo_path2_acl" | 474 | /* Structure for dumping argv[] and envp[] of "struct linux_binprm". */ |
369 | * "struct tomoyo_path_number_acl" "struct tomoyo_mkdev_acl" to embed | 475 | struct tomoyo_page_dump { |
370 | * "u8" without enlarging their structure size. | 476 | struct page *page; /* Previously dumped page. */ |
371 | */ | 477 | char *data; /* Contents of "page". Size is PAGE_SIZE. */ |
478 | }; | ||
479 | |||
480 | /* Structure for attribute checks in addition to pathname checks. */ | ||
481 | struct tomoyo_obj_info { | ||
482 | /* | ||
483 | * True if tomoyo_get_attributes() was already called, false otherwise. | ||
484 | */ | ||
485 | bool validate_done; | ||
486 | /* True if @stat[] is valid. */ | ||
487 | bool stat_valid[TOMOYO_MAX_PATH_STAT]; | ||
488 | /* First pathname. Initialized with { NULL, NULL } if no path. */ | ||
489 | struct path path1; | ||
490 | /* Second pathname. Initialized with { NULL, NULL } if no path. */ | ||
491 | struct path path2; | ||
492 | /* | ||
493 | * Information on @path1, @path1's parent directory, @path2, @path2's | ||
494 | * parent directory. | ||
495 | */ | ||
496 | struct tomoyo_mini_stat stat[TOMOYO_MAX_PATH_STAT]; | ||
497 | /* | ||
498 | * Content of symbolic link to be created. NULL for operations other | ||
499 | * than symlink(). | ||
500 | */ | ||
501 | struct tomoyo_path_info *symlink_target; | ||
502 | }; | ||
503 | |||
504 | /* Structure for argv[]. */ | ||
505 | struct tomoyo_argv { | ||
506 | unsigned long index; | ||
507 | const struct tomoyo_path_info *value; | ||
508 | bool is_not; | ||
509 | }; | ||
510 | |||
511 | /* Structure for envp[]. */ | ||
512 | struct tomoyo_envp { | ||
513 | const struct tomoyo_path_info *name; | ||
514 | const struct tomoyo_path_info *value; | ||
515 | bool is_not; | ||
516 | }; | ||
517 | |||
518 | /* Structure for execve() operation. */ | ||
519 | struct tomoyo_execve { | ||
520 | struct tomoyo_request_info r; | ||
521 | struct tomoyo_obj_info obj; | ||
522 | struct linux_binprm *bprm; | ||
523 | /* For dumping argv[] and envp[]. */ | ||
524 | struct tomoyo_page_dump dump; | ||
525 | /* For temporary use. */ | ||
526 | char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ | ||
527 | }; | ||
528 | |||
529 | /* Structure for entries which follows "struct tomoyo_condition". */ | ||
530 | struct tomoyo_condition_element { | ||
531 | /* | ||
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 | ||
534 | * of the array of this struct. | ||
535 | */ | ||
536 | u8 left; | ||
537 | /* | ||
538 | * Right hand operand. A "struct tomoyo_number_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 | ||
541 | * struct. | ||
542 | */ | ||
543 | u8 right; | ||
544 | /* Equation operator. True if equals or overlaps, false otherwise. */ | ||
545 | bool equals; | ||
546 | }; | ||
547 | |||
548 | /* Structure for optional arguments. */ | ||
549 | struct tomoyo_condition { | ||
550 | struct tomoyo_shared_acl_head head; | ||
551 | u32 size; /* Memory size allocated for this entry. */ | ||
552 | u16 condc; /* Number of conditions in this struct. */ | ||
553 | u16 numbers_count; /* Number of "struct tomoyo_number_union values". */ | ||
554 | u16 names_count; /* Number of "struct tomoyo_name_union names". */ | ||
555 | u16 argc; /* Number of "struct tomoyo_argv". */ | ||
556 | u16 envc; /* Number of "struct tomoyo_envp". */ | ||
557 | /* | ||
558 | * struct tomoyo_condition_element condition[condc]; | ||
559 | * struct tomoyo_number_union values[numbers_count]; | ||
560 | * struct tomoyo_name_union names[names_count]; | ||
561 | * struct tomoyo_argv argv[argc]; | ||
562 | * struct tomoyo_envp envp[envc]; | ||
563 | */ | ||
564 | }; | ||
565 | |||
566 | /* Common header for individual entries. */ | ||
372 | struct tomoyo_acl_info { | 567 | struct tomoyo_acl_info { |
373 | struct list_head list; | 568 | struct list_head list; |
569 | struct tomoyo_condition *cond; /* Maybe NULL. */ | ||
374 | bool is_deleted; | 570 | bool is_deleted; |
375 | 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". */ |
376 | } __packed; | 572 | } __packed; |
377 | 573 | ||
378 | /* | 574 | /* Structure for domain information. */ |
379 | * tomoyo_domain_info is a structure which is used for holding permissions | ||
380 | * (e.g. "allow_read /lib/libc-2.5.so") given to each domain. | ||
381 | * It has following fields. | ||
382 | * | ||
383 | * (1) "list" which is linked to tomoyo_domain_list . | ||
384 | * (2) "acl_info_list" which is linked to "struct tomoyo_acl_info". | ||
385 | * (3) "domainname" which holds the name of the domain. | ||
386 | * (4) "profile" which remembers profile number assigned to this domain. | ||
387 | * (5) "is_deleted" is a bool which is true if this domain is marked as | ||
388 | * "deleted", false otherwise. | ||
389 | * (6) "quota_warned" is a bool which is used for suppressing warning message | ||
390 | * when learning mode learned too much entries. | ||
391 | * (7) "ignore_global_allow_read" is a bool which is true if this domain | ||
392 | * should ignore "allow_read" directive in exception policy. | ||
393 | * (8) "transition_failed" is a bool which is set to true when this domain was | ||
394 | * unable to create a new domain at tomoyo_find_next_domain() because the | ||
395 | * name of the domain to be created was too long or it could not allocate | ||
396 | * memory. If set to true, more than one process continued execve() | ||
397 | * without domain transition. | ||
398 | * (9) "users" is an atomic_t that holds how many "struct cred"->security | ||
399 | * are referring this "struct tomoyo_domain_info". If is_deleted == true | ||
400 | * and users == 0, this struct will be kfree()d upon next garbage | ||
401 | * collection. | ||
402 | * | ||
403 | * A domain's lifecycle is an analogy of files on / directory. | ||
404 | * Multiple domains with the same domainname cannot be created (as with | ||
405 | * creating files with the same filename fails with -EEXIST). | ||
406 | * If a process reached a domain, that process can reside in that domain after | ||
407 | * that domain is marked as "deleted" (as with a process can access an already | ||
408 | * open()ed file after that file was unlink()ed). | ||
409 | */ | ||
410 | struct tomoyo_domain_info { | 575 | struct tomoyo_domain_info { |
411 | struct list_head list; | 576 | struct list_head list; |
412 | struct list_head acl_info_list; | 577 | struct list_head acl_info_list; |
413 | /* Name of this domain. Never NULL. */ | 578 | /* Name of this domain. Never NULL. */ |
414 | const struct tomoyo_path_info *domainname; | 579 | const struct tomoyo_path_info *domainname; |
580 | /* Namespace for this domain. Never NULL. */ | ||
581 | struct tomoyo_policy_namespace *ns; | ||
415 | u8 profile; /* Profile number to use. */ | 582 | u8 profile; /* Profile number to use. */ |
583 | u8 group; /* Group number to use. */ | ||
416 | bool is_deleted; /* Delete flag. */ | 584 | bool is_deleted; /* Delete flag. */ |
417 | bool quota_warned; /* Quota warnning flag. */ | 585 | bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; |
418 | bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ | ||
419 | bool transition_failed; /* Domain transition failed flag. */ | ||
420 | atomic_t users; /* Number of referring credentials. */ | 586 | atomic_t users; /* Number of referring credentials. */ |
421 | }; | 587 | }; |
422 | 588 | ||
423 | /* | 589 | /* |
424 | * tomoyo_path_acl is a structure which is used for holding an | 590 | * Structure for "file execute", "file read", "file write", "file append", |
425 | * entry with one pathname operation (e.g. open(), mkdir()). | 591 | * "file unlink", "file getattr", "file rmdir", "file truncate", |
426 | * It has following fields. | 592 | * "file symlink", "file chroot" and "file unmount" directive. |
427 | * | ||
428 | * (1) "head" which is a "struct tomoyo_acl_info". | ||
429 | * (2) "perm" which is a bitmask of permitted operations. | ||
430 | * (3) "name" is the pathname. | ||
431 | * | ||
432 | * Directives held by this structure are "allow_read/write", "allow_execute", | ||
433 | * "allow_read", "allow_write", "allow_unlink", "allow_rmdir", | ||
434 | * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_chroot" and | ||
435 | * "allow_unmount". | ||
436 | */ | 593 | */ |
437 | struct tomoyo_path_acl { | 594 | struct tomoyo_path_acl { |
438 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ | 595 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ |
439 | u16 perm; | 596 | u16 perm; /* Bitmask of values in "enum tomoyo_path_acl_index". */ |
440 | struct tomoyo_name_union name; | 597 | struct tomoyo_name_union name; |
441 | }; | 598 | }; |
442 | 599 | ||
443 | /* | 600 | /* |
444 | * tomoyo_path_number_acl is a structure which is used for holding an | 601 | * Structure for "file create", "file mkdir", "file mkfifo", "file mksock", |
445 | * entry with one pathname and one number operation. | 602 | * "file ioctl", "file chmod", "file chown" and "file chgrp" directive. |
446 | * It has following fields. | ||
447 | * | ||
448 | * (1) "head" which is a "struct tomoyo_acl_info". | ||
449 | * (2) "perm" which is a bitmask of permitted operations. | ||
450 | * (3) "name" is the pathname. | ||
451 | * (4) "number" is the numeric value. | ||
452 | * | ||
453 | * Directives held by this structure are "allow_create", "allow_mkdir", | ||
454 | * "allow_ioctl", "allow_mkfifo", "allow_mksock", "allow_chmod", "allow_chown" | ||
455 | * and "allow_chgrp". | ||
456 | * | ||
457 | */ | 603 | */ |
458 | struct tomoyo_path_number_acl { | 604 | struct tomoyo_path_number_acl { |
459 | 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". */ | ||
460 | u8 perm; | 607 | u8 perm; |
461 | struct tomoyo_name_union name; | 608 | struct tomoyo_name_union name; |
462 | struct tomoyo_number_union number; | 609 | struct tomoyo_number_union number; |
463 | }; | 610 | }; |
464 | 611 | ||
465 | /* | 612 | /* Structure for "file mkblock" and "file mkchar" directive. */ |
466 | * tomoyo_mkdev_acl is a structure which is used for holding an | ||
467 | * entry with one pathname and three numbers operation. | ||
468 | * It has following fields. | ||
469 | * | ||
470 | * (1) "head" which is a "struct tomoyo_acl_info". | ||
471 | * (2) "perm" which is a bitmask of permitted operations. | ||
472 | * (3) "mode" is the create mode. | ||
473 | * (4) "major" is the major number of device node. | ||
474 | * (5) "minor" is the minor number of device node. | ||
475 | * | ||
476 | * Directives held by this structure are "allow_mkchar", "allow_mkblock". | ||
477 | * | ||
478 | */ | ||
479 | struct tomoyo_mkdev_acl { | 613 | struct tomoyo_mkdev_acl { |
480 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MKDEV_ACL */ | 614 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MKDEV_ACL */ |
481 | u8 perm; | 615 | u8 perm; /* Bitmask of values in "enum tomoyo_mkdev_acl_index". */ |
482 | struct tomoyo_name_union name; | 616 | struct tomoyo_name_union name; |
483 | struct tomoyo_number_union mode; | 617 | struct tomoyo_number_union mode; |
484 | struct tomoyo_number_union major; | 618 | struct tomoyo_number_union major; |
@@ -486,38 +620,16 @@ struct tomoyo_mkdev_acl { | |||
486 | }; | 620 | }; |
487 | 621 | ||
488 | /* | 622 | /* |
489 | * tomoyo_path2_acl is a structure which is used for holding an | 623 | * Structure for "file rename", "file link" and "file pivot_root" directive. |
490 | * entry with two pathnames operation (i.e. link(), rename() and pivot_root()). | ||
491 | * It has following fields. | ||
492 | * | ||
493 | * (1) "head" which is a "struct tomoyo_acl_info". | ||
494 | * (2) "perm" which is a bitmask of permitted operations. | ||
495 | * (3) "name1" is the source/old pathname. | ||
496 | * (4) "name2" is the destination/new pathname. | ||
497 | * | ||
498 | * Directives held by this structure are "allow_rename", "allow_link" and | ||
499 | * "allow_pivot_root". | ||
500 | */ | 624 | */ |
501 | struct tomoyo_path2_acl { | 625 | struct tomoyo_path2_acl { |
502 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ | 626 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ |
503 | u8 perm; | 627 | u8 perm; /* Bitmask of values in "enum tomoyo_path2_acl_index". */ |
504 | struct tomoyo_name_union name1; | 628 | struct tomoyo_name_union name1; |
505 | struct tomoyo_name_union name2; | 629 | struct tomoyo_name_union name2; |
506 | }; | 630 | }; |
507 | 631 | ||
508 | /* | 632 | /* Structure for "file mount" directive. */ |
509 | * tomoyo_mount_acl is a structure which is used for holding an | ||
510 | * entry for mount operation. | ||
511 | * It has following fields. | ||
512 | * | ||
513 | * (1) "head" which is a "struct tomoyo_acl_info". | ||
514 | * (2) "dev_name" is the device name. | ||
515 | * (3) "dir_name" is the mount point. | ||
516 | * (4) "fs_type" is the filesystem type. | ||
517 | * (5) "flags" is the mount flags. | ||
518 | * | ||
519 | * Directive held by this structure is "allow_mount". | ||
520 | */ | ||
521 | struct tomoyo_mount_acl { | 633 | struct tomoyo_mount_acl { |
522 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */ | 634 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */ |
523 | struct tomoyo_name_union dev_name; | 635 | struct tomoyo_name_union dev_name; |
@@ -526,7 +638,15 @@ struct tomoyo_mount_acl { | |||
526 | struct tomoyo_number_union flags; | 638 | struct tomoyo_number_union flags; |
527 | }; | 639 | }; |
528 | 640 | ||
529 | #define TOMOYO_MAX_IO_READ_QUEUE 32 | 641 | /* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */ |
642 | struct tomoyo_acl_param { | ||
643 | char *data; | ||
644 | struct list_head *list; | ||
645 | struct tomoyo_policy_namespace *ns; | ||
646 | bool is_delete; | ||
647 | }; | ||
648 | |||
649 | #define TOMOYO_MAX_IO_READ_QUEUE 64 | ||
530 | 650 | ||
531 | /* | 651 | /* |
532 | * Structure for reading/writing policy via /sys/kernel/security/tomoyo | 652 | * Structure for reading/writing policy via /sys/kernel/security/tomoyo |
@@ -538,95 +658,55 @@ struct tomoyo_io_buffer { | |||
538 | int (*poll) (struct file *file, poll_table *wait); | 658 | int (*poll) (struct file *file, poll_table *wait); |
539 | /* Exclusive lock for this structure. */ | 659 | /* Exclusive lock for this structure. */ |
540 | struct mutex io_sem; | 660 | struct mutex io_sem; |
541 | /* Index returned by tomoyo_read_lock(). */ | ||
542 | int reader_idx; | ||
543 | char __user *read_user_buf; | 661 | char __user *read_user_buf; |
544 | int read_user_buf_avail; | 662 | size_t read_user_buf_avail; |
545 | struct { | 663 | struct { |
664 | struct list_head *ns; | ||
546 | struct list_head *domain; | 665 | struct list_head *domain; |
547 | struct list_head *group; | 666 | struct list_head *group; |
548 | struct list_head *acl; | 667 | struct list_head *acl; |
549 | int avail; | 668 | size_t avail; |
550 | int step; | 669 | unsigned int step; |
551 | int query_index; | 670 | unsigned int query_index; |
552 | u16 index; | 671 | u16 index; |
672 | u16 cond_index; | ||
673 | u8 acl_group_index; | ||
674 | u8 cond_step; | ||
553 | u8 bit; | 675 | u8 bit; |
554 | u8 w_pos; | 676 | u8 w_pos; |
555 | bool eof; | 677 | bool eof; |
556 | bool print_this_domain_only; | 678 | bool print_this_domain_only; |
557 | bool print_execute_only; | 679 | bool print_transition_related_only; |
680 | bool print_cond_part; | ||
558 | const char *w[TOMOYO_MAX_IO_READ_QUEUE]; | 681 | const char *w[TOMOYO_MAX_IO_READ_QUEUE]; |
559 | } r; | 682 | } r; |
560 | /* The position currently writing to. */ | 683 | struct { |
561 | struct tomoyo_domain_info *write_var1; | 684 | struct tomoyo_policy_namespace *ns; |
685 | /* The position currently writing to. */ | ||
686 | struct tomoyo_domain_info *domain; | ||
687 | /* Bytes available for writing. */ | ||
688 | size_t avail; | ||
689 | bool is_delete; | ||
690 | } w; | ||
562 | /* Buffer for reading. */ | 691 | /* Buffer for reading. */ |
563 | char *read_buf; | 692 | char *read_buf; |
564 | /* Size of read buffer. */ | 693 | /* Size of read buffer. */ |
565 | int readbuf_size; | 694 | size_t readbuf_size; |
566 | /* Buffer for writing. */ | 695 | /* Buffer for writing. */ |
567 | char *write_buf; | 696 | char *write_buf; |
568 | /* Bytes available for writing. */ | ||
569 | int write_avail; | ||
570 | /* Size of write buffer. */ | 697 | /* Size of write buffer. */ |
571 | int writebuf_size; | 698 | size_t writebuf_size; |
572 | /* Type of this interface. */ | 699 | /* Type of this interface. */ |
573 | u8 type; | 700 | enum tomoyo_securityfs_interface_index type; |
574 | }; | 701 | /* Users counter protected by tomoyo_io_buffer_list_lock. */ |
575 | 702 | u8 users; | |
576 | /* | 703 | /* List for telling GC not to kfree() elements. */ |
577 | * tomoyo_readable_file is a structure which is used for holding | 704 | struct list_head list; |
578 | * "allow_read" entries. | ||
579 | * It has following fields. | ||
580 | * | ||
581 | * (1) "head" is "struct tomoyo_acl_head". | ||
582 | * (2) "filename" is a pathname which is allowed to open(O_RDONLY). | ||
583 | */ | ||
584 | struct tomoyo_readable_file { | ||
585 | struct tomoyo_acl_head head; | ||
586 | const struct tomoyo_path_info *filename; | ||
587 | }; | ||
588 | |||
589 | /* | ||
590 | * tomoyo_no_pattern is a structure which is used for holding | ||
591 | * "file_pattern" entries. | ||
592 | * It has following fields. | ||
593 | * | ||
594 | * (1) "head" is "struct tomoyo_acl_head". | ||
595 | * (2) "pattern" is a pathname pattern which is used for converting pathnames | ||
596 | * to pathname patterns during learning mode. | ||
597 | */ | ||
598 | struct tomoyo_no_pattern { | ||
599 | struct tomoyo_acl_head head; | ||
600 | const struct tomoyo_path_info *pattern; | ||
601 | }; | ||
602 | |||
603 | /* | ||
604 | * tomoyo_no_rewrite is a structure which is used for holding | ||
605 | * "deny_rewrite" entries. | ||
606 | * It has following fields. | ||
607 | * | ||
608 | * (1) "head" is "struct tomoyo_acl_head". | ||
609 | * (2) "pattern" is a pathname which is by default not permitted to modify | ||
610 | * already existing content. | ||
611 | */ | ||
612 | struct tomoyo_no_rewrite { | ||
613 | struct tomoyo_acl_head head; | ||
614 | const struct tomoyo_path_info *pattern; | ||
615 | }; | 705 | }; |
616 | 706 | ||
617 | /* | 707 | /* |
618 | * tomoyo_transition_control is a structure which is used for holding | 708 | * Structure for "initialize_domain"/"no_initialize_domain"/"keep_domain"/ |
619 | * "initialize_domain"/"no_initialize_domain"/"keep_domain"/"no_keep_domain" | 709 | * "no_keep_domain" keyword. |
620 | * entries. | ||
621 | * It has following fields. | ||
622 | * | ||
623 | * (1) "head" is "struct tomoyo_acl_head". | ||
624 | * (2) "type" is type of this entry. | ||
625 | * (3) "is_last_name" is a bool which is true if "domainname" is "the last | ||
626 | * component of a domainname", false otherwise. | ||
627 | * (4) "domainname" which is "a domainname" or "the last component of a | ||
628 | * domainname". | ||
629 | * (5) "program" which is a program's pathname. | ||
630 | */ | 710 | */ |
631 | struct tomoyo_transition_control { | 711 | struct tomoyo_transition_control { |
632 | struct tomoyo_acl_head head; | 712 | struct tomoyo_acl_head head; |
@@ -637,32 +717,14 @@ struct tomoyo_transition_control { | |||
637 | const struct tomoyo_path_info *program; /* Maybe NULL */ | 717 | const struct tomoyo_path_info *program; /* Maybe NULL */ |
638 | }; | 718 | }; |
639 | 719 | ||
640 | /* | 720 | /* Structure for "aggregator" keyword. */ |
641 | * tomoyo_aggregator is a structure which is used for holding | ||
642 | * "aggregator" entries. | ||
643 | * It has following fields. | ||
644 | * | ||
645 | * (1) "head" is "struct tomoyo_acl_head". | ||
646 | * (2) "original_name" which is originally requested name. | ||
647 | * (3) "aggregated_name" which is name to rewrite. | ||
648 | */ | ||
649 | struct tomoyo_aggregator { | 721 | struct tomoyo_aggregator { |
650 | struct tomoyo_acl_head head; | 722 | struct tomoyo_acl_head head; |
651 | const struct tomoyo_path_info *original_name; | 723 | const struct tomoyo_path_info *original_name; |
652 | const struct tomoyo_path_info *aggregated_name; | 724 | const struct tomoyo_path_info *aggregated_name; |
653 | }; | 725 | }; |
654 | 726 | ||
655 | /* | 727 | /* Structure for policy manager. */ |
656 | * tomoyo_manager is a structure which is used for holding list of | ||
657 | * domainnames or programs which are permitted to modify configuration via | ||
658 | * /sys/kernel/security/tomoyo/ interface. | ||
659 | * It has following fields. | ||
660 | * | ||
661 | * (1) "head" is "struct tomoyo_acl_head". | ||
662 | * (2) "is_domain" is a bool which is true if "manager" is a domainname, false | ||
663 | * otherwise. | ||
664 | * (3) "manager" is a domainname or a program's pathname. | ||
665 | */ | ||
666 | struct tomoyo_manager { | 728 | struct tomoyo_manager { |
667 | struct tomoyo_acl_head head; | 729 | struct tomoyo_acl_head head; |
668 | bool is_domain; /* True if manager is a domainname. */ | 730 | bool is_domain; /* True if manager is a domainname. */ |
@@ -677,6 +739,7 @@ struct tomoyo_preference { | |||
677 | bool permissive_verbose; | 739 | bool permissive_verbose; |
678 | }; | 740 | }; |
679 | 741 | ||
742 | /* Structure for /sys/kernel/security/tomnoyo/profile interface. */ | ||
680 | struct tomoyo_profile { | 743 | struct tomoyo_profile { |
681 | const struct tomoyo_path_info *comment; | 744 | const struct tomoyo_path_info *comment; |
682 | struct tomoyo_preference *learning; | 745 | struct tomoyo_preference *learning; |
@@ -685,323 +748,409 @@ struct tomoyo_profile { | |||
685 | struct tomoyo_preference preference; | 748 | struct tomoyo_preference preference; |
686 | u8 default_config; | 749 | u8 default_config; |
687 | 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]; | ||
752 | }; | ||
753 | |||
754 | /* Structure for representing YYYY/MM/DD hh/mm/ss. */ | ||
755 | struct tomoyo_time { | ||
756 | u16 year; | ||
757 | u8 month; | ||
758 | u8 day; | ||
759 | u8 hour; | ||
760 | u8 min; | ||
761 | u8 sec; | ||
762 | }; | ||
763 | |||
764 | /* Structure for policy namespace. */ | ||
765 | struct tomoyo_policy_namespace { | ||
766 | /* Profile table. Memory is allocated as needed. */ | ||
767 | struct tomoyo_profile *profile_ptr[TOMOYO_MAX_PROFILES]; | ||
768 | /* List of "struct tomoyo_group". */ | ||
769 | struct list_head group_list[TOMOYO_MAX_GROUP]; | ||
770 | /* List of policy. */ | ||
771 | struct list_head policy_list[TOMOYO_MAX_POLICY]; | ||
772 | /* The global ACL referred by "use_group" keyword. */ | ||
773 | struct list_head acl_group[TOMOYO_MAX_ACL_GROUPS]; | ||
774 | /* List for connecting to tomoyo_namespace_list list. */ | ||
775 | struct list_head namespace_list; | ||
776 | /* Profile version. Currently only 20100903 is defined. */ | ||
777 | unsigned int profile_version; | ||
778 | /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */ | ||
779 | const char *name; | ||
688 | }; | 780 | }; |
689 | 781 | ||
690 | /********** Function prototypes. **********/ | 782 | /********** Function prototypes. **********/ |
691 | 783 | ||
692 | /* Check whether the given string starts with the given keyword. */ | ||
693 | bool tomoyo_str_starts(char **src, const char *find); | ||
694 | /* Get tomoyo_realpath() of current process. */ | ||
695 | const char *tomoyo_get_exe(void); | ||
696 | /* Format string. */ | ||
697 | void tomoyo_normalize_line(unsigned char *buffer); | ||
698 | /* Print warning or error message on console. */ | ||
699 | void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) | ||
700 | __attribute__ ((format(printf, 2, 3))); | ||
701 | /* Check all profiles currently assigned to domains are defined. */ | ||
702 | void tomoyo_check_profile(void); | ||
703 | /* Open operation for /sys/kernel/security/tomoyo/ interface. */ | ||
704 | int tomoyo_open_control(const u8 type, struct file *file); | ||
705 | /* Close /sys/kernel/security/tomoyo/ interface. */ | ||
706 | int tomoyo_close_control(struct file *file); | ||
707 | /* Poll operation for /sys/kernel/security/tomoyo/ interface. */ | ||
708 | int tomoyo_poll_control(struct file *file, poll_table *wait); | ||
709 | /* Read operation for /sys/kernel/security/tomoyo/ interface. */ | ||
710 | int tomoyo_read_control(struct file *file, char __user *buffer, | ||
711 | const int buffer_len); | ||
712 | /* Write operation for /sys/kernel/security/tomoyo/ interface. */ | ||
713 | int tomoyo_write_control(struct file *file, const char __user *buffer, | ||
714 | const int buffer_len); | ||
715 | /* Check whether the domain has too many ACL entries to hold. */ | ||
716 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); | ||
717 | /* Print out of memory warning message. */ | ||
718 | void tomoyo_warn_oom(const char *function); | ||
719 | /* Check whether the given name matches the given name_union. */ | ||
720 | const struct tomoyo_path_info * | ||
721 | tomoyo_compare_name_union(const struct tomoyo_path_info *name, | ||
722 | const struct tomoyo_name_union *ptr); | ||
723 | /* Check whether the given number matches the given number_union. */ | ||
724 | bool tomoyo_compare_number_union(const unsigned long value, | 784 | bool tomoyo_compare_number_union(const unsigned long value, |
725 | const struct tomoyo_number_union *ptr); | 785 | const struct tomoyo_number_union *ptr); |
726 | int tomoyo_get_mode(const u8 profile, const u8 index); | 786 | bool tomoyo_condition(struct tomoyo_request_info *r, |
727 | void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) | 787 | const struct tomoyo_condition *cond); |
728 | __attribute__ ((format(printf, 2, 3))); | ||
729 | /* Check whether the domainname is correct. */ | ||
730 | bool tomoyo_correct_domain(const unsigned char *domainname); | 788 | bool tomoyo_correct_domain(const unsigned char *domainname); |
731 | /* Check whether the token is correct. */ | ||
732 | bool tomoyo_correct_path(const char *filename); | 789 | bool tomoyo_correct_path(const char *filename); |
733 | bool tomoyo_correct_word(const char *string); | 790 | bool tomoyo_correct_word(const char *string); |
734 | /* Check whether the token can be a domainname. */ | ||
735 | bool tomoyo_domain_def(const unsigned char *buffer); | 791 | bool tomoyo_domain_def(const unsigned char *buffer); |
736 | bool tomoyo_parse_name_union(const char *filename, | 792 | bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); |
737 | struct tomoyo_name_union *ptr); | 793 | bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, |
738 | /* Check whether the given filename matches the given path_group. */ | 794 | struct tomoyo_page_dump *dump); |
739 | const struct tomoyo_path_info * | 795 | bool tomoyo_memory_ok(void *ptr); |
740 | tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, | ||
741 | const struct tomoyo_group *group); | ||
742 | /* Check whether the given value matches the given number_group. */ | ||
743 | bool tomoyo_number_matches_group(const unsigned long min, | 796 | bool tomoyo_number_matches_group(const unsigned long min, |
744 | const unsigned long max, | 797 | const unsigned long max, |
745 | const struct tomoyo_group *group); | 798 | const struct tomoyo_group *group); |
746 | /* Check whether the given filename matches the given pattern. */ | 799 | bool tomoyo_parse_name_union(struct tomoyo_acl_param *param, |
800 | struct tomoyo_name_union *ptr); | ||
801 | bool tomoyo_parse_number_union(struct tomoyo_acl_param *param, | ||
802 | struct tomoyo_number_union *ptr); | ||
747 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, | 803 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, |
748 | const struct tomoyo_path_info *pattern); | 804 | const struct tomoyo_path_info *pattern); |
749 | 805 | bool tomoyo_permstr(const char *string, const char *keyword); | |
750 | bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num); | 806 | bool tomoyo_str_starts(char **src, const char *find); |
751 | /* Tokenize a line. */ | ||
752 | bool tomoyo_tokenize(char *buffer, char *w[], size_t size); | ||
753 | /* Write domain policy violation warning message to console? */ | ||
754 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); | ||
755 | /* Fill "struct tomoyo_request_info". */ | ||
756 | int tomoyo_init_request_info(struct tomoyo_request_info *r, | ||
757 | struct tomoyo_domain_info *domain, | ||
758 | const u8 index); | ||
759 | /* Check permission for mount operation. */ | ||
760 | int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, | ||
761 | unsigned long flags, void *data_page); | ||
762 | /* Create "aggregator" entry in exception policy. */ | ||
763 | int tomoyo_write_aggregator(char *data, const bool is_delete); | ||
764 | int tomoyo_write_transition_control(char *data, const bool is_delete, | ||
765 | const u8 type); | ||
766 | /* | ||
767 | * Create "allow_read/write", "allow_execute", "allow_read", "allow_write", | ||
768 | * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir", | ||
769 | * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar", | ||
770 | * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and | ||
771 | * "allow_link" entry in domain policy. | ||
772 | */ | ||
773 | int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, | ||
774 | const bool is_delete); | ||
775 | /* Create "allow_read" entry in exception policy. */ | ||
776 | int tomoyo_write_globally_readable(char *data, const bool is_delete); | ||
777 | /* Create "allow_mount" entry in domain policy. */ | ||
778 | int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain, | ||
779 | const bool is_delete); | ||
780 | /* Create "deny_rewrite" entry in exception policy. */ | ||
781 | int tomoyo_write_no_rewrite(char *data, const bool is_delete); | ||
782 | /* Create "file_pattern" entry in exception policy. */ | ||
783 | int tomoyo_write_pattern(char *data, const bool is_delete); | ||
784 | /* Create "path_group"/"number_group" entry in exception policy. */ | ||
785 | int tomoyo_write_group(char *data, const bool is_delete, const u8 type); | ||
786 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) | ||
787 | __attribute__ ((format(printf, 2, 3))); | ||
788 | /* Find a domain by the given name. */ | ||
789 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | ||
790 | /* Find or create a domain by the given name. */ | ||
791 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | ||
792 | const u8 profile); | ||
793 | struct tomoyo_profile *tomoyo_profile(const u8 profile); | ||
794 | /* | ||
795 | * Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". | ||
796 | */ | ||
797 | struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type); | ||
798 | |||
799 | /* Check mode for specified functionality. */ | ||
800 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | ||
801 | const u8 index); | ||
802 | /* Fill in "struct tomoyo_path_info" members. */ | ||
803 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | ||
804 | /* Run policy loader when /sbin/init starts. */ | ||
805 | void tomoyo_load_policy(const char *filename); | ||
806 | |||
807 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr); | ||
808 | |||
809 | /* Convert binary string to ascii string. */ | ||
810 | char *tomoyo_encode(const char *str); | 807 | char *tomoyo_encode(const char *str); |
811 | 808 | char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | |
812 | /* | 809 | va_list args); |
813 | * Returns realpath(3) of the given pathname except that | 810 | char *tomoyo_read_token(struct tomoyo_acl_param *param); |
814 | * ignores chroot'ed root and does not follow the final symlink. | ||
815 | */ | ||
816 | char *tomoyo_realpath_nofollow(const char *pathname); | ||
817 | /* | ||
818 | * Returns realpath(3) of the given pathname except that | ||
819 | * ignores chroot'ed root and the pathname is already solved. | ||
820 | */ | ||
821 | char *tomoyo_realpath_from_path(struct path *path); | 811 | char *tomoyo_realpath_from_path(struct path *path); |
822 | /* Get patterned pathname. */ | 812 | char *tomoyo_realpath_nofollow(const char *pathname); |
823 | const char *tomoyo_pattern(const struct tomoyo_path_info *filename); | 813 | const char *tomoyo_get_exe(void); |
824 | 814 | const char *tomoyo_yesno(const unsigned int value); | |
825 | /* Check memory quota. */ | 815 | const struct tomoyo_path_info *tomoyo_compare_name_union |
826 | bool tomoyo_memory_ok(void *ptr); | 816 | (const struct tomoyo_path_info *name, const struct tomoyo_name_union *ptr); |
827 | void *tomoyo_commit_ok(void *data, const unsigned int size); | ||
828 | |||
829 | /* | ||
830 | * Keep the given name on the RAM. | ||
831 | * The RAM is shared, so NEVER try to modify or kfree() the returned name. | ||
832 | */ | ||
833 | const struct tomoyo_path_info *tomoyo_get_name(const char *name); | 817 | const struct tomoyo_path_info *tomoyo_get_name(const char *name); |
834 | 818 | const struct tomoyo_path_info *tomoyo_path_matches_group | |
835 | /* Check for memory usage. */ | 819 | (const struct tomoyo_path_info *pathname, const struct tomoyo_group *group); |
836 | void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); | ||
837 | |||
838 | /* Set memory quota. */ | ||
839 | int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); | ||
840 | |||
841 | /* Initialize mm related code. */ | ||
842 | void __init tomoyo_mm_init(void); | ||
843 | int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | ||
844 | const struct tomoyo_path_info *filename); | ||
845 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | 820 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, |
846 | struct path *path, const int flag); | 821 | struct path *path, const int flag); |
847 | int tomoyo_path_number_perm(const u8 operation, struct path *path, | 822 | int tomoyo_close_control(struct tomoyo_io_buffer *head); |
848 | unsigned long number); | 823 | int tomoyo_find_next_domain(struct linux_binprm *bprm); |
824 | int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, | ||
825 | const u8 index); | ||
826 | int tomoyo_init_request_info(struct tomoyo_request_info *r, | ||
827 | struct tomoyo_domain_info *domain, | ||
828 | const u8 index); | ||
849 | int tomoyo_mkdev_perm(const u8 operation, struct path *path, | 829 | int tomoyo_mkdev_perm(const u8 operation, struct path *path, |
850 | const unsigned int mode, unsigned int dev); | 830 | const unsigned int mode, unsigned int dev); |
851 | int tomoyo_path_perm(const u8 operation, struct path *path); | 831 | int tomoyo_mount_permission(char *dev_name, struct path *path, |
832 | const char *type, unsigned long flags, | ||
833 | void *data_page); | ||
834 | int tomoyo_open_control(const u8 type, struct file *file); | ||
852 | int tomoyo_path2_perm(const u8 operation, struct path *path1, | 835 | int tomoyo_path2_perm(const u8 operation, struct path *path1, |
853 | struct path *path2); | 836 | struct path *path2); |
854 | int tomoyo_find_next_domain(struct linux_binprm *bprm); | 837 | int tomoyo_path_number_perm(const u8 operation, struct path *path, |
855 | 838 | unsigned long number); | |
856 | void tomoyo_print_ulong(char *buffer, const int buffer_len, | 839 | int tomoyo_path_perm(const u8 operation, struct path *path, |
857 | const unsigned long value, const u8 type); | 840 | const char *target); |
858 | 841 | int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |
859 | /* Drop refcount on tomoyo_name_union. */ | 842 | const struct tomoyo_path_info *filename); |
860 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr); | 843 | int tomoyo_poll_control(struct file *file, poll_table *wait); |
861 | 844 | int tomoyo_poll_log(struct file *file, poll_table *wait); | |
862 | /* Run garbage collector. */ | 845 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) |
863 | void tomoyo_run_gc(void); | 846 | __printf(2, 3); |
864 | |||
865 | void tomoyo_memory_free(void *ptr); | ||
866 | |||
867 | 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, |
868 | bool is_delete, struct tomoyo_domain_info *domain, | 848 | struct tomoyo_acl_param *param, |
869 | bool (*check_duplicate) (const struct tomoyo_acl_info | 849 | bool (*check_duplicate) |
870 | *, | 850 | (const struct tomoyo_acl_info *, |
871 | const struct tomoyo_acl_info | 851 | const struct tomoyo_acl_info *), |
872 | *), | 852 | bool (*merge_duplicate) |
873 | bool (*merge_duplicate) (struct tomoyo_acl_info *, | 853 | (struct tomoyo_acl_info *, struct tomoyo_acl_info *, |
874 | struct tomoyo_acl_info *, | 854 | const bool)); |
875 | const bool)); | ||
876 | 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, |
877 | bool is_delete, struct list_head *list, | 856 | struct tomoyo_acl_param *param, |
878 | bool (*check_duplicate) (const struct tomoyo_acl_head | 857 | bool (*check_duplicate) |
879 | *, | 858 | (const struct tomoyo_acl_head *, |
880 | const struct tomoyo_acl_head | 859 | const struct tomoyo_acl_head *)); |
881 | *)); | 860 | int tomoyo_write_aggregator(struct tomoyo_acl_param *param); |
861 | int tomoyo_write_file(struct tomoyo_acl_param *param); | ||
862 | int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type); | ||
863 | int tomoyo_write_transition_control(struct tomoyo_acl_param *param, | ||
864 | const u8 type); | ||
865 | ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, | ||
866 | const int buffer_len); | ||
867 | ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, | ||
868 | const char __user *buffer, const int buffer_len); | ||
869 | struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param); | ||
870 | struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, | ||
871 | const bool transit); | ||
872 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); | ||
873 | struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, | ||
874 | const u8 idx); | ||
875 | struct tomoyo_policy_namespace *tomoyo_assign_namespace | ||
876 | (const char *domainname); | ||
877 | struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, | ||
878 | const u8 profile); | ||
879 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | ||
880 | const u8 index); | ||
881 | u8 tomoyo_parse_ulong(unsigned long *result, char **str); | ||
882 | void *tomoyo_commit_ok(void *data, const unsigned int size); | ||
883 | void __init tomoyo_load_builtin_policy(void); | ||
884 | void __init tomoyo_mm_init(void); | ||
882 | void tomoyo_check_acl(struct tomoyo_request_info *r, | 885 | void tomoyo_check_acl(struct tomoyo_request_info *r, |
883 | bool (*check_entry) (struct tomoyo_request_info *, | 886 | bool (*check_entry) (struct tomoyo_request_info *, |
884 | const struct tomoyo_acl_info *)); | 887 | const struct tomoyo_acl_info *)); |
888 | void tomoyo_check_profile(void); | ||
889 | void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp); | ||
890 | void tomoyo_del_condition(struct list_head *element); | ||
891 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | ||
892 | void tomoyo_get_attributes(struct tomoyo_obj_info *obj); | ||
893 | void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns); | ||
894 | void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) | ||
895 | __printf(2, 3); | ||
896 | void tomoyo_load_policy(const char *filename); | ||
897 | void tomoyo_memory_free(void *ptr); | ||
898 | void tomoyo_normalize_line(unsigned char *buffer); | ||
899 | void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register); | ||
900 | void tomoyo_print_ulong(char *buffer, const int buffer_len, | ||
901 | const unsigned long value, const u8 type); | ||
902 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr); | ||
903 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr); | ||
904 | void tomoyo_read_log(struct tomoyo_io_buffer *head); | ||
905 | void tomoyo_update_stat(const u8 index); | ||
906 | void tomoyo_warn_oom(const char *function); | ||
907 | void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) | ||
908 | __printf(2, 3); | ||
909 | void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, | ||
910 | va_list args); | ||
885 | 911 | ||
886 | /********** External variable definitions. **********/ | 912 | /********** External variable definitions. **********/ |
887 | 913 | ||
888 | /* Lock for GC. */ | 914 | extern bool tomoyo_policy_loaded; |
889 | extern struct srcu_struct tomoyo_ss; | 915 | extern const char * const tomoyo_condition_keyword |
890 | 916 | [TOMOYO_MAX_CONDITION_KEYWORD]; | |
891 | /* The list for "struct tomoyo_domain_info". */ | 917 | extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; |
918 | extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX | ||
919 | + TOMOYO_MAX_MAC_CATEGORY_INDEX]; | ||
920 | extern const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE]; | ||
921 | extern const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION]; | ||
922 | extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX]; | ||
923 | extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; | ||
924 | extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; | ||
925 | extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION]; | ||
926 | extern struct list_head tomoyo_condition_list; | ||
892 | extern struct list_head tomoyo_domain_list; | 927 | extern struct list_head tomoyo_domain_list; |
893 | |||
894 | extern struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY]; | ||
895 | extern struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP]; | ||
896 | extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; | 928 | extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; |
897 | 929 | extern struct list_head tomoyo_namespace_list; | |
898 | /* Lock for protecting policy. */ | ||
899 | extern struct mutex tomoyo_policy_lock; | 930 | extern struct mutex tomoyo_policy_lock; |
900 | 931 | extern struct srcu_struct tomoyo_ss; | |
901 | /* Has /sbin/init started? */ | ||
902 | extern bool tomoyo_policy_loaded; | ||
903 | |||
904 | /* The kernel's domain. */ | ||
905 | extern struct tomoyo_domain_info tomoyo_kernel_domain; | 932 | extern struct tomoyo_domain_info tomoyo_kernel_domain; |
906 | 933 | extern struct tomoyo_policy_namespace tomoyo_kernel_namespace; | |
907 | extern const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION]; | 934 | extern unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; |
908 | extern const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION]; | 935 | extern unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; |
909 | extern const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION]; | ||
910 | extern const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION]; | ||
911 | |||
912 | extern unsigned int tomoyo_quota_for_query; | ||
913 | extern unsigned int tomoyo_query_memory_size; | ||
914 | 936 | ||
915 | /********** Inlined functions. **********/ | 937 | /********** Inlined functions. **********/ |
916 | 938 | ||
939 | /** | ||
940 | * tomoyo_read_lock - Take lock for protecting policy. | ||
941 | * | ||
942 | * Returns index number for tomoyo_read_unlock(). | ||
943 | */ | ||
917 | static inline int tomoyo_read_lock(void) | 944 | static inline int tomoyo_read_lock(void) |
918 | { | 945 | { |
919 | return srcu_read_lock(&tomoyo_ss); | 946 | return srcu_read_lock(&tomoyo_ss); |
920 | } | 947 | } |
921 | 948 | ||
949 | /** | ||
950 | * tomoyo_read_unlock - Release lock for protecting policy. | ||
951 | * | ||
952 | * @idx: Index number returned by tomoyo_read_lock(). | ||
953 | * | ||
954 | * Returns nothing. | ||
955 | */ | ||
922 | static inline void tomoyo_read_unlock(int idx) | 956 | static inline void tomoyo_read_unlock(int idx) |
923 | { | 957 | { |
924 | srcu_read_unlock(&tomoyo_ss, idx); | 958 | srcu_read_unlock(&tomoyo_ss, idx); |
925 | } | 959 | } |
926 | 960 | ||
927 | /* strcmp() for "struct tomoyo_path_info" structure. */ | 961 | /** |
928 | static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, | 962 | * tomoyo_sys_getppid - Copy of getppid(). |
929 | const struct tomoyo_path_info *b) | 963 | * |
964 | * Returns parent process's PID. | ||
965 | * | ||
966 | * Alpha does not have getppid() defined. To be able to build this module on | ||
967 | * Alpha, I have to copy getppid() from kernel/timer.c. | ||
968 | */ | ||
969 | static inline pid_t tomoyo_sys_getppid(void) | ||
930 | { | 970 | { |
931 | return a->hash != b->hash || strcmp(a->name, b->name); | 971 | pid_t pid; |
972 | rcu_read_lock(); | ||
973 | pid = task_tgid_vnr(current->real_parent); | ||
974 | rcu_read_unlock(); | ||
975 | return pid; | ||
932 | } | 976 | } |
933 | 977 | ||
934 | /** | 978 | /** |
935 | * tomoyo_valid - Check whether the character is a valid char. | 979 | * tomoyo_sys_getpid - Copy of getpid(). |
936 | * | 980 | * |
937 | * @c: The character to check. | 981 | * Returns current thread's PID. |
938 | * | 982 | * |
939 | * Returns true if @c is a valid character, false otherwise. | 983 | * Alpha does not have getpid() defined. To be able to build this module on |
984 | * Alpha, I have to copy getpid() from kernel/timer.c. | ||
940 | */ | 985 | */ |
941 | static inline bool tomoyo_valid(const unsigned char c) | 986 | static inline pid_t tomoyo_sys_getpid(void) |
942 | { | 987 | { |
943 | return c > ' ' && c < 127; | 988 | return task_tgid_vnr(current); |
944 | } | 989 | } |
945 | 990 | ||
946 | /** | 991 | /** |
947 | * tomoyo_invalid - Check whether the character is an invalid char. | 992 | * tomoyo_pathcmp - strcmp() for "struct tomoyo_path_info" structure. |
948 | * | 993 | * |
949 | * @c: The character to check. | 994 | * @a: Pointer to "struct tomoyo_path_info". |
995 | * @b: Pointer to "struct tomoyo_path_info". | ||
950 | * | 996 | * |
951 | * Returns true if @c is an invalid character, false otherwise. | 997 | * Returns true if @a == @b, false otherwise. |
952 | */ | 998 | */ |
953 | static inline bool tomoyo_invalid(const unsigned char c) | 999 | static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, |
1000 | const struct tomoyo_path_info *b) | ||
954 | { | 1001 | { |
955 | return c && (c <= ' ' || c >= 127); | 1002 | return a->hash != b->hash || strcmp(a->name, b->name); |
956 | } | 1003 | } |
957 | 1004 | ||
1005 | /** | ||
1006 | * tomoyo_put_name - Drop reference on "struct tomoyo_name". | ||
1007 | * | ||
1008 | * @name: Pointer to "struct tomoyo_path_info". Maybe NULL. | ||
1009 | * | ||
1010 | * Returns nothing. | ||
1011 | */ | ||
958 | 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) |
959 | { | 1013 | { |
960 | if (name) { | 1014 | if (name) { |
961 | struct tomoyo_name *ptr = | 1015 | struct tomoyo_name *ptr = |
962 | container_of(name, typeof(*ptr), entry); | 1016 | container_of(name, typeof(*ptr), entry); |
963 | atomic_dec(&ptr->users); | 1017 | atomic_dec(&ptr->head.users); |
964 | } | 1018 | } |
965 | } | 1019 | } |
966 | 1020 | ||
1021 | /** | ||
1022 | * tomoyo_put_condition - Drop reference on "struct tomoyo_condition". | ||
1023 | * | ||
1024 | * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. | ||
1025 | * | ||
1026 | * Returns nothing. | ||
1027 | */ | ||
1028 | static inline void tomoyo_put_condition(struct tomoyo_condition *cond) | ||
1029 | { | ||
1030 | if (cond) | ||
1031 | atomic_dec(&cond->head.users); | ||
1032 | } | ||
1033 | |||
1034 | /** | ||
1035 | * tomoyo_put_group - Drop reference on "struct tomoyo_group". | ||
1036 | * | ||
1037 | * @group: Pointer to "struct tomoyo_group". Maybe NULL. | ||
1038 | * | ||
1039 | * Returns nothing. | ||
1040 | */ | ||
967 | static inline void tomoyo_put_group(struct tomoyo_group *group) | 1041 | static inline void tomoyo_put_group(struct tomoyo_group *group) |
968 | { | 1042 | { |
969 | if (group) | 1043 | if (group) |
970 | atomic_dec(&group->users); | 1044 | atomic_dec(&group->head.users); |
971 | } | 1045 | } |
972 | 1046 | ||
1047 | /** | ||
1048 | * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. | ||
1049 | * | ||
1050 | * Returns pointer to "struct tomoyo_domain_info" for current thread. | ||
1051 | */ | ||
973 | static inline struct tomoyo_domain_info *tomoyo_domain(void) | 1052 | static inline struct tomoyo_domain_info *tomoyo_domain(void) |
974 | { | 1053 | { |
975 | return current_cred()->security; | 1054 | return current_cred()->security; |
976 | } | 1055 | } |
977 | 1056 | ||
1057 | /** | ||
1058 | * tomoyo_real_domain - Get "struct tomoyo_domain_info" for specified thread. | ||
1059 | * | ||
1060 | * @task: Pointer to "struct task_struct". | ||
1061 | * | ||
1062 | * Returns pointer to "struct tomoyo_security" for specified thread. | ||
1063 | */ | ||
978 | 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 |
979 | *task) | 1065 | *task) |
980 | { | 1066 | { |
981 | return task_cred_xxx(task, security); | 1067 | return task_cred_xxx(task, security); |
982 | } | 1068 | } |
983 | 1069 | ||
984 | static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1, | 1070 | /** |
985 | const struct tomoyo_acl_info *p2) | 1071 | * tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry. |
1072 | * | ||
1073 | * @a: Pointer to "struct tomoyo_name_union". | ||
1074 | * @b: Pointer to "struct tomoyo_name_union". | ||
1075 | * | ||
1076 | * Returns true if @a == @b, false otherwise. | ||
1077 | */ | ||
1078 | static inline bool tomoyo_same_name_union | ||
1079 | (const struct tomoyo_name_union *a, const struct tomoyo_name_union *b) | ||
986 | { | 1080 | { |
987 | return p1->type == p2->type; | 1081 | return a->filename == b->filename && a->group == b->group; |
988 | } | 1082 | } |
989 | 1083 | ||
990 | static inline bool tomoyo_same_name_union | 1084 | /** |
991 | (const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2) | 1085 | * tomoyo_same_number_union - Check for duplicated "struct tomoyo_number_union" entry. |
1086 | * | ||
1087 | * @a: Pointer to "struct tomoyo_number_union". | ||
1088 | * @b: Pointer to "struct tomoyo_number_union". | ||
1089 | * | ||
1090 | * Returns true if @a == @b, false otherwise. | ||
1091 | */ | ||
1092 | static inline bool tomoyo_same_number_union | ||
1093 | (const struct tomoyo_number_union *a, const struct tomoyo_number_union *b) | ||
992 | { | 1094 | { |
993 | return p1->filename == p2->filename && p1->group == p2->group && | 1095 | return a->values[0] == b->values[0] && a->values[1] == b->values[1] && |
994 | p1->is_group == p2->is_group; | 1096 | a->group == b->group && a->value_type[0] == b->value_type[0] && |
1097 | a->value_type[1] == b->value_type[1]; | ||
995 | } | 1098 | } |
996 | 1099 | ||
997 | static inline bool tomoyo_same_number_union | 1100 | /** |
998 | (const struct tomoyo_number_union *p1, const struct tomoyo_number_union *p2) | 1101 | * tomoyo_current_namespace - Get "struct tomoyo_policy_namespace" for current thread. |
1102 | * | ||
1103 | * Returns pointer to "struct tomoyo_policy_namespace" for current thread. | ||
1104 | */ | ||
1105 | static inline struct tomoyo_policy_namespace *tomoyo_current_namespace(void) | ||
1106 | { | ||
1107 | return tomoyo_domain()->ns; | ||
1108 | } | ||
1109 | |||
1110 | #if defined(CONFIG_SLOB) | ||
1111 | |||
1112 | /** | ||
1113 | * tomoyo_round2 - Round up to power of 2 for calculating memory usage. | ||
1114 | * | ||
1115 | * @size: Size to be rounded up. | ||
1116 | * | ||
1117 | * Returns @size. | ||
1118 | * | ||
1119 | * Since SLOB does not round up, this function simply returns @size. | ||
1120 | */ | ||
1121 | static inline int tomoyo_round2(size_t size) | ||
1122 | { | ||
1123 | return size; | ||
1124 | } | ||
1125 | |||
1126 | #else | ||
1127 | |||
1128 | /** | ||
1129 | * tomoyo_round2 - Round up to power of 2 for calculating memory usage. | ||
1130 | * | ||
1131 | * @size: Size to be rounded up. | ||
1132 | * | ||
1133 | * Returns rounded size. | ||
1134 | * | ||
1135 | * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of | ||
1136 | * (e.g.) 128 bytes. | ||
1137 | */ | ||
1138 | static inline int tomoyo_round2(size_t size) | ||
999 | { | 1139 | { |
1000 | return p1->values[0] == p2->values[0] && p1->values[1] == p2->values[1] | 1140 | #if PAGE_SIZE == 4096 |
1001 | && p1->group == p2->group && p1->min_type == p2->min_type && | 1141 | size_t bsize = 32; |
1002 | p1->max_type == p2->max_type && p1->is_group == p2->is_group; | 1142 | #else |
1143 | size_t bsize = 64; | ||
1144 | #endif | ||
1145 | if (!size) | ||
1146 | return 0; | ||
1147 | while (size > bsize) | ||
1148 | bsize <<= 1; | ||
1149 | return bsize; | ||
1003 | } | 1150 | } |
1004 | 1151 | ||
1152 | #endif | ||
1153 | |||
1005 | /** | 1154 | /** |
1006 | * list_for_each_cookie - iterate over a list with cookie. | 1155 | * list_for_each_cookie - iterate over a list with cookie. |
1007 | * @pos: the &struct list_head to use as a loop cursor. | 1156 | * @pos: the &struct list_head to use as a loop cursor. |