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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6388 - (hide annotations) (download) (as text)
Wed Apr 8 07:35:53 2015 UTC (9 years, 1 month ago) by kumaneko
File MIME type: text/x-csrc
File size: 177120 byte(s)
Fix incorrect readdir() permission check.
1 kumaneko 2863 /*
2 kumaneko 2864 * security/ccsecurity/policy_io.c
3 kumaneko 2863 *
4 kumaneko 5771 * Copyright (C) 2005-2012 NTT DATA CORPORATION
5 kumaneko 2863 *
6 kumaneko 6388 * Version: 1.8.3+ 2015/04/08
7 kumaneko 2863 */
8    
9     #include "internal.h"
10    
11 kumaneko 5594 /***** SECTION1: Constants definition *****/
12 kumaneko 4082
13 kumaneko 5594 /* Define this to enable debug mode. */
14     /* #define DEBUG_CONDITION */
15 kumaneko 4082
16 kumaneko 5594 #ifdef DEBUG_CONDITION
17     #define dprintk printk
18     #else
19     #define dprintk(...) do { } while (0)
20 kumaneko 4082 #endif
21    
22 kumaneko 5618 /* 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 kumaneko 5619 #ifdef CONFIG_CCSECURITY_FILE_GETATTR
30 kumaneko 5618 [CCS_MAC_FILE_GETATTR] = CCS_MAC_CATEGORY_FILE,
31 kumaneko 5619 #endif
32 kumaneko 5618 [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 kumaneko 5623 #ifdef CONFIG_CCSECURITY_MISC
51 kumaneko 5618 /* CONFIG::misc group */
52     [CCS_MAC_ENVIRON] = CCS_MAC_CATEGORY_MISC,
53 kumaneko 5623 #endif
54 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK
55 kumaneko 5618 /* 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 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
63 kumaneko 5618 [CCS_MAC_NETWORK_INET_DGRAM_RECV] = CCS_MAC_CATEGORY_NETWORK,
64 kumaneko 5619 #endif
65 kumaneko 5618 [CCS_MAC_NETWORK_INET_RAW_BIND] = CCS_MAC_CATEGORY_NETWORK,
66     [CCS_MAC_NETWORK_INET_RAW_SEND] = CCS_MAC_CATEGORY_NETWORK,
67 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
68 kumaneko 5618 [CCS_MAC_NETWORK_INET_RAW_RECV] = CCS_MAC_CATEGORY_NETWORK,
69 kumaneko 5619 #endif
70 kumaneko 5618 [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 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
77 kumaneko 5618 [CCS_MAC_NETWORK_UNIX_DGRAM_RECV] = CCS_MAC_CATEGORY_NETWORK,
78 kumaneko 5619 #endif
79 kumaneko 5618 [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 kumaneko 5619 #endif
84     #ifdef CONFIG_CCSECURITY_IPC
85 kumaneko 5618 /* CONFIG::ipc group */
86     [CCS_MAC_SIGNAL] = CCS_MAC_CATEGORY_IPC,
87 kumaneko 5619 #endif
88     #ifdef CONFIG_CCSECURITY_CAPABILITY
89 kumaneko 5618 /* 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 kumaneko 5619 #endif
101 kumaneko 5618 };
102    
103 kumaneko 4063 /* String table for operation mode. */
104 kumaneko 5597 static const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {
105 kumaneko 3968 [CCS_CONFIG_DISABLED] = "disabled",
106     [CCS_CONFIG_LEARNING] = "learning",
107 kumaneko 3748 [CCS_CONFIG_PERMISSIVE] = "permissive",
108 kumaneko 3968 [CCS_CONFIG_ENFORCING] = "enforcing"
109 kumaneko 2863 };
110 kumaneko 2915
111 kumaneko 4063 /* String table for /proc/ccs/profile interface. */
112 kumaneko 5686 static const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX
113     + CCS_MAX_MAC_CATEGORY_INDEX] = {
114 kumaneko 4063 /* CONFIG::file group */
115 kumaneko 3968 [CCS_MAC_FILE_EXECUTE] = "execute",
116     [CCS_MAC_FILE_OPEN] = "open",
117     [CCS_MAC_FILE_CREATE] = "create",
118     [CCS_MAC_FILE_UNLINK] = "unlink",
119 kumaneko 5619 #ifdef CONFIG_CCSECURITY_FILE_GETATTR
120 kumaneko 4080 [CCS_MAC_FILE_GETATTR] = "getattr",
121 kumaneko 5619 #endif
122 kumaneko 3968 [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 kumaneko 4049 [CCS_MAC_FILE_CHOWN] = "chown",
134 kumaneko 3968 [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 kumaneko 5623 #ifdef CONFIG_CCSECURITY_MISC
141 kumaneko 4063 /* CONFIG::misc group */
142 kumaneko 3968 [CCS_MAC_ENVIRON] = "env",
143 kumaneko 5623 #endif
144 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK
145 kumaneko 4063 /* CONFIG::network group */
146 kumaneko 3968 [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 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
153 kumaneko 3968 [CCS_MAC_NETWORK_INET_DGRAM_RECV] = "inet_dgram_recv",
154 kumaneko 5619 #endif
155 kumaneko 3968 [CCS_MAC_NETWORK_INET_RAW_BIND] = "inet_raw_bind",
156     [CCS_MAC_NETWORK_INET_RAW_SEND] = "inet_raw_send",
157 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
158 kumaneko 3968 [CCS_MAC_NETWORK_INET_RAW_RECV] = "inet_raw_recv",
159 kumaneko 5619 #endif
160 kumaneko 3968 [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 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
167 kumaneko 3968 [CCS_MAC_NETWORK_UNIX_DGRAM_RECV] = "unix_dgram_recv",
168 kumaneko 5619 #endif
169 kumaneko 3968 [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 kumaneko 5619 #endif
174     #ifdef CONFIG_CCSECURITY_IPC
175 kumaneko 4063 /* CONFIG::ipc group */
176 kumaneko 3968 [CCS_MAC_SIGNAL] = "signal",
177 kumaneko 5619 #endif
178     #ifdef CONFIG_CCSECURITY_CAPABILITY
179 kumaneko 4063 /* CONFIG::capability group */
180 kumaneko 3968 [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 kumaneko 5619 #endif
191 kumaneko 4063 /* CONFIG group */
192 kumaneko 3968 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_FILE] = "file",
193 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK
194 kumaneko 3968 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_NETWORK] = "network",
195 kumaneko 5619 #endif
196 kumaneko 5623 #ifdef CONFIG_CCSECURITY_MISC
197 kumaneko 3968 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_MISC] = "misc",
198 kumaneko 5623 #endif
199 kumaneko 5619 #ifdef CONFIG_CCSECURITY_IPC
200 kumaneko 3968 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_IPC] = "ipc",
201 kumaneko 5619 #endif
202     #ifdef CONFIG_CCSECURITY_CAPABILITY
203 kumaneko 3968 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
204 kumaneko 5619 #endif
205 kumaneko 2915 };
206    
207 kumaneko 4063 /* String table for path operation. */
208 kumaneko 5686 static const char * const ccs_path_keyword[CCS_MAX_PATH_OPERATION] = {
209 kumaneko 3968 [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 kumaneko 5619 #ifdef CONFIG_CCSECURITY_FILE_GETATTR
215 kumaneko 4080 [CCS_TYPE_GETATTR] = "getattr",
216 kumaneko 5619 #endif
217 kumaneko 3968 [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 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK
225 kumaneko 5686
226 kumaneko 5106 /* String table for socket's operation. */
227 kumaneko 5686 static const char * const ccs_socket_keyword[CCS_MAX_NETWORK_OPERATION] = {
228 kumaneko 5106 [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 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
234 kumaneko 5106 [CCS_NETWORK_RECV] = "recv",
235 kumaneko 5619 #endif
236 kumaneko 5106 };
237 kumaneko 5686
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 kumaneko 5619 #endif
249 kumaneko 5106
250 kumaneko 4063 /* String table for categories. */
251 kumaneko 3968 static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {
252     [CCS_MAC_CATEGORY_FILE] = "file",
253 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK
254 kumaneko 3968 [CCS_MAC_CATEGORY_NETWORK] = "network",
255 kumaneko 5619 #endif
256 kumaneko 5623 #ifdef CONFIG_CCSECURITY_MISC
257 kumaneko 3968 [CCS_MAC_CATEGORY_MISC] = "misc",
258 kumaneko 5623 #endif
259 kumaneko 5619 #ifdef CONFIG_CCSECURITY_IPC
260 kumaneko 3968 [CCS_MAC_CATEGORY_IPC] = "ipc",
261 kumaneko 5619 #endif
262     #ifdef CONFIG_CCSECURITY_CAPABILITY
263 kumaneko 3968 [CCS_MAC_CATEGORY_CAPABILITY] = "capability",
264 kumaneko 5619 #endif
265 kumaneko 3968 };
266    
267 kumaneko 4063 /* String table for conditions. */
268 kumaneko 5597 static const char * const ccs_condition_keyword[CCS_MAX_CONDITION_KEYWORD] = {
269 kumaneko 3968 [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 kumaneko 4063 /* String table for PREFERENCE keyword. */
333 kumaneko 4049 static const char * const ccs_pref_keywords[CCS_MAX_PREF] = {
334 kumaneko 4170 [CCS_PREF_MAX_AUDIT_LOG] = "max_audit_log",
335 kumaneko 4049 [CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
336     [CCS_PREF_ENFORCING_PENALTY] = "enforcing_penalty",
337     };
338    
339 kumaneko 5594 /* 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 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK
360 kumaneko 5594 [CCS_ADDRESS_GROUP] = "address_group ",
361 kumaneko 5619 #endif
362 kumaneko 5594 };
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 kumaneko 5595 struct iattr;
382    
383 kumaneko 5594 /* 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 kumaneko 5597 /* Structure for audit log. */
396     struct ccs_log {
397     struct list_head list;
398     char *log;
399     int size;
400     };
401    
402 kumaneko 5594 /***** SECTION3: Prototype definition section *****/
403    
404 kumaneko 5686 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 kumaneko 5618 u8 ccs_get_config(const u8 profile, const u8 index);
408 kumaneko 5597 void ccs_transition_failed(const char *domainname);
409     void ccs_write_log(struct ccs_request_info *r, const char *fmt, ...);
410 kumaneko 5594
411 kumaneko 5618 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 kumaneko 5596 static bool ccs_domain_quota_ok(struct ccs_request_info *r);
417 kumaneko 5595 static bool ccs_flush(struct ccs_io_buffer *head);
418 kumaneko 5686 static bool ccs_get_audit(const struct ccs_request_info *r);
419 kumaneko 5595 static bool ccs_has_more_namespace(struct ccs_io_buffer *head);
420     static bool ccs_manager(void);
421 kumaneko 5618 static bool ccs_namespace_jump(const char *domainname);
422 kumaneko 5595 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 kumaneko 5596 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 kumaneko 5686 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 kumaneko 5595 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 kumaneko 5596 static bool ccs_same_condition(const struct ccs_condition *a,
441     const struct ccs_condition *b);
442 kumaneko 5595 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 kumaneko 5596 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 kumaneko 5686 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 kumaneko 5596 static const struct ccs_path_info *ccs_get_domainname
455     (struct ccs_acl_param *param);
456 kumaneko 5594 static const struct ccs_path_info *ccs_get_dqword(char *start);
457 kumaneko 5595 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 kumaneko 5596 static int ccs_set_mode(char *name, const char *value,
463     struct ccs_profile *profile);
464 kumaneko 5686 static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
465     __printf(2, 3);
466 kumaneko 5595 static int ccs_truncate(char *str);
467 kumaneko 5686 static int ccs_update_acl(const int size, struct ccs_acl_param *param);
468 kumaneko 5595 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 kumaneko 5686 static int ccs_write_acl(struct ccs_policy_namespace *ns,
471     struct list_head *list, char *data,
472     const bool is_delete);
473 kumaneko 5595 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 kumaneko 5596 static int ccs_write_transition_control(struct ccs_acl_param *param,
485     const u8 type);
486 kumaneko 5595 static s8 ccs_find_yesno(const char *string, const char *find);
487 kumaneko 5596 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 kumaneko 5594 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 kumaneko 5618 static struct ccs_domain_info *ccs_find_domain(const char *domainname);
496 kumaneko 5595 static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial);
497 kumaneko 5597 static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
498     const u8 idx);
499 kumaneko 5618 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 kumaneko 5596 static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
504     const unsigned int profile);
505 kumaneko 5618 static struct ccs_profile *ccs_profile(const u8 profile);
506 kumaneko 5595 static u8 ccs_condition_type(const char *word);
507 kumaneko 5618 static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3);
508 kumaneko 5596 static u8 ccs_parse_ulong(unsigned long *result, char **str);
509 kumaneko 5595 static unsigned int ccs_poll(struct file *file, poll_table *wait);
510 kumaneko 5771 static void __init ccs_create_entry(const char *name, const umode_t mode,
511 kumaneko 5596 struct proc_dir_entry *parent,
512     const u8 key);
513 kumaneko 5595 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 kumaneko 5596 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
518 kumaneko 5597 __printf(3, 4);
519 kumaneko 5594 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...);
520 kumaneko 5595 static void ccs_check_profile(void);
521 kumaneko 5618 static void ccs_convert_time(time_t time, struct ccs_time *stamp);
522     static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns);
523 kumaneko 5596 static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
524 kumaneko 5597 __printf(2, 3);
525 kumaneko 5618 static void ccs_normalize_line(unsigned char *buffer);
526 kumaneko 5594 static void ccs_print_config(struct ccs_io_buffer *head, const u8 config);
527 kumaneko 5596 static void ccs_print_name_union(struct ccs_io_buffer *head,
528     const struct ccs_name_union *ptr);
529     static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
530     const struct ccs_name_union *ptr);
531 kumaneko 5595 static void ccs_print_namespace(struct ccs_io_buffer *head);
532 kumaneko 5596 static void ccs_print_number_union(struct ccs_io_buffer *head,
533     const struct ccs_number_union *ptr);
534     static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
535     const struct ccs_number_union *ptr);
536 kumaneko 5594 static void ccs_read_domain(struct ccs_io_buffer *head);
537 kumaneko 5595 static void ccs_read_exception(struct ccs_io_buffer *head);
538 kumaneko 5686 static void ccs_read_log(struct ccs_io_buffer *head);
539 kumaneko 5595 static void ccs_read_manager(struct ccs_io_buffer *head);
540 kumaneko 5594 static void ccs_read_pid(struct ccs_io_buffer *head);
541 kumaneko 5595 static void ccs_read_profile(struct ccs_io_buffer *head);
542 kumaneko 5594 static void ccs_read_query(struct ccs_io_buffer *head);
543 kumaneko 5595 static void ccs_read_stat(struct ccs_io_buffer *head);
544 kumaneko 5594 static void ccs_read_version(struct ccs_io_buffer *head);
545 kumaneko 5595 static void ccs_set_group(struct ccs_io_buffer *head, const char *category);
546 kumaneko 5594 static void ccs_set_namespace_cursor(struct ccs_io_buffer *head);
547 kumaneko 5595 static void ccs_set_slash(struct ccs_io_buffer *head);
548     static void ccs_set_space(struct ccs_io_buffer *head);
549     static void ccs_set_string(struct ccs_io_buffer *head, const char *string);
550 kumaneko 5596 static void ccs_set_uint(unsigned int *i, const char *string,
551     const char *find);
552 kumaneko 5618 static void ccs_update_stat(const u8 index);
553 kumaneko 5686 static void ccs_update_task_domain(struct ccs_request_info *r);
554     static void ccs_write_log2(struct ccs_request_info *r, int len,
555     const char *fmt, va_list args);
556 kumaneko 5594
557 kumaneko 5622 #ifdef CONFIG_CCSECURITY_PORTRESERVE
558     static bool __ccs_lport_reserved(const u16 port);
559     static int ccs_write_reserved_port(struct ccs_acl_param *param);
560     #endif
561    
562     #ifdef CONFIG_CCSECURITY_NETWORK
563     static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
564     struct ccs_ipaddr_union *ptr);
565 kumaneko 5686 static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
566     const u32 *ip);
567     static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
568     const struct in6_addr *ip);
569 kumaneko 5622 static int ccs_write_inet_network(struct ccs_acl_param *param);
570     static int ccs_write_unix_network(struct ccs_acl_param *param);
571     static void ccs_print_ip(char *buf, const unsigned int size,
572     const struct ccs_ipaddr_union *ptr);
573     #endif
574    
575     #ifdef CONFIG_CCSECURITY_CAPABILITY
576     static int ccs_write_capability(struct ccs_acl_param *param);
577     #endif
578    
579 kumaneko 5623 #ifdef CONFIG_CCSECURITY_MISC
580     static int ccs_write_misc(struct ccs_acl_param *param);
581     #endif
582    
583 kumaneko 5622 #ifdef CONFIG_CCSECURITY_IPC
584     static int ccs_write_ipc(struct ccs_acl_param *param);
585     #endif
586    
587 kumaneko 5623 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
588     static ssize_t ccs_write_self(struct file *file, const char __user *buf,
589     size_t count, loff_t *ppos);
590     #endif
591    
592 kumaneko 5594 /***** SECTION4: Standalone functions section *****/
593    
594 kumaneko 5597 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
595    
596     /**
597     * fatal_signal_pending - Check whether SIGKILL is pending or not.
598     *
599     * @p: Pointer to "struct task_struct".
600     *
601     * Returns true if SIGKILL is pending on @p, false otherwise.
602     *
603     * This is for compatibility with older kernels.
604     */
605     #define fatal_signal_pending(p) (signal_pending(p) && \
606     sigismember(&p->pending.signal, SIGKILL))
607    
608     #endif
609    
610 kumaneko 5594 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
611    
612     /**
613     * __wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
614     *
615     * @wq: The waitqueue to wait on.
616     * @condition: A C expression for the event to wait for.
617     * @ret: Timeout, in jiffies.
618     *
619     * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
620     * signal, and the remaining jiffies otherwise if the condition evaluated to
621     * true before the timeout elapsed.
622     *
623     * This is for compatibility with older kernels.
624     */
625     #define __wait_event_interruptible_timeout(wq, condition, ret) \
626     do { \
627     wait_queue_t __wait; \
628     init_waitqueue_entry(&__wait, current); \
629     \
630     add_wait_queue(&wq, &__wait); \
631     for (;;) { \
632     set_current_state(TASK_INTERRUPTIBLE); \
633     if (condition) \
634     break; \
635     if (!signal_pending(current)) { \
636     ret = schedule_timeout(ret); \
637     if (!ret) \
638     break; \
639     continue; \
640     } \
641     ret = -ERESTARTSYS; \
642     break; \
643     } \
644     current->state = TASK_RUNNING; \
645     remove_wait_queue(&wq, &__wait); \
646     } while (0)
647    
648     /**
649     * wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
650     *
651     * @wq: The waitqueue to wait on.
652     * @condition: A C expression for the event to wait for.
653     * @timeout: Timeout, in jiffies.
654     *
655     * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
656     * signal, and the remaining jiffies otherwise if the condition evaluated to
657     * true before the timeout elapsed.
658     *
659     * This is for compatibility with older kernels.
660     */
661     #define wait_event_interruptible_timeout(wq, condition, timeout) \
662     ({ \
663     long __ret = timeout; \
664     if (!(condition)) \
665     __wait_event_interruptible_timeout(wq, condition, __ret); \
666     __ret; \
667     })
668    
669     #endif
670    
671 kumaneko 5618 /**
672     * ccs_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
673     *
674     * @time: Seconds since 1970/01/01 00:00:00.
675     * @stamp: Pointer to "struct ccs_time".
676     *
677     * Returns nothing.
678     *
679     * This function does not handle Y2038 problem.
680     */
681     static void ccs_convert_time(time_t time, struct ccs_time *stamp)
682     {
683     static const u16 ccs_eom[2][12] = {
684     { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
685     { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
686     };
687     u16 y;
688     u8 m;
689     bool r;
690     stamp->sec = time % 60;
691     time /= 60;
692     stamp->min = time % 60;
693     time /= 60;
694     stamp->hour = time % 24;
695     time /= 24;
696     for (y = 1970; ; y++) {
697     const unsigned short days = (y & 3) ? 365 : 366;
698     if (time < days)
699     break;
700     time -= days;
701     }
702     r = (y & 3) == 0;
703     for (m = 0; m < 11 && time >= ccs_eom[r][m]; m++);
704     if (m)
705     time -= ccs_eom[r][m - 1];
706     stamp->year = y;
707     stamp->month = ++m;
708     stamp->day = ++time;
709     }
710    
711 kumaneko 5595 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 23)
712     #if !defined(RHEL_VERSION) || RHEL_VERSION != 3
713    
714     /**
715     * PDE - Get "struct proc_dir_entry".
716     *
717     * @inode: Pointer to "struct inode".
718     *
719     * Returns pointer to "struct proc_dir_entry".
720     *
721     * This is for compatibility with older kernels.
722     */
723     static inline struct proc_dir_entry *PDE(const struct inode *inode)
724     {
725     return (struct proc_dir_entry *) inode->u.generic_ip;
726     }
727    
728     #endif
729     #endif
730    
731     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
732    
733     /**
734     * proc_notify_change - Update inode's attributes and reflect to the dentry.
735     *
736     * @dentry: Pointer to "struct dentry".
737     * @iattr: Pointer to "struct iattr".
738     *
739     * Returns 0 on success, negative value otherwise.
740     *
741     * The 2.4 kernels don't allow chmod()/chown() for files in /proc,
742     * while the 2.6 kernels allow.
743     * To permit management of /proc/ccs/ interface by non-root user,
744     * I modified to allow chmod()/chown() of /proc/ccs/ interface like 2.6 kernels
745     * by adding "struct inode_operations"->setattr hook.
746     */
747     static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
748     {
749     struct inode *inode = dentry->d_inode;
750     struct proc_dir_entry *de = PDE(inode);
751     int error;
752    
753     error = inode_change_ok(inode, iattr);
754     if (error)
755     goto out;
756    
757     error = inode_setattr(inode, iattr);
758     if (error)
759     goto out;
760    
761     de->uid = inode->i_uid;
762     de->gid = inode->i_gid;
763     de->mode = inode->i_mode;
764     out:
765     return error;
766     }
767    
768     #endif
769    
770 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK
771    
772 kumaneko 5594 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && defined(CONFIG_NET)
773     #define ccs_in4_pton in4_pton
774     #define ccs_in6_pton in6_pton
775     #else
776     /*
777     * Routines for parsing IPv4 or IPv6 address.
778     * These are copied from lib/hexdump.c net/core/utils.c .
779     */
780     #include <linux/ctype.h>
781    
782     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
783     static int hex_to_bin(char ch)
784     {
785     if ((ch >= '0') && (ch <= '9'))
786     return ch - '0';
787     ch = tolower(ch);
788     if ((ch >= 'a') && (ch <= 'f'))
789     return ch - 'a' + 10;
790     return -1;
791     }
792     #endif
793    
794     #define IN6PTON_XDIGIT 0x00010000
795     #define IN6PTON_DIGIT 0x00020000
796     #define IN6PTON_COLON_MASK 0x00700000
797     #define IN6PTON_COLON_1 0x00100000 /* single : requested */
798     #define IN6PTON_COLON_2 0x00200000 /* second : requested */
799     #define IN6PTON_COLON_1_2 0x00400000 /* :: requested */
800     #define IN6PTON_DOT 0x00800000 /* . */
801     #define IN6PTON_DELIM 0x10000000
802     #define IN6PTON_NULL 0x20000000 /* first/tail */
803     #define IN6PTON_UNKNOWN 0x40000000
804    
805     static inline int xdigit2bin(char c, int delim)
806     {
807     int val;
808    
809     if (c == delim || c == '\0')
810     return IN6PTON_DELIM;
811     if (c == ':')
812     return IN6PTON_COLON_MASK;
813     if (c == '.')
814     return IN6PTON_DOT;
815    
816     val = hex_to_bin(c);
817     if (val >= 0)
818     return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0);
819    
820     if (delim == -1)
821     return IN6PTON_DELIM;
822     return IN6PTON_UNKNOWN;
823     }
824    
825     static int ccs_in4_pton(const char *src, int srclen, u8 *dst, int delim,
826     const char **end)
827     {
828     const char *s;
829     u8 *d;
830     u8 dbuf[4];
831     int ret = 0;
832     int i;
833     int w = 0;
834    
835     if (srclen < 0)
836     srclen = strlen(src);
837     s = src;
838     d = dbuf;
839     i = 0;
840     while (1) {
841     int c;
842     c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
843     if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM |
844     IN6PTON_COLON_MASK)))
845     goto out;
846     if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
847     if (w == 0)
848     goto out;
849     *d++ = w & 0xff;
850     w = 0;
851     i++;
852     if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
853     if (i != 4)
854     goto out;
855     break;
856     }
857     goto cont;
858     }
859     w = (w * 10) + c;
860     if ((w & 0xffff) > 255)
861     goto out;
862     cont:
863     if (i >= 4)
864     goto out;
865     s++;
866     srclen--;
867     }
868     ret = 1;
869     memcpy(dst, dbuf, sizeof(dbuf));
870     out:
871     if (end)
872     *end = s;
873     return ret;
874     }
875    
876     static int ccs_in6_pton(const char *src, int srclen, u8 *dst, int delim,
877     const char **end)
878     {
879     const char *s, *tok = NULL;
880     u8 *d, *dc = NULL;
881     u8 dbuf[16];
882     int ret = 0;
883     int i;
884     int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL;
885     int w = 0;
886    
887     memset(dbuf, 0, sizeof(dbuf));
888    
889     s = src;
890     d = dbuf;
891     if (srclen < 0)
892     srclen = strlen(src);
893    
894     while (1) {
895     int c;
896    
897     c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
898     if (!(c & state))
899     goto out;
900     if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
901     /* process one 16-bit word */
902     if (!(state & IN6PTON_NULL)) {
903     *d++ = (w >> 8) & 0xff;
904     *d++ = w & 0xff;
905     }
906     w = 0;
907     if (c & IN6PTON_DELIM) {
908     /* We've processed last word */
909     break;
910     }
911     /*
912     * COLON_1 => XDIGIT
913     * COLON_2 => XDIGIT|DELIM
914     * COLON_1_2 => COLON_2
915     */
916     switch (state & IN6PTON_COLON_MASK) {
917     case IN6PTON_COLON_2:
918     dc = d;
919     state = IN6PTON_XDIGIT | IN6PTON_DELIM;
920     if (dc - dbuf >= sizeof(dbuf))
921     state |= IN6PTON_NULL;
922     break;
923     case IN6PTON_COLON_1|IN6PTON_COLON_1_2:
924     state = IN6PTON_XDIGIT | IN6PTON_COLON_2;
925     break;
926     case IN6PTON_COLON_1:
927     state = IN6PTON_XDIGIT;
928     break;
929     case IN6PTON_COLON_1_2:
930     state = IN6PTON_COLON_2;
931     break;
932     default:
933     state = 0;
934     }
935     tok = s + 1;
936     goto cont;
937     }
938    
939     if (c & IN6PTON_DOT) {
940     ret = ccs_in4_pton(tok ? tok : s, srclen +
941     (int)(s - tok), d, delim, &s);
942     if (ret > 0) {
943     d += 4;
944     break;
945     }
946     goto out;
947     }
948    
949     w = (w << 4) | (0xff & c);
950     state = IN6PTON_COLON_1 | IN6PTON_DELIM;
951     if (!(w & 0xf000))
952     state |= IN6PTON_XDIGIT;
953     if (!dc && d + 2 < dbuf + sizeof(dbuf)) {
954     state |= IN6PTON_COLON_1_2;
955     state &= ~IN6PTON_DELIM;
956     }
957     if (d + 2 >= dbuf + sizeof(dbuf))
958     state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2);
959     cont:
960     if ((dc && d + 4 < dbuf + sizeof(dbuf)) ||
961     d + 4 == dbuf + sizeof(dbuf))
962     state |= IN6PTON_DOT;
963     if (d >= dbuf + sizeof(dbuf))
964     state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK);
965     s++;
966     srclen--;
967     }
968    
969     i = 15; d--;
970    
971     if (dc) {
972     while (d >= dc)
973     dst[i--] = *d--;
974     while (i >= dc - dbuf)
975     dst[i--] = 0;
976     while (i >= 0)
977     dst[i--] = *d--;
978     } else
979     memcpy(dst, dbuf, sizeof(dbuf));
980    
981     ret = 1;
982     out:
983     if (end)
984     *end = s;
985     return ret;
986     }
987     #endif
988    
989     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
990    
991     /*
992     * Routines for printing IPv4 or IPv6 address.
993     * These are copied from include/linux/kernel.h include/net/ipv6.h
994     * include/net/addrconf.h lib/hexdump.c lib/vsprintf.c and simplified.
995     */
996     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
997 kumaneko 6183 #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5 || !defined(RHEL_MINOR) || RHEL_MINOR < 9
998 kumaneko 5594 static const char hex_asc[] = "0123456789abcdef";
999     #define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
1000     #define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
1001    
1002     static inline char *pack_hex_byte(char *buf, u8 byte)
1003     {
1004     *buf++ = hex_asc_hi(byte);
1005     *buf++ = hex_asc_lo(byte);
1006     return buf;
1007     }
1008     #endif
1009 kumaneko 6179 #endif
1010 kumaneko 5594
1011     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1012     static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
1013     {
1014     return (a->s6_addr32[0] | a->s6_addr32[1] |
1015     (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0;
1016     }
1017     #endif
1018    
1019     static inline int ipv6_addr_is_isatap(const struct in6_addr *addr)
1020     {
1021     return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
1022     }
1023    
1024     static char *ip4_string(char *p, const u8 *addr)
1025     {
1026     /*
1027     * Since this function is called outside vsnprintf(), I can use
1028     * sprintf() here.
1029     */
1030     return p +
1031     sprintf(p, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
1032     }
1033    
1034     static char *ip6_compressed_string(char *p, const char *addr)
1035     {
1036     int i, j, range;
1037     unsigned char zerolength[8];
1038     int longest = 1;
1039     int colonpos = -1;
1040     u16 word;
1041     u8 hi, lo;
1042     bool needcolon = false;
1043     bool useIPv4;
1044     struct in6_addr in6;
1045    
1046     memcpy(&in6, addr, sizeof(struct in6_addr));
1047    
1048     useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
1049    
1050     memset(zerolength, 0, sizeof(zerolength));
1051    
1052     if (useIPv4)
1053     range = 6;
1054     else
1055     range = 8;
1056    
1057     /* find position of longest 0 run */
1058     for (i = 0; i < range; i++) {
1059     for (j = i; j < range; j++) {
1060     if (in6.s6_addr16[j] != 0)
1061     break;
1062     zerolength[i]++;
1063     }
1064     }
1065     for (i = 0; i < range; i++) {
1066     if (zerolength[i] > longest) {
1067     longest = zerolength[i];
1068     colonpos = i;
1069     }
1070     }
1071     if (longest == 1) /* don't compress a single 0 */
1072     colonpos = -1;
1073    
1074     /* emit address */
1075     for (i = 0; i < range; i++) {
1076     if (i == colonpos) {
1077     if (needcolon || i == 0)
1078     *p++ = ':';
1079     *p++ = ':';
1080     needcolon = false;
1081     i += longest - 1;
1082     continue;
1083     }
1084     if (needcolon) {
1085     *p++ = ':';
1086     needcolon = false;
1087     }
1088     /* hex u16 without leading 0s */
1089     word = ntohs(in6.s6_addr16[i]);
1090     hi = word >> 8;
1091     lo = word & 0xff;
1092     if (hi) {
1093     if (hi > 0x0f)
1094     p = pack_hex_byte(p, hi);
1095     else
1096     *p++ = hex_asc_lo(hi);
1097     p = pack_hex_byte(p, lo);
1098     } else if (lo > 0x0f)
1099     p = pack_hex_byte(p, lo);
1100     else
1101     *p++ = hex_asc_lo(lo);
1102     needcolon = true;
1103     }
1104    
1105     if (useIPv4) {
1106     if (needcolon)
1107     *p++ = ':';
1108     p = ip4_string(p, &in6.s6_addr[12]);
1109     }
1110     *p = '\0';
1111    
1112     return p;
1113     }
1114     #endif
1115    
1116     /**
1117     * ccs_print_ipv4 - Print an IPv4 address.
1118     *
1119     * @buffer: Buffer to write to.
1120     * @buffer_len: Size of @buffer.
1121     * @ip: Pointer to "u32 in network byte order".
1122     *
1123     * Returns written length.
1124     */
1125 kumaneko 5686 static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
1126     const u32 *ip)
1127 kumaneko 5594 {
1128     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
1129     return snprintf(buffer, buffer_len, "%pI4", ip);
1130     #else
1131     char addr[sizeof("255.255.255.255")];
1132     ip4_string(addr, (const u8 *) ip);
1133     return snprintf(buffer, buffer_len, "%s", addr);
1134     #endif
1135     }
1136    
1137     /**
1138     * ccs_print_ipv6 - Print an IPv6 address.
1139     *
1140     * @buffer: Buffer to write to.
1141     * @buffer_len: Size of @buffer.
1142     * @ip: Pointer to "struct in6_addr".
1143     *
1144     * Returns written length.
1145     */
1146 kumaneko 5686 static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
1147     const struct in6_addr *ip)
1148 kumaneko 5594 {
1149     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
1150     return snprintf(buffer, buffer_len, "%pI6c", ip);
1151     #else
1152     char addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
1153     ip6_compressed_string(addr, (const u8 *) ip);
1154     return snprintf(buffer, buffer_len, "%s", addr);
1155     #endif
1156     }
1157    
1158 kumaneko 5686 /**
1159     * ccs_print_ip - Print an IP address.
1160     *
1161     * @buf: Buffer to write to.
1162     * @size: Size of @buf.
1163     * @ptr: Pointer to "struct ipaddr_union".
1164     *
1165     * Returns nothing.
1166     */
1167     static void ccs_print_ip(char *buf, const unsigned int size,
1168     const struct ccs_ipaddr_union *ptr)
1169     {
1170     int len;
1171     if (ptr->is_ipv6)
1172     len = ccs_print_ipv6(buf, size, &ptr->ip[0]);
1173     else
1174     len = ccs_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0]);
1175     if (!memcmp(&ptr->ip[0], &ptr->ip[1], 16) || len >= size / 2)
1176     return;
1177     buf[len++] = '-';
1178     if (ptr->is_ipv6)
1179     ccs_print_ipv6(buf + len, size - len, &ptr->ip[1]);
1180     else
1181     ccs_print_ipv4(buf + len, size - len,
1182     &ptr->ip[1].s6_addr32[0]);
1183     }
1184    
1185 kumaneko 5619 #endif
1186    
1187 kumaneko 5594 /***** SECTION5: Variables definition section *****/
1188    
1189 kumaneko 2863 /* Permit policy management by non-root user? */
1190     static bool ccs_manage_by_non_root;
1191    
1192 kumaneko 5618 /* Lock for protecting policy. */
1193     DEFINE_MUTEX(ccs_policy_lock);
1194    
1195     /* Has /sbin/init started? */
1196     bool ccs_policy_loaded;
1197    
1198 kumaneko 5594 /* List of namespaces. */
1199     LIST_HEAD(ccs_namespace_list);
1200     /* True if namespace other than ccs_kernel_namespace is defined. */
1201     static bool ccs_namespace_enabled;
1202    
1203 kumaneko 5618 /* Initial namespace.*/
1204     static struct ccs_policy_namespace ccs_kernel_namespace;
1205    
1206     /* List of "struct ccs_condition". */
1207     LIST_HEAD(ccs_condition_list);
1208    
1209 kumaneko 5614 #ifdef CONFIG_CCSECURITY_PORTRESERVE
1210 kumaneko 5594 /* Bitmap for reserved local port numbers.*/
1211     static u8 ccs_reserved_port_map[8192];
1212 kumaneko 5614 #endif
1213 kumaneko 5594
1214     /* Wait queue for kernel -> userspace notification. */
1215     static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1216     /* Wait queue for userspace -> kernel notification. */
1217     static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);
1218    
1219     /* The list for "struct ccs_query". */
1220     static LIST_HEAD(ccs_query_list);
1221    
1222     /* Lock for manipulating ccs_query_list. */
1223     static DEFINE_SPINLOCK(ccs_query_list_lock);
1224    
1225     /* Number of "struct file" referring /proc/ccs/query interface. */
1226     static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1227    
1228 kumaneko 5597 /* Wait queue for /proc/ccs/audit. */
1229     static DECLARE_WAIT_QUEUE_HEAD(ccs_log_wait);
1230    
1231     /* The list for "struct ccs_log". */
1232     static LIST_HEAD(ccs_log);
1233    
1234     /* Lock for "struct list_head ccs_log". */
1235     static DEFINE_SPINLOCK(ccs_log_lock);
1236    
1237     /* Length of "stuct list_head ccs_log". */
1238     static unsigned int ccs_log_count;
1239    
1240 kumaneko 5594 /* Timestamp counter for last updated. */
1241     static unsigned int ccs_stat_updated[CCS_MAX_POLICY_STAT];
1242 kumaneko 5597
1243 kumaneko 5594 /* Counter for number of updates. */
1244     static unsigned int ccs_stat_modified[CCS_MAX_POLICY_STAT];
1245    
1246 kumaneko 5595 /* Operations for /proc/ccs/self_domain interface. */
1247     static
1248     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
1249     const
1250     #endif
1251     struct file_operations ccs_self_operations = {
1252 kumaneko 5623 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
1253 kumaneko 5595 .write = ccs_write_self,
1254 kumaneko 5623 #endif
1255 kumaneko 5595 .read = ccs_read_self,
1256     };
1257    
1258     /* Operations for /proc/ccs/ interface. */
1259     static
1260     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
1261     const
1262     #endif
1263     struct file_operations ccs_operations = {
1264     .open = ccs_open,
1265     .release = ccs_release,
1266     .poll = ccs_poll,
1267     .read = ccs_read,
1268     .write = ccs_write,
1269     };
1270    
1271     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
1272    
1273     /* The inode operations for /proc/ccs/ directory. */
1274     static struct inode_operations ccs_dir_inode_operations;
1275    
1276     /* The inode operations for files under /proc/ccs/ directory. */
1277     static struct inode_operations ccs_file_inode_operations;
1278    
1279     #endif
1280    
1281 kumaneko 5594 /***** SECTION6: Dependent functions section *****/
1282    
1283 kumaneko 2863 /**
1284 kumaneko 5594 * list_for_each_cookie - iterate over a list with cookie.
1285     *
1286     * @pos: Pointer to "struct list_head".
1287     * @head: Pointer to "struct list_head".
1288     */
1289     #define list_for_each_cookie(pos, head) \
1290     for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \
1291     pos != (head); pos = srcu_dereference(pos->next, &ccs_ss))
1292    
1293     /**
1294 kumaneko 5618 * ccs_read_token - Read a word from a line.
1295     *
1296     * @param: Pointer to "struct ccs_acl_param".
1297     *
1298     * Returns a word on success, "" otherwise.
1299     *
1300     * To allow the caller to skip NULL check, this function returns "" rather than
1301     * NULL if there is no more words to read.
1302     */
1303     static char *ccs_read_token(struct ccs_acl_param *param)
1304     {
1305     char *pos = param->data;
1306     char *del = strchr(pos, ' ');
1307     if (del)
1308     *del++ = '\0';
1309     else
1310     del = pos + strlen(pos);
1311     param->data = del;
1312     return pos;
1313     }
1314    
1315     /**
1316     * ccs_make_byte - Make byte value from three octal characters.
1317     *
1318     * @c1: The first character.
1319     * @c2: The second character.
1320     * @c3: The third character.
1321     *
1322     * Returns byte value.
1323     */
1324     static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3)
1325     {
1326     return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
1327     }
1328    
1329     /**
1330     * ccs_correct_word2 - Check whether the given string follows the naming rules.
1331     *
1332     * @string: The byte sequence to check. Not '\0'-terminated.
1333     * @len: Length of @string.
1334     *
1335     * Returns true if @string follows the naming rules, false otherwise.
1336     */
1337     static bool ccs_correct_word2(const char *string, size_t len)
1338     {
1339     const char *const start = string;
1340     bool in_repetition = false;
1341     unsigned char c;
1342     unsigned char d;
1343     unsigned char e;
1344     if (!len)
1345     goto out;
1346     while (len--) {
1347     c = *string++;
1348     if (c == '\\') {
1349     if (!len--)
1350     goto out;
1351     c = *string++;
1352     switch (c) {
1353     case '\\': /* "\\" */
1354     continue;
1355     case '$': /* "\$" */
1356     case '+': /* "\+" */
1357     case '?': /* "\?" */
1358     case '*': /* "\*" */
1359     case '@': /* "\@" */
1360     case 'x': /* "\x" */
1361     case 'X': /* "\X" */
1362     case 'a': /* "\a" */
1363     case 'A': /* "\A" */
1364     case '-': /* "\-" */
1365     continue;
1366     case '{': /* "/\{" */
1367     if (string - 3 < start || *(string - 3) != '/')
1368     break;
1369     in_repetition = true;
1370     continue;
1371     case '}': /* "\}/" */
1372     if (*string != '/')
1373     break;
1374     if (!in_repetition)
1375     break;
1376     in_repetition = false;
1377     continue;
1378     case '0': /* "\ooo" */
1379     case '1':
1380     case '2':
1381     case '3':
1382     if (!len-- || !len--)
1383     break;
1384     d = *string++;
1385     e = *string++;
1386     if (d < '0' || d > '7' || e < '0' || e > '7')
1387     break;
1388     c = ccs_make_byte(c, d, e);
1389     if (c <= ' ' || c >= 127)
1390     continue;
1391     }
1392     goto out;
1393     } else if (in_repetition && c == '/') {
1394     goto out;
1395     } else if (c <= ' ' || c >= 127) {
1396     goto out;
1397     }
1398     }
1399     if (in_repetition)
1400     goto out;
1401     return true;
1402     out:
1403     return false;
1404     }
1405    
1406     /**
1407     * ccs_correct_word - Check whether the given string follows the naming rules.
1408     *
1409     * @string: The string to check.
1410     *
1411     * Returns true if @string follows the naming rules, false otherwise.
1412     */
1413     static bool ccs_correct_word(const char *string)
1414     {
1415     return ccs_correct_word2(string, strlen(string));
1416     }
1417    
1418     /**
1419 kumaneko 5597 * ccs_get_group - Allocate memory for "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group".
1420     *
1421     * @param: Pointer to "struct ccs_acl_param".
1422     * @idx: Index number.
1423     *
1424     * Returns pointer to "struct ccs_group" on success, NULL otherwise.
1425     */
1426     static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
1427     const u8 idx)
1428     {
1429     struct ccs_group e = { };
1430     struct ccs_group *group = NULL;
1431     struct list_head *list;
1432     const char *group_name = ccs_read_token(param);
1433     bool found = false;
1434     if (!ccs_correct_word(group_name) || idx >= CCS_MAX_GROUP)
1435     return NULL;
1436     e.group_name = ccs_get_name(group_name);
1437     if (!e.group_name)
1438     return NULL;
1439     if (mutex_lock_interruptible(&ccs_policy_lock))
1440     goto out;
1441     list = &param->ns->group_list[idx];
1442     list_for_each_entry(group, list, head.list) {
1443     if (e.group_name != group->group_name ||
1444     atomic_read(&group->head.users) == CCS_GC_IN_PROGRESS)
1445     continue;
1446     atomic_inc(&group->head.users);
1447     found = true;
1448     break;
1449     }
1450     if (!found) {
1451     struct ccs_group *entry = ccs_commit_ok(&e, sizeof(e));
1452     if (entry) {
1453     INIT_LIST_HEAD(&entry->member_list);
1454     atomic_set(&entry->head.users, 1);
1455     list_add_tail_rcu(&entry->head.list, list);
1456     group = entry;
1457     found = true;
1458     }
1459     }
1460     mutex_unlock(&ccs_policy_lock);
1461     out:
1462     ccs_put_name(e.group_name);
1463     return found ? group : NULL;
1464     }
1465    
1466     /**
1467 kumaneko 5594 * ccs_parse_name_union - Parse a ccs_name_union.
1468     *
1469     * @param: Pointer to "struct ccs_acl_param".
1470     * @ptr: Pointer to "struct ccs_name_union".
1471     *
1472     * Returns true on success, false otherwise.
1473     */
1474     static bool ccs_parse_name_union(struct ccs_acl_param *param,
1475     struct ccs_name_union *ptr)
1476     {
1477     char *filename;
1478     if (param->data[0] == '@') {
1479     param->data++;
1480     ptr->group = ccs_get_group(param, CCS_PATH_GROUP);
1481     return ptr->group != NULL;
1482     }
1483     filename = ccs_read_token(param);
1484     if (!ccs_correct_word(filename))
1485     return false;
1486     ptr->filename = ccs_get_name(filename);
1487     return ptr->filename != NULL;
1488     }
1489    
1490     /**
1491 kumaneko 5596 * ccs_parse_ulong - Parse an "unsigned long" value.
1492     *
1493     * @result: Pointer to "unsigned long".
1494     * @str: Pointer to string to parse.
1495     *
1496     * Returns one of values in "enum ccs_value_type".
1497     *
1498     * The @src is updated to point the first character after the value
1499     * on success.
1500     */
1501     static u8 ccs_parse_ulong(unsigned long *result, char **str)
1502     {
1503     const char *cp = *str;
1504     char *ep;
1505     int base = 10;
1506     if (*cp == '0') {
1507     char c = *(cp + 1);
1508     if (c == 'x' || c == 'X') {
1509     base = 16;
1510     cp += 2;
1511     } else if (c >= '0' && c <= '7') {
1512     base = 8;
1513     cp++;
1514     }
1515     }
1516     *result = simple_strtoul(cp, &ep, base);
1517     if (cp == ep)
1518     return CCS_VALUE_TYPE_INVALID;
1519     *str = ep;
1520     switch (base) {
1521     case 16:
1522     return CCS_VALUE_TYPE_HEXADECIMAL;
1523     case 8:
1524     return CCS_VALUE_TYPE_OCTAL;
1525     default:
1526     return CCS_VALUE_TYPE_DECIMAL;
1527     }
1528     }
1529    
1530     /**
1531 kumaneko 5594 * ccs_parse_number_union - Parse a ccs_number_union.
1532     *
1533     * @param: Pointer to "struct ccs_acl_param".
1534     * @ptr: Pointer to "struct ccs_number_union".
1535     *
1536     * Returns true on success, false otherwise.
1537     */
1538     static bool ccs_parse_number_union(struct ccs_acl_param *param,
1539     struct ccs_number_union *ptr)
1540     {
1541     char *data;
1542     u8 type;
1543     unsigned long v;
1544     memset(ptr, 0, sizeof(*ptr));
1545     if (param->data[0] == '@') {
1546     param->data++;
1547     ptr->group = ccs_get_group(param, CCS_NUMBER_GROUP);
1548     return ptr->group != NULL;
1549     }
1550     data = ccs_read_token(param);
1551     type = ccs_parse_ulong(&v, &data);
1552     if (type == CCS_VALUE_TYPE_INVALID)
1553     return false;
1554     ptr->values[0] = v;
1555     ptr->value_type[0] = type;
1556     if (!*data) {
1557     ptr->values[1] = v;
1558     ptr->value_type[1] = type;
1559     return true;
1560     }
1561     if (*data++ != '-')
1562     return false;
1563     type = ccs_parse_ulong(&v, &data);
1564     if (type == CCS_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
1565     return false;
1566     ptr->values[1] = v;
1567     ptr->value_type[1] = type;
1568     return true;
1569     }
1570    
1571 kumaneko 5619 #ifdef CONFIG_CCSECURITY_NETWORK
1572    
1573 kumaneko 5594 /**
1574     * ccs_parse_ipaddr_union - Parse an IP address.
1575     *
1576     * @param: Pointer to "struct ccs_acl_param".
1577     * @ptr: Pointer to "struct ccs_ipaddr_union".
1578     *
1579     * Returns true on success, false otherwise.
1580     */
1581     static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
1582     struct ccs_ipaddr_union *ptr)
1583     {
1584     u8 * const min = ptr->ip[0].in6_u.u6_addr8;
1585     u8 * const max = ptr->ip[1].in6_u.u6_addr8;
1586     char *address = ccs_read_token(param);
1587     const char *end;
1588     if (!strchr(address, ':') &&
1589     ccs_in4_pton(address, -1, min, '-', &end) > 0) {
1590     ptr->is_ipv6 = false;
1591     if (!*end)
1592     ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
1593     else if (*end++ != '-' ||
1594     ccs_in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
1595     return false;
1596     return true;
1597     }
1598     if (ccs_in6_pton(address, -1, min, '-', &end) > 0) {
1599     ptr->is_ipv6 = true;
1600     if (!*end)
1601     memmove(max, min, sizeof(u16) * 8);
1602     else if (*end++ != '-' ||
1603     ccs_in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
1604     return false;
1605     return true;
1606     }
1607     return false;
1608     }
1609    
1610 kumaneko 5619 #endif
1611    
1612 kumaneko 5594 /**
1613     * ccs_get_dqword - ccs_get_name() for a quoted string.
1614     *
1615     * @start: String to save.
1616     *
1617     * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
1618     */
1619     static const struct ccs_path_info *ccs_get_dqword(char *start)
1620     {
1621     char *cp = start + strlen(start) - 1;
1622     if (cp == start || *start++ != '"' || *cp != '"')
1623     return NULL;
1624     *cp = '\0';
1625     if (*start && !ccs_correct_word(start))
1626     return NULL;
1627     return ccs_get_name(start);
1628     }
1629    
1630     /**
1631     * ccs_parse_name_union_quoted - Parse a quoted word.
1632     *
1633     * @param: Pointer to "struct ccs_acl_param".
1634     * @ptr: Pointer to "struct ccs_name_union".
1635     *
1636     * Returns true on success, false otherwise.
1637     */
1638     static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param,
1639     struct ccs_name_union *ptr)
1640     {
1641     char *filename = param->data;
1642     if (*filename == '@')
1643     return ccs_parse_name_union(param, ptr);
1644     ptr->filename = ccs_get_dqword(filename);
1645     return ptr->filename != NULL;
1646     }
1647    
1648     /**
1649     * ccs_parse_argv - Parse an argv[] condition part.
1650     *
1651     * @left: Lefthand value.
1652     * @right: Righthand value.
1653     * @argv: Pointer to "struct ccs_argv".
1654     *
1655     * Returns true on success, false otherwise.
1656     */
1657     static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv)
1658     {
1659     if (ccs_parse_ulong(&argv->index, &left) != CCS_VALUE_TYPE_DECIMAL ||
1660     *left++ != ']' || *left)
1661     return false;
1662     argv->value = ccs_get_dqword(right);
1663     return argv->value != NULL;
1664     }
1665    
1666     /**
1667     * ccs_parse_envp - Parse an envp[] condition part.
1668     *
1669     * @left: Lefthand value.
1670     * @right: Righthand value.
1671     * @envp: Pointer to "struct ccs_envp".
1672     *
1673     * Returns true on success, false otherwise.
1674     */
1675     static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp)
1676     {
1677     const struct ccs_path_info *name;
1678     const struct ccs_path_info *value;
1679     char *cp = left + strlen(left) - 1;
1680     if (*cp-- != ']' || *cp != '"')
1681     goto out;
1682     *cp = '\0';
1683     if (!ccs_correct_word(left))
1684     goto out;
1685     name = ccs_get_name(left);
1686     if (!name)
1687     goto out;
1688     if (!strcmp(right, "NULL")) {
1689     value = NULL;
1690     } else {
1691     value = ccs_get_dqword(right);
1692     if (!value) {
1693     ccs_put_name(name);
1694     goto out;
1695     }
1696     }
1697     envp->name = name;
1698     envp->value = value;
1699     return true;
1700     out:
1701     return false;
1702     }
1703    
1704     /**
1705     * ccs_same_condition - Check for duplicated "struct ccs_condition" entry.
1706     *
1707     * @a: Pointer to "struct ccs_condition".
1708     * @b: Pointer to "struct ccs_condition".
1709     *
1710     * Returns true if @a == @b, false otherwise.
1711     */
1712     static bool ccs_same_condition(const struct ccs_condition *a,
1713     const struct ccs_condition *b)
1714     {
1715     return a->size == b->size && a->condc == b->condc &&
1716     a->numbers_count == b->numbers_count &&
1717     a->names_count == b->names_count &&
1718     a->argc == b->argc && a->envc == b->envc &&
1719     a->grant_log == b->grant_log &&
1720     a->exec_transit == b->exec_transit && a->transit == b->transit
1721     && !memcmp(a + 1, b + 1, a->size - sizeof(*a));
1722     }
1723    
1724     /**
1725     * ccs_condition_type - Get condition type.
1726     *
1727     * @word: Keyword string.
1728     *
1729     * Returns one of values in "enum ccs_conditions_index" on success,
1730     * CCS_MAX_CONDITION_KEYWORD otherwise.
1731     */
1732     static u8 ccs_condition_type(const char *word)
1733     {
1734     u8 i;
1735     for (i = 0; i < CCS_MAX_CONDITION_KEYWORD; i++) {
1736     if (!strcmp(word, ccs_condition_keyword[i]))
1737     break;
1738     }
1739     return i;
1740     }
1741    
1742     /**
1743     * ccs_commit_condition - Commit "struct ccs_condition".
1744     *
1745     * @entry: Pointer to "struct ccs_condition".
1746     *
1747     * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
1748     *
1749     * This function merges duplicated entries. This function returns NULL if
1750     * @entry is not duplicated but memory quota for policy has exceeded.
1751     */
1752     static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry)
1753     {
1754     struct ccs_condition *ptr;
1755     bool found = false;
1756     if (mutex_lock_interruptible(&ccs_policy_lock)) {
1757     dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
1758     ptr = NULL;
1759     found = true;
1760     goto out;
1761     }
1762     list_for_each_entry(ptr, &ccs_condition_list, head.list) {
1763     if (!ccs_same_condition(ptr, entry) ||
1764     atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS)
1765     continue;
1766     /* Same entry found. Share this entry. */
1767     atomic_inc(&ptr->head.users);
1768     found = true;
1769     break;
1770     }
1771     if (!found) {
1772     if (ccs_memory_ok(entry, entry->size)) {
1773     atomic_set(&entry->head.users, 1);
1774     list_add(&entry->head.list, &ccs_condition_list);
1775     } else {
1776     found = true;
1777     ptr = NULL;
1778     }
1779     }
1780     mutex_unlock(&ccs_policy_lock);
1781     out:
1782     if (found) {
1783     ccs_del_condition(&entry->head.list);
1784     kfree(entry);
1785     entry = ptr;
1786     }
1787     return entry;
1788     }
1789    
1790     /**
1791 kumaneko 5618 * ccs_correct_path - Check whether the given pathname follows the naming rules.
1792     *
1793     * @filename: The pathname to check.
1794     *
1795     * Returns true if @filename follows the naming rules, false otherwise.
1796     */
1797     static bool ccs_correct_path(const char *filename)
1798     {
1799     return *filename == '/' && ccs_correct_word(filename);
1800     }
1801    
1802     /**
1803     * ccs_domain_def - Check whether the given token can be a domainname.
1804     *
1805     * @buffer: The token to check.
1806     *
1807     * Returns true if @buffer possibly be a domainname, false otherwise.
1808     */
1809     static bool ccs_domain_def(const unsigned char *buffer)
1810     {
1811     const unsigned char *cp;
1812     int len;
1813     if (*buffer != '<')
1814     return false;
1815     cp = strchr(buffer, ' ');
1816     if (!cp)
1817     len = strlen(buffer);
1818     else
1819     len = cp - buffer;
1820     if (buffer[len - 1] != '>' || !ccs_correct_word2(buffer + 1, len - 2))
1821     return false;
1822     return true;
1823     }
1824    
1825     /**
1826     * ccs_correct_domain - Check whether the given domainname follows the naming rules.
1827     *
1828     * @domainname: The domainname to check.
1829     *
1830     * Returns true if @domainname follows the naming rules, false otherwise.
1831     */
1832     static bool ccs_correct_domain(const unsigned char *domainname)
1833     {
1834     if (!domainname || !ccs_domain_def(domainname))
1835     return false;
1836     domainname = strchr(domainname, ' ');
1837     if (!domainname++)
1838     return true;
1839     while (1) {
1840     const unsigned char *cp = strchr(domainname, ' ');
1841     if (!cp)
1842     break;
1843     if (*domainname != '/' ||
1844     !ccs_correct_word2(domainname, cp - domainname))
1845     return false;
1846     domainname = cp + 1;
1847     }
1848     return ccs_correct_path(domainname);
1849     }
1850    
1851     /**
1852     * ccs_normalize_line - Format string.
1853     *
1854     * @buffer: The line to normalize.
1855     *
1856     * Returns nothing.
1857     *
1858     * Leading and trailing whitespaces are removed.
1859     * Multiple whitespaces are packed into single space.
1860     */
1861     static void ccs_normalize_line(unsigned char *buffer)
1862     {
1863     unsigned char *sp = buffer;
1864     unsigned char *dp = buffer;
1865     bool first = true;
1866     while (*sp && (*sp <= ' ' || *sp >= 127))
1867     sp++;
1868     while (*sp) {
1869     if (!first)
1870     *dp++ = ' ';
1871     first = false;
1872     while (*sp > ' ' && *sp < 127)
1873     *dp++ = *sp++;
1874     while (*sp && (*sp <= ' ' || *sp >= 127))
1875     sp++;
1876     }
1877     *dp = '\0';
1878     }
1879    
1880     /**
1881 kumaneko 5596 * ccs_get_domainname - Read a domainname from a line.
1882     *
1883     * @param: Pointer to "struct ccs_acl_param".
1884     *
1885     * Returns a domainname on success, NULL otherwise.
1886     */
1887     static const struct ccs_path_info *ccs_get_domainname
1888     (struct ccs_acl_param *param)
1889     {
1890     char *start = param->data;
1891     char *pos = start;
1892     while (*pos) {
1893     if (*pos++ != ' ' || *pos++ == '/')
1894     continue;
1895     pos -= 2;
1896     *pos++ = '\0';
1897     break;
1898     }
1899     param->data = pos;
1900     if (ccs_correct_domain(start))
1901     return ccs_get_name(start);
1902     return NULL;
1903     }
1904    
1905     /**
1906 kumaneko 5594 * ccs_get_transit_preference - Parse domain transition preference for execve().
1907     *
1908     * @param: Pointer to "struct ccs_acl_param".
1909     * @e: Pointer to "struct ccs_condition".
1910     *
1911     * Returns the condition string part.
1912     */
1913     static char *ccs_get_transit_preference(struct ccs_acl_param *param,
1914     struct ccs_condition *e)
1915     {
1916     char * const pos = param->data;
1917     bool flag;
1918     if (*pos == '<') {
1919     e->transit = ccs_get_domainname(param);
1920     goto done;
1921     }
1922     {
1923     char *cp = strchr(pos, ' ');
1924     if (cp)
1925     *cp = '\0';
1926     flag = ccs_correct_path(pos) || !strcmp(pos, "keep") ||
1927     !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
1928     !strcmp(pos, "child") || !strcmp(pos, "parent");
1929     if (cp)
1930     *cp = ' ';
1931     }
1932     if (!flag)
1933     return pos;
1934     e->transit = ccs_get_name(ccs_read_token(param));
1935     done:
1936     if (e->transit) {
1937     e->exec_transit = true;
1938     return param->data;
1939     }
1940     /*
1941     * Return a bad read-only condition string that will let
1942     * ccs_get_condition() return NULL.
1943     */
1944     return "/";
1945     }
1946    
1947     /**
1948     * ccs_get_condition - Parse condition part.
1949     *
1950     * @param: Pointer to "struct ccs_acl_param".
1951     *
1952     * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
1953     */
1954     struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param)
1955     {
1956     struct ccs_condition *entry = NULL;
1957     struct ccs_condition_element *condp = NULL;
1958     struct ccs_number_union *numbers_p = NULL;
1959     struct ccs_name_union *names_p = NULL;
1960     struct ccs_argv *argv = NULL;
1961     struct ccs_envp *envp = NULL;
1962     struct ccs_condition e = { };
1963     char * const start_of_string = ccs_get_transit_preference(param, &e);
1964     char * const end_of_string = start_of_string + strlen(start_of_string);
1965     char *pos;
1966     rerun:
1967     pos = start_of_string;
1968     while (1) {
1969     u8 left = -1;
1970     u8 right = -1;
1971     char *left_word = pos;
1972     char *cp;
1973     char *right_word;
1974     bool is_not;
1975     if (!*left_word)
1976     break;
1977     /*
1978     * Since left-hand condition does not allow use of "path_group"
1979     * or "number_group" and environment variable's names do not
1980     * accept '=', it is guaranteed that the original line consists
1981     * of one or more repetition of $left$operator$right blocks
1982     * where "$left is free from '=' and ' '" and "$operator is
1983     * either '=' or '!='" and "$right is free from ' '".
1984     * Therefore, we can reconstruct the original line at the end
1985     * of dry run even if we overwrite $operator with '\0'.
1986     */
1987     cp = strchr(pos, ' ');
1988     if (cp) {
1989     *cp = '\0'; /* Will restore later. */
1990     pos = cp + 1;
1991     } else {
1992     pos = "";
1993     }
1994     right_word = strchr(left_word, '=');
1995     if (!right_word || right_word == left_word)
1996     goto out;
1997     is_not = *(right_word - 1) == '!';
1998     if (is_not)
1999     *(right_word++ - 1) = '\0'; /* Will restore later. */
2000     else if (*(right_word + 1) != '=')
2001     *right_word++ = '\0'; /* Will restore later. */
2002     else
2003     goto out;
2004     dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
2005     is_not ? "!" : "", right_word);
2006     if (!strcmp(left_word, "grant_log")) {
2007     if (entry) {
2008     if (is_not ||
2009     entry->grant_log != CCS_GRANTLOG_AUTO)
2010     goto out;
2011     else if (!strcmp(right_word, "yes"))
2012     entry->grant_log = CCS_GRANTLOG_YES;
2013     else if (!strcmp(right_word, "no"))
2014     entry->grant_log = CCS_GRANTLOG_NO;
2015     else
2016     goto out;
2017     }
2018     continue;
2019     }
2020     if (!strcmp(left_word, "auto_domain_transition")) {
2021     if (entry) {
2022     if (is_not || entry->transit)
2023     goto out;
2024     entry->transit = ccs_get_dqword(right_word);
2025     if (!entry->transit ||
2026     (entry->transit->name[0] != '/' &&
2027     !ccs_domain_def(entry->transit->name)))
2028     goto out;
2029     }
2030     continue;
2031     }
2032     if (!strncmp(left_word, "exec.argv[", 10)) {
2033     if (!argv) {
2034     e.argc++;
2035     e.condc++;
2036     } else {
2037     e.argc--;
2038     e.condc--;
2039     left = CCS_ARGV_ENTRY;
2040     argv->is_not = is_not;
2041     if (!ccs_parse_argv(left_word + 10,
2042     right_word, argv++))
2043     goto out;
2044     }
2045     goto store_value;
2046     }
2047     if (!strncmp(left_word, "exec.envp[\"", 11)) {
2048     if (!envp) {
2049     e.envc++;
2050     e.condc++;
2051     } else {
2052     e.envc--;
2053     e.condc--;
2054     left = CCS_ENVP_ENTRY;
2055     envp->is_not = is_not;
2056     if (!ccs_parse_envp(left_word + 11,
2057     right_word, envp++))
2058     goto out;
2059     }
2060     goto store_value;
2061     }
2062     left = ccs_condition_type(left_word);
2063     dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
2064     left);
2065     if (left == CCS_MAX_CONDITION_KEYWORD) {
2066     if (!numbers_p) {
2067     e.numbers_count++;
2068     } else {
2069     e.numbers_count--;
2070     left = CCS_NUMBER_UNION;
2071     param->data = left_word;
2072     if (*left_word == '@' ||
2073     !ccs_parse_number_union(param,
2074     numbers_p++))
2075     goto out;
2076     }
2077     }
2078     if (!condp)
2079     e.condc++;
2080     else
2081     e.condc--;
2082     if (left == CCS_EXEC_REALPATH || left == CCS_SYMLINK_TARGET) {
2083     if (!names_p) {
2084     e.names_count++;
2085     } else {
2086     e.names_count--;
2087     right = CCS_NAME_UNION;
2088     param->data = right_word;
2089     if (!ccs_parse_name_union_quoted(param,
2090     names_p++))
2091     goto out;
2092     }
2093     goto store_value;
2094     }
2095     right = ccs_condition_type(right_word);
2096     if (right == CCS_MAX_CONDITION_KEYWORD) {
2097     if (!numbers_p) {
2098     e.numbers_count++;
2099     } else {
2100     e.numbers_count--;
2101     right = CCS_NUMBER_UNION;
2102     param->data = right_word;
2103     if (!ccs_parse_number_union(param,
2104     numbers_p++))
2105     goto out;
2106     }
2107     }
2108     store_value:
2109     if (!condp) {
2110     dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
2111     "match=%u\n", __LINE__, left, right, !is_not);
2112     continue;
2113     }
2114     condp->left = left;
2115     condp->right = right;
2116     condp->equals = !is_not;
2117     dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
2118     __LINE__, condp->left, condp->right,
2119     condp->equals);
2120     condp++;
2121     }
2122     dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
2123     __LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
2124     e.envc);
2125     if (entry) {
2126     BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
2127     e.condc);
2128     return ccs_commit_condition(entry);
2129     }
2130     e.size = sizeof(*entry)
2131     + e.condc * sizeof(struct ccs_condition_element)
2132     + e.numbers_count * sizeof(struct ccs_number_union)
2133     + e.names_count * sizeof(struct ccs_name_union)
2134     + e.argc * sizeof(struct ccs_argv)
2135     + e.envc * sizeof(struct ccs_envp);
2136     entry = kzalloc(e.size, CCS_GFP_FLAGS);
2137     if (!entry)
2138     goto out2;
2139     *entry = e;
2140     e.transit = NULL;
2141     condp = (struct ccs_condition_element *) (entry + 1);
2142     numbers_p = (struct ccs_number_union *) (condp + e.condc);
2143     names_p = (struct ccs_name_union *) (numbers_p + e.numbers_count);
2144     argv = (struct ccs_argv *) (names_p + e.names_count);
2145     envp = (struct ccs_envp *) (argv + e.argc);
2146     {
2147     bool flag = false;
2148     for (pos = start_of_string; pos < end_of_string; pos++) {
2149     if (*pos)
2150     continue;
2151     if (flag) /* Restore " ". */
2152     *pos = ' ';
2153     else if (*(pos + 1) == '=') /* Restore "!=". */
2154     *pos = '!';
2155     else /* Restore "=". */
2156     *pos = '=';
2157     flag = !flag;
2158     }
2159     }
2160     goto rerun;
2161     out:
2162     dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
2163     if (entry) {
2164     ccs_del_condition(&entry->head.list);
2165     kfree(entry);
2166     }
2167     out2:
2168     ccs_put_name(e.transit);
2169     return NULL;
2170     }
2171    
2172     /**
2173 kumaneko 2958 * ccs_yesno - Return "yes" or "no".
2174 kumaneko 2863 *
2175 kumaneko 2958 * @value: Bool value.
2176 kumaneko 4063 *
2177     * Returns "yes" if @value is not 0, "no" otherwise.
2178 kumaneko 2863 */
2179 kumaneko 5597 static const char *ccs_yesno(const unsigned int value)
2180 kumaneko 2863 {
2181 kumaneko 2958 return value ? "yes" : "no";
2182 kumaneko 2863 }
2183    
2184 kumaneko 4063 /**
2185 kumaneko 4084 * ccs_addprintf - strncat()-like-snprintf().
2186 kumaneko 4063 *
2187     * @buffer: Buffer to write to. Must be '\0'-terminated.
2188     * @len: Size of @buffer.
2189     * @fmt: The printf()'s format string, followed by parameters.
2190     *
2191     * Returns nothing.
2192     */
2193 kumaneko 4049 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
2194 kumaneko 3780 {
2195     va_list args;
2196     const int pos = strlen(buffer);
2197     va_start(args, fmt);
2198     vsnprintf(buffer + pos, len - pos - 1, fmt, args);
2199     va_end(args);
2200     }
2201    
2202 kumaneko 2863 /**
2203 kumaneko 3780 * ccs_flush - Flush queued string to userspace's buffer.
2204 kumaneko 2863 *
2205 kumaneko 4063 * @head: Pointer to "struct ccs_io_buffer".
2206 kumaneko 2863 *
2207 kumaneko 3780 * Returns true if all data was flushed, false otherwise.
2208     */
2209     static bool ccs_flush(struct ccs_io_buffer *head)
2210     {
2211     while (head->r.w_pos) {
2212     const char *w = head->r.w[0];
2213 kumaneko 4668 size_t len = strlen(w);
2214 kumaneko 3780 if (len) {
2215     if (len > head->read_user_buf_avail)
2216     len = head->read_user_buf_avail;
2217     if (!len)
2218     return false;
2219     if (copy_to_user(head->read_user_buf, w, len))
2220     return false;
2221     head->read_user_buf_avail -= len;
2222     head->read_user_buf += len;
2223     w += len;
2224     }
2225 kumaneko 4536 head->r.w[0] = w;
2226     if (*w)
2227 kumaneko 3780 return false;
2228     /* Add '\0' for audit logs and query. */
2229 kumaneko 5106 if (head->type == CCS_AUDIT || head->type == CCS_QUERY) {
2230 kumaneko 3780 if (!head->read_user_buf_avail ||
2231     copy_to_user(head->read_user_buf, "", 1))
2232     return false;
2233     head->read_user_buf_avail--;
2234     head->read_user_buf++;
2235     }
2236     head->r.w_pos--;
2237     for (len = 0; len < head->r.w_pos; len++)
2238     head->r.w[len] = head->r.w[len + 1];
2239     }
2240     head->r.avail = 0;
2241     return true;
2242     }
2243    
2244     /**
2245     * ccs_set_string - Queue string to "struct ccs_io_buffer" structure.
2246 kumaneko 2863 *
2247 kumaneko 3780 * @head: Pointer to "struct ccs_io_buffer".
2248     * @string: String to print.
2249     *
2250 kumaneko 4084 * Returns nothing.
2251     *
2252 kumaneko 3780 * Note that @string has to be kept valid until @head is kfree()d.
2253     * This means that char[] allocated on stack memory cannot be passed to
2254     * this function. Use ccs_io_printf() for char[] allocated on stack memory.
2255 kumaneko 2863 */
2256 kumaneko 3780 static void ccs_set_string(struct ccs_io_buffer *head, const char *string)
2257 kumaneko 2863 {
2258 kumaneko 3780 if (head->r.w_pos < CCS_MAX_IO_READ_QUEUE) {
2259     head->r.w[head->r.w_pos++] = string;
2260     ccs_flush(head);
2261     } else
2262 kumaneko 3829 printk(KERN_WARNING "Too many words in a line.\n");
2263 kumaneko 3780 }
2264    
2265     /**
2266     * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
2267     *
2268     * @head: Pointer to "struct ccs_io_buffer".
2269     * @fmt: The printf()'s format string, followed by parameters.
2270 kumaneko 4063 *
2271     * Returns nothing.
2272 kumaneko 3780 */
2273 kumaneko 4535 static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
2274 kumaneko 3780 {
2275 kumaneko 2863 va_list args;
2276 kumaneko 4668 size_t len;
2277     size_t pos = head->r.avail;
2278 kumaneko 2863 int size = head->readbuf_size - pos;
2279     if (size <= 0)
2280 kumaneko 3780 return;
2281 kumaneko 2863 va_start(args, fmt);
2282 kumaneko 3780 len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1;
2283 kumaneko 2863 va_end(args);
2284 kumaneko 3780 if (pos + len >= head->readbuf_size) {
2285 kumaneko 3829 printk(KERN_WARNING "Too many words in a line.\n");
2286 kumaneko 3780 return;
2287     }
2288     head->r.avail += len;
2289     ccs_set_string(head, head->read_buf + pos);
2290 kumaneko 2863 }
2291    
2292 kumaneko 4063 /**
2293     * ccs_set_space - Put a space to "struct ccs_io_buffer" structure.
2294     *
2295     * @head: Pointer to "struct ccs_io_buffer".
2296     *
2297     * Returns nothing.
2298     */
2299 kumaneko 3780 static void ccs_set_space(struct ccs_io_buffer *head)
2300     {
2301     ccs_set_string(head, " ");
2302     }
2303    
2304 kumaneko 4063 /**
2305     * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure.
2306     *
2307     * @head: Pointer to "struct ccs_io_buffer".
2308     *
2309 kumaneko 5686 * Returns true if all data was flushed, false otherwise.
2310 kumaneko 4063 */
2311 kumaneko 3780 static bool ccs_set_lf(struct ccs_io_buffer *head)
2312     {
2313     ccs_set_string(head, "\n");
2314     return !head->r.w_pos;
2315     }
2316    
2317 kumaneko 2863 /**
2318 kumaneko 4724 * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure.
2319     *
2320     * @head: Pointer to "struct ccs_io_buffer".
2321     *
2322     * Returns nothing.
2323     */
2324     static void ccs_set_slash(struct ccs_io_buffer *head)
2325     {
2326     ccs_set_string(head, "/");
2327     }
2328    
2329     /**
2330 kumaneko 5050 * ccs_init_policy_namespace - Initialize namespace.
2331     *
2332     * @ns: Pointer to "struct ccs_policy_namespace".
2333     *
2334     * Returns nothing.
2335     */
2336 kumaneko 5618 static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns)
2337 kumaneko 5050 {
2338     unsigned int idx;
2339 kumaneko 5094 for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++)
2340     INIT_LIST_HEAD(&ns->acl_group[idx]);
2341 kumaneko 5050 for (idx = 0; idx < CCS_MAX_GROUP; idx++)
2342     INIT_LIST_HEAD(&ns->group_list[idx]);
2343     for (idx = 0; idx < CCS_MAX_POLICY; idx++)
2344     INIT_LIST_HEAD(&ns->policy_list[idx]);
2345 kumaneko 5052 ns->profile_version = 20100903;
2346 kumaneko 5050 ccs_namespace_enabled = !list_empty(&ccs_namespace_list);
2347     list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list);
2348     }
2349    
2350     /**
2351     * ccs_print_namespace - Print namespace header.
2352     *
2353     * @head: Pointer to "struct ccs_io_buffer".
2354     *
2355     * Returns nothing.
2356     */
2357     static void ccs_print_namespace(struct ccs_io_buffer *head)
2358     {
2359     if (!ccs_namespace_enabled)
2360     return;
2361     ccs_set_string(head,
2362     container_of(head->r.ns, struct ccs_policy_namespace,
2363     namespace_list)->name);
2364     ccs_set_space(head);
2365     }
2366    
2367     /**
2368 kumaneko 3694 * ccs_assign_profile - Create a new profile.
2369 kumaneko 2863 *
2370 kumaneko 5050 * @ns: Pointer to "struct ccs_policy_namespace".
2371 kumaneko 2863 * @profile: Profile number to create.
2372     *
2373     * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
2374     */
2375 kumaneko 5050 static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
2376     const unsigned int profile)
2377 kumaneko 2863 {
2378     struct ccs_profile *ptr;
2379     struct ccs_profile *entry;
2380 kumaneko 2892 if (profile >= CCS_MAX_PROFILES)
2381 kumaneko 2863 return NULL;
2382 kumaneko 5050 ptr = ns->profile_ptr[profile];
2383 kumaneko 2863 if (ptr)
2384     return ptr;
2385 kumaneko 3512 entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
2386 kumaneko 3534 if (mutex_lock_interruptible(&ccs_policy_lock))
2387     goto out;
2388 kumaneko 5050 ptr = ns->profile_ptr[profile];
2389 kumaneko 5487 if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
2390 kumaneko 2863 ptr = entry;
2391 kumaneko 2958 ptr->default_config = CCS_CONFIG_DISABLED |
2392     CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
2393     memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
2394 kumaneko 2943 sizeof(ptr->config));
2395 kumaneko 4170 ptr->pref[CCS_PREF_MAX_AUDIT_LOG] =
2396     CONFIG_CCSECURITY_MAX_AUDIT_LOG;
2397 kumaneko 4049 ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
2398     CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
2399 kumaneko 2863