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

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

Version: ~ [ linux-5.12-rc1 ] ~ [ linux-5.11.2 ] ~ [ linux-5.10.19 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.101 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.177 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.222 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.258 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.258 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ 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.6+   2020/04/13
  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 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
522 static void ccs_convert_time(time_t time, struct ccs_time *stamp);
523 #else
524 static void ccs_convert_time(time64_t time, struct ccs_time *stamp);
525 #endif
526 static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns);
527 static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
528         __printf(2, 3);
529 static void ccs_normalize_line(unsigned char *buffer);
530 static void ccs_print_config(struct ccs_io_buffer *head, const u8 config);
531 static void ccs_print_name_union(struct ccs_io_buffer *head,
532                                  const struct ccs_name_union *ptr);
533 static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
534                                         const struct ccs_name_union *ptr);
535 static void ccs_print_namespace(struct ccs_io_buffer *head);
536 static void ccs_print_number_union(struct ccs_io_buffer *head,
537                                    const struct ccs_number_union *ptr);
538 static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
539                                            const struct ccs_number_union *ptr);
540 static void ccs_read_domain(struct ccs_io_buffer *head);
541 static void ccs_read_exception(struct ccs_io_buffer *head);
542 static void ccs_read_log(struct ccs_io_buffer *head);
543 static void ccs_read_manager(struct ccs_io_buffer *head);
544 static void ccs_read_pid(struct ccs_io_buffer *head);
545 static void ccs_read_profile(struct ccs_io_buffer *head);
546 static void ccs_read_query(struct ccs_io_buffer *head);
547 static void ccs_read_stat(struct ccs_io_buffer *head);
548 static void ccs_read_version(struct ccs_io_buffer *head);
549 static void ccs_set_group(struct ccs_io_buffer *head, const char *category);
550 static void ccs_set_namespace_cursor(struct ccs_io_buffer *head);
551 static void ccs_set_slash(struct ccs_io_buffer *head);
552 static void ccs_set_space(struct ccs_io_buffer *head);
553 static void ccs_set_string(struct ccs_io_buffer *head, const char *string);
554 static void ccs_set_uint(unsigned int *i, const char *string,
555                          const char *find);
556 static void ccs_update_stat(const u8 index);
557 static void ccs_update_task_domain(struct ccs_request_info *r);
558 static void ccs_write_log2(struct ccs_request_info *r, int len,
559                            const char *fmt, va_list args);
560 
561 #ifdef CONFIG_CCSECURITY_PORTRESERVE
562 static bool __ccs_lport_reserved(const u16 port);
563 static int ccs_write_reserved_port(struct ccs_acl_param *param);
564 #endif
565 
566 #ifdef CONFIG_CCSECURITY_NETWORK
567 static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
568                                    struct ccs_ipaddr_union *ptr);
569 static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
570                           const u32 *ip);
571 static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
572                           const struct in6_addr *ip);
573 static int ccs_write_inet_network(struct ccs_acl_param *param);
574 static int ccs_write_unix_network(struct ccs_acl_param *param);
575 static void ccs_print_ip(char *buf, const unsigned int size,
576                          const struct ccs_ipaddr_union *ptr);
577 #endif
578 
579 #ifdef CONFIG_CCSECURITY_CAPABILITY
580 static int ccs_write_capability(struct ccs_acl_param *param);
581 #endif
582 
583 #ifdef CONFIG_CCSECURITY_MISC
584 static int ccs_write_misc(struct ccs_acl_param *param);
585 #endif
586 
587 #ifdef CONFIG_CCSECURITY_IPC
588 static int ccs_write_ipc(struct ccs_acl_param *param);
589 #endif
590 
591 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
592 static ssize_t ccs_write_self(struct file *file, const char __user *buf,
593                               size_t count, loff_t *ppos);
594 #endif
595 
596 /***** SECTION4: Standalone functions section *****/
597 
598 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
599 
600 /**
601  * fatal_signal_pending - Check whether SIGKILL is pending or not.
602  *
603  * @p: Pointer to "struct task_struct".
604  *
605  * Returns true if SIGKILL is pending on @p, false otherwise.
606  *
607  * This is for compatibility with older kernels.
608  */
609 #define fatal_signal_pending(p) (signal_pending(p) &&                   \
610                                  sigismember(&p->pending.signal, SIGKILL))
611 
612 #endif
613 
614 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
615 
616 /**
617  * __wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
618  *
619  * @wq:        The waitqueue to wait on.
620  * @condition: A C expression for the event to wait for.
621  * @ret:       Timeout, in jiffies.
622  *
623  * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
624  * signal, and the remaining jiffies otherwise if the condition evaluated to
625  * true before the timeout elapsed.
626  *
627  * This is for compatibility with older kernels.
628  */
629 #define __wait_event_interruptible_timeout(wq, condition, ret)          \
630 do {                                                                    \
631         wait_queue_t __wait;                                            \
632         init_waitqueue_entry(&__wait, current);                         \
633                                                                         \
634         add_wait_queue(&wq, &__wait);                                   \
635         for (;;) {                                                      \
636                 set_current_state(TASK_INTERRUPTIBLE);                  \
637                 if (condition)                                          \
638                         break;                                          \
639                 if (!signal_pending(current)) {                         \
640                         ret = schedule_timeout(ret);                    \
641                         if (!ret)                                       \
642                                 break;                                  \
643                         continue;                                       \
644                 }                                                       \
645                 ret = -ERESTARTSYS;                                     \
646                 break;                                                  \
647         }                                                               \
648         current->state = TASK_RUNNING;                                  \
649         remove_wait_queue(&wq, &__wait);                                \
650 } while (0)
651 
652 /**
653  * wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
654  *
655  * @wq:        The waitqueue to wait on.
656  * @condition: A C expression for the event to wait for.
657  * @timeout:   Timeout, in jiffies.
658  *
659  * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
660  * signal, and the remaining jiffies otherwise if the condition evaluated to
661  * true before the timeout elapsed.
662  *
663  * This is for compatibility with older kernels.
664  */
665 #define wait_event_interruptible_timeout(wq, condition, timeout)        \
666 ({                                                                      \
667         long __ret = timeout;                                           \
668         if (!(condition))                                               \
669                 __wait_event_interruptible_timeout(wq, condition, __ret); \
670         __ret;                                                          \
671 })
672 
673 #endif
674 
675 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
676 /**
677  * ccs_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
678  *
679  * @time:  Seconds since 1970/01/01 00:00:00.
680  * @stamp: Pointer to "struct ccs_time".
681  *
682  * Returns nothing.
683  *
684  * This function does not handle Y2038 problem.
685  */
686 static void ccs_convert_time(time_t time, struct ccs_time *stamp)
687 {
688         static const u16 ccs_eom[2][12] = {
689                 { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
690                 { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
691         };
692         u16 y;
693         u8 m;
694         bool r;
695         stamp->sec = time % 60;
696         time /= 60;
697         stamp->min = time % 60;
698         time /= 60;
699         stamp->hour = time % 24;
700         time /= 24;
701         for (y = 1970; ; y++) {
702                 const unsigned short days = (y & 3) ? 365 : 366;
703                 if (time < days)
704                         break;
705                 time -= days;
706         }
707         r = (y & 3) == 0;
708         for (m = 0; m < 11 && time >= ccs_eom[r][m]; m++);
709         if (m)
710                 time -= ccs_eom[r][m - 1];
711         stamp->year = y;
712         stamp->month = ++m;
713         stamp->day = ++time;
714 }
715 #else
716 /**
717  * ccs_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
718  *
719  * @time:  Seconds since 1970/01/01 00:00:00.
720  * @stamp: Pointer to "struct ccs_time".
721  *
722  * Returns nothing.
723  */
724 static void ccs_convert_time(time64_t time, struct ccs_time *stamp)
725 {
726         struct tm tm;
727 
728         time64_to_tm(time, 0, &tm);
729         stamp->sec = tm.tm_sec;
730         stamp->min = tm.tm_min;
731         stamp->hour = tm.tm_hour;
732         stamp->day = tm.tm_mday;
733         stamp->month = tm.tm_mon + 1;
734         stamp->year = tm.tm_year + 1900;
735 }
736 #endif
737 
738 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 23)
739 #if !defined(RHEL_VERSION) || RHEL_VERSION != 3
740 
741 /**
742  * PDE - Get "struct proc_dir_entry".
743  *
744  * @inode: Pointer to "struct inode".
745  *
746  * Returns pointer to "struct proc_dir_entry".
747  *
748  * This is for compatibility with older kernels.
749  */
750 static inline struct proc_dir_entry *PDE(const struct inode *inode)
751 {
752         return (struct proc_dir_entry *) inode->u.generic_ip;
753 }
754 
755 #endif
756 #endif
757 
758 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
759 
760 /**
761  * proc_notify_change - Update inode's attributes and reflect to the dentry.
762  *
763  * @dentry: Pointer to "struct dentry".
764  * @iattr:  Pointer to "struct iattr".
765  *
766  * Returns 0 on success, negative value otherwise.
767  *
768  * The 2.4 kernels don't allow chmod()/chown() for files in /proc,
769  * while the 2.6 kernels allow.
770  * To permit management of /proc/ccs/ interface by non-root user,
771  * I modified to allow chmod()/chown() of /proc/ccs/ interface like 2.6 kernels
772  * by adding "struct inode_operations"->setattr hook.
773  */
774 static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
775 {
776         struct inode *inode = dentry->d_inode;
777         struct proc_dir_entry *de = PDE(inode);
778         int error;
779 
780         error = inode_change_ok(inode, iattr);
781         if (error)
782                 goto out;
783 
784         error = inode_setattr(inode, iattr);
785         if (error)
786                 goto out;
787 
788         de->uid = inode->i_uid;
789         de->gid = inode->i_gid;
790         de->mode = inode->i_mode;
791 out:
792         return error;
793 }
794 
795 #endif
796 
797 #ifdef CONFIG_CCSECURITY_NETWORK
798 
799 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && defined(CONFIG_NET)
800 #define ccs_in4_pton in4_pton
801 #define ccs_in6_pton in6_pton
802 #else
803 /*
804  * Routines for parsing IPv4 or IPv6 address.
805  * These are copied from lib/hexdump.c net/core/utils.c .
806  */
807 #include <linux/ctype.h>
808 
809 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
810 static int hex_to_bin(char ch)
811 {
812         if ((ch >= '') && (ch <= '9'))
813                 return ch - '';
814         ch = tolower(ch);
815         if ((ch >= 'a') && (ch <= 'f'))
816                 return ch - 'a' + 10;
817         return -1;
818 }
819 #endif
820 
821 #define IN6PTON_XDIGIT          0x00010000
822 #define IN6PTON_DIGIT           0x00020000
823 #define IN6PTON_COLON_MASK      0x00700000
824 #define IN6PTON_COLON_1         0x00100000      /* single : requested */
825 #define IN6PTON_COLON_2         0x00200000      /* second : requested */
826 #define IN6PTON_COLON_1_2       0x00400000      /* :: requested */
827 #define IN6PTON_DOT             0x00800000      /* . */
828 #define IN6PTON_DELIM           0x10000000
829 #define IN6PTON_NULL            0x20000000      /* first/tail */
830 #define IN6PTON_UNKNOWN         0x40000000
831 
832 static inline int xdigit2bin(char c, int delim)
833 {
834         int val;
835 
836         if (c == delim || c == '\0')
837                 return IN6PTON_DELIM;
838         if (c == ':')
839                 return IN6PTON_COLON_MASK;
840         if (c == '.')
841                 return IN6PTON_DOT;
842 
843         val = hex_to_bin(c);
844         if (val >= 0)
845                 return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0);
846 
847         if (delim == -1)
848                 return IN6PTON_DELIM;
849         return IN6PTON_UNKNOWN;
850 }
851 
852 static int ccs_in4_pton(const char *src, int srclen, u8 *dst, int delim,
853                         const char **end)
854 {
855         const char *s;
856         u8 *d;
857         u8 dbuf[4];
858         int ret = 0;
859         int i;
860         int w = 0;
861 
862         if (srclen < 0)
863                 srclen = strlen(src);
864         s = src;
865         d = dbuf;
866         i = 0;
867         while (1) {
868                 int c;
869                 c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
870                 if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM |
871                            IN6PTON_COLON_MASK)))
872                         goto out;
873                 if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
874                         if (w == 0)
875                                 goto out;
876                         *d++ = w & 0xff;
877                         w = 0;
878                         i++;
879                         if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
880                                 if (i != 4)
881                                         goto out;
882                                 break;
883                         }
884                         goto cont;
885                 }
886                 w = (w * 10) + c;
887                 if ((w & 0xffff) > 255)
888                         goto out;
889 cont:
890                 if (i >= 4)
891                         goto out;
892                 s++;
893                 srclen--;
894         }
895         ret = 1;
896         memcpy(dst, dbuf, sizeof(dbuf));
897 out:
898         if (end)
899                 *end = s;
900         return ret;
901 }
902 
903 static int ccs_in6_pton(const char *src, int srclen, u8 *dst, int delim,
904                         const char **end)
905 {
906         const char *s, *tok = NULL;
907         u8 *d, *dc = NULL;
908         u8 dbuf[16];
909         int ret = 0;
910         int i;
911         int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL;
912         int w = 0;
913 
914         memset(dbuf, 0, sizeof(dbuf));
915 
916         s = src;
917         d = dbuf;
918         if (srclen < 0)
919                 srclen = strlen(src);
920 
921         while (1) {
922                 int c;
923 
924                 c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
925                 if (!(c & state))
926                         goto out;
927                 if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
928                         /* process one 16-bit word */
929                         if (!(state & IN6PTON_NULL)) {
930                                 *d++ = (w >> 8) & 0xff;
931                                 *d++ = w & 0xff;
932                         }
933                         w = 0;
934                         if (c & IN6PTON_DELIM) {
935                                 /* We've processed last word */
936                                 break;
937                         }
938                         /*
939                          * COLON_1 => XDIGIT
940                          * COLON_2 => XDIGIT|DELIM
941                          * COLON_1_2 => COLON_2
942                          */
943                         switch (state & IN6PTON_COLON_MASK) {
944                         case IN6PTON_COLON_2:
945                                 dc = d;
946                                 state = IN6PTON_XDIGIT | IN6PTON_DELIM;
947                                 if (dc - dbuf >= sizeof(dbuf))
948                                         state |= IN6PTON_NULL;
949                                 break;
950                         case IN6PTON_COLON_1|IN6PTON_COLON_1_2:
951                                 state = IN6PTON_XDIGIT | IN6PTON_COLON_2;
952                                 break;
953                         case IN6PTON_COLON_1:
954                                 state = IN6PTON_XDIGIT;
955                                 break;
956                         case IN6PTON_COLON_1_2:
957                                 state = IN6PTON_COLON_2;
958                                 break;
959                         default:
960                                 state = 0;
961                         }
962                         tok = s + 1;
963                         goto cont;
964                 }
965 
966                 if (c & IN6PTON_DOT) {
967                         ret = ccs_in4_pton(tok ? tok : s, srclen +
968                                            (int)(s - tok), d, delim, &s);
969                         if (ret > 0) {
970                                 d += 4;
971                                 break;
972                         }
973                         goto out;
974                 }
975 
976                 w = (w << 4) | (0xff & c);
977                 state = IN6PTON_COLON_1 | IN6PTON_DELIM;
978                 if (!(w & 0xf000))
979                         state |= IN6PTON_XDIGIT;
980                 if (!dc && d + 2 < dbuf + sizeof(dbuf)) {
981                         state |= IN6PTON_COLON_1_2;
982                         state &= ~IN6PTON_DELIM;
983                 }
984                 if (d + 2 >= dbuf + sizeof(dbuf))
985                         state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2);
986 cont:
987                 if ((dc && d + 4 < dbuf + sizeof(dbuf)) ||
988                     d + 4 == dbuf + sizeof(dbuf))
989                         state |= IN6PTON_DOT;
990                 if (d >= dbuf + sizeof(dbuf))
991                         state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK);
992                 s++;
993                 srclen--;
994         }
995 
996         i = 15; d--;
997 
998         if (dc) {
999                 while (d >= dc)
1000                         dst[i--] = *d--;
1001                 while (i >= dc - dbuf)
1002                         dst[i--] = 0;
1003                 while (i >= 0)
1004                         dst[i--] = *d--;
1005         } else
1006                 memcpy(dst, dbuf, sizeof(dbuf));
1007 
1008         ret = 1;
1009 out:
1010         if (end)
1011                 *end = s;
1012         return ret;
1013 }
1014 #endif
1015 
1016 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
1017 
1018 /*
1019  * Routines for printing IPv4 or IPv6 address.
1020  * These are copied from include/linux/kernel.h include/net/ipv6.h
1021  * include/net/addrconf.h lib/hexdump.c lib/vsprintf.c and simplified.
1022  */
1023 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
1024 #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5 || !defined(RHEL_MINOR) || RHEL_MINOR < 9
1025 static const char hex_asc[] = "0123456789abcdef";
1026 #define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
1027 #define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
1028 
1029 static inline char *pack_hex_byte(char *buf, u8 byte)
1030 {
1031         *buf++ = hex_asc_hi(byte);
1032         *buf++ = hex_asc_lo(byte);
1033         return buf;
1034 }
1035 #endif
1036 #endif
1037 
1038 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1039 static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
1040 {
1041         return (a->s6_addr32[0] | a->s6_addr32[1] |
1042                 (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0;
1043 }
1044 #endif
1045 
1046 static inline int ipv6_addr_is_isatap(const struct in6_addr *addr)
1047 {
1048         return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
1049 }
1050 
1051 static char *ip4_string(char *p, const u8 *addr)
1052 {
1053         /*
1054          * Since this function is called outside vsnprintf(), I can use
1055          * sprintf() here.
1056          */
1057         return p +
1058                 sprintf(p, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
1059 }
1060 
1061 static char *ip6_compressed_string(char *p, const char *addr)
1062 {
1063         int i, j, range;
1064         unsigned char zerolength[8];
1065         int longest = 1;
1066         int colonpos = -1;
1067         u16 word;
1068         u8 hi, lo;
1069         bool needcolon = false;
1070         bool useIPv4;
1071         struct in6_addr in6;
1072 
1073         memcpy(&in6, addr, sizeof(struct in6_addr));
1074 
1075         useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
1076 
1077         memset(zerolength, 0, sizeof(zerolength));
1078 
1079         if (useIPv4)
1080                 range = 6;
1081         else
1082                 range = 8;
1083 
1084         /* find position of longest 0 run */
1085         for (i = 0; i < range; i++) {
1086                 for (j = i; j < range; j++) {
1087                         if (in6.s6_addr16[j] != 0)
1088                                 break;
1089                         zerolength[i]++;
1090                 }
1091         }
1092         for (i = 0; i < range; i++) {
1093                 if (zerolength[i] > longest) {
1094                         longest = zerolength[i];
1095                         colonpos = i;
1096                 }
1097         }
1098         if (longest == 1)               /* don't compress a single 0 */
1099                 colonpos = -1;
1100 
1101         /* emit address */
1102         for (i = 0; i < range; i++) {
1103                 if (i == colonpos) {
1104                         if (needcolon || i == 0)
1105                                 *p++ = ':';
1106                         *p++ = ':';
1107                         needcolon = false;
1108                         i += longest - 1;
1109                         continue;
1110                 }
1111                 if (needcolon) {
1112                         *p++ = ':';
1113                         needcolon = false;
1114                 }
1115                 /* hex u16 without leading 0s */
1116                 word = ntohs(in6.s6_addr16[i]);
1117                 hi = word >> 8;
1118                 lo = word & 0xff;
1119                 if (hi) {
1120                         if (hi > 0x0f)
1121                                 p = pack_hex_byte(p, hi);
1122                         else
1123                                 *p++ = hex_asc_lo(hi);
1124                         p = pack_hex_byte(p, lo);
1125                 } else if (lo > 0x0f)
1126                         p = pack_hex_byte(p, lo);
1127                 else
1128                         *p++ = hex_asc_lo(lo);
1129                 needcolon = true;
1130         }
1131 
1132         if (useIPv4) {
1133                 if (needcolon)
1134                         *p++ = ':';
1135                 p = ip4_string(p, &in6.s6_addr[12]);
1136         }
1137         *p = '\0';
1138 
1139         return p;
1140 }
1141 #endif
1142 
1143 /**
1144  * ccs_print_ipv4 - Print an IPv4 address.
1145  *
1146  * @buffer:     Buffer to write to.
1147  * @buffer_len: Size of @buffer.
1148  * @ip:         Pointer to "u32 in network byte order".
1149  *
1150  * Returns written length.
1151  */
1152 static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
1153                           const u32 *ip)
1154 {
1155 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
1156         return snprintf(buffer, buffer_len, "%pI4", ip);
1157 #else
1158         char addr[sizeof("255.255.255.255")];
1159         ip4_string(addr, (const u8 *) ip);
1160         return snprintf(buffer, buffer_len, "%s", addr);
1161 #endif
1162 }
1163 
1164 /**
1165  * ccs_print_ipv6 - Print an IPv6 address.
1166  *
1167  * @buffer:     Buffer to write to.
1168  * @buffer_len: Size of @buffer.
1169  * @ip:         Pointer to "struct in6_addr".
1170  *
1171  * Returns written length.
1172  */
1173 static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
1174                           const struct in6_addr *ip)
1175 {
1176 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
1177         return snprintf(buffer, buffer_len, "%pI6c", ip);
1178 #else
1179         char addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
1180         ip6_compressed_string(addr, (const u8 *) ip);
1181         return snprintf(buffer, buffer_len, "%s", addr);
1182 #endif
1183 }
1184 
1185 /**
1186  * ccs_print_ip - Print an IP address.
1187  *
1188  * @buf:  Buffer to write to.
1189  * @size: Size of @buf.
1190  * @ptr:  Pointer to "struct ipaddr_union".
1191  *
1192  * Returns nothing.
1193  */
1194 static void ccs_print_ip(char *buf, const unsigned int size,
1195                          const struct ccs_ipaddr_union *ptr)
1196 {
1197         int len;
1198         if (ptr->is_ipv6)
1199                 len = ccs_print_ipv6(buf, size, &ptr->ip[0]);
1200         else
1201                 len = ccs_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0]);
1202         if (!memcmp(&ptr->ip[0], &ptr->ip[1], 16) || len >= size / 2)
1203                 return;
1204         buf[len++] = '-';
1205         if (ptr->is_ipv6)
1206                 ccs_print_ipv6(buf + len, size - len, &ptr->ip[1]);
1207         else
1208                 ccs_print_ipv4(buf + len, size - len,
1209                                &ptr->ip[1].s6_addr32[0]);
1210 }
1211 
1212 #endif
1213 
1214 /***** SECTION5: Variables definition section *****/
1215 
1216 /* Permit policy management by non-root user? */
1217 static bool ccs_manage_by_non_root;
1218 
1219 /* Lock for protecting policy. */
1220 DEFINE_MUTEX(ccs_policy_lock);
1221 
1222 /* Has /sbin/init started? */
1223 bool ccs_policy_loaded;
1224 
1225 /* List of namespaces. */
1226 LIST_HEAD(ccs_namespace_list);
1227 /* True if namespace other than ccs_kernel_namespace is defined. */
1228 static bool ccs_namespace_enabled;
1229 
1230 /* Initial namespace.*/
1231 static struct ccs_policy_namespace ccs_kernel_namespace;
1232 
1233 /* List of "struct ccs_condition". */
1234 LIST_HEAD(ccs_condition_list);
1235 
1236 #ifdef CONFIG_CCSECURITY_PORTRESERVE
1237 /* Bitmap for reserved local port numbers.*/
1238 static u8 ccs_reserved_port_map[8192];
1239 #endif
1240 
1241 /* Wait queue for kernel -> userspace notification. */
1242 static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1243 /* Wait queue for userspace -> kernel notification. */
1244 static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);
1245 
1246 /* The list for "struct ccs_query". */
1247 static LIST_HEAD(ccs_query_list);
1248 
1249 /* Lock for manipulating ccs_query_list. */
1250 static DEFINE_SPINLOCK(ccs_query_list_lock);
1251 
1252 /* Number of "struct file" referring /proc/ccs/query interface. */
1253 static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1254 
1255 /* Wait queue for /proc/ccs/audit. */
1256 static DECLARE_WAIT_QUEUE_HEAD(ccs_log_wait);
1257 
1258 /* The list for "struct ccs_log". */
1259 static LIST_HEAD(ccs_log);
1260 
1261 /* Lock for "struct list_head ccs_log". */
1262 static DEFINE_SPINLOCK(ccs_log_lock);
1263 
1264 /* Length of "stuct list_head ccs_log". */
1265 static unsigned int ccs_log_count;
1266 
1267 /* Counter for number of updates. */
1268 static atomic_t ccs_stat_updated[CCS_MAX_POLICY_STAT];
1269 
1270 /* Timestamp counter for last updated. */
1271 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
1272 static unsigned int ccs_stat_modified[CCS_MAX_POLICY_STAT];
1273 #else
1274 static time64_t ccs_stat_modified[CCS_MAX_POLICY_STAT];
1275 #endif
1276 
1277 /* Operations for /proc/ccs/self_domain interface. */
1278 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
1279 static const struct proc_ops ccs_self_operations = {
1280 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
1281         .proc_write = ccs_write_self,
1282 #endif
1283         .proc_read  = ccs_read_self,
1284 };
1285 #else
1286 static
1287 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
1288 const
1289 #endif
1290 struct file_operations ccs_self_operations = {
1291 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
1292         .write = ccs_write_self,
1293 #endif
1294         .read  = ccs_read_self,
1295 };
1296 #endif
1297 
1298 /* Operations for /proc/ccs/ interface. */
1299 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
1300 static const struct proc_ops ccs_operations = {
1301         .proc_open    = ccs_open,
1302         .proc_release = ccs_release,
1303         .proc_poll    = ccs_poll,
1304         .proc_read    = ccs_read,
1305         .proc_write   = ccs_write,
1306 };
1307 #else
1308 static
1309 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
1310 const
1311 #endif
1312 struct file_operations ccs_operations = {
1313         .open    = ccs_open,
1314         .release = ccs_release,
1315         .poll    = ccs_poll,
1316         .read    = ccs_read,
1317         .write   = ccs_write,
1318 };
1319 #endif
1320 
1321 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
1322 
1323 /* The inode operations for /proc/ccs/ directory. */
1324 static struct inode_operations ccs_dir_inode_operations;
1325 
1326 /* The inode operations for files under /proc/ccs/ directory. */
1327 static struct inode_operations ccs_file_inode_operations;
1328 
1329 #endif
1330 
1331 /***** SECTION6: Dependent functions section *****/
1332 
1333 /**
1334  * list_for_each_cookie - iterate over a list with cookie.
1335  *
1336  * @pos:  Pointer to "struct list_head".
1337  * @head: Pointer to "struct list_head".
1338  */
1339 #define list_for_each_cookie(pos, head)                                 \
1340         for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \
1341              pos != (head); pos = srcu_dereference(pos->next, &ccs_ss))
1342 
1343 /**
1344  * ccs_read_token - Read a word from a line.
1345  *
1346  * @param: Pointer to "struct ccs_acl_param".
1347  *
1348  * Returns a word on success, "" otherwise.
1349  *
1350  * To allow the caller to skip NULL check, this function returns "" rather than
1351  * NULL if there is no more words to read.
1352  */
1353 static char *ccs_read_token(struct ccs_acl_param *param)
1354 {
1355         char *pos = param->data;
1356         char *del = strchr(pos, ' ');
1357         if (del)
1358                 *del++ = '\0';
1359         else
1360                 del = pos + strlen(pos);
1361         param->data = del;
1362         return pos;
1363 }
1364 
1365 /**
1366  * ccs_make_byte - Make byte value from three octal characters.
1367  *
1368  * @c1: The first character.
1369  * @c2: The second character.
1370  * @c3: The third character.
1371  *
1372  * Returns byte value.
1373  */
1374 static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3)
1375 {
1376         return ((c1 - '') << 6) + ((c2 - '') << 3) + (c3 - '');
1377 }
1378 
1379 /**
1380  * ccs_correct_word2 - Check whether the given string follows the naming rules.
1381  *
1382  * @string: The byte sequence to check. Not '\0'-terminated.
1383  * @len:    Length of @string.
1384  *
1385  * Returns true if @string follows the naming rules, false otherwise.
1386  */
1387 static bool ccs_correct_word2(const char *string, size_t len)
1388 {
1389         u8 recursion = 20;
1390         const char *const start = string;
1391         bool in_repetition = false;
1392         if (!len)
1393                 goto out;
1394         while (len--) {
1395                 unsigned char c = *string++;
1396                 if (c == '\\') {
1397                         if (!len--)
1398                                 goto out;
1399                         c = *string++;
1400                         if (c >= '' && c <= '3') {
1401                                 unsigned char d;
1402                                 unsigned char e;
1403                                 if (!len-- || !len--)
1404                                         goto out;
1405                                 d = *string++;
1406                                 e = *string++;
1407                                 if (d < '' || d > '7' || e < '' || e > '7')
1408                                         goto out;
1409                                 c = ccs_make_byte(c, d, e);
1410                                 if (c <= ' ' || c >= 127)
1411                                         continue;
1412                                 goto out;
1413                         }
1414                         switch (c) {
1415                         case '\\':  /* "\\" */
1416                         case '+':   /* "\+" */
1417                         case '?':   /* "\?" */
1418                         case 'x':   /* "\x" */
1419                         case 'a':   /* "\a" */
1420                         case '-':   /* "\-" */
1421                                 continue;
1422                         }
1423                         if (!recursion--)
1424                                 goto out;
1425                         switch (c) {
1426                         case '*':   /* "\*" */
1427                         case '@':   /* "\@" */
1428                         case '$':   /* "\$" */
1429                         case 'X':   /* "\X" */
1430                         case 'A':   /* "\A" */
1431                                 continue;
1432                         case '{':   /* "/\{" */
1433                                 if (string - 3 < start || *(string - 3) != '/')
1434                                         goto out;
1435                                 in_repetition = true;
1436                                 continue;
1437                         case '}':   /* "\}/" */
1438                                 if (*string != '/')
1439                                         goto out;
1440                                 if (!in_repetition)
1441                                         goto out;
1442                                 in_repetition = false;
1443                                 continue;
1444                         }
1445                         goto out;
1446                 } else if (in_repetition && c == '/') {
1447                         goto out;
1448                 } else if (c <= ' ' || c >= 127) {
1449                         goto out;
1450                 }
1451         }
1452         if (in_repetition)
1453                 goto out;
1454         return true;
1455 out:
1456         return false;
1457 }
1458 
1459 /**
1460  * ccs_correct_word - Check whether the given string follows the naming rules.
1461  *
1462  * @string: The string to check.
1463  *
1464  * Returns true if @string follows the naming rules, false otherwise.
1465  */
1466 static bool ccs_correct_word(const char *string)
1467 {
1468         return ccs_correct_word2(string, strlen(string));
1469 }
1470 
1471 /**
1472  * ccs_get_group - Allocate memory for "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group".
1473  *
1474  * @param: Pointer to "struct ccs_acl_param".
1475  * @idx:   Index number.
1476  *
1477  * Returns pointer to "struct ccs_group" on success, NULL otherwise.
1478  */
1479 static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
1480                                        const u8 idx)
1481 {
1482         struct ccs_group e = { };
1483         struct ccs_group *group = NULL;
1484         struct list_head *list;
1485         const char *group_name = ccs_read_token(param);
1486         bool found = false;
1487         if (!ccs_correct_word(group_name) || idx >= CCS_MAX_GROUP)
1488                 return NULL;
1489         e.group_name = ccs_get_name(group_name);
1490         if (!e.group_name)
1491                 return NULL;
1492         if (mutex_lock_interruptible(&ccs_policy_lock))
1493                 goto out;
1494         list = &param->ns->group_list[idx];
1495         list_for_each_entry(group, list, head.list) {
1496                 if (e.group_name != group->group_name ||
1497                     atomic_read(&group->head.users) == CCS_GC_IN_PROGRESS)
1498                         continue;
1499                 atomic_inc(&group->head.users);
1500                 found = true;
1501                 break;
1502         }
1503         if (!found) {
1504                 struct ccs_group *entry = ccs_commit_ok(&e, sizeof(e));
1505                 if (entry) {
1506                         INIT_LIST_HEAD(&entry->member_list);
1507                         atomic_set(&entry->head.users, 1);
1508                         list_add_tail_rcu(&entry->head.list, list);
1509                         group = entry;
1510                         found = true;
1511                 }
1512         }
1513         mutex_unlock(&ccs_policy_lock);
1514 out:
1515         ccs_put_name(e.group_name);
1516         return found ? group : NULL;
1517 }
1518 
1519 /**
1520  * ccs_parse_name_union - Parse a ccs_name_union.
1521  *
1522  * @param: Pointer to "struct ccs_acl_param".
1523  * @ptr:   Pointer to "struct ccs_name_union".
1524  *
1525  * Returns true on success, false otherwise.
1526  */
1527 static bool ccs_parse_name_union(struct ccs_acl_param *param,
1528                                  struct ccs_name_union *ptr)
1529 {
1530         char *filename;
1531         if (param->data[0] == '@') {
1532                 param->data++;
1533                 ptr->group = ccs_get_group(param, CCS_PATH_GROUP);
1534                 return ptr->group != NULL;
1535         }
1536         filename = ccs_read_token(param);
1537         if (!ccs_correct_word(filename))
1538                 return false;
1539         ptr->filename = ccs_get_name(filename);
1540         return ptr->filename != NULL;
1541 }
1542 
1543 /**
1544  * ccs_parse_ulong - Parse an "unsigned long" value.
1545  *
1546  * @result: Pointer to "unsigned long".
1547  * @str:    Pointer to string to parse.
1548  *
1549  * Returns one of values in "enum ccs_value_type".
1550  *
1551  * The @src is updated to point the first character after the value
1552  * on success.
1553  */
1554 static u8 ccs_parse_ulong(unsigned long *result, char **str)
1555 {
1556         const char *cp = *str;
1557         char *ep;
1558         int base = 10;
1559         if (*cp == '') {
1560                 char c = *(cp + 1);
1561                 if (c == 'x' || c == 'X') {
1562                         base = 16;
1563                         cp += 2;
1564                 } else if (c >= '' && c <= '7') {
1565                         base = 8;
1566                         cp++;
1567                 }
1568         }
1569         *result = simple_strtoul(cp, &ep, base);
1570         if (cp == ep)
1571                 return CCS_VALUE_TYPE_INVALID;
1572         *str = ep;
1573         switch (base) {
1574         case 16:
1575                 return CCS_VALUE_TYPE_HEXADECIMAL;
1576         case 8:
1577                 return CCS_VALUE_TYPE_OCTAL;
1578         default:
1579                 return CCS_VALUE_TYPE_DECIMAL;
1580         }
1581 }
1582 
1583 /**
1584  * ccs_parse_number_union - Parse a ccs_number_union.
1585  *
1586  * @param: Pointer to "struct ccs_acl_param".
1587  * @ptr:   Pointer to "struct ccs_number_union".
1588  *
1589  * Returns true on success, false otherwise.
1590  */
1591 static bool ccs_parse_number_union(struct ccs_acl_param *param,
1592                                    struct ccs_number_union *ptr)
1593 {
1594         char *data;
1595         u8 type;
1596         unsigned long v;
1597         memset(ptr, 0, sizeof(*ptr));
1598         if (param->data[0] == '@') {
1599                 param->data++;
1600                 ptr->group = ccs_get_group(param, CCS_NUMBER_GROUP);
1601                 return ptr->group != NULL;
1602         }
1603         data = ccs_read_token(param);
1604         type = ccs_parse_ulong(&v, &data);
1605         if (type == CCS_VALUE_TYPE_INVALID)
1606                 return false;
1607         ptr->values[0] = v;
1608         ptr->value_type[0] = type;
1609         if (!*data) {
1610                 ptr->values[1] = v;
1611                 ptr->value_type[1] = type;
1612                 return true;
1613         }
1614         if (*data++ != '-')
1615                 return false;
1616         type = ccs_parse_ulong(&v, &data);
1617         if (type == CCS_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
1618                 return false;
1619         ptr->values[1] = v;
1620         ptr->value_type[1] = type;
1621         return true;
1622 }
1623 
1624 #ifdef CONFIG_CCSECURITY_NETWORK
1625 
1626 /**
1627  * ccs_parse_ipaddr_union - Parse an IP address.
1628  *
1629  * @param: Pointer to "struct ccs_acl_param".
1630  * @ptr:   Pointer to "struct ccs_ipaddr_union".
1631  *
1632  * Returns true on success, false otherwise.
1633  */
1634 static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
1635                                    struct ccs_ipaddr_union *ptr)
1636 {
1637         u8 * const min = ptr->ip[0].in6_u.u6_addr8;
1638         u8 * const max = ptr->ip[1].in6_u.u6_addr8;
1639         char *address = ccs_read_token(param);
1640         const char *end;
1641         if (!strchr(address, ':') &&
1642             ccs_in4_pton(address, -1, min, '-', &end) > 0) {
1643                 ptr->is_ipv6 = false;
1644                 if (!*end)
1645                         ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
1646                 else if (*end++ != '-' ||
1647                          ccs_in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
1648                         return false;
1649                 return true;
1650         }
1651         if (ccs_in6_pton(address, -1, min, '-', &end) > 0) {
1652                 ptr->is_ipv6 = true;
1653                 if (!*end)
1654                         memmove(max, min, sizeof(u16) * 8);
1655                 else if (*end++ != '-' ||
1656                          ccs_in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
1657                         return false;
1658                 return true;
1659         }
1660         return false;
1661 }
1662 
1663 #endif
1664 
1665 /**
1666  * ccs_get_dqword - ccs_get_name() for a quoted string.
1667  *
1668  * @start: String to save.
1669  *
1670  * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
1671  */
1672 static const struct ccs_path_info *ccs_get_dqword(char *start)
1673 {
1674         char *cp = start + strlen(start) - 1;
1675         if (cp == start || *start++ != '"' || *cp != '"')
1676                 return NULL;
1677         *cp = '\0';
1678         if (*start && !ccs_correct_word(start))
1679                 return NULL;
1680         return ccs_get_name(start);
1681 }
1682 
1683 /**
1684  * ccs_parse_name_union_quoted - Parse a quoted word.
1685  *
1686  * @param: Pointer to "struct ccs_acl_param".
1687  * @ptr:   Pointer to "struct ccs_name_union".
1688  *
1689  * Returns true on success, false otherwise.
1690  */
1691 static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param,
1692                                         struct ccs_name_union *ptr)
1693 {
1694         char *filename = param->data;
1695         if (*filename == '@')
1696                 return ccs_parse_name_union(param, ptr);
1697         ptr->filename = ccs_get_dqword(filename);
1698         return ptr->filename != NULL;
1699 }
1700 
1701 /**
1702  * ccs_parse_argv - Parse an argv[] condition part.
1703  *
1704  * @left:  Lefthand value.
1705  * @right: Righthand value.
1706  * @argv:  Pointer to "struct ccs_argv".
1707  *
1708  * Returns true on success, false otherwise.
1709  */
1710 static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv)
1711 {
1712         if (ccs_parse_ulong(&argv->index, &left) != CCS_VALUE_TYPE_DECIMAL ||
1713             *left++ != ']' || *left)
1714                 return false;
1715         argv->value = ccs_get_dqword(right);
1716         return argv->value != NULL;
1717 }
1718 
1719 /**
1720  * ccs_parse_envp - Parse an envp[] condition part.
1721  *
1722  * @left:  Lefthand value.
1723  * @right: Righthand value.
1724  * @envp:  Pointer to "struct ccs_envp".
1725  *
1726  * Returns true on success, false otherwise.
1727  */
1728 static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp)
1729 {
1730         const struct ccs_path_info *name;
1731         const struct ccs_path_info *value;
1732         char *cp = left + strlen(left) - 1;
1733         if (*cp-- != ']' || *cp != '"')
1734                 goto out;
1735         *cp = '\0';
1736         if (!ccs_correct_word(left))
1737                 goto out;
1738         name = ccs_get_name(left);
1739         if (!name)
1740                 goto out;
1741         if (!strcmp(right, "NULL")) {
1742                 value = NULL;
1743         } else {
1744                 value = ccs_get_dqword(right);
1745                 if (!value) {
1746                         ccs_put_name(name);
1747                         goto out;
1748                 }
1749         }
1750         envp->name = name;
1751         envp->value = value;
1752         return true;
1753 out:
1754         return false;
1755 }
1756 
1757 /**
1758  * ccs_same_condition - Check for duplicated "struct ccs_condition" entry.
1759  *
1760  * @a: Pointer to "struct ccs_condition".
1761  * @b: Pointer to "struct ccs_condition".
1762  *
1763  * Returns true if @a == @b, false otherwise.
1764  */
1765 static bool ccs_same_condition(const struct ccs_condition *a,
1766                                const struct ccs_condition *b)
1767 {
1768         return a->size == b->size && a->condc == b->condc &&
1769                 a->numbers_count == b->numbers_count &&
1770                 a->names_count == b->names_count &&
1771                 a->argc == b->argc && a->envc == b->envc &&
1772                 a->grant_log == b->grant_log &&
1773                 a->exec_transit == b->exec_transit && a->transit == b->transit
1774                 && !memcmp(a + 1, b + 1, a->size - sizeof(*a));
1775 }
1776 
1777 /**
1778  * ccs_condition_type - Get condition type.
1779  *
1780  * @word: Keyword string.
1781  *
1782  * Returns one of values in "enum ccs_conditions_index" on success,
1783  * CCS_MAX_CONDITION_KEYWORD otherwise.
1784  */
1785 static u8 ccs_condition_type(const char *word)
1786 {
1787         u8 i;
1788         for (i = 0; i < CCS_MAX_CONDITION_KEYWORD; i++) {
1789                 if (!strcmp(word, ccs_condition_keyword[i]))
1790                         break;
1791         }
1792         return i;
1793 }
1794 
1795 /**
1796  * ccs_commit_condition - Commit "struct ccs_condition".
1797  *
1798  * @entry: Pointer to "struct ccs_condition".
1799  *
1800  * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
1801  *
1802  * This function merges duplicated entries. This function returns NULL if
1803  * @entry is not duplicated but memory quota for policy has exceeded.
1804  */
1805 static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry)
1806 {
1807         struct ccs_condition *ptr;
1808         bool found = false;
1809         if (mutex_lock_interruptible(&ccs_policy_lock)) {
1810                 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
1811                 ptr = NULL;
1812                 found = true;
1813                 goto out;
1814         }
1815         list_for_each_entry(ptr, &ccs_condition_list, head.list) {
1816                 if (!ccs_same_condition(ptr, entry) ||
1817                     atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS)
1818                         continue;
1819                 /* Same entry found. Share this entry. */
1820                 atomic_inc(&ptr->head.users);
1821                 found = true;
1822                 break;
1823         }
1824         if (!found) {
1825                 if (ccs_memory_ok(entry, entry->size)) {
1826                         atomic_set(&entry->head.users, 1);
1827                         list_add(&entry->head.list, &ccs_condition_list);
1828                 } else {
1829                         found = true;
1830                         ptr = NULL;
1831                 }
1832         }
1833         mutex_unlock(&ccs_policy_lock);
1834 out:
1835         if (found) {
1836                 ccs_del_condition(&entry->head.list);
1837                 kfree(entry);
1838                 entry = ptr;
1839         }
1840         return entry;
1841 }
1842 
1843 /**
1844  * ccs_correct_path - Check whether the given pathname follows the naming rules.
1845  *
1846  * @filename: The pathname to check.
1847  *
1848  * Returns true if @filename follows the naming rules, false otherwise.
1849  */
1850 static bool ccs_correct_path(const char *filename)
1851 {
1852         return *filename == '/' && ccs_correct_word(filename);
1853 }
1854 
1855 /**
1856  * ccs_domain_def - Check whether the given token can be a domainname.
1857  *
1858  * @buffer: The token to check.
1859  *
1860  * Returns true if @buffer possibly be a domainname, false otherwise.
1861  */
1862 static bool ccs_domain_def(const unsigned char *buffer)
1863 {
1864         const unsigned char *cp;
1865         int len;
1866         if (*buffer != '<')
1867                 return false;
1868         cp = strchr(buffer, ' ');
1869         if (!cp)
1870                 len = strlen(buffer);
1871         else
1872                 len = cp - buffer;
1873         if (buffer[len - 1] != '>' || !ccs_correct_word2(buffer + 1, len - 2))
1874                 return false;
1875         return true;
1876 }
1877 
1878 /**
1879  * ccs_correct_domain - Check whether the given domainname follows the naming rules.
1880  *
1881  * @domainname: The domainname to check.
1882  *
1883  * Returns true if @domainname follows the naming rules, false otherwise.
1884  */
1885 static bool ccs_correct_domain(const unsigned char *domainname)
1886 {
1887         if (!domainname || !ccs_domain_def(domainname))
1888                 return false;
1889         domainname = strchr(domainname, ' ');
1890         if (!domainname++)
1891                 return true;
1892         while (1) {
1893                 const unsigned char *cp = strchr(domainname, ' ');
1894                 if (!cp)
1895                         break;
1896                 if (*domainname != '/' ||
1897                     !ccs_correct_word2(domainname, cp - domainname))
1898                         return false;
1899                 domainname = cp + 1;
1900         }
1901         return ccs_correct_path(domainname);
1902 }
1903 
1904 /**
1905  * ccs_normalize_line - Format string.
1906  *
1907  * @buffer: The line to normalize.
1908  *
1909  * Returns nothing.
1910  *
1911  * Leading and trailing whitespaces are removed.
1912  * Multiple whitespaces are packed into single space.
1913  */
1914 static void ccs_normalize_line(unsigned char *buffer)
1915 {
1916         unsigned char *sp = buffer;
1917         unsigned char *dp = buffer;
1918         bool first = true;
1919         while (*sp && (*sp <= ' ' || *sp >= 127))
1920                 sp++;
1921         while (*sp) {
1922                 if (!first)
1923                         *dp++ = ' ';
1924                 first = false;
1925                 while (*sp > ' ' && *sp < 127)
1926                         *dp++ = *sp++;
1927                 while (*sp && (*sp <= ' ' || *sp >= 127))
1928                         sp++;
1929         }
1930         *dp = '\0';
1931 }
1932 
1933 /**
1934  * ccs_get_domainname - Read a domainname from a line.
1935  *
1936  * @param: Pointer to "struct ccs_acl_param".
1937  *
1938  * Returns a domainname on success, NULL otherwise.
1939  */
1940 static const struct ccs_path_info *ccs_get_domainname
1941 (struct ccs_acl_param *param)
1942 {
1943         char *start = param->data;
1944         char *pos = start;
1945         while (*pos) {
1946                 if (*pos++ != ' ' || *pos++ == '/')
1947                         continue;
1948                 pos -= 2;
1949                 *pos++ = '\0';
1950                 break;
1951         }
1952         param->data = pos;
1953         if (ccs_correct_domain(start))
1954                 return ccs_get_name(start);
1955         return NULL;
1956 }
1957 
1958 /**
1959  * ccs_get_transit_preference - Parse domain transition preference for execve().
1960  *
1961  * @param: Pointer to "struct ccs_acl_param".
1962  * @e:     Pointer to "struct ccs_condition".
1963  *
1964  * Returns the condition string part.
1965  */
1966 static char *ccs_get_transit_preference(struct ccs_acl_param *param,
1967                                         struct ccs_condition *e)
1968 {
1969         char * const pos = param->data;
1970         bool flag;
1971         if (*pos == '<') {
1972                 e->transit = ccs_get_domainname(param);
1973                 goto done;
1974         }
1975         {
1976                 char *cp = strchr(pos, ' ');
1977                 if (cp)
1978                         *cp = '\0';
1979                 flag = ccs_correct_path(pos) || !strcmp(pos, "keep") ||
1980                         !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
1981                         !strcmp(pos, "child") || !strcmp(pos, "parent");
1982                 if (cp)
1983                         *cp = ' ';
1984         }
1985         if (!flag)
1986                 return pos;
1987         e->transit = ccs_get_name(ccs_read_token(param));
1988 done:
1989         if (e->transit) {
1990                 e->exec_transit = true;
1991                 return param->data;
1992         }
1993         /*
1994          * Return a bad read-only condition string that will let
1995          * ccs_get_condition() return NULL.
1996          */
1997         return "/";
1998 }
1999 
2000 /**
2001  * ccs_get_condition - Parse condition part.
2002  *
2003  * @param: Pointer to "struct ccs_acl_param".
2004  *
2005  * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
2006  */
2007 static struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param)
2008 {
2009         struct ccs_condition *entry = NULL;
2010         struct ccs_condition_element *condp = NULL;
2011         struct ccs_number_union *numbers_p = NULL;
2012         struct ccs_name_union *names_p = NULL;
2013         struct ccs_argv *argv = NULL;
2014         struct ccs_envp *envp = NULL;
2015         struct ccs_condition e = { };
2016         char * const start_of_string = ccs_get_transit_preference(param, &e);
2017         char * const end_of_string = start_of_string + strlen(start_of_string);
2018         char *pos;
2019 rerun:
2020         pos = start_of_string;
2021         while (1) {
2022                 u8 left = -1;
2023                 u8 right = -1;
2024                 char *left_word = pos;
2025                 char *cp;
2026                 char *right_word;
2027                 bool is_not;
2028                 if (!*left_word)
2029                         break;
2030                 /*
2031                  * Since left-hand condition does not allow use of "path_group"
2032                  * or "number_group" and environment variable's names do not
2033                  * accept '=', it is guaranteed that the original line consists
2034                  * of one or more repetition of $left$operator$right blocks
2035                  * where "$left is free from '=' and ' '" and "$operator is
2036                  * either '=' or '!='" and "$right is free from ' '".
2037                  * Therefore, we can reconstruct the original line at the end
2038                  * of dry run even if we overwrite $operator with '\0'.
2039                  */
2040                 cp = strchr(pos, ' ');
2041                 if (cp) {
2042                         *cp = '\0'; /* Will restore later. */
2043                         pos = cp + 1;
2044                 } else {
2045                         pos = "";
2046                 }
2047                 right_word = strchr(left_word, '=');
2048                 if (!right_word || right_word == left_word)
2049                         goto out;
2050                 is_not = *(right_word - 1) == '!';
2051                 if (is_not)
2052                         *(right_word++ - 1) = '\0'; /* Will restore later. */
2053                 else if (*(right_word + 1) != '=')
2054                         *right_word++ = '\0'; /* Will restore later. */
2055                 else
2056                         goto out;
2057                 dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
2058                         is_not ? "!" : "", right_word);
2059                 if (!strcmp(left_word, "grant_log")) {
2060                         if (entry) {
2061                                 if (is_not ||
2062                                     entry->grant_log != CCS_GRANTLOG_AUTO)
2063                                         goto out;
2064                                 else if (!strcmp(right_word, "yes"))
2065                                         entry->grant_log = CCS_GRANTLOG_YES;
2066                                 else if (!strcmp(right_word, "no"))
2067                                         entry->grant_log = CCS_GRANTLOG_NO;
2068                                 else
2069                                         goto out;
2070                         }
2071                         continue;
2072                 }
2073                 if (!strcmp(left_word, "auto_domain_transition")) {
2074                         if (entry) {
2075                                 if (is_not || entry->transit)
2076                                         goto out;
2077                                 entry->transit = ccs_get_dqword(right_word);
2078                                 if (!entry->transit ||
2079                                     (entry->transit->name[0] != '/' &&
2080                                      !ccs_domain_def(entry->transit->name)))
2081                                         goto out;
2082                         }
2083                         continue;
2084                 }
2085                 if (!strncmp(left_word, "exec.argv[", 10)) {
2086                         if (!argv) {
2087                                 e.argc++;
2088                                 e.condc++;
2089                         } else {
2090                                 e.argc--;
2091                                 e.condc--;
2092                                 left = CCS_ARGV_ENTRY;
2093                                 argv->is_not = is_not;
2094                                 if (!ccs_parse_argv(left_word + 10,
2095                                                     right_word, argv++))
2096                                         goto out;
2097                         }
2098                         goto store_value;
2099                 }
2100                 if (!strncmp(left_word, "exec.envp[\"", 11)) {
2101                         if (!envp) {
2102                                 e.envc++;
2103                                 e.condc++;
2104                         } else {
2105                                 e.envc--;
2106                                 e.condc--;
2107                                 left = CCS_ENVP_ENTRY;
2108                                 envp->is_not = is_not;
2109                                 if (!ccs_parse_envp(left_word + 11,
2110                                                     right_word, envp++))
2111                                         goto out;
2112                         }
2113                         goto store_value;
2114                 }
2115                 left = ccs_condition_type(left_word);
2116                 dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
2117                         left);
2118                 if (left == CCS_MAX_CONDITION_KEYWORD) {
2119                         if (!numbers_p) {
2120                                 e.numbers_count++;
2121                         } else {
2122                                 e.numbers_count--;
2123                                 left = CCS_NUMBER_UNION;
2124                                 param->data = left_word;
2125                                 if (*left_word == '@' ||
2126                                     !ccs_parse_number_union(param,
2127                                                             numbers_p++))
2128                                         goto out;
2129                         }
2130                 }
2131                 if (!condp)
2132                         e.condc++;
2133                 else
2134                         e.condc--;
2135                 if (left == CCS_EXEC_REALPATH || left == CCS_SYMLINK_TARGET) {
2136                         if (!names_p) {
2137                                 e.names_count++;
2138                         } else {
2139                                 e.names_count--;
2140                                 right = CCS_NAME_UNION;
2141                                 param->data = right_word;
2142                                 if (!ccs_parse_name_union_quoted(param,
2143                                                                  names_p++))
2144                                         goto out;
2145                         }
2146                         goto store_value;
2147                 }
2148                 right = ccs_condition_type(right_word);
2149                 if (right == CCS_MAX_CONDITION_KEYWORD) {
2150                         if (!numbers_p) {
2151                                 e.numbers_count++;
2152                         } else {
2153                                 e.numbers_count--;
2154                                 right = CCS_NUMBER_UNION;
2155                                 param->data = right_word;
2156                                 if (!ccs_parse_number_union(param,
2157                                                             numbers_p++))
2158                                         goto out;
2159                         }
2160                 }
2161 store_value:
2162                 if (!condp) {
2163                         dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
2164                                 "match=%u\n", __LINE__, left, right, !is_not);
2165                         continue;
2166                 }
2167                 condp->left = left;
2168                 condp->right = right;
2169                 condp->equals = !is_not;
2170                 dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
2171                         __LINE__, condp->left, condp->right,
2172                         condp->equals);
2173                 condp++;
2174         }
2175         dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
2176                 __LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
2177                 e.envc);
2178         if (entry) {
2179                 BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
2180                        e.condc);
2181                 return ccs_commit_condition(entry);
2182         }
2183         e.size = sizeof(*entry)
2184                 + e.condc * sizeof(struct ccs_condition_element)
2185                 + e.numbers_count * sizeof(struct ccs_number_union)
2186                 + e.names_count * sizeof(struct ccs_name_union)
2187                 + e.argc * sizeof(struct ccs_argv)
2188                 + e.envc * sizeof(struct ccs_envp);
2189         entry = kzalloc(e.size, CCS_GFP_FLAGS);
2190         if (!entry)
2191                 goto out2;
2192         *entry = e;
2193         e.transit = NULL;
2194         condp = (struct ccs_condition_element *) (entry + 1);
2195         numbers_p = (struct ccs_number_union *) (condp + e.condc);
2196         names_p = (struct ccs_name_union *) (numbers_p + e.numbers_count);
2197         argv = (struct ccs_argv *) (names_p + e.names_count);
2198         envp = (struct ccs_envp *) (argv + e.argc);
2199         {
2200                 bool flag = false;
2201                 for (pos = start_of_string; pos < end_of_string; pos++) {
2202                         if (*pos)
2203                                 continue;
2204                         if (flag) /* Restore " ". */
2205                                 *pos = ' ';
2206                         else if (*(pos + 1) == '=') /* Restore "!=". */
2207                                 *pos = '!';
2208                         else /* Restore "=". */
2209                                 *pos = '=';
2210                         flag = !flag;
2211                 }
2212         }
2213         goto rerun;
2214 out:
2215         dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
2216         if (entry) {
2217                 ccs_del_condition(&entry->head.list);
2218                 kfree(entry);
2219         }
2220 out2:
2221         ccs_put_name(e.transit);
2222         return NULL;
2223 }
2224 
2225 /**
2226  * ccs_yesno - Return "yes" or "no".
2227  *
2228  * @value: Bool value.
2229  *
2230  * Returns "yes" if @value is not 0, "no" otherwise.
2231  */
2232 static const char *ccs_yesno(const unsigned int value)
2233 {
2234         return value ? "yes" : "no";
2235 }
2236 
2237 /**
2238  * ccs_addprintf - strncat()-like-snprintf().
2239  *
2240  * @buffer: Buffer to write to. Must be '\0'-terminated.
2241  * @len:    Size of @buffer.
2242  * @fmt:    The printf()'s format string, followed by parameters.
2243  *
2244  * Returns nothing.
2245  */
2246 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
2247 {
2248         va_list args;
2249         const int pos = strlen(buffer);
2250         va_start(args, fmt);
2251         vsnprintf(buffer + pos, len - pos - 1, fmt, args);
2252         va_end(args);
2253 }
2254 
2255 /**
2256  * ccs_flush - Flush queued string to userspace's buffer.
2257  *
2258  * @head: Pointer to "struct ccs_io_buffer".
2259  *
2260  * Returns true if all data was flushed, false otherwise.
2261  */
2262 static bool ccs_flush(struct ccs_io_buffer *head)
2263 {
2264         while (head->r.w_pos) {
2265                 const char *w = head->r.w[0];
2266                 size_t len = strlen(w);
2267                 if (len) {
2268                         if (len > head->read_user_buf_avail)
2269                                 len = head->read_user_buf_avail;
2270                         if (!len)
2271                                 return false;
2272                         if (copy_to_user(head->read_user_buf, w, len))
2273                                 return false;
2274                         head->read_user_buf_avail -= len;
2275                         head->read_user_buf += len;
2276                         w += len;
2277                 }
2278                 head->r.w[0] = w;
2279                 if (*w)
2280                         return false;
2281                 /* Add '\0' for audit logs and query. */
2282                 if (head->type == CCS_AUDIT || head->type == CCS_QUERY) {
2283                         if (!head->read_user_buf_avail ||
2284                             copy_to_user(head->read_user_buf, "", 1))
2285                                 return false;
2286                         head->read_user_buf_avail--;
2287                         head->read_user_buf++;
2288                 }
2289                 head->r.w_pos--;
2290                 for (len = 0; len < head->r.w_pos; len++)
2291                         head->r.w[len] = head->r.w[len + 1];
2292         }
2293         head->r.avail = 0;
2294         return true;
2295 }
2296 
2297 /**
2298  * ccs_set_string - Queue string to "struct ccs_io_buffer" structure.
2299  *
2300  * @head:   Pointer to "struct ccs_io_buffer".
2301  * @string: String to print.
2302  *
2303  * Returns nothing.
2304  *
2305  * Note that @string has to be kept valid until @head is kfree()d.
2306  * This means that char[] allocated on stack memory cannot be passed to
2307  * this function. Use ccs_io_printf() for char[] allocated on stack memory.
2308  */
2309 static void ccs_set_string(struct ccs_io_buffer *head, const char *string)
2310 {
2311         if (head->r.w_pos < CCS_MAX_IO_READ_QUEUE) {
2312                 head->r.w[head->r.w_pos++] = string;
2313                 ccs_flush(head);
2314         } else
2315                 printk(KERN_WARNING "Too many words in a line.\n");
2316 }
2317 
2318 /**
2319  * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
2320  *
2321  * @head: Pointer to "struct ccs_io_buffer".
2322  * @fmt:  The printf()'s format string, followed by parameters.
2323  *
2324  * Returns nothing.
2325  */
2326 static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
2327 {
2328         va_list args;
2329         size_t len;
2330         size_t pos = head->r.avail;
2331         int size = head->readbuf_size - pos;
2332         if (size <= 0)
2333                 return;
2334         va_start(args, fmt);
2335         len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1;
2336         va_end(args);
2337         if (pos + len >= head->readbuf_size) {
2338                 printk(KERN_WARNING "Too many words in a line.\n");
2339                 return;
2340         }
2341         head->r.avail += len;
2342         ccs_set_string(head, head->read_buf + pos);
2343 }
2344 
2345 /**
2346  * ccs_set_space - Put a space to "struct ccs_io_buffer" structure.
2347  *
2348  * @head: Pointer to "struct ccs_io_buffer".
2349  *
2350  * Returns nothing.
2351  */
2352 static void ccs_set_space(struct ccs_io_buffer *head)
2353 {
2354         ccs_set_string(head, " ");
2355 }
2356 
2357 /**
2358  * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure.
2359  *
2360  * @head: Pointer to "struct ccs_io_buffer".
2361  *
2362  * Returns true if all data was flushed, false otherwise.
2363  */
2364 static bool ccs_set_lf(struct ccs_io_buffer *head)
2365 {
2366         ccs_set_string(head, "\n");
2367         return !head->r.w_pos;
2368 }
2369 
2370 /**
2371  * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure.
2372  *
2373  * @head: Pointer to "struct ccs_io_buffer".
2374  *
2375  * Returns nothing.
2376  */
2377 static void ccs_set_slash(struct ccs_io_buffer *head)
2378 {
2379         ccs_set_string(head, "/");
2380 }
2381 
2382 /**
2383  * ccs_init_policy_namespace - Initialize namespace.
2384  *
2385  * @ns: Pointer to "struct ccs_policy_namespace".
2386  *
2387  * Returns nothing.
2388  */
2389 static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns)
2390 {
2391         unsigned int idx;
2392         for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++)
2393                 INIT_LIST_HEAD(&ns->acl_group[idx]);
2394         for (idx = 0; idx < CCS_MAX_GROUP; idx++)
2395                 INIT_LIST_HEAD(&ns->group_list[idx]);
2396         for (idx = 0; idx < CCS_MAX_POLICY; idx++)
2397                 INIT_LIST_HEAD(&ns->policy_list[idx]);
2398         ns->profile_version = 20150505;
2399         ccs_namespace_enabled = !list_empty(&ccs_namespace_list);
2400         list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list);
2401 }
2402 
2403 /**
2404  * ccs_print_namespace - Print namespace header.
2405  *
2406  * @head: Pointer to "struct ccs_io_buffer".
2407  *
2408  * Returns nothing.
2409  */
2410 static void ccs_print_namespace(struct ccs_io_buffer *head)
2411 {
2412         if (!ccs_namespace_enabled)
2413                 return;
2414         ccs_set_string(head,
2415                        container_of(head->r.ns, struct ccs_policy_namespace,
2416                                     namespace_list)->name);
2417         ccs_set_space(head);
2418 }
2419 
2420 /**
2421  * ccs_assign_profile - Create a new profile.
2422  *
2423  * @ns:      Pointer to "struct ccs_policy_namespace".
2424  * @profile: Profile number to create.
2425  *
2426  * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
2427  */
2428 static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
2429                                               const unsigned int profile)
2430 {
2431         struct ccs_profile *ptr;
2432         struct ccs_profile *entry;
2433         if (profile >= CCS_MAX_PROFILES)
2434                 return NULL;
2435         ptr = ns->profile_ptr[profile];
2436         if (ptr)
2437                 return ptr;
2438         entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
2439         if (mutex_lock_interruptible(&ccs_policy_lock))
2440                 goto out;
2441         ptr = ns->profile_ptr[profile];
2442         if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
2443                 ptr = entry;
2444                 ptr->default_config = CCS_CONFIG_DISABLED |
2445                         CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
2446                 memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
2447                        sizeof(ptr->config));
2448                 ptr->pref[CCS_PREF_MAX_AUDIT_LOG] =
2449                         CONFIG_CCSECURITY_MAX_AUDIT_LOG;
2450                 ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
2451                         CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
2452                 mb(); /* Avoid out-of-order execution. */
2453                 ns->profile_ptr[profile] = ptr;
2454                 entry = NULL;
2455         }
2456         mutex_unlock(&ccs_policy_lock);
2457 out:
2458         kfree(entry);
2459         return ptr;
2460 }
2461 
2462 /**
2463  * ccs_check_profile - Check all profiles currently assigned to domains are defined.
2464  *
2465  * Returns nothing.
2466  */
2467 static void ccs_check_profile(void)
2468 {
2469         struct ccs_domain_info *domain;
2470         const int idx = ccs_read_lock();
2471         ccs_policy_loaded = true;
2472         printk(KERN_INFO "CCSecurity: 1.8.6+   2020/04/13\n");
2473         list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
2474                 const u8 profile = domain->profile;
2475                 struct ccs_policy_namespace *ns = domain->ns;
2476                 if (ns->profile_version == 20100903) {
2477                         static bool done;
2478                         if (!done)
2479                                 printk(KERN_INFO "Converting profile version "
2480                                        "from %u to %u.\n", 20100903, 20150505);
2481                         done = true;
2482                         ns->profile_version = 20150505;
2483                 }
2484                 if (ns->profile_version != 20150505)
2485                         printk(KERN_ERR
2486                                "Profile version %u is not supported.\n",
2487                                ns->profile_version);
2488                 else if (!ns->profile_ptr[profile])
2489                         printk(KERN_ERR
2490                                "Profile %u (used by '%s') is not defined.\n",
2491                                profile, domain->domainname->name);
2492                 else
2493                         continue;
2494                 printk(KERN_ERR
2495                        "Userland tools for TOMOYO 1.8 must be installed and "
2496                        "policy must be initialized.\n");
2497                 printk(KERN_ERR "Please see https://tomoyo.osdn.jp/1.8/ "
2498                        "for more information.\n");
2499                 panic("STOP!");
2500         }
2501         ccs_read_unlock(idx);
2502         printk(KERN_INFO "Mandatory Access Control activated.\n");
2503 }
2504 
2505 /**
2506  * ccs_profile - Find a profile.
2507  *
2508  * @profile: Profile number to find.
2509  *
2510  * Returns pointer to "struct ccs_profile".
2511  */
2512 static struct ccs_profile *ccs_profile(const u8 profile)
2513 {
2514         static struct ccs_profile ccs_null_profile;
2515         struct ccs_profile *ptr = ccs_current_namespace()->
2516                 profile_ptr[profile];
2517         if (!ptr)
2518                 ptr = &ccs_null_profile;
2519         return ptr;
2520 }
2521 
2522 /**
2523  * ccs_get_config - Get config for specified profile's specified functionality.
2524  *
2525  * @profile: Profile number.
2526  * @index:   Index number of functionality.
2527  *
2528  * Returns config.
2529  *
2530  * First, check for CONFIG::category::functionality.
2531  * If CONFIG::category::functionality is set to use default, then check
2532  * CONFIG::category. If CONFIG::category is set to use default, then use
2533  * CONFIG. CONFIG cannot be set to use default.
2534  */
2535 u8 ccs_get_config(const u8 profile, const u8 index)
2536 {
2537         u8 config;
2538         const struct ccs_profile *p;
2539         if (!ccs_policy_loaded)
2540                 return CCS_CONFIG_DISABLED;
2541         p = ccs_profile(profile);
2542         config = p->config[index];
2543         if (config == CCS_CONFIG_USE_DEFAULT)
2544                 config = p->config[ccs_index2category[index]
2545                                    + CCS_MAX_MAC_INDEX];
2546         if (config == CCS_CONFIG_USE_DEFAULT)
2547                 config = p->default_config;
2548         return config;
2549 }
2550 
2551 /**
2552  * ccs_find_yesno - Find values for specified keyword.
2553  *
2554  * @string: String to check.
2555  * @find:   Name of keyword.
2556  *
2557  * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
2558  */
2559 static s8 ccs_find_yesno(const char *string, const char *find)
2560 {
2561         const char *cp = strstr(string, find);
2562         if (cp) {
2563                 cp += strlen(find);
2564                 if (!strncmp(cp, "=yes", 4))
2565                         return 1;
2566                 else if (!strncmp(cp, "=no", 3))
2567                         return 0;
2568         }
2569         return -1;
2570 }
2571 
2572 /**
2573  * ccs_set_uint - Set value for specified preference.
2574  *
2575  * @i:      Pointer to "unsigned int".
2576  * @string: String to check.
2577  * @find:   Name of keyword.
2578  *
2579  * Returns nothing.
2580  */
2581 static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
2582 {
2583         const char *cp = strstr(string, find);
2584         if (cp)
2585                 sscanf(cp + strlen(find), "=%u", i);
2586 }
2587 
2588 /**
2589  * ccs_str_starts - Check whether the given string starts with the given keyword.
2590  *
2591  * @src:  Pointer to pointer to the string.
2592  * @find: Pointer to the keyword.
2593  *
2594  * Returns true if @src starts with @find, false otherwise.
2595  *
2596  * The @src is updated to point the first character after the @find
2597  * if @src starts with @find.
2598  */
2599 static bool ccs_str_starts(char **src, const char *find)
2600 {
2601         const int len = strlen(find);
2602         char *tmp = *src;
2603         if (strncmp(tmp, find, len))
2604                 return false;
2605         tmp += len;
2606         *src = tmp;
2607         return true;
2608 }
2609 
2610 /**
2611  * ccs_print_group - Print group's name.
2612  *
2613  * @head:  Pointer to "struct ccs_io_buffer".
2614  * @group: Pointer to "struct ccsgroup". Maybe NULL.
2615  *
2616  * Returns true if @group is not NULL. false otherwise.
2617  */
2618 static bool ccs_print_group(struct ccs_io_buffer *head,
2619                             const struct ccs_group *group)
2620 {
2621         if (group) {
2622                 ccs_set_string(head, "@");
2623                 ccs_set_string(head, group->group_name->name);
2624                 return true;
2625         }
2626         return false;
2627 }
2628 
2629 /**
2630  * ccs_set_mode - Set mode for specified profile.
2631  *
2632  * @name:    Name of functionality.
2633  * @value:   Mode for @name.
2634  * @profile: Pointer to "struct ccs_profile".
2635  *
2636  * Returns 0 on success, negative value otherwise.
2637  */
2638 static int ccs_set_mode(char *name, const char *value,
2639                         struct ccs_profile *profile)
2640 {
2641         u8 i;
2642         u8 config;
2643         if (!strcmp(name, "CONFIG")) {
2644                 i = CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
2645                 config = profile->default_config;
2646         } else if (ccs_str_starts(&name, "CONFIG::")) {
2647                 config = 0;
2648                 for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
2649                      i++) {
2650                         int len = 0;
2651                         if (i < CCS_MAX_MAC_INDEX) {
2652                                 const u8 c = ccs_index2category[i];
2653                                 const char *category =
2654                                         ccs_category_keywords[c];
2655                                 len = strlen(category);
2656                                 if (strncmp(name, category, len) ||
2657                                     name[len++] != ':' || name[len++] != ':')
2658                                         continue;
2659                         }
2660                         if (strcmp(name + len, ccs_mac_keywords[i]))
2661                                 continue;
2662                         config = profile->config[i];
2663                         break;
2664                 }
2665                 if (i == CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
2666                         return -EINVAL;
2667         } else {
2668                 return -EINVAL;
2669         }
2670         if (strstr(value, "use_default")) {
2671                 config = CCS_CONFIG_USE_DEFAULT;
2672         } else {
2673                 u8 mode;
2674                 for (mode = 0; mode < CCS_CONFIG_MAX_MODE; mode++)
2675                         if (strstr(value, ccs_mode[mode]))
2676                                 /*
2677                                  * Update lower 3 bits in order to distinguish
2678                                  * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
2679                                  */
2680                                 config = (config & ~7) | mode;
2681                 if (config != CCS_CONFIG_USE_DEFAULT) {
2682                         switch (ccs_find_yesno(value, "grant_log")) {
2683                         case 1:
2684                                 config |= CCS_CONFIG_WANT_GRANT_LOG;
2685                                 break;
2686                         case 0:
2687                                 config &= ~CCS_CONFIG_WANT_GRANT_LOG;
2688                                 break;
2689                         }
2690                         switch (ccs_find_yesno(value, "reject_log")) {
2691                         case 1:
2692                                 config |= CCS_CONFIG_WANT_REJECT_LOG;
2693                                 break;
2694                         case 0:
2695                                 config &= ~CCS_CONFIG_WANT_REJECT_LOG;
2696                                 break;
2697                         }
2698                 }
2699         }
2700         if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
2701                 profile->config[i] = config;
2702         else if (config != CCS_CONFIG_USE_DEFAULT)
2703                 profile->default_config = config;
2704         return 0;
2705 }
2706 
2707 /**
2708  * ccs_write_profile - Write profile table.
2709  *
2710  * @head: Pointer to "struct ccs_io_buffer".
2711  *
2712  * Returns 0 on success, negative value otherwise.
2713  */
2714 static int ccs_write_profile(struct ccs_io_buffer *head)
2715 {
2716         char *data = head->write_buf;
2717         unsigned int i;
2718         char *cp;
2719         struct ccs_profile *profile;
2720         if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
2721             == 1)
2722                 return 0;
2723         i = simple_strtoul(data, &cp, 10);
2724         if (*cp != '-')
2725                 return -EINVAL;
2726         data = cp + 1;
2727         profile = ccs_assign_profile(head->w.ns, i);
2728         if (!profile)
2729                 return -EINVAL;
2730         cp = strchr(data, '=');
2731         if (!cp)
2732                 return -EINVAL;
2733         *cp++ = '\0';
2734         if (!strcmp(data, "COMMENT")) {
2735                 static DEFINE_SPINLOCK(lock);
2736                 const struct ccs_path_info *new_comment = ccs_get_name(cp);
2737                 const struct ccs_path_info *old_comment;
2738                 if (!new_comment)
2739                         return -ENOMEM;
2740                 spin_lock(&lock);
2741                 old_comment = profile->comment;
2742                 profile->comment = new_comment;
2743                 spin_unlock(&lock);
2744                 ccs_put_name(old_comment);
2745                 return 0;
2746         }
2747         if (!strcmp(data, "PREFERENCE")) {
2748                 for (i = 0; i < CCS_MAX_PREF; i++)
2749                         ccs_set_uint(&profile->pref[i], cp,
2750                                      ccs_pref_keywords[i]);
2751                 return 0;
2752         }
2753         return ccs_set_mode(data, cp, profile);
2754 }
2755 
2756 /**
2757  * ccs_print_config - Print mode for specified functionality.
2758  *
2759  * @head:   Pointer to "struct ccs_io_buffer".
2760  * @config: Mode for that functionality.
2761  *
2762  * Returns nothing.
2763  *
2764  * Caller prints functionality's name.
2765  */
2766 static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)
2767 {
2768         ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
2769                       ccs_mode[config & 3],
2770                       ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),
2771                       ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));
2772 }
2773 
2774 /**
2775  * ccs_read_profile - Read profile table.
2776  *
2777  * @head: Pointer to "struct ccs_io_buffer".
2778  *
2779  * Returns nothing.
2780  */
2781 static void ccs_read_profile(struct ccs_io_buffer *head)
2782 {
2783         u8 index;
2784         struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2785                                                        namespace_list);
2786         const struct ccs_profile *profile;
2787         if (head->r.eof)
2788                 return;
2789 next:
2790         index = head->r.index;
2791         profile = ns->profile_ptr[index];
2792         switch (head->r.step) {
2793         case 0:
2794                 ccs_print_namespace(head);
2795                 ccs_io_printf(head, "PROFILE_VERSION=%u\n",
2796                               ns->profile_version);
2797                 head->r.step++;
2798                 break;
2799         case 1:
2800                 for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++)
2801                         if (ns->profile_ptr[head->r.index])
2802                                 break;
2803                 if (head->r.index == CCS_MAX_PROFILES) {
2804                         head->r.eof = true;
2805                         return;
2806                 }
2807                 head->r.step++;
2808                 break;
2809         case 2:
2810                 {
2811                         u8 i;
2812                         const struct ccs_path_info *comment = profile->comment;
2813                         ccs_print_namespace(head);
2814                         ccs_io_printf(head, "%u-COMMENT=", index);
2815                         ccs_set_string(head, comment ? comment->name : "");
2816                         ccs_set_lf(head);
2817                         ccs_print_namespace(head);
2818                         ccs_io_printf(head, "%u-PREFERENCE={ ", index);
2819                         for (i = 0; i < CCS_MAX_PREF; i++)
2820                                 ccs_io_printf(head, "%s=%u ",
2821                                               ccs_pref_keywords[i],
2822                                               profile->pref[i]);
2823                         ccs_set_string(head, "}\n");
2824                         head->r.step++;
2825                 }
2826                 break;
2827         case 3:
2828                 {
2829                         ccs_print_namespace(head);
2830                         ccs_io_printf(head, "%u-%s", index, "CONFIG");
2831                         ccs_print_config(head, profile->default_config);
2832                         head->r.bit = 0;
2833                         head->r.step++;
2834                 }
2835                 break;
2836         case 4:
2837                 for ( ; head->r.bit < CCS_MAX_MAC_INDEX
2838                               + CCS_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {
2839                         const u8 i = head->r.bit;
2840                         const u8 config = profile->config[i];
2841                         if (config == CCS_CONFIG_USE_DEFAULT)
2842                                 continue;
2843                         ccs_print_namespace(head);
2844                         if (i < CCS_MAX_MAC_INDEX)
2845                                 ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
2846                                               ccs_category_keywords
2847                                               [ccs_index2category[i]],
2848                                               ccs_mac_keywords[i]);
2849                         else
2850                                 ccs_io_printf(head, "%u-CONFIG::%s", index,
2851                                               ccs_mac_keywords[i]);
2852                         ccs_print_config(head, config);
2853                         head->r.bit++;
2854                         break;
2855                 }
2856                 if (head->r.bit == CCS_MAX_MAC_INDEX
2857                     + CCS_MAX_MAC_CATEGORY_INDEX) {
2858                         head->r.index++;
2859                         head->r.step = 1;
2860                 }
2861                 break;
2862         }
2863         if (ccs_flush(head))
2864                 goto next;
2865 }
2866 
2867 /**
2868  * ccs_update_policy - Update an entry for exception policy.
2869  *
2870  * @size:  Size of new entry in bytes.
2871  * @param: Pointer to "struct ccs_acl_param".
2872  *
2873  * Returns 0 on success, negative value otherwise.
2874  *
2875  * Caller holds ccs_read_lock().
2876  */
2877 static int ccs_update_policy(const int size, struct ccs_acl_param *param)
2878 {
2879         struct ccs_acl_head *new_entry = &param->e.acl_head;
2880         int error = param->is_delete ? -ENOENT : -ENOMEM;
2881         struct ccs_acl_head *entry;
2882         struct list_head *list = param->list;
2883         BUG_ON(size < sizeof(*entry));
2884         if (mutex_lock_interruptible(&ccs_policy_lock))
2885                 return -ENOMEM;
2886         list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
2887                 if (entry->is_deleted == CCS_GC_IN_PROGRESS)
2888                         continue;
2889                 if (memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
2890                         continue;
2891                 entry->is_deleted = param->is_delete;
2892                 error = 0;
2893                 break;
2894         }
2895         if (error && !param->is_delete) {
2896                 entry = ccs_commit_ok(new_entry, size);
2897                 if (entry) {
2898                         list_add_tail_rcu(&entry->list, list);
2899                         error = 0;
2900                 }
2901         }
2902         mutex_unlock(&ccs_policy_lock);
2903         return error;
2904 }
2905 
2906 /**
2907  * ccs_update_manager_entry - Add a manager entry.
2908  *
2909  * @manager:   The path to manager or the domainnamme.
2910  * @is_delete: True if it is a delete request.
2911  *
2912  * Returns 0 on success, negative value otherwise.
2913  */
2914 static int ccs_update_manager_entry(const char *manager,
2915                                     const bool is_delete)
2916 {
2917         struct ccs_acl_param param = {
2918                 /* .ns = &ccs_kernel_namespace, */
2919                 .is_delete = is_delete,
2920                 .list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER],
2921         };
2922         struct ccs_manager *e = &param.e.manager;
2923         int error = is_delete ? -ENOENT : -ENOMEM;
2924         /* Forced zero clear for using memcmp() at ccs_update_policy(). */
2925         memset(&param.e, 0, sizeof(param.e));
2926         if (!ccs_correct_domain(manager) && !ccs_correct_word(manager))
2927                 return -EINVAL;
2928         e->manager = ccs_get_name(manager);
2929         if (e->manager) {
2930                 error = ccs_update_policy(sizeof(*e), &param);
2931                 ccs_put_name(e->manager);
2932         }
2933         return error;
2934 }
2935 
2936 /**
2937  * ccs_write_manager - Write manager policy.
2938  *
2939  * @head: Pointer to "struct ccs_io_buffer".
2940  *
2941  * Returns 0 on success, negative value otherwise.
2942  */
2943 static int ccs_write_manager(struct ccs_io_buffer *head)
2944 {
2945         const char *data = head->write_buf;
2946         if (!strcmp(data, "manage_by_non_root")) {
2947                 ccs_manage_by_non_root = !head->w.is_delete;
2948                 return 0;
2949         }
2950         return ccs_update_manager_entry(data, head->w.is_delete);
2951 }
2952 
2953 /**
2954  * ccs_read_manager - Read manager policy.
2955  *
2956  * @head: Pointer to "struct ccs_io_buffer".
2957  *
2958  * Returns nothing.
2959  *
2960  * Caller holds ccs_read_lock().
2961  */
2962 static void ccs_read_manager(struct ccs_io_buffer *head)
2963 {
2964         if (head->r.eof)
2965                 return;
2966         list_for_each_cookie(head->r.acl, &ccs_kernel_namespace.
2967                              policy_list[CCS_ID_MANAGER]) {
2968                 struct ccs_manager *ptr =
2969                         list_entry(head->r.acl, typeof(*ptr), head.list);
2970                 if (ptr->head.is_deleted)
2971                         continue;
2972                 if (!ccs_flush(head))
2973                         return;
2974                 ccs_set_string(head, ptr->manager->name);
2975                 ccs_set_lf(head);
2976         }
2977         head->r.eof = true;
2978 }
2979 
2980 /**
2981  * ccs_manager - Check whether the current process is a policy manager.
2982  *
2983  * Returns true if the current process is permitted to modify policy
2984  * via /proc/ccs/ interface.
2985  *
2986  * Caller holds ccs_read_lock().
2987  */
2988 static bool ccs_manager(void)
2989 {
2990         struct ccs_manager *ptr;
2991         struct ccs_path_info exe;
2992         struct ccs_security *task = ccs_current_security();
2993         const struct ccs_path_info *domainname
2994                 = ccs_current_domain()->domainname;
2995         bool found = false;
2996         if (!ccs_policy_loaded)
2997                 return true;
2998         if (task->ccs_flags & CCS_TASK_IS_MANAGER)
2999                 return true;
3000         if (!ccs_manage_by_non_root &&
3001             (!uid_eq(current_uid(), GLOBAL_ROOT_UID) ||
3002              !uid_eq(current_euid(), GLOBAL_ROOT_UID)))
3003                 return false;
3004         exe.name = ccs_get_exe();
3005         if (!exe.name)
3006                 return false;
3007         ccs_fill_path_info(&exe);
3008         list_for_each_entry_srcu(ptr, &ccs_kernel_namespace.
3009                                  policy_list[CCS_ID_MANAGER], head.list,
3010                                  &ccs_ss) {
3011                 if (ptr->head.is_deleted)
3012                         continue;
3013                 if (ccs_pathcmp(domainname, ptr->manager) &&
3014                     ccs_pathcmp(&exe, ptr->manager))
3015                         continue;
3016                 /* Set manager flag. */
3017                 task->ccs_flags |= CCS_TASK_IS_MANAGER;
3018                 found = true;
3019                 break;
3020         }
3021         if (!found) { /* Reduce error messages. */
3022                 static pid_t ccs_last_pid;
3023                 const pid_t pid = current->pid;
3024                 if (ccs_last_pid != pid) {
3025                         printk(KERN_WARNING "%s ( %s ) is not permitted to "
3026                                "update policies.\n", domainname->name,
3027                                exe.name);
3028                         ccs_last_pid = pid;
3029                 }
3030         }
3031         kfree(exe.name);
3032         return found;
3033 }
3034 
3035 /**
3036  * ccs_find_domain - Find a domain by the given name.
3037  *
3038  * @domainname: The domainname to find.
3039  *
3040  * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
3041  *
3042  * Caller holds ccs_read_lock().
3043  */
3044 static struct ccs_domain_info *ccs_find_domain(const char *domainname)
3045 {
3046         struct ccs_domain_info *domain;
3047         struct ccs_path_info name;
3048         name.name = domainname;
3049         ccs_fill_path_info(&name);
3050         list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
3051                 if (!domain->is_deleted &&
3052                     !ccs_pathcmp(&name, domain->domainname))
3053                         return domain;
3054         }
3055         return NULL;
3056 }
3057 
3058 /**
3059  * ccs_select_domain - Parse select command.
3060  *
3061  * @head: Pointer to "struct ccs_io_buffer".
3062  * @data: String to parse.
3063  *
3064  * Returns true on success, false otherwise.
3065  *
3066  * Caller holds ccs_read_lock().
3067  */
3068 static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data)
3069 {
3070         unsigned int pid;
3071         struct ccs_domain_info *domain = NULL;
3072         bool global_pid = false;
3073         if (strncmp(data, "select ", 7))
3074                 return false;
3075         data += 7;
3076         if (sscanf(data, "pid=%u", &pid) == 1 ||
3077             (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
3078                 struct task_struct *p;
3079                 ccs_tasklist_lock();
3080 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
3081                 if (global_pid)
3082                         p = ccsecurity_exports.find_task_by_pid_ns(pid,
3083                                                                &init_pid_ns);
3084                 else
3085                         p = ccsecurity_exports.find_task_by_vpid(pid);
3086 #else
3087                 p = find_task_by_pid(pid);
3088 #endif
3089                 if (p)
3090                         domain = ccs_task_domain(p);
3091                 ccs_tasklist_unlock();
3092         } else if (!strncmp(data, "domain=", 7)) {
3093                 if (*(data + 7) == '<')
3094                         domain = ccs_find_domain(data + 7);
3095         } else if (sscanf(data, "Q=%u", &pid) == 1) {
3096                 domain = ccs_find_domain_by_qid(pid);
3097         } else
3098                 return false;
3099         head->w.domain = domain;
3100         /* Accessing read_buf is safe because head->io_sem is held. */
3101         if (!head->read_buf)
3102                 return true; /* Do nothing if open(O_WRONLY). */
3103         memset(&head->r, 0, sizeof(head->r));
3104         head->r.print_this_domain_only = true;
3105         if (domain)
3106                 head->r.domain = &domain->list;
3107         else
3108                 head->r.eof = true;
3109         ccs_io_printf(head, "# select %s\n", data);
3110         if (domain && domain->is_deleted)
3111                 ccs_set_string(head, "# This is a deleted domain.\n");
3112         return true;
3113 }
3114 
3115 /**
3116  * ccs_update_acl - Update "struct ccs_acl_info" entry.
3117  *
3118  * @size:  Size of new entry in bytes.
3119  * @param: Pointer to "struct ccs_acl_param".
3120  *
3121  * Returns 0 on success, negative value otherwise.
3122  *
3123  * Caller holds ccs_read_lock().
3124  */
3125 static int ccs_update_acl(const int size, struct ccs_acl_param *param)
3126 {
3127         struct ccs_acl_info *new_entry = &param->e.acl_info;
3128         const bool is_delete = param->is_delete;
3129         int error = is_delete ? -ENOENT : -ENOMEM;
3130         struct ccs_acl_info *entry;
3131         struct list_head * const list = param->list;
3132         BUG_ON(size < sizeof(*entry));
3133         if (param->data[0]) {
3134                 new_entry->cond = ccs_get_condition(param);
3135                 if (!new_entry->cond)
3136                         return -EINVAL;
3137                 /*
3138                  * Domain transition preference is allowed for only
3139                  * "file execute"/"task auto_execute_handler"/
3140                  * "task denied_auto_execute_handler" entries.
3141                  */
3142                 if (new_entry->cond->exec_transit &&
3143                     !(new_entry->type == CCS_TYPE_PATH_ACL &&
3144                       new_entry->perm == 1 << CCS_TYPE_EXECUTE)
3145 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3146                     && new_entry->type != CCS_TYPE_AUTO_EXECUTE_HANDLER &&
3147                     new_entry->type != CCS_TYPE_DENIED_EXECUTE_HANDLER
3148 #endif
3149                     )
3150                         return -EINVAL;
3151         }
3152         if (mutex_lock_interruptible(&ccs_policy_lock))
3153                 return -ENOMEM;
3154         list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
3155                 if (entry->is_deleted == CCS_GC_IN_PROGRESS)
3156                         continue;
3157                 if (entry->type != new_entry->type ||
3158                     entry->cond != new_entry->cond ||
3159                     memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
3160                         continue;
3161                 if (is_delete)
3162                         entry->perm &= ~new_entry->perm;
3163                 else
3164                         entry->perm |= new_entry->perm;
3165                 entry->is_deleted = !entry->perm;
3166                 error = 0;
3167                 break;
3168         }
3169         if (error && !is_delete) {
3170                 entry = ccs_commit_ok(new_entry, size);
3171                 if (entry) {
3172                         list_add_tail_rcu(&entry->list, list);
3173                         error = 0;
3174                 }
3175         }
3176         mutex_unlock(&ccs_policy_lock);
3177         return error;
3178 }
3179 
3180 /**
3181  * ccs_permstr - Find permission keywords.
3182  *
3183  * @string: String representation for permissions in foo/bar/buz format.
3184  * @keyword: Keyword to find from @string/
3185  *
3186  * Returns true if @keyword was found in @string, false otherwise.
3187  *
3188  * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
3189  */
3190 static bool ccs_permstr(const char *string, const char *keyword)
3191 {
3192         const char *cp = strstr(string, keyword);
3193         if (cp)
3194                 return cp == string || *(cp - 1) == '/';
3195         return false;
3196 }
3197 
3198 /**
3199  * ccs_write_task - Update task related list.
3200  *
3201  * @param: Pointer to "struct ccs_acl_param".
3202  *
3203  * Returns 0 on success, negative value otherwise.
3204  *
3205  * Caller holds ccs_read_lock().
3206  */
3207 static int ccs_write_task(struct ccs_acl_param *param)
3208 {
3209         int error;
3210         const bool is_auto = ccs_str_starts(&param->data,
3211                                             "auto_domain_transition ");
3212         if (!is_auto && !ccs_str_starts(&param->data,
3213                                         "manual_domain_transition ")) {
3214 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3215                 struct ccs_handler_acl *e = &param->e.handler_acl;
3216                 char *handler;
3217                 if (ccs_str_starts(&param->data, "auto_execute_handler "))
3218                         e->head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER;
3219                 else if (ccs_str_starts(&param->data,
3220                                         "denied_execute_handler "))
3221                         e->head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER;
3222                 else
3223                         return -EINVAL;
3224                 handler = ccs_read_token(param);
3225                 if (!ccs_correct_path(handler))
3226                         return -EINVAL;
3227                 e->handler = ccs_get_name(handler);
3228                 if (!e->handler)
3229                         return -ENOMEM;
3230                 if (e->handler->is_patterned)
3231                         return -EINVAL; /* No patterns allowed. */
3232                 return ccs_update_acl(sizeof(*e), param);
3233 #else
3234                 error = -EINVAL;
3235 #endif
3236         } else {
3237 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
3238                 struct ccs_task_acl *e = &param->e.task_acl;
3239                 e->head.type = is_auto ?
3240                         CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL;
3241                 e->domainname = ccs_get_domainname(param);
3242                 if (!e->domainname)
3243                         return -EINVAL;
3244                 return ccs_update_acl(sizeof(*e), param);
3245 #else
3246                 error = -EINVAL;
3247 #endif
3248         }
3249         return error;
3250 }
3251 
3252 #ifdef CONFIG_CCSECURITY_NETWORK
3253 
3254 /**
3255  * ccs_write_inet_network - Write "struct ccs_inet_acl" list.
3256  *
3257  * @param: Pointer to "struct ccs_acl_param".
3258  *
3259  * Returns 0 on success, negative value otherwise.
3260  *
3261  * Caller holds ccs_read_lock().
3262  */
3263 static int ccs_write_inet_network(struct ccs_acl_param *param)
3264 {
3265         struct ccs_inet_acl *e = &param->e.inet_acl;
3266         u8 type;
3267         const char *protocol = ccs_read_token(param);
3268         const char *operation = ccs_read_token(param);
3269         e->head.type = CCS_TYPE_INET_ACL;
3270         for (type = 0; type < CCS_SOCK_MAX; type++)
3271                 if (!strcmp(protocol, ccs_proto_keyword[type]))
3272                         break;
3273         if (type == CCS_SOCK_MAX)
3274                 return -EINVAL;
3275         e->protocol = type;
3276         e->head.perm = 0;
3277         for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
3278                 if (ccs_permstr(operation, ccs_socket_keyword[type]))
3279                         e->head.perm |= 1 << type;
3280         if (!e->head.perm)
3281                 return -EINVAL;
3282         if (param->data[0] == '@') {
3283                 param->data++;
3284                 e->address.group = ccs_get_group(param, CCS_ADDRESS_GROUP);
3285                 if (!e->address.group)
3286                         return -ENOMEM;
3287         } else {
3288                 if (!ccs_parse_ipaddr_union(param, &e->address))
3289                         return -EINVAL;
3290         }
3291         if (!ccs_parse_number_union(param, &e->port) ||
3292             e->port.values[1] > 65535)
3293                 return -EINVAL;
3294         return ccs_update_acl(sizeof(*e), param);
3295 }
3296 
3297 /**
3298  * ccs_write_unix_network - Write "struct ccs_unix_acl" list.
3299  *
3300  * @param: Pointer to "struct ccs_acl_param".
3301  *
3302  * Returns 0 on success, negative value otherwise.
3303  */
3304 static int ccs_write_unix_network(struct ccs_acl_param *param)
3305 {
3306         struct ccs_unix_acl *e = &param->e.unix_acl;
3307         u8 type;
3308         const char *protocol = ccs_read_token(param);
3309         const char *operation = ccs_read_token(param);
3310         e->head.type = CCS_TYPE_UNIX_ACL;
3311         for (type = 0; type < CCS_SOCK_MAX; type++)
3312                 if (!strcmp(protocol, ccs_proto_keyword[type]))
3313                         break;
3314         if (type == CCS_SOCK_MAX)
3315                 return -EINVAL;
3316         e->protocol = type;
3317         e->head.perm = 0;
3318         for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
3319                 if (ccs_permstr(operation, ccs_socket_keyword[type]))
3320                         e->head.perm |= 1 << type;
3321         if (!e->head.perm)
3322                 return -EINVAL;
3323         if (!ccs_parse_name_union(param, &e->name))
3324                 return -EINVAL;
3325         return ccs_update_acl(sizeof(*e), param);
3326 }
3327 
3328 #endif
3329 
3330 /**
3331  * ccs_write_file - Update file related list.
3332  *
3333  * @param: Pointer to "struct ccs_acl_param".
3334  *
3335  * Returns 0 on success, negative value otherwise.
3336  *
3337  * Caller holds ccs_read_lock().
3338  */
3339 static int ccs_write_file(struct ccs_acl_param *param)
3340 {
3341         u16 perm = 0;
3342         u8 type;
3343         const char *operation = ccs_read_token(param);
3344         for (type = 0; type < CCS_MAX_PATH_OPERATION; type++)
3345                 if (ccs_permstr(operation, ccs_path_keyword[type]))
3346                         perm |= 1 << type;
3347         if (perm) {
3348                 struct ccs_path_acl *e = &param->e.path_acl;
3349                 e->head.type = CCS_TYPE_PATH_ACL;
3350                 e->head.perm = perm;
3351                 if (!ccs_parse_name_union(param, &e->name))
3352                         return -EINVAL;
3353                 return ccs_update_acl(sizeof(*e), param);
3354         }
3355         for (type = 0; type < CCS_MAX_PATH2_OPERATION; type++)
3356                 if (ccs_permstr(operation, ccs_mac_keywords[ccs_pp2mac[type]]))
3357                         perm |= 1 << type;
3358         if (perm) {
3359                 struct ccs_path2_acl *e = &param->e.path2_acl;
3360                 e->head.type = CCS_TYPE_PATH2_ACL;
3361                 e->head.perm = perm;
3362                 if (!ccs_parse_name_union(param, &e->name1) ||
3363                     !ccs_parse_name_union(param, &e->name2))
3364                         return -EINVAL;
3365                 return ccs_update_acl(sizeof(*e), param);
3366         }
3367         for (type = 0; type < CCS_MAX_PATH_NUMBER_OPERATION; type++)
3368                 if (ccs_permstr(operation, ccs_mac_keywords[ccs_pn2mac[type]]))
3369                         perm |= 1 << type;
3370         if (perm) {
3371                 struct ccs_path_number_acl *e = &param->e.path_number_acl;
3372                 e->head.type = CCS_TYPE_PATH_NUMBER_ACL;
3373                 e->head.perm = perm;
3374                 if (!ccs_parse_name_union(param, &e->name) ||
3375                     !ccs_parse_number_union(param, &e->number))
3376                         return -EINVAL;
3377                 return ccs_update_acl(sizeof(*e), param);
3378         }
3379         for (type = 0; type < CCS_MAX_MKDEV_OPERATION; type++)
3380                 if (ccs_permstr(operation,
3381                                 ccs_mac_keywords[ccs_pnnn2mac[type]]))
3382                         perm |= 1 << type;
3383         if (perm) {
3384                 struct ccs_mkdev_acl *e = &param->e.mkdev_acl;
3385                 e->head.type = CCS_TYPE_MKDEV_ACL;
3386                 e->head.perm = perm;
3387                 if (!ccs_parse_name_union(param, &e->name) ||
3388                     !ccs_parse_number_union(param, &e->mode) ||
3389                     !ccs_parse_number_union(param, &e->major) ||
3390                     !ccs_parse_number_union(param, &e->minor))
3391                         return -EINVAL;
3392                 return ccs_update_acl(sizeof(*e), param);
3393         }
3394         if (ccs_permstr(operation, ccs_mac_keywords[CCS_MAC_FILE_MOUNT])) {
3395                 struct ccs_mount_acl *e = &param->e.mount_acl;
3396                 e->head.type = CCS_TYPE_MOUNT_ACL;
3397                 if (!ccs_parse_name_union(param, &e->dev_name) ||
3398                     !ccs_parse_name_union(param, &e->dir_name) ||
3399                     !ccs_parse_name_union(param, &e->fs_type) ||
3400                     !ccs_parse_number_union(param, &e->flags))
3401                         return -EINVAL;
3402                 return ccs_update_acl(sizeof(*e), param);
3403         }
3404         return -EINVAL;
3405 }
3406 
3407 #ifdef CONFIG_CCSECURITY_MISC
3408 
3409 /**
3410  * ccs_write_misc - Update environment variable list.
3411  *
3412  * @param: Pointer to "struct ccs_acl_param".
3413  *
3414  * Returns 0 on success, negative value otherwise.
3415  */
3416 static int ccs_write_misc(struct ccs_acl_param *param)
3417 {
3418         if (ccs_str_starts(&param->data, "env ")) {
3419                 struct ccs_env_acl *e = &param->e.env_acl;
3420                 const char *data = ccs_read_token(param);
3421                 e->head.type = CCS_TYPE_ENV_ACL;
3422                 if (!ccs_correct_word(data) || strchr(data, '='))
3423                         return -EINVAL;
3424                 e->env = ccs_get_name(data);
3425                 if (!e->env)
3426                         return -ENOMEM;
3427                 return ccs_update_acl(sizeof(*e), param);
3428         }
3429         return -EINVAL;
3430 }
3431 
3432 #endif
3433 
3434 #ifdef CONFIG_CCSECURITY_IPC
3435 
3436 /**
3437  * ccs_write_ipc - Update "struct ccs_signal_acl" list.
3438  *
3439  * @param: Pointer to "struct ccs_acl_param".
3440  *
3441  * Returns 0 on success, negative value otherwise.
3442  */
3443 static int ccs_write_ipc(struct ccs_acl_param *param)
3444 {
3445         struct ccs_signal_acl *e = &param->e.signal_acl;
3446         e->head.type = CCS_TYPE_SIGNAL_ACL;
3447         if (!ccs_parse_number_union(param, &e->sig))
3448                 return -EINVAL;
3449         e->domainname = ccs_get_domainname(param);
3450         if (!e->domainname)
3451                 return -EINVAL;
3452         return ccs_update_acl(sizeof(*e), param);
3453 }
3454 
3455 #endif
3456 
3457 #ifdef CONFIG_CCSECURITY_CAPABILITY
3458 
3459 /**
3460  * ccs_write_capability - Write "struct ccs_capability_acl" list.
3461  *
3462  * @param: Pointer to "struct ccs_acl_param".
3463  *
3464  * Returns 0 on success, negative value otherwise.
3465  *
3466  * Caller holds ccs_read_lock().
3467  */
3468 static int ccs_write_capability(struct ccs_acl_param *param)
3469 {
3470         struct ccs_capability_acl *e = &param->e.capability_acl;
3471         const char *operation = ccs_read_token(param);
3472         u8 type;
3473         e->head.type = CCS_TYPE_CAPABILITY_ACL;
3474         for (type = 0; type < CCS_MAX_CAPABILITY_INDEX; type++) {
3475                 if (strcmp(operation, ccs_mac_keywords[ccs_c2mac[type]]))
3476                         continue;
3477                 e->operation = type;
3478                 return ccs_update_acl(sizeof(*e), param);
3479         }
3480         return -EINVAL;
3481 }
3482 
3483 #endif
3484 
3485 /**
3486  * ccs_write_acl - Write "struct ccs_acl_info" list.
3487  *
3488  * @ns:        Pointer to "struct ccs_policy_namespace".
3489  * @list:      Pointer to "struct list_head".
3490  * @data:      Policy to be interpreted.
3491  * @is_delete: True if it is a delete request.
3492  *
3493  * Returns 0 on success, negative value otherwise.
3494  *
3495  * Caller holds ccs_read_lock().
3496  */
3497 static int ccs_write_acl(struct ccs_policy_namespace *ns,
3498                          struct list_head *list, char *data,
3499                          const bool is_delete)
3500 {
3501         struct ccs_acl_param param = {
3502                 .ns = ns,
3503                 .list = list,
3504                 .data = data,
3505                 .is_delete = is_delete,
3506         };
3507         static const struct {
3508                 const char *keyword;
3509                 int (*write) (struct ccs_acl_param *);
3510         } ccs_callback[] = {
3511                 { "file ", ccs_write_file },
3512 #ifdef CONFIG_CCSECURITY_NETWORK
3513                 { "network inet ", ccs_write_inet_network },
3514                 { "network unix ", ccs_write_unix_network },
3515 #endif
3516 #ifdef CONFIG_CCSECURITY_MISC
3517                 { "misc ", ccs_write_misc },
3518 #endif
3519 #ifdef CONFIG_CCSECURITY_CAPABILITY
3520                 { "capability ", ccs_write_capability },
3521 #endif
3522 #ifdef CONFIG_CCSECURITY_IPC
3523                 { "ipc signal ", ccs_write_ipc },
3524 #endif
3525                 { "task ", ccs_write_task },
3526         };
3527         u8 i;
3528         /* Forced zero clear for using memcmp() at ccs_update_acl(). */
3529         memset(&param.e, 0, sizeof(param.e));
3530         param.e.acl_info.perm = 1;
3531         for (i = 0; i < ARRAY_SIZE(ccs_callback); i++) {
3532                 int error;
3533                 if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))
3534                         continue;
3535                 error = ccs_callback[i].write(&param);
3536                 ccs_del_acl(&param.e.acl_info.list);
3537                 return error;
3538         }
3539         return -EINVAL;
3540 }
3541 
3542 /**
3543  * ccs_delete_domain - Delete a domain.
3544  *
3545  * @domainname: The name of domain.
3546  *
3547  * Returns 0.
3548  */
3549 static int ccs_delete_domain(char *domainname)
3550 {
3551         struct ccs_domain_info *domain;
3552         struct ccs_path_info name;
3553         name.name = domainname;
3554         ccs_fill_path_info(&name);
3555         if (mutex_lock_interruptible(&ccs_policy_lock))
3556                 return 0;
3557         /* Is there an active domain? */
3558         list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
3559                 /* Never delete ccs_kernel_domain. */
3560                 if (domain == &ccs_kernel_domain)
3561                         continue;
3562                 if (domain->is_deleted ||
3563                     ccs_pathcmp(domain->domainname, &name))
3564                         continue;
3565                 domain->is_deleted = true;
3566                 break;
3567         }
3568         mutex_unlock(&ccs_policy_lock);
3569         return 0;
3570 }
3571 
3572 /**
3573  * ccs_write_domain - Write domain policy.
3574  *
3575  * @head: Pointer to "struct ccs_io_buffer".
3576  *
3577  * Returns 0 on success, negative value otherwise.
3578  *
3579  * Caller holds ccs_read_lock().
3580  */
3581 static int ccs_write_domain(struct ccs_io_buffer *head)
3582 {
3583         char *data = head->write_buf;
3584         struct ccs_policy_namespace *ns;
3585         struct ccs_domain_info *domain = head->w.domain;
3586         const bool is_delete = head->w.is_delete;
3587         const bool is_select = !is_delete && ccs_str_starts(&data, "select ");
3588         unsigned int idx;
3589         if (*data == '<') {
3590                 domain = NULL;
3591                 if (is_delete)
3592                         ccs_delete_domain(data);
3593                 else if (is_select)
3594                         domain = ccs_find_domain(data);
3595                 else
3596                         domain = ccs_assign_domain(data, false);
3597                 head->w.domain = domain;
3598                 return 0;
3599         }
3600         if (!domain)
3601                 return -EINVAL;
3602         ns = domain->ns;
3603         if (sscanf(data, "use_profile %u\n", &idx) == 1 &&
3604             idx < CCS_MAX_PROFILES) {
3605                 if (!ccs_policy_loaded || ns->profile_ptr[(u8) idx])
3606                         if (!is_delete)
3607                                 domain->profile = (u8) idx;
3608                 return 0;
3609         }
3610         if (sscanf(data, "use_group %u\n", &idx) == 1 &&
3611             idx < CCS_MAX_ACL_GROUPS) {
3612                 if (!is_delete)
3613                         set_bit(idx, domain->group);
3614                 else
3615                         clear_bit(idx, domain->group);
3616                 return 0;
3617         }
3618         for (idx = 0; idx < CCS_MAX_DOMAIN_INFO_FLAGS; idx++) {
3619                 const char *cp = ccs_dif[idx];
3620                 if (strncmp(data, cp, strlen(cp) - 1))
3621                         continue;
3622                 domain->flags[idx] = !is_delete;
3623                 return 0;
3624         }
3625         return ccs_write_acl(ns, &domain->acl_info_list, data, is_delete);
3626 }
3627 
3628 /**
3629  * ccs_print_name_union - Print a ccs_name_union.
3630  *
3631  * @head: Pointer to "struct ccs_io_buffer".
3632  * @ptr:  Pointer to "struct ccs_name_union".
3633  *
3634  * Returns nothing.
3635  */
3636 static void ccs_print_name_union(struct ccs_io_buffer *head,
3637                                  const struct ccs_name_union *ptr)
3638 {
3639         ccs_set_space(head);
3640         if (!ccs_print_group(head, ptr->group))
3641                 ccs_set_string(head, ptr->filename->name);
3642 }
3643 
3644 /**
3645  * ccs_print_name_union_quoted - Print a ccs_name_union with a quote.
3646  *
3647  * @head: Pointer to "struct ccs_io_buffer".
3648  * @ptr:  Pointer to "struct ccs_name_union".
3649  *
3650  * Returns nothing.
3651  */
3652 static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
3653                                         const struct ccs_name_union *ptr)
3654 {
3655         if (!ccs_print_group(head, ptr->group)) {
3656                 ccs_set_string(head, "\"");
3657                 ccs_set_string(head, ptr->filename->name);
3658                 ccs_set_string(head, "\"");
3659         }
3660 }
3661 
3662 /**
3663  * ccs_print_number_union_nospace - Print a ccs_number_union without a space.
3664  *
3665  * @head: Pointer to "struct ccs_io_buffer".
3666  * @ptr:  Pointer to "struct ccs_number_union".
3667  *
3668  * Returns nothing.
3669  */
3670 static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
3671                                            const struct ccs_number_union *ptr)
3672 {
3673         if (!ccs_print_group(head, ptr->group)) {
3674                 int i;
3675                 unsigned long min = ptr->values[0];
3676                 const unsigned long max = ptr->values[1];
3677                 u8 min_type = ptr->value_type[0];
3678                 const u8 max_type = ptr->value_type[1];
3679                 char buffer[128];
3680                 buffer[0] = '\0';
3681                 for (i = 0; i < 2; i++) {
3682                         switch (min_type) {
3683                         case CCS_VALUE_TYPE_HEXADECIMAL:
3684                                 ccs_addprintf(buffer, sizeof(buffer), "0x%lX",
3685                                               min);
3686                                 break;
3687                         case CCS_VALUE_TYPE_OCTAL:
3688                                 ccs_addprintf(buffer, sizeof(buffer), "0%lo",
3689                                               min);
3690                                 break;
3691                         default:
3692                                 ccs_addprintf(buffer, sizeof(buffer), "%lu",
3693                                               min);
3694                                 break;
3695                         }
3696                         if (min == max && min_type == max_type)
3697                                 break;
3698                         ccs_addprintf(buffer, sizeof(buffer), "-");
3699                         min_type = max_type;
3700                         min = max;
3701                 }
3702                 ccs_io_printf(head, "%s", buffer);
3703         }
3704 }
3705 
3706 /**
3707  * ccs_print_number_union - Print a ccs_number_union.
3708  *
3709  * @head: Pointer to "struct ccs_io_buffer".
3710  * @ptr:  Pointer to "struct ccs_number_union".
3711  *
3712  * Returns nothing.
3713  */
3714 static void ccs_print_number_union(struct ccs_io_buffer *head,
3715                                    const struct ccs_number_union *ptr)
3716 {
3717         ccs_set_space(head);
3718         ccs_print_number_union_nospace(head, ptr);
3719 }
3720 
3721 /**
3722  * ccs_print_condition - Print condition part.
3723  *
3724  * @head: Pointer to "struct ccs_io_buffer".
3725  * @cond: Pointer to "struct ccs_condition".
3726  *
3727  * Returns true on success, false otherwise.
3728  */
3729 static bool ccs_print_condition(struct ccs_io_buffer *head,
3730                                 const struct ccs_condition *cond)
3731 {
3732         switch (head->r.cond_step) {
3733         case 0:
3734                 head->r.cond_index = 0;
3735                 head->r.cond_step++;
3736                 if (cond->transit && cond->exec_transit) {
3737                         ccs_set_space(head);
3738                         ccs_set_string(head, cond->transit->name);
3739                 }
3740                 /* fall through */
3741         case 1:
3742                 {
3743                         const u16 condc = cond->condc;
3744                         const struct ccs_condition_element *condp =
3745                                 (typeof(condp)) (cond + 1);
3746                         const struct ccs_number_union *numbers_p =
3747                                 (typeof(numbers_p)) (condp + condc);
3748                         const struct ccs_name_union *names_p =
3749                                 (typeof(names_p))
3750                                 (numbers_p + cond->numbers_count);
3751                         const struct ccs_argv *argv =
3752                                 (typeof(argv)) (names_p + cond->names_count);
3753                         const struct ccs_envp *envp =
3754                                 (typeof(envp)) (argv + cond->argc);
3755                         u16 skip;
3756                         for (skip = 0; skip < head->r.cond_index; skip++) {
3757                                 const u8 left = condp->left;
3758                                 const u8 right = condp->right;
3759                                 condp++;
3760                                 switch (left) {
3761                                 case CCS_ARGV_ENTRY:
3762                                         argv++;
3763                                         continue;
3764                                 case CCS_ENVP_ENTRY:
3765                                         envp++;
3766                                         continue;
3767                                 case CCS_NUMBER_UNION:
3768                                         numbers_p++;
3769                                         break;
3770                                 }
3771                                 switch (right) {
3772                                 case CCS_NAME_UNION:
3773                                         names_p++;
3774                                         break;
3775                                 case CCS_NUMBER_UNION:
3776                                         numbers_p++;
3777                                         break;
3778                                 }
3779                         }
3780                         while (head->r.cond_index < condc) {
3781                                 const u8 match = condp->equals;
3782                                 const u8 left = condp->left;
3783                                 const u8 right = condp->right;
3784                                 if (!ccs_flush(head))
3785                                         return false;
3786                                 condp++;
3787                                 head->r.cond_index++;
3788                                 ccs_set_space(head);
3789                                 switch (left) {
3790                                 case CCS_ARGV_ENTRY:
3791                                         ccs_io_printf(head,
3792                                                       "exec.argv[%lu]%s=\"",
3793                                                       argv->index,
3794                                                       argv->is_not ? "!" : "");
3795                                         ccs_set_string(head,
3796                                                        argv->value->name);
3797                                         ccs_set_string(head, "\"");
3798                                         argv++;
3799                                         continue;
3800                                 case CCS_ENVP_ENTRY:
3801                                         ccs_set_string(head, "exec.envp[\"");
3802                                         ccs_set_string(head, envp->name->name);
3803                                         ccs_io_printf(head, "\"]%s=",
3804                                                       envp->is_not ? "!" : "");
3805                                         if (envp->value) {
3806                                                 ccs_set_string(head, "\"");
3807                                                 ccs_set_string(head, envp->
3808                                                                value->name);
3809                                                 ccs_set_string(head, "\"");
3810                                         } else {
3811                                                 ccs_set_string(head, "NULL");
3812                                         }
3813                                         envp++;
3814                                         continue;
3815                                 case CCS_NUMBER_UNION:
3816                                         ccs_print_number_union_nospace
3817                                                 (head, numbers_p++);
3818                                         break;
3819                                 default:
3820                                         ccs_set_string(head,
3821                                                ccs_condition_keyword[left]);
3822                                         break;
3823                                 }
3824                                 ccs_set_string(head, match ? "=" : "!=");
3825                                 switch (right) {
3826                                 case CCS_NAME_UNION:
3827                                         ccs_print_name_union_quoted
3828                                                 (head, names_p++);
3829                                         break;
3830                                 case CCS_NUMBER_UNION:
3831                                         ccs_print_number_union_nospace
3832                                                 (head, numbers_p++);
3833                                         break;
3834                                 default:
3835                                         ccs_set_string(head,
3836                                                ccs_condition_keyword[right]);
3837                                         break;
3838                                 }
3839                         }
3840                 }
3841                 head->r.cond_step++;
3842                 /* fall through */
3843         case 2:
3844                 if (!ccs_flush(head))
3845                         break;
3846                 head->r.cond_step++;
3847                 /* fall through */
3848         case 3:
3849                 if (cond->grant_log != CCS_GRANTLOG_AUTO)
3850                         ccs_io_printf(head, " grant_log=%s",
3851                                       ccs_yesno(cond->grant_log ==
3852                                                 CCS_GRANTLOG_YES));
3853                 if (cond->transit && !cond->exec_transit) {
3854                         const char *name = cond->transit->name;
3855                         ccs_set_string(head, " auto_domain_transition=\"");
3856                         ccs_set_string(head, name);
3857                         ccs_set_string(head, "\"");
3858                 }
3859                 ccs_set_lf(head);
3860                 return true;
3861         }
3862         return false;
3863 }
3864 
3865 /**
3866  * ccs_set_group - Print "acl_group " header keyword and category name.
3867  *
3868  * @head:     Pointer to "struct ccs_io_buffer".
3869  * @category: Category name.
3870  *
3871  * Returns nothing.
3872  */
3873 static void ccs_set_group(struct ccs_io_buffer *head, const char *category)
3874 {
3875         if (head->type == CCS_EXCEPTION_POLICY) {
3876                 ccs_print_namespace(head);
3877                 ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
3878         }
3879         ccs_set_string(head, category);
3880 }
3881 
3882 /**
3883  * ccs_print_entry - Print an ACL entry.
3884  *
3885  * @head: Pointer to "struct ccs_io_buffer".
3886  * @acl:  Pointer to an ACL entry.
3887  *
3888  * Returns true on success, false otherwise.
3889  */
3890 static bool ccs_print_entry(struct ccs_io_buffer *head,
3891                             const struct ccs_acl_info *acl)
3892 {
3893         const u8 acl_type = acl->type;
3894         const bool may_trigger_transition = acl->cond && acl->cond->transit;
3895         bool first = true;
3896         u8 bit;
3897         if (head->r.print_cond_part)
3898                 goto print_cond_part;
3899         if (acl->is_deleted)
3900                 return true;
3901         if (!ccs_flush(head))
3902                 return false;
3903         else if (acl_type == CCS_TYPE_PATH_ACL) {
3904                 struct ccs_path_acl *ptr
3905                         = container_of(acl, typeof(*ptr), head);
3906                 for (bit = 0; bit < CCS_MAX_PATH_OPERATION; bit++) {
3907                         if (!(acl->perm & (1 << bit)))
3908                                 continue;
3909                         if (head->r.print_transition_related_only &&
3910                             bit != CCS_TYPE_EXECUTE && !may_trigger_transition)
3911                                 continue;
3912                         if (first) {
3913                                 ccs_set_group(head, "file ");
3914                                 first = false;
3915                         } else {
3916                                 ccs_set_slash(head);
3917                         }
3918                         ccs_set_string(head, ccs_path_keyword[bit]);
3919                 }
3920                 if (first)
3921                         return true;
3922                 ccs_print_name_union(head, &ptr->name);
3923 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3924         } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||
3925                    acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
3926                 struct ccs_handler_acl *ptr
3927                         = container_of(acl, typeof(*ptr), head);
3928                 ccs_set_group(head, "task ");
3929                 ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER
3930                                ? "auto_execute_handler " :
3931                                "denied_execute_handler ");
3932                 ccs_set_string(head, ptr->handler->name);
3933 #endif
3934 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
3935         } else if (acl_type == CCS_TYPE_AUTO_TASK_ACL ||
3936                    acl_type == CCS_TYPE_MANUAL_TASK_ACL) {
3937                 struct ccs_task_acl *ptr =
3938                         container_of(acl, typeof(*ptr), head);
3939                 ccs_set_group(head, "task ");
3940                 ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?
3941                                "auto_domain_transition " :
3942                                "manual_domain_transition ");
3943                 ccs_set_string(head, ptr->domainname->name);
3944 #endif
3945         } else if (head->r.print_transition_related_only &&
3946                    !may_trigger_transition) {
3947                 return true;
3948         } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
3949                 struct ccs_mkdev_acl *ptr =
3950                         container_of(acl, typeof(*ptr), head);
3951                 for (bit = 0; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
3952                         if (!(acl->perm & (1 << bit)))
3953                                 continue;
3954                         if (first) {
3955                                 ccs_set_group(head, "file ");
3956                                 first = false;
3957                         } else {
3958                                 ccs_set_slash(head);
3959                         }
3960                         ccs_set_string(head, ccs_mac_keywords
3961                                        [ccs_pnnn2mac[bit]]);
3962                 }
3963                 if (first)
3964                         return true;
3965                 ccs_print_name_union(head, &ptr->name);
3966                 ccs_print_number_union(head, &ptr->mode);
3967                 ccs_print_number_union(head, &ptr->major);
3968                 ccs_print_number_union(head, &ptr->minor);
3969         } else if (acl_type == CCS_TYPE_PATH2_ACL) {
3970                 struct ccs_path2_acl *ptr =
3971                         container_of(acl, typeof(*ptr), head);
3972                 for (bit = 0; bit < CCS_MAX_PATH2_OPERATION; bit++) {
3973                         if (!(acl->perm & (1 << bit)))
3974                                 continue;
3975                         if (first) {
3976                                 ccs_set_group(head, "file ");
3977                                 first = false;
3978                         } else {
3979                                 ccs_set_slash(head);
3980                         }
3981                         ccs_set_string(head, ccs_mac_keywords
3982                                        [ccs_pp2mac[bit]]);
3983                 }
3984                 if (first)
3985                         return true;
3986                 ccs_print_name_union(head, &ptr->name1);
3987                 ccs_print_name_union(head, &ptr->name2);
3988         } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
3989                 struct ccs_path_number_acl *ptr =
3990                         container_of(acl, typeof(*ptr), head);
3991                 for (bit = 0; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
3992                         if (!(acl->perm & (1 << bit)))
3993                                 continue;
3994                         if (first) {
3995                                 ccs_set_group(head, "file ");
3996                                 first = false;
3997                         } else {
3998                                 ccs_set_slash(head);
3999                         }
4000                         ccs_set_string(head, ccs_mac_keywords
4001                                        [ccs_pn2mac[bit]]);
4002                 }
4003                 if (first)
4004                         return true;
4005                 ccs_print_name_union(head, &ptr->name);
4006                 ccs_print_number_union(head, &ptr->number);
4007 #ifdef CONFIG_CCSECURITY_MISC
4008         } else if (acl_type == CCS_TYPE_ENV_ACL) {
4009                 struct ccs_env_acl *ptr =
4010                         container_of(acl, typeof(*ptr), head);
4011                 ccs_set_group(head, "misc env ");
4012                 ccs_set_string(head, ptr->env->name);
4013 #endif
4014 #ifdef CONFIG_CCSECURITY_CAPABILITY
4015         } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
4016                 struct ccs_capability_acl *ptr =
4017                         container_of(acl, typeof(*ptr), head);
4018                 ccs_set_group(head, "capability ");
4019                 ccs_set_string(head, ccs_mac_keywords
4020                                [ccs_c2mac[ptr->operation]]);
4021 #endif
4022 #ifdef CONFIG_CCSECURITY_NETWORK
4023         } else if (acl_type == CCS_TYPE_INET_ACL) {
4024                 struct ccs_inet_acl *ptr =
4025                         container_of(acl, typeof(*ptr), head);
4026                 for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
4027                         if (!(acl->perm & (1 << bit)))
4028                                 continue;
4029                         if (first) {
4030                                 ccs_set_group(head, "network inet ");
4031                                 ccs_set_string(head, ccs_proto_keyword
4032                                                [ptr->protocol]);
4033                                 ccs_set_space(head);
4034                                 first = false;
4035                         } else {
4036                                 ccs_set_slash(head);
4037                         }
4038                         ccs_set_string(head, ccs_socket_keyword[bit]);
4039                 }
4040                 if (first)
4041                         return true;
4042                 ccs_set_space(head);
4043                 if (!ccs_print_group(head, ptr->address.group)) {
4044                         char buf[128];
4045                         ccs_print_ip(buf, sizeof(buf), &ptr->address);
4046                         ccs_io_printf(head, "%s", buf);
4047                 }
4048                 ccs_print_number_union(head, &ptr->port);
4049         } else if (acl_type == CCS_TYPE_UNIX_ACL) {
4050                 struct ccs_unix_acl *ptr =
4051                         container_of(acl, typeof(*ptr), head);
4052                 for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
4053                         if (!(acl->perm & (1 << bit)))
4054                                 continue;
4055                         if (first) {
4056                                 ccs_set_group(head, "network unix ");
4057                                 ccs_set_string(head, ccs_proto_keyword
4058                                                [ptr->protocol]);
4059                                 ccs_set_space(head);
4060                                 first = false;
4061                         } else {
4062                                 ccs_set_slash(head);
4063                         }
4064                         ccs_set_string(head, ccs_socket_keyword[bit]);
4065                 }
4066                 if (first)
4067                         return true;
4068                 ccs_print_name_union(head, &ptr->name);
4069 #endif
4070 #ifdef CONFIG_CCSECURITY_IPC
4071         } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
4072                 struct ccs_signal_acl *ptr =
4073                         container_of(acl, typeof(*ptr), head);
4074                 ccs_set_group(head, "ipc signal ");
4075                 ccs_print_number_union_nospace(head, &ptr->sig);
4076                 ccs_set_space(head);
4077                 ccs_set_string(head, ptr->domainname->name);
4078 #endif
4079         } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
4080                 struct ccs_mount_acl *ptr =
4081                         container_of(acl, typeof(*ptr), head);
4082                 ccs_set_group(head, "file mount");
4083                 ccs_print_name_union(head, &ptr->dev_name);
4084                 ccs_print_name_union(head, &ptr->dir_name);
4085                 ccs_print_name_union(head, &ptr->fs_type);
4086                 ccs_print_number_union(head, &ptr->flags);
4087         }
4088         if (acl->cond) {
4089                 head->r.print_cond_part = true;
4090                 head->r.cond_step = 0;
4091                 if (!ccs_flush(head))
4092                         return false;
4093 print_cond_part:
4094                 if (!ccs_print_condition(head, acl->cond))
4095                         return false;
4096                 head->r.print_cond_part = false;
4097         } else {
4098                 ccs_set_lf(head);
4099         }
4100         return true;
4101 }
4102 
4103 /**
4104  * ccs_read_acl - Read "struct ccs_acl_info" list.
4105  *
4106  * @head: Pointer to "struct ccs_io_buffer".
4107  * @list: Pointer to "struct list_head".
4108  *
4109  * Returns true on success, false otherwise.
4110  *
4111  * Caller holds ccs_read_lock().
4112  */
4113 static bool ccs_read_acl(struct ccs_io_buffer *head, struct list_head *list)
4114 {
4115         list_for_each_cookie(head->r.acl, list) {
4116                 struct ccs_acl_info *ptr =
4117                         list_entry(head->r.acl, typeof(*ptr), list);
4118                 if (!ccs_print_entry(head, ptr))
4119                         return false;
4120         }
4121         head->r.acl = NULL;
4122         return true;
4123 }
4124 
4125 /**
4126  * ccs_read_domain - Read domain policy.
4127  *
4128  * @head: Pointer to "struct ccs_io_buffer".
4129  *
4130  * Returns nothing.
4131  *
4132  * Caller holds ccs_read_lock().
4133  */
4134 static void ccs_read_domain(struct ccs_io_buffer *head)
4135 {
4136         if (head->r.eof)
4137                 return;
4138         list_for_each_cookie(head->r.domain, &ccs_domain_list) {
4139                 struct ccs_domain_info *domain =
4140                         list_entry(head->r.domain, typeof(*domain), list);
4141                 switch (head->r.step) {
4142                         u8 i;
4143                 case 0:
4144                         if (domain->is_deleted &&
4145                             !head->r.print_this_domain_only)
4146                                 continue;
4147                         /* Print domainname and flags. */
4148                         ccs_set_string(head, domain->domainname->name);
4149                         ccs_set_lf(head);
4150                         ccs_io_printf(head, "use_profile %u\n",
4151                                       domain->profile);
4152                         for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)
4153                                 if (domain->flags[i])
4154                                         ccs_set_string(head, ccs_dif[i]);
4155                         head->r.index = 0;
4156                         head->r.step++;
4157                         /* fall through */
4158                 case 1:
4159                         while (head->r.index < CCS_MAX_ACL_GROUPS) {
4160                                 i = head->r.index++;
4161                                 if (!test_bit(i, domain->group))
4162                                         continue;
4163                                 ccs_io_printf(head, "use_group %u\n", i);
4164                                 if (!ccs_flush(head))
4165                                         return;
4166                         }
4167                         head->r.index = 0;
4168                         head->r.step++;
4169                         ccs_set_lf(head);
4170                         /* fall through */
4171                 case 2:
4172                         if (!ccs_read_acl(head, &domain->acl_info_list))
4173                                 return;
4174                         head->r.step++;
4175                         if (!ccs_set_lf(head))
4176                                 return;
4177                         /* fall through */
4178                 case 3:
4179                         head->r.step = 0;
4180                         if (head->r.print_this_domain_only)
4181                                 goto done;
4182                 }
4183         }
4184 done:
4185         head->r.eof = true;
4186 }
4187 
4188 /**
4189  * ccs_write_pid - Specify PID to obtain domainname.
4190  *
4191  * @head: Pointer to "struct ccs_io_buffer".
4192  *
4193  * Returns 0.
4194  */
4195 static int ccs_write_pid(struct ccs_io_buffer *head)
4196 {
4197         head->r.eof = false;
4198         return 0;
4199 }
4200 
4201 /**
4202  * ccs_read_pid - Read information of a process.
4203  *
4204  * @head: Pointer to "struct ccs_io_buffer".
4205  *
4206  * Returns the domainname which the specified PID is in or
4207  * process information of the specified PID on success,
4208  * empty string otherwise.
4209  *
4210  * Caller holds ccs_read_lock().
4211  */
4212 static void ccs_read_pid(struct ccs_io_buffer *head)
4213 {
4214         char *buf = head->write_buf;
4215         bool task_info = false;
4216         bool global_pid = false;
4217         unsigned int pid;
4218         struct task_struct *p;
4219         struct ccs_domain_info *domain = NULL;
4220         u32 ccs_flags = 0;
4221         /* Accessing write_buf is safe because head->io_sem is held. */
4222         if (!buf) {
4223                 head->r.eof = true;
4224                 return; /* Do nothing if open(O_RDONLY). */
4225         }
4226         if (head->r.w_pos || head->r.eof)
4227                 return;
4228         head->r.eof = true;
4229         if (ccs_str_starts(&buf, "info "))
4230                 task_info = true;
4231         if (ccs_str_starts(&buf, "global-pid "))
4232                 global_pid = true;
4233         pid = (unsigned int) simple_strtoul(buf, NULL, 10);
4234         ccs_tasklist_lock();
4235 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
4236         if (global_pid)
4237                 p = ccsecurity_exports.find_task_by_pid_ns(pid, &init_pid_ns);
4238         else
4239                 p = ccsecurity_exports.find_task_by_vpid(pid);
4240 #else
4241         p = find_task_by_pid(pid);
4242 #endif
4243         if (p) {
4244                 domain = ccs_task_domain(p);
4245                 ccs_flags = ccs_task_flags(p);
4246         }
4247         ccs_tasklist_unlock();
4248         if (!domain)
4249                 return;
4250         if (!task_info) {
4251                 ccs_io_printf(head, "%u %u ", pid, domain->profile);
4252                 ccs_set_string(head, domain->domainname->name);
4253         } else {
4254                 ccs_io_printf(head, "%u manager=%s execute_handler=%s ", pid,
4255                               ccs_yesno(ccs_flags &
4256                                         CCS_TASK_IS_MANAGER),
4257                               ccs_yesno(ccs_flags &
4258                                         CCS_TASK_IS_EXECUTE_HANDLER));
4259         }
4260 }
4261 
4262 /**
4263  * ccs_write_group - Write "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
4264  *
4265  * @param: Pointer to "struct ccs_acl_param".
4266  * @type:  Type of this group.
4267  *
4268  * Returns 0 on success, negative value otherwise.
4269  */
4270 static int ccs_write_group(struct ccs_acl_param *param, const u8 type)
4271 {
4272         struct ccs_group *group = ccs_get_group(param, type);
4273         int error = -EINVAL;
4274         if (!group)
4275                 return -ENOMEM;
4276         param->list = &group->member_list;
4277         if (type == CCS_PATH_GROUP) {
4278                 struct ccs_path_group *e = &param->e.path_group;
4279                 e->member_name = ccs_get_name(ccs_read_token(param));
4280                 if (!e->member_name) {
4281                         error = -ENOMEM;
4282                         goto out;
4283                 }
4284                 error = ccs_update_policy(sizeof(*e), param);
4285                 ccs_put_name(e->member_name);
4286         } else if (type == CCS_NUMBER_GROUP) {
4287                 struct ccs_number_group *e = &param->e.number_group;
4288                 if (param->data[0] == '@' ||
4289                     !ccs_parse_number_union(param, &e->number))
4290                         goto out;
4291                 error = ccs_update_policy(sizeof(*e), param);
4292 #ifdef CONFIG_CCSECURITY_NETWORK
4293         } else {
4294                 struct ccs_address_group *e = &param->e.address_group;
4295                 if (param->data[0] == '@' ||
4296                     !ccs_parse_ipaddr_union(param, &e->address))
4297                         goto out;
4298                 error = ccs_update_policy(sizeof(*e), param);
4299 #endif
4300         }
4301 out:
4302         ccs_put_group(group);
4303         return error;
4304 }
4305 
4306 #ifdef CONFIG_CCSECURITY_PORTRESERVE
4307 /**
4308  * ccs_lport_reserved - Check whether local port is reserved or not.
4309  *
4310  * @port: Port number.
4311  *
4312  * Returns true if local port is reserved, false otherwise.
4313  */
4314 static bool __ccs_lport_reserved(const u16 port)
4315 {
4316         return ccs_reserved_port_map[port >> 3] & (1 << (port & 7))
4317                 ? true : false;
4318 }
4319 
4320 /**
4321  * ccs_write_reserved_port - Update "struct ccs_reserved" list.
4322  *
4323  * @param: Pointer to "struct ccs_acl_param".
4324  *
4325  * Returns 0 on success, negative value otherwise.
4326  *
4327  * Caller holds ccs_read_lock().
4328  */
4329 static int ccs_write_reserved_port(struct ccs_acl_param *param)
4330 {
4331         struct ccs_reserved *e = &param->e.reserved;
4332         struct ccs_policy_namespace *ns = param->ns;
4333         int error;
4334         u8 *tmp;
4335         if (param->data[0] == '@' ||
4336             !ccs_parse_number_union(param, &e->port) ||
4337             e->port.values[1] > 65535 || param->data[0])
4338                 return -EINVAL;
4339         param->list = &ns->policy_list[CCS_ID_RESERVEDPORT];
4340         error = ccs_update_policy(sizeof(*e), param);
4341         if (error)
4342                 return error;
4343         tmp = kzalloc(sizeof(ccs_reserved_port_map), CCS_GFP_FLAGS);
4344         if (!tmp)
4345                 return -ENOMEM;
4346         list_for_each_entry_srcu(ns, &ccs_namespace_list, namespace_list,
4347                                  &ccs_ss) {
4348                 struct ccs_reserved *ptr;
4349                 struct list_head *list = &ns->policy_list[CCS_ID_RESERVEDPORT];
4350                 list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
4351                         unsigned int port;
4352                         if (ptr->head.is_deleted)
4353                                 continue;
4354                         for (port = ptr->port.values[0];
4355                              port <= ptr->port.values[1]; port++)
4356                                 tmp[port >> 3] |= 1 << (port & 7);
4357                 }
4358         }
4359         memmove(ccs_reserved_port_map, tmp, sizeof(ccs_reserved_port_map));
4360         kfree(tmp);
4361         /*
4362          * Since this feature is no-op by default, we don't need to register
4363          * this callback hook unless the first entry is added.
4364          */
4365         ccsecurity_ops.lport_reserved = __ccs_lport_reserved;
4366         return 0;
4367 }
4368 #endif
4369 
4370 /**
4371  * ccs_write_aggregator - Write "struct ccs_aggregator" list.
4372  *
4373  * @param: Pointer to "struct ccs_acl_param".
4374  *
4375  * Returns 0 on success, negative value otherwise.
4376  */
4377 static int ccs_write_aggregator(struct ccs_acl_param *param)
4378 {
4379         struct ccs_aggregator *e = &param->e.aggregator;
4380         int error = param->is_delete ? -ENOENT : -ENOMEM;
4381         const char *original_name = ccs_read_token(param);
4382         const char *aggregated_name = ccs_read_token(param);
4383         if (!ccs_correct_word(original_name) ||
4384             !ccs_correct_path(aggregated_name))
4385                 return -EINVAL;
4386         e->original_name = ccs_get_name(original_name);
4387         e->aggregated_name = ccs_get_name(aggregated_name);
4388         if (!e->original_name || !e->aggregated_name ||
4389             e->aggregated_name->is_patterned) /* No patterns allowed. */
4390                 goto out;
4391         param->list = &param->ns->policy_list[CCS_ID_AGGREGATOR];
4392         error = ccs_update_policy(sizeof(*e), param);
4393 out:
4394         ccs_put_name(e->original_name);
4395         ccs_put_name(e->aggregated_name);
4396         return error;
4397 }
4398 
4399 /**
4400  * ccs_write_transition_control - Write "struct ccs_transition_control" list.
4401  *
4402  * @param: Pointer to "struct ccs_acl_param".
4403  * @type:  Type of this entry.
4404  *
4405  * Returns 0 on success, negative value otherwise.
4406  */
4407 static int ccs_write_transition_control(struct ccs_acl_param *param,
4408                                         const u8 type)
4409 {
4410         struct ccs_transition_control *e = &param->e.transition_control;
4411         int error = param->is_delete ? -ENOENT : -ENOMEM;
4412         char *program = param->data;
4413         char *domainname = strstr(program, " from ");
4414         e->type = type;
4415         if (domainname) {
4416                 *domainname = '\0';
4417                 domainname += 6;
4418         } else if (type == CCS_TRANSITION_CONTROL_NO_KEEP ||
4419                    type == CCS_TRANSITION_CONTROL_KEEP) {
4420                 domainname = program;
4421                 program = NULL;
4422         }
4423         if (program && strcmp(program, "any")) {
4424                 if (!ccs_correct_path(program))
4425                         return -EINVAL;
4426                 e->program = ccs_get_name(program);
4427                 if (!e->program)
4428                         goto out;
4429         }
4430         if (domainname && strcmp(domainname, "any")) {
4431                 if (!ccs_correct_domain(domainname)) {
4432                         if (!ccs_correct_path(domainname))
4433                                 goto out;
4434                         e->is_last_name = true;
4435                 }
4436                 e->domainname = ccs_get_name(domainname);
4437                 if (!e->domainname)
4438                         goto out;
4439         }
4440         param->list = &param->ns->policy_list[CCS_ID_TRANSITION_CONTROL];
4441         error = ccs_update_policy(sizeof(*e), param);
4442 out:
4443         ccs_put_name(e->domainname);
4444         ccs_put_name(e->program);
4445         return error;
4446 }
4447 
4448 /**
4449  * ccs_write_exception - Write exception policy.
4450  *
4451  * @head: Pointer to "struct ccs_io_buffer".
4452  *
4453  * Returns 0 on success, negative value otherwise.
4454  */
4455 static int ccs_write_exception(struct ccs_io_buffer *head)
4456 {
4457         const bool is_delete = head->w.is_delete;
4458         struct ccs_acl_param param = {
4459                 .ns = head->w.ns,
4460                 .is_delete = is_delete,
4461                 .data = head->write_buf,
4462         };
4463         u8 i;
4464         /* Forced zero clear for using memcmp() at ccs_update_policy(). */
4465         memset(&param.e, 0, sizeof(param.e));
4466         if (ccs_str_starts(&param.data, "aggregator "))
4467                 return ccs_write_aggregator(&param);
4468 #ifdef CONFIG_CCSECURITY_PORTRESERVE
4469         if (ccs_str_starts(&param.data, "deny_autobind "))
4470                 return ccs_write_reserved_port(&param);
4471 #endif
4472         for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
4473                 if (ccs_str_starts(&param.data, ccs_transition_type[i]))
4474                         return ccs_write_transition_control(&param, i);
4475         for (i = 0; i < CCS_MAX_GROUP; i++)
4476                 if (ccs_str_starts(&param.data, ccs_group_name[i]))
4477                         return ccs_write_group(&param, i);
4478         if (ccs_str_starts(&param.data, "acl_group ")) {
4479                 unsigned int group;
4480                 char *data;
4481                 group = simple_strtoul(param.data, &data, 10);
4482                 if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
4483                         return ccs_write_acl(head->w.ns,
4484                                              &head->w.ns->acl_group[group],
4485                                              data, is_delete);
4486         }
4487         return -EINVAL;
4488 }
4489 
4490 /**
4491  * ccs_read_group - Read "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
4492  *
4493  * @head: Pointer to "struct ccs_io_buffer".
4494  * @idx:  Index number.
4495  *
4496  * Returns true on success, false otherwise.
4497  *
4498  * Caller holds ccs_read_lock().
4499  */
4500 static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)
4501 {
4502         struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
4503                                                        namespace_list);
4504         struct list_head *list = &ns->group_list[idx];
4505         list_for_each_cookie(head->r.group, list) {
4506                 struct ccs_group *group =
4507                         list_entry(head->r.group, typeof(*group), head.list);
4508                 list_for_each_cookie(head->r.acl, &group->member_list) {
4509                         struct ccs_acl_head *ptr =
4510                                 list_entry(head->r.acl, typeof(*ptr), list);
4511                         if (ptr->is_deleted)
4512                                 continue;
4513                         if (!ccs_flush(head))
4514                                 return false;
4515                         ccs_print_namespace(head);
4516                         ccs_set_string(head, ccs_group_name[idx]);
4517                         ccs_set_string(head, group->group_name->name);
4518                         if (idx == CCS_PATH_GROUP) {
4519                                 ccs_set_space(head);
4520                                 ccs_set_string(head, container_of
4521                                                (ptr, struct ccs_path_group,
4522                                                 head)->member_name->name);
4523                         } else if (idx == CCS_NUMBER_GROUP) {
4524                                 ccs_print_number_union(head, &container_of
4525                                                (ptr, struct ccs_number_group,
4526                                                 head)->number);
4527 #ifdef CONFIG_CCSECURITY_NETWORK
4528                         } else if (idx == CCS_ADDRESS_GROUP) {
4529                                 char buffer[128];
4530                                 struct ccs_address_group *member =
4531                                         container_of(ptr, typeof(*member),
4532                                                      head);
4533                                 ccs_print_ip(buffer, sizeof(buffer),
4534                                              &member->address);
4535                                 ccs_io_printf(head, " %s", buffer);
4536 #endif
4537                         }
4538                         ccs_set_lf(head);
4539                 }
4540                 head->r.acl = NULL;
4541         }
4542         head->r.group = NULL;
4543         return true;
4544 }
4545 
4546 /**
4547  * ccs_read_policy - Read "struct ccs_..._entry" list.
4548  *
4549  * @head: Pointer to "struct ccs_io_buffer".
4550  * @idx:  Index number.
4551  *
4552  * Returns true on success, false otherwise.
4553  *
4554  * Caller holds ccs_read_lock().
4555  */
4556 static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)
4557 {
4558         struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
4559                                                        namespace_list);
4560         struct list_head *list = &ns->policy_list[idx];
4561         list_for_each_cookie(head->r.acl, list) {
4562                 struct ccs_acl_head *acl =
4563                         container_of(head->r.acl, typeof(*acl), list);
4564                 if (acl->is_deleted)
4565                         continue;
4566                 if (head->r.print_transition_related_only &&
4567                     idx != CCS_ID_TRANSITION_CONTROL)
4568                         continue;
4569                 if (!ccs_flush(head))
4570                         return false;
4571                 switch (idx) {
4572                 case CCS_ID_TRANSITION_CONTROL:
4573                         {
4574                                 struct ccs_transition_control *ptr =
4575                                         container_of(acl, typeof(*ptr), head);
4576                                 ccs_print_namespace(head);
4577                                 ccs_set_string(head,
4578                                                ccs_transition_type[ptr->type]);
4579                                 ccs_set_string(head, ptr->program ?
4580                                                ptr->program->name : "any");
4581                                 ccs_set_string(head, " from ");
4582                                 ccs_set_string(head, ptr->domainname ?
4583                                                ptr->domainname->name : "any");
4584                         }
4585                         break;
4586                 case CCS_ID_AGGREGATOR:
4587                         {
4588                                 struct ccs_aggregator *ptr =
4589                                         container_of(acl, typeof(*ptr), head);
4590                                 ccs_print_namespace(head);
4591                                 ccs_set_string(head, "aggregator ");
4592                                 ccs_set_string(head, ptr->original_name->name);
4593                                 ccs_set_space(head);
4594                                 ccs_set_string(head,
4595                                                ptr->aggregated_name->name);
4596                         }
4597                         break;
4598 #ifdef CONFIG_CCSECURITY_PORTRESERVE
4599                 case CCS_ID_RESERVEDPORT:
4600                         {
4601                                 struct ccs_reserved *ptr =
4602                                         container_of(acl, typeof(*ptr), head);
4603                                 ccs_print_namespace(head);
4604                                 ccs_set_string(head, "deny_autobind ");
4605                                 ccs_print_number_union_nospace(head,
4606                                                                &ptr->port);
4607                         }
4608                         break;
4609 #endif
4610                 default:
4611                         continue;
4612                 }
4613                 ccs_set_lf(head);
4614         }
4615         head->r.acl = NULL;
4616         return true;
4617 }
4618 
4619 /**
4620  * ccs_read_exception - Read exception policy.
4621  *
4622  * @head: Pointer to "struct ccs_io_buffer".
4623  *
4624  * Returns nothing.
4625  *
4626  * Caller holds ccs_read_lock().
4627  */
4628 static void ccs_read_exception(struct ccs_io_buffer *head)
4629 {
4630         struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
4631                                                        namespace_list);
4632         if (head->r.eof)
4633                 return;
4634         while (head->r.step < CCS_MAX_POLICY &&
4635                ccs_read_policy(head, head->r.step))
4636                 head->r.step++;
4637         if (head->r.step < CCS_MAX_POLICY)
4638                 return;
4639         while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP &&
4640                ccs_read_group(head, head->r.step - CCS_MAX_POLICY))
4641                 head->r.step++;
4642         if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)
4643                 return;
4644         while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
4645                + CCS_MAX_ACL_GROUPS) {
4646                 head->r.acl_group_index =
4647                         head->r.step - CCS_MAX_POLICY - CCS_MAX_GROUP;
4648                 if (!ccs_read_acl(head, &ns->acl_group
4649                                   [head->r.acl_group_index]))
4650                         return;
4651                 head->r.step++;
4652         }
4653         head->r.eof = true;
4654 }
4655 
4656 /**
4657  * ccs_truncate - Truncate a line.
4658  *
4659  * @str: String to truncate.
4660  *
4661  * Returns length of truncated @str.
4662  */
4663 static int ccs_truncate(char *str)
4664 {
4665         char *start = str;
4666         while (*(unsigned char *) str > (unsigned char) ' ')
4667                 str++;
4668         *str = '\0';
4669         return strlen(start) + 1;
4670 }
4671 
4672 /**
4673  * ccs_add_entry - Add an ACL to current thread's domain. Used by learning mode.
4674  *
4675  * @header: Lines containing ACL.
4676  *
4677  * Returns nothing.
4678  */
4679 static void ccs_add_entry(char *header)
4680 {
4681         char *buffer;
4682         char *realpath = NULL;
4683         char *argv0 = NULL;
4684         char *symlink = NULL;
4685 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
4686         char *handler;
4687 #endif
4688         char *cp = strchr(header, '\n');
4689         int len;
4690         if (!cp)
4691                 return;
4692         cp = strchr(cp + 1, '\n');
4693         if (!cp)
4694                 return;
4695         *cp++ = '\0';
4696         len = strlen(cp) + 1;
4697         /* strstr() will return NULL if ordering is wrong. */
4698         if (*cp == 'f') {
4699                 argv0 = strstr(header, " argv[]={ \"");
4700                 if (argv0) {
4701                         argv0 += 10;
4702                         len += ccs_truncate(argv0) + 14;
4703                 }
4704                 realpath = strstr(header, " exec={ realpath=\"");
4705                 if (realpath) {
4706                         realpath += 8;
4707                         len += ccs_truncate(realpath) + 6;
4708                 }
4709                 symlink = strstr(header, " symlink.target=\"");
4710                 if (symlink)
4711                         len += ccs_truncate(symlink + 1) + 1;
4712         }
4713 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
4714         handler = strstr(header, "type=execute_handler");
4715         if (handler)
4716                 len += ccs_truncate(handler) + 6;
4717 #endif
4718         buffer = kmalloc(len, CCS_GFP_FLAGS);
4719         if (!buffer)
4720                 return;
4721         snprintf(buffer, len - 1, "%s", cp);
4722 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
4723         if (handler)
4724                 ccs_addprintf(buffer, len, " task.%s", handler);
4725 #endif
4726         if (realpath)
4727                 ccs_addprintf(buffer, len, " exec.%s", realpath);
4728         if (argv0)
4729                 ccs_addprintf(buffer, len, " exec.argv[0]=%s", argv0);
4730         if (symlink)
4731                 ccs_addprintf(buffer, len, "%s", symlink);
4732         ccs_normalize_line(buffer);
4733         {
4734                 struct ccs_domain_info *domain = ccs_current_domain();
4735                 if (!ccs_write_acl(domain->ns, &domain->acl_info_list,
4736                                    buffer, false))
4737                         ccs_update_stat(CCS_STAT_POLICY_UPDATES);
4738         }
4739         kfree(buffer);
4740 }
4741 
4742 /**
4743  * ccs_domain_quota_ok - Check for domain's quota.
4744  *
4745  * @r: Pointer to "struct ccs_request_info".
4746  *
4747  * Returns true if the domain is not exceeded quota, false otherwise.
4748  *
4749  * Caller holds ccs_read_lock().
4750  */
4751 static bool ccs_domain_quota_ok(struct ccs_request_info *r)
4752 {
4753         unsigned int count = 0;
4754         struct ccs_domain_info * const domain = ccs_current_domain();
4755         struct ccs_acl_info *ptr;
4756         if (r->mode != CCS_CONFIG_LEARNING)
4757                 return false;
4758         if (!domain)
4759                 return true;
4760         list_for_each_entry_srcu(ptr, &domain->acl_info_list, list, &ccs_ss) {
4761                 u16 perm;
4762                 u8 i;
4763                 if (ptr->is_deleted)
4764                         continue;
4765                 switch (ptr->type) {
4766                 case CCS_TYPE_PATH_ACL:
4767                 case CCS_TYPE_PATH2_ACL:
4768                 case CCS_TYPE_PATH_NUMBER_ACL:
4769                 case CCS_TYPE_MKDEV_ACL:
4770 #ifdef CONFIG_CCSECURITY_NETWORK
4771                 case CCS_TYPE_INET_ACL:
4772                 case CCS_TYPE_UNIX_ACL:
4773 #endif
4774                         perm = ptr->perm;
4775                         break;
4776 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
4777                 case CCS_TYPE_AUTO_EXECUTE_HANDLER:
4778                 case CCS_TYPE_DENIED_EXECUTE_HANDLER:
4779 #endif
4780 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
4781                 case CCS_TYPE_AUTO_TASK_ACL:
4782                 case CCS_TYPE_MANUAL_TASK_ACL:
4783 #endif
4784                         perm = 0;
4785                         break;
4786                 default:
4787                         perm = 1;
4788                 }
4789                 for (i = 0; i < 16; i++)
4790                         if (perm & (1 << i))
4791                                 count++;
4792         }
4793         if (count < ccs_profile(r->profile)->pref[CCS_PREF_MAX_LEARNING_ENTRY])
4794                 return true;
4795         if (!domain->flags[CCS_DIF_QUOTA_WARNED]) {
4796                 domain->flags[CCS_DIF_QUOTA_WARNED] = true;
4797                 /* r->granted = false; */
4798                 ccs_write_log(r, "%s", ccs_dif[CCS_DIF_QUOTA_WARNED]);
4799                 printk(KERN_WARNING "WARNING: "
4800                        "Domain '%s' has too many ACLs to hold. "
4801                        "Stopped learning mode.\n", domain->domainname->name);
4802         }
4803         return false;
4804 }
4805 
4806 /**
4807  * ccs_supervisor - Ask for the supervisor's decision.
4808  *
4809  * @r:   Pointer to "struct ccs_request_info".
4810  * @fmt: The printf()'s format string, followed by parameters.
4811  *
4812  * Returns 0 if the supervisor decided to permit the access request which
4813  * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor
4814  * decided to retry the access request which violated the policy in enforcing
4815  * mode, 0 if it is not in enforcing mode, -EPERM otherwise.
4816  */
4817 static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
4818 {
4819         va_list args;
4820         int error;
4821         int len;
4822         static unsigned int ccs_serial;
4823         struct ccs_query entry = { };
4824         bool quota_exceeded = false;
4825         va_start(args, fmt);
4826         len = vsnprintf((char *) &len, 1, fmt, args) + 1;
4827         va_end(args);
4828         /* Write /proc/ccs/audit. */
4829         va_start(args, fmt);
4830         ccs_write_log2(r, len, fmt, args);
4831         va_end(args);
4832         /* Nothing more to do if granted. */
4833         if (r->granted)
4834                 return 0;
4835         if (r->mode)
4836                 ccs_update_stat(r->mode);
4837         switch (r->mode) {
4838                 int i;
4839                 struct ccs_profile *p;
4840         case CCS_CONFIG_ENFORCING:
4841                 error = -EPERM;
4842                 if (atomic_read(&ccs_query_observers))
4843                         break;
4844                 if (r->dont_sleep_on_enforce_error)
4845                         goto out;
4846                 p = ccs_profile(r->profile);
4847                 /* Check enforcing_penalty parameter. */
4848                 for (i = 0; i < p->pref[CCS_PREF_ENFORCING_PENALTY]; i++) {
4849                         set_current_state(TASK_INTERRUPTIBLE);
4850                         schedule_timeout(HZ / 10);
4851                 }
4852                 goto out;
4853         case CCS_CONFIG_LEARNING:
4854                 error = 0;
4855                 /* Check max_learning_entry parameter. */
4856                 if (ccs_domain_quota_ok(r))
4857                         break;
4858                 /* fall through */
4859         default:
4860                 return 0;
4861         }
4862         /* Get message. */
4863         va_start(args, fmt);
4864         entry.query = ccs_init_log(r, len, fmt, args);
4865         va_end(args);
4866         if (!entry.query)
4867                 goto out;
4868         entry.query_len = strlen(entry.query) + 1;
4869         if (!error) {
4870                 ccs_add_entry(entry.query);
4871                 goto out;
4872         }
4873         len = ccs_round2(entry.query_len);
4874         entry.domain = ccs_current_domain();
4875         spin_lock(&ccs_query_list_lock);
4876         if (ccs_memory_quota[CCS_MEMORY_QUERY] &&
4877             ccs_memory_used[CCS_MEMORY_QUERY] + len
4878             >= ccs_memory_quota[CCS_MEMORY_QUERY]) {
4879                 quota_exceeded = true;
4880         } else {
4881                 entry.serial = ccs_serial++;
4882                 entry.retry = r->retry;
4883                 ccs_memory_used[CCS_MEMORY_QUERY] += len;
4884                 list_add_tail(&entry.list, &ccs_query_list);
4885         }
4886         spin_unlock(&ccs_query_list_lock);
4887         if (quota_exceeded)
4888                 goto out;
4889         /* Give 10 seconds for supervisor's opinion. */
4890         while (entry.timer < 10) {
4891                 wake_up_all(&ccs_query_wait);
4892                 if (wait_event_interruptible_timeout
4893                     (ccs_answer_wait, entry.answer ||
4894                      !atomic_read(&ccs_query_observers), HZ))
4895                         break;
4896                 else
4897                         entry.timer++;
4898         }
4899         spin_lock(&ccs_query_list_lock);
4900         list_del(&entry.list);
4901         ccs_memory_used[CCS_MEMORY_QUERY] -= len;
4902         spin_unlock(&ccs_query_list_lock);
4903         switch (entry.answer) {
4904         case 3: /* Asked to retry by administrator. */
4905                 error = CCS_RETRY_REQUEST;
4906                 r->retry++;
4907                 break;
4908         case 1:
4909                 /* Granted by administrator. */
4910                 error = 0;
4911                 break;
4912         default:
4913                 /* Timed out or rejected by administrator. */
4914                 break;
4915         }
4916 out:
4917         kfree(entry.query);
4918         return error;
4919 }
4920 
4921 /**
4922  * ccs_audit_log - Audit permission check log.
4923  *
4924  * @r: Pointer to "struct ccs_request_info".
4925  *
4926  * Returns return value of ccs_supervisor().
4927  */
4928 int ccs_audit_log(struct ccs_request_info *r)
4929 {
4930         switch (r->param_type) {
4931                 u8 type;
4932                 char buf[48];
4933 #ifdef CONFIG_CCSECURITY_NETWORK
4934                 const u32 *address;
4935 #endif
4936         case CCS_TYPE_PATH_ACL:
4937                 return ccs_supervisor(r, "file %s %s\n", ccs_path_keyword
4938                                       [r->param.path.operation],
4939                                       r->param.path.filename->name);
4940         case CCS_TYPE_PATH2_ACL:
4941                 return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords
4942                                       [ccs_pp2mac[r->param.path2.operation]],
4943                                       r->param.path2.filename1->name,
4944                                       r->param.path2.filename2->name);
4945         case CCS_TYPE_PATH_NUMBER_ACL:
4946                 type = r->param.path_number.operation;
4947                 switch (type) {
4948                 case CCS_TYPE_CREATE:
4949                 case CCS_TYPE_MKDIR:
4950                 case CCS_TYPE_MKFIFO:
4951                 case CCS_TYPE_MKSOCK:
4952                 case CCS_TYPE_CHMOD:
4953                         snprintf(buf, sizeof(buf), "0%lo",
4954                                  r->param.path_number.number);
4955                         break;
4956                 case CCS_TYPE_IOCTL:
4957                         snprintf(buf, sizeof(buf), "0x%lX",
4958                                  r->param.path_number.number);
4959                         break;
4960                 default:
4961                         snprintf(buf, sizeof(buf), "%lu",
4962                                  r->param.path_number.number);
4963                         break;
4964                 }
4965                 return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords
4966                                       [ccs_pn2mac[type]],
4967                                       r->param.path_number.filename->name,
4968                                       buf);
4969         case CCS_TYPE_MKDEV_ACL:
4970                 return ccs_supervisor(r, "file %s %s 0%o %u %u\n",
4971                                       ccs_mac_keywords
4972                                       [ccs_pnnn2mac[r->param.mkdev.operation]],
4973                                       r->param.mkdev.filename->name,
4974                                       r->param.mkdev.mode,
4975                                       r->param.mkdev.major,
4976                                       r->param.mkdev.minor);
4977         case CCS_TYPE_MOUNT_ACL:
4978                 return ccs_supervisor(r, "file mount %s %s %s 0x%lX\n",
4979                                       r->param.mount.dev->name,
4980                                       r->param.mount.dir->name,
4981                                       r->param.mount.type->name,
4982                                       r->param.mount.flags);
4983 #ifdef CONFIG_CCSECURITY_MISC
4984         case CCS_TYPE_ENV_ACL:
4985                 return ccs_supervisor(r, "misc env %s\n",
4986                                       r->param.environ.name->name);
4987 #endif
4988 #ifdef CONFIG_CCSECURITY_CAPABILITY
4989         case CCS_TYPE_CAPABILITY_ACL:
4990                 return ccs_supervisor(r, "capability %s\n", ccs_mac_keywords
4991                                       [ccs_c2mac[r->param.capability.
4992                                                  operation]]);
4993 #endif
4994 #ifdef CONFIG_CCSECURITY_NETWORK
4995         case CCS_TYPE_INET_ACL:
4996                 address = r->param.inet_network.address;
4997                 if (r->param.inet_network.is_ipv6)
4998                         ccs_print_ipv6(buf, sizeof(buf),
4999                                        (const struct in6_addr *) address);
5000                 else
5001                         ccs_print_ipv4(buf, sizeof(buf), address);
5002                 return ccs_supervisor(r, "network inet %s %s %s %u\n",
5003                                       ccs_proto_keyword[r->param.inet_network.
5004                                                         protocol],
5005                                       ccs_socket_keyword[r->param.inet_network.
5006                                                          operation],
5007                                       buf, r->param.inet_network.port);
5008         case CCS_TYPE_UNIX_ACL:
5009                 return ccs_supervisor(r, "network unix %s %s %s\n",
5010                                       ccs_proto_keyword[r->param.
5011                                                         unix_network.protocol],
5012                                       ccs_socket_keyword[r->param.unix_network.
5013                                                          operation],
5014                                       r->param.unix_network.address->name);
5015 #endif
5016 #ifdef CONFIG_CCSECURITY_IPC
5017         case CCS_TYPE_SIGNAL_ACL:
5018                 return ccs_supervisor(r, "ipc signal %d %s\n",
5019                                       r->param.signal.sig,
5020                                       r->param.signal.dest_pattern);
5021 #endif
5022         }
5023         return 0;
5024 }
5025 
5026 /**
5027  * ccs_find_domain_by_qid - Get domain by query id.
5028  *
5029  * @serial: Query ID assigned by ccs_supervisor().
5030  *
5031  * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
5032  */
5033 static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial)
5034 {
5035         struct ccs_query *ptr;
5036         struct ccs_domain_info *domain = NULL;
5037         spin_lock(&ccs_query_list_lock);
5038         list_for_each_entry(ptr, &ccs_query_list, list) {
5039                 if (ptr->serial != serial)
5040                         continue;
5041                 domain = ptr->domain;
5042                 break;
5043         }
5044         spin_unlock(&ccs_query_list_lock);
5045         return domain;
5046 }
5047 
5048 /**
5049  * ccs_read_query - Read access requests which violated policy in enforcing mode.
5050  *
5051  * @head: Pointer to "struct ccs_io_buffer".
5052  *
5053  * Returns nothing.
5054  */
5055 static void ccs_read_query(struct ccs_io_buffer *head)
5056 {
5057         struct list_head *tmp;
5058         unsigned int pos = 0;
5059         size_t len = 0;
5060         char *buf;
5061         if (head->r.w_pos)
5062                 return;
5063         kfree(head->read_buf);
5064         head->read_buf = NULL;
5065         spin_lock(&ccs_query_list_lock);
5066         list_for_each(tmp, &ccs_query_list) {
5067                 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
5068                 if (pos++ != head->r.query_index)
5069                         continue;
5070                 len = ptr->query_len;
5071                 break;
5072         }
5073         spin_unlock(&ccs_query_list_lock);
5074         if (!len) {
5075                 head->r.query_index = 0;
5076                 return;
5077         }
5078         buf = kzalloc(len + 32, CCS_GFP_FLAGS);
5079         if (!buf)
5080                 return;
5081         pos = 0;
5082         spin_lock(&ccs_query_list_lock);
5083         list_for_each(tmp, &ccs_query_list) {
5084                 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
5085                 if (pos++ != head->r.query_index)
5086                         continue;
5087                 /*
5088                  * Some query can be skipped because ccs_query_list
5089                  * can change, but I don't care.
5090                  */
5091                 if (len == ptr->query_len)
5092                         snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
5093                                  ptr->retry, ptr->query);
5094                 break;
5095         }
5096         spin_unlock(&ccs_query_list_lock);
5097         if (buf[0]) {
5098                 head->read_buf = buf;
5099                 head->r.w[head->r.w_pos++] = buf;
5100                 head->r.query_index++;
5101         } else {
5102                 kfree(buf);
5103         }
5104 }
5105 
5106 /**
5107  * ccs_write_answer - Write the supervisor's decision.
5108  *
5109  * @head: Pointer to "struct ccs_io_buffer".
5110  *
5111  * Returns 0 on success, -EINVAL otherwise.
5112  */
5113 static int ccs_write_answer(struct ccs_io_buffer *head)
5114 {
5115         char *data = head->write_buf;
5116         struct list_head *tmp;
5117         unsigned int serial;
5118         unsigned int answer;
5119         spin_lock(&ccs_query_list_lock);
5120         list_for_each(tmp, &ccs_query_list) {
5121                 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
5122                 ptr->timer = 0;
5123         }
5124         spin_unlock(&ccs_query_list_lock);
5125         if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
5126                 return -EINVAL;
5127         spin_lock(&ccs_query_list_lock);
5128         list_for_each(tmp, &ccs_query_list) {
5129                 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
5130                 if (ptr->serial != serial)
5131                         continue;
5132                 ptr->answer = (u8) answer;
5133                 /* Remove from ccs_query_list. */
5134                 if (ptr->answer) {
5135                         list_del(&ptr->list);
5136                         INIT_LIST_HEAD(&ptr->list);
5137                 }
5138                 break;
5139         }
5140         spin_unlock(&ccs_query_list_lock);
5141         wake_up_all(&ccs_answer_wait);
5142         return 0;
5143 }
5144 
5145 /**
5146  * ccs_read_version - Get version.
5147  *
5148  * @head: Pointer to "struct ccs_io_buffer".
5149  *
5150  * Returns nothing.
5151  */
5152 static void ccs_read_version(struct ccs_io_buffer *head)
5153 {
5154         if (head->r.eof)
5155                 return;
5156         ccs_set_string(head, "1.8.6");
5157         head->r.eof = true;
5158 }
5159 
5160 /**
5161  * ccs_update_stat - Update statistic counters.
5162  *
5163  * @index: Index for policy type.
5164  *
5165  * Returns nothing.
5166  */
5167 static void ccs_update_stat(const u8 index)
5168 {
5169 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
5170         struct timeval tv;
5171 #endif
5172 
5173         atomic_inc(&ccs_stat_updated[index]);
5174 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
5175         do_gettimeofday(&tv);
5176         ccs_stat_modified[index] = tv.tv_sec;
5177 #elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
5178         ccs_stat_modified[index] = get_seconds();
5179 #else
5180         ccs_stat_modified[index] = ktime_get_real_seconds();
5181 #endif
5182 }
5183 
5184 /**
5185  * ccs_read_stat - Read statistic data.
5186  *
5187  * @head: Pointer to "struct ccs_io_buffer".
5188  *
5189  * Returns nothing.
5190  */
5191 static void ccs_read_stat(struct ccs_io_buffer *head)
5192 {
5193         u8 i;
5194         unsigned int total = 0;
5195         if (head->r.eof)
5196                 return;
5197         for (i = 0; i < CCS_MAX_POLICY_STAT; i++) {
5198                 ccs_io_printf(head, "Policy %-30s %10u", ccs_policy_headers[i],
5199                               atomic_read(&ccs_stat_updated[i]));
5200                 if (ccs_stat_modified[i]) {
5201                         struct ccs_time stamp;
5202                         ccs_convert_time(ccs_stat_modified[i], &stamp);
5203                         ccs_io_printf(head, " (Last: %04u/%02u/%02u "
5204                                       "%02u:%02u:%02u)",
5205                                       stamp.year, stamp.month, stamp.day,
5206                                       stamp.hour, stamp.min, stamp.sec);
5207                 }
5208                 ccs_set_lf(head);
5209         }
5210         for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) {
5211                 unsigned int used = ccs_memory_used[i];
5212                 total += used;
5213                 ccs_io_printf(head, "Memory used by %-22s %10u",
5214                               ccs_memory_headers[i], used);
5215                 used = ccs_memory_quota[i];
5216                 if (used)
5217                         ccs_io_printf(head, " (Quota: %10u)", used);
5218                 ccs_set_lf(head);
5219         }
5220         ccs_io_printf(head, "Total memory used:                    %10u\n",
5221                       total);
5222         head->r.eof = true;
5223 }
5224 
5225 /**
5226  * ccs_write_stat - Set memory quota.
5227  *
5228  * @head: Pointer to "struct ccs_io_buffer".
5229  *
5230  * Returns 0.
5231  */
5232 static int ccs_write_stat(struct ccs_io_buffer *head)
5233 {
5234         char *data = head->write_buf;
5235         u8 i;
5236         if (ccs_str_starts(&data, "Memory used by "))
5237                 for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
5238                         if (ccs_str_starts(&data, ccs_memory_headers[i])) {
5239                                 if (*data == ' ')
5240                                         data++;
5241                                 ccs_memory_quota[i] =
5242                                         simple_strtoul(data, NULL, 10);
5243                         }
5244         return 0;
5245 }
5246 
5247 /**
5248  * ccs_print_bprm - Print "struct linux_binprm" for auditing.
5249  *
5250  * @bprm: Pointer to "struct linux_binprm".
5251  * @dump: Pointer to "struct ccs_page_dump".
5252  *
5253  * Returns the contents of @bprm on success, NULL otherwise.
5254  *
5255  * This function uses kzalloc(), so caller must kfree() if this function
5256  * didn't return NULL.
5257  */
5258 static char *ccs_print_bprm(struct linux_binprm *bprm,
5259                             struct ccs_page_dump *dump)
5260 {
5261         static const int ccs_buffer_len = 4096 * 2;
5262         char *buffer = kzalloc(ccs_buffer_len, CCS_GFP_FLAGS);
5263         char *cp;
5264         char *last_start;
5265         int len;
5266         unsigned long pos = bprm->p;
5267         int offset = pos % PAGE_SIZE;
5268         int argv_count = bprm->argc;
5269         int envp_count = bprm->envc;
5270         bool truncated = false;
5271         if (!buffer)
5272                 return NULL;
5273         len = snprintf(buffer, ccs_buffer_len - 1, "argv[]={ ");
5274         cp = buffer + len;
5275         if (!argv_count) {
5276                 memmove(cp, "} envp[]={ ", 11);
5277                 cp += 11;
5278         }
5279         last_start = cp;
5280         while (argv_count || envp_count) {
5281                 if (!ccs_dump_page(bprm, pos, dump))
5282                         goto out;
5283                 pos += PAGE_SIZE - offset;
5284                 /* Read. */
5285                 while (offset < P