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

Subversion リポジトリの参照

Contents of /trunk/akari/policy_io.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 690 - (show annotations) (download) (as text)
Wed Nov 2 14:00:12 2022 UTC (17 months, 3 weeks ago) by kumaneko
File MIME type: text/x-csrc
File size: 180664 byte(s)


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