~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/security/ccsecurity/policy_io.c

Version: ~ [ linux-5.1-rc5 ] ~ [ linux-5.0.7 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.34 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.111 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.168 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.178 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.138 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.65 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * security/ccsecurity/policy_io.c
  3  *
  4  * Copyright (C) 2005-2012  NTT DATA CORPORATION
  5  *
  6  * Version: 1.8.5   2015/11/11
  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 >= '') && (ch <= '9'))
786                 return ch - '';
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 - '') << 6) + ((c2 - '') << 3) + (c3 - '');
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         u8 recursion = 20;
1340         const char *const start = string;
1341         bool in_repetition = false;
1342         if (!len)
1343                 goto out;
1344         while (len--) {
1345                 unsigned char c = *string++;
1346                 if (c == '\\') {
1347                         if (!len--)
1348                                 goto out;
1349                         c = *string++;
1350                         if (c >= '' && c <= '3') {
1351                                 unsigned char d;
1352                                 unsigned char e;
1353                                 if (!len-- || !len--)
1354                                         goto out;
1355                                 d = *string++;
1356                                 e = *string++;
1357                                 if (d < '' || d > '7' || e < '' || e > '7')
1358                                         goto out;
1359                                 c = ccs_make_byte(c, d, e);
1360                                 if (c <= ' ' || c >= 127)
1361                                         continue;
1362                                 goto out;
1363                         }
1364                         switch (c) {
1365                         case '\\':  /* "\\" */
1366                         case '+':   /* "\+" */
1367                         case '?':   /* "\?" */
1368                         case 'x':   /* "\x" */
1369                         case 'a':   /* "\a" */
1370                         case '-':   /* "\-" */
1371                                 continue;
1372                         }
1373                         if (!recursion--)
1374                                 goto out;
1375                         switch (c) {
1376                         case '*':   /* "\*" */
1377                         case '@':   /* "\@" */
1378                         case '$':   /* "\$" */
1379                         case 'X':   /* "\X" */
1380                         case 'A':   /* "\A" */
1381                                 continue;
1382                         case '{':   /* "/\{" */
1383                                 if (string - 3 < start || *(string - 3) != '/')
1384                                         goto out;
1385                                 in_repetition = true;
1386                                 continue;
1387                         case '}':   /* "\}/" */
1388                                 if (*string != '/')
1389                                         goto out;
1390                                 if (!in_repetition)
1391                                         goto out;
1392                                 in_repetition = false;
1393                                 continue;
1394                         }
1395                         goto out;
1396                 } else if (in_repetition && c == '/') {
1397                         goto out;
1398                 } else if (c <= ' ' || c >= 127) {
1399                         goto out;
1400                 }
1401         }
1402         if (in_repetition)
1403                 goto out;
1404         return true;
1405 out:
1406         return false;
1407 }
1408 
1409 /**
1410  * ccs_correct_word - Check whether the given string follows the naming rules.
1411  *
1412  * @string: The string to check.
1413  *
1414  * Returns true if @string follows the naming rules, false otherwise.
1415  */
1416 static bool ccs_correct_word(const char *string)
1417 {
1418         return ccs_correct_word2(string, strlen(string));
1419 }
1420 
1421 /**
1422  * ccs_get_group - Allocate memory for "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group".
1423  *
1424  * @param: Pointer to "struct ccs_acl_param".
1425  * @idx:   Index number.
1426  *
1427  * Returns pointer to "struct ccs_group" on success, NULL otherwise.
1428  */
1429 static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
1430                                        const u8 idx)
1431 {
1432         struct ccs_group e = { };
1433         struct ccs_group *group = NULL;
1434         struct list_head *list;
1435         const char *group_name = ccs_read_token(param);
1436         bool found = false;
1437         if (!ccs_correct_word(group_name) || idx >= CCS_MAX_GROUP)
1438                 return NULL;
1439         e.group_name = ccs_get_name(group_name);
1440         if (!e.group_name)
1441                 return NULL;
1442         if (mutex_lock_interruptible(&ccs_policy_lock))
1443                 goto out;
1444         list = &param->ns->group_list[idx];
1445         list_for_each_entry(group, list, head.list) {
1446                 if (e.group_name != group->group_name ||
1447                     atomic_read(&group->head.users) == CCS_GC_IN_PROGRESS)
1448                         continue;
1449                 atomic_inc(&group->head.users);
1450                 found = true;
1451                 break;
1452         }
1453         if (!found) {
1454                 struct ccs_group *entry = ccs_commit_ok(&e, sizeof(e));
1455                 if (entry) {
1456                         INIT_LIST_HEAD(&entry->member_list);
1457                         atomic_set(&entry->head.users, 1);
1458                         list_add_tail_rcu(&entry->head.list, list);
1459                         group = entry;
1460                         found = true;
1461                 }
1462         }
1463         mutex_unlock(&ccs_policy_lock);
1464 out:
1465         ccs_put_name(e.group_name);
1466         return found ? group : NULL;
1467 }
1468 
1469 /**
1470  * ccs_parse_name_union - Parse a ccs_name_union.
1471  *
1472  * @param: Pointer to "struct ccs_acl_param".
1473  * @ptr:   Pointer to "struct ccs_name_union".
1474  *
1475  * Returns true on success, false otherwise.
1476  */
1477 static bool ccs_parse_name_union(struct ccs_acl_param *param,
1478                                  struct ccs_name_union *ptr)
1479 {
1480         char *filename;
1481         if (param->data[0] == '@') {
1482                 param->data++;
1483                 ptr->group = ccs_get_group(param, CCS_PATH_GROUP);
1484                 return ptr->group != NULL;
1485         }
1486         filename = ccs_read_token(param);
1487         if (!ccs_correct_word(filename))
1488                 return false;
1489         ptr->filename = ccs_get_name(filename);
1490         return ptr->filename != NULL;
1491 }
1492 
1493 /**
1494  * ccs_parse_ulong - Parse an "unsigned long" value.
1495  *
1496  * @result: Pointer to "unsigned long".
1497  * @str:    Pointer to string to parse.
1498  *
1499  * Returns one of values in "enum ccs_value_type".
1500  *
1501  * The @src is updated to point the first character after the value
1502  * on success.
1503  */
1504 static u8 ccs_parse_ulong(unsigned long *result, char **str)
1505 {
1506         const char *cp = *str;
1507         char *ep;
1508         int base = 10;
1509         if (*cp == '') {
1510                 char c = *(cp + 1);
1511                 if (c == 'x' || c == 'X') {
1512                         base = 16;
1513                         cp += 2;
1514                 } else if (c >= '' && c <= '7') {
1515                         base = 8;
1516                         cp++;
1517                 }
1518         }
1519         *result = simple_strtoul(cp, &ep, base);
1520         if (cp == ep)
1521                 return CCS_VALUE_TYPE_INVALID;
1522         *str = ep;
1523         switch (base) {
1524         case 16:
1525                 return CCS_VALUE_TYPE_HEXADECIMAL;
1526         case 8:
1527                 return CCS_VALUE_TYPE_OCTAL;
1528         default:
1529                 return CCS_VALUE_TYPE_DECIMAL;
1530         }
1531 }
1532 
1533 /**
1534  * ccs_parse_number_union - Parse a ccs_number_union.
1535  *
1536  * @param: Pointer to "struct ccs_acl_param".
1537  * @ptr:   Pointer to "struct ccs_number_union".
1538  *
1539  * Returns true on success, false otherwise.
1540  */
1541 static bool ccs_parse_number_union(struct ccs_acl_param *param,
1542                                    struct ccs_number_union *ptr)
1543 {
1544         char *data;
1545         u8 type;
1546         unsigned long v;
1547         memset(ptr, 0, sizeof(*ptr));
1548         if (param->data[0] == '@') {
1549                 param->data++;
1550                 ptr->group = ccs_get_group(param, CCS_NUMBER_GROUP);
1551                 return ptr->group != NULL;
1552         }
1553         data = ccs_read_token(param);
1554         type = ccs_parse_ulong(&v, &data);
1555         if (type == CCS_VALUE_TYPE_INVALID)
1556                 return false;
1557         ptr->values[0] = v;
1558         ptr->value_type[0] = type;
1559         if (!*data) {
1560                 ptr->values[1] = v;
1561                 ptr->value_type[1] = type;
1562                 return true;
1563         }
1564         if (*data++ != '-')
1565                 return false;
1566         type = ccs_parse_ulong(&v, &data);
1567         if (type == CCS_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
1568                 return false;
1569         ptr->values[1] = v;
1570         ptr->value_type[1] = type;
1571         return true;
1572 }
1573 
1574 #ifdef CONFIG_CCSECURITY_NETWORK
1575 
1576 /**
1577  * ccs_parse_ipaddr_union - Parse an IP address.
1578  *
1579  * @param: Pointer to "struct ccs_acl_param".
1580  * @ptr:   Pointer to "struct ccs_ipaddr_union".
1581  *
1582  * Returns true on success, false otherwise.
1583  */
1584 static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
1585                                    struct ccs_ipaddr_union *ptr)
1586 {
1587         u8 * const min = ptr->ip[0].in6_u.u6_addr8;
1588         u8 * const max = ptr->ip[1].in6_u.u6_addr8;
1589         char *address = ccs_read_token(param);
1590         const char *end;
1591         if (!strchr(address, ':') &&
1592             ccs_in4_pton(address, -1, min, '-', &end) > 0) {
1593                 ptr->is_ipv6 = false;
1594                 if (!*end)
1595                         ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
1596                 else if (*end++ != '-' ||
1597                          ccs_in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
1598                         return false;
1599                 return true;
1600         }
1601         if (ccs_in6_pton(address, -1, min, '-', &end) > 0) {
1602                 ptr->is_ipv6 = true;
1603                 if (!*end)
1604                         memmove(max, min, sizeof(u16) * 8);
1605                 else if (*end++ != '-' ||
1606                          ccs_in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
1607                         return false;
1608                 return true;
1609         }
1610         return false;
1611 }
1612 
1613 #endif
1614 
1615 /**
1616  * ccs_get_dqword - ccs_get_name() for a quoted string.
1617  *
1618  * @start: String to save.
1619  *
1620  * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
1621  */
1622 static const struct ccs_path_info *ccs_get_dqword(char *start)
1623 {
1624         char *cp = start + strlen(start) - 1;
1625         if (cp == start || *start++ != '"' || *cp != '"')
1626                 return NULL;
1627         *cp = '\0';
1628         if (*start && !ccs_correct_word(start))
1629                 return NULL;
1630         return ccs_get_name(start);
1631 }
1632 
1633 /**
1634  * ccs_parse_name_union_quoted - Parse a quoted word.
1635  *
1636  * @param: Pointer to "struct ccs_acl_param".
1637  * @ptr:   Pointer to "struct ccs_name_union".
1638  *
1639  * Returns true on success, false otherwise.
1640  */
1641 static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param,
1642                                         struct ccs_name_union *ptr)
1643 {
1644         char *filename = param->data;
1645         if (*filename == '@')
1646                 return ccs_parse_name_union(param, ptr);
1647         ptr->filename = ccs_get_dqword(filename);
1648         return ptr->filename != NULL;
1649 }
1650 
1651 /**
1652  * ccs_parse_argv - Parse an argv[] condition part.
1653  *
1654  * @left:  Lefthand value.
1655  * @right: Righthand value.
1656  * @argv:  Pointer to "struct ccs_argv".
1657  *
1658  * Returns true on success, false otherwise.
1659  */
1660 static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv)
1661 {
1662         if (ccs_parse_ulong(&argv->index, &left) != CCS_VALUE_TYPE_DECIMAL ||
1663             *left++ != ']' || *left)
1664                 return false;
1665         argv->value = ccs_get_dqword(right);
1666         return argv->value != NULL;
1667 }
1668 
1669 /**
1670  * ccs_parse_envp - Parse an envp[] condition part.
1671  *
1672  * @left:  Lefthand value.
1673  * @right: Righthand value.
1674  * @envp:  Pointer to "struct ccs_envp".
1675  *
1676  * Returns true on success, false otherwise.
1677  */
1678 static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp)
1679 {
1680         const struct ccs_path_info *name;
1681         const struct ccs_path_info *value;
1682         char *cp = left + strlen(left) - 1;
1683         if (*cp-- != ']' || *cp != '"')
1684                 goto out;
1685         *cp = '\0';
1686         if (!ccs_correct_word(left))
1687                 goto out;
1688         name = ccs_get_name(left);
1689         if (!name)
1690                 goto out;
1691         if (!strcmp(right, "NULL")) {
1692                 value = NULL;
1693         } else {
1694                 value = ccs_get_dqword(right);
1695                 if (!value) {
1696                         ccs_put_name(name);
1697                         goto out;
1698                 }
1699         }
1700         envp->name = name;
1701         envp->value = value;
1702         return true;
1703 out:
1704         return false;
1705 }
1706 
1707 /**
1708  * ccs_same_condition - Check for duplicated "struct ccs_condition" entry.
1709  *
1710  * @a: Pointer to "struct ccs_condition".
1711  * @b: Pointer to "struct ccs_condition".
1712  *
1713  * Returns true if @a == @b, false otherwise.
1714  */
1715 static bool ccs_same_condition(const struct ccs_condition *a,
1716                                const struct ccs_condition *b)
1717 {
1718         return a->size == b->size && a->condc == b->condc &&
1719                 a->numbers_count == b->numbers_count &&
1720                 a->names_count == b->names_count &&
1721                 a->argc == b->argc && a->envc == b->envc &&
1722                 a->grant_log == b->grant_log &&
1723                 a->exec_transit == b->exec_transit && a->transit == b->transit
1724                 && !memcmp(a + 1, b + 1, a->size - sizeof(*a));
1725 }
1726 
1727 /**
1728  * ccs_condition_type - Get condition type.
1729  *
1730  * @word: Keyword string.
1731  *
1732  * Returns one of values in "enum ccs_conditions_index" on success,
1733  * CCS_MAX_CONDITION_KEYWORD otherwise.
1734  */
1735 static u8 ccs_condition_type(const char *word)
1736 {
1737         u8 i;
1738         for (i = 0; i < CCS_MAX_CONDITION_KEYWORD; i++) {
1739                 if (!strcmp(word, ccs_condition_keyword[i]))
1740                         break;
1741         }
1742         return i;
1743 }
1744 
1745 /**
1746  * ccs_commit_condition - Commit "struct ccs_condition".
1747  *
1748  * @entry: Pointer to "struct ccs_condition".
1749  *
1750  * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
1751  *
1752  * This function merges duplicated entries. This function returns NULL if
1753  * @entry is not duplicated but memory quota for policy has exceeded.
1754  */
1755 static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry)
1756 {
1757         struct ccs_condition *ptr;
1758         bool found = false;
1759         if (mutex_lock_interruptible(&ccs_policy_lock)) {
1760                 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
1761                 ptr = NULL;
1762                 found = true;
1763                 goto out;
1764         }
1765         list_for_each_entry(ptr, &ccs_condition_list, head.list) {
1766                 if (!ccs_same_condition(ptr, entry) ||
1767                     atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS)
1768                         continue;
1769                 /* Same entry found. Share this entry. */
1770                 atomic_inc(&ptr->head.users);
1771                 found = true;
1772                 break;
1773         }
1774         if (!found) {
1775                 if (ccs_memory_ok(entry, entry->size)) {
1776                         atomic_set(&entry->head.users, 1);
1777                         list_add(&entry->head.list, &ccs_condition_list);
1778                 } else {
1779                         found = true;
1780                         ptr = NULL;
1781                 }
1782         }
1783         mutex_unlock(&ccs_policy_lock);
1784 out:
1785         if (found) {
1786                 ccs_del_condition(&entry->head.list);
1787                 kfree(entry);
1788                 entry = ptr;
1789         }
1790         return entry;
1791 }
1792 
1793 /**
1794  * ccs_correct_path - Check whether the given pathname follows the naming rules.
1795  *
1796  * @filename: The pathname to check.
1797  *
1798  * Returns true if @filename follows the naming rules, false otherwise.
1799  */
1800 static bool ccs_correct_path(const char *filename)
1801 {
1802         return *filename == '/' && ccs_correct_word(filename);
1803 }
1804 
1805 /**
1806  * ccs_domain_def - Check whether the given token can be a domainname.
1807  *
1808  * @buffer: The token to check.
1809  *
1810  * Returns true if @buffer possibly be a domainname, false otherwise.
1811  */
1812 static bool ccs_domain_def(const unsigned char *buffer)
1813 {
1814         const unsigned char *cp;
1815         int len;
1816         if (*buffer != '<')
1817                 return false;
1818         cp = strchr(buffer, ' ');
1819         if (!cp)
1820                 len = strlen(buffer);
1821         else
1822                 len = cp - buffer;
1823         if (buffer[len - 1] != '>' || !ccs_correct_word2(buffer + 1, len - 2))
1824                 return false;
1825         return true;
1826 }
1827 
1828 /**
1829  * ccs_correct_domain - Check whether the given domainname follows the naming rules.
1830  *
1831  * @domainname: The domainname to check.
1832  *
1833  * Returns true if @domainname follows the naming rules, false otherwise.
1834  */
1835 static bool ccs_correct_domain(const unsigned char *domainname)
1836 {
1837         if (!domainname || !ccs_domain_def(domainname))
1838                 return false;
1839         domainname = strchr(domainname, ' ');
1840         if (!domainname++)
1841                 return true;
1842         while (1) {
1843                 const unsigned char *cp = strchr(domainname, ' ');
1844                 if (!cp)
1845                         break;
1846                 if (*domainname != '/' ||
1847                     !ccs_correct_word2(domainname, cp - domainname))
1848                         return false;
1849                 domainname = cp + 1;
1850         }
1851         return ccs_correct_path(domainname);
1852 }
1853 
1854 /**
1855  * ccs_normalize_line - Format string.
1856  *
1857  * @buffer: The line to normalize.
1858  *
1859  * Returns nothing.
1860  *
1861  * Leading and trailing whitespaces are removed.
1862  * Multiple whitespaces are packed into single space.
1863  */
1864 static void ccs_normalize_line(unsigned char *buffer)
1865 {
1866         unsigned char *sp = buffer;
1867         unsigned char *dp = buffer;
1868         bool first = true;
1869         while (*sp && (*sp <= ' ' || *sp >= 127))
1870                 sp++;
1871         while (*sp) {
1872                 if (!first)
1873                         *dp++ = ' ';
1874                 first = false;
1875                 while (*sp > ' ' && *sp < 127)
1876                         *dp++ = *sp++;
1877                 while (*sp && (*sp <= ' ' || *sp >= 127))
1878                         sp++;
1879         }
1880         *dp = '\0';
1881 }
1882 
1883 /**
1884  * ccs_get_domainname - Read a domainname from a line.
1885  *
1886  * @param: Pointer to "struct ccs_acl_param".
1887  *
1888  * Returns a domainname on success, NULL otherwise.
1889  */
1890 static const struct ccs_path_info *ccs_get_domainname
1891 (struct ccs_acl_param *param)
1892 {
1893         char *start = param->data;
1894         char *pos = start;
1895         while (*pos) {
1896                 if (*pos++ != ' ' || *pos++ == '/')
1897                         continue;
1898                 pos -= 2;
1899                 *pos++ = '\0';
1900                 break;
1901         }
1902         param->data = pos;
1903         if (ccs_correct_domain(start))
1904                 return ccs_get_name(start);
1905         return NULL;
1906 }
1907 
1908 /**
1909  * ccs_get_transit_preference - Parse domain transition preference for execve().
1910  *
1911  * @param: Pointer to "struct ccs_acl_param".
1912  * @e:     Pointer to "struct ccs_condition".
1913  *
1914  * Returns the condition string part.
1915  */
1916 static char *ccs_get_transit_preference(struct ccs_acl_param *param,
1917                                         struct ccs_condition *e)
1918 {
1919         char * const pos = param->data;
1920         bool flag;
1921         if (*pos == '<') {
1922                 e->transit = ccs_get_domainname(param);
1923                 goto done;
1924         }
1925         {
1926                 char *cp = strchr(pos, ' ');
1927                 if (cp)
1928                         *cp = '\0';
1929                 flag = ccs_correct_path(pos) || !strcmp(pos, "keep") ||
1930                         !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
1931                         !strcmp(pos, "child") || !strcmp(pos, "parent");
1932                 if (cp)
1933                         *cp = ' ';
1934         }
1935         if (!flag)
1936                 return pos;
1937         e->transit = ccs_get_name(ccs_read_token(param));
1938 done:
1939         if (e->transit) {
1940                 e->exec_transit = true;
1941                 return param->data;
1942         }
1943         /*
1944          * Return a bad read-only condition string that will let
1945          * ccs_get_condition() return NULL.
1946          */
1947         return "/";
1948 }
1949 
1950 /**
1951  * ccs_get_condition - Parse condition part.
1952  *
1953  * @param: Pointer to "struct ccs_acl_param".
1954  *
1955  * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
1956  */
1957 struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param)
1958 {
1959         struct ccs_condition *entry = NULL;
1960         struct ccs_condition_element *condp = NULL;
1961         struct ccs_number_union *numbers_p = NULL;
1962         struct ccs_name_union *names_p = NULL;
1963         struct ccs_argv *argv = NULL;
1964         struct ccs_envp *envp = NULL;
1965         struct ccs_condition e = { };
1966         char * const start_of_string = ccs_get_transit_preference(param, &e);
1967         char * const end_of_string = start_of_string + strlen(start_of_string);
1968         char *pos;
1969 rerun:
1970         pos = start_of_string;
1971         while (1) {
1972                 u8 left = -1;
1973                 u8 right = -1;
1974                 char *left_word = pos;
1975                 char *cp;
1976                 char *right_word;
1977                 bool is_not;
1978                 if (!*left_word)
1979                         break;
1980                 /*
1981                  * Since left-hand condition does not allow use of "path_group"
1982                  * or "number_group" and environment variable's names do not
1983                  * accept '=', it is guaranteed that the original line consists
1984                  * of one or more repetition of $left$operator$right blocks
1985                  * where "$left is free from '=' and ' '" and "$operator is
1986                  * either '=' or '!='" and "$right is free from ' '".
1987                  * Therefore, we can reconstruct the original line at the end
1988                  * of dry run even if we overwrite $operator with '\0'.
1989                  */
1990                 cp = strchr(pos, ' ');
1991                 if (cp) {
1992                         *cp = '\0'; /* Will restore later. */
1993                         pos = cp + 1;
1994                 } else {
1995                         pos = "";
1996                 }
1997                 right_word = strchr(left_word, '=');
1998                 if (!right_word || right_word == left_word)
1999                         goto out;
2000                 is_not = *(right_word - 1) == '!';
2001                 if (is_not)
2002                         *(right_word++ - 1) = '\0'; /* Will restore later. */
2003                 else if (*(right_word + 1) != '=')
2004                         *right_word++ = '\0'; /* Will restore later. */
2005                 else
2006                         goto out;
2007                 dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
2008                         is_not ? "!" : "", right_word);
2009                 if (!strcmp(left_word, "grant_log")) {
2010                         if (entry) {
2011                                 if (is_not ||
2012                                     entry->grant_log != CCS_GRANTLOG_AUTO)
2013                                         goto out;
2014                                 else if (!strcmp(right_word, "yes"))
2015                                         entry->grant_log = CCS_GRANTLOG_YES;
2016                                 else if (!strcmp(right_word, "no"))
2017                                         entry->grant_log = CCS_GRANTLOG_NO;
2018                                 else
2019                                         goto out;
2020                         }
2021                         continue;
2022                 }
2023                 if (!strcmp(left_word, "auto_domain_transition")) {
2024                         if (entry) {
2025                                 if (is_not || entry->transit)
2026                                         goto out;
2027                                 entry->transit = ccs_get_dqword(right_word);
2028                                 if (!entry->transit ||
2029                                     (entry->transit->name[0] != '/' &&
2030                                      !ccs_domain_def(entry->transit->name)))
2031                                         goto out;
2032                         }
2033                         continue;
2034                 }
2035                 if (!strncmp(left_word, "exec.argv[", 10)) {
2036                         if (!argv) {
2037                                 e.argc++;
2038                                 e.condc++;
2039                         } else {
2040                                 e.argc--;
2041                                 e.condc--;
2042                                 left = CCS_ARGV_ENTRY;
2043                                 argv->is_not = is_not;
2044                                 if (!ccs_parse_argv(left_word + 10,
2045                                                     right_word, argv++))
2046                                         goto out;
2047                         }
2048                         goto store_value;
2049                 }
2050                 if (!strncmp(left_word, "exec.envp[\"", 11)) {
2051                         if (!envp) {
2052                                 e.envc++;
2053                                 e.condc++;
2054                         } else {
2055                                 e.envc--;
2056                                 e.condc--;
2057                                 left = CCS_ENVP_ENTRY;
2058                                 envp->is_not = is_not;
2059                                 if (!ccs_parse_envp(left_word + 11,
2060                                                     right_word, envp++))
2061                                         goto out;
2062                         }
2063                         goto store_value;
2064                 }
2065                 left = ccs_condition_type(left_word);
2066                 dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
2067                         left);
2068                 if (left == CCS_MAX_CONDITION_KEYWORD) {
2069                         if (!numbers_p) {
2070                                 e.numbers_count++;
2071                         } else {
2072                                 e.numbers_count--;
2073                                 left = CCS_NUMBER_UNION;
2074                                 param->data = left_word;
2075                                 if (*left_word == '@' ||
2076                                     !ccs_parse_number_union(param,
2077                                                             numbers_p++))
2078                                         goto out;
2079                         }
2080                 }
2081                 if (!condp)
2082                         e.condc++;
2083                 else
2084                         e.condc--;
2085                 if (left == CCS_EXEC_REALPATH || left == CCS_SYMLINK_TARGET) {
2086                         if (!names_p) {
2087                                 e.names_count++;
2088                         } else {
2089                                 e.names_count--;
2090                                 right = CCS_NAME_UNION;
2091                                 param->data = right_word;
2092                                 if (!ccs_parse_name_union_quoted(param,
2093                                                                  names_p++))
2094                                         goto out;
2095                         }
2096                         goto store_value;
2097                 }
2098                 right = ccs_condition_type(right_word);
2099                 if (right == CCS_MAX_CONDITION_KEYWORD) {
2100                         if (!numbers_p) {
2101                                 e.numbers_count++;
2102                         } else {
2103                                 e.numbers_count--;
2104                                 right = CCS_NUMBER_UNION;
2105                                 param->data = right_word;
2106                                 if (!ccs_parse_number_union(param,
2107                                                             numbers_p++))
2108                                         goto out;
2109                         }
2110                 }
2111 store_value:
2112                 if (!condp) {
2113                         dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
2114                                 "match=%u\n", __LINE__, left, right, !is_not);
2115                         continue;
2116                 }
2117                 condp->left = left;
2118                 condp->right = right;
2119                 condp->equals = !is_not;
2120                 dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
2121                         __LINE__, condp->left, condp->right,
2122                         condp->equals);
2123                 condp++;
2124         }
2125         dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
2126                 __LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
2127                 e.envc);
2128         if (entry) {
2129                 BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
2130                        e.condc);
2131                 return ccs_commit_condition(entry);
2132         }
2133         e.size = sizeof(*entry)
2134                 + e.condc * sizeof(struct ccs_condition_element)
2135                 + e.numbers_count * sizeof(struct ccs_number_union)
2136                 + e.names_count * sizeof(struct ccs_name_union)
2137                 + e.argc * sizeof(struct ccs_argv)
2138                 + e.envc * sizeof(struct ccs_envp);
2139         entry = kzalloc(e.size, CCS_GFP_FLAGS);
2140         if (!entry)
2141                 goto out2;
2142         *entry = e;
2143         e.transit = NULL;
2144         condp = (struct ccs_condition_element *) (entry + 1);
2145         numbers_p = (struct ccs_number_union *) (condp + e.condc);
2146         names_p = (struct ccs_name_union *) (numbers_p + e.numbers_count);
2147         argv = (struct ccs_argv *) (names_p + e.names_count);
2148         envp = (struct ccs_envp *) (argv + e.argc);
2149         {
2150                 bool flag = false;
2151                 for (pos = start_of_string; pos < end_of_string; pos++) {
2152                         if (*pos)
2153                                 continue;
2154                         if (flag) /* Restore " ". */
2155                                 *pos = ' ';
2156                         else if (*(pos + 1) == '=') /* Restore "!=". */
2157                                 *pos = '!';
2158                         else /* Restore "=". */
2159                                 *pos = '=';
2160                         flag = !flag;
2161                 }
2162         }
2163         goto rerun;
2164 out:
2165         dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
2166         if (entry) {
2167                 ccs_del_condition(&entry->head.list);
2168                 kfree(entry);
2169         }
2170 out2:
2171         ccs_put_name(e.transit);
2172         return NULL;
2173 }
2174 
2175 /**
2176  * ccs_yesno - Return "yes" or "no".
2177  *
2178  * @value: Bool value.
2179  *
2180  * Returns "yes" if @value is not 0, "no" otherwise.
2181  */
2182 static const char *ccs_yesno(const unsigned int value)
2183 {
2184         return value ? "yes" : "no";
2185 }
2186 
2187 /**
2188  * ccs_addprintf - strncat()-like-snprintf().
2189  *
2190  * @buffer: Buffer to write to. Must be '\0'-terminated.
2191  * @len:    Size of @buffer.
2192  * @fmt:    The printf()'s format string, followed by parameters.
2193  *
2194  * Returns nothing.
2195  */
2196 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
2197 {
2198         va_list args;
2199         const int pos = strlen(buffer);
2200         va_start(args, fmt);
2201         vsnprintf(buffer + pos, len - pos - 1, fmt, args);
2202         va_end(args);
2203 }
2204 
2205 /**
2206  * ccs_flush - Flush queued string to userspace's buffer.
2207  *
2208  * @head: Pointer to "struct ccs_io_buffer".
2209  *
2210  * Returns true if all data was flushed, false otherwise.
2211  */
2212 static bool ccs_flush(struct ccs_io_buffer *head)
2213 {
2214         while (head->r.w_pos) {
2215                 const char *w = head->r.w[0];
2216                 size_t len = strlen(w);
2217                 if (len) {
2218                         if (len > head->read_user_buf_avail)
2219                                 len = head->read_user_buf_avail;
2220                         if (!len)
2221                                 return false;
2222                         if (copy_to_user(head->read_user_buf, w, len))
2223                                 return false;
2224                         head->read_user_buf_avail -= len;
2225                         head->read_user_buf += len;
2226                         w += len;
2227                 }
2228                 head->r.w[0] = w;
2229                 if (*w)
2230                         return false;
2231                 /* Add '\0' for audit logs and query. */
2232                 if (head->type == CCS_AUDIT || head->type == CCS_QUERY) {
2233                         if (!head->read_user_buf_avail ||
2234                             copy_to_user(head->read_user_buf, "", 1))
2235                                 return false;
2236                         head->read_user_buf_avail--;
2237                         head->read_user_buf++;
2238                 }
2239                 head->r.w_pos--;
2240                 for (len = 0; len < head->r.w_pos; len++)
2241                         head->r.w[len] = head->r.w[len + 1];
2242         }
2243         head->r.avail = 0;
2244         return true;
2245 }
2246 
2247 /**
2248  * ccs_set_string - Queue string to "struct ccs_io_buffer" structure.
2249  *
2250  * @head:   Pointer to "struct ccs_io_buffer".
2251  * @string: String to print.
2252  *
2253  * Returns nothing.
2254  *
2255  * Note that @string has to be kept valid until @head is kfree()d.
2256  * This means that char[] allocated on stack memory cannot be passed to
2257  * this function. Use ccs_io_printf() for char[] allocated on stack memory.
2258  */
2259 static void ccs_set_string(struct ccs_io_buffer *head, const char *string)
2260 {
2261         if (head->r.w_pos < CCS_MAX_IO_READ_QUEUE) {
2262                 head->r.w[head->r.w_pos++] = string;
2263                 ccs_flush(head);
2264         } else
2265                 printk(KERN_WARNING "Too many words in a line.\n");
2266 }
2267 
2268 /**
2269  * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
2270  *
2271  * @head: Pointer to "struct ccs_io_buffer".
2272  * @fmt:  The printf()'s format string, followed by parameters.
2273  *
2274  * Returns nothing.
2275  */
2276 static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
2277 {
2278         va_list args;
2279         size_t len;
2280         size_t pos = head->r.avail;
2281         int size = head->readbuf_size - pos;
2282         if (size <= 0)
2283                 return;
2284         va_start(args, fmt);
2285         len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1;
2286         va_end(args);
2287         if (pos + len >= head->readbuf_size) {
2288                 printk(KERN_WARNING "Too many words in a line.\n");
2289                 return;
2290         }
2291         head->r.avail += len;
2292         ccs_set_string(head, head->read_buf + pos);
2293 }
2294 
2295 /**
2296  * ccs_set_space - Put a space to "struct ccs_io_buffer" structure.
2297  *
2298  * @head: Pointer to "struct ccs_io_buffer".
2299  *
2300  * Returns nothing.
2301  */
2302 static void ccs_set_space(struct ccs_io_buffer *head)
2303 {
2304         ccs_set_string(head, " ");
2305 }
2306 
2307 /**
2308  * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure.
2309  *
2310  * @head: Pointer to "struct ccs_io_buffer".
2311  *
2312  * Returns true if all data was flushed, false otherwise.
2313  */
2314 static bool ccs_set_lf(struct ccs_io_buffer *head)
2315 {
2316         ccs_set_string(head, "\n");
2317         return !head->r.w_pos;
2318 }
2319 
2320 /**
2321  * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure.
2322  *
2323  * @head: Pointer to "struct ccs_io_buffer".
2324  *
2325  * Returns nothing.
2326  */
2327 static void ccs_set_slash(struct ccs_io_buffer *head)
2328 {
2329         ccs_set_string(head, "/");
2330 }
2331 
2332 /**
2333  * ccs_init_policy_namespace - Initialize namespace.
2334  *
2335  * @ns: Pointer to "struct ccs_policy_namespace".
2336  *
2337  * Returns nothing.
2338  */
2339 static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns)
2340 {
2341         unsigned int idx;
2342         for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++)
2343                 INIT_LIST_HEAD(&ns->acl_group[idx]);
2344         for (idx = 0; idx < CCS_MAX_GROUP; idx++)
2345                 INIT_LIST_HEAD(&ns->group_list[idx]);
2346         for (idx = 0; idx < CCS_MAX_POLICY; idx++)
2347                 INIT_LIST_HEAD(&ns->policy_list[idx]);
2348         ns->profile_version = 20150505;
2349         ccs_namespace_enabled = !list_empty(&ccs_namespace_list);
2350         list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list);
2351 }
2352 
2353 /**
2354  * ccs_print_namespace - Print namespace header.
2355  *
2356  * @head: Pointer to "struct ccs_io_buffer".
2357  *
2358  * Returns nothing.
2359  */
2360 static void ccs_print_namespace(struct ccs_io_buffer *head)
2361 {
2362         if (!ccs_namespace_enabled)
2363                 return;
2364         ccs_set_string(head,
2365                        container_of(head->r.ns, struct ccs_policy_namespace,
2366                                     namespace_list)->name);
2367         ccs_set_space(head);
2368 }
2369 
2370 /**
2371  * ccs_assign_profile - Create a new profile.
2372  *
2373  * @ns:      Pointer to "struct ccs_policy_namespace".
2374  * @profile: Profile number to create.
2375  *
2376  * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
2377  */
2378 static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
2379                                               const unsigned int profile)
2380 {
2381         struct ccs_profile *ptr;
2382         struct ccs_profile *entry;
2383         if (profile >= CCS_MAX_PROFILES)
2384                 return NULL;
2385         ptr = ns->profile_ptr[profile];
2386         if (ptr)
2387                 return ptr;
2388         entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
2389         if (mutex_lock_interruptible(&ccs_policy_lock))
2390                 goto out;
2391         ptr = ns->profile_ptr[profile];
2392         if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
2393                 ptr = entry;
2394                 ptr->default_config = CCS_CONFIG_DISABLED |
2395                         CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
2396                 memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
2397                        sizeof(ptr->config));
2398                 ptr->pref[CCS_PREF_MAX_AUDIT_LOG] =
2399                         CONFIG_CCSECURITY_MAX_AUDIT_LOG;
2400                 ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
2401                         CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
2402                 mb(); /* Avoid out-of-order execution. */
2403                 ns->profile_ptr[profile] = ptr;
2404                 entry = NULL;
2405         }
2406         mutex_unlock(&ccs_policy_lock);
2407 out:
2408         kfree(entry);
2409         return ptr;
2410 }
2411 
2412 /**
2413  * ccs_check_profile - Check all profiles currently assigned to domains are defined.
2414  *
2415  * Returns nothing.
2416  */
2417 static void ccs_check_profile(void)
2418 {
2419         struct ccs_domain_info *domain;
2420         const int idx = ccs_read_lock();
2421         ccs_policy_loaded = true;
2422         printk(KERN_INFO "CCSecurity: 1.8.5   2015/11/11\n");
2423         list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
2424                 const u8 profile = domain->profile;
2425                 struct ccs_policy_namespace *ns = domain->ns;
2426                 if (ns->profile_version == 20100903) {
2427                         static bool done;
2428                         if (!done)
2429                                 printk(KERN_INFO "Converting profile version "
2430                                        "from %u to %u.\n", 20100903, 20150505);
2431                         done = true;
2432                         ns->profile_version = 20150505;
2433                 }
2434                 if (ns->profile_version != 20150505)
2435                         printk(KERN_ERR
2436                                "Profile version %u is not supported.\n",
2437                                ns->profile_version);
2438                 else if (!ns->profile_ptr[profile])
2439                         printk(KERN_ERR
2440                                "Profile %u (used by '%s') is not defined.\n",
2441                                profile, domain->domainname->name);
2442                 else
2443                         continue;
2444                 printk(KERN_ERR
2445                        "Userland tools for TOMOYO 1.8 must be installed and "
2446                        "policy must be initialized.\n");
2447                 printk(KERN_ERR "Please see http://tomoyo.osdn.jp/1.8/ "
2448                        "for more information.\n");
2449                 panic("STOP!");
2450         }
2451         ccs_read_unlock(idx);
2452 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY)
2453         ccsecurity_exports.add_hooks();
2454 #endif
2455         printk(KERN_INFO "Mandatory Access Control activated.\n");
2456 }
2457 
2458 /**
2459  * ccs_profile - Find a profile.
2460  *
2461  * @profile: Profile number to find.
2462  *
2463  * Returns pointer to "struct ccs_profile".
2464  */
2465 static struct ccs_profile *ccs_profile(const u8 profile)
2466 {
2467         static struct ccs_profile ccs_null_profile;
2468         struct ccs_profile *ptr = ccs_current_namespace()->
2469                 profile_ptr[profile];
2470         if (!ptr)
2471                 ptr = &ccs_null_profile;
2472         return ptr;
2473 }
2474 
2475 /**
2476  * ccs_get_config - Get config for specified profile's specified functionality.
2477  *
2478  * @profile: Profile number.
2479  * @index:   Index number of functionality.
2480  *
2481  * Returns config.
2482  *
2483  * First, check for CONFIG::category::functionality.
2484  * If CONFIG::category::functionality is set to use default, then check
2485  * CONFIG::category. If CONFIG::category is set to use default, then use
2486  * CONFIG. CONFIG cannot be set to use default.
2487  */
2488 u8 ccs_get_config(const u8 profile, const u8 index)
2489 {
2490         u8 config;
2491         const struct ccs_profile *p;
2492         if (!ccs_policy_loaded)
2493                 return CCS_CONFIG_DISABLED;
2494         p = ccs_profile(profile);
2495         config = p->config[index];
2496         if (config == CCS_CONFIG_USE_DEFAULT)
2497                 config = p->config[ccs_index2category[index]
2498                                    + CCS_MAX_MAC_INDEX];
2499         if (config == CCS_CONFIG_USE_DEFAULT)
2500                 config = p->default_config;
2501         return config;
2502 }
2503 
2504 /**
2505  * ccs_find_yesno - Find values for specified keyword.
2506  *
2507  * @string: String to check.
2508  * @find:   Name of keyword.
2509  *
2510  * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
2511  */
2512 static s8 ccs_find_yesno(const char *string, const char *find)
2513 {
2514         const char *cp = strstr(string, find);
2515         if (cp) {
2516                 cp += strlen(find);
2517                 if (!strncmp(cp, "=yes", 4))
2518                         return 1;
2519                 else if (!strncmp(cp, "=no", 3))
2520                         return 0;
2521         }
2522         return -1;
2523 }
2524 
2525 /**
2526  * ccs_set_uint - Set value for specified preference.
2527  *
2528  * @i:      Pointer to "unsigned int".
2529  * @string: String to check.
2530  * @find:   Name of keyword.
2531  *
2532  * Returns nothing.
2533  */
2534 static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
2535 {
2536         const char *cp = strstr(string, find);
2537         if (cp)
2538                 sscanf(cp + strlen(find), "=%u", i);
2539 }
2540 
2541 /**
2542  * ccs_str_starts - Check whether the given string starts with the given keyword.
2543  *
2544  * @src:  Pointer to pointer to the string.
2545  * @find: Pointer to the keyword.
2546  *
2547  * Returns true if @src starts with @find, false otherwise.
2548  *
2549  * The @src is updated to point the first character after the @find
2550  * if @src starts with @find.
2551  */
2552 static bool ccs_str_starts(char **src, const char *find)
2553 {
2554         const int len = strlen(find);
2555         char *tmp = *src;
2556         if (strncmp(tmp, find, len))
2557                 return false;
2558         tmp += len;
2559         *src = tmp;
2560         return true;
2561 }
2562 
2563 /**
2564  * ccs_print_group - Print group's name.
2565  *
2566  * @head:  Pointer to "struct ccs_io_buffer".
2567  * @group: Pointer to "struct ccsgroup". Maybe NULL.
2568  *
2569  * Returns true if @group is not NULL. false otherwise.
2570  */
2571 static bool ccs_print_group(struct ccs_io_buffer *head,
2572                             const struct ccs_group *group)
2573 {
2574         if (group) {
2575                 ccs_set_string(head, "@");
2576                 ccs_set_string(head, group->group_name->name);
2577                 return true;
2578         }
2579         return false;
2580 }
2581 
2582 /**
2583  * ccs_set_mode - Set mode for specified profile.
2584  *
2585  * @name:    Name of functionality.
2586  * @value:   Mode for @name.
2587  * @profile: Pointer to "struct ccs_profile".
2588  *
2589  * Returns 0 on success, negative value otherwise.
2590  */
2591 static int ccs_set_mode(char *name, const char *value,
2592                         struct ccs_profile *profile)
2593 {
2594         u8 i;
2595         u8 config;
2596         if (!strcmp(name, "CONFIG")) {
2597                 i = CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
2598                 config = profile->default_config;
2599         } else if (ccs_str_starts(&name, "CONFIG::")) {
2600                 config = 0;
2601                 for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
2602                      i++) {
2603                         int len = 0;
2604                         if (i < CCS_MAX_MAC_INDEX) {
2605                                 const u8 c = ccs_index2category[i];
2606                                 const char *category =
2607                                         ccs_category_keywords[c];
2608                                 len = strlen(category);
2609                                 if (strncmp(name, category, len) ||
2610                                     name[len++] != ':' || name[len++] != ':')
2611                                         continue;
2612                         }
2613                         if (strcmp(name + len, ccs_mac_keywords[i]))
2614                                 continue;
2615                         config = profile->config[i];
2616                         break;
2617                 }
2618                 if (i == CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
2619                         return -EINVAL;
2620         } else {
2621                 return -EINVAL;
2622         }
2623         if (strstr(value, "use_default")) {
2624                 config = CCS_CONFIG_USE_DEFAULT;
2625         } else {
2626                 u8 mode;
2627                 for (mode = 0; mode < CCS_CONFIG_MAX_MODE; mode++)
2628                         if (strstr(value, ccs_mode[mode]))
2629                                 /*
2630                                  * Update lower 3 bits in order to distinguish
2631                                  * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
2632                                  */
2633                                 config = (config & ~7) | mode;
2634                 if (config != CCS_CONFIG_USE_DEFAULT) {
2635                         switch (ccs_find_yesno(value, "grant_log")) {
2636                         case 1:
2637                                 config |= CCS_CONFIG_WANT_GRANT_LOG;
2638                                 break;
2639                         case 0:
2640                                 config &= ~CCS_CONFIG_WANT_GRANT_LOG;
2641                                 break;
2642                         }
2643                         switch (ccs_find_yesno(value, "reject_log")) {
2644                         case 1:
2645                                 config |= CCS_CONFIG_WANT_REJECT_LOG;
2646                                 break;
2647                         case 0:
2648                                 config &= ~CCS_CONFIG_WANT_REJECT_LOG;
2649                                 break;
2650                         }
2651                 }
2652         }
2653         if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
2654                 profile->config[i] = config;
2655         else if (config != CCS_CONFIG_USE_DEFAULT)
2656                 profile->default_config = config;
2657         return 0;
2658 }
2659 
2660 /**
2661  * ccs_write_profile - Write profile table.
2662  *
2663  * @head: Pointer to "struct ccs_io_buffer".
2664  *
2665  * Returns 0 on success, negative value otherwise.
2666  */
2667 static int ccs_write_profile(struct ccs_io_buffer *head)
2668 {
2669         char *data = head->write_buf;
2670         unsigned int i;
2671         char *cp;
2672         struct ccs_profile *profile;
2673         if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
2674             == 1)
2675                 return 0;
2676         i = simple_strtoul(data, &cp, 10);
2677         if (*cp != '-')
2678                 return -EINVAL;
2679         data = cp + 1;
2680         profile = ccs_assign_profile(head->w.ns, i);
2681         if (!profile)
2682                 return -EINVAL;
2683         cp = strchr(data, '=');
2684         if (!cp)
2685                 return -EINVAL;
2686         *cp++ = '\0';
2687         if (!strcmp(data, "COMMENT")) {
2688                 static DEFINE_SPINLOCK(lock);
2689                 const struct ccs_path_info *new_comment = ccs_get_name(cp);
2690                 const struct ccs_path_info *old_comment;
2691                 if (!new_comment)
2692                         return -ENOMEM;
2693                 spin_lock(&lock);
2694                 old_comment = profile->comment;
2695                 profile->comment = new_comment;
2696                 spin_unlock(&lock);
2697                 ccs_put_name(old_comment);
2698                 return 0;
2699         }
2700         if (!strcmp(data, "PREFERENCE")) {
2701                 for (i = 0; i < CCS_MAX_PREF; i++)
2702                         ccs_set_uint(&profile->pref[i], cp,
2703                                      ccs_pref_keywords[i]);
2704                 return 0;
2705         }
2706         return ccs_set_mode(data, cp, profile);
2707 }
2708 
2709 /**
2710  * ccs_print_config - Print mode for specified functionality.
2711  *
2712  * @head:   Pointer to "struct ccs_io_buffer".
2713  * @config: Mode for that functionality.
2714  *
2715  * Returns nothing.
2716  *
2717  * Caller prints functionality's name.
2718  */
2719 static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)
2720 {
2721         ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
2722                       ccs_mode[config & 3],
2723                       ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),
2724                       ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));
2725 }
2726 
2727 /**
2728  * ccs_read_profile - Read profile table.
2729  *
2730  * @head: Pointer to "struct ccs_io_buffer".
2731  *
2732  * Returns nothing.
2733  */
2734 static void ccs_read_profile(struct ccs_io_buffer *head)
2735 {
2736         u8 index;
2737         struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2738                                                        namespace_list);
2739         const struct ccs_profile *profile;
2740         if (head->r.eof)
2741                 return;
2742 next:
2743         index = head->r.index;
2744         profile = ns->profile_ptr[index];
2745         switch (head->r.step) {
2746         case 0:
2747                 ccs_print_namespace(head);
2748                 ccs_io_printf(head, "PROFILE_VERSION=%u\n",
2749                               ns->profile_version);
2750                 head->r.step++;
2751                 break;
2752         case 1:
2753                 for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++)
2754                         if (ns->profile_ptr[head->r.index])
2755                                 break;
2756                 if (head->r.index == CCS_MAX_PROFILES) {
2757                         head->r.eof = true;
2758                         return;
2759                 }
2760                 head->r.step++;
2761                 break;
2762         case 2:
2763                 {
2764                         u8 i;
2765                         const struct ccs_path_info *comment = profile->comment;
2766                         ccs_print_namespace(head);
2767                         ccs_io_printf(head, "%u-COMMENT=", index);
2768                         ccs_set_string(head, comment ? comment->name : "");
2769                         ccs_set_lf(head);
2770                         ccs_print_namespace(head);
2771                         ccs_io_printf(head, "%u-PREFERENCE={ ", index);
2772                         for (i = 0; i < CCS_MAX_PREF; i++)
2773                                 ccs_io_printf(head, "%s=%u ",
2774                                               ccs_pref_keywords[i],
2775                                               profile->pref[i]);
2776                         ccs_set_string(head, "}\n");
2777                         head->r.step++;
2778                 }
2779                 break;
2780         case 3:
2781                 {
2782                         ccs_print_namespace(head);
2783                         ccs_io_printf(head, "%u-%s", index, "CONFIG");
2784                         ccs_print_config(head, profile->default_config);
2785                         head->r.bit = 0;
2786                         head->r.step++;
2787                 }
2788                 break;
2789         case 4:
2790                 for ( ; head->r.bit < CCS_MAX_MAC_INDEX
2791                               + CCS_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {
2792                         const u8 i = head->r.bit;
2793                         const u8 config = profile->config[i];
2794                         if (config == CCS_CONFIG_USE_DEFAULT)
2795                                 continue;
2796                         ccs_print_namespace(head);
2797                         if (i < CCS_MAX_MAC_INDEX)
2798                                 ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
2799                                               ccs_category_keywords
2800                                               [ccs_index2category[i]],
2801                                               ccs_mac_keywords[i]);
2802                         else
2803                                 ccs_io_printf(head, "%u-CONFIG::%s", index,
2804                                               ccs_mac_keywords[i]);
2805                         ccs_print_config(head, config);
2806                         head->r.bit++;
2807                         break;
2808                 }
2809                 if (head->r.bit == CCS_MAX_MAC_INDEX
2810                     + CCS_MAX_MAC_CATEGORY_INDEX) {
2811                         head->r.index++;
2812                         head->r.step = 1;
2813                 }
2814                 break;
2815         }
2816         if (ccs_flush(head))
2817                 goto next;
2818 }
2819 
2820 /**
2821  * ccs_update_policy - Update an entry for exception policy.
2822  *
2823  * @size:  Size of new entry in bytes.
2824  * @param: Pointer to "struct ccs_acl_param".
2825  *
2826  * Returns 0 on success, negative value otherwise.
2827  *
2828  * Caller holds ccs_read_lock().
2829  */
2830 static int ccs_update_policy(const int size, struct ccs_acl_param *param)
2831 {
2832         struct ccs_acl_head *new_entry = &param->e.acl_head;
2833         int error = param->is_delete ? -ENOENT : -ENOMEM;
2834         struct ccs_acl_head *entry;
2835         struct list_head *list = param->list;
2836         BUG_ON(size < sizeof(*entry));
2837         if (mutex_lock_interruptible(&ccs_policy_lock))
2838                 return -ENOMEM;
2839         list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
2840                 if (entry->is_deleted == CCS_GC_IN_PROGRESS)
2841                         continue;
2842                 if (memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
2843                         continue;
2844                 entry->is_deleted = param->is_delete;
2845                 error = 0;
2846                 break;
2847         }
2848         if (error && !param->is_delete) {
2849                 entry = ccs_commit_ok(new_entry, size);
2850                 if (entry) {
2851                         list_add_tail_rcu(&entry->list, list);
2852                         error = 0;
2853                 }
2854         }
2855         mutex_unlock(&ccs_policy_lock);
2856         return error;
2857 }
2858 
2859 /**
2860  * ccs_update_manager_entry - Add a manager entry.
2861  *
2862  * @manager:   The path to manager or the domainnamme.
2863  * @is_delete: True if it is a delete request.
2864  *
2865  * Returns 0 on success, negative value otherwise.
2866  */
2867 static int ccs_update_manager_entry(const char *manager,
2868                                     const bool is_delete)
2869 {
2870         struct ccs_acl_param param = {
2871                 /* .ns = &ccs_kernel_namespace, */
2872                 .is_delete = is_delete,
2873                 .list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER],
2874         };
2875         struct ccs_manager *e = &param.e.manager;
2876         int error = is_delete ? -ENOENT : -ENOMEM;
2877         /* Forced zero clear for using memcmp() at ccs_update_policy(). */
2878         memset(&param.e, 0, sizeof(param.e));
2879         if (!ccs_correct_domain(manager) && !ccs_correct_word(manager))
2880                 return -EINVAL;
2881         e->manager = ccs_get_name(manager);
2882         if (e->manager) {
2883                 error = ccs_update_policy(sizeof(*e), &param);
2884                 ccs_put_name(e->manager);
2885         }
2886         return error;
2887 }
2888 
2889 /**
2890  * ccs_write_manager - Write manager policy.
2891  *
2892  * @head: Pointer to "struct ccs_io_buffer".
2893  *
2894  * Returns 0 on success, negative value otherwise.
2895  */
2896 static int ccs_write_manager(struct ccs_io_buffer *head)
2897 {
2898         const char *data = head->write_buf;
2899         if (!strcmp(data, "manage_by_non_root")) {
2900                 ccs_manage_by_non_root = !head->w.is_delete;
2901                 return 0;
2902         }
2903         return ccs_update_manager_entry(data, head->w.is_delete);
2904 }
2905 
2906 /**
2907  * ccs_read_manager - Read manager policy.
2908  *
2909  * @head: Pointer to "struct ccs_io_buffer".
2910  *
2911  * Returns nothing.
2912  *
2913  * Caller holds ccs_read_lock().
2914  */
2915 static void ccs_read_manager(struct ccs_io_buffer *head)
2916 {
2917         if (head->r.eof)
2918                 return;
2919         list_for_each_cookie(head->r.acl, &ccs_kernel_namespace.
2920                              policy_list[CCS_ID_MANAGER]) {
2921                 struct ccs_manager *ptr =
2922                         list_entry(head->r.acl, typeof(*ptr), head.list);
2923                 if (ptr->head.is_deleted)
2924                         continue;
2925                 if (!ccs_flush(head))
2926                         return;
2927                 ccs_set_string(head, ptr->manager->name);
2928                 ccs_set_lf(head);
2929         }
2930         head->r.eof = true;
2931 }
2932 
2933 /**
2934  * ccs_manager - Check whether the current process is a policy manager.
2935  *
2936  * Returns true if the current process is permitted to modify policy
2937  * via /proc/ccs/ interface.
2938  *
2939  * Caller holds ccs_read_lock().
2940  */
2941 static bool ccs_manager(void)
2942 {
2943         struct ccs_manager *ptr;
2944         struct ccs_path_info exe;
2945         struct ccs_security *task = ccs_current_security();
2946         const struct ccs_path_info *domainname
2947                 = ccs_current_domain()->domainname;
2948         bool found = false;
2949         if (!ccs_policy_loaded)
2950                 return true;
2951         if (task->ccs_flags & CCS_TASK_IS_MANAGER)
2952                 return true;
2953         if (!ccs_manage_by_non_root &&
2954             (!uid_eq(current_uid(), GLOBAL_ROOT_UID) ||
2955              !uid_eq(current_euid(), GLOBAL_ROOT_UID)))
2956                 return false;
2957         exe.name = ccs_get_exe();
2958         if (!exe.name)
2959                 return false;
2960         ccs_fill_path_info(&exe);
2961         list_for_each_entry_srcu(ptr, &ccs_kernel_namespace.
2962                                  policy_list[CCS_ID_MANAGER], head.list,
2963                                  &ccs_ss) {
2964                 if (ptr->head.is_deleted)
2965                         continue;
2966                 if (ccs_pathcmp(domainname, ptr->manager) &&
2967                     ccs_pathcmp(&exe, ptr->manager))
2968                         continue;
2969                 /* Set manager flag. */
2970                 task->ccs_flags |= CCS_TASK_IS_MANAGER;
2971                 found = true;
2972                 break;
2973         }
2974         if (!found) { /* Reduce error messages. */
2975                 static pid_t ccs_last_pid;
2976                 const pid_t pid = current->pid;
2977                 if (ccs_last_pid != pid) {
2978                         printk(KERN_WARNING "%s ( %s ) is not permitted to "
2979                                "update policies.\n", domainname->name,
2980                                exe.name);
2981                         ccs_last_pid = pid;
2982                 }
2983         }
2984         kfree(exe.name);
2985         return found;
2986 }
2987 
2988 /**
2989  * ccs_find_domain - Find a domain by the given name.
2990  *
2991  * @domainname: The domainname to find.
2992  *
2993  * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
2994  *
2995  * Caller holds ccs_read_lock().
2996  */
2997 static struct ccs_domain_info *ccs_find_domain(const char *domainname)
2998 {
2999         struct ccs_domain_info *domain;
3000         struct ccs_path_info name;
3001         name.name = domainname;
3002         ccs_fill_path_info(&name);
3003         list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
3004                 if (!domain->is_deleted &&
3005                     !ccs_pathcmp(&name, domain->domainname))
3006                         return domain;
3007         }
3008         return NULL;
3009 }
3010 
3011 /**
3012  * ccs_select_domain - Parse select command.
3013  *
3014  * @head: Pointer to "struct ccs_io_buffer".
3015  * @data: String to parse.
3016  *
3017  * Returns true on success, false otherwise.
3018  *
3019  * Caller holds ccs_read_lock().
3020  */
3021 static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data)
3022 {
3023         unsigned int pid;
3024         struct ccs_domain_info *domain = NULL;
3025         bool global_pid = false;
3026         if (strncmp(data, "select ", 7))
3027                 return false;
3028         data += 7;
3029         if (sscanf(data, "pid=%u", &pid) == 1 ||
3030             (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
3031                 struct task_struct *p;
3032                 ccs_tasklist_lock();
3033 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
3034                 if (global_pid)
3035                         p = ccsecurity_exports.find_task_by_pid_ns(pid,
3036                                                                &init_pid_ns);
3037                 else
3038                         p = ccsecurity_exports.find_task_by_vpid(pid);
3039 #else
3040                 p = find_task_by_pid(pid);
3041 #endif
3042                 if (p)
3043                         domain = ccs_task_domain(p);
3044                 ccs_tasklist_unlock();
3045         } else if (!strncmp(data, "domain=", 7)) {
3046                 if (*(data + 7) == '<')
3047                         domain = ccs_find_domain(data + 7);
3048         } else if (sscanf(data, "Q=%u", &pid) == 1) {
3049                 domain = ccs_find_domain_by_qid(pid);
3050         } else
3051                 return false;
3052         head->w.domain = domain;
3053         /* Accessing read_buf is safe because head->io_sem is held. */
3054         if (!head->read_buf)
3055                 return true; /* Do nothing if open(O_WRONLY). */
3056         memset(&head->r, 0, sizeof(head->r));
3057         head->r.print_this_domain_only = true;
3058         if (domain)
3059                 head->r.domain = &domain->list;
3060         else
3061                 head->r.eof = true;
3062         ccs_io_printf(head, "# select %s\n", data);
3063         if (domain && domain->is_deleted)
3064                 ccs_set_string(head, "# This is a deleted domain.\n");
3065         return true;
3066 }
3067 
3068 /**
3069  * ccs_update_acl - Update "struct ccs_acl_info" entry.
3070  *
3071  * @size:  Size of new entry in bytes.
3072  * @param: Pointer to "struct ccs_acl_param".
3073  *
3074  * Returns 0 on success, negative value otherwise.
3075  *
3076  * Caller holds ccs_read_lock().
3077  */
3078 static int ccs_update_acl(const int size, struct ccs_acl_param *param)
3079 {
3080         struct ccs_acl_info *new_entry = &param->e.acl_info;
3081         const bool is_delete = param->is_delete;
3082         int error = is_delete ? -ENOENT : -ENOMEM;
3083         struct ccs_acl_info *entry;
3084         struct list_head * const list = param->list;
3085         BUG_ON(size < sizeof(*entry));
3086         if (param->data[0]) {
3087                 new_entry->cond = ccs_get_condition(param);
3088                 if (!new_entry->cond)
3089                         return -EINVAL;
3090                 /*
3091                  * Domain transition preference is allowed for only
3092                  * "file execute"/"task auto_execute_handler"/
3093                  * "task denied_auto_execute_handler" entries.
3094                  */
3095                 if (new_entry->cond->exec_transit &&
3096                     !(new_entry->type == CCS_TYPE_PATH_ACL &&
3097                       new_entry->perm == 1 << CCS_TYPE_EXECUTE)
3098 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3099                     && new_entry->type != CCS_TYPE_AUTO_EXECUTE_HANDLER &&
3100                     new_entry->type != CCS_TYPE_DENIED_EXECUTE_HANDLER
3101 #endif
3102                     )
3103                         return -EINVAL;
3104         }
3105         if (mutex_lock_interruptible(&ccs_policy_lock))
3106                 return -ENOMEM;
3107         list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
3108                 if (entry->is_deleted == CCS_GC_IN_PROGRESS)
3109                         continue;
3110                 if (entry->type != new_entry->type ||
3111                     entry->cond != new_entry->cond ||
3112                     memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
3113                         continue;
3114                 if (is_delete)
3115                         entry->perm &= ~new_entry->perm;
3116                 else
3117                         entry->perm |= new_entry->perm;
3118                 entry->is_deleted = !entry->perm;
3119                 error = 0;
3120                 break;
3121         }
3122         if (error && !is_delete) {
3123                 entry = ccs_commit_ok(new_entry, size);
3124                 if (entry) {
3125                         list_add_tail_rcu(&entry->list, list);
3126                         error = 0;
3127                 }
3128         }
3129         mutex_unlock(&ccs_policy_lock);
3130         return error;
3131 }
3132 
3133 /**
3134  * ccs_permstr - Find permission keywords.
3135  *
3136  * @string: String representation for permissions in foo/bar/buz format.
3137  * @keyword: Keyword to find from @string/
3138  *
3139  * Returns true if @keyword was found in @string, false otherwise.
3140  *
3141  * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
3142  */
3143 static bool ccs_permstr(const char *string, const char *keyword)
3144 {
3145         const char *cp = strstr(string, keyword);
3146         if (cp)
3147                 return cp == string || *(cp - 1) == '/';
3148         return false;
3149 }
3150 
3151 /**
3152  * ccs_write_task - Update task related list.
3153  *
3154  * @param: Pointer to "struct ccs_acl_param".
3155  *
3156  * Returns 0 on success, negative value otherwise.
3157  *
3158  * Caller holds ccs_read_lock().
3159  */
3160 static int ccs_write_task(struct ccs_acl_param *param)
3161 {
3162         int error;
3163         const bool is_auto = ccs_str_starts(&param->data,
3164                                             "auto_domain_transition ");
3165         if (!is_auto && !ccs_str_starts(&param->data,
3166                                         "manual_domain_transition ")) {
3167 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3168                 struct ccs_handler_acl *e = &param->e.handler_acl;
3169                 char *handler;
3170                 if (ccs_str_starts(&param->data, "auto_execute_handler "))
3171                         e->head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER;
3172                 else if (ccs_str_starts(&param->data,
3173                                         "denied_execute_handler "))
3174                         e->head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER;
3175                 else
3176                         return -EINVAL;
3177                 handler = ccs_read_token(param);
3178                 if (!ccs_correct_path(handler))
3179                         return -EINVAL;
3180                 e->handler = ccs_get_name(handler);
3181                 if (!e->handler)
3182                         return -ENOMEM;
3183                 if (e->handler->is_patterned)
3184                         return -EINVAL; /* No patterns allowed. */
3185                 return ccs_update_acl(sizeof(*e), param);
3186 #else
3187                 error = -EINVAL;
3188 #endif
3189         } else {
3190 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
3191                 struct ccs_task_acl *e = &param->e.task_acl;
3192                 e->head.type = is_auto ?
3193                         CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL;
3194                 e->domainname = ccs_get_domainname(param);
3195                 if (!e->domainname)
3196                         return -EINVAL;
3197                 return ccs_update_acl(sizeof(*e), param);
3198 #else
3199                 error = -EINVAL;
3200 #endif
3201         }
3202         return error;
3203 }
3204 
3205 #ifdef CONFIG_CCSECURITY_NETWORK
3206 
3207 /**
3208  * ccs_write_inet_network - Write "struct ccs_inet_acl" list.
3209  *
3210  * @param: Pointer to "struct ccs_acl_param".
3211  *
3212  * Returns 0 on success, negative value otherwise.
3213  *
3214  * Caller holds ccs_read_lock().
3215  */
3216 static int ccs_write_inet_network(struct ccs_acl_param *param)
3217 {
3218         struct ccs_inet_acl *e = &param->e.inet_acl;
3219         u8 type;
3220         const char *protocol = ccs_read_token(param);
3221         const char *operation = ccs_read_token(param);
3222         e->head.type = CCS_TYPE_INET_ACL;
3223         for (type = 0; type < CCS_SOCK_MAX; type++)
3224                 if (!strcmp(protocol, ccs_proto_keyword[type]))
3225                         break;
3226         if (type == CCS_SOCK_MAX)
3227                 return -EINVAL;
3228         e->protocol = type;
3229         e->head.perm = 0;
3230         for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
3231                 if (ccs_permstr(operation, ccs_socket_keyword[type]))
3232                         e->head.perm |= 1 << type;
3233         if (!e->head.perm)
3234                 return -EINVAL;
3235         if (param->data[0] == '@') {
3236                 param->data++;
3237                 e->address.group = ccs_get_group(param, CCS_ADDRESS_GROUP);
3238                 if (!e->address.group)
3239                         return -ENOMEM;
3240         } else {
3241                 if (!ccs_parse_ipaddr_union(param, &e->address))
3242                         return -EINVAL;
3243         }
3244         if (!ccs_parse_number_union(param, &e->port) ||
3245             e->port.values[1] > 65535)
3246                 return -EINVAL;
3247         return ccs_update_acl(sizeof(*e), param);
3248 }
3249 
3250 /**
3251  * ccs_write_unix_network - Write "struct ccs_unix_acl" list.
3252  *
3253  * @param: Pointer to "struct ccs_acl_param".
3254  *
3255  * Returns 0 on success, negative value otherwise.
3256  */
3257 static int ccs_write_unix_network(struct ccs_acl_param *param)
3258 {
3259         struct ccs_unix_acl *e = &param->e.unix_acl;
3260         u8 type;
3261         const char *protocol = ccs_read_token(param);
3262         const char *operation = ccs_read_token(param);
3263         e->head.type = CCS_TYPE_UNIX_ACL;
3264         for (type = 0; type < CCS_SOCK_MAX; type++)
3265                 if (!strcmp(protocol, ccs_proto_keyword[type]))
3266                         break;
3267         if (type == CCS_SOCK_MAX)
3268                 return -EINVAL;
3269         e->protocol = type;
3270         e->head.perm = 0;
3271         for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
3272                 if (ccs_permstr(operation, ccs_socket_keyword[type]))
3273                         e->head.perm |= 1 << type;
3274         if (!e->head.perm)
3275                 return -EINVAL;
3276         if (!ccs_parse_name_union(param, &e->name))
3277                 return -EINVAL;
3278         return ccs_update_acl(sizeof(*e), param);
3279 }
3280 
3281 #endif
3282 
3283 /**
3284  * ccs_write_file - Update file related list.
3285  *
3286  * @param: Pointer to "struct ccs_acl_param".
3287  *
3288  * Returns 0 on success, negative value otherwise.
3289  *
3290  * Caller holds ccs_read_lock().
3291  */
3292 static int ccs_write_file(struct ccs_acl_param *param)
3293 {
3294         u16 perm = 0;
3295         u8 type;
3296         const char *operation = ccs_read_token(param);
3297         for (type = 0; type < CCS_MAX_PATH_OPERATION; type++)
3298                 if (ccs_permstr(operation, ccs_path_keyword[type]))
3299                         perm |= 1 << type;
3300         if (perm) {
3301                 struct ccs_path_acl *e = &param->e.path_acl;
3302                 e->head.type = CCS_TYPE_PATH_ACL;
3303                 e->head.perm = perm;
3304                 if (!ccs_parse_name_union(param, &e->name))
3305                         return -EINVAL;
3306                 return ccs_update_acl(sizeof(*e), param);
3307         }
3308         for (type = 0; type < CCS_MAX_PATH2_OPERATION; type++)
3309                 if (ccs_permstr(operation, ccs_mac_keywords[ccs_pp2mac[type]]))
3310                         perm |= 1 << type;
3311         if (perm) {
3312                 struct ccs_path2_acl *e = &param->e.path2_acl;
3313                 e->head.type = CCS_TYPE_PATH2_ACL;
3314                 e->head.perm = perm;
3315                 if (!ccs_parse_name_union(param, &e->name1) ||
3316                     !ccs_parse_name_union(param, &e->name2))
3317                         return -EINVAL;
3318                 return ccs_update_acl(sizeof(*e), param);
3319         }
3320         for (type = 0; type < CCS_MAX_PATH_NUMBER_OPERATION; type++)
3321                 if (ccs_permstr(operation, ccs_mac_keywords[ccs_pn2mac[type]]))
3322                         perm |= 1 << type;
3323         if (perm) {
3324                 struct ccs_path_number_acl *e = &param->e.path_number_acl;
3325                 e->head.type = CCS_TYPE_PATH_NUMBER_ACL;
3326                 e->head.perm = perm;
3327                 if (!ccs_parse_name_union(param, &e->name) ||
3328                     !ccs_parse_number_union(param, &e->number))
3329                         return -EINVAL;
3330                 return ccs_update_acl(sizeof(*e), param);
3331         }
3332         for (type = 0; type < CCS_MAX_MKDEV_OPERATION; type++)
3333                 if (ccs_permstr(operation,
3334                                 ccs_mac_keywords[ccs_pnnn2mac[type]]))
3335                         perm |= 1 << type;
3336         if (perm) {
3337                 struct ccs_mkdev_acl *e = &param->e.mkdev_acl;
3338                 e->head.type = CCS_TYPE_MKDEV_ACL;
3339                 e->head.perm = perm;
3340                 if (!ccs_parse_name_union(param, &e->name) ||
3341                     !ccs_parse_number_union(param, &e->mode) ||
3342                     !ccs_parse_number_union(param, &e->major) ||
3343                     !ccs_parse_number_union(param, &e->minor))
3344                         return -EINVAL;
3345                 return ccs_update_acl(sizeof(*e), param);
3346         }
3347         if (ccs_permstr(operation, ccs_mac_keywords[CCS_MAC_FILE_MOUNT])) {
3348                 struct ccs_mount_acl *e = &param->e.mount_acl;
3349                 e->head.type = CCS_TYPE_MOUNT_ACL;
3350                 if (!ccs_parse_name_union(param, &e->dev_name) ||
3351                     !ccs_parse_name_union(param, &e->dir_name) ||
3352                     !ccs_parse_name_union(param, &e->fs_type) ||
3353                     !ccs_parse_number_union(param, &e->flags))
3354                         return -EINVAL;
3355                 return ccs_update_acl(sizeof(*e), param);
3356         }
3357         return -EINVAL;
3358 }
3359 
3360 #ifdef CONFIG_CCSECURITY_MISC
3361 
3362 /**
3363  * ccs_write_misc - Update environment variable list.
3364  *
3365  * @param: Pointer to "struct ccs_acl_param".
3366  *
3367  * Returns 0 on success, negative value otherwise.
3368  */
3369 static int ccs_write_misc(struct ccs_acl_param *param)
3370 {
3371         if (ccs_str_starts(&param->data, "env ")) {
3372                 struct ccs_env_acl *e = &param->e.env_acl;
3373                 const char *data = ccs_read_token(param);
3374                 e->head.type = CCS_TYPE_ENV_ACL;
3375                 if (!ccs_correct_word(data) || strchr(data, '='))
3376                         return -EINVAL;
3377                 e->env = ccs_get_name(data);
3378                 if (!e->env)
3379                         return -ENOMEM;
3380                 return ccs_update_acl(sizeof(*e), param);
3381         }
3382         return -EINVAL;
3383 }
3384 
3385 #endif
3386 
3387 #ifdef CONFIG_CCSECURITY_IPC
3388 
3389 /**
3390  * ccs_write_ipc - Update "struct ccs_signal_acl" list.
3391  *
3392  * @param: Pointer to "struct ccs_acl_param".
3393  *
3394  * Returns 0 on success, negative value otherwise.
3395  */
3396 static int ccs_write_ipc(struct ccs_acl_param *param)
3397 {
3398         struct ccs_signal_acl *e = &param->e.signal_acl;
3399         e->head.type = CCS_TYPE_SIGNAL_ACL;
3400         if (!ccs_parse_number_union(param, &e->sig))
3401                 return -EINVAL;
3402         e->domainname = ccs_get_domainname(param);
3403         if (!e->domainname)
3404                 return -EINVAL;
3405         return ccs_update_acl(sizeof(*e), param);
3406 }
3407 
3408 #endif
3409 
3410 #ifdef CONFIG_CCSECURITY_CAPABILITY
3411 
3412 /**
3413  * ccs_write_capability - Write "struct ccs_capability_acl" list.
3414  *
3415  * @param: Pointer to "struct ccs_acl_param".
3416  *
3417  * Returns 0 on success, negative value otherwise.
3418  *
3419  * Caller holds ccs_read_lock().
3420  */
3421 static int ccs_write_capability(struct ccs_acl_param *param)
3422 {
3423         struct ccs_capability_acl *e = &param->e.capability_acl;
3424         const char *operation = ccs_read_token(param);
3425         u8 type;
3426         e->head.type = CCS_TYPE_CAPABILITY_ACL;
3427         for (type = 0; type < CCS_MAX_CAPABILITY_INDEX; type++) {
3428                 if (strcmp(operation, ccs_mac_keywords[ccs_c2mac[type]]))
3429                         continue;
3430                 e->operation = type;
3431                 return ccs_update_acl(sizeof(*e), param);
3432         }
3433         return -EINVAL;
3434 }
3435 
3436 #endif
3437 
3438 /**
3439  * ccs_write_acl - Write "struct ccs_acl_info" list.
3440  *
3441  * @ns:        Pointer to "struct ccs_policy_namespace".
3442  * @list:      Pointer to "struct list_head".
3443  * @data:      Policy to be interpreted.
3444  * @is_delete: True if it is a delete request.
3445  *
3446  * Returns 0 on success, negative value otherwise.
3447  *
3448  * Caller holds ccs_read_lock().
3449  */
3450 static int ccs_write_acl(struct ccs_policy_namespace *ns,
3451                          struct list_head *list, char *data,
3452                          const bool is_delete)
3453 {
3454         struct ccs_acl_param param = {
3455                 .ns = ns,
3456                 .list = list,
3457                 .data = data,
3458                 .is_delete = is_delete,
3459         };
3460         static const struct {
3461                 const char *keyword;
3462                 int (*write) (struct ccs_acl_param *);
3463         } ccs_callback[] = {
3464                 { "file ", ccs_write_file },
3465 #ifdef CONFIG_CCSECURITY_NETWORK
3466                 { "network inet ", ccs_write_inet_network },
3467                 { "network unix ", ccs_write_unix_network },
3468 #endif
3469 #ifdef CONFIG_CCSECURITY_MISC
3470                 { "misc ", ccs_write_misc },
3471 #endif
3472 #ifdef CONFIG_CCSECURITY_CAPABILITY
3473                 { "capability ", ccs_write_capability },
3474 #endif
3475 #ifdef CONFIG_CCSECURITY_IPC
3476                 { "ipc signal ", ccs_write_ipc },
3477 #endif
3478                 { "task ", ccs_write_task },
3479         };
3480         u8 i;
3481         /* Forced zero clear for using memcmp() at ccs_update_acl(). */
3482         memset(&param.e, 0, sizeof(param.e));
3483         param.e.acl_info.perm = 1;
3484         for (i = 0; i < ARRAY_SIZE(ccs_callback); i++) {
3485                 int error;
3486                 if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))
3487                         continue;
3488                 error = ccs_callback[i].write(&param);
3489                 ccs_del_acl(&param.e.acl_info.list);
3490                 return error;
3491         }
3492         return -EINVAL;
3493 }
3494 
3495 /**
3496  * ccs_delete_domain - Delete a domain.
3497  *
3498  * @domainname: The name of domain.
3499  *
3500  * Returns 0.
3501  */
3502 static int ccs_delete_domain(char *domainname)
3503 {
3504         struct ccs_domain_info *domain;
3505         struct ccs_path_info name;
3506         name.name = domainname;
3507         ccs_fill_path_info(&name);
3508         if (mutex_lock_interruptible(&ccs_policy_lock))
3509                 return 0;
3510         /* Is there an active domain? */
3511         list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
3512                 /* Never delete ccs_kernel_domain. */
3513                 if (domain == &ccs_kernel_domain)
3514                         continue;
3515                 if (domain->is_deleted ||
3516                     ccs_pathcmp(domain->domainname, &name))
3517                         continue;
3518                 domain->is_deleted = true;
3519                 break;
3520         }
3521         mutex_unlock(&ccs_policy_lock);
3522         return 0;
3523 }
3524 
3525 /**
3526  * ccs_write_domain - Write domain policy.
3527  *
3528  * @head: Pointer to "struct ccs_io_buffer".
3529  *
3530  * Returns 0 on success, negative value otherwise.
3531  *
3532  * Caller holds ccs_read_lock().
3533  */
3534 static int ccs_write_domain(struct ccs_io_buffer *head)
3535 {
3536         char *data = head->write_buf;
3537         struct ccs_policy_namespace *ns;
3538         struct ccs_domain_info *domain = head->w.domain;
3539         const bool is_delete = head->w.is_delete;
3540         const bool is_select = !is_delete && ccs_str_starts(&data, "select ");
3541         unsigned int idx;
3542         if (*data == '<') {
3543                 domain = NULL;
3544                 if (is_delete)
3545                         ccs_delete_domain(data);
3546                 else if (is_select)
3547                         domain = ccs_find_domain(data);
3548                 else
3549                         domain = ccs_assign_domain(data, false);
3550                 head->w.domain = domain;
3551                 return 0;
3552         }
3553         if (!domain)
3554                 return -EINVAL;
3555         ns = domain->ns;
3556         if (sscanf(data, "use_profile %u\n", &idx) == 1 &&
3557             idx < CCS_MAX_PROFILES) {
3558                 if (!ccs_policy_loaded || ns->profile_ptr[(u8) idx])
3559                         if (!is_delete)
3560                                 domain->profile = (u8) idx;
3561                 return 0;
3562         }
3563         if (sscanf(data, "use_group %u\n", &idx) == 1 &&
3564             idx < CCS_MAX_ACL_GROUPS) {
3565                 if (!is_delete)
3566                         set_bit(idx, domain->group);
3567                 else
3568                         clear_bit(idx, domain->group);
3569                 return 0;
3570         }
3571         for (idx = 0; idx < CCS_MAX_DOMAIN_INFO_FLAGS; idx++) {
3572                 const char *cp = ccs_dif[idx];
3573                 if (strncmp(data, cp, strlen(cp) - 1))
3574                         continue;
3575                 domain->flags[idx] = !is_delete;
3576                 return 0;
3577         }
3578         return ccs_write_acl(ns, &domain->acl_info_list, data, is_delete);
3579 }
3580 
3581 /**
3582  * ccs_print_name_union - Print a ccs_name_union.
3583  *
3584  * @head: Pointer to "struct ccs_io_buffer".
3585  * @ptr:  Pointer to "struct ccs_name_union".
3586  *
3587  * Returns nothing.
3588  */
3589 static void ccs_print_name_union(struct ccs_io_buffer *head,
3590                                  const struct ccs_name_union *ptr)
3591 {
3592         ccs_set_space(head);
3593         if (!ccs_print_group(head, ptr->group))
3594                 ccs_set_string(head, ptr->filename->name);
3595 }
3596 
3597 /**
3598  * ccs_print_name_union_quoted - Print a ccs_name_union with a quote.
3599  *
3600  * @head: Pointer to "struct ccs_io_buffer".
3601  * @ptr:  Pointer to "struct ccs_name_union".
3602  *
3603  * Returns nothing.
3604  */
3605 static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
3606                                         const struct ccs_name_union *ptr)
3607 {
3608         if (!ccs_print_group(head, ptr->group)) {
3609                 ccs_set_string(head, "\"");
3610                 ccs_set_string(head, ptr->filename->name);
3611                 ccs_set_string(head, "\"");
3612         }
3613 }
3614 
3615 /**
3616  * ccs_print_number_union_nospace - Print a ccs_number_union without a space.
3617  *
3618  * @head: Pointer to "struct ccs_io_buffer".
3619  * @ptr:  Pointer to "struct ccs_number_union".
3620  *
3621  * Returns nothing.
3622  */
3623 static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
3624                                            const struct ccs_number_union *ptr)
3625 {
3626         if (!ccs_print_group(head, ptr->group)) {
3627                 int i;
3628                 unsigned long min = ptr->values[0];
3629                 const unsigned long max = ptr->values[1];
3630                 u8 min_type = ptr->value_type[0];
3631                 const u8 max_type = ptr->value_type[1];
3632                 char buffer[128];
3633                 buffer[0] = '\0';
3634                 for (i = 0; i < 2; i++) {
3635                         switch (min_type) {
3636                         case CCS_VALUE_TYPE_HEXADECIMAL:
3637                                 ccs_addprintf(buffer, sizeof(buffer), "0x%lX",
3638                                               min);
3639                                 break;
3640                         case CCS_VALUE_TYPE_OCTAL:
3641                                 ccs_addprintf(buffer, sizeof(buffer), "0%lo",
3642                                               min);
3643                                 break;
3644                         default:
3645                                 ccs_addprintf(buffer, sizeof(buffer), "%lu",
3646                                               min);
3647                                 break;
3648                         }
3649                         if (min == max && min_type == max_type)
3650                                 break;
3651                         ccs_addprintf(buffer, sizeof(buffer), "-");
3652                         min_type = max_type;
3653                         min = max;
3654                 }
3655                 ccs_io_printf(head, "%s", buffer);
3656         }
3657 }
3658 
3659 /**
3660  * ccs_print_number_union - Print a ccs_number_union.
3661  *
3662  * @head: Pointer to "struct ccs_io_buffer".
3663  * @ptr:  Pointer to "struct ccs_number_union".
3664  *
3665  * Returns nothing.
3666  */
3667 static void ccs_print_number_union(struct ccs_io_buffer *head,
3668                                    const struct ccs_number_union *ptr)
3669 {
3670         ccs_set_space(head);
3671         ccs_print_number_union_nospace(head, ptr);
3672 }
3673 
3674 /**
3675  * ccs_print_condition - Print condition part.
3676  *
3677  * @head: Pointer to "struct ccs_io_buffer".
3678  * @cond: Pointer to "struct ccs_condition".
3679  *
3680  * Returns true on success, false otherwise.
3681  */
3682 static bool ccs_print_condition(struct ccs_io_buffer *head,
3683                                 const struct ccs_condition *cond)
3684 {
3685         switch (head->r.cond_step) {
3686         case 0:
3687                 head->r.cond_index = 0;
3688                 head->r.cond_step++;
3689                 if (cond->transit && cond->exec_transit) {
3690                         ccs_set_space(head);
3691                         ccs_set_string(head, cond->transit->name);
3692                 }
3693                 /* fall through */
3694         case 1:
3695                 {
3696                         const u16 condc = cond->condc;
3697                         const struct ccs_condition_element *condp =
3698                                 (typeof(condp)) (cond + 1);
3699                         const struct ccs_number_union *numbers_p =
3700                                 (typeof(numbers_p)) (condp + condc);
3701                         const struct ccs_name_union *names_p =
3702                                 (typeof(names_p))
3703                                 (numbers_p + cond->numbers_count);
3704                         const struct ccs_argv *argv =
3705                                 (typeof(argv)) (names_p + cond->names_count);
3706                         const struct ccs_envp *envp =
3707                                 (typeof(envp)) (argv + cond->argc);
3708                         u16 skip;
3709                         for (skip = 0; skip < head->r.cond_index; skip++) {
3710                                 const u8 left = condp->left;
3711                                 const u8 right = condp->right;
3712                                 condp++;
3713                                 switch (left) {
3714                                 case CCS_ARGV_ENTRY:
3715                                         argv++;
3716                                         continue;
3717                                 case CCS_ENVP_ENTRY:
3718                                         envp++;
3719                                         continue;
3720                                 case CCS_NUMBER_UNION:
3721                                         numbers_p++;
3722                                         break;
3723                                 }
3724                                 switch (right) {
3725                                 case CCS_NAME_UNION:
3726                                         names_p++;
3727                                         break;
3728                                 case CCS_NUMBER_UNION:
3729                                         numbers_p++;
3730                                         break;
3731                                 }
3732                         }
3733                         while (head->r.cond_index < condc) {
3734                                 const u8 match = condp->equals;
3735                                 const u8 left = condp->left;
3736                                 const u8 right = condp->right;
3737                                 if (!ccs_flush(head))
3738                                         return false;
3739                                 condp++;
3740                                 head->r.cond_index++;
3741                                 ccs_set_space(head);
3742                                 switch (left) {
3743                                 case CCS_ARGV_ENTRY:
3744                                         ccs_io_printf(head,
3745                                                       "exec.argv[%lu]%s=\"",
3746                                                       argv->index,
3747                                                       argv->is_not ? "!" : "");
3748                                         ccs_set_string(head,
3749                                                        argv->value->name);
3750                                         ccs_set_string(head, "\"");
3751                                         argv++;
3752                                         continue;
3753                                 case CCS_ENVP_ENTRY:
3754                                         ccs_set_string(head, "exec.envp[\"");
3755                                         ccs_set_string(head, envp->name->name);
3756                                         ccs_io_printf(head, "\"]%s=",
3757                                                       envp->is_not ? "!" : "");
3758                                         if (envp->value) {
3759                                                 ccs_set_string(head, "\"");
3760                                                 ccs_set_string(head, envp->
3761                                                                value->name);
3762                                                 ccs_set_string(head, "\"");
3763                                         } else {
3764                                                 ccs_set_string(head, "NULL");
3765                                         }
3766                                         envp++;
3767                                         continue;
3768                                 case CCS_NUMBER_UNION:
3769                                         ccs_print_number_union_nospace
3770                                                 (head, numbers_p++);
3771                                         break;
3772                                 default:
3773                                         ccs_set_string(head,
3774                                                ccs_condition_keyword[left]);
3775                                         break;
3776                                 }
3777                                 ccs_set_string(head, match ? "=" : "!=");
3778                                 switch (right) {
3779                                 case CCS_NAME_UNION:
3780                                         ccs_print_name_union_quoted
3781                                                 (head, names_p++);
3782                                         break;
3783                                 case CCS_NUMBER_UNION:
3784                                         ccs_print_number_union_nospace
3785                                                 (head, numbers_p++);
3786                                         break;
3787                                 default:
3788                                         ccs_set_string(head,
3789                                                ccs_condition_keyword[right]);
3790                                         break;
3791                                 }
3792                         }
3793                 }
3794                 head->r.cond_step++;
3795                 /* fall through */
3796         case 2:
3797                 if (!ccs_flush(head))
3798                         break;
3799                 head->r.cond_step++;
3800                 /* fall through */
3801         case 3:
3802                 if (cond->grant_log != CCS_GRANTLOG_AUTO)
3803                         ccs_io_printf(head, " grant_log=%s",
3804                                       ccs_yesno(cond->grant_log ==
3805                                                 CCS_GRANTLOG_YES));
3806                 if (cond->transit && !cond->exec_transit) {
3807                         const char *name = cond->transit->name;
3808                         ccs_set_string(head, " auto_domain_transition=\"");
3809                         ccs_set_string(head, name);
3810                         ccs_set_string(head, "\"");
3811                 }
3812                 ccs_set_lf(head);
3813                 return true;
3814         }
3815         return false;
3816 }
3817 
3818 /**
3819  * ccs_set_group - Print "acl_group " header keyword and category name.
3820  *
3821  * @head:     Pointer to "struct ccs_io_buffer".
3822  * @category: Category name.
3823  *
3824  * Returns nothing.
3825  */
3826 static void ccs_set_group(struct ccs_io_buffer *head, const char *category)
3827 {
3828         if (head->type == CCS_EXCEPTION_POLICY) {
3829                 ccs_print_namespace(head);
3830                 ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
3831         }
3832         ccs_set_string(head, category);
3833 }
3834 
3835 /**
3836  * ccs_print_entry - Print an ACL entry.
3837  *
3838  * @head: Pointer to "struct ccs_io_buffer".
3839  * @acl:  Pointer to an ACL entry.
3840  *
3841  * Returns true on success, false otherwise.
3842  */
3843 static bool ccs_print_entry(struct ccs_io_buffer *head,
3844                             const struct ccs_acl_info *acl)
3845 {
3846         const u8 acl_type = acl->type;
3847         const bool may_trigger_transition = acl->cond && acl->cond->transit;
3848         bool first = true;
3849         u8 bit;
3850         if (head->r.print_cond_part)
3851                 goto print_cond_part;
3852         if (acl->is_deleted)
3853                 return true;
3854         if (!ccs_flush(head))
3855                 return false;
3856         else if (acl_type == CCS_TYPE_PATH_ACL) {
3857                 struct ccs_path_acl *ptr
3858                         = container_of(acl, typeof(*ptr), head);
3859                 for (bit = 0; bit < CCS_MAX_PATH_OPERATION; bit++) {
3860                         if (!(acl->perm & (1 << bit)))
3861                                 continue;
3862                         if (head->r.print_transition_related_only &&
3863                             bit != CCS_TYPE_EXECUTE && !may_trigger_transition)
3864                                 continue;
3865                         if (first) {
3866                                 ccs_set_group(head, "file ");
3867                                 first = false;
3868                         } else {
3869                                 ccs_set_slash(head);
3870                         }
3871                         ccs_set_string(head, ccs_path_keyword[bit]);
3872                 }
3873                 if (first)
3874                         return true;
3875                 ccs_print_name_union(head, &ptr->name);
3876 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3877         } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||
3878                    acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
3879                 struct ccs_handler_acl *ptr
3880                         = container_of(acl, typeof(*ptr), head);
3881                 ccs_set_group(head, "task ");
3882                 ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER
3883                                ? "auto_execute_handler " :
3884                                "denied_execute_handler ");
3885                 ccs_set_string(head, ptr->handler->name);
3886 #endif
3887 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
3888         } else if (acl_type == CCS_TYPE_AUTO_TASK_ACL ||
3889                    acl_type == CCS_TYPE_MANUAL_TASK_ACL) {
3890                 struct ccs_task_acl *ptr =
3891                         container_of(acl, typeof(*ptr), head);
3892                 ccs_set_group(head, "task ");
3893                 ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?
3894                                "auto_domain_transition " :
3895                                "manual_domain_transition ");
3896                 ccs_set_string(head, ptr->domainname->name);
3897 #endif
3898         } else if (head->r.print_transition_related_only &&
3899                    !may_trigger_transition) {
3900                 return true;
3901         } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
3902                 struct ccs_mkdev_acl *ptr =
3903                         container_of(acl, typeof(*ptr), head);
3904                 for (bit = 0; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
3905                         if (!(acl->perm & (1 << bit)))
3906                                 continue;
3907                         if (first) {
3908                                 ccs_set_group(head, "file ");
3909                                 first = false;
3910                         } else {
3911                                 ccs_set_slash(head);
3912                         }
3913                         ccs_set_string(head, ccs_mac_keywords
3914                                        [ccs_pnnn2mac[bit]]);
3915                 }
3916                 if (first)
3917                         return true;
3918                 ccs_print_name_union(head, &ptr->name);
3919                 ccs_print_number_union(head, &ptr->mode);
3920                 ccs_print_number_union(head, &ptr->major);
3921                 ccs_print_number_union(head, &ptr->minor);
3922         } else if (acl_type == CCS_TYPE_PATH2_ACL) {
3923                 struct ccs_path2_acl *ptr =
3924                         container_of(acl, typeof(*ptr), head);
3925                 for (bit = 0; bit < CCS_MAX_PATH2_OPERATION; bit++) {
3926                         if (!(acl->perm & (1 << bit)))
3927                                 continue;
3928                         if (first) {
3929                                 ccs_set_group(head, "file ");
3930                                 first = false;
3931                         } else {
3932                                 ccs_set_slash(head);
3933                         }
3934                         ccs_set_string(head, ccs_mac_keywords
3935                                        [ccs_pp2mac[bit]]);
3936                 }
3937                 if (first)
3938                         return true;
3939                 ccs_print_name_union(head, &ptr->name1);
3940                 ccs_print_name_union(head, &ptr->name2);
3941         } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
3942                 struct ccs_path_number_acl *ptr =
3943                         container_of(acl, typeof(*ptr), head);
3944                 for (bit = 0; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
3945                         if (!(acl->perm & (1 << bit)))
3946                                 continue;
3947                         if (first) {
3948                                 ccs_set_group(head, "file ");
3949                                 first = false;
3950                         } else {
3951                                 ccs_set_slash(head);
3952                         }
3953                         ccs_set_string(head, ccs_mac_keywords
3954                                        [ccs_pn2mac[bit]]);
3955                 }
3956                 if (first)
3957                         return true;
3958                 ccs_print_name_union(head, &ptr->name);
3959                 ccs_print_number_union(head, &ptr->number);
3960 #ifdef CONFIG_CCSECURITY_MISC
3961         } else if (acl_type == CCS_TYPE_ENV_ACL) {
3962                 struct ccs_env_acl *ptr =
3963                         container_of(acl, typeof(*ptr), head);
3964                 ccs_set_group(head, "misc env ");
3965                 ccs_set_string(head, ptr->env->name);
3966 #endif
3967 #ifdef CONFIG_CCSECURITY_CAPABILITY
3968         } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
3969                 struct ccs_capability_acl *ptr =
3970                         container_of(acl, typeof(*ptr), head);
3971                 ccs_set_group(head, "capability ");
3972                 ccs_set_string(head, ccs_mac_keywords
3973                                [ccs_c2mac[ptr->operation]]);
3974 #endif
3975 #ifdef CONFIG_CCSECURITY_NETWORK
3976         } else if (acl_type == CCS_TYPE_INET_ACL) {
3977                 struct ccs_inet_acl *ptr =
3978                         container_of(acl, typeof(*ptr), head);
3979                 for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
3980                         if (!(acl->perm & (1 << bit)))
3981                                 continue;
3982                         if (first) {
3983                                 ccs_set_group(head, "network inet ");
3984                                 ccs_set_string(head, ccs_proto_keyword
3985                                                [ptr->protocol]);
3986                                 ccs_set_space(head);
3987                                 first = false;
3988                         } else {
3989                                 ccs_set_slash(head);
3990                         }
3991                         ccs_set_string(head, ccs_socket_keyword[bit]);
3992                 }
3993                 if (first)
3994                         return true;
3995                 ccs_set_space(head);
3996                 if (!ccs_print_group(head, ptr->address.group)) {
3997                         char buf[128];
3998                         ccs_print_ip(buf, sizeof(buf), &ptr->address);
3999                         ccs_io_printf(head, "%s", buf);
4000                 }
4001                 ccs_print_number_union(head, &ptr->port);
4002         } else if (acl_type == CCS_TYPE_UNIX_ACL) {
4003                 struct ccs_unix_acl *ptr =
4004                         container_of(acl, typeof(*ptr), head);
4005                 for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
4006                         if (!(acl->perm & (1 << bit)))
4007                                 continue;
4008                         if (first) {
4009                                 ccs_set_group(head, "network unix ");
4010                                 ccs_set_string(head, ccs_proto_keyword
4011                                                [ptr->protocol]);
4012                                 ccs_set_space(head);
4013                                 first = false;
4014                         } else {
4015                                 ccs_set_slash(head);
4016                         }
4017                         ccs_set_string(head, ccs_socket_keyword[bit]);
4018                 }
4019                 if (first)
4020                         return true;
4021                 ccs_print_name_union(head, &ptr->name);
4022 #endif
4023 #ifdef CONFIG_CCSECURITY_IPC
4024         } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
4025                 struct ccs_signal_acl *ptr =
4026                         container_of(acl, typeof(*ptr), head);
4027                 ccs_set_group(head, "ipc signal ");
4028                 ccs_print_number_union_nospace(head, &ptr->sig);
4029                 ccs_set_space(head);
4030                 ccs_set_string(head, ptr->domainname->name);
4031 #endif
4032         } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
4033                 struct ccs_mount_acl *ptr =
4034                         container_of(acl, typeof(*ptr), head);
4035                 ccs_set_group(head, "file mount");
4036                 ccs_print_name_union(head, &ptr->dev_name);
4037                 ccs_print_name_union(head, &ptr->dir_name);
4038                 ccs_print_name_union(head, &ptr->fs_type);
4039                 ccs_print_number_union(head, &ptr->flags);
4040         }
4041         if (acl->cond) {
4042                 head->r.print_cond_part = true;
4043                 head->r.cond_step = 0;
4044                 if (!ccs_flush(head))
4045                         return false;
4046 print_cond_part:
4047                 if (!ccs_print_condition(head, acl->cond))
4048                         return false;
4049                 head->r.print_cond_part = false;
4050         } else {
4051                 ccs_set_lf(head);
4052         }
4053         return true;
4054 }
4055 
4056 /**
4057  * ccs_read_acl - Read "struct ccs_acl_info" list.
4058  *
4059  * @head: Pointer to "struct ccs_io_buffer".
4060  * @list: Pointer to "struct list_head".
4061  *
4062  * Returns true on success, false otherwise.
4063  *
4064  * Caller holds ccs_read_lock().
4065  */
4066 static bool ccs_read_acl(struct ccs_io_buffer *head, struct list_head *list)
4067 {
4068         list_for_each_cookie(head->r.acl, list) {
4069                 struct ccs_acl_info *ptr =
4070                         list_entry(head->r.acl, typeof(*ptr), list);
4071                 if (!ccs_print_entry(head, ptr))
4072                         return false;
4073         }
4074         head->r.acl = NULL;
4075         return true;
4076 }
4077 
4078 /**
4079  * ccs_read_domain - Read domain policy.
4080  *
4081  * @head: Pointer to "struct ccs_io_buffer".
4082  *
4083  * Returns nothing.
4084  *
4085  * Caller holds ccs_read_lock().
4086  */
4087 static void ccs_read_domain(struct ccs_io_buffer *head)
4088 {
4089         if (head->r.eof)
4090                 return;
4091         list_for_each_cookie(head->r.domain, &ccs_domain_list) {
4092                 struct ccs_domain_info *domain =
4093                         list_entry(head->r.domain, typeof(*domain), list);
4094                 switch (head->r.step) {
4095                         u8 i;
4096                 case 0:
4097                         if (domain->is_deleted &&
4098                             !head->r.print_this_domain_only)
4099                                 continue;
4100                         /* Print domainname and flags. */
4101                         ccs_set_string(head, domain->domainname->name);
4102                         ccs_set_lf(head);
4103                         ccs_io_printf(head, "use_profile %u\n",
4104                                       domain->profile);
4105                         for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)
4106                                 if (domain->flags[i])
4107                                         ccs_set_string(head, ccs_dif[i]);
4108                         head->r.index = 0;
4109                         head->r.step++;
4110                         /* fall through */
4111                 case 1:
4112                         while (head->r.index < CCS_MAX_ACL_GROUPS) {
4113                                 i = head->r.index++;
4114                                 if (!test_bit(i, domain->group))
4115                                         continue;
4116                                 ccs_io_printf(head, "use_group %u\n", i);
4117                                 if (!ccs_flush(head))
4118                                         return;
4119                         }
4120                         head->r.index = 0;
4121                         head->r.step++;
4122                         ccs_set_lf(head);
4123                         /* fall through */
4124                 case 2:
4125                         if (!ccs_read_acl(head, &domain->acl_info_list))
4126                                 return;
4127                         head->r.step++;
4128                         if (!ccs_set_lf(head))
4129                                 return;
4130                         /* fall through */
4131                 case 3:
4132                         head->r.step = 0;
4133                         if (head->r.print_this_domain_only)
4134                                 goto done;
4135                 }
4136         }
4137 done:
4138         head->r.eof = true;
4139 }
4140 
4141 /**
4142  * ccs_write_pid - Specify PID to obtain domainname.
4143  *
4144  * @head: Pointer to "struct ccs_io_buffer".
4145  *
4146  * Returns 0.
4147  */
4148 static int ccs_write_pid(struct ccs_io_buffer *head)
4149 {
4150         head->r.eof = false;
4151         return 0;
4152 }
4153 
4154 /**
4155  * ccs_read_pid - Read information of a process.
4156  *
4157  * @head: Pointer to "struct ccs_io_buffer".
4158  *
4159  * Returns the domainname which the specified PID is in or
4160  * process information of the specified PID on success,
4161  * empty string otherwise.
4162  *
4163  * Caller holds ccs_read_lock().
4164  */
4165 static void ccs_read_pid(struct ccs_io_buffer *head)
4166 {
4167         char *buf = head->write_buf;
4168         bool task_info = false;
4169         bool global_pid = false;
4170         unsigned int pid;
4171         struct task_struct *p;
4172         struct ccs_domain_info *domain = NULL;
4173         u32 ccs_flags = 0;
4174         /* Accessing write_buf is safe because head->io_sem is held. */
4175         if (!buf) {
4176                 head->r.eof = true;
4177                 return; /* Do nothing if open(O_RDONLY). */
4178         }
4179         if (head->r.w_pos || head->r.eof)
4180                 return;
4181         head->r.eof = true;
4182         if (ccs_str_starts(&buf, "info "))
4183                 task_info = true;
4184         if (ccs_str_starts(&buf, "global-pid "))
4185                 global_pid = true;
4186         pid = (unsigned int) simple_strtoul(buf, NULL, 10);
4187         ccs_tasklist_lock();
4188 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
4189         if (global_pid)
4190                 p = ccsecurity_exports.find_task_by_pid_ns(pid, &init_pid_ns);
4191         else
4192                 p = ccsecurity_exports.find_task_by_vpid(pid);
4193 #else
4194         p = find_task_by_pid(pid);
4195 #endif
4196         if (p) {
4197                 domain = ccs_task_domain(p);
4198                 ccs_flags = ccs_task_flags(p);
4199         }
4200         ccs_tasklist_unlock();
4201         if (!domain)
4202                 return;
4203         if (!task_info) {
4204                 ccs_io_printf(head, "%u %u ", pid, domain->profile);
4205                 ccs_set_string(head, domain->domainname->name);
4206         } else {
4207                 ccs_io_printf(head, "%u manager=%s execute_handler=%s ", pid,
4208                               ccs_yesno(ccs_flags &
4209                                         CCS_TASK_IS_MANAGER),
4210                               ccs_yesno(ccs_flags &
4211                                         CCS_TASK_IS_EXECUTE_HANDLER));
4212         }
4213 }
4214 
4215 /**
4216  * ccs_write_group - Write "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
4217  *
4218  * @param: Pointer to "struct ccs_acl_param".
4219  * @type:  Type of this group.
4220  *
4221  * Returns 0 on success, negative value otherwise.
4222  */
4223 static int ccs_write_group(struct ccs_acl_param *param, const u8 type)
4224 {
4225         struct ccs_group *group = ccs_get_group(param, type);
4226         int error = -EINVAL;
4227         if (!group)
4228                 return -ENOMEM;
4229         param->list = &group->member_list;
4230         if (type == CCS_PATH_GROUP) {
4231                 struct ccs_path_group *e = &param->e.path_group;
4232                 e->member_name = ccs_get_name(ccs_read_token(param));
4233                 if (!e->member_name) {
4234                         error = -ENOMEM;
4235                         goto out;
4236                 }
4237                 error = ccs_update_policy(sizeof(*e), param);
4238                 ccs_put_name(e->member_name);
4239         } else if (type == CCS_NUMBER_GROUP) {
4240                 struct ccs_number_group *e = &param->e.number_group;
4241                 if (param->data[0] == '@' ||
4242                     !ccs_parse_number_union(param, &e->number))
4243                         goto out;
4244                 error = ccs_update_policy(sizeof(*e), param);
4245 #ifdef CONFIG_CCSECURITY_NETWORK
4246         } else {
4247                 struct ccs_address_group *e = &param->e.address_group;
4248                 if (param->data[0] == '@' ||
4249                     !ccs_parse_ipaddr_union(param, &e->address))
4250                         goto out;
4251                 error = ccs_update_policy(sizeof(*e), param);
4252 #endif
4253         }
4254 out:
4255         ccs_put_group(group);
4256         return error;
4257 }
4258 
4259 #ifdef CONFIG_CCSECURITY_PORTRESERVE
4260 /**
4261  * ccs_lport_reserved - Check whether local port is reserved or not.
4262  *
4263  * @port: Port number.
4264  *
4265  * Returns true if local port is reserved, false otherwise.
4266  */
4267 static bool __ccs_lport_reserved(const u16 port)
4268 {
4269         return ccs_reserved_port_map[port >> 3] & (1 << (port & 7))
4270                 ? true : false;
4271 }
4272 
4273 /**
4274  * ccs_write_reserved_port - Update "struct ccs_reserved" list.
4275  *
4276  * @param: Pointer to "struct ccs_acl_param".
4277  *
4278  * Returns 0 on success, negative value otherwise.
4279  *
4280  * Caller holds ccs_read_lock().
4281  */
4282 static int ccs_write_reserved_port(struct ccs_acl_param *param)
4283 {
4284         struct ccs_reserved *e = &param->e.reserved;
4285         struct ccs_policy_namespace *ns = param->ns;
4286         int error;
4287         u8 *tmp;
4288         if (param->data[0] == '@' ||
4289             !ccs_parse_number_union(param, &e->port) ||
4290             e->port.values[1] > 65535 || param->data[0])
4291                 return -EINVAL;
4292         param->list = &ns->policy_list[CCS_ID_RESERVEDPORT];
4293         error = ccs_update_policy(sizeof(*e), param);
4294         if (error)
4295                 return error;
4296         tmp = kzalloc(sizeof(ccs_reserved_port_map), CCS_GFP_FLAGS);
4297         if (!tmp)
4298                 return -ENOMEM;
4299         list_for_each_entry_srcu(ns, &ccs_namespace_list, namespace_list,
4300                                  &ccs_ss) {
4301                 struct ccs_reserved *ptr;
4302                 struct list_head *list = &ns->policy_list[CCS_ID_RESERVEDPORT];
4303                 list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
4304                         unsigned int port;
4305                         if (ptr->head.is_deleted)
4306                                 continue;
4307                         for (port = ptr->port.values[0];
4308                              port <= ptr->port.values[1]; port++)
4309                                 tmp[port >> 3] |= 1 << (port & 7);
4310                 }
4311         }
4312         memmove(ccs_reserved_port_map, tmp, sizeof(ccs_reserved_port_map));
4313         kfree(tmp);
4314         /*
4315          * Since this feature is no-op by default, we don't need to register
4316          * this callback hook unless the first entry is added.
4317          */
4318         ccsecurity_ops.lport_reserved = __ccs_lport_reserved;
4319         return 0;
4320 }
4321 #endif
4322 
4323 /**
4324  * ccs_write_aggregator - Write "struct ccs_aggregator" list.
4325  *
4326  * @param: Pointer to "struct ccs_acl_param".
4327  *
4328  * Returns 0 on success, negative value otherwise.
4329  */
4330 static int ccs_write_aggregator(struct ccs_acl_param *param)
4331 {
4332         struct ccs_aggregator *e = &param->e.aggregator;
4333         int error = param->is_delete ? -ENOENT : -ENOMEM;
4334         const char *original_name = ccs_read_token(param);
4335         const char *aggregated_name = ccs_read_token(param);
4336         if (!ccs_correct_word(original_name) ||
4337             !ccs_correct_path(aggregated_name))
4338                 return -EINVAL;
4339         e->original_name = ccs_get_name(original_name);
4340         e->aggregated_name = ccs_get_name(aggregated_name);
4341         if (!e->original_name || !e->aggregated_name ||
4342             e->aggregated_name->is_patterned) /* No patterns allowed. */
4343                 goto out;
4344         param->list = &param->ns->policy_list[CCS_ID_AGGREGATOR];
4345         error = ccs_update_policy(sizeof(*e), param);
4346 out:
4347         ccs_put_name(e->original_name);
4348         ccs_put_name(e->aggregated_name);
4349         return error;
4350 }
4351 
4352 /**
4353  * ccs_write_transition_control - Write "struct ccs_transition_control" list.
4354  *
4355  * @param: Pointer to "struct ccs_acl_param".
4356  * @type:  Type of this entry.
4357  *
4358  * Returns 0 on success, negative value otherwise.
4359  */
4360 static int ccs_write_transition_control(struct ccs_acl_param *param,
4361                                         const u8 type)
4362 {
4363         struct ccs_transition_control *e = &param->e.transition_control;
4364         int error = param->is_delete ? -ENOENT : -ENOMEM;
4365         char *program = param->data;
4366         char *domainname = strstr(program, " from ");
4367         e->type = type;
4368         if (domainname) {
4369                 *domainname = '\0';
4370                 domainname += 6;
4371         } else if (type == CCS_TRANSITION_CONTROL_NO_KEEP ||
4372                    type == CCS_TRANSITION_CONTROL_KEEP) {
4373                 domainname = program;
4374                 program = NULL;
4375         }
4376         if (program && strcmp(program, "any")) {
4377                 if (!ccs_correct_path(program))
4378                         return -EINVAL;
4379                 e->program = ccs_get_name(program);
4380                 if (!e->program)
4381                         goto out;
4382         }
4383         if (domainname && strcmp(domainname, "any")) {
4384                 if (!ccs_correct_domain(domainname)) {
4385                         if (!ccs_correct_path(domainname))
4386                                 goto out;
4387                         e->is_last_name = true;
4388                 }
4389                 e->domainname = ccs_get_name(domainname);
4390                 if (!e->domainname)
4391                         goto out;
4392         }
4393         param->list = &param->ns->policy_list[CCS_ID_TRANSITION_CONTROL];
4394         error = ccs_update_policy(sizeof(*e), param);
4395 out:
4396         ccs_put_name(e->domainname);
4397         ccs_put_name(e->program);
4398         return error;
4399 }
4400 
4401 /**
4402  * ccs_write_exception - Write exception policy.
4403  *
4404  * @head: Pointer to "struct ccs_io_buffer".
4405  *
4406  * Returns 0 on success, negative value otherwise.
4407  */
4408 static int ccs_write_exception(struct ccs_io_buffer *head)
4409 {
4410         const bool is_delete = head->w.is_delete;
4411         struct ccs_acl_param param = {
4412                 .ns = head->w.ns,
4413                 .is_delete = is_delete,
4414                 .data = head->write_buf,
4415         };
4416         u8 i;
4417         /* Forced zero clear for using memcmp() at ccs_update_policy(). */
4418         memset(&param.e, 0, sizeof(param.e));
4419         if (ccs_str_starts(&param.data, "aggregator "))
4420                 return ccs_write_aggregator(&param);
4421 #ifdef CONFIG_CCSECURITY_PORTRESERVE
4422         if (ccs_str_starts(&param.data, "deny_autobind "))
4423                 return ccs_write_reserved_port(&param);
4424 #endif
4425         for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
4426                 if (ccs_str_starts(&param.data, ccs_transition_type[i]))
4427                         return ccs_write_transition_control(&param, i);
4428         for (i = 0; i < CCS_MAX_GROUP; i++)
4429                 if (ccs_str_starts(&param.data, ccs_group_name[i]))
4430                         return ccs_write_group(&param, i);
4431         if (ccs_str_starts(&param.data, "acl_group ")) {
4432                 unsigned int group;
4433                 char *data;
4434                 group = simple_strtoul(param.data, &data, 10);
4435                 if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
4436                         return ccs_write_acl(head->w.ns,
4437                                              &head->w.ns->acl_group[group],
4438                                              data, is_delete);
4439         }
4440         return -EINVAL;
4441 }
4442 
4443 /**
4444  * ccs_read_group - Read "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
4445  *
4446  * @head: Pointer to "struct ccs_io_buffer".
4447  * @idx:  Index number.
4448  *
4449  * Returns true on success, false otherwise.
4450  *
4451  * Caller holds ccs_read_lock().
4452  */
4453 static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)
4454 {
4455         struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
4456                                                        namespace_list);
4457         struct list_head *list = &ns->group_list[idx];
4458         list_for_each_cookie(head->r.group, list) {
4459                 struct ccs_group *group =
4460                         list_entry(head->r.group, typeof(*group), head.list);
4461                 list_for_each_cookie(head->r.acl, &group->member_list) {
4462                         struct ccs_acl_head *ptr =
4463                                 list_entry(head->r.acl, typeof(*ptr), list);
4464                         if (ptr->is_deleted)
4465                                 continue;
4466                         if (!ccs_flush(head))
4467                                 return false;
4468                         ccs_print_namespace(head);
4469                         ccs_set_string(head, ccs_group_name[idx]);
4470                         ccs_set_string(head, group->group_name->name);
4471                         if (idx == CCS_PATH_GROUP) {
4472                                 ccs_set_space(head);
4473                                 ccs_set_string(head, container_of
4474                                                (ptr, struct ccs_path_group,
4475                                                 head)->member_name->name);
4476                         } else if (idx == CCS_NUMBER_GROUP) {
4477                                 ccs_print_number_union(head, &container_of
4478                                                (ptr, struct ccs_number_group,
4479                                                 head)->number);
4480 #ifdef CONFIG_CCSECURITY_NETWORK
4481                         } else if (idx == CCS_ADDRESS_GROUP) {
4482                                 char buffer[128];
4483                                 struct ccs_address_group *member =
4484                                         container_of(ptr, typeof(*member),
4485                                                      head);
4486                                 ccs_print_ip(buffer, sizeof(buffer),
4487                                              &member->address);
4488                                 ccs_io_printf(head, " %s", buffer);
4489 #endif
4490                         }
4491                         ccs_set_lf(head);
4492                 }
4493                 head->r.acl = NULL;
4494         }
4495         head->r.group = NULL;
4496         return true;
4497 }
4498 
4499 /**
4500  * ccs_read_policy - Read "struct ccs_..._entry" list.
4501  *
4502  * @head: Pointer to "struct ccs_io_buffer".
4503  * @idx:  Index number.
4504  *
4505  * Returns true on success, false otherwise.
4506  *
4507  * Caller holds ccs_read_lock().
4508  */
4509 static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)
4510 {
4511         struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
4512                                                        namespace_list);
4513         struct list_head *list = &ns->policy_list[idx];
4514         list_for_each_cookie(head->r.acl, list) {
4515                 struct ccs_acl_head *acl =
4516                         container_of(head->r.acl, typeof(*acl), list);
4517                 if (acl->is_deleted)
4518                         continue;
4519                 if (head->r.print_transition_related_only &&
4520                     idx != CCS_ID_TRANSITION_CONTROL)
4521                         continue;
4522                 if (!ccs_flush(head))
4523                         return false;
4524                 switch (idx) {
4525                 case CCS_ID_TRANSITION_CONTROL:
4526                         {
4527                                 struct ccs_transition_control *ptr =
4528                                         container_of(acl, typeof(*ptr), head);
4529                                 ccs_print_namespace(head);
4530                                 ccs_set_string(head,
4531                                                ccs_transition_type[ptr->type]);
4532                                 ccs_set_string(head, ptr->program ?
4533                                                ptr->program->name : "any");
4534                                 ccs_set_string(head, " from ");
4535                                 ccs_set_string(head, ptr->domainname ?
4536                                                ptr->domainname->name : "any");
4537                         }
4538                         break;
4539                 case CCS_ID_AGGREGATOR:
4540                         {
4541                                 struct ccs_aggregator *ptr =
4542                                         container_of(acl, typeof(*ptr), head);
4543                                 ccs_print_namespace(head);
4544                                 ccs_set_string(head, "aggregator ");
4545                                 ccs_set_string(head, ptr->original_name->name);
4546                                 ccs_set_space(head);
4547                                 ccs_set_string(head,
4548                                                ptr->aggregated_name->name);
4549                         }
4550                         break;
4551 #ifdef CONFIG_CCSECURITY_PORTRESERVE
4552                 case CCS_ID_RESERVEDPORT:
4553                         {
4554                                 struct ccs_reserved *ptr =
4555                                         container_of(acl, typeof(*ptr), head);
4556                                 ccs_print_namespace(head);
4557                                 ccs_set_string(head, "deny_autobind ");
4558                                 ccs_print_number_union_nospace(head,
4559                                                                &ptr->port);
4560                         }
4561                         break;
4562 #endif
4563                 default:
4564                         continue;
4565                 }
4566                 ccs_set_lf(head);
4567         }
4568         head->r.acl = NULL;
4569         return true;
4570 }
4571 
4572 /**
4573  * ccs_read_exception - Read exception policy.
4574  *
4575  * @head: Pointer to "struct ccs_io_buffer".
4576  *
4577  * Returns nothing.
4578  *
4579  * Caller holds ccs_read_lock().
4580  */
4581 static void ccs_read_exception(struct ccs_io_buffer *head)
4582 {
4583         struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
4584                                                        namespace_list);
4585         if (head->r.eof)
4586                 return;
4587         while (head->r.step < CCS_MAX_POLICY &&
4588                ccs_read_policy(head, head->r.step))
4589                 head->r.step++;
4590         if (head->r.step < CCS_MAX_POLICY)
4591                 return;
4592         while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP &&
4593                ccs_read_group(head, head->r.step - CCS_MAX_POLICY))
4594                 head->r.step++;
4595         if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)
4596                 return;
4597         while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
4598                + CCS_MAX_ACL_GROUPS) {
4599                 head->r.acl_group_index =
4600                         head->r.step - CCS_MAX_POLICY - CCS_MAX_GROUP;
4601                 if (!ccs_read_acl(head, &ns->acl_group
4602                                   [head->r.acl_group_index]))
4603                         return;
4604                 head->r.step++;
4605         }
4606         head->r.eof = true;
4607 }
4608 
4609 /**
4610  * ccs_truncate - Truncate a line.
4611  *
4612  * @str: String to truncate.
4613  *
4614  * Returns length of truncated @str.
4615  */
4616 static int ccs_truncate(char *str)
4617 {
4618         char *start = str;
4619         while (*(unsigned char *) str > (unsigned char) ' ')
4620                 str++;
4621         *str = '\0';
4622         return strlen(start) + 1;
4623 }
4624 
4625 /**
4626  * ccs_add_entry - Add an ACL to current thread's domain. Used by learning mode.
4627  *
4628  * @header: Lines containing ACL.
4629  *
4630  * Returns nothing.
4631  */
4632 static void ccs_add_entry(char *header)
4633 {
4634         char *buffer;
4635         char *realpath = NULL;
4636         char *argv0 = NULL;
4637         char *symlink = NULL;
4638 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
4639         char *handler;
4640 #endif
4641         char *cp = strchr(header, '\n');
4642         int len;
4643         if (!cp)
4644                 return;
4645         cp = strchr(cp + 1, '\n');
4646         if (!cp)
4647                 return;
4648         *cp++ = '\0';
4649         len = strlen(cp) + 1;
4650         /* strstr() will return NULL if ordering is wrong. */
4651         if (*cp == 'f') {
4652                 argv0 = strstr(header, " argv[]={ \"");
4653                 if (argv0) {
4654                         argv0 += 10;
4655                         len += ccs_truncate(argv0) + 14;
4656                 }
4657                 realpath = strstr(header, " exec={ realpath=\"");
4658                 if (realpath) {
4659                         realpath += 8;
4660                         len += ccs_truncate(realpath) + 6;
4661                 }
4662                 symlink = strstr(header, " symlink.target=\"");
4663                 if (symlink)
4664                         len += ccs_truncate(symlink + 1) + 1;
4665         }
4666 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
4667         handler = strstr(header, "type=execute_handler");
4668         if (handler)
4669                 len += ccs_truncate(handler) + 6;
4670 #endif
4671         buffer = kmalloc(len, CCS_GFP_FLAGS);
4672         if (!buffer)
4673                 return;
4674         snprintf(buffer, len - 1, "%s", cp);
4675 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
4676         if (handler)
4677                 ccs_addprintf(buffer, len, " task.%s", handler);
4678 #endif
4679         if (realpath)
4680                 ccs_addprintf(buffer, len, " exec.%s", realpath);
4681         if (argv0)
4682                 ccs_addprintf(buffer, len, " exec.argv[0]=%s", argv0);
4683         if (symlink)
4684                 ccs_addprintf(buffer, len, "%s", symlink);
4685         ccs_normalize_line(buffer);
4686         {
4687                 struct ccs_domain_info *domain = ccs_current_domain();
4688                 if (!ccs_write_acl(domain->ns, &domain->acl_info_list,
4689                                    buffer, false))
4690                         ccs_update_stat(CCS_STAT_POLICY_UPDATES);
4691         }
4692         kfree(buffer);
4693 }
4694 
4695 /**
4696  * ccs_domain_quota_ok - Check for domain's quota.
4697  *
4698  * @r: Pointer to "struct ccs_request_info".
4699  *
4700  * Returns true if the domain is not exceeded quota, false otherwise.
4701  *
4702  * Caller holds ccs_read_lock().
4703  */
4704 static bool ccs_domain_quota_ok(struct ccs_request_info *r)
4705 {
4706         unsigned int count = 0;
4707         struct ccs_domain_info * const domain = ccs_current_domain();
4708         struct ccs_acl_info *ptr;
4709         if (r->mode != CCS_CONFIG_LEARNING)
4710                 return false;
4711         if (!domain)
4712                 return true;
4713         list_for_each_entry_srcu(ptr, &domain->acl_info_list, list, &ccs_ss) {
4714                 u16 perm;
4715                 u8 i;
4716                 if (ptr->is_deleted)
4717                         continue;
4718                 switch (ptr->type) {
4719                 case CCS_TYPE_PATH_ACL:
4720                 case CCS_TYPE_PATH2_ACL:
4721                 case CCS_TYPE_PATH_NUMBER_ACL:
4722                 case CCS_TYPE_MKDEV_ACL:
4723 #ifdef CONFIG_CCSECURITY_NETWORK
4724                 case CCS_TYPE_INET_ACL:
4725                 case CCS_TYPE_UNIX_ACL:
4726 #endif
4727                         perm = ptr->perm;
4728                         break;
4729 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
4730                 case CCS_TYPE_AUTO_EXECUTE_HANDLER:
4731                 case CCS_TYPE_DENIED_EXECUTE_HANDLER:
4732 #endif
4733 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
4734                 case CCS_TYPE_AUTO_TASK_ACL:
4735                 case CCS_TYPE_MANUAL_TASK_ACL:
4736 #endif
4737                         perm = 0;
4738                         break;
4739                 default:
4740                         perm = 1;
4741                 }
4742                 for (i = 0; i < 16; i++)
4743                         if (perm & (1 << i))
4744                                 count++;
4745         }
4746         if (count < ccs_profile(r->profile)->pref[CCS_PREF_MAX_LEARNING_ENTRY])
4747                 return true;
4748         if (!domain->flags[CCS_DIF_QUOTA_WARNED]) {
4749                 domain->flags[CCS_DIF_QUOTA_WARNED] = true;
4750                 /* r->granted = false; */
4751                 ccs_write_log(r, "%s", ccs_dif[CCS_DIF_QUOTA_WARNED]);
4752                 printk(KERN_WARNING "WARNING: "
4753                        "Domain '%s' has too many ACLs to hold. "
4754                        "Stopped learning mode.\n", domain->domainname->name);
4755         }
4756         return false;
4757 }
4758 
4759 /**
4760  * ccs_supervisor - Ask for the supervisor's decision.
4761  *
4762  * @r:   Pointer to "struct ccs_request_info".
4763  * @fmt: The printf()'s format string, followed by parameters.
4764  *
4765  * Returns 0 if the supervisor decided to permit the access request which
4766  * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor
4767  * decided to retry the access request which violated the policy in enforcing
4768  * mode, 0 if it is not in enforcing mode, -EPERM otherwise.
4769  */
4770 static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
4771 {
4772         va_list args;
4773         int error;
4774         int len;
4775         static unsigned int ccs_serial;
4776         struct ccs_query entry = { };
4777         bool quota_exceeded = false;
4778         va_start(args, fmt);
4779         len = vsnprintf((char *) &len, 1, fmt, args) + 1;
4780         va_end(args);
4781         /* Write /proc/ccs/audit. */
4782         va_start(args, fmt);
4783         ccs_write_log2(r, len, fmt, args);
4784         va_end(args);
4785         /* Nothing more to do if granted. */
4786         if (r->granted)
4787                 return 0;
4788         if (r->mode)
4789                 ccs_update_stat(r->mode);
4790         switch (r->mode) {
4791                 int i;
4792                 struct ccs_profile *p;
4793         case CCS_CONFIG_ENFORCING:
4794                 error = -EPERM;
4795                 if (atomic_read(&ccs_query_observers))
4796                         break;
4797                 if (r->dont_sleep_on_enforce_error)
4798                         goto out;
4799                 p = ccs_profile(r->profile);
4800                 /* Check enforcing_penalty parameter. */
4801                 for (i = 0; i < p->pref[CCS_PREF_ENFORCING_PENALTY]; i++) {
4802                         set_current_state(TASK_INTERRUPTIBLE);
4803                         schedule_timeout(HZ / 10);
4804                 }
4805                 goto out;
4806         case CCS_CONFIG_LEARNING:
4807                 error = 0;
4808                 /* Check max_learning_entry parameter. */
4809                 if (ccs_domain_quota_ok(r))
4810                         break;
4811                 /* fall through */
4812         default:
4813                 return 0;
4814         }
4815         /* Get message. */
4816         va_start(args, fmt);
4817         entry.query = ccs_init_log(r, len, fmt, args);
4818         va_end(args);
4819         if (!entry.query)
4820                 goto out;
4821         entry.query_len = strlen(entry.query) + 1;
4822         if (!error) {
4823                 ccs_add_entry(entry.query);
4824                 goto out;
4825         }
4826         len = ccs_round2(entry.query_len);
4827         entry.domain = ccs_current_domain();
4828         spin_lock(&ccs_query_list_lock);
4829         if (ccs_memory_quota[CCS_MEMORY_QUERY] &&
4830             ccs_memory_used[CCS_MEMORY_QUERY] + len
4831             >= ccs_memory_quota[CCS_MEMORY_QUERY]) {
4832                 quota_exceeded = true;
4833         } else {
4834                 entry.serial = ccs_serial++;
4835                 entry.retry = r->retry;
4836                 ccs_memory_used[CCS_MEMORY_QUERY] += len;
4837                 list_add_tail(&entry.list, &ccs_query_list);
4838         }
4839         spin_unlock(&ccs_query_list_lock);
4840         if (quota_exceeded)
4841                 goto out;
4842         /* Give 10 seconds for supervisor's opinion. */
4843         while (entry.timer < 10) {
4844                 wake_up_all(&ccs_query_wait);
4845                 if (wait_event_interruptible_timeout
4846                     (ccs_answer_wait, entry.answer ||
4847                      !atomic_read(&ccs_query_observers), HZ))
4848                         break;
4849                 else
4850                         entry.timer++;
4851         }
4852         spin_lock(&ccs_query_list_lock);
4853         list_del(&entry.list);
4854         ccs_memory_used[CCS_MEMORY_QUERY] -= len;
4855         spin_unlock(&ccs_query_list_lock);
4856         switch (entry.answer) {
4857         case 3: /* Asked to retry by administrator. */
4858                 error = CCS_RETRY_REQUEST;
4859                 r->retry++;
4860                 break;
4861         case 1:
4862                 /* Granted by administrator. */
4863                 error = 0;
4864                 break;
4865         default:
4866                 /* Timed out or rejected by administrator. */
4867                 break;
4868         }
4869 out:
4870         kfree(entry.query);
4871         return error;
4872 }
4873 
4874 /**
4875  * ccs_audit_log - Audit permission check log.
4876  *
4877  * @r: Pointer to "struct ccs_request_info".
4878  *
4879  * Returns return value of ccs_supervisor().
4880  */
4881 int ccs_audit_log(struct ccs_request_info *r)
4882 {
4883         switch (r->param_type) {
4884                 u8 type;
4885                 char buf[48];
4886 #ifdef CONFIG_CCSECURITY_NETWORK
4887                 const u32 *address;
4888 #endif
4889         case CCS_TYPE_PATH_ACL:
4890                 return ccs_supervisor(r, "file %s %s\n", ccs_path_keyword
4891                                       [r->param.path.operation],
4892                                       r->param.path.filename->name);
4893         case CCS_TYPE_PATH2_ACL:
4894                 return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords
4895                                       [ccs_pp2mac[r->param.path2.operation]],
4896                                       r->param.path2.filename1->name,
4897                                       r->param.path2.filename2->name);
4898         case CCS_TYPE_PATH_NUMBER_ACL:
4899                 type = r->param.path_number.operation;
4900                 switch (type) {
4901                 case CCS_TYPE_CREATE:
4902                 case CCS_TYPE_MKDIR:
4903                 case CCS_TYPE_MKFIFO:
4904                 case CCS_TYPE_MKSOCK:
4905                 case CCS_TYPE_CHMOD:
4906                         snprintf(buf, sizeof(buf), "0%lo",
4907                                  r->param.path_number.number);
4908                         break;
4909                 case CCS_TYPE_IOCTL:
4910                         snprintf(buf, sizeof(buf), "0x%lX",
4911                                  r->param.path_number.number);
4912                         break;
4913                 default:
4914                         snprintf(buf, sizeof(buf), "%lu",
4915                                  r->param.path_number.number);
4916                         break;
4917                 }
4918                 return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords
4919                                       [ccs_pn2mac[type]],
4920                                       r->param.path_number.filename->name,
4921                                       buf);
4922         case CCS_TYPE_MKDEV_ACL:
4923                 return ccs_supervisor(r, "file %s %s 0%o %u %u\n",
4924                                       ccs_mac_keywords
4925                                       [ccs_pnnn2mac[r->param.mkdev.operation]],
4926                                       r->param.mkdev.filename->name,
4927                                       r->param.mkdev.mode,
4928                                       r->param.mkdev.major,
4929                                       r->param.mkdev.minor);
4930         case CCS_TYPE_MOUNT_ACL:
4931                 return ccs_supervisor(r, "file mount %s %s %s 0x%lX\n",
4932                                       r->param.mount.dev->name,
4933                                       r->param.mount.dir->name,
4934                                       r->param.mount.type->name,
4935                                       r->param.mount.flags);
4936 #ifdef CONFIG_CCSECURITY_MISC
4937         case CCS_TYPE_ENV_ACL:
4938                 return ccs_supervisor(r, "misc env %s\n",
4939                                       r->param.environ.name->name);
4940 #endif
4941 #ifdef CONFIG_CCSECURITY_CAPABILITY
4942         case CCS_TYPE_CAPABILITY_ACL:
4943                 return ccs_supervisor(r, "capability %s\n", ccs_mac_keywords
4944                                       [ccs_c2mac[r->param.capability.
4945                                                  operation]]);
4946 #endif
4947 #ifdef CONFIG_CCSECURITY_NETWORK
4948         case CCS_TYPE_INET_ACL:
4949                 address = r->param.inet_network.address;
4950                 if (r->param.inet_network.is_ipv6)
4951                         ccs_print_ipv6(buf, sizeof(buf),
4952                                        (const struct in6_addr *) address);
4953                 else
4954                         ccs_print_ipv4(buf, sizeof(buf), address);
4955                 return ccs_supervisor(r, "network inet %s %s %s %u\n",
4956                                       ccs_proto_keyword[r->param.inet_network.
4957                                                         protocol],
4958                                       ccs_socket_keyword[r->param.inet_network.
4959                                                          operation],
4960                                       buf, r->param.inet_network.port);
4961         case CCS_TYPE_UNIX_ACL:
4962                 return ccs_supervisor(r, "network unix %s %s %s\n",
4963                                       ccs_proto_keyword[r->param.
4964                                                         unix_network.protocol],
4965                                       ccs_socket_keyword[r->param.unix_network.
4966                                                          operation],
4967                                       r->param.unix_network.address->name);
4968 #endif
4969 #ifdef CONFIG_CCSECURITY_IPC
4970         case CCS_TYPE_SIGNAL_ACL:
4971                 return ccs_supervisor(r, "ipc signal %d %s\n",
4972                                       r->param.signal.sig,
4973                                       r->param.signal.dest_pattern);
4974 #endif
4975         }
4976         return 0;
4977 }
4978 
4979 /**
4980  * ccs_find_domain_by_qid - Get domain by query id.
4981  *
4982  * @serial: Query ID assigned by ccs_supervisor().
4983  *
4984  * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
4985  */
4986 static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial)
4987 {
4988         struct ccs_query *ptr;
4989         struct ccs_domain_info *domain = NULL;
4990         spin_lock(&ccs_query_list_lock);
4991         list_for_each_entry(ptr, &ccs_query_list, list) {
4992                 if (ptr->serial != serial)
4993                         continue;
4994                 domain = ptr->domain;
4995                 break;
4996         }
4997         spin_unlock(&ccs_query_list_lock);
4998         return domain;
4999 }
5000 
5001 /**
5002  * ccs_read_query - Read access requests which violated policy in enforcing mode.
5003  *
5004  * @head: Pointer to "struct ccs_io_buffer".
5005  *
5006  * Returns nothing.
5007  */
5008 static void ccs_read_query(struct ccs_io_buffer *head)
5009 {
5010         struct list_head *tmp;
5011         unsigned int pos = 0;
5012         size_t len = 0;
5013         char *buf;
5014         if (head->r.w_pos)
5015                 return;
5016         kfree(head->read_buf);
5017         head->read_buf = NULL;
5018         spin_lock(&ccs_query_list_lock);
5019         list_for_each(tmp, &ccs_query_list) {
5020                 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
5021                 if (pos++ != head->r.query_index)
5022                         continue;
5023                 len = ptr->query_len;
5024                 break;
5025         }
5026         spin_unlock(&ccs_query_list_lock);
5027         if (!len) {
5028                 head->r.query_index = 0;
5029                 return;
5030         }
5031         buf = kzalloc(len + 32, CCS_GFP_FLAGS);
5032         if (!buf)
5033                 return;
5034         pos = 0;
5035         spin_lock(&ccs_query_list_lock);
5036         list_for_each(tmp, &ccs_query_list) {
5037                 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
5038                 if (pos++ != head->r.query_index)
5039                         continue;
5040                 /*
5041                  * Some query can be skipped because ccs_query_list
5042                  * can change, but I don't care.
5043                  */
5044                 if (len == ptr->query_len)
5045                         snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
5046                                  ptr->retry, ptr->query);
5047                 break;
5048         }
5049         spin_unlock(&ccs_query_list_lock);
5050         if (buf[0]) {
5051                 head->read_buf = buf;
5052                 head->r.w[head->r.w_pos++] = buf;
5053                 head->r.query_index++;
5054         } else {
5055                 kfree(buf);
5056         }
5057 }
5058 
5059 /**
5060  * ccs_write_answer - Write the supervisor's decision.
5061  *
5062  * @head: Pointer to "struct ccs_io_buffer".
5063  *
5064  * Returns 0 on success, -EINVAL otherwise.
5065  */
5066 static int ccs_write_answer(struct ccs_io_buffer *head)
5067 {
5068         char *data = head->write_buf;
5069         struct list_head *tmp;
5070         unsigned int serial;
5071         unsigned int answer;
5072         spin_lock(&ccs_query_list_lock);
5073         list_for_each(tmp, &ccs_query_list) {
5074                 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
5075                 ptr->timer = 0;
5076         }
5077         spin_unlock(&ccs_query_list_lock);
5078         if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
5079                 return -EINVAL;
5080         spin_lock(&ccs_query_list_lock);
5081         list_for_each(tmp, &ccs_query_list) {
5082                 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
5083                 if (ptr->serial != serial)
5084                         continue;
5085                 ptr->answer = (u8) answer;
5086                 /* Remove from ccs_query_list. */
5087                 if (ptr->answer) {
5088                         list_del(&ptr->list);
5089                         INIT_LIST_HEAD(&ptr->list);
5090                 }
5091                 break;
5092         }
5093         spin_unlock(&ccs_query_list_lock);
5094         wake_up_all(&ccs_answer_wait);
5095         return 0;
5096 }
5097 
5098 /**
5099  * ccs_read_version - Get version.
5100  *
5101  * @head: Pointer to "struct ccs_io_buffer".
5102  *
5103  * Returns nothing.
5104  */
5105 static void ccs_read_version(struct ccs_io_buffer *head)
5106 {
5107         if (head->r.eof)
5108                 return;
5109         ccs_set_string(head, "1.8.5");
5110         head->r.eof = true;
5111 }
5112 
5113 /**
5114  * ccs_update_stat - Update statistic counters.
5115  *
5116  * @index: Index for policy type.
5117  *
5118  * Returns nothing.
5119  */
5120 static void ccs_update_stat(const u8 index)
5121 {
5122 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
5123         struct timeval tv;
5124         do_gettimeofday(&tv);
5125         /*
5126          * I don't use atomic operations because race condition is not fatal.
5127          */
5128         ccs_stat_updated[index]++;
5129         ccs_stat_modified[index] = tv.tv_sec;
5130 #else
5131         /*
5132          * I don't use atomic operations because race condition is not fatal.
5133          */
5134         ccs_stat_updated[index]++;
5135         ccs_stat_modified[index] = get_seconds();
5136 #endif
5137 }
5138 
5139 /**
5140  * ccs_read_stat - Read statistic data.
5141  *
5142  * @head: Pointer to "struct ccs_io_buffer".
5143  *
5144  * Returns nothing.
5145  */
5146 static void ccs_read_stat(struct ccs_io_buffer *head)
5147 {
5148         u8 i;
5149         unsigned int total = 0;
5150         if (head->r.eof)
5151                 return;
5152         for (i = 0; i < CCS_MAX_POLICY_STAT; i++) {
5153                 ccs_io_printf(head, "Policy %-30s %10u", ccs_policy_headers[i],
5154                               ccs_stat_updated[i]);
5155                 if (ccs_stat_modified[i]) {
5156                         struct ccs_time stamp;
5157                         ccs_convert_time(ccs_stat_modified[i], &stamp);
5158                         ccs_io_printf(head, " (Last: %04u/%02u/%02u "
5159                                       "%02u:%02u:%02u)",
5160                                       stamp.year, stamp.month, stamp.day,
5161                                       stamp.hour, stamp.min, stamp.sec);
5162                 }
5163                 ccs_set_lf(head);
5164         }
5165         for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) {
5166                 unsigned int used = ccs_memory_used[i];
5167                 total += used;
5168                 ccs_io_printf(head, "Memory used by %-22s %10u",
5169                               ccs_memory_headers[i], used);
5170                 used = ccs_memory_quota[i];
5171                 if (used)
5172                         ccs_io_printf(head, " (Quota: %10u)", used);
5173                 ccs_set_lf(head);
5174         }
5175         ccs_io_printf(head, "Total memory used:                    %10u\n",
5176                       total);
5177         head->r.eof = true;
5178 }
5179 
5180 /**
5181  * ccs_write_stat - Set memory quota.
5182  *
5183  * @head: Pointer to "struct ccs_io_buffer".
5184  *
5185  * Returns 0.
5186  */
5187 static int ccs_write_stat(struct ccs_io_buffer *head)
5188 {
5189         char *data = head->write_buf;
5190         u8 i;
5191         if (ccs_str_starts(&data, "Memory used by "))
5192                 for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
5193                         if (ccs_str_starts(&data, ccs_memory_headers[i])) {
5194                                 if (*data == ' ')
5195                                         data++;
5196                                 ccs_memory_quota[i] =
5197                                         simple_strtoul(data, NULL, 10);
5198                         }
5199         return 0;
5200 }
5201 
5202 /**
5203  * ccs_print_bprm - Print "struct linux_binprm" for auditing.
5204  *
5205  * @bprm: Pointer to "struct linux_binprm".
5206  * @dump: Pointer to "struct ccs_page_dump".
5207  *
5208  * Returns the contents of @bprm on success, NULL otherwise.
5209  *
5210  * This function uses kzalloc(), so caller must kfree() if this function
5211  * didn't return NULL.
5212  */
5213 static char *ccs_print_bprm(struct linux_binprm *bprm,
5214                             struct ccs_page_dump *dump)
5215 {
5216         static const int ccs_buffer_len = 4096 * 2;
5217         char *buffer = kzalloc(ccs_buffer_len, CCS_GFP_FLAGS);
5218         char *cp;
5219         char *last_start;
5220         int len;
5221         unsigned long pos = bprm->p;
5222         int offset = pos % PAGE_SIZE;
5223         int argv_count = bprm->argc;
5224         int envp_count = bprm->envc;
5225         bool truncated = false;
5226         if (!buffer)
5227                 return NULL;
5228         len = snprintf(buffer, ccs_buffer_len - 1, "argv[]={ ");
5229         cp = buffer + len;
5230         if (!argv_count) {
5231                 memmove(cp, "} envp[]={ ", 11);
5232                 cp += 11;
5233         }
5234         last_start = cp;
5235         while (argv_count || envp_count) {
5236                 if (!ccs_dump_page(bprm, pos, dump))
5237                         goto out;
5238                 pos += PAGE_SIZE - offset;
5239                 /* Read. */
5240                 while (offset < PAGE_SIZE) {
5241                         const char *kaddr = dump->data;
5242                         const unsigned char c = kaddr[offset++];
5243                         if (cp == last_start)
5244                                 *cp++ = '"';
5245                         if (cp >= buffer + ccs_buffer_len - 32) {
5246                                 /* Reserve some room for "..." string. */
5247                                 truncated = true;
5248                         } else if (c == '\\') {
5249                                 *cp++ = '\\';
5250                                 *cp++ = '\\';
5251                         } else if (c > ' ' && c < 127) {
5252                                 *cp++ = c;
5253                         } else if (!c) {
5254                                 *cp++ = '"';
5255                                 *cp++ = ' ';
5256                                 last_start = cp;
5257                         } else {
5258                                 *cp++ = '\\';
5259                                 *cp++ = (c >> 6) + '';
5260                                 *cp++ = ((c >> 3) & 7) + '';
5261                                 *cp++ = (c & 7) + '';
5262                         }
5263                         if (c)
5264                                 continue;
5265                         if (argv_count) {
5266                                 if (--argv_count == 0) {
5267                                         if (truncated) {
5268                                                 cp = last_start;
5269                                                 memmove(cp, "... ", 4);
5270                                                 cp += 4;
5271                                         }
5272                                         memmove(cp, "} envp[]={ ", 11);
5273                                         cp += 11;
5274                                         last_start = cp;
5275                                         truncated = false;
5276                                 }
5277                         } else if (envp_count) {
5278                                 if (--envp_count == 0) {
5279                                         if (truncated) {
5280                                                 cp = last_start;
5281                                                 memmove(cp, "... ", 4);
5282                                                 cp += 4;
5283                                         }
5284                                 }
5285                         }
5286                         if (!argv_count && !envp_count)
5287                                 break;
5288                 }
5289                 offset = 0;
5290         }
5291         *cp++ = '}';
5292         *cp = '\0';
5293         return buffer;
5294 out:
5295         snprintf(buffer, ccs_buffer_len - 1, "argv[]={ ... } envp[]= { ... }");
5296         return buffer;
5297 }
5298 
5299 /**
5300  * ccs_filetype - Get string representation of file type.
5301  *
5302  * @mode: Mode value for stat().
5303  *
5304  * Returns file type string.
5305  */
5306 static inline const char *ccs_filetype(const umode_t mode)
5307 {
5308         switch (mode & S_IFMT) {
5309         case S_IFREG:
5310         case 0:
5311                 return ccs_condition_keyword[CCS_TYPE_IS_FILE];
5312         case S_IFDIR:
5313                 return ccs_condition_keyword[CCS_TYPE_IS_DIRECTORY];
5314         case S_IFLNK:
5315                 return ccs_condition_keyword[CCS_TYPE_IS_SYMLINK];
5316         case S_IFIFO:
5317                 return ccs_condition_keyword[CCS_TYPE_IS_FIFO];
5318         case S_IFSOCK:
5319                 return ccs_condition_keyword[CCS_TYPE_IS_SOCKET];
5320         case S_IFBLK:
5321                 return ccs_condition_keyword[CCS_TYPE_IS_BLOCK_DEV];
5322         case S_IFCHR:
5323                 return ccs_condition_keyword[CCS_TYPE_IS_CHAR_DEV];
5324         }
5325         return "unknown"; /* This should not happen. */
5326 }
5327 
5328 /**
5329  * ccs_print_header - Get header line of audit log.
5330  *
5331  * @r: Pointer to "struct ccs_request_info".
5332  *
5333  * Returns string representation.
5334  *
5335  * This function uses kmalloc(), so caller must kfree() if this function
5336  * didn't return NULL.
5337  */
5338 static char *ccs_print_header(struct ccs_request_info *r)
5339 {
5340         struct ccs_time stamp;
5341         struct ccs_obj_info *obj = r->obj;
5342         const u32 ccs_flags = ccs_current_flags();
5343 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
5344         const pid_t gpid = ccs_sys_getpid();
5345 #else
5346         const pid_t gpid = task_pid_nr(current);
5347 #endif
5348         static const int ccs_buffer_len = 4096;
5349         char *buffer = kmalloc(ccs_buffer_len, CCS_GFP_FLAGS);
5350         int pos;
5351         u8 i;
5352         if (!buffer)
5353                 return NULL;
5354 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
5355         {
5356                 struct timeval tv;
5357                 do_gettimeofday(&tv);
5358                 ccs_convert_time(tv.tv_sec, &stamp);
5359         }
5360 #else
5361         ccs_convert_time(get_seconds(), &stamp);
5362 #endif
5363         pos = snprintf(buffer, ccs_buffer_len - 1,
5364                        "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
5365                        "granted=%s (global-pid=%u) task={ pid=%u ppid=%u "
5366                        "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
5367                        "fsuid=%u fsgid=%u type%s=execute_handler }",
5368                        stamp.year, stamp.month, stamp.day, stamp.hour,
5369                        stamp.min, stamp.sec, r->profile, ccs_mode[r->mode],
5370                        ccs_yesno(r->granted), gpid, ccs_sys_getpid(),
5371                        ccs_sys_getppid(),
5372                        from_kuid(&init_user_ns, current_uid()),
5373                        from_kgid(&init_user_ns, current_gid()),
5374                        from_kuid(&init_user_ns, current_euid()),
5375                        from_kgid(&init_user_ns, current_egid()),
5376                        from_kuid(&init_user_ns, current_suid()),
5377                        from_kgid(&init_user_ns, current_sgid()),
5378                        from_kuid(&init_user_ns, current_fsuid()),
5379                        from_kgid(&init_user_ns, current_fsgid()),
5380                        ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER ? "" : "!");
5381         if (!obj)
5382                 goto no_obj_info;
5383         if (!obj->validate_done) {
5384                 ccs_get_attributes(obj);
5385                 obj->validate_done = true;
5386         }
5387         for (i = 0; i < CCS_MAX_PATH_STAT; i++) {
5388                 struct ccs_mini_stat *stat;
5389                 unsigned int dev;
5390                 umode_t mode;
5391                 if (!obj->stat_valid[i])
5392                         continue;
5393                 stat = &obj->stat[i];
5394                 dev = stat->dev;
5395                 mode = stat->mode;
5396                 if (i & 1) {
5397                         pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos,
5398                                         " path%u.parent={ uid=%u gid=%u "
5399                                         "ino=%lu perm=0%o }", (i >> 1) + 1,
5400                                         from_kuid(&init_user_ns, stat->uid),
5401                                         from_kgid(&init_user_ns, stat->gid),
5402                                         (unsigned long) stat->ino,
5403                                         stat->mode & S_IALLUGO);
5404                         continue;
5405                 }
5406                 pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos,
5407                                 " path%u={ uid=%u gid=%u ino=%lu major=%u"
5408                                 " minor=%u perm=0%o type=%s", (i >> 1) + 1,
5409                                 from_kuid(&init_user_ns, stat->uid),
5410                                 from_kgid(&init_user_ns, stat->gid),
5411                                 (unsigned long) stat->ino, MAJOR(dev),
5412                                 MINOR(dev), mode & S_IALLUGO,
5413                                 ccs_filetype(mode));
5414                 if (S_ISCHR(mode) || S_ISBLK(mode)) {
5415                         dev = stat->rdev;
5416                         pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos,
5417                                         " dev_major=%u dev_minor=%u",
5418                                         MAJOR(dev), MINOR(dev));
5419                 }
5420                 pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos, " }");
5421         }
5422 no_obj_info:
5423         if (pos < ccs_buffer_len - 1)
5424                 return buffer;
5425         kfree(buffer);
5426         return NULL;
5427 }
5428 
5429 /**
5430  * ccs_init_log - Allocate buffer for audit logs.
5431  *
5432  * @r:    Pointer to "struct ccs_request_info".
5433  * @len:  Buffer size needed for @fmt and @args.
5434  * @fmt:  The printf()'s format string.
5435  * @args: va_list structure for @fmt.
5436  *
5437  * Returns pointer to allocated memory.
5438  *
5439  * This function uses kzalloc(), so caller must kfree() if this function
5440  * didn't return NULL.
5441  */
5442 static char *ccs_init_log(struct ccs_request_info *r, int len, const char *fmt,
5443                           va_list args)
5444 {
5445         char *buf = NULL;
5446         char *bprm_info = NULL;
5447         char *realpath = NULL;
5448         const char *symlink = NULL;
5449         const char *header = NULL;
5450         int pos;
5451         const char *domainname = ccs_current_domain()->domainname->name;
5452         header = ccs_print_header(r);
5453         if (!header)
5454                 return NULL;
5455         /* +10 is for '\n' etc. and '\0'. */
5456         len += strlen(domainname) + strlen(header) + 10;
5457         if (r->ee) {
5458                 struct file *file = r->ee->bprm->file;
5459 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
5460                 struct path path = { file->f_vfsmnt, file->f_dentry };
5461                 realpath = ccs_realpath(&path);
5462 #else
5463                 realpath = ccs_realpath(&file->f_path);
5464 #endif
5465                 bprm_info = ccs_print_bprm(r->ee->bprm, &r->ee->dump);
5466                 if (!realpath || !bprm_info)
5467                         goto out;
5468                 /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */
5469                 len += strlen(realpath) + 80 + strlen(bprm_info);
5470         } else if (r->obj && r->obj->symlink_target) {
5471                 symlink = r->obj->symlink_target->name;
5472                 /* +18 is for " symlink.target=\"%s\"" */
5473                 len += 18 + strlen(symlink);
5474         }
5475         len = ccs_round2(len);
5476         buf = kzalloc(len, CCS_GFP_FLAGS);
5477         if (!buf)
5478                 goto out;
5479         len--;
5480         pos = snprintf(buf, len, "%s", header);
5481         if (realpath) {
5482                 struct linux_binprm *bprm = r->ee->bprm;
5483                 pos += snprintf(buf + pos, len - pos,
5484                                 " exec={ realpath=\"%s\" argc=%d envc=%d %s }",
5485                                 realpath, bprm->argc, bprm->envc, bprm_info);
5486         } else if (symlink)
5487                 pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"",
5488                                 symlink);
5489         pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname);
5490         vsnprintf(buf + pos, len - pos, fmt, args);
5491 out:
5492         kfree(realpath);
5493         kfree(bprm_info);
5494         kfree(header);
5495         return buf;
5496 }
5497 
5498 /**
5499  * ccs_transition_failed - Print waning message and send signal when domain transition failed.
5500  *
5501  * @domainname: Name of domain to transit.
5502  *
5503  * Returns nothing.
5504  *
5505  * Note that if current->pid == 1, sending SIGKILL won't work.
5506  */
5507 void ccs_transition_failed(const char *domainname)
5508 {
5509         printk(KERN_WARNING
5510                "ERROR: Unable to transit to '%s' domain.\n", domainname);
5511         force_sig(SIGKILL, current);
5512 }
5513 
5514 /**
5515  * ccs_update_task_domain - Update task's domain.
5516  *
5517  * @r: Pointer to "struct ccs_request_info".
5518  *
5519  * Returns nothing.
5520  *
5521  * The task will retry as hard as possible. But if domain transition failed,
5522  * the task will be killed by SIGKILL.
5523  */
5524 static void ccs_update_task_domain(struct ccs_request_info *r)
5525 {
5526         char *buf;
5527         const char *cp;
5528         const struct ccs_acl_info *acl = r->matched_acl;
5529         r->matched_acl = NULL;
5530         if (!acl || !acl->cond || !acl->cond->transit ||
5531             acl->cond->exec_transit)
5532                 return;
5533         while (1) {
5534                 buf = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
5535                 if (buf)
5536                         break;
5537                 ssleep(1);
5538                 if (fatal_signal_pending(current))
5539                         return;
5540         }
5541         cp = acl->cond->transit->name;
5542         if (*cp == '/')
5543                 snprintf(buf, CCS_EXEC_TMPSIZE - 1, "%s %s",
5544                          ccs_current_domain()->domainname->name, cp);
5545         else
5546                 strncpy(buf, cp, CCS_EXEC_TMPSIZE - 1);
5547         if (!ccs_assign_domain(buf, true))
5548                 ccs_transition_failed(buf);
5549         kfree(buf);
5550 }
5551 
5552 /**
5553  * ccs_get_audit - Get audit mode.
5554  *
5555  * @r: Pointer to "struct ccs_request_info".
5556  *
5557  * Returns true if this request should be audited, false otherwise.
5558  */
5559 static bool ccs_get_audit(const struct ccs_request_info *r)
5560 {
5561         const struct ccs_acl_info *matched_acl = r->matched_acl;
5562         const u8 profile = r->profile;
5563         const u8 index = r->type;
5564         const bool is_granted = r->granted;
5565         u8 mode;
5566         struct ccs_profile *p;
5567         if (!ccs_policy_loaded)
5568                 return false;
5569         p = ccs_profile(profile);
5570         if (ccs_log_count >= p->pref[CCS_PREF_MAX_AUDIT_LOG])
5571                 return false;
5572         if (is_granted && matched_acl && matched_acl->cond &&
5573             matched_acl->cond->grant_log != CCS_GRANTLOG_AUTO)
5574                 return matched_acl->cond->grant_log == CCS_GRANTLOG_YES;
5575         mode = p->config[index];
5576         if (mode == CCS_CONFIG_USE_DEFAULT)
5577                 mode = p->config
5578                         [ccs_index2category[index] + CCS_MAX_MAC_INDEX];
5579         if (mode == CCS_CONFIG_USE_DEFAULT)
5580                 mode = p->default_config;
5581         if (is_granted)
5582                 return mode & CCS_CONFIG_WANT_GRANT_LOG;
5583         return mode & CCS_CONFIG_WANT_REJECT_LOG;
5584 }
5585 
5586 /**
5587  * ccs_write_log2 - Write an audit log.
5588  *
5589  * @r:    Pointer to "struct ccs_request_info".
5590  * @len:  Buffer size needed for @fmt and @args.
5591  * @fmt:  The printf()'s format string.
5592  * @args: va_list structure for @fmt.
5593  *
5594  * Returns nothing.
5595  */
5596 static void ccs_write_log2(struct ccs_request_info *r, int len,
5597                            const char *fmt, va_list args)
5598 {
5599         char *buf;
5600         struct ccs_log *entry;
5601         bool quota_exceeded = false;
5602         if (!ccs_get_audit(r))
5603                 goto out;
5604         buf = ccs_init_log(r, len, fmt, args);
5605         if (!buf)
5606                 goto out;
5607         entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
5608         if (!entry) {
5609                 kfree(buf);
5610                 goto out;
5611         }
5612         entry->log = buf;
5613         len = ccs_round2(strlen(buf) + 1);
5614         /*
5615          * The entry->size is used for memory quota checks.
5616          * Don't go beyond strlen(entry->log).
5617          */
5618         entry->size = len + ccs_round2(sizeof(*entry));
5619         spin_lock(&ccs_log_lock);
5620         if (ccs_memory_quota[CCS_MEMORY_AUDIT] &&
5621             ccs_memory_used[CCS_MEMORY_AUDIT] + entry->size >=
5622             ccs_memory_quota[CCS_MEMORY_AUDIT]) {
5623                 quota_exceeded = true;
5624         } else {
5625                 ccs_memory_used[CCS_MEMORY_AUDIT] += entry->size;
5626                 list_add_tail(&entry->list, &ccs_log);
5627                 ccs_log_count++;
5628         }
5629         spin_unlock(&ccs_log_lock);
5630         if (quota_exceeded) {
5631                 kfree(buf);
5632                 kfree(entry);
5633                 goto out;
5634         }
5635         wake_up(&ccs_log_wait);
5636 out:
5637         ccs_update_task_domain(r);
5638 }
5639 
5640 /**
5641  * ccs_write_log - Write an audit log.
5642  *
5643  * @r:   Pointer to "struct ccs_request_info".