オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /trunk/1.8.x/ccs-patch/security/ccsecurity/policy_io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6183 - (show annotations) (download) (as text)
Tue Jan 15 11:33:06 2013 UTC (11 years, 4 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 176414 byte(s)


1 /*
2 * security/ccsecurity/policy_io.c
3 *
4 * Copyright (C) 2005-2012 NTT DATA CORPORATION
5 *
6 * Version: 1.8.3+ 2012/05/05
7 */
8
9 #include "internal.h"
10
11 /***** SECTION1: Constants definition *****/
12
13 /* Define this to enable debug mode. */
14 /* #define DEBUG_CONDITION */
15
16 #ifdef DEBUG_CONDITION
17 #define dprintk printk
18 #else
19 #define dprintk(...) do { } while (0)
20 #endif
21
22 /* Mapping table from "enum ccs_mac_index" to "enum ccs_mac_category_index". */
23 static const u8 ccs_index2category[CCS_MAX_MAC_INDEX] = {
24 /* CONFIG::file group */
25 [CCS_MAC_FILE_EXECUTE] = CCS_MAC_CATEGORY_FILE,
26 [CCS_MAC_FILE_OPEN] = CCS_MAC_CATEGORY_FILE,
27 [CCS_MAC_FILE_CREATE] = CCS_MAC_CATEGORY_FILE,
28 [CCS_MAC_FILE_UNLINK] = CCS_MAC_CATEGORY_FILE,
29 #ifdef CONFIG_CCSECURITY_FILE_GETATTR
30 [CCS_MAC_FILE_GETATTR] = CCS_MAC_CATEGORY_FILE,
31 #endif
32 [CCS_MAC_FILE_MKDIR] = CCS_MAC_CATEGORY_FILE,
33 [CCS_MAC_FILE_RMDIR] = CCS_MAC_CATEGORY_FILE,
34 [CCS_MAC_FILE_MKFIFO] = CCS_MAC_CATEGORY_FILE,
35 [CCS_MAC_FILE_MKSOCK] = CCS_MAC_CATEGORY_FILE,
36 [CCS_MAC_FILE_TRUNCATE] = CCS_MAC_CATEGORY_FILE,
37 [CCS_MAC_FILE_SYMLINK] = CCS_MAC_CATEGORY_FILE,
38 [CCS_MAC_FILE_MKBLOCK] = CCS_MAC_CATEGORY_FILE,
39 [CCS_MAC_FILE_MKCHAR] = CCS_MAC_CATEGORY_FILE,
40 [CCS_MAC_FILE_LINK] = CCS_MAC_CATEGORY_FILE,
41 [CCS_MAC_FILE_RENAME] = CCS_MAC_CATEGORY_FILE,
42 [CCS_MAC_FILE_CHMOD] = CCS_MAC_CATEGORY_FILE,
43 [CCS_MAC_FILE_CHOWN] = CCS_MAC_CATEGORY_FILE,
44 [CCS_MAC_FILE_CHGRP] = CCS_MAC_CATEGORY_FILE,
45 [CCS_MAC_FILE_IOCTL] = CCS_MAC_CATEGORY_FILE,
46 [CCS_MAC_FILE_CHROOT] = CCS_MAC_CATEGORY_FILE,
47 [CCS_MAC_FILE_MOUNT] = CCS_MAC_CATEGORY_FILE,
48 [CCS_MAC_FILE_UMOUNT] = CCS_MAC_CATEGORY_FILE,
49 [CCS_MAC_FILE_PIVOT_ROOT] = CCS_MAC_CATEGORY_FILE,
50 #ifdef CONFIG_CCSECURITY_MISC
51 /* CONFIG::misc group */
52 [CCS_MAC_ENVIRON] = CCS_MAC_CATEGORY_MISC,
53 #endif
54 #ifdef CONFIG_CCSECURITY_NETWORK
55 /* CONFIG::network group */
56 [CCS_MAC_NETWORK_INET_STREAM_BIND] = CCS_MAC_CATEGORY_NETWORK,
57 [CCS_MAC_NETWORK_INET_STREAM_LISTEN] = CCS_MAC_CATEGORY_NETWORK,
58 [CCS_MAC_NETWORK_INET_STREAM_CONNECT] = CCS_MAC_CATEGORY_NETWORK,
59 [CCS_MAC_NETWORK_INET_STREAM_ACCEPT] = CCS_MAC_CATEGORY_NETWORK,
60 [CCS_MAC_NETWORK_INET_DGRAM_BIND] = CCS_MAC_CATEGORY_NETWORK,
61 [CCS_MAC_NETWORK_INET_DGRAM_SEND] = CCS_MAC_CATEGORY_NETWORK,
62 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
63 [CCS_MAC_NETWORK_INET_DGRAM_RECV] = CCS_MAC_CATEGORY_NETWORK,
64 #endif
65 [CCS_MAC_NETWORK_INET_RAW_BIND] = CCS_MAC_CATEGORY_NETWORK,
66 [CCS_MAC_NETWORK_INET_RAW_SEND] = CCS_MAC_CATEGORY_NETWORK,
67 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
68 [CCS_MAC_NETWORK_INET_RAW_RECV] = CCS_MAC_CATEGORY_NETWORK,
69 #endif
70 [CCS_MAC_NETWORK_UNIX_STREAM_BIND] = CCS_MAC_CATEGORY_NETWORK,
71 [CCS_MAC_NETWORK_UNIX_STREAM_LISTEN] = CCS_MAC_CATEGORY_NETWORK,
72 [CCS_MAC_NETWORK_UNIX_STREAM_CONNECT] = CCS_MAC_CATEGORY_NETWORK,
73 [CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT] = CCS_MAC_CATEGORY_NETWORK,
74 [CCS_MAC_NETWORK_UNIX_DGRAM_BIND] = CCS_MAC_CATEGORY_NETWORK,
75 [CCS_MAC_NETWORK_UNIX_DGRAM_SEND] = CCS_MAC_CATEGORY_NETWORK,
76 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
77 [CCS_MAC_NETWORK_UNIX_DGRAM_RECV] = CCS_MAC_CATEGORY_NETWORK,
78 #endif
79 [CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND] = CCS_MAC_CATEGORY_NETWORK,
80 [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = CCS_MAC_CATEGORY_NETWORK,
81 [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = CCS_MAC_CATEGORY_NETWORK,
82 [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT] = CCS_MAC_CATEGORY_NETWORK,
83 #endif
84 #ifdef CONFIG_CCSECURITY_IPC
85 /* CONFIG::ipc group */
86 [CCS_MAC_SIGNAL] = CCS_MAC_CATEGORY_IPC,
87 #endif
88 #ifdef CONFIG_CCSECURITY_CAPABILITY
89 /* CONFIG::capability group */
90 [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET] = CCS_MAC_CATEGORY_CAPABILITY,
91 [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = CCS_MAC_CATEGORY_CAPABILITY,
92 [CCS_MAC_CAPABILITY_SYS_REBOOT] = CCS_MAC_CATEGORY_CAPABILITY,
93 [CCS_MAC_CAPABILITY_SYS_VHANGUP] = CCS_MAC_CATEGORY_CAPABILITY,
94 [CCS_MAC_CAPABILITY_SYS_SETTIME] = CCS_MAC_CATEGORY_CAPABILITY,
95 [CCS_MAC_CAPABILITY_SYS_NICE] = CCS_MAC_CATEGORY_CAPABILITY,
96 [CCS_MAC_CAPABILITY_SYS_SETHOSTNAME] = CCS_MAC_CATEGORY_CAPABILITY,
97 [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = CCS_MAC_CATEGORY_CAPABILITY,
98 [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD] = CCS_MAC_CATEGORY_CAPABILITY,
99 [CCS_MAC_CAPABILITY_SYS_PTRACE] = CCS_MAC_CATEGORY_CAPABILITY,
100 #endif
101 };
102
103 /* String table for operation mode. */
104 static const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {
105 [CCS_CONFIG_DISABLED] = "disabled",
106 [CCS_CONFIG_LEARNING] = "learning",
107 [CCS_CONFIG_PERMISSIVE] = "permissive",
108 [CCS_CONFIG_ENFORCING] = "enforcing"
109 };
110
111 /* String table for /proc/ccs/profile interface. */
112 static const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX
113 + CCS_MAX_MAC_CATEGORY_INDEX] = {
114 /* CONFIG::file group */
115 [CCS_MAC_FILE_EXECUTE] = "execute",
116 [CCS_MAC_FILE_OPEN] = "open",
117 [CCS_MAC_FILE_CREATE] = "create",
118 [CCS_MAC_FILE_UNLINK] = "unlink",
119 #ifdef CONFIG_CCSECURITY_FILE_GETATTR
120 [CCS_MAC_FILE_GETATTR] = "getattr",
121 #endif
122 [CCS_MAC_FILE_MKDIR] = "mkdir",
123 [CCS_MAC_FILE_RMDIR] = "rmdir",
124 [CCS_MAC_FILE_MKFIFO] = "mkfifo",
125 [CCS_MAC_FILE_MKSOCK] = "mksock",
126 [CCS_MAC_FILE_TRUNCATE] = "truncate",
127 [CCS_MAC_FILE_SYMLINK] = "symlink",
128 [CCS_MAC_FILE_MKBLOCK] = "mkblock",
129 [CCS_MAC_FILE_MKCHAR] = "mkchar",
130 [CCS_MAC_FILE_LINK] = "link",
131 [CCS_MAC_FILE_RENAME] = "rename",
132 [CCS_MAC_FILE_CHMOD] = "chmod",
133 [CCS_MAC_FILE_CHOWN] = "chown",
134 [CCS_MAC_FILE_CHGRP] = "chgrp",
135 [CCS_MAC_FILE_IOCTL] = "ioctl",
136 [CCS_MAC_FILE_CHROOT] = "chroot",
137 [CCS_MAC_FILE_MOUNT] = "mount",
138 [CCS_MAC_FILE_UMOUNT] = "unmount",
139 [CCS_MAC_FILE_PIVOT_ROOT] = "pivot_root",
140 #ifdef CONFIG_CCSECURITY_MISC
141 /* CONFIG::misc group */
142 [CCS_MAC_ENVIRON] = "env",
143 #endif
144 #ifdef CONFIG_CCSECURITY_NETWORK
145 /* CONFIG::network group */
146 [CCS_MAC_NETWORK_INET_STREAM_BIND] = "inet_stream_bind",
147 [CCS_MAC_NETWORK_INET_STREAM_LISTEN] = "inet_stream_listen",
148 [CCS_MAC_NETWORK_INET_STREAM_CONNECT] = "inet_stream_connect",
149 [CCS_MAC_NETWORK_INET_STREAM_ACCEPT] = "inet_stream_accept",
150 [CCS_MAC_NETWORK_INET_DGRAM_BIND] = "inet_dgram_bind",
151 [CCS_MAC_NETWORK_INET_DGRAM_SEND] = "inet_dgram_send",
152 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
153 [CCS_MAC_NETWORK_INET_DGRAM_RECV] = "inet_dgram_recv",
154 #endif
155 [CCS_MAC_NETWORK_INET_RAW_BIND] = "inet_raw_bind",
156 [CCS_MAC_NETWORK_INET_RAW_SEND] = "inet_raw_send",
157 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
158 [CCS_MAC_NETWORK_INET_RAW_RECV] = "inet_raw_recv",
159 #endif
160 [CCS_MAC_NETWORK_UNIX_STREAM_BIND] = "unix_stream_bind",
161 [CCS_MAC_NETWORK_UNIX_STREAM_LISTEN] = "unix_stream_listen",
162 [CCS_MAC_NETWORK_UNIX_STREAM_CONNECT] = "unix_stream_connect",
163 [CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT] = "unix_stream_accept",
164 [CCS_MAC_NETWORK_UNIX_DGRAM_BIND] = "unix_dgram_bind",
165 [CCS_MAC_NETWORK_UNIX_DGRAM_SEND] = "unix_dgram_send",
166 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
167 [CCS_MAC_NETWORK_UNIX_DGRAM_RECV] = "unix_dgram_recv",
168 #endif
169 [CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND] = "unix_seqpacket_bind",
170 [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = "unix_seqpacket_listen",
171 [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect",
172 [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT] = "unix_seqpacket_accept",
173 #endif
174 #ifdef CONFIG_CCSECURITY_IPC
175 /* CONFIG::ipc group */
176 [CCS_MAC_SIGNAL] = "signal",
177 #endif
178 #ifdef CONFIG_CCSECURITY_CAPABILITY
179 /* CONFIG::capability group */
180 [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET] = "use_route",
181 [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = "use_packet",
182 [CCS_MAC_CAPABILITY_SYS_REBOOT] = "SYS_REBOOT",
183 [CCS_MAC_CAPABILITY_SYS_VHANGUP] = "SYS_VHANGUP",
184 [CCS_MAC_CAPABILITY_SYS_SETTIME] = "SYS_TIME",
185 [CCS_MAC_CAPABILITY_SYS_NICE] = "SYS_NICE",
186 [CCS_MAC_CAPABILITY_SYS_SETHOSTNAME] = "SYS_SETHOSTNAME",
187 [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = "use_kernel_module",
188 [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD] = "SYS_KEXEC_LOAD",
189 [CCS_MAC_CAPABILITY_SYS_PTRACE] = "SYS_PTRACE",
190 #endif
191 /* CONFIG group */
192 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_FILE] = "file",
193 #ifdef CONFIG_CCSECURITY_NETWORK
194 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_NETWORK] = "network",
195 #endif
196 #ifdef CONFIG_CCSECURITY_MISC
197 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_MISC] = "misc",
198 #endif
199 #ifdef CONFIG_CCSECURITY_IPC
200 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_IPC] = "ipc",
201 #endif
202 #ifdef CONFIG_CCSECURITY_CAPABILITY
203 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
204 #endif
205 };
206
207 /* String table for path operation. */
208 static const char * const ccs_path_keyword[CCS_MAX_PATH_OPERATION] = {
209 [CCS_TYPE_EXECUTE] = "execute",
210 [CCS_TYPE_READ] = "read",
211 [CCS_TYPE_WRITE] = "write",
212 [CCS_TYPE_APPEND] = "append",
213 [CCS_TYPE_UNLINK] = "unlink",
214 #ifdef CONFIG_CCSECURITY_FILE_GETATTR
215 [CCS_TYPE_GETATTR] = "getattr",
216 #endif
217 [CCS_TYPE_RMDIR] = "rmdir",
218 [CCS_TYPE_TRUNCATE] = "truncate",
219 [CCS_TYPE_SYMLINK] = "symlink",
220 [CCS_TYPE_CHROOT] = "chroot",
221 [CCS_TYPE_UMOUNT] = "unmount",
222 };
223
224 #ifdef CONFIG_CCSECURITY_NETWORK
225
226 /* String table for socket's operation. */
227 static const char * const ccs_socket_keyword[CCS_MAX_NETWORK_OPERATION] = {
228 [CCS_NETWORK_BIND] = "bind",
229 [CCS_NETWORK_LISTEN] = "listen",
230 [CCS_NETWORK_CONNECT] = "connect",
231 [CCS_NETWORK_ACCEPT] = "accept",
232 [CCS_NETWORK_SEND] = "send",
233 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
234 [CCS_NETWORK_RECV] = "recv",
235 #endif
236 };
237
238 /* String table for socket's protocols. */
239 static const char * const ccs_proto_keyword[CCS_SOCK_MAX] = {
240 [SOCK_STREAM] = "stream",
241 [SOCK_DGRAM] = "dgram",
242 [SOCK_RAW] = "raw",
243 [SOCK_SEQPACKET] = "seqpacket",
244 [0] = " ", /* Dummy for avoiding NULL pointer dereference. */
245 [4] = " ", /* Dummy for avoiding NULL pointer dereference. */
246 };
247
248 #endif
249
250 /* String table for categories. */
251 static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {
252 [CCS_MAC_CATEGORY_FILE] = "file",
253 #ifdef CONFIG_CCSECURITY_NETWORK
254 [CCS_MAC_CATEGORY_NETWORK] = "network",
255 #endif
256 #ifdef CONFIG_CCSECURITY_MISC
257 [CCS_MAC_CATEGORY_MISC] = "misc",
258 #endif
259 #ifdef CONFIG_CCSECURITY_IPC
260 [CCS_MAC_CATEGORY_IPC] = "ipc",
261 #endif
262 #ifdef CONFIG_CCSECURITY_CAPABILITY
263 [CCS_MAC_CATEGORY_CAPABILITY] = "capability",
264 #endif
265 };
266
267 /* String table for conditions. */
268 static const char * const ccs_condition_keyword[CCS_MAX_CONDITION_KEYWORD] = {
269 [CCS_TASK_UID] = "task.uid",
270 [CCS_TASK_EUID] = "task.euid",
271 [CCS_TASK_SUID] = "task.suid",
272 [CCS_TASK_FSUID] = "task.fsuid",
273 [CCS_TASK_GID] = "task.gid",
274 [CCS_TASK_EGID] = "task.egid",
275 [CCS_TASK_SGID] = "task.sgid",
276 [CCS_TASK_FSGID] = "task.fsgid",
277 [CCS_TASK_PID] = "task.pid",
278 [CCS_TASK_PPID] = "task.ppid",
279 [CCS_EXEC_ARGC] = "exec.argc",
280 [CCS_EXEC_ENVC] = "exec.envc",
281 [CCS_TYPE_IS_SOCKET] = "socket",
282 [CCS_TYPE_IS_SYMLINK] = "symlink",
283 [CCS_TYPE_IS_FILE] = "file",
284 [CCS_TYPE_IS_BLOCK_DEV] = "block",
285 [CCS_TYPE_IS_DIRECTORY] = "directory",
286 [CCS_TYPE_IS_CHAR_DEV] = "char",
287 [CCS_TYPE_IS_FIFO] = "fifo",
288 [CCS_MODE_SETUID] = "setuid",
289 [CCS_MODE_SETGID] = "setgid",
290 [CCS_MODE_STICKY] = "sticky",
291 [CCS_MODE_OWNER_READ] = "owner_read",
292 [CCS_MODE_OWNER_WRITE] = "owner_write",
293 [CCS_MODE_OWNER_EXECUTE] = "owner_execute",
294 [CCS_MODE_GROUP_READ] = "group_read",
295 [CCS_MODE_GROUP_WRITE] = "group_write",
296 [CCS_MODE_GROUP_EXECUTE] = "group_execute",
297 [CCS_MODE_OTHERS_READ] = "others_read",
298 [CCS_MODE_OTHERS_WRITE] = "others_write",
299 [CCS_MODE_OTHERS_EXECUTE] = "others_execute",
300 [CCS_TASK_TYPE] = "task.type",
301 [CCS_TASK_EXECUTE_HANDLER] = "execute_handler",
302 [CCS_EXEC_REALPATH] = "exec.realpath",
303 [CCS_SYMLINK_TARGET] = "symlink.target",
304 [CCS_PATH1_UID] = "path1.uid",
305 [CCS_PATH1_GID] = "path1.gid",
306 [CCS_PATH1_INO] = "path1.ino",
307 [CCS_PATH1_MAJOR] = "path1.major",
308 [CCS_PATH1_MINOR] = "path1.minor",
309 [CCS_PATH1_PERM] = "path1.perm",
310 [CCS_PATH1_TYPE] = "path1.type",
311 [CCS_PATH1_DEV_MAJOR] = "path1.dev_major",
312 [CCS_PATH1_DEV_MINOR] = "path1.dev_minor",
313 [CCS_PATH2_UID] = "path2.uid",
314 [CCS_PATH2_GID] = "path2.gid",
315 [CCS_PATH2_INO] = "path2.ino",
316 [CCS_PATH2_MAJOR] = "path2.major",
317 [CCS_PATH2_MINOR] = "path2.minor",
318 [CCS_PATH2_PERM] = "path2.perm",
319 [CCS_PATH2_TYPE] = "path2.type",
320 [CCS_PATH2_DEV_MAJOR] = "path2.dev_major",
321 [CCS_PATH2_DEV_MINOR] = "path2.dev_minor",
322 [CCS_PATH1_PARENT_UID] = "path1.parent.uid",
323 [CCS_PATH1_PARENT_GID] = "path1.parent.gid",
324 [CCS_PATH1_PARENT_INO] = "path1.parent.ino",
325 [CCS_PATH1_PARENT_PERM] = "path1.parent.perm",
326 [CCS_PATH2_PARENT_UID] = "path2.parent.uid",
327 [CCS_PATH2_PARENT_GID] = "path2.parent.gid",
328 [CCS_PATH2_PARENT_INO] = "path2.parent.ino",
329 [CCS_PATH2_PARENT_PERM] = "path2.parent.perm",
330 };
331
332 /* String table for PREFERENCE keyword. */
333 static const char * const ccs_pref_keywords[CCS_MAX_PREF] = {
334 [CCS_PREF_MAX_AUDIT_LOG] = "max_audit_log",
335 [CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
336 [CCS_PREF_ENFORCING_PENALTY] = "enforcing_penalty",
337 };
338
339 /* String table for domain flags. */
340 const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
341 [CCS_DIF_QUOTA_WARNED] = "quota_exceeded\n",
342 [CCS_DIF_TRANSITION_FAILED] = "transition_failed\n",
343 };
344
345 /* String table for domain transition control keywords. */
346 static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
347 [CCS_TRANSITION_CONTROL_NO_RESET] = "no_reset_domain ",
348 [CCS_TRANSITION_CONTROL_RESET] = "reset_domain ",
349 [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
350 [CCS_TRANSITION_CONTROL_INITIALIZE] = "initialize_domain ",
351 [CCS_TRANSITION_CONTROL_NO_KEEP] = "no_keep_domain ",
352 [CCS_TRANSITION_CONTROL_KEEP] = "keep_domain ",
353 };
354
355 /* String table for grouping keywords. */
356 static const char * const ccs_group_name[CCS_MAX_GROUP] = {
357 [CCS_PATH_GROUP] = "path_group ",
358 [CCS_NUMBER_GROUP] = "number_group ",
359 #ifdef CONFIG_CCSECURITY_NETWORK
360 [CCS_ADDRESS_GROUP] = "address_group ",
361 #endif
362 };
363
364 /* String table for /proc/ccs/stat interface. */
365 static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {
366 [CCS_STAT_POLICY_UPDATES] = "update:",
367 [CCS_STAT_POLICY_LEARNING] = "violation in learning mode:",
368 [CCS_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:",
369 [CCS_STAT_POLICY_ENFORCING] = "violation in enforcing mode:",
370 };
371
372 /* String table for /proc/ccs/stat interface. */
373 static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
374 [CCS_MEMORY_POLICY] = "policy:",
375 [CCS_MEMORY_AUDIT] = "audit log:",
376 [CCS_MEMORY_QUERY] = "query message:",
377 };
378
379 /***** SECTION2: Structure definition *****/
380
381 struct iattr;
382
383 /* Structure for query. */
384 struct ccs_query {
385 struct list_head list;
386 struct ccs_domain_info *domain;
387 char *query;
388 size_t query_len;
389 unsigned int serial;
390 u8 timer;
391 u8 answer;
392 u8 retry;
393 };
394
395 /* Structure for audit log. */
396 struct ccs_log {
397 struct list_head list;
398 char *log;
399 int size;
400 };
401
402 /***** SECTION3: Prototype definition section *****/
403
404 int ccs_audit_log(struct ccs_request_info *r);
405 struct ccs_domain_info *ccs_assign_domain(const char *domainname,
406 const bool transit);
407 u8 ccs_get_config(const u8 profile, const u8 index);
408 void ccs_transition_failed(const char *domainname);
409 void ccs_write_log(struct ccs_request_info *r, const char *fmt, ...);
410
411 static bool ccs_correct_domain(const unsigned char *domainname);
412 static bool ccs_correct_path(const char *filename);
413 static bool ccs_correct_word(const char *string);
414 static bool ccs_correct_word2(const char *string, size_t len);
415 static bool ccs_domain_def(const unsigned char *buffer);
416 static bool ccs_domain_quota_ok(struct ccs_request_info *r);
417 static bool ccs_flush(struct ccs_io_buffer *head);
418 static bool ccs_get_audit(const struct ccs_request_info *r);
419 static bool ccs_has_more_namespace(struct ccs_io_buffer *head);
420 static bool ccs_manager(void);
421 static bool ccs_namespace_jump(const char *domainname);
422 static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv);
423 static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp);
424 static bool ccs_parse_name_union(struct ccs_acl_param *param,
425 struct ccs_name_union *ptr);
426 static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param,
427 struct ccs_name_union *ptr);
428 static bool ccs_parse_number_union(struct ccs_acl_param *param,
429 struct ccs_number_union *ptr);
430 static bool ccs_permstr(const char *string, const char *keyword);
431 static bool ccs_print_condition(struct ccs_io_buffer *head,
432 const struct ccs_condition *cond);
433 static bool ccs_print_entry(struct ccs_io_buffer *head,
434 const struct ccs_acl_info *acl);
435 static bool ccs_print_group(struct ccs_io_buffer *head,
436 const struct ccs_group *group);
437 static bool ccs_read_acl(struct ccs_io_buffer *head, struct list_head *list);
438 static bool ccs_read_group(struct ccs_io_buffer *head, const int idx);
439 static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx);
440 static bool ccs_same_condition(const struct ccs_condition *a,
441 const struct ccs_condition *b);
442 static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data);
443 static bool ccs_set_lf(struct ccs_io_buffer *head);
444 static bool ccs_str_starts(char **src, const char *find);
445 static char *ccs_get_transit_preference(struct ccs_acl_param *param,
446 struct ccs_condition *e);
447 static char *ccs_init_log(struct ccs_request_info *r, int len, const char *fmt,
448 va_list args);
449 static char *ccs_print_bprm(struct linux_binprm *bprm,
450 struct ccs_page_dump *dump);
451 static char *ccs_print_header(struct ccs_request_info *r);
452 static char *ccs_read_token(struct ccs_acl_param *param);
453 static const char *ccs_yesno(const unsigned int value);
454 static const struct ccs_path_info *ccs_get_domainname
455 (struct ccs_acl_param *param);
456 static const struct ccs_path_info *ccs_get_dqword(char *start);
457 static int __init ccs_init_module(void);
458 static int ccs_delete_domain(char *domainname);
459 static int ccs_open(struct inode *inode, struct file *file);
460 static int ccs_parse_policy(struct ccs_io_buffer *head, char *line);
461 static int ccs_release(struct inode *inode, struct file *file);
462 static int ccs_set_mode(char *name, const char *value,
463 struct ccs_profile *profile);
464 static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
465 __printf(2, 3);
466 static int ccs_truncate(char *str);
467 static int ccs_update_acl(const int size, struct ccs_acl_param *param);
468 static int ccs_update_manager_entry(const char *manager, const bool is_delete);
469 static int ccs_update_policy(const int size, struct ccs_acl_param *param);
470 static int ccs_write_acl(struct ccs_policy_namespace *ns,
471 struct list_head *list, char *data,
472 const bool is_delete);
473 static int ccs_write_aggregator(struct ccs_acl_param *param);
474 static int ccs_write_answer(struct ccs_io_buffer *head);
475 static int ccs_write_domain(struct ccs_io_buffer *head);
476 static int ccs_write_exception(struct ccs_io_buffer *head);
477 static int ccs_write_file(struct ccs_acl_param *param);
478 static int ccs_write_group(struct ccs_acl_param *param, const u8 type);
479 static int ccs_write_manager(struct ccs_io_buffer *head);
480 static int ccs_write_pid(struct ccs_io_buffer *head);
481 static int ccs_write_profile(struct ccs_io_buffer *head);
482 static int ccs_write_stat(struct ccs_io_buffer *head);
483 static int ccs_write_task(struct ccs_acl_param *param);
484 static int ccs_write_transition_control(struct ccs_acl_param *param,
485 const u8 type);
486 static s8 ccs_find_yesno(const char *string, const char *find);
487 static ssize_t ccs_read(struct file *file, char __user *buf, size_t count,
488 loff_t *ppos);
489 static ssize_t ccs_read_self(struct file *file, char __user *buf, size_t count,
490 loff_t *ppos);
491 static ssize_t ccs_write(struct file *file, const char __user *buf,
492 size_t count, loff_t *ppos);
493 static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry);
494 static struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param);
495 static struct ccs_domain_info *ccs_find_domain(const char *domainname);
496 static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial);
497 static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
498 const u8 idx);
499 static struct ccs_policy_namespace *ccs_assign_namespace
500 (const char *domainname);
501 static struct ccs_policy_namespace *ccs_find_namespace(const char *name,
502 const unsigned int len);
503 static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
504 const unsigned int profile);
505 static struct ccs_profile *ccs_profile(const u8 profile);
506 static u8 ccs_condition_type(const char *word);
507 static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3);
508 static u8 ccs_parse_ulong(unsigned long *result, char **str);
509 static unsigned int ccs_poll(struct file *file, poll_table *wait);
510 static void __init ccs_create_entry(const char *name, const umode_t mode,
511 struct proc_dir_entry *parent,
512 const u8 key);
513 static void __init ccs_load_builtin_policy(void);
514 static void __init ccs_policy_io_init(void);
515 static void __init ccs_proc_init(void);
516 static void ccs_add_entry(char *header);
517 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
518 __printf(3, 4);
519 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...);
520 static void ccs_check_profile(void);
521 static void ccs_convert_time(time_t time, struct ccs_time *stamp);
522 static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns);
523 static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
524 __printf(2, 3);
525 static void ccs_normalize_line(unsigned char *buffer);
526 static void ccs_print_config(struct ccs_io_buffer *head, const u8 config);
527 static void ccs_print_name_union(struct ccs_io_buffer *head,
528 const struct ccs_name_union *ptr);
529 static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
530 const struct ccs_name_union *ptr);
531 static void ccs_print_namespace(struct ccs_io_buffer *head);
532 static void ccs_print_number_union(struct ccs_io_buffer *head,
533 const struct ccs_number_union *ptr);
534 static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
535 const struct ccs_number_union *ptr);
536 static void ccs_read_domain(struct ccs_io_buffer *head);
537 static void ccs_read_exception(struct ccs_io_buffer *head);
538 static void ccs_read_log(struct ccs_io_buffer *head);
539 static void ccs_read_manager(struct ccs_io_buffer *head);
540 static void ccs_read_pid(struct ccs_io_buffer *head);
541 static void ccs_read_profile(struct ccs_io_buffer *head);
542 static void ccs_read_query(struct ccs_io_buffer *head);
543 static void ccs_read_stat(struct ccs_io_buffer *head);
544 static void ccs_read_version(struct ccs_io_buffer *head);
545 static void ccs_set_group(struct ccs_io_buffer *head, const char *category);
546 static void ccs_set_namespace_cursor(struct ccs_io_buffer *head);
547 static void ccs_set_slash(struct ccs_io_buffer *head);
548 static void ccs_set_space(struct ccs_io_buffer *head);
549 static void ccs_set_string(struct ccs_io_buffer *head, const char *string);
550 static void ccs_set_uint(unsigned int *i, const char *string,
551 const char *find);
552 static void ccs_update_stat(const u8 index);
553 static void ccs_update_task_domain(struct ccs_request_info *r);
554 static void ccs_write_log2(struct ccs_request_info *r, int len,
555 const char *fmt, va_list args);
556
557 #ifdef CONFIG_CCSECURITY_PORTRESERVE
558 static bool __ccs_lport_reserved(const u16 port);
559 static int ccs_write_reserved_port(struct ccs_acl_param *param);
560 #endif
561
562 #ifdef CONFIG_CCSECURITY_NETWORK
563 static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
564 struct ccs_ipaddr_union *ptr);
565 static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
566 const u32 *ip);
567 static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
568 const struct in6_addr *ip);
569 static int ccs_write_inet_network(struct ccs_acl_param *param);
570 static int ccs_write_unix_network(struct ccs_acl_param *param);
571 static void ccs_print_ip(char *buf, const unsigned int size,
572 const struct ccs_ipaddr_union *ptr);
573 #endif
574
575 #ifdef CONFIG_CCSECURITY_CAPABILITY
576 static int ccs_write_capability(struct ccs_acl_param *param);
577 #endif
578
579 #ifdef CONFIG_CCSECURITY_MISC
580 static int ccs_write_misc(struct ccs_acl_param *param);
581 #endif
582
583 #ifdef CONFIG_CCSECURITY_IPC
584 static int ccs_write_ipc(struct ccs_acl_param *param);
585 #endif
586
587 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
588 static ssize_t ccs_write_self(struct file *file, const char __user *buf,
589 size_t count, loff_t *ppos);
590 #endif
591
592 /***** SECTION4: Standalone functions section *****/
593
594 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
595
596 /**
597 * fatal_signal_pending - Check whether SIGKILL is pending or not.
598 *
599 * @p: Pointer to "struct task_struct".
600 *
601 * Returns true if SIGKILL is pending on @p, false otherwise.
602 *
603 * This is for compatibility with older kernels.
604 */
605 #define fatal_signal_pending(p) (signal_pending(p) && \
606 sigismember(&p->pending.signal, SIGKILL))
607
608 #endif
609
610 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
611
612 /**
613 * __wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
614 *
615 * @wq: The waitqueue to wait on.
616 * @condition: A C expression for the event to wait for.
617 * @ret: Timeout, in jiffies.
618 *
619 * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
620 * signal, and the remaining jiffies otherwise if the condition evaluated to
621 * true before the timeout elapsed.
622 *
623 * This is for compatibility with older kernels.
624 */
625 #define __wait_event_interruptible_timeout(wq, condition, ret) \
626 do { \
627 wait_queue_t __wait; \
628 init_waitqueue_entry(&__wait, current); \
629 \
630 add_wait_queue(&wq, &__wait); \
631 for (;;) { \
632 set_current_state(TASK_INTERRUPTIBLE); \
633 if (condition) \
634 break; \
635 if (!signal_pending(current)) { \
636 ret = schedule_timeout(ret); \
637 if (!ret) \
638 break; \
639 continue; \
640 } \
641 ret = -ERESTARTSYS; \
642 break; \
643 } \
644 current->state = TASK_RUNNING; \
645 remove_wait_queue(&wq, &__wait); \
646 } while (0)
647
648 /**
649 * wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
650 *
651 * @wq: The waitqueue to wait on.
652 * @condition: A C expression for the event to wait for.
653 * @timeout: Timeout, in jiffies.
654 *
655 * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
656 * signal, and the remaining jiffies otherwise if the condition evaluated to
657 * true before the timeout elapsed.
658 *
659 * This is for compatibility with older kernels.
660 */
661 #define wait_event_interruptible_timeout(wq, condition, timeout) \
662 ({ \
663 long __ret = timeout; \
664 if (!(condition)) \
665 __wait_event_interruptible_timeout(wq, condition, __ret); \
666 __ret; \
667 })
668
669 #endif
670
671 /**
672 * ccs_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
673 *
674 * @time: Seconds since 1970/01/01 00:00:00.
675 * @stamp: Pointer to "struct ccs_time".
676 *
677 * Returns nothing.
678 *
679 * This function does not handle Y2038 problem.
680 */
681 static void ccs_convert_time(time_t time, struct ccs_time *stamp)
682 {
683 static const u16 ccs_eom[2][12] = {
684 { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
685 { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
686 };
687 u16 y;
688 u8 m;
689 bool r;
690 stamp->sec = time % 60;
691 time /= 60;
692 stamp->min = time % 60;
693 time /= 60;
694 stamp->hour = time % 24;
695 time /= 24;
696 for (y = 1970; ; y++) {
697 const unsigned short days = (y & 3) ? 365 : 366;
698 if (time < days)
699 break;
700 time -= days;
701 }
702 r = (y & 3) == 0;
703 for (m = 0; m < 11 && time >= ccs_eom[r][m]; m++);
704 if (m)
705 time -= ccs_eom[r][m - 1];
706 stamp->year = y;
707 stamp->month = ++m;
708 stamp->day = ++time;
709 }
710
711 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 23)
712 #if !defined(RHEL_VERSION) || RHEL_VERSION != 3
713
714 /**
715 * PDE - Get "struct proc_dir_entry".
716 *
717 * @inode: Pointer to "struct inode".
718 *
719 * Returns pointer to "struct proc_dir_entry".
720 *
721 * This is for compatibility with older kernels.
722 */
723 static inline struct proc_dir_entry *PDE(const struct inode *inode)
724 {
725 return (struct proc_dir_entry *) inode->u.generic_ip;
726 }
727
728 #endif
729 #endif
730
731 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
732
733 /**
734 * proc_notify_change - Update inode's attributes and reflect to the dentry.
735 *
736 * @dentry: Pointer to "struct dentry".
737 * @iattr: Pointer to "struct iattr".
738 *
739 * Returns 0 on success, negative value otherwise.
740 *
741 * The 2.4 kernels don't allow chmod()/chown() for files in /proc,
742 * while the 2.6 kernels allow.
743 * To permit management of /proc/ccs/ interface by non-root user,
744 * I modified to allow chmod()/chown() of /proc/ccs/ interface like 2.6 kernels
745 * by adding "struct inode_operations"->setattr hook.
746 */
747 static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
748 {
749 struct inode *inode = dentry->d_inode;
750 struct proc_dir_entry *de = PDE(inode);
751 int error;
752
753 error = inode_change_ok(inode, iattr);
754 if (error)
755 goto out;
756
757 error = inode_setattr(inode, iattr);
758 if (error)
759 goto out;
760
761 de->uid = inode->i_uid;
762 de->gid = inode->i_gid;
763 de->mode = inode->i_mode;
764 out:
765 return error;
766 }
767
768 #endif
769
770 #ifdef CONFIG_CCSECURITY_NETWORK
771
772 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && defined(CONFIG_NET)
773 #define ccs_in4_pton in4_pton
774 #define ccs_in6_pton in6_pton
775 #else
776 /*
777 * Routines for parsing IPv4 or IPv6 address.
778 * These are copied from lib/hexdump.c net/core/utils.c .
779 */
780 #include <linux/ctype.h>
781
782 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
783 static int hex_to_bin(char ch)
784 {
785 if ((ch >= '0') && (ch <= '9'))
786 return ch - '0';
787 ch = tolower(ch);
788 if ((ch >= 'a') && (ch <= 'f'))
789 return ch - 'a' + 10;
790 return -1;
791 }
792 #endif
793
794 #define IN6PTON_XDIGIT 0x00010000
795 #define IN6PTON_DIGIT 0x00020000
796 #define IN6PTON_COLON_MASK 0x00700000
797 #define IN6PTON_COLON_1 0x00100000 /* single : requested */
798 #define IN6PTON_COLON_2 0x00200000 /* second : requested */
799 #define IN6PTON_COLON_1_2 0x00400000 /* :: requested */
800 #define IN6PTON_DOT 0x00800000 /* . */
801 #define IN6PTON_DELIM 0x10000000
802 #define IN6PTON_NULL 0x20000000 /* first/tail */
803 #define IN6PTON_UNKNOWN 0x40000000
804
805 static inline int xdigit2bin(char c, int delim)
806 {
807 int val;
808
809 if (c == delim || c == '\0')
810 return IN6PTON_DELIM;
811 if (c == ':')
812 return IN6PTON_COLON_MASK;
813 if (c == '.')
814 return IN6PTON_DOT;
815
816 val = hex_to_bin(c);
817 if (val >= 0)
818 return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0);
819
820 if (delim == -1)
821 return IN6PTON_DELIM;
822 return IN6PTON_UNKNOWN;
823 }
824
825 static int ccs_in4_pton(const char *src, int srclen, u8 *dst, int delim,
826 const char **end)
827 {
828 const char *s;
829 u8 *d;
830 u8 dbuf[4];
831 int ret = 0;
832 int i;
833 int w = 0;
834
835 if (srclen < 0)
836 srclen = strlen(src);
837 s = src;
838 d = dbuf;
839 i = 0;
840 while (1) {
841 int c;
842 c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
843 if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM |
844 IN6PTON_COLON_MASK)))
845 goto out;
846 if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
847 if (w == 0)
848 goto out;
849 *d++ = w & 0xff;
850 w = 0;
851 i++;
852 if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
853 if (i != 4)
854 goto out;
855 break;
856 }
857 goto cont;
858 }
859 w = (w * 10) + c;
860 if ((w & 0xffff) > 255)
861 goto out;
862 cont:
863 if (i >= 4)
864 goto out;
865 s++;
866 srclen--;
867 }
868 ret = 1;
869 memcpy(dst, dbuf, sizeof(dbuf));
870 out:
871 if (end)
872 *end = s;
873 return ret;
874 }
875
876 static int ccs_in6_pton(const char *src, int srclen, u8 *dst, int delim,
877 const char **end)
878 {
879 const char *s, *tok = NULL;
880 u8 *d, *dc = NULL;
881 u8 dbuf[16];
882 int ret = 0;
883 int i;
884 int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL;
885 int w = 0;
886
887 memset(dbuf, 0, sizeof(dbuf));
888
889 s = src;
890 d = dbuf;
891 if (srclen < 0)
892 srclen = strlen(src);
893
894 while (1) {
895 int c;
896
897 c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
898 if (!(c & state))
899 goto out;
900 if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
901 /* process one 16-bit word */
902 if (!(state & IN6PTON_NULL)) {
903 *d++ = (w >> 8) & 0xff;
904 *d++ = w & 0xff;
905 }
906 w = 0;
907 if (c & IN6PTON_DELIM) {
908 /* We've processed last word */
909 break;
910 }
911 /*
912 * COLON_1 => XDIGIT
913 * COLON_2 => XDIGIT|DELIM
914 * COLON_1_2 => COLON_2
915 */
916 switch (state & IN6PTON_COLON_MASK) {
917 case IN6PTON_COLON_2:
918 dc = d;
919 state = IN6PTON_XDIGIT | IN6PTON_DELIM;
920 if (dc - dbuf >= sizeof(dbuf))
921 state |= IN6PTON_NULL;
922 break;
923 case IN6PTON_COLON_1|IN6PTON_COLON_1_2:
924 state = IN6PTON_XDIGIT | IN6PTON_COLON_2;
925 break;
926 case IN6PTON_COLON_1:
927 state = IN6PTON_XDIGIT;
928 break;
929 case IN6PTON_COLON_1_2:
930 state = IN6PTON_COLON_2;
931 break;
932 default:
933 state = 0;
934 }
935 tok = s + 1;
936 goto cont;
937 }
938
939 if (c & IN6PTON_DOT) {
940 ret = ccs_in4_pton(tok ? tok : s, srclen +
941 (int)(s - tok), d, delim, &s);
942 if (ret > 0) {
943 d += 4;
944 break;
945 }
946 goto out;
947 }
948
949 w = (w << 4) | (0xff & c);
950 state = IN6PTON_COLON_1 | IN6PTON_DELIM;
951 if (!(w & 0xf000))
952 state |= IN6PTON_XDIGIT;
953 if (!dc && d + 2 < dbuf + sizeof(dbuf)) {
954 state |= IN6PTON_COLON_1_2;
955 state &= ~IN6PTON_DELIM;
956 }
957 if (d + 2 >= dbuf + sizeof(dbuf))
958 state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2);
959 cont:
960 if ((dc && d + 4 < dbuf + sizeof(dbuf)) ||
961 d + 4 == dbuf + sizeof(dbuf))
962 state |= IN6PTON_DOT;
963 if (d >= dbuf + sizeof(dbuf))
964 state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK);
965 s++;
966 srclen--;
967 }
968
969 i = 15; d--;
970
971 if (dc) {
972 while (d >= dc)
973 dst[i--] = *d--;
974 while (i >= dc - dbuf)
975 dst[i--] = 0;
976 while (i >= 0)
977 dst[i--] = *d--;
978 } else
979 memcpy(dst, dbuf, sizeof(dbuf));
980
981 ret = 1;
982 out:
983 if (end)
984 *end = s;
985 return ret;
986 }
987 #endif
988
989 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
990
991 /*
992 * Routines for printing IPv4 or IPv6 address.
993 * These are copied from include/linux/kernel.h include/net/ipv6.h
994 * include/net/addrconf.h lib/hexdump.c lib/vsprintf.c and simplified.
995 */
996 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
997 #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5 || !defined(RHEL_MINOR) || RHEL_MINOR < 9
998 static const char hex_asc[] = "0123456789abcdef";
999 #define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
1000 #define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
1001
1002 static inline char *pack_hex_byte(char *buf, u8 byte)
1003 {
1004 *buf++ = hex_asc_hi(byte);
1005 *buf++ = hex_asc_lo(byte);
1006 return buf;
1007 }
1008 #endif
1009 #endif
1010
1011 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1012 static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
1013 {
1014 return (a->s6_addr32[0] | a->s6_addr32[1] |
1015 (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0;
1016 }
1017 #endif
1018
1019 static inline int ipv6_addr_is_isatap(const struct in6_addr *addr)
1020 {
1021 return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
1022 }
1023
1024 static char *ip4_string(char *p, const u8 *addr)
1025 {
1026 /*
1027 * Since this function is called outside vsnprintf(), I can use
1028 * sprintf() here.
1029 */
1030 return p +
1031 sprintf(p, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
1032 }
1033
1034 static char *ip6_compressed_string(char *p, const char *addr)
1035 {
1036 int i, j, range;
1037 unsigned char zerolength[8];
1038 int longest = 1;
1039 int colonpos = -1;
1040 u16 word;
1041 u8 hi, lo;
1042 bool needcolon = false;
1043 bool useIPv4;
1044 struct in6_addr in6;
1045
1046 memcpy(&in6, addr, sizeof(struct in6_addr));
1047
1048 useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
1049
1050 memset(zerolength, 0, sizeof(zerolength));
1051
1052 if (useIPv4)
1053 range = 6;
1054 else
1055 range = 8;
1056
1057 /* find position of longest 0 run */
1058 for (i = 0; i < range; i++) {
1059 for (j = i; j < range; j++) {
1060 if (in6.s6_addr16[j] != 0)
1061 break;
1062 zerolength[i]++;
1063 }
1064 }
1065 for (i = 0; i < range; i++) {
1066 if (zerolength[i] > longest) {
1067 longest = zerolength[i];
1068 colonpos = i;
1069 }
1070 }
1071 if (longest == 1) /* don't compress a single 0 */
1072 colonpos = -1;
1073
1074 /* emit address */
1075 for (i = 0; i < range; i++) {
1076 if (i == colonpos) {
1077 if (needcolon || i == 0)
1078 *p++ = ':';
1079 *p++ = ':';
1080 needcolon = false;
1081 i += longest - 1;
1082 continue;
1083 }
1084 if (needcolon) {
1085 *p++ = ':';
1086 needcolon = false;
1087 }
1088 /* hex u16 without leading 0s */
1089 word = ntohs(in6.s6_addr16[i]);
1090 hi = word >> 8;
1091 lo = word & 0xff;
1092 if (hi) {
1093 if (hi > 0x0f)
1094 p = pack_hex_byte(p, hi);
1095 else
1096 *p++ = hex_asc_lo(hi);
1097 p = pack_hex_byte(p, lo);
1098 } else if (lo > 0x0f)
1099 p = pack_hex_byte(p, lo);
1100 else
1101 *p++ = hex_asc_lo(lo);
1102 needcolon = true;
1103 }
1104
1105 if (useIPv4) {
1106 if (needcolon)
1107 *p++ = ':';
1108 p = ip4_string(p, &in6.s6_addr[12]);
1109 }
1110 *p = '\0';
1111
1112 return p;
1113 }
1114 #endif
1115
1116 /**
1117 * ccs_print_ipv4 - Print an IPv4 address.
1118 *
1119 * @buffer: Buffer to write to.
1120 * @buffer_len: Size of @buffer.
1121 * @ip: Pointer to "u32 in network byte order".
1122 *
1123 * Returns written length.
1124 */
1125 static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
1126 const u32 *ip)
1127 {
1128 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
1129 return snprintf(buffer, buffer_len, "%pI4", ip);
1130 #else
1131 char addr[sizeof("255.255.255.255")];
1132 ip4_string(addr, (const u8 *) ip);
1133 return snprintf(buffer, buffer_len, "%s", addr);
1134 #endif
1135 }
1136
1137 /**
1138 * ccs_print_ipv6 - Print an IPv6 address.
1139 *
1140 * @buffer: Buffer to write to.
1141 * @buffer_len: Size of @buffer.
1142 * @ip: Pointer to "struct in6_addr".
1143 *
1144 * Returns written length.
1145 */
1146 static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
1147 const struct in6_addr *ip)
1148 {
1149 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
1150 return snprintf(buffer, buffer_len, "%pI6c", ip);
1151 #else
1152 char addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
1153 ip6_compressed_string(addr, (const u8 *) ip);
1154 return snprintf(buffer, buffer_len, "%s", addr);
1155 #endif
1156 }
1157
1158 /**
1159 * ccs_print_ip - Print an IP address.
1160 *
1161 * @buf: Buffer to write to.
1162 * @size: Size of @buf.
1163 * @ptr: Pointer to "struct ipaddr_union".
1164 *
1165 * Returns nothing.
1166 */
1167 static void ccs_print_ip(char *buf, const unsigned int size,
1168 const struct ccs_ipaddr_union *ptr)
1169 {
1170 int len;
1171 if (ptr->is_ipv6)
1172 len = ccs_print_ipv6(buf, size, &ptr->ip[0]);
1173 else
1174 len = ccs_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0]);
1175 if (!memcmp(&ptr->ip[0], &ptr->ip[1], 16) || len >= size / 2)
1176 return;
1177 buf[len++] = '-';
1178 if (ptr->is_ipv6)
1179 ccs_print_ipv6(buf + len, size - len, &ptr->ip[1]);
1180 else
1181 ccs_print_ipv4(buf + len, size - len,
1182 &ptr->ip[1].s6_addr32[0]);
1183 }
1184
1185 #endif
1186
1187 /***** SECTION5: Variables definition section *****/
1188
1189 /* Permit policy management by non-root user? */
1190 static bool ccs_manage_by_non_root;
1191
1192 /* Lock for protecting policy. */
1193 DEFINE_MUTEX(ccs_policy_lock);
1194
1195 /* Has /sbin/init started? */
1196 bool ccs_policy_loaded;
1197
1198 /* List of namespaces. */
1199 LIST_HEAD(ccs_namespace_list);
1200 /* True if namespace other than ccs_kernel_namespace is defined. */
1201 static bool ccs_namespace_enabled;
1202
1203 /* Initial namespace.*/
1204 static struct ccs_policy_namespace ccs_kernel_namespace;
1205
1206 /* List of "struct ccs_condition". */
1207 LIST_HEAD(ccs_condition_list);
1208
1209 #ifdef CONFIG_CCSECURITY_PORTRESERVE
1210 /* Bitmap for reserved local port numbers.*/
1211 static u8 ccs_reserved_port_map[8192];
1212 #endif
1213
1214 /* Wait queue for kernel -> userspace notification. */
1215 static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1216 /* Wait queue for userspace -> kernel notification. */
1217 static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);
1218
1219 /* The list for "struct ccs_query". */
1220 static LIST_HEAD(ccs_query_list);
1221
1222 /* Lock for manipulating ccs_query_list. */
1223 static DEFINE_SPINLOCK(ccs_query_list_lock);
1224
1225 /* Number of "struct file" referring /proc/ccs/query interface. */
1226 static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1227
1228 /* Wait queue for /proc/ccs/audit. */
1229 static DECLARE_WAIT_QUEUE_HEAD(ccs_log_wait);
1230
1231 /* The list for "struct ccs_log". */
1232 static LIST_HEAD(ccs_log);
1233
1234 /* Lock for "struct list_head ccs_log". */
1235 static DEFINE_SPINLOCK(ccs_log_lock);
1236
1237 /* Length of "stuct list_head ccs_log". */
1238 static unsigned int ccs_log_count;
1239
1240 /* Timestamp counter for last updated. */
1241 static unsigned int ccs_stat_updated[CCS_MAX_POLICY_STAT];
1242
1243 /* Counter for number of updates. */
1244 static unsigned int ccs_stat_modified[CCS_MAX_POLICY_STAT];
1245
1246 /* Operations for /proc/ccs/self_domain interface. */
1247 static
1248 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
1249 const
1250 #endif
1251 struct file_operations ccs_self_operations = {
1252 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
1253 .write = ccs_write_self,
1254 #endif
1255 .read = ccs_read_self,
1256 };
1257
1258 /* Operations for /proc/ccs/ interface. */
1259 static
1260 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
1261 const
1262 #endif
1263 struct file_operations ccs_operations = {
1264 .open = ccs_open,
1265 .release = ccs_release,
1266 .poll = ccs_poll,
1267 .read = ccs_read,
1268 .write = ccs_write,
1269 };
1270
1271 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
1272
1273 /* The inode operations for /proc/ccs/ directory. */
1274 static struct inode_operations ccs_dir_inode_operations;
1275
1276 /* The inode operations for files under /proc/ccs/ directory. */
1277 static struct inode_operations ccs_file_inode_operations;
1278
1279 #endif
1280
1281 /***** SECTION6: Dependent functions section *****/
1282
1283 /**
1284 * list_for_each_cookie - iterate over a list with cookie.
1285 *
1286 * @pos: Pointer to "struct list_head".
1287 * @head: Pointer to "struct list_head".
1288 */
1289 #define list_for_each_cookie(pos, head) \
1290 for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \
1291 pos != (head); pos = srcu_dereference(pos->next, &ccs_ss))
1292
1293 /**
1294 * ccs_read_token - Read a word from a line.
1295 *
1296 * @param: Pointer to "struct ccs_acl_param".
1297 *
1298 * Returns a word on success, "" otherwise.
1299 *
1300 * To allow the caller to skip NULL check, this function returns "" rather than
1301 * NULL if there is no more words to read.
1302 */
1303 static char *ccs_read_token(struct ccs_acl_param *param)
1304 {
1305 char *pos = param->data;
1306 char *del = strchr(pos, ' ');
1307 if (del)
1308 *del++ = '\0';
1309 else
1310 del = pos + strlen(pos);
1311 param->data = del;
1312 return pos;
1313 }
1314
1315 /**
1316 * ccs_make_byte - Make byte value from three octal characters.
1317 *
1318 * @c1: The first character.
1319 * @c2: The second character.
1320 * @c3: The third character.
1321 *
1322 * Returns byte value.
1323 */
1324 static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3)
1325 {
1326 return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
1327 }
1328
1329 /**
1330 * ccs_correct_word2 - Check whether the given string follows the naming rules.
1331 *
1332 * @string: The byte sequence to check. Not '\0'-terminated.
1333 * @len: Length of @string.
1334 *
1335 * Returns true if @string follows the naming rules, false otherwise.
1336 */
1337 static bool ccs_correct_word2(const char *string, size_t len)
1338 {
1339 const char *const start = string;
1340 bool in_repetition = false;
1341 unsigned char c;
1342 unsigned char d;
1343 unsigned char e;
1344 if (!len)
1345 goto out;
1346 while (len--) {
1347 c = *string++;
1348 if (c == '\\') {
1349 if (!len--)
1350 goto out;
1351 c = *string++;
1352 switch (c) {
1353 case '\\': /* "\\" */
1354 continue;
1355 case '$': /* "\$" */
1356 case '+': /* "\+" */
1357 case '?': /* "\?" */
1358 case '*': /* "\*" */
1359 case '@': /* "\@" */
1360 case 'x': /* "\x" */
1361 case 'X': /* "\X" */
1362 case 'a': /* "\a" */
1363 case 'A': /* "\A" */
1364 case '-': /* "\-" */
1365 continue;
1366 case '{': /* "/\{" */
1367 if (string - 3 < start || *(string - 3) != '/')
1368 break;
1369 in_repetition = true;
1370 continue;
1371 case '}': /* "\}/" */
1372 if (*string != '/')
1373 break;
1374 if (!in_repetition)
1375 break;
1376 in_repetition = false;
1377 continue;
1378 case '0': /* "\ooo" */
1379 case '1':
1380 case '2':
1381 case '3':
1382 if (!len-- || !len--)
1383 break;
1384 d = *string++;
1385 e = *string++;
1386 if (d < '0' || d > '7' || e < '0' || e > '7')
1387 break;
1388 c = ccs_make_byte(c, d, e);
1389 if (c <= ' ' || c >= 127)
1390 continue;
1391 }
1392 goto out;
1393 } else if (in_repetition && c == '/') {
1394 goto out;
1395 } else if (c <= ' ' || c >= 127) {
1396 goto out;
1397 }
1398 }
1399 if (in_repetition)
1400 goto out;
1401 return true;
1402 out:
1403 return false;
1404 }
1405
1406 /**
1407 * ccs_correct_word - Check whether the given string follows the naming rules.
1408 *
1409 * @string: The string to check.
1410 *
1411 * Returns true if @string follows the naming rules, false otherwise.
1412 */
1413 static bool ccs_correct_word(const char *string)
1414 {
1415 return ccs_correct_word2(string, strlen(string));
1416 }
1417
1418 /**
1419 * ccs_get_group - Allocate memory for "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group".
1420 *
1421 * @param: Pointer to "struct ccs_acl_param".
1422 * @idx: Index number.
1423 *
1424 * Returns pointer to "struct ccs_group" on success, NULL otherwise.
1425 */
1426 static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
1427 const u8 idx)
1428 {
1429 struct ccs_group e = { };
1430 struct ccs_group *group = NULL;
1431 struct list_head *list;
1432 const char *group_name = ccs_read_token(param);
1433 bool found = false;
1434 if (!ccs_correct_word(group_name) || idx >= CCS_MAX_GROUP)
1435 return NULL;
1436 e.group_name = ccs_get_name(group_name);
1437 if (!e.group_name)
1438 return NULL;
1439 if (mutex_lock_interruptible(&ccs_policy_lock))
1440 goto out;
1441 list = &param->ns->group_list[idx];
1442 list_for_each_entry(group, list, head.list) {
1443 if (e.group_name != group->group_name ||
1444 atomic_read(&group->head.users) == CCS_GC_IN_PROGRESS)
1445 continue;
1446 atomic_inc(&group->head.users);
1447 found = true;
1448 break;
1449 }
1450 if (!found) {
1451 struct ccs_group *entry = ccs_commit_ok(&e, sizeof(e));
1452 if (entry) {
1453 INIT_LIST_HEAD(&entry->member_list);
1454 atomic_set(&entry->head.users, 1);
1455 list_add_tail_rcu(&entry->head.list, list);
1456 group = entry;
1457 found = true;
1458 }
1459 }
1460 mutex_unlock(&ccs_policy_lock);
1461 out:
1462 ccs_put_name(e.group_name);
1463 return found ? group : NULL;
1464 }
1465
1466 /**
1467 * ccs_parse_name_union - Parse a ccs_name_union.
1468 *
1469 * @param: Pointer to "struct ccs_acl_param".
1470 * @ptr: Pointer to "struct ccs_name_union".
1471 *
1472 * Returns true on success, false otherwise.
1473 */
1474 static bool ccs_parse_name_union(struct ccs_acl_param *param,
1475 struct ccs_name_union *ptr)
1476 {
1477 char *filename;
1478 if (param->data[0] == '@') {
1479 param->data++;
1480 ptr->group = ccs_get_group(param, CCS_PATH_GROUP);
1481 return ptr->group != NULL;
1482 }
1483 filename = ccs_read_token(param);
1484 if (!ccs_correct_word(filename))
1485 return false;
1486 ptr->filename = ccs_get_name(filename);
1487 return ptr->filename != NULL;
1488 }
1489
1490 /**
1491 * ccs_parse_ulong - Parse an "unsigned long" value.
1492 *
1493 * @result: Pointer to "unsigned long".
1494 * @str: Pointer to string to parse.
1495 *
1496 * Returns one of values in "enum ccs_value_type".
1497 *
1498 * The @src is updated to point the first character after the value
1499 * on success.
1500 */
1501 static u8 ccs_parse_ulong(unsigned long *result, char **str)
1502 {
1503 const char *cp = *str;
1504 char *ep;
1505 int base = 10;
1506 if (*cp == '0') {
1507 char c = *(cp + 1);
1508 if (c == 'x' || c == 'X') {
1509 base = 16;
1510 cp += 2;
1511 } else if (c >= '0' && c <= '7') {
1512 base = 8;
1513 cp++;
1514 }
1515 }
1516 *result = simple_strtoul(cp, &ep, base);
1517 if (cp == ep)
1518 return CCS_VALUE_TYPE_INVALID;
1519 *str = ep;
1520 switch (base) {
1521 case 16:
1522 return CCS_VALUE_TYPE_HEXADECIMAL;
1523 case 8:
1524 return CCS_VALUE_TYPE_OCTAL;
1525 default:
1526 return CCS_VALUE_TYPE_DECIMAL;
1527 }
1528 }
1529
1530 /**
1531 * ccs_parse_number_union - Parse a ccs_number_union.
1532 *
1533 * @param: Pointer to "struct ccs_acl_param".
1534 * @ptr: Pointer to "struct ccs_number_union".
1535 *
1536 * Returns true on success, false otherwise.
1537 */
1538 static bool ccs_parse_number_union(struct ccs_acl_param *param,
1539 struct ccs_number_union *ptr)
1540 {
1541 char *data;
1542 u8 type;
1543 unsigned long v;
1544 memset(ptr, 0, sizeof(*ptr));
1545 if (param->data[0] == '@') {
1546 param->data++;
1547 ptr->group = ccs_get_group(param, CCS_NUMBER_GROUP);
1548 return ptr->group != NULL;
1549 }
1550 data = ccs_read_token(param);
1551 type = ccs_parse_ulong(&v, &data);
1552 if (type == CCS_VALUE_TYPE_INVALID)
1553 return false;
1554 ptr->values[0] = v;
1555 ptr->value_type[0] = type;
1556 if (!*data) {
1557 ptr->values[1] = v;
1558 ptr->value_type[1] = type;
1559 return true;
1560 }
1561 if (*data++ != '-')
1562 return false;
1563 type = ccs_parse_ulong(&v, &data);
1564 if (type == CCS_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
1565 return false;
1566 ptr->values[1] = v;
1567 ptr->value_type[1] = type;
1568 return true;
1569 }
1570
1571 #ifdef CONFIG_CCSECURITY_NETWORK
1572
1573 /**
1574 * ccs_parse_ipaddr_union - Parse an IP address.
1575 *
1576 * @param: Pointer to "struct ccs_acl_param".
1577 * @ptr: Pointer to "struct ccs_ipaddr_union".
1578 *
1579 * Returns true on success, false otherwise.
1580 */
1581 static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
1582 struct ccs_ipaddr_union *ptr)
1583 {
1584 u8 * const min = ptr->ip[0].in6_u.u6_addr8;
1585 u8 * const max = ptr->ip[1].in6_u.u6_addr8;
1586 char *address = ccs_read_token(param);
1587 const char *end;
1588 if (!strchr(address, ':') &&
1589 ccs_in4_pton(address, -1, min, '-', &end) > 0) {
1590 ptr->is_ipv6 = false;
1591 if (!*end)
1592 ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
1593 else if (*end++ != '-' ||
1594 ccs_in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
1595 return false;
1596 return true;
1597 }
1598 if (ccs_in6_pton(address, -1, min, '-', &end) > 0) {
1599 ptr->is_ipv6 = true;
1600 if (!*end)
1601 memmove(max, min, sizeof(u16) * 8);
1602 else if (*end++ != '-' ||
1603 ccs_in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
1604 return false;
1605 return true;
1606 }
1607 return false;
1608 }
1609
1610 #endif
1611
1612 /**
1613 * ccs_get_dqword - ccs_get_name() for a quoted string.
1614 *
1615 * @start: String to save.
1616 *
1617 * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
1618 */
1619 static const struct ccs_path_info *ccs_get_dqword(char *start)
1620 {
1621 char *cp = start + strlen(start) - 1;
1622 if (cp == start || *start++ != '"' || *cp != '"')
1623 return NULL;
1624 *cp = '\0';
1625 if (*start && !ccs_correct_word(start))
1626 return NULL;
1627 return ccs_get_name(start);
1628 }
1629
1630 /**
1631 * ccs_parse_name_union_quoted - Parse a quoted word.
1632 *
1633 * @param: Pointer to "struct ccs_acl_param".
1634 * @ptr: Pointer to "struct ccs_name_union".
1635 *
1636 * Returns true on success, false otherwise.
1637 */
1638 static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param,
1639 struct ccs_name_union *ptr)
1640 {
1641 char *filename = param->data;
1642 if (*filename == '@')
1643 return ccs_parse_name_union(param, ptr);
1644 ptr->filename = ccs_get_dqword(filename);
1645 return ptr->filename != NULL;
1646 }
1647
1648 /**
1649 * ccs_parse_argv - Parse an argv[] condition part.
1650 *
1651 * @left: Lefthand value.
1652 * @right: Righthand value.
1653 * @argv: Pointer to "struct ccs_argv".
1654 *
1655 * Returns true on success, false otherwise.
1656 */
1657 static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv)
1658 {
1659 if (ccs_parse_ulong(&argv->index, &left) != CCS_VALUE_TYPE_DECIMAL ||
1660 *left++ != ']' || *left)
1661 return false;
1662 argv->value = ccs_get_dqword(right);
1663 return argv->value != NULL;
1664 }
1665
1666 /**
1667 * ccs_parse_envp - Parse an envp[] condition part.
1668 *
1669 * @left: Lefthand value.
1670 * @right: Righthand value.
1671 * @envp: Pointer to "struct ccs_envp".
1672 *
1673 * Returns true on success, false otherwise.
1674 */
1675 static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp)
1676 {
1677 const struct ccs_path_info *name;
1678 const struct ccs_path_info *value;
1679 char *cp = left + strlen(left) - 1;
1680 if (*cp-- != ']' || *cp != '"')
1681 goto out;
1682 *cp = '\0';
1683 if (!ccs_correct_word(left))
1684 goto out;
1685 name = ccs_get_name(left);
1686 if (!name)
1687 goto out;
1688 if (!strcmp(right, "NULL")) {
1689 value = NULL;
1690 } else {
1691 value = ccs_get_dqword(right);
1692 if (!value) {
1693 ccs_put_name(name);
1694 goto out;
1695 }
1696 }
1697 envp->name = name;
1698 envp->value = value;
1699 return true;
1700 out:
1701 return false;
1702 }
1703
1704 /**
1705 * ccs_same_condition - Check for duplicated "struct ccs_condition" entry.
1706 *
1707 * @a: Pointer to "struct ccs_condition".
1708 * @b: Pointer to "struct ccs_condition".
1709 *
1710 * Returns true if @a == @b, false otherwise.
1711 */
1712 static bool ccs_same_condition(const struct ccs_condition *a,
1713 const struct ccs_condition *b)
1714 {
1715 return a->size == b->size && a->condc == b->condc &&
1716 a->numbers_count == b->numbers_count &&
1717 a->names_count == b->names_count &&
1718 a->argc == b->argc && a->envc == b->envc &&
1719 a->grant_log == b->grant_log &&
1720 a->exec_transit == b->exec_transit && a->transit == b->transit
1721 && !memcmp(a + 1, b + 1, a->size - sizeof(*a));
1722 }
1723
1724 /**
1725 * ccs_condition_type - Get condition type.
1726 *
1727 * @word: Keyword string.
1728 *
1729 * Returns one of values in "enum ccs_conditions_index" on success,
1730 * CCS_MAX_CONDITION_KEYWORD otherwise.
1731 */
1732 static u8 ccs_condition_type(const char *word)
1733 {
1734 u8 i;
1735 for (i = 0; i < CCS_MAX_CONDITION_KEYWORD; i++) {
1736 if (!strcmp(word, ccs_condition_keyword[i]))
1737 break;
1738 }
1739 return i;
1740 }
1741
1742 /**
1743 * ccs_commit_condition - Commit "struct ccs_condition".
1744 *
1745 * @entry: Pointer to "struct ccs_condition".
1746 *
1747 * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
1748 *
1749 * This function merges duplicated entries. This function returns NULL if
1750 * @entry is not duplicated but memory quota for policy has exceeded.
1751 */
1752 static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry)
1753 {
1754 struct ccs_condition *ptr;
1755 bool found = false;
1756 if (mutex_lock_interruptible(&ccs_policy_lock)) {
1757 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
1758 ptr = NULL;
1759 found = true;
1760 goto out;
1761 }
1762 list_for_each_entry(ptr, &ccs_condition_list, head.list) {
1763 if (!ccs_same_condition(ptr, entry) ||
1764 atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS)
1765 continue;
1766 /* Same entry found. Share this entry. */
1767 atomic_inc(&ptr->head.users);
1768 found = true;
1769 break;
1770 }
1771 if (!found) {
1772 if (ccs_memory_ok(entry, entry->size)) {
1773 atomic_set(&entry->head.users, 1);
1774 list_add(&entry->head.list, &ccs_condition_list);
1775 } else {
1776 found = true;
1777 ptr = NULL;
1778 }
1779 }
1780 mutex_unlock(&ccs_policy_lock);
1781 out:
1782 if (found) {
1783 ccs_del_condition(&entry->head.list);
1784 kfree(entry);
1785 entry = ptr;
1786 }
1787 return entry;
1788 }
1789
1790 /**
1791 * ccs_correct_path - Check whether the given pathname follows the naming rules.
1792 *
1793 * @filename: The pathname to check.
1794 *
1795 * Returns true if @filename follows the naming rules, false otherwise.
1796 */
1797 static bool ccs_correct_path(const char *filename)
1798 {
1799 return *filename == '/' && ccs_correct_word(filename);
1800 }
1801
1802 /**
1803 * ccs_domain_def - Check whether the given token can be a domainname.
1804 *
1805 * @buffer: The token to check.
1806 *
1807 * Returns true if @buffer possibly be a domainname, false otherwise.
1808 */
1809 static bool ccs_domain_def(const unsigned char *buffer)
1810 {
1811 const unsigned char *cp;
1812 int len;
1813 if (*buffer != '<')
1814 return false;
1815 cp = strchr(buffer, ' ');
1816 if (!cp)
1817 len = strlen(buffer);
1818 else
1819 len = cp - buffer;
1820 if (buffer[len - 1] != '>' || !ccs_correct_word2(buffer + 1, len - 2))
1821 return false;
1822 return true;
1823 }
1824
1825 /**
1826 * ccs_correct_domain - Check whether the given domainname follows the naming rules.
1827 *
1828 * @domainname: The domainname to check.
1829 *
1830 * Returns true if @domainname follows the naming rules, false otherwise.
1831 */
1832 static bool ccs_correct_domain(const unsigned char *domainname)
1833 {
1834 if (!domainname || !ccs_domain_def(domainname))
1835 return false;
1836 domainname = strchr(domainname, ' ');
1837 if (!domainname++)
1838 return true;
1839 while (1) {
1840 const unsigned char *cp = strchr(domainname, ' ');
1841 if (!cp)
1842 break;
1843 if (*domainname != '/' ||
1844 !ccs_correct_word2(domainname, cp - domainname))
1845 return false;
1846 domainname = cp + 1;
1847 }
1848 return ccs_correct_path(domainname);
1849 }
1850
1851 /**
1852 * ccs_normalize_line - Format string.
1853 *
1854 * @buffer: The line to normalize.
1855 *
1856 * Returns nothing.
1857 *
1858 * Leading and trailing whitespaces are removed.
1859 * Multiple whitespaces are packed into single space.
1860 */
1861 static void ccs_normalize_line(unsigned char *buffer)
1862 {
1863 unsigned char *sp = buffer;
1864 unsigned char *dp = buffer;
1865 bool first = true;
1866 while (*sp && (*sp <= ' ' || *sp >= 127))
1867 sp++;
1868 while (*sp) {
1869 if (!first)
1870 *dp++ = ' ';
1871 first = false;
1872 while (*sp > ' ' && *sp < 127)
1873 *dp++ = *sp++;
1874 while (*sp && (*sp <= ' ' || *sp >= 127))
1875 sp++;
1876 }
1877 *dp = '\0';
1878 }
1879
1880 /**
1881 * ccs_get_domainname - Read a domainname from a line.
1882 *
1883 * @param: Pointer to "struct ccs_acl_param".
1884 *
1885 * Returns a domainname on success, NULL otherwise.
1886 */
1887 static const struct ccs_path_info *ccs_get_domainname
1888 (struct ccs_acl_param *param)
1889 {
1890 char *start = param->data;
1891 char *pos = start;
1892 while (*pos) {
1893 if (*pos++ != ' ' || *pos++ == '/')
1894 continue;
1895 pos -= 2;
1896 *pos++ = '\0';
1897 break;
1898 }
1899 param->data = pos;
1900 if (ccs_correct_domain(start))
1901 return ccs_get_name(start);
1902 return NULL;
1903 }
1904
1905 /**
1906 * ccs_get_transit_preference - Parse domain transition preference for execve().
1907 *
1908 * @param: Pointer to "struct ccs_acl_param".
1909 * @e: Pointer to "struct ccs_condition".
1910 *
1911 * Returns the condition string part.
1912 */
1913 static char *ccs_get_transit_preference(struct ccs_acl_param *param,
1914 struct ccs_condition *e)
1915 {
1916 char * const pos = param->data;
1917 bool flag;
1918 if (*pos == '<') {
1919 e->transit = ccs_get_domainname(param);
1920 goto done;
1921 }
1922 {
1923 char *cp = strchr(pos, ' ');
1924 if (cp)
1925 *cp = '\0';
1926 flag = ccs_correct_path(pos) || !strcmp(pos, "keep") ||
1927 !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
1928 !strcmp(pos, "child") || !strcmp(pos, "parent");
1929 if (cp)
1930 *cp = ' ';
1931 }
1932 if (!flag)
1933 return pos;
1934 e->transit = ccs_get_name(ccs_read_token(param));
1935 done:
1936 if (e->transit) {
1937 e->exec_transit = true;
1938 return param->data;
1939 }
1940 /*
1941 * Return a bad read-only condition string that will let
1942 * ccs_get_condition() return NULL.
1943 */
1944 return "/";
1945 }
1946
1947 /**
1948 * ccs_get_condition - Parse condition part.
1949 *
1950 * @param: Pointer to "struct ccs_acl_param".
1951 *
1952 * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
1953 */
1954 struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param)
1955 {
1956 struct ccs_condition *entry = NULL;
1957 struct ccs_condition_element *condp = NULL;
1958 struct ccs_number_union *numbers_p = NULL;
1959 struct ccs_name_union *names_p = NULL;
1960 struct ccs_argv *argv = NULL;
1961 struct ccs_envp *envp = NULL;
1962 struct ccs_condition e = { };
1963 char * const start_of_string = ccs_get_transit_preference(param, &e);
1964 char * const end_of_string = start_of_string + strlen(start_of_string);
1965 char *pos;
1966 rerun:
1967 pos = start_of_string;
1968 while (1) {
1969 u8 left = -1;
1970 u8 right = -1;
1971 char *left_word = pos;
1972 char *cp;
1973 char *right_word;
1974 bool is_not;
1975 if (!*left_word)
1976 break;
1977 /*
1978 * Since left-hand condition does not allow use of "path_group"
1979 * or "number_group" and environment variable's names do not
1980 * accept '=', it is guaranteed that the original line consists
1981 * of one or more repetition of $left$operator$right blocks
1982 * where "$left is free from '=' and ' '" and "$operator is
1983 * either '=' or '!='" and "$right is free from ' '".
1984 * Therefore, we can reconstruct the original line at the end
1985 * of dry run even if we overwrite $operator with '\0'.
1986 */
1987 cp = strchr(pos, ' ');
1988 if (cp) {
1989 *cp = '\0'; /* Will restore later. */
1990 pos = cp + 1;
1991 } else {
1992 pos = "";
1993 }
1994 right_word = strchr(left_word, '=');
1995 if (!right_word || right_word == left_word)
1996 goto out;
1997 is_not = *(right_word - 1) == '!';
1998 if (is_not)
1999 *(right_word++ - 1) = '\0'; /* Will restore later. */
2000 else if (*(right_word + 1) != '=')
2001 *right_word++ = '\0'; /* Will restore later. */
2002 else
2003 goto out;
2004 dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
2005 is_not ? "!" : "", right_word);
2006 if (!strcmp(left_word, "grant_log")) {
2007 if (entry) {
2008 if (is_not ||
2009 entry->grant_log != CCS_GRANTLOG_AUTO)
2010 goto out;
2011 else if (!strcmp(right_word, "yes"))
2012 entry->grant_log = CCS_GRANTLOG_YES;
2013 else if (!strcmp(right_word, "no"))
2014 entry->grant_log = CCS_GRANTLOG_NO;
2015 else
2016 goto out;
2017 }
2018 continue;
2019 }
2020 if (!strcmp(left_word, "auto_domain_transition")) {
2021 if (entry) {
2022 if (is_not || entry->transit)
2023 goto out;
2024 entry->transit = ccs_get_dqword(right_word);
2025 if (!entry->transit ||
2026 (entry->transit->name[0] != '/' &&
2027 !ccs_domain_def(entry->transit->name)))
2028 goto out;
2029 }
2030 continue;
2031 }
2032 if (!strncmp(left_word, "exec.argv[", 10)) {
2033 if (!argv) {
2034 e.argc++;
2035 e.condc++;
2036 } else {
2037 e.argc--;
2038 e.condc--;
2039 left = CCS_ARGV_ENTRY;
2040 argv->is_not = is_not;
2041 if (!ccs_parse_argv(left_word + 10,
2042 right_word, argv++))
2043 goto out;
2044 }
2045 goto store_value;
2046 }
2047 if (!strncmp(left_word, "exec.envp[\"", 11)) {
2048 if (!envp) {
2049 e.envc++;
2050 e.condc++;
2051 } else {
2052 e.envc--;
2053 e.condc--;
2054 left = CCS_ENVP_ENTRY;
2055 envp->is_not = is_not;
2056 if (!ccs_parse_envp(left_word + 11,
2057 right_word, envp++))
2058 goto out;
2059 }
2060 goto store_value;
2061 }
2062 left = ccs_condition_type(left_word);
2063 dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
2064 left);
2065 if (left == CCS_MAX_CONDITION_KEYWORD) {
2066 if (!numbers_p) {
2067 e.numbers_count++;
2068 } else {
2069 e.numbers_count--;
2070 left = CCS_NUMBER_UNION;
2071 param->data = left_word;
2072 if (*left_word == '@' ||
2073 !ccs_parse_number_union(param,
2074 numbers_p++))
2075 goto out;
2076 }
2077 }
2078 if (!condp)
2079 e.condc++;
2080 else
2081 e.condc--;
2082 if (left == CCS_EXEC_REALPATH || left == CCS_SYMLINK_TARGET) {
2083 if (!names_p) {
2084 e.names_count++;
2085 } else {
2086 e.names_count--;
2087 right = CCS_NAME_UNION;
2088 param->data = right_word;
2089 if (!ccs_parse_name_union_quoted(param,
2090 names_p++))
2091 goto out;
2092 }
2093 goto store_value;
2094 }
2095 right = ccs_condition_type(right_word);
2096 if (right == CCS_MAX_CONDITION_KEYWORD) {
2097 if (!numbers_p) {
2098 e.numbers_count++;
2099 } else {
2100 e.numbers_count--;
2101 right = CCS_NUMBER_UNION;
2102 param->data = right_word;
2103 if (!ccs_parse_number_union(param,
2104 numbers_p++))
2105 goto out;
2106 }
2107 }
2108 store_value:
2109 if (!condp) {
2110 dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
2111 "match=%u\n", __LINE__, left, right, !is_not);
2112 continue;
2113 }
2114 condp->left = left;
2115 condp->right = right;
2116 condp->equals = !is_not;
2117 dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
2118 __LINE__, condp->left, condp->right,
2119 condp->equals);
2120 condp++;
2121 }
2122 dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
2123 __LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
2124 e.envc);
2125 if (entry) {
2126 BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
2127 e.condc);
2128 return ccs_commit_condition(entry);
2129 }
2130 e.size = sizeof(*entry)
2131 + e.condc * sizeof(struct ccs_condition_element)
2132 + e.numbers_count * sizeof(struct ccs_number_union)
2133 + e.names_count * sizeof(struct ccs_name_union)
2134 + e.argc * sizeof(struct ccs_argv)
2135 + e.envc * sizeof(struct ccs_envp);
2136 entry = kzalloc(e.size, CCS_GFP_FLAGS);
2137 if (!entry)
2138 goto out2;
2139 *entry = e;
2140 e.transit = NULL;
2141 condp = (struct ccs_condition_element *) (entry + 1);
2142 numbers_p = (struct ccs_number_union *) (condp + e.condc);
2143 names_p = (struct ccs_name_union *) (numbers_p + e.numbers_count);
2144 argv = (struct ccs_argv *) (names_p + e.names_count);
2145 envp = (struct ccs_envp *) (argv + e.argc);
2146 {
2147 bool flag = false;
2148 for (pos = start_of_string; pos < end_of_string; pos++) {
2149 if (*pos)
2150 continue;
2151 if (flag) /* Restore " ". */
2152 *pos = ' ';
2153 else if (*(pos + 1) == '=') /* Restore "!=". */
2154 *pos = '!';
2155 else /* Restore "=". */
2156 *pos = '=';
2157 flag = !flag;
2158 }
2159 }
2160 goto rerun;
2161 out:
2162 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
2163 if (entry) {
2164 ccs_del_condition(&entry->head.list);
2165 kfree(entry);
2166 }
2167 out2:
2168 ccs_put_name(e.transit);
2169 return NULL;
2170 }
2171
2172 /**
2173 * ccs_yesno - Return "yes" or "no".
2174 *
2175 * @value: Bool value.
2176 *
2177 * Returns "yes" if @value is not 0, "no" otherwise.
2178 */
2179 static const char *ccs_yesno(const unsigned int value)
2180 {
2181 return value ? "yes" : "no";
2182 }
2183
2184 /**
2185 * ccs_addprintf - strncat()-like-snprintf().
2186 *
2187 * @buffer: Buffer to write to. Must be '\0'-terminated.
2188 * @len: Size of @buffer.
2189 * @fmt: The printf()'s format string, followed by parameters.
2190 *
2191 * Returns nothing.
2192 */
2193 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
2194 {
2195 va_list args;
2196 const int pos = strlen(buffer);
2197 va_start(args, fmt);
2198 vsnprintf(buffer + pos, len - pos - 1, fmt, args);
2199 va_end(args);
2200 }
2201
2202 /**
2203 * ccs_flush - Flush queued string to userspace's buffer.
2204 *
2205 * @head: Pointer to "struct ccs_io_buffer".
2206 *
2207 * Returns true if all data was flushed, false otherwise.
2208 */
2209 static bool ccs_flush(struct ccs_io_buffer *head)
2210 {
2211 while (head->r.w_pos) {
2212 const char *w = head->r.w[0];
2213 size_t len = strlen(w);
2214 if (len) {
2215 if (len > head->read_user_buf_avail)
2216 len = head->read_user_buf_avail;
2217 if (!len)
2218 return false;
2219 if (copy_to_user(head->read_user_buf, w, len))
2220 return false;
2221 head->read_user_buf_avail -= len;
2222 head->read_user_buf += len;
2223 w += len;
2224 }
2225 head->r.w[0] = w;
2226 if (*w)
2227 return false;
2228 /* Add '\0' for audit logs and query. */
2229 if (head->type == CCS_AUDIT || head->type == CCS_QUERY) {
2230 if (!head->read_user_buf_avail ||
2231 copy_to_user(head->read_user_buf, "", 1))
2232 return false;
2233 head->read_user_buf_avail--;
2234 head->read_user_buf++;
2235 }
2236 head->r.w_pos--;
2237 for (len = 0; len < head->r.w_pos; len++)
2238 head->r.w[len] = head->r.w[len + 1];
2239 }
2240 head->r.avail = 0;
2241 return true;
2242 }
2243
2244 /**
2245 * ccs_set_string - Queue string to "struct ccs_io_buffer" structure.
2246 *
2247 * @head: Pointer to "struct ccs_io_buffer".
2248 * @string: String to print.
2249 *
2250 * Returns nothing.
2251 *
2252 * Note that @string has to be kept valid until @head is kfree()d.
2253 * This means that char[] allocated on stack memory cannot be passed to
2254 * this function. Use ccs_io_printf() for char[] allocated on stack memory.
2255 */
2256 static void ccs_set_string(struct ccs_io_buffer *head, const char *string)
2257 {
2258 if (head->r.w_pos < CCS_MAX_IO_READ_QUEUE) {
2259 head->r.w[head->r.w_pos++] = string;
2260 ccs_flush(head);
2261 } else
2262 printk(KERN_WARNING "Too many words in a line.\n");
2263 }
2264
2265 /**
2266 * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
2267 *
2268 * @head: Pointer to "struct ccs_io_buffer".
2269 * @fmt: The printf()'s format string, followed by parameters.
2270 *
2271 * Returns nothing.
2272 */
2273 static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
2274 {
2275 va_list args;
2276 size_t len;
2277 size_t pos = head->r.avail;
2278 int size = head->readbuf_size - pos;
2279 if (size <= 0)
2280 return;
2281 va_start(args, fmt);
2282 len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1;
2283 va_end(args);
2284 if (pos + len >= head->readbuf_size) {
2285 printk(KERN_WARNING "Too many words in a line.\n");
2286 return;
2287 }
2288 head->r.avail += len;
2289 ccs_set_string(head, head->read_buf + pos);
2290 }
2291
2292 /**
2293 * ccs_set_space - Put a space to "struct ccs_io_buffer" structure.
2294 *
2295 * @head: Pointer to "struct ccs_io_buffer".
2296 *
2297 * Returns nothing.
2298 */
2299 static void ccs_set_space(struct ccs_io_buffer *head)
2300 {
2301 ccs_set_string(head, " ");
2302 }
2303
2304 /**
2305 * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure.
2306 *
2307 * @head: Pointer to "struct ccs_io_buffer".
2308 *
2309 * Returns true if all data was flushed, false otherwise.
2310 */
2311 static bool ccs_set_lf(struct ccs_io_buffer *head)
2312 {
2313 ccs_set_string(head, "\n");
2314 return !head->r.w_pos;
2315 }
2316
2317 /**
2318 * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure.
2319 *
2320 * @head: Pointer to "struct ccs_io_buffer".
2321 *
2322 * Returns nothing.
2323 */
2324 static void ccs_set_slash(struct ccs_io_buffer *head)
2325 {
2326 ccs_set_string(head, "/");
2327 }
2328
2329 /**
2330 * ccs_init_policy_namespace - Initialize namespace.
2331 *
2332 * @ns: Pointer to "struct ccs_policy_namespace".
2333 *
2334 * Returns nothing.
2335 */
2336 static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns)
2337 {
2338 unsigned int idx;
2339 for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++)
2340 INIT_LIST_HEAD(&ns->acl_group[idx]);
2341 for (idx = 0; idx < CCS_MAX_GROUP; idx++)
2342 INIT_LIST_HEAD(&ns->group_list[idx]);
2343 for (idx = 0; idx < CCS_MAX_POLICY; idx++)
2344 INIT_LIST_HEAD(&ns->policy_list[idx]);
2345 ns->profile_version = 20100903;
2346 ccs_namespace_enabled = !list_empty(&ccs_namespace_list);
2347 list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list);
2348 }
2349
2350 /**
2351 * ccs_print_namespace - Print namespace header.
2352 *
2353 * @head: Pointer to "struct ccs_io_buffer".
2354 *
2355 * Returns nothing.
2356 */
2357 static void ccs_print_namespace(struct ccs_io_buffer *head)
2358 {
2359 if (!ccs_namespace_enabled)
2360 return;
2361 ccs_set_string(head,
2362 container_of(head->r.ns, struct ccs_policy_namespace,
2363 namespace_list)->name);
2364 ccs_set_space(head);
2365 }
2366
2367 /**
2368 * ccs_assign_profile - Create a new profile.
2369 *
2370 * @ns: Pointer to "struct ccs_policy_namespace".
2371 * @profile: Profile number to create.
2372 *
2373 * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
2374 */
2375 static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
2376 const unsigned int profile)
2377 {
2378 struct ccs_profile *ptr;
2379 struct ccs_profile *entry;
2380 if (profile >= CCS_MAX_PROFILES)
2381 return NULL;
2382 ptr = ns->profile_ptr[profile];
2383 if (ptr)
2384 return ptr;
2385 entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
2386 if (mutex_lock_interruptible(&ccs_policy_lock))
2387 goto out;
2388 ptr = ns->profile_ptr[profile];
2389 if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
2390 ptr = entry;
2391 ptr->default_config = CCS_CONFIG_DISABLED |
2392 CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
2393 memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
2394 sizeof(ptr->config));
2395 ptr->pref[CCS_PREF_MAX_AUDIT_LOG] =
2396 CONFIG_CCSECURITY_MAX_AUDIT_LOG;
2397 ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
2398 CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
2399 mb(); /* Avoid out-of-order execution. */
2400 ns->profile_ptr[profile] = ptr;
2401 entry = NULL;
2402 }
2403 mutex_unlock(&ccs_policy_lock);
2404 out:
2405 kfree(entry);
2406 return ptr;
2407 }
2408
2409 /**
2410 * ccs_check_profile - Check all profiles currently assigned to domains are defined.
2411 *
2412 * Returns nothing.
2413 */
2414 static void ccs_check_profile(void)
2415 {
2416 struct ccs_domain_info *domain;
2417 const int idx = ccs_read_lock();
2418 ccs_policy_loaded = true;
2419 printk(KERN_INFO "CCSecurity: 1.8.3+ 2012/05/05\n");
2420 list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
2421 const u8 profile = domain->profile;
2422 const struct ccs_policy_namespace *ns = domain->ns;
2423 if (ns->profile_version != 20100903)
2424 printk(KERN_ERR
2425 "Profile version %u is not supported.\n",
2426 ns->profile_version);
2427 else if (!ns->profile_ptr[profile])
2428 printk(KERN_ERR
2429 "Profile %u (used by '%s') is not defined.\n",
2430 profile, domain->domainname->name);
2431 else
2432 continue;
2433 printk(KERN_ERR
2434 "Userland tools for TOMOYO 1.8 must be installed and "
2435 "policy must be initialized.\n");
2436 printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "
2437 "for more information.\n");
2438 panic("STOP!");
2439 }
2440 ccs_read_unlock(idx);
2441 printk(KERN_INFO "Mandatory Access Control activated.\n");
2442 }
2443
2444 /**
2445 * ccs_profile - Find a profile.
2446 *
2447 * @profile: Profile number to find.
2448 *
2449 * Returns pointer to "struct ccs_profile".
2450 */
2451 static struct ccs_profile *ccs_profile(const u8 profile)
2452 {
2453 static struct ccs_profile ccs_null_profile;
2454 struct ccs_profile *ptr = ccs_current_namespace()->
2455 profile_ptr[profile];
2456 if (!ptr)
2457 ptr = &ccs_null_profile;
2458 return ptr;
2459 }
2460
2461 /**
2462 * ccs_get_config - Get config for specified profile's specified functionality.
2463 *
2464 * @profile: Profile number.
2465 * @index: Index number of functionality.
2466 *
2467 * Returns config.
2468 *
2469 * First, check for CONFIG::category::functionality.
2470 * If CONFIG::category::functionality is set to use default, then check
2471 * CONFIG::category. If CONFIG::category is set to use default, then use
2472 * CONFIG. CONFIG cannot be set to use default.
2473 */
2474 u8 ccs_get_config(const u8 profile, const u8 index)
2475 {
2476 u8 config;
2477 const struct ccs_profile *p;
2478 if (!ccs_policy_loaded)
2479 return CCS_CONFIG_DISABLED;
2480 p = ccs_profile(profile);
2481 config = p->config[index];
2482 if (config == CCS_CONFIG_USE_DEFAULT)
2483 config = p->config[ccs_index2category[index]
2484 + CCS_MAX_MAC_INDEX];
2485 if (config == CCS_CONFIG_USE_DEFAULT)
2486 config = p->default_config;
2487 return config;
2488 }
2489
2490 /**
2491 * ccs_find_yesno - Find values for specified keyword.
2492 *
2493 * @string: String to check.
2494 * @find: Name of keyword.
2495 *
2496 * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
2497 */
2498 static s8 ccs_find_yesno(const char *string, const char *find)
2499 {
2500 const char *cp = strstr(string, find);
2501 if (cp) {
2502 cp += strlen(find);
2503 if (!strncmp(cp, "=yes", 4))
2504 return 1;
2505 else if (!strncmp(cp, "=no", 3))
2506 return 0;
2507 }
2508 return -1;
2509 }
2510
2511 /**
2512 * ccs_set_uint - Set value for specified preference.
2513 *
2514 * @i: Pointer to "unsigned int".
2515 * @string: String to check.
2516 * @find: Name of keyword.
2517 *
2518 * Returns nothing.
2519 */
2520 static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
2521 {
2522 const char *cp = strstr(string, find);
2523 if (cp)
2524 sscanf(cp + strlen(find), "=%u", i);
2525 }
2526
2527 /**
2528 * ccs_str_starts - Check whether the given string starts with the given keyword.
2529 *
2530 * @src: Pointer to pointer to the string.
2531 * @find: Pointer to the keyword.
2532 *
2533 * Returns true if @src starts with @find, false otherwise.
2534 *
2535 * The @src is updated to point the first character after the @find
2536 * if @src starts with @find.
2537 */
2538 static bool ccs_str_starts(char **src, const char *find)
2539 {
2540 const int len = strlen(find);
2541 char *tmp = *src;
2542 if (strncmp(tmp, find, len))
2543 return false;
2544 tmp += len;
2545 *src = tmp;
2546 return true;
2547 }
2548
2549 /**
2550 * ccs_print_group - Print group's name.
2551 *
2552 * @head: Pointer to "struct ccs_io_buffer".
2553 * @group: Pointer to "struct ccsgroup". Maybe NULL.
2554 *
2555 * Returns true if @group is not NULL. false otherwise.
2556 */
2557 static bool ccs_print_group(struct ccs_io_buffer *head,
2558 const struct ccs_group *group)
2559 {
2560 if (group) {
2561 ccs_set_string(head, "@");
2562 ccs_set_string(head, group->group_name->name);
2563 return true;
2564 }
2565 return false;
2566 }
2567
2568 /**
2569 * ccs_set_mode - Set mode for specified profile.
2570 *
2571 * @name: Name of functionality.
2572 * @value: Mode for @name.
2573 * @profile: Pointer to "struct ccs_profile".
2574 *
2575 * Returns 0 on success, negative value otherwise.
2576 */
2577 static int ccs_set_mode(char *name, const char *value,
2578 struct ccs_profile *profile)
2579 {
2580 u8 i;
2581 u8 config;
2582 if (!strcmp(name, "CONFIG")) {
2583 i = CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
2584 config = profile->default_config;
2585 } else if (ccs_str_starts(&name, "CONFIG::")) {
2586 config = 0;
2587 for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
2588 i++) {
2589 int len = 0;
2590 if (i < CCS_MAX_MAC_INDEX) {
2591 const u8 c = ccs_index2category[i];
2592 const char *category =
2593 ccs_category_keywords[c];
2594 len = strlen(category);
2595 if (strncmp(name, category, len) ||
2596 name[len++] != ':' || name[len++] != ':')
2597 continue;
2598 }
2599 if (strcmp(name + len, ccs_mac_keywords[i]))
2600 continue;
2601 config = profile->config[i];
2602 break;
2603 }
2604 if (i == CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
2605 return -EINVAL;
2606 } else {
2607 return -EINVAL;
2608 }
2609 if (strstr(value, "use_default")) {
2610 config = CCS_CONFIG_USE_DEFAULT;
2611 } else {
2612 u8 mode;
2613 for (mode = 0; mode < CCS_CONFIG_MAX_MODE; mode++)
2614 if (strstr(value, ccs_mode[mode]))
2615 /*
2616 * Update lower 3 bits in order to distinguish
2617 * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
2618 */
2619 config = (config & ~7) | mode;
2620 if (config != CCS_CONFIG_USE_DEFAULT) {
2621 switch (ccs_find_yesno(value, "grant_log")) {
2622 case 1:
2623 config |= CCS_CONFIG_WANT_GRANT_LOG;
2624 break;
2625 case 0:
2626 config &= ~CCS_CONFIG_WANT_GRANT_LOG;
2627 break;
2628 }
2629 switch (ccs_find_yesno(value, "reject_log")) {
2630 case 1:
2631 config |= CCS_CONFIG_WANT_REJECT_LOG;
2632 break;
2633 case 0:
2634 config &= ~CCS_CONFIG_WANT_REJECT_LOG;
2635 break;
2636 }
2637 }
2638 }
2639 if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
2640 profile->config[i] = config;
2641 else if (config != CCS_CONFIG_USE_DEFAULT)
2642 profile->default_config = config;
2643 return 0;
2644 }
2645
2646 /**
2647 * ccs_write_profile - Write profile table.
2648 *
2649 * @head: Pointer to "struct ccs_io_buffer".
2650 *
2651 * Returns 0 on success, negative value otherwise.
2652 */
2653 static int ccs_write_profile(struct ccs_io_buffer *head)
2654 {
2655 char *data = head->write_buf;
2656 unsigned int i;
2657 char *cp;
2658 struct ccs_profile *profile;
2659 if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
2660 == 1)
2661 return 0;
2662 i = simple_strtoul(data, &cp, 10);
2663 if (*cp != '-')
2664 return -EINVAL;
2665 data = cp + 1;
2666 profile = ccs_assign_profile(head->w.ns, i);
2667 if (!profile)
2668 return -EINVAL;
2669 cp = strchr(data, '=');
2670 if (!cp)
2671 return -EINVAL;
2672 *cp++ = '\0';
2673 if (!strcmp(data, "COMMENT")) {
2674 static DEFINE_SPINLOCK(lock);
2675 const struct ccs_path_info *new_comment = ccs_get_name(cp);
2676 const struct ccs_path_info *old_comment;
2677 if (!new_comment)
2678 return -ENOMEM;
2679 spin_lock(&lock);
2680 old_comment = profile->comment;
2681 profile->comment = new_comment;
2682 spin_unlock(&lock);
2683 ccs_put_name(old_comment);
2684 return 0;
2685 }
2686 if (!strcmp(data, "PREFERENCE")) {
2687 for (i = 0; i < CCS_MAX_PREF; i++)
2688 ccs_set_uint(&profile->pref[i], cp,
2689 ccs_pref_keywords[i]);
2690 return 0;
2691 }
2692 return ccs_set_mode(data, cp, profile);
2693 }
2694
2695 /**
2696 * ccs_print_config - Print mode for specified functionality.
2697 *
2698 * @head: Pointer to "struct ccs_io_buffer".
2699 * @config: Mode for that functionality.
2700 *
2701 * Returns nothing.
2702 *
2703 * Caller prints functionality's name.
2704 */
2705 static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)
2706 {
2707 ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
2708 ccs_mode[config & 3],
2709 ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),
2710 ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));
2711 }
2712
2713 /**
2714 * ccs_read_profile - Read profile table.
2715 *
2716 * @head: Pointer to "struct ccs_io_buffer".
2717 *
2718 * Returns nothing.
2719 */
2720 static void ccs_read_profile(struct ccs_io_buffer *head)
2721 {
2722 u8 index;
2723 struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2724 namespace_list);
2725 const struct ccs_profile *profile;
2726 if (head->r.eof)
2727 return;
2728 next:
2729 index = head->r.index;
2730 profile = ns->profile_ptr[index];
2731 switch (head->r.step) {
2732 case 0:
2733 ccs_print_namespace(head);
2734 ccs_io_printf(head, "PROFILE_VERSION=%u\n",
2735 ns->profile_version);
2736 head->r.step++;
2737 break;
2738 case 1:
2739 for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++)
2740 if (ns->profile_ptr[head->r.index])
2741 break;
2742 if (head->r.index == CCS_MAX_PROFILES) {
2743 head->r.eof = true;
2744 return;
2745 }
2746 head->r.step++;
2747 break;
2748 case 2:
2749 {
2750 u8 i;
2751 const struct ccs_path_info *comment = profile->comment;
2752 ccs_print_namespace(head);
2753 ccs_io_printf(head, "%u-COMMENT=", index);
2754 ccs_set_string(head, comment ? comment->name : "");
2755 ccs_set_lf(head);
2756 ccs_print_namespace(head);
2757 ccs_io_printf(head, "%u-PREFERENCE={ ", index);
2758 for (i = 0; i < CCS_MAX_PREF; i++)
2759 ccs_io_printf(head, "%s=%u ",
2760 ccs_pref_keywords[i],
2761 profile->pref[i]);
2762 ccs_set_string(head, "}\n");
2763 head->r.step++;
2764 }
2765 break;
2766 case 3:
2767 {
2768 ccs_print_namespace(head);
2769 ccs_io_printf(head, "%u-%s", index, "CONFIG");
2770 ccs_print_config(head, profile->default_config);
2771 head->r.bit = 0;
2772 head->r.step++;
2773 }
2774 break;
2775 case 4:
2776 for ( ; head->r.bit < CCS_MAX_MAC_INDEX
2777 + CCS_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {
2778 const u8 i = head->r.bit;
2779 const u8 config = profile->config[i];
2780 if (config == CCS_CONFIG_USE_DEFAULT)
2781 continue;
2782 ccs_print_namespace(head);
2783 if (i < CCS_MAX_MAC_INDEX)
2784 ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
2785 ccs_category_keywords
2786 [ccs_index2category[i]],
2787 ccs_mac_keywords[i]);
2788 else
2789 ccs_io_printf(head, "%u-CONFIG::%s", index,
2790 ccs_mac_keywords[i]);
2791 ccs_print_config(head, config);
2792 head->r.bit++;
2793 break;
2794 }
2795 if (head->r.bit == CCS_MAX_MAC_INDEX
2796 + CCS_MAX_MAC_CATEGORY_INDEX) {
2797 head->r.index++;
2798 head->r.step = 1;
2799 }
2800 break;
2801 }
2802 if (ccs_flush(head))
2803 goto next;
2804 }
2805
2806 /**
2807 * ccs_update_policy - Update an entry for exception policy.
2808 *
2809 * @size: Size of new entry in bytes.
2810 * @param: Pointer to "struct ccs_acl_param".
2811 *
2812 * Returns 0 on success, negative value otherwise.
2813 *
2814 * Caller holds ccs_read_lock().
2815 */
2816 static int ccs_update_policy(const int size, struct ccs_acl_param *param)
2817 {
2818 struct ccs_acl_head *new_entry = &param->e.acl_head;
2819 int error = param->is_delete ? -ENOENT : -ENOMEM;
2820 struct ccs_acl_head *entry;
2821 struct list_head *list = param->list;
2822 BUG_ON(size < sizeof(*entry));
2823 if (mutex_lock_interruptible(&ccs_policy_lock))
2824 return -ENOMEM;
2825 list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
2826 if (entry->is_deleted == CCS_GC_IN_PROGRESS)
2827 continue;
2828 if (memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
2829 continue;
2830 entry->is_deleted = param->is_delete;
2831 error = 0;
2832 break;
2833 }
2834 if (error && !param->is_delete) {
2835 entry = ccs_commit_ok(new_entry, size);
2836 if (entry) {
2837 list_add_tail_rcu(&entry->list, list);
2838 error = 0;
2839 }
2840 }
2841 mutex_unlock(&ccs_policy_lock);
2842 return error;
2843 }
2844
2845 /**
2846 * ccs_update_manager_entry - Add a manager entry.
2847 *
2848 * @manager: The path to manager or the domainnamme.
2849 * @is_delete: True if it is a delete request.
2850 *
2851 * Returns 0 on success, negative value otherwise.
2852 */
2853 static int ccs_update_manager_entry(const char *manager,
2854 const bool is_delete)
2855 {
2856 struct ccs_acl_param param = {
2857 /* .ns = &ccs_kernel_namespace, */
2858 .is_delete = is_delete,
2859 .list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER],
2860 };
2861 struct ccs_manager *e = &param.e.manager;
2862 int error = is_delete ? -ENOENT : -ENOMEM;
2863 /* Forced zero clear for using memcmp() at ccs_update_policy(). */
2864 memset(&param.e, 0, sizeof(param.e));
2865 if (!ccs_correct_domain(manager) && !ccs_correct_word(manager))
2866 return -EINVAL;
2867 e->manager = ccs_get_name(manager);
2868 if (e->manager) {
2869 error = ccs_update_policy(sizeof(*e), &param);
2870 ccs_put_name(e->manager);
2871 }
2872 return error;
2873 }
2874
2875 /**
2876 * ccs_write_manager - Write manager policy.
2877 *
2878 * @head: Pointer to "struct ccs_io_buffer".
2879 *
2880 * Returns 0 on success, negative value otherwise.
2881 */
2882 static int ccs_write_manager(struct ccs_io_buffer *head)
2883 {
2884 const char *data = head->write_buf;
2885 if (!strcmp(data, "manage_by_non_root")) {
2886 ccs_manage_by_non_root = !head->w.is_delete;
2887 return 0;
2888 }
2889 return ccs_update_manager_entry(data, head->w.is_delete);
2890 }
2891
2892 /**
2893 * ccs_read_manager - Read manager policy.
2894 *
2895 * @head: Pointer to "struct ccs_io_buffer".
2896 *
2897 * Returns nothing.
2898 *
2899 * Caller holds ccs_read_lock().
2900 */
2901 static void ccs_read_manager(struct ccs_io_buffer *head)
2902 {
2903 if (head->r.eof)
2904 return;
2905 list_for_each_cookie(head->r.acl, &ccs_kernel_namespace.
2906 policy_list[CCS_ID_MANAGER]) {
2907 struct ccs_manager *ptr =
2908 list_entry(head->r.acl, typeof(*ptr), head.list);
2909 if (ptr->head.is_deleted)
2910 continue;
2911 if (!ccs_flush(head))
2912 return;
2913 ccs_set_string(head, ptr->manager->name);
2914 ccs_set_lf(head);
2915 }
2916 head->r.eof = true;
2917 }
2918
2919 /**
2920 * ccs_manager - Check whether the current process is a policy manager.
2921 *
2922 * Returns true if the current process is permitted to modify policy
2923 * via /proc/ccs/ interface.
2924 *
2925 * Caller holds ccs_read_lock().
2926 */
2927 static bool ccs_manager(void)
2928 {
2929 struct ccs_manager *ptr;
2930 struct ccs_path_info exe;
2931 struct ccs_security *task = ccs_current_security();
2932 const struct ccs_path_info *domainname
2933 = ccs_current_domain()->domainname;
2934 bool found = false;
2935 if (!ccs_policy_loaded)
2936 return true;
2937 if (task->ccs_flags & CCS_TASK_IS_MANAGER)
2938 return true;
2939 if (!ccs_manage_by_non_root &&
2940 (!uid_eq(current_uid(), GLOBAL_ROOT_UID) ||
2941 !uid_eq(current_euid(), GLOBAL_ROOT_UID)))
2942 return false;
2943 exe.name = ccs_get_exe();
2944 if (!exe.name)
2945 return false;
2946 ccs_fill_path_info(&exe);
2947 list_for_each_entry_srcu(ptr, &ccs_kernel_namespace.
2948 policy_list[CCS_ID_MANAGER], head.list,
2949 &ccs_ss) {
2950 if (ptr->head.is_deleted)
2951 continue;
2952 if (ccs_pathcmp(domainname, ptr->manager) &&
2953 ccs_pathcmp(&exe, ptr->manager))
2954 continue;
2955 /* Set manager flag. */
2956 task->ccs_flags |= CCS_TASK_IS_MANAGER;
2957 found = true;
2958 break;
2959 }
2960 if (!found) { /* Reduce error messages. */
2961 static pid_t ccs_last_pid;
2962 const pid_t pid = current->pid;
2963 if (ccs_last_pid != pid) {
2964 printk(KERN_WARNING "%s ( %s ) is not permitted to "
2965 "update policies.\n", domainname->name,
2966 exe.name);
2967 ccs_last_pid = pid;
2968 }
2969 }
2970 kfree(exe.name);
2971 return found;
2972 }
2973
2974 /**
2975 * ccs_find_domain - Find a domain by the given name.
2976 *
2977 * @domainname: The domainname to find.
2978 *
2979 * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
2980 *
2981 * Caller holds ccs_read_lock().
2982 */
2983 static struct ccs_domain_info *ccs_find_domain(const char *domainname)
2984 {
2985 struct ccs_domain_info *domain;
2986 struct ccs_path_info name;
2987 name.name = domainname;
2988 ccs_fill_path_info(&name);
2989 list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
2990 if (!domain->is_deleted &&
2991 !ccs_pathcmp(&name, domain->domainname))
2992 return domain;
2993 }
2994 return NULL;
2995 }
2996
2997 /**
2998 * ccs_select_domain - Parse select command.
2999 *
3000 * @head: Pointer to "struct ccs_io_buffer".
3001 * @data: String to parse.
3002 *
3003 * Returns true on success, false otherwise.
3004 *
3005 * Caller holds ccs_read_lock().
3006 */
3007 static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data)
3008 {
3009 unsigned int pid;
3010 struct ccs_domain_info *domain = NULL;
3011 bool global_pid = false;
3012 if (strncmp(data, "select ", 7))
3013 return false;
3014 data += 7;
3015 if (sscanf(data, "pid=%u", &pid) == 1 ||
3016 (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
3017 struct task_struct *p;
3018 ccs_tasklist_lock();
3019 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
3020 if (global_pid)
3021 p = ccsecurity_exports.find_task_by_pid_ns(pid,
3022 &init_pid_ns);
3023 else
3024 p = ccsecurity_exports.find_task_by_vpid(pid);
3025 #else
3026 p = find_task_by_pid(pid);
3027 #endif
3028 if (p)
3029 domain = ccs_task_domain(p);
3030 ccs_tasklist_unlock();
3031 } else if (!strncmp(data, "domain=", 7)) {
3032 if (*(data + 7) == '<')
3033 domain = ccs_find_domain(data + 7);
3034 } else if (sscanf(data, "Q=%u", &pid) == 1) {
3035 domain = ccs_find_domain_by_qid(pid);
3036 } else
3037 return false;
3038 head->w.domain = domain;
3039 /* Accessing read_buf is safe because head->io_sem is held. */
3040 if (!head->read_buf)
3041 return true; /* Do nothing if open(O_WRONLY). */
3042 memset(&head->r, 0, sizeof(head->r));
3043 head->r.print_this_domain_only = true;
3044 if (domain)
3045 head->r.domain = &domain->list;
3046 else
3047 head->r.eof = true;
3048 ccs_io_printf(head, "# select %s\n", data);
3049 if (domain && domain->is_deleted)
3050 ccs_set_string(head, "# This is a deleted domain.\n");
3051 return true;
3052 }
3053
3054 /**
3055 * ccs_update_acl - Update "struct ccs_acl_info" entry.
3056 *
3057 * @size: Size of new entry in bytes.
3058 * @param: Pointer to "struct ccs_acl_param".
3059 *
3060 * Returns 0 on success, negative value otherwise.
3061 *
3062 * Caller holds ccs_read_lock().
3063 */
3064 static int ccs_update_acl(const int size, struct ccs_acl_param *param)
3065 {
3066 struct ccs_acl_info *new_entry = &param->e.acl_info;
3067 const bool is_delete = param->is_delete;
3068 int error = is_delete ? -ENOENT : -ENOMEM;
3069 struct ccs_acl_info *entry;
3070 struct list_head * const list = param->list;
3071 BUG_ON(size < sizeof(*entry));
3072 if (param->data[0]) {
3073 new_entry->cond = ccs_get_condition(param);
3074 if (!new_entry->cond)
3075 return -EINVAL;
3076 /*
3077 * Domain transition preference is allowed for only
3078 * "file execute"/"task auto_execute_handler"/
3079 * "task denied_auto_execute_handler" entries.
3080 */
3081 if (new_entry->cond->exec_transit &&
3082 !(new_entry->type == CCS_TYPE_PATH_ACL &&
3083 new_entry->perm == 1 << CCS_TYPE_EXECUTE)
3084 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3085 && new_entry->type != CCS_TYPE_AUTO_EXECUTE_HANDLER &&
3086 new_entry->type != CCS_TYPE_DENIED_EXECUTE_HANDLER
3087 #endif
3088 )
3089 return -EINVAL;
3090 }
3091 if (mutex_lock_interruptible(&ccs_policy_lock))
3092 return -ENOMEM;
3093 list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
3094 if (entry->is_deleted == CCS_GC_IN_PROGRESS)
3095 continue;
3096 if (entry->type != new_entry->type ||
3097 entry->cond != new_entry->cond ||
3098 memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
3099 continue;
3100 if (is_delete)
3101 entry->perm &= ~new_entry->perm;
3102 else
3103 entry->perm |= new_entry->perm;
3104 entry->is_deleted = !entry->perm;
3105 error = 0;
3106 break;
3107 }
3108 if (error && !is_delete) {
3109 entry = ccs_commit_ok(new_entry, size);
3110 if (entry) {
3111 list_add_tail_rcu(&entry->list, list);
3112 error = 0;
3113 }
3114 }
3115 mutex_unlock(&ccs_policy_lock);
3116 return error;
3117 }
3118
3119 /**
3120 * ccs_permstr - Find permission keywords.
3121 *
3122 * @string: String representation for permissions in foo/bar/buz format.
3123 * @keyword: Keyword to find from @string/
3124 *
3125 * Returns ture if @keyword was found in @string, false otherwise.
3126 *
3127 * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
3128 */
3129 static bool ccs_permstr(const char *string, const char *keyword)
3130 {
3131 const char *cp = strstr(string, keyword);
3132 if (cp)
3133 return cp == string || *(cp - 1) == '/';
3134 return false;
3135 }
3136
3137 /**
3138 * ccs_write_task - Update task related list.
3139 *
3140 * @param: Pointer to "struct ccs_acl_param".
3141 *
3142 * Returns 0 on success, negative value otherwise.
3143 *
3144 * Caller holds ccs_read_lock().
3145 */
3146 static int ccs_write_task(struct ccs_acl_param *param)
3147 {
3148 int error;
3149 const bool is_auto = ccs_str_starts(&param->data,
3150 "auto_domain_transition ");
3151 if (!is_auto && !ccs_str_starts(&param->data,
3152 "manual_domain_transition ")) {
3153 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3154 struct ccs_handler_acl *e = &param->e.handler_acl;
3155 char *handler;
3156 if (ccs_str_starts(&param->data, "auto_execute_handler "))
3157 e->head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER;
3158 else if (ccs_str_starts(&param->data,
3159 "denied_execute_handler "))
3160 e->head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER;
3161 else
3162 return -EINVAL;
3163 handler = ccs_read_token(param);
3164 if (!ccs_correct_path(handler))
3165 return -EINVAL;
3166 e->handler = ccs_get_name(handler);
3167 if (!e->handler)
3168 return -ENOMEM;
3169 if (e->handler->is_patterned)
3170 return -EINVAL; /* No patterns allowed. */
3171 return ccs_update_acl(sizeof(*e), param);
3172 #else
3173 error = -EINVAL;
3174 #endif
3175 } else {
3176 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
3177 struct ccs_task_acl *e = &param->e.task_acl;
3178 e->head.type = is_auto ?
3179 CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL;
3180 e->domainname = ccs_get_domainname(param);
3181 if (!e->domainname)
3182 return -EINVAL;
3183 return ccs_update_acl(sizeof(*e), param);
3184 #else
3185 error = -EINVAL;
3186 #endif
3187 }
3188 return error;
3189 }
3190
3191 #ifdef CONFIG_CCSECURITY_NETWORK
3192
3193 /**
3194 * ccs_write_inet_network - Write "struct ccs_inet_acl" list.
3195 *
3196 * @param: Pointer to "struct ccs_acl_param".
3197 *
3198 * Returns 0 on success, negative value otherwise.
3199 *
3200 * Caller holds ccs_read_lock().
3201 */
3202 static int ccs_write_inet_network(struct ccs_acl_param *param)
3203 {
3204 struct ccs_inet_acl *e = &param->e.inet_acl;
3205 u8 type;
3206 const char *protocol = ccs_read_token(param);
3207 const char *operation = ccs_read_token(param);
3208 e->head.type = CCS_TYPE_INET_ACL;
3209 for (type = 0; type < CCS_SOCK_MAX; type++)
3210 if (!strcmp(protocol, ccs_proto_keyword[type]))
3211 break;
3212 if (type == CCS_SOCK_MAX)
3213 return -EINVAL;
3214 e->protocol = type;
3215 e->head.perm = 0;
3216 for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
3217 if (ccs_permstr(operation, ccs_socket_keyword[type]))
3218 e->head.perm |= 1 << type;
3219 if (!e->head.perm)
3220 return -EINVAL;
3221 if (param->data[0] == '@') {
3222 param->data++;
3223 e->addres