summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmin Kuster <akuster808@gmail.com>2015-10-25 14:53:39 -0700
committerArmin Kuster <akuster808@gmail.com>2015-10-30 11:56:30 -0700
commitb0c1edfe23f9ed18884e506a6653a23e504705db (patch)
tree640920aa1f482a2da14dfbdcf1a4b93f42cf6806
parent36feac0d9d318200208da19543acfdca5fe61573 (diff)
downloadmeta-security-b0c1edfe23f9ed18884e506a6653a23e504705db.tar.gz
ccs-patch: Add ccs kernel patches
add 4.1 kernel support for css Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.1.diff968
-rw-r--r--recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.2.diff681
-rw-r--r--recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto.4.1.patch1029
-rw-r--r--recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto_security.patch17920
-rw-r--r--recipes-kernel/linux/linux-yocto-4.1/tomoyo.cfg16
-rw-r--r--recipes-kernel/linux/linux-yocto-4.1/tomoyo.scc4
-rw-r--r--recipes-kernel/linux/linux-yocto_4.1.bbappend9
7 files changed, 20627 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.1.diff b/recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.1.diff
new file mode 100644
index 0000000..9ad49fd
--- /dev/null
+++ b/recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.1.diff
@@ -0,0 +1,968 @@
1This is TOMOYO Linux patch for kernel 4.1.8.
2
3Source code for this patch is https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.1.8.tar.xz
4---
5 fs/exec.c | 2
6 fs/open.c | 2
7 fs/proc/version.c | 7 ++
8 include/linux/init_task.h | 9 +++
9 include/linux/sched.h | 6 ++
10 include/linux/security.h | 62 +++++++++++++++----------
11 include/net/ip.h | 4 +
12 kernel/fork.c | 5 ++
13 kernel/kexec.c | 3 +
14 kernel/module.c | 5 ++
15 kernel/ptrace.c | 10 ++++
16 kernel/reboot.c | 3 +
17 kernel/sched/core.c | 2
18 kernel/signal.c | 10 ++++
19 kernel/sys.c | 8 +++
20 kernel/time/ntp.c | 8 +++
21 net/ipv4/raw.c | 4 +
22 net/ipv4/udp.c | 4 +
23 net/ipv6/raw.c | 4 +
24 net/ipv6/udp.c | 4 +
25 net/socket.c | 4 +
26 net/unix/af_unix.c | 4 +
27 security/Kconfig | 2
28 security/Makefile | 3 +
29 security/security.c | 110 ++++++++++++++++++++++++++++++++++++++++------
30 25 files changed, 248 insertions(+), 37 deletions(-)
31
32--- linux-4.1.8.orig/fs/exec.c
33+++ linux-4.1.8/fs/exec.c
34@@ -1461,7 +1461,7 @@ static int exec_binprm(struct linux_binp
35 old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
36 rcu_read_unlock();
37
38- ret = search_binary_handler(bprm);
39+ ret = ccs_search_binary_handler(bprm);
40 if (ret >= 0) {
41 audit_bprm(bprm);
42 trace_sched_process_exec(current, old_pid, bprm);
43--- linux-4.1.8.orig/fs/open.c
44+++ linux-4.1.8/fs/open.c
45@@ -1106,6 +1106,8 @@ EXPORT_SYMBOL(sys_close);
46 */
47 SYSCALL_DEFINE0(vhangup)
48 {
49+ if (!ccs_capable(CCS_SYS_VHANGUP))
50+ return -EPERM;
51 if (capable(CAP_SYS_TTY_CONFIG)) {
52 tty_vhangup_self();
53 return 0;
54--- linux-4.1.8.orig/fs/proc/version.c
55+++ linux-4.1.8/fs/proc/version.c
56@@ -32,3 +32,10 @@ static int __init proc_version_init(void
57 return 0;
58 }
59 fs_initcall(proc_version_init);
60+
61+static int __init ccs_show_version(void)
62+{
63+ printk(KERN_INFO "Hook version: 4.1.8 2015/09/26\n");
64+ return 0;
65+}
66+fs_initcall(ccs_show_version);
67--- linux-4.1.8.orig/include/linux/init_task.h
68+++ linux-4.1.8/include/linux/init_task.h
69@@ -182,6 +182,14 @@ extern struct task_group root_task_group
70 # define INIT_KASAN(tsk)
71 #endif
72
73+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
74+#define INIT_CCSECURITY \
75+ .ccs_domain_info = NULL, \
76+ .ccs_flags = 0,
77+#else
78+#define INIT_CCSECURITY
79+#endif
80+
81 /*
82 * INIT_TASK is used to set up the first task table, touch at
83 * your own risk!. Base=0, limit=0x1fffff (=2MB)
84@@ -258,6 +266,7 @@ extern struct task_group root_task_group
85 INIT_VTIME(tsk) \
86 INIT_NUMA_BALANCING(tsk) \
87 INIT_KASAN(tsk) \
88+ INIT_CCSECURITY \
89 }
90
91
92--- linux-4.1.8.orig/include/linux/sched.h
93+++ linux-4.1.8/include/linux/sched.h
94@@ -6,6 +6,8 @@
95 #include <linux/sched/prio.h>
96
97
98+struct ccs_domain_info;
99+
100 struct sched_param {
101 int sched_priority;
102 };
103@@ -1724,6 +1726,10 @@ struct task_struct {
104 #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
105 unsigned long task_state_change;
106 #endif
107+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
108+ struct ccs_domain_info *ccs_domain_info;
109+ u32 ccs_flags;
110+#endif
111 };
112
113 /* Future-safe accessor for struct task_struct's cpus_allowed. */
114--- linux-4.1.8.orig/include/linux/security.h
115+++ linux-4.1.8/include/linux/security.h
116@@ -53,6 +53,7 @@ struct msg_queue;
117 struct xattr;
118 struct xfrm_sec_ctx;
119 struct mm_struct;
120+#include <linux/ccsecurity.h>
121
122 /* Maximum number of letters for an LSM name string */
123 #define SECURITY_NAME_MAX 10
124@@ -2042,7 +2043,10 @@ static inline int security_syslog(int ty
125 static inline int security_settime(const struct timespec *ts,
126 const struct timezone *tz)
127 {
128- return cap_settime(ts, tz);
129+ int error = cap_settime(ts, tz);
130+ if (!error)
131+ error = ccs_settime(ts, tz);
132+ return error;
133 }
134
135 static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
136@@ -2111,18 +2115,18 @@ static inline int security_sb_mount(cons
137 const char *type, unsigned long flags,
138 void *data)
139 {
140- return 0;
141+ return ccs_sb_mount(dev_name, path, type, flags, data);
142 }
143
144 static inline int security_sb_umount(struct vfsmount *mnt, int flags)
145 {
146- return 0;
147+ return ccs_sb_umount(mnt, flags);
148 }
149
150 static inline int security_sb_pivotroot(struct path *old_path,
151 struct path *new_path)
152 {
153- return 0;
154+ return ccs_sb_pivotroot(old_path, new_path);
155 }
156
157 static inline int security_sb_set_mnt_opts(struct super_block *sb,
158@@ -2260,7 +2264,7 @@ static inline int security_inode_setattr
159
160 static inline int security_inode_getattr(const struct path *path)
161 {
162- return 0;
163+ return ccs_inode_getattr(path);
164 }
165
166 static inline int security_inode_setxattr(struct dentry *dentry,
167@@ -2336,7 +2340,7 @@ static inline void security_file_free(st
168 static inline int security_file_ioctl(struct file *file, unsigned int cmd,
169 unsigned long arg)
170 {
171- return 0;
172+ return ccs_file_ioctl(file, cmd, arg);
173 }
174
175 static inline int security_mmap_file(struct file *file, unsigned long prot,
176@@ -2365,7 +2369,7 @@ static inline int security_file_lock(str
177 static inline int security_file_fcntl(struct file *file, unsigned int cmd,
178 unsigned long arg)
179 {
180- return 0;
181+ return ccs_file_fcntl(file, cmd, arg);
182 }
183
184 static inline void security_file_set_fowner(struct file *file)
185@@ -2388,7 +2392,7 @@ static inline int security_file_receive(
186 static inline int security_file_open(struct file *file,
187 const struct cred *cred)
188 {
189- return 0;
190+ return ccs_file_open(file, cred);
191 }
192
193 static inline int security_task_create(unsigned long clone_flags)
194@@ -2750,7 +2754,7 @@ static inline int security_unix_may_send
195 static inline int security_socket_create(int family, int type,
196 int protocol, int kern)
197 {
198- return 0;
199+ return ccs_socket_create(family, type, protocol, kern);
200 }
201
202 static inline int security_socket_post_create(struct socket *sock,
203@@ -2765,19 +2769,19 @@ static inline int security_socket_bind(s
204 struct sockaddr *address,
205 int addrlen)
206 {
207- return 0;
208+ return ccs_socket_bind(sock, address, addrlen);
209 }
210
211 static inline int security_socket_connect(struct socket *sock,
212 struct sockaddr *address,
213 int addrlen)
214 {
215- return 0;
216+ return ccs_socket_connect(sock, address, addrlen);
217 }
218
219 static inline int security_socket_listen(struct socket *sock, int backlog)
220 {
221- return 0;
222+ return ccs_socket_listen(sock, backlog);
223 }
224
225 static inline int security_socket_accept(struct socket *sock,
226@@ -2789,7 +2793,7 @@ static inline int security_socket_accept
227 static inline int security_socket_sendmsg(struct socket *sock,
228 struct msghdr *msg, int size)
229 {
230- return 0;
231+ return ccs_socket_sendmsg(sock, msg, size);
232 }
233
234 static inline int security_socket_recvmsg(struct socket *sock,
235@@ -3031,42 +3035,42 @@ int security_path_chroot(struct path *pa
236 #else /* CONFIG_SECURITY_PATH */
237 static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
238 {
239- return 0;
240+ return ccs_path_unlink(dir, dentry);
241 }
242
243 static inline int security_path_mkdir(struct path *dir, struct dentry *dentry,
244 umode_t mode)
245 {
246- return 0;
247+ return ccs_path_mkdir(dir, dentry, mode);
248 }
249
250 static inline int security_path_rmdir(struct path *dir, struct dentry *dentry)
251 {
252- return 0;
253+ return ccs_path_rmdir(dir, dentry);
254 }
255
256 static inline int security_path_mknod(struct path *dir, struct dentry *dentry,
257 umode_t mode, unsigned int dev)
258 {
259- return 0;
260+ return ccs_path_mknod(dir, dentry, mode, dev);
261 }
262
263 static inline int security_path_truncate(struct path *path)
264 {
265- return 0;
266+ return ccs_path_truncate(path);
267 }
268
269 static inline int security_path_symlink(struct path *dir, struct dentry *dentry,
270 const char *old_name)
271 {
272- return 0;
273+ return ccs_path_symlink(dir, dentry, old_name);
274 }
275
276 static inline int security_path_link(struct dentry *old_dentry,
277 struct path *new_dir,
278 struct dentry *new_dentry)
279 {
280- return 0;
281+ return ccs_path_link(old_dentry, new_dir, new_dentry);
282 }
283
284 static inline int security_path_rename(struct path *old_dir,
285@@ -3075,22 +3079,32 @@ static inline int security_path_rename(s
286 struct dentry *new_dentry,
287 unsigned int flags)
288 {
289- return 0;
290+ /*
291+ * Not using RENAME_EXCHANGE here in order to avoid KABI breakage
292+ * by doing "#include <uapi/linux/fs.h>" .
293+ */
294+ if (flags & (1 << 1)) {
295+ int err = ccs_path_rename(new_dir, new_dentry, old_dir,
296+ old_dentry);
297+ if (err)
298+ return err;
299+ }
300+ return ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
301 }
302
303 static inline int security_path_chmod(struct path *path, umode_t mode)
304 {
305- return 0;
306+ return ccs_path_chmod(path, mode);
307 }
308
309 static inline int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
310 {
311- return 0;
312+ return ccs_path_chown(path, uid, gid);
313 }
314
315 static inline int security_path_chroot(struct path *path)
316 {
317- return 0;
318+ return ccs_path_chroot(path);
319 }
320 #endif /* CONFIG_SECURITY_PATH */
321
322--- linux-4.1.8.orig/include/net/ip.h
323+++ linux-4.1.8/include/net/ip.h
324@@ -216,6 +216,8 @@ void inet_get_local_port_range(struct ne
325 #ifdef CONFIG_SYSCTL
326 static inline int inet_is_local_reserved_port(struct net *net, int port)
327 {
328+ if (ccs_lport_reserved(port))
329+ return 1;
330 if (!net->ipv4.sysctl_local_reserved_ports)
331 return 0;
332 return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
333@@ -229,6 +231,8 @@ static inline bool sysctl_dev_name_is_al
334 #else
335 static inline int inet_is_local_reserved_port(struct net *net, int port)
336 {
337+ if (ccs_lport_reserved(port))
338+ return 1;
339 return 0;
340 }
341 #endif
342--- linux-4.1.8.orig/kernel/fork.c
343+++ linux-4.1.8/kernel/fork.c
344@@ -257,6 +257,7 @@ void __put_task_struct(struct task_struc
345 delayacct_tsk_free(tsk);
346 put_signal_struct(tsk->signal);
347
348+ ccs_free_task_security(tsk);
349 if (!profile_handoff_task(tsk))
350 free_task(tsk);
351 }
352@@ -1423,6 +1424,9 @@ static struct task_struct *copy_process(
353 goto bad_fork_cleanup_perf;
354 /* copy all the process information */
355 shm_init_task(p);
356+ retval = ccs_alloc_task_security(p);
357+ if (retval)
358+ goto bad_fork_cleanup_audit;
359 retval = copy_semundo(clone_flags, p);
360 if (retval)
361 goto bad_fork_cleanup_audit;
362@@ -1627,6 +1631,7 @@ bad_fork_cleanup_semundo:
363 exit_sem(p);
364 bad_fork_cleanup_audit:
365 audit_free(p);
366+ ccs_free_task_security(p);
367 bad_fork_cleanup_perf:
368 perf_event_free_task(p);
369 bad_fork_cleanup_policy:
370--- linux-4.1.8.orig/kernel/kexec.c
371+++ linux-4.1.8/kernel/kexec.c
372@@ -41,6 +41,7 @@
373 #include <asm/uaccess.h>
374 #include <asm/io.h>
375 #include <asm/sections.h>
376+#include <linux/ccsecurity.h>
377
378 #include <crypto/hash.h>
379 #include <crypto/sha.h>
380@@ -1245,6 +1246,8 @@ SYSCALL_DEFINE4(kexec_load, unsigned lon
381 /* We only trust the superuser with rebooting the system. */
382 if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
383 return -EPERM;
384+ if (!ccs_capable(CCS_SYS_KEXEC_LOAD))
385+ return -EPERM;
386
387 /*
388 * Verify we have a legal set of flags
389--- linux-4.1.8.orig/kernel/module.c
390+++ linux-4.1.8/kernel/module.c
391@@ -61,6 +61,7 @@
392 #include <linux/bsearch.h>
393 #include <uapi/linux/module.h>
394 #include "module-internal.h"
395+#include <linux/ccsecurity.h>
396
397 #define CREATE_TRACE_POINTS
398 #include <trace/events/module.h>
399@@ -799,6 +800,8 @@ SYSCALL_DEFINE2(delete_module, const cha
400
401 if (!capable(CAP_SYS_MODULE) || modules_disabled)
402 return -EPERM;
403+ if (!ccs_capable(CCS_USE_KERNEL_MODULE))
404+ return -EPERM;
405
406 if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
407 return -EFAULT;
408@@ -3155,6 +3158,8 @@ static int may_init_module(void)
409 {
410 if (!capable(CAP_SYS_MODULE) || modules_disabled)
411 return -EPERM;
412+ if (!ccs_capable(CCS_USE_KERNEL_MODULE))
413+ return -EPERM;
414
415 return 0;
416 }
417--- linux-4.1.8.orig/kernel/ptrace.c
418+++ linux-4.1.8/kernel/ptrace.c
419@@ -1034,6 +1034,11 @@ SYSCALL_DEFINE4(ptrace, long, request, l
420 {
421 struct task_struct *child;
422 long ret;
423+ {
424+ const int rc = ccs_ptrace_permission(request, pid);
425+ if (rc)
426+ return rc;
427+ }
428
429 if (request == PTRACE_TRACEME) {
430 ret = ptrace_traceme();
431@@ -1180,6 +1185,11 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_lo
432 {
433 struct task_struct *child;
434 long ret;
435+ {
436+ const int rc = ccs_ptrace_permission(request, pid);
437+ if (rc)
438+ return rc;
439+ }
440
441 if (request == PTRACE_TRACEME) {
442 ret = ptrace_traceme();
443--- linux-4.1.8.orig/kernel/reboot.c
444+++ linux-4.1.8/kernel/reboot.c
445@@ -16,6 +16,7 @@
446 #include <linux/syscalls.h>
447 #include <linux/syscore_ops.h>
448 #include <linux/uaccess.h>
449+#include <linux/ccsecurity.h>
450
451 /*
452 * this indicates whether you can reboot with ctrl-alt-del: the default is yes
453@@ -295,6 +296,8 @@ SYSCALL_DEFINE4(reboot, int, magic1, int
454 magic2 != LINUX_REBOOT_MAGIC2B &&
455 magic2 != LINUX_REBOOT_MAGIC2C))
456 return -EINVAL;
457+ if (!ccs_capable(CCS_SYS_REBOOT))
458+ return -EPERM;
459
460 /*
461 * If pid namespaces are enabled and the current task is in a child
462--- linux-4.1.8.orig/kernel/sched/core.c
463+++ linux-4.1.8/kernel/sched/core.c
464@@ -3145,6 +3145,8 @@ int can_nice(const struct task_struct *p
465 SYSCALL_DEFINE1(nice, int, increment)
466 {
467 long nice, retval;
468+ if (!ccs_capable(CCS_SYS_NICE))
469+ return -EPERM;
470
471 /*
472 * Setpriority might change our priority at the same moment.
473--- linux-4.1.8.orig/kernel/signal.c
474+++ linux-4.1.8/kernel/signal.c
475@@ -2901,6 +2901,8 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const s
476 SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
477 {
478 struct siginfo info;
479+ if (ccs_kill_permission(pid, sig))
480+ return -EPERM;
481
482 info.si_signo = sig;
483 info.si_errno = 0;
484@@ -2969,6 +2971,8 @@ SYSCALL_DEFINE3(tgkill, pid_t, tgid, pid
485 /* This is only valid for single tasks */
486 if (pid <= 0 || tgid <= 0)
487 return -EINVAL;
488+ if (ccs_tgkill_permission(tgid, pid, sig))
489+ return -EPERM;
490
491 return do_tkill(tgid, pid, sig);
492 }
493@@ -2985,6 +2989,8 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int,
494 /* This is only valid for single tasks */
495 if (pid <= 0)
496 return -EINVAL;
497+ if (ccs_tkill_permission(pid, sig))
498+ return -EPERM;
499
500 return do_tkill(0, pid, sig);
501 }
502@@ -2999,6 +3005,8 @@ static int do_rt_sigqueueinfo(pid_t pid,
503 return -EPERM;
504
505 info->si_signo = sig;
506+ if (ccs_sigqueue_permission(pid, sig))
507+ return -EPERM;
508
509 /* POSIX.1b doesn't mention process groups. */
510 return kill_proc_info(sig, info, pid);
511@@ -3047,6 +3055,8 @@ static int do_rt_tgsigqueueinfo(pid_t tg
512 return -EPERM;
513
514 info->si_signo = sig;
515+ if (ccs_tgsigqueue_permission(tgid, pid, sig))
516+ return -EPERM;
517
518 return do_send_specific(tgid, pid, sig, info);
519 }
520--- linux-4.1.8.orig/kernel/sys.c
521+++ linux-4.1.8/kernel/sys.c
522@@ -183,6 +183,10 @@ SYSCALL_DEFINE3(setpriority, int, which,
523
524 if (which > PRIO_USER || which < PRIO_PROCESS)
525 goto out;
526+ if (!ccs_capable(CCS_SYS_NICE)) {
527+ error = -EPERM;
528+ goto out;
529+ }
530
531 /* normalize: avoid signed division (rounding problems) */
532 error = -ESRCH;
533@@ -1222,6 +1226,8 @@ SYSCALL_DEFINE2(sethostname, char __user
534
535 if (len < 0 || len > __NEW_UTS_LEN)
536 return -EINVAL;
537+ if (!ccs_capable(CCS_SYS_SETHOSTNAME))
538+ return -EPERM;
539 down_write(&uts_sem);
540 errno = -EFAULT;
541 if (!copy_from_user(tmp, name, len)) {
542@@ -1272,6 +1278,8 @@ SYSCALL_DEFINE2(setdomainname, char __us
543 return -EPERM;
544 if (len < 0 || len > __NEW_UTS_LEN)
545 return -EINVAL;
546+ if (!ccs_capable(CCS_SYS_SETHOSTNAME))
547+ return -EPERM;
548
549 down_write(&uts_sem);
550 errno = -EFAULT;
551--- linux-4.1.8.orig/kernel/time/ntp.c
552+++ linux-4.1.8/kernel/time/ntp.c
553@@ -16,6 +16,7 @@
554 #include <linux/mm.h>
555 #include <linux/module.h>
556 #include <linux/rtc.h>
557+#include <linux/ccsecurity.h>
558
559 #include "ntp_internal.h"
560
561@@ -626,10 +627,15 @@ int ntp_validate_timex(struct timex *txc
562 if (!(txc->modes & ADJ_OFFSET_READONLY) &&
563 !capable(CAP_SYS_TIME))
564 return -EPERM;
565+ if (!(txc->modes & ADJ_OFFSET_READONLY) &&
566+ !ccs_capable(CCS_SYS_SETTIME))
567+ return -EPERM;
568 } else {
569 /* In order to modify anything, you gotta be super-user! */
570 if (txc->modes && !capable(CAP_SYS_TIME))
571 return -EPERM;
572+ if (txc->modes && !ccs_capable(CCS_SYS_SETTIME))
573+ return -EPERM;
574 /*
575 * if the quartz is off by more than 10% then
576 * something is VERY wrong!
577@@ -642,6 +648,8 @@ int ntp_validate_timex(struct timex *txc
578
579 if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
580 return -EPERM;
581+ if ((txc->modes & ADJ_SETOFFSET) && !ccs_capable(CCS_SYS_SETTIME))
582+ return -EPERM;
583
584 /*
585 * Check for potential multiplication overflows that can
586--- linux-4.1.8.orig/net/ipv4/raw.c
587+++ linux-4.1.8/net/ipv4/raw.c
588@@ -727,6 +727,10 @@ static int raw_recvmsg(struct sock *sk,
589 skb = skb_recv_datagram(sk, flags, noblock, &err);
590 if (!skb)
591 goto out;
592+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
593+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
594+ goto out;
595+ }
596
597 copied = skb->len;
598 if (len < copied) {
599--- linux-4.1.8.orig/net/ipv4/udp.c
600+++ linux-4.1.8/net/ipv4/udp.c
601@@ -1272,6 +1272,10 @@ try_again:
602 &peeked, &off, &err);
603 if (!skb)
604 goto out;
605+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
606+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
607+ goto out;
608+ }
609
610 ulen = skb->len - sizeof(struct udphdr);
611 copied = len;
612--- linux-4.1.8.orig/net/ipv6/raw.c
613+++ linux-4.1.8/net/ipv6/raw.c
614@@ -477,6 +477,10 @@ static int rawv6_recvmsg(struct sock *sk
615 skb = skb_recv_datagram(sk, flags, noblock, &err);
616 if (!skb)
617 goto out;
618+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
619+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
620+ goto out;
621+ }
622
623 copied = skb->len;
624 if (copied > len) {
625--- linux-4.1.8.orig/net/ipv6/udp.c
626+++ linux-4.1.8/net/ipv6/udp.c
627@@ -413,6 +413,10 @@ try_again:
628 &peeked, &off, &err);
629 if (!skb)
630 goto out;
631+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
632+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
633+ goto out;
634+ }
635
636 ulen = skb->len - sizeof(struct udphdr);
637 copied = len;
638--- linux-4.1.8.orig/net/socket.c
639+++ linux-4.1.8/net/socket.c
640@@ -1485,6 +1485,10 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
641 if (err < 0)
642 goto out_fd;
643
644+ if (ccs_socket_post_accept_permission(sock, newsock)) {
645+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
646+ goto out_fd;
647+ }
648 if (upeer_sockaddr) {
649 if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
650 &len, 2) < 0) {
651--- linux-4.1.8.orig/net/unix/af_unix.c
652+++ linux-4.1.8/net/unix/af_unix.c
653@@ -1800,6 +1800,10 @@ static int unix_dgram_recvmsg(struct soc
654 wake_up_interruptible_sync_poll(&u->peer_wait,
655 POLLOUT | POLLWRNORM | POLLWRBAND);
656
657+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
658+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
659+ goto out_unlock;
660+ }
661 if (msg->msg_name)
662 unix_copy_addr(msg, skb->sk);
663
664--- linux-4.1.8.orig/security/Kconfig
665+++ linux-4.1.8/security/Kconfig
666@@ -168,5 +168,7 @@ config DEFAULT_SECURITY
667 default "yama" if DEFAULT_SECURITY_YAMA
668 default "" if DEFAULT_SECURITY_DAC
669
670+source security/ccsecurity/Kconfig
671+
672 endmenu
673
674--- linux-4.1.8.orig/security/Makefile
675+++ linux-4.1.8/security/Makefile
676@@ -27,3 +27,6 @@ obj-$(CONFIG_CGROUP_DEVICE) += device_c
677 # Object integrity file lists
678 subdir-$(CONFIG_INTEGRITY) += integrity
679 obj-$(CONFIG_INTEGRITY) += integrity/
680+
681+subdir-$(CONFIG_CCSECURITY) += ccsecurity
682+obj-$(CONFIG_CCSECURITY) += ccsecurity/
683--- linux-4.1.8.orig/security/security.c
684+++ linux-4.1.8/security/security.c
685@@ -226,7 +226,10 @@ int security_syslog(int type)
686
687 int security_settime(const struct timespec *ts, const struct timezone *tz)
688 {
689- return security_ops->settime(ts, tz);
690+ int error = security_ops->settime(ts, tz);
691+ if (!error)
692+ error = ccs_settime(ts, tz);
693+ return error;
694 }
695
696 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
697@@ -303,17 +306,26 @@ int security_sb_statfs(struct dentry *de
698 int security_sb_mount(const char *dev_name, struct path *path,
699 const char *type, unsigned long flags, void *data)
700 {
701- return security_ops->sb_mount(dev_name, path, type, flags, data);
702+ int error = security_ops->sb_mount(dev_name, path, type, flags, data);
703+ if (!error)
704+ error = ccs_sb_mount(dev_name, path, type, flags, data);
705+ return error;
706 }
707
708 int security_sb_umount(struct vfsmount *mnt, int flags)
709 {
710- return security_ops->sb_umount(mnt, flags);
711+ int error = security_ops->sb_umount(mnt, flags);
712+ if (!error)
713+ error = ccs_sb_umount(mnt, flags);
714+ return error;
715 }
716
717 int security_sb_pivotroot(struct path *old_path, struct path *new_path)
718 {
719- return security_ops->sb_pivotroot(old_path, new_path);
720+ int error = security_ops->sb_pivotroot(old_path, new_path);
721+ if (!error)
722+ error = ccs_sb_pivotroot(old_path, new_path);
723+ return error;
724 }
725
726 int security_sb_set_mnt_opts(struct super_block *sb,
727@@ -410,31 +422,47 @@ EXPORT_SYMBOL(security_old_inode_init_se
728 int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
729 unsigned int dev)
730 {
731+ int error;
732 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
733 return 0;
734+ error = ccs_path_mknod(dir, dentry, mode, dev);
735+ if (error)
736+ return error;
737 return security_ops->path_mknod(dir, dentry, mode, dev);
738 }
739 EXPORT_SYMBOL(security_path_mknod);
740
741 int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
742 {
743+ int error;
744 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
745 return 0;
746+ error = ccs_path_mkdir(dir, dentry, mode);
747+ if (error)
748+ return error;
749 return security_ops->path_mkdir(dir, dentry, mode);
750 }
751 EXPORT_SYMBOL(security_path_mkdir);
752
753 int security_path_rmdir(struct path *dir, struct dentry *dentry)
754 {
755+ int error;
756 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
757 return 0;
758+ error = ccs_path_rmdir(dir, dentry);
759+ if (error)
760+ return error;
761 return security_ops->path_rmdir(dir, dentry);
762 }
763
764 int security_path_unlink(struct path *dir, struct dentry *dentry)
765 {
766+ int error;
767 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
768 return 0;
769+ error = ccs_path_unlink(dir, dentry);
770+ if (error)
771+ return error;
772 return security_ops->path_unlink(dir, dentry);
773 }
774 EXPORT_SYMBOL(security_path_unlink);
775@@ -442,16 +470,24 @@ EXPORT_SYMBOL(security_path_unlink);
776 int security_path_symlink(struct path *dir, struct dentry *dentry,
777 const char *old_name)
778 {
779+ int error;
780 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
781 return 0;
782+ error = ccs_path_symlink(dir, dentry, old_name);
783+ if (error)
784+ return error;
785 return security_ops->path_symlink(dir, dentry, old_name);
786 }
787
788 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
789 struct dentry *new_dentry)
790 {
791+ int error;
792 if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
793 return 0;
794+ error = ccs_path_link(old_dentry, new_dir, new_dentry);
795+ if (error)
796+ return error;
797 return security_ops->path_link(old_dentry, new_dir, new_dentry);
798 }
799
800@@ -459,6 +495,7 @@ int security_path_rename(struct path *ol
801 struct path *new_dir, struct dentry *new_dentry,
802 unsigned int flags)
803 {
804+ int error;
805 if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
806 (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
807 return 0;
808@@ -468,8 +505,15 @@ int security_path_rename(struct path *ol
809 old_dir, old_dentry);
810 if (err)
811 return err;
812+ err = ccs_path_rename(new_dir, new_dentry, old_dir,
813+ old_dentry);
814+ if (err)
815+ return err;
816 }
817
818+ error = ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
819+ if (error)
820+ return error;
821 return security_ops->path_rename(old_dir, old_dentry, new_dir,
822 new_dentry);
823 }
824@@ -477,27 +521,42 @@ EXPORT_SYMBOL(security_path_rename);
825
826 int security_path_truncate(struct path *path)
827 {
828+ int error;
829 if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
830 return 0;
831+ error = ccs_path_truncate(path);
832+ if (error)
833+ return error;
834 return security_ops->path_truncate(path);
835 }
836
837 int security_path_chmod(struct path *path, umode_t mode)
838 {
839+ int error;
840 if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
841 return 0;
842+ error = ccs_path_chmod(path, mode);
843+ if (error)
844+ return error;
845 return security_ops->path_chmod(path, mode);
846 }
847
848 int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
849 {
850+ int error;
851 if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
852 return 0;
853+ error = ccs_path_chown(path, uid, gid);
854+ if (error)
855+ return error;
856 return security_ops->path_chown(path, uid, gid);
857 }
858
859 int security_path_chroot(struct path *path)
860 {
861+ int error = ccs_path_chroot(path);
862+ if (error)
863+ return error;
864 return security_ops->path_chroot(path);
865 }
866 #endif
867@@ -610,9 +669,13 @@ EXPORT_SYMBOL_GPL(security_inode_setattr
868
869 int security_inode_getattr(const struct path *path)
870 {
871+ int error;
872 if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
873 return 0;
874- return security_ops->inode_getattr(path);
875+ error = security_ops->inode_getattr(path);
876+ if (!error)
877+ error = ccs_inode_getattr(path);
878+ return error;
879 }
880
881 int security_inode_setxattr(struct dentry *dentry, const char *name,
882@@ -729,7 +792,10 @@ void security_file_free(struct file *fil
883
884 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
885 {
886- return security_ops->file_ioctl(file, cmd, arg);
887+ int error = security_ops->file_ioctl(file, cmd, arg);
888+ if (!error)
889+ error = ccs_file_ioctl(file, cmd, arg);
890+ return error;
891 }
892
893 static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
894@@ -794,7 +860,10 @@ int security_file_lock(struct file *file
895
896 int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
897 {
898- return security_ops->file_fcntl(file, cmd, arg);
899+ int error = security_ops->file_fcntl(file, cmd, arg);
900+ if (!error)
901+ error = ccs_file_fcntl(file, cmd, arg);
902+ return error;
903 }
904
905 void security_file_set_fowner(struct file *file)
906@@ -818,6 +887,8 @@ int security_file_open(struct file *file
907 int ret;
908
909 ret = security_ops->file_open(file, cred);
910+ if (!ret)
911+ ret = ccs_file_open(file, cred);
912 if (ret)
913 return ret;
914
915@@ -1168,7 +1239,10 @@ EXPORT_SYMBOL(security_unix_may_send);
916
917 int security_socket_create(int family, int type, int protocol, int kern)
918 {
919- return security_ops->socket_create(family, type, protocol, kern);
920+ int error = security_ops->socket_create(family, type, protocol, kern);
921+ if (!error)
922+ error = ccs_socket_create(family, type, protocol, kern);
923+ return error;
924 }
925
926 int security_socket_post_create(struct socket *sock, int family,
927@@ -1180,17 +1254,26 @@ int security_socket_post_create(struct s
928
929 int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
930 {
931- return security_ops->socket_bind(sock, address, addrlen);
932+ int error = security_ops->socket_bind(sock, address, addrlen);
933+ if (!error)
934+ error = ccs_socket_bind(sock, address, addrlen);
935+ return error;
936 }
937
938 int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
939 {
940- return security_ops->socket_connect(sock, address, addrlen);
941+ int error = security_ops->socket_connect(sock, address, addrlen);
942+ if (!error)
943+ error = ccs_socket_connect(sock, address, addrlen);
944+ return error;
945 }
946
947 int security_socket_listen(struct socket *sock, int backlog)
948 {
949- return security_ops->socket_listen(sock, backlog);
950+ int error = security_ops->socket_listen(sock, backlog);
951+ if (!error)
952+ error = ccs_socket_listen(sock, backlog);
953+ return error;
954 }
955
956 int security_socket_accept(struct socket *sock, struct socket *newsock)
957@@ -1200,7 +1283,10 @@ int security_socket_accept(struct socket
958
959 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
960 {
961- return security_ops->socket_sendmsg(sock, msg, size);
962+ int error = security_ops->socket_sendmsg(sock, msg, size);
963+ if (!error)
964+ error = ccs_socket_sendmsg(sock, msg, size);
965+ return error;
966 }
967
968 int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
diff --git a/recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.2.diff b/recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.2.diff
new file mode 100644
index 0000000..d1b021a
--- /dev/null
+++ b/recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.2.diff
@@ -0,0 +1,681 @@
1This is TOMOYO Linux patch for kernel 4.2.1.
2
3Source code for this patch is https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.2.1.tar.xz
4---
5 fs/exec.c | 2 -
6 fs/open.c | 2 +
7 fs/proc/version.c | 7 +++++
8 include/linux/init_task.h | 9 ++++++
9 include/linux/sched.h | 6 ++++
10 include/linux/security.h | 62 ++++++++++++++++++++++++++++------------------
11 include/net/ip.h | 4 ++
12 kernel/fork.c | 5 +++
13 kernel/kexec.c | 3 ++
14 kernel/module.c | 5 +++
15 kernel/ptrace.c | 10 +++++++
16 kernel/reboot.c | 3 ++
17 kernel/sched/core.c | 2 +
18 kernel/signal.c | 10 +++++++
19 kernel/sys.c | 8 +++++
20 kernel/time/ntp.c | 8 +++++
21 net/ipv4/raw.c | 4 ++
22 net/ipv4/udp.c | 4 ++
23 net/ipv6/raw.c | 4 ++
24 net/ipv6/udp.c | 4 ++
25 net/socket.c | 4 ++
26 net/unix/af_unix.c | 4 ++
27 security/Kconfig | 2 +
28 security/Makefile | 3 ++
29 24 files changed, 150 insertions(+), 25 deletions(-)
30
31--- linux-4.2.1.orig/fs/exec.c
32+++ linux-4.2.1/fs/exec.c
33@@ -1461,7 +1461,7 @@ static int exec_binprm(struct linux_binp
34 old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
35 rcu_read_unlock();
36
37- ret = search_binary_handler(bprm);
38+ ret = ccs_search_binary_handler(bprm);
39 if (ret >= 0) {
40 audit_bprm(bprm);
41 trace_sched_process_exec(current, old_pid, bprm);
42--- linux-4.2.1.orig/fs/open.c
43+++ linux-4.2.1/fs/open.c
44@@ -1117,6 +1117,8 @@ EXPORT_SYMBOL(sys_close);
45 */
46 SYSCALL_DEFINE0(vhangup)
47 {
48+ if (!ccs_capable(CCS_SYS_VHANGUP))
49+ return -EPERM;
50 if (capable(CAP_SYS_TTY_CONFIG)) {
51 tty_vhangup_self();
52 return 0;
53--- linux-4.2.1.orig/fs/proc/version.c
54+++ linux-4.2.1/fs/proc/version.c
55@@ -32,3 +32,10 @@ static int __init proc_version_init(void
56 return 0;
57 }
58 fs_initcall(proc_version_init);
59+
60+static int __init ccs_show_version(void)
61+{
62+ printk(KERN_INFO "Hook version: 4.2 2015/09/26\n");
63+ return 0;
64+}
65+fs_initcall(ccs_show_version);
66--- linux-4.2.1.orig/include/linux/init_task.h
67+++ linux-4.2.1/include/linux/init_task.h
68@@ -173,6 +173,14 @@ extern struct task_group root_task_group
69 # define INIT_KASAN(tsk)
70 #endif
71
72+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
73+#define INIT_CCSECURITY \
74+ .ccs_domain_info = NULL, \
75+ .ccs_flags = 0,
76+#else
77+#define INIT_CCSECURITY
78+#endif
79+
80 /*
81 * INIT_TASK is used to set up the first task table, touch at
82 * your own risk!. Base=0, limit=0x1fffff (=2MB)
83@@ -249,6 +257,7 @@ extern struct task_group root_task_group
84 INIT_VTIME(tsk) \
85 INIT_NUMA_BALANCING(tsk) \
86 INIT_KASAN(tsk) \
87+ INIT_CCSECURITY \
88 }
89
90
91--- linux-4.2.1.orig/include/linux/sched.h
92+++ linux-4.2.1/include/linux/sched.h
93@@ -6,6 +6,8 @@
94 #include <linux/sched/prio.h>
95
96
97+struct ccs_domain_info;
98+
99 struct sched_param {
100 int sched_priority;
101 };
102@@ -1776,6 +1778,10 @@ struct task_struct {
103 unsigned long task_state_change;
104 #endif
105 int pagefault_disabled;
106+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
107+ struct ccs_domain_info *ccs_domain_info;
108+ u32 ccs_flags;
109+#endif
110 /* CPU-specific state of this task */
111 struct thread_struct thread;
112 /*
113--- linux-4.2.1.orig/include/linux/security.h
114+++ linux-4.2.1/include/linux/security.h
115@@ -53,6 +53,7 @@ struct msg_queue;
116 struct xattr;
117 struct xfrm_sec_ctx;
118 struct mm_struct;
119+#include <linux/ccsecurity.h>
120
121 /* If capable should audit the security request */
122 #define SECURITY_CAP_NOAUDIT 0
123@@ -460,7 +461,10 @@ static inline int security_syslog(int ty
124 static inline int security_settime(const struct timespec *ts,
125 const struct timezone *tz)
126 {
127- return cap_settime(ts, tz);
128+ int error = cap_settime(ts, tz);
129+ if (!error)
130+ error = ccs_settime(ts, tz);
131+ return error;
132 }
133
134 static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
135@@ -529,18 +533,18 @@ static inline int security_sb_mount(cons
136 const char *type, unsigned long flags,
137 void *data)
138 {
139- return 0;
140+ return ccs_sb_mount(dev_name, path, type, flags, data);
141 }
142
143 static inline int security_sb_umount(struct vfsmount *mnt, int flags)
144 {
145- return 0;
146+ return ccs_sb_umount(mnt, flags);
147 }
148
149 static inline int security_sb_pivotroot(struct path *old_path,
150 struct path *new_path)
151 {
152- return 0;
153+ return ccs_sb_pivotroot(old_path, new_path);
154 }
155
156 static inline int security_sb_set_mnt_opts(struct super_block *sb,
157@@ -679,7 +683,7 @@ static inline int security_inode_setattr
158
159 static inline int security_inode_getattr(const struct path *path)
160 {
161- return 0;
162+ return ccs_inode_getattr(path);
163 }
164
165 static inline int security_inode_setxattr(struct dentry *dentry,
166@@ -755,7 +759,7 @@ static inline void security_file_free(st
167 static inline int security_file_ioctl(struct file *file, unsigned int cmd,
168 unsigned long arg)
169 {
170- return 0;
171+ return ccs_file_ioctl(file, cmd, arg);
172 }
173
174 static inline int security_mmap_file(struct file *file, unsigned long prot,
175@@ -784,7 +788,7 @@ static inline int security_file_lock(str
176 static inline int security_file_fcntl(struct file *file, unsigned int cmd,
177 unsigned long arg)
178 {
179- return 0;
180+ return ccs_file_fcntl(file, cmd, arg);
181 }
182
183 static inline void security_file_set_fowner(struct file *file)
184@@ -807,7 +811,7 @@ static inline int security_file_receive(
185 static inline int security_file_open(struct file *file,
186 const struct cred *cred)
187 {
188- return 0;
189+ return ccs_file_open(file, cred);
190 }
191
192 static inline int security_task_create(unsigned long clone_flags)
193@@ -1169,7 +1173,7 @@ static inline int security_unix_may_send
194 static inline int security_socket_create(int family, int type,
195 int protocol, int kern)
196 {
197- return 0;
198+ return ccs_socket_create(family, type, protocol, kern);
199 }
200
201 static inline int security_socket_post_create(struct socket *sock,
202@@ -1184,19 +1188,19 @@ static inline int security_socket_bind(s
203 struct sockaddr *address,
204 int addrlen)
205 {
206- return 0;
207+ return ccs_socket_bind(sock, address, addrlen);
208 }
209
210 static inline int security_socket_connect(struct socket *sock,
211 struct sockaddr *address,
212 int addrlen)
213 {
214- return 0;
215+ return ccs_socket_connect(sock, address, addrlen);
216 }
217
218 static inline int security_socket_listen(struct socket *sock, int backlog)
219 {
220- return 0;
221+ return ccs_socket_listen(sock, backlog);
222 }
223
224 static inline int security_socket_accept(struct socket *sock,
225@@ -1208,7 +1212,7 @@ static inline int security_socket_accept
226 static inline int security_socket_sendmsg(struct socket *sock,
227 struct msghdr *msg, int size)
228 {
229- return 0;
230+ return ccs_socket_sendmsg(sock, msg, size);
231 }
232
233 static inline int security_socket_recvmsg(struct socket *sock,
234@@ -1450,42 +1454,42 @@ int security_path_chroot(struct path *pa
235 #else /* CONFIG_SECURITY_PATH */
236 static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
237 {
238- return 0;
239+ return ccs_path_unlink(dir, dentry);
240 }
241
242 static inline int security_path_mkdir(struct path *dir, struct dentry *dentry,
243 umode_t mode)
244 {
245- return 0;
246+ return ccs_path_mkdir(dir, dentry, mode);
247 }
248
249 static inline int security_path_rmdir(struct path *dir, struct dentry *dentry)
250 {
251- return 0;
252+ return ccs_path_rmdir(dir, dentry);
253 }
254
255 static inline int security_path_mknod(struct path *dir, struct dentry *dentry,
256 umode_t mode, unsigned int dev)
257 {
258- return 0;
259+ return ccs_path_mknod(dir, dentry, mode, dev);
260 }
261
262 static inline int security_path_truncate(struct path *path)
263 {
264- return 0;
265+ return ccs_path_truncate(path);
266 }
267
268 static inline int security_path_symlink(struct path *dir, struct dentry *dentry,
269 const char *old_name)
270 {
271- return 0;
272+ return ccs_path_symlink(dir, dentry, old_name);
273 }
274
275 static inline int security_path_link(struct dentry *old_dentry,
276 struct path *new_dir,
277 struct dentry *new_dentry)
278 {
279- return 0;
280+ return ccs_path_link(old_dentry, new_dir, new_dentry);
281 }
282
283 static inline int security_path_rename(struct path *old_dir,
284@@ -1494,22 +1498,32 @@ static inline int security_path_rename(s
285 struct dentry *new_dentry,
286 unsigned int flags)
287 {
288- return 0;
289+ /*
290+ * Not using RENAME_EXCHANGE here in order to avoid KABI breakage
291+ * by doing "#include <uapi/linux/fs.h>" .
292+ */
293+ if (flags & (1 << 1)) {
294+ int err = ccs_path_rename(new_dir, new_dentry, old_dir,
295+ old_dentry);
296+ if (err)
297+ return err;
298+ }
299+ return ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
300 }
301
302 static inline int security_path_chmod(struct path *path, umode_t mode)
303 {
304- return 0;
305+ return ccs_path_chmod(path, mode);
306 }
307
308 static inline int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
309 {
310- return 0;
311+ return ccs_path_chown(path, uid, gid);
312 }
313
314 static inline int security_path_chroot(struct path *path)
315 {
316- return 0;
317+ return ccs_path_chroot(path);
318 }
319 #endif /* CONFIG_SECURITY_PATH */
320
321--- linux-4.2.1.orig/include/net/ip.h
322+++ linux-4.2.1/include/net/ip.h
323@@ -217,6 +217,8 @@ void inet_get_local_port_range(struct ne
324 #ifdef CONFIG_SYSCTL
325 static inline int inet_is_local_reserved_port(struct net *net, int port)
326 {
327+ if (ccs_lport_reserved(port))
328+ return 1;
329 if (!net->ipv4.sysctl_local_reserved_ports)
330 return 0;
331 return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
332@@ -230,6 +232,8 @@ static inline bool sysctl_dev_name_is_al
333 #else
334 static inline int inet_is_local_reserved_port(struct net *net, int port)
335 {
336+ if (ccs_lport_reserved(port))
337+ return 1;
338 return 0;
339 }
340 #endif
341--- linux-4.2.1.orig/kernel/fork.c
342+++ linux-4.2.1/kernel/fork.c
343@@ -257,6 +257,7 @@ void __put_task_struct(struct task_struc
344 delayacct_tsk_free(tsk);
345 put_signal_struct(tsk->signal);
346
347+ ccs_free_task_security(tsk);
348 if (!profile_handoff_task(tsk))
349 free_task(tsk);
350 }
351@@ -1425,6 +1426,9 @@ static struct task_struct *copy_process(
352 goto bad_fork_cleanup_perf;
353 /* copy all the process information */
354 shm_init_task(p);
355+ retval = ccs_alloc_task_security(p);
356+ if (retval)
357+ goto bad_fork_cleanup_audit;
358 retval = copy_semundo(clone_flags, p);
359 if (retval)
360 goto bad_fork_cleanup_audit;
361@@ -1629,6 +1633,7 @@ bad_fork_cleanup_semundo:
362 exit_sem(p);
363 bad_fork_cleanup_audit:
364 audit_free(p);
365+ ccs_free_task_security(p);
366 bad_fork_cleanup_perf:
367 perf_event_free_task(p);
368 bad_fork_cleanup_policy:
369--- linux-4.2.1.orig/kernel/kexec.c
370+++ linux-4.2.1/kernel/kexec.c
371@@ -41,6 +41,7 @@
372 #include <asm/uaccess.h>
373 #include <asm/io.h>
374 #include <asm/sections.h>
375+#include <linux/ccsecurity.h>
376
377 #include <crypto/hash.h>
378 #include <crypto/sha.h>
379@@ -1256,6 +1257,8 @@ SYSCALL_DEFINE4(kexec_load, unsigned lon
380 /* We only trust the superuser with rebooting the system. */
381 if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
382 return -EPERM;
383+ if (!ccs_capable(CCS_SYS_KEXEC_LOAD))
384+ return -EPERM;
385
386 /*
387 * Verify we have a legal set of flags
388--- linux-4.2.1.orig/kernel/module.c
389+++ linux-4.2.1/kernel/module.c
390@@ -61,6 +61,7 @@
391 #include <linux/bsearch.h>
392 #include <uapi/linux/module.h>
393 #include "module-internal.h"
394+#include <linux/ccsecurity.h>
395
396 #define CREATE_TRACE_POINTS
397 #include <trace/events/module.h>
398@@ -956,6 +957,8 @@ SYSCALL_DEFINE2(delete_module, const cha
399
400 if (!capable(CAP_SYS_MODULE) || modules_disabled)
401 return -EPERM;
402+ if (!ccs_capable(CCS_USE_KERNEL_MODULE))
403+ return -EPERM;
404
405 if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
406 return -EFAULT;
407@@ -3311,6 +3314,8 @@ static int may_init_module(void)
408 {
409 if (!capable(CAP_SYS_MODULE) || modules_disabled)
410 return -EPERM;
411+ if (!ccs_capable(CCS_USE_KERNEL_MODULE))
412+ return -EPERM;
413
414 return 0;
415 }
416--- linux-4.2.1.orig/kernel/ptrace.c
417+++ linux-4.2.1/kernel/ptrace.c
418@@ -1034,6 +1034,11 @@ SYSCALL_DEFINE4(ptrace, long, request, l
419 {
420 struct task_struct *child;
421 long ret;
422+ {
423+ const int rc = ccs_ptrace_permission(request, pid);
424+ if (rc)
425+ return rc;
426+ }
427
428 if (request == PTRACE_TRACEME) {
429 ret = ptrace_traceme();
430@@ -1180,6 +1185,11 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_lo
431 {
432 struct task_struct *child;
433 long ret;
434+ {
435+ const int rc = ccs_ptrace_permission(request, pid);
436+ if (rc)
437+ return rc;
438+ }
439
440 if (request == PTRACE_TRACEME) {
441 ret = ptrace_traceme();
442--- linux-4.2.1.orig/kernel/reboot.c
443+++ linux-4.2.1/kernel/reboot.c
444@@ -16,6 +16,7 @@
445 #include <linux/syscalls.h>
446 #include <linux/syscore_ops.h>
447 #include <linux/uaccess.h>
448+#include <linux/ccsecurity.h>
449
450 /*
451 * this indicates whether you can reboot with ctrl-alt-del: the default is yes
452@@ -295,6 +296,8 @@ SYSCALL_DEFINE4(reboot, int, magic1, int
453 magic2 != LINUX_REBOOT_MAGIC2B &&
454 magic2 != LINUX_REBOOT_MAGIC2C))
455 return -EINVAL;
456+ if (!ccs_capable(CCS_SYS_REBOOT))
457+ return -EPERM;
458
459 /*
460 * If pid namespaces are enabled and the current task is in a child
461--- linux-4.2.1.orig/kernel/sched/core.c
462+++ linux-4.2.1/kernel/sched/core.c
463@@ -3402,6 +3402,8 @@ int can_nice(const struct task_struct *p
464 SYSCALL_DEFINE1(nice, int, increment)
465 {
466 long nice, retval;
467+ if (!ccs_capable(CCS_SYS_NICE))
468+ return -EPERM;
469
470 /*
471 * Setpriority might change our priority at the same moment.
472--- linux-4.2.1.orig/kernel/signal.c
473+++ linux-4.2.1/kernel/signal.c
474@@ -2896,6 +2896,8 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const s
475 SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
476 {
477 struct siginfo info;
478+ if (ccs_kill_permission(pid, sig))
479+ return -EPERM;
480
481 info.si_signo = sig;
482 info.si_errno = 0;
483@@ -2964,6 +2966,8 @@ SYSCALL_DEFINE3(tgkill, pid_t, tgid, pid
484 /* This is only valid for single tasks */
485 if (pid <= 0 || tgid <= 0)
486 return -EINVAL;
487+ if (ccs_tgkill_permission(tgid, pid, sig))
488+ return -EPERM;
489
490 return do_tkill(tgid, pid, sig);
491 }
492@@ -2980,6 +2984,8 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int,
493 /* This is only valid for single tasks */
494 if (pid <= 0)
495 return -EINVAL;
496+ if (ccs_tkill_permission(pid, sig))
497+ return -EPERM;
498
499 return do_tkill(0, pid, sig);
500 }
501@@ -2994,6 +3000,8 @@ static int do_rt_sigqueueinfo(pid_t pid,
502 return -EPERM;
503
504 info->si_signo = sig;
505+ if (ccs_sigqueue_permission(pid, sig))
506+ return -EPERM;
507
508 /* POSIX.1b doesn't mention process groups. */
509 return kill_proc_info(sig, info, pid);
510@@ -3042,6 +3050,8 @@ static int do_rt_tgsigqueueinfo(pid_t tg
511 return -EPERM;
512
513 info->si_signo = sig;
514+ if (ccs_tgsigqueue_permission(tgid, pid, sig))
515+ return -EPERM;
516
517 return do_send_specific(tgid, pid, sig, info);
518 }
519--- linux-4.2.1.orig/kernel/sys.c
520+++ linux-4.2.1/kernel/sys.c
521@@ -183,6 +183,10 @@ SYSCALL_DEFINE3(setpriority, int, which,
522
523 if (which > PRIO_USER || which < PRIO_PROCESS)
524 goto out;
525+ if (!ccs_capable(CCS_SYS_NICE)) {
526+ error = -EPERM;
527+ goto out;
528+ }
529
530 /* normalize: avoid signed division (rounding problems) */
531 error = -ESRCH;
532@@ -1222,6 +1226,8 @@ SYSCALL_DEFINE2(sethostname, char __user
533
534 if (len < 0 || len > __NEW_UTS_LEN)
535 return -EINVAL;
536+ if (!ccs_capable(CCS_SYS_SETHOSTNAME))
537+ return -EPERM;
538 down_write(&uts_sem);
539 errno = -EFAULT;
540 if (!copy_from_user(tmp, name, len)) {
541@@ -1272,6 +1278,8 @@ SYSCALL_DEFINE2(setdomainname, char __us
542 return -EPERM;
543 if (len < 0 || len > __NEW_UTS_LEN)
544 return -EINVAL;
545+ if (!ccs_capable(CCS_SYS_SETHOSTNAME))
546+ return -EPERM;
547
548 down_write(&uts_sem);
549 errno = -EFAULT;
550--- linux-4.2.1.orig/kernel/time/ntp.c
551+++ linux-4.2.1/kernel/time/ntp.c
552@@ -16,6 +16,7 @@
553 #include <linux/mm.h>
554 #include <linux/module.h>
555 #include <linux/rtc.h>
556+#include <linux/ccsecurity.h>
557
558 #include "ntp_internal.h"
559
560@@ -655,10 +656,15 @@ int ntp_validate_timex(struct timex *txc
561 if (!(txc->modes & ADJ_OFFSET_READONLY) &&
562 !capable(CAP_SYS_TIME))
563 return -EPERM;
564+ if (!(txc->modes & ADJ_OFFSET_READONLY) &&
565+ !ccs_capable(CCS_SYS_SETTIME))
566+ return -EPERM;
567 } else {
568 /* In order to modify anything, you gotta be super-user! */
569 if (txc->modes && !capable(CAP_SYS_TIME))
570 return -EPERM;
571+ if (txc->modes && !ccs_capable(CCS_SYS_SETTIME))
572+ return -EPERM;
573 /*
574 * if the quartz is off by more than 10% then
575 * something is VERY wrong!
576@@ -671,6 +677,8 @@ int ntp_validate_timex(struct timex *txc
577
578 if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
579 return -EPERM;
580+ if ((txc->modes & ADJ_SETOFFSET) && !ccs_capable(CCS_SYS_SETTIME))
581+ return -EPERM;
582
583 /*
584 * Check for potential multiplication overflows that can
585--- linux-4.2.1.orig/net/ipv4/raw.c
586+++ linux-4.2.1/net/ipv4/raw.c
587@@ -727,6 +727,10 @@ static int raw_recvmsg(struct sock *sk,
588 skb = skb_recv_datagram(sk, flags, noblock, &err);
589 if (!skb)
590 goto out;
591+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
592+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
593+ goto out;
594+ }
595
596 copied = skb->len;
597 if (len < copied) {
598--- linux-4.2.1.orig/net/ipv4/udp.c
599+++ linux-4.2.1/net/ipv4/udp.c
600@@ -1272,6 +1272,10 @@ try_again:
601 &peeked, &off, &err);
602 if (!skb)
603 goto out;
604+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
605+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
606+ goto out;
607+ }
608
609 ulen = skb->len - sizeof(struct udphdr);
610 copied = len;
611--- linux-4.2.1.orig/net/ipv6/raw.c
612+++ linux-4.2.1/net/ipv6/raw.c
613@@ -477,6 +477,10 @@ static int rawv6_recvmsg(struct sock *sk
614 skb = skb_recv_datagram(sk, flags, noblock, &err);
615 if (!skb)
616 goto out;
617+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
618+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
619+ goto out;
620+ }
621
622 copied = skb->len;
623 if (copied > len) {
624--- linux-4.2.1.orig/net/ipv6/udp.c
625+++ linux-4.2.1/net/ipv6/udp.c
626@@ -413,6 +413,10 @@ try_again:
627 &peeked, &off, &err);
628 if (!skb)
629 goto out;
630+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
631+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
632+ goto out;
633+ }
634
635 ulen = skb->len - sizeof(struct udphdr);
636 copied = len;
637--- linux-4.2.1.orig/net/socket.c
638+++ linux-4.2.1/net/socket.c
639@@ -1482,6 +1482,10 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
640 if (err < 0)
641 goto out_fd;
642
643+ if (ccs_socket_post_accept_permission(sock, newsock)) {
644+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
645+ goto out_fd;
646+ }
647 if (upeer_sockaddr) {
648 if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
649 &len, 2) < 0) {
650--- linux-4.2.1.orig/net/unix/af_unix.c
651+++ linux-4.2.1/net/unix/af_unix.c
652@@ -1911,6 +1911,10 @@ static int unix_dgram_recvmsg(struct soc
653 wake_up_interruptible_sync_poll(&u->peer_wait,
654 POLLOUT | POLLWRNORM | POLLWRBAND);
655
656+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
657+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
658+ goto out_unlock;
659+ }
660 if (msg->msg_name)
661 unix_copy_addr(msg, skb->sk);
662
663--- linux-4.2.1.orig/security/Kconfig
664+++ linux-4.2.1/security/Kconfig
665@@ -168,5 +168,7 @@ config DEFAULT_SECURITY
666 default "yama" if DEFAULT_SECURITY_YAMA
667 default "" if DEFAULT_SECURITY_DAC
668
669+source security/ccsecurity/Kconfig
670+
671 endmenu
672
673--- linux-4.2.1.orig/security/Makefile
674+++ linux-4.2.1/security/Makefile
675@@ -27,3 +27,6 @@ obj-$(CONFIG_CGROUP_DEVICE) += device_c
676 # Object integrity file lists
677 subdir-$(CONFIG_INTEGRITY) += integrity
678 obj-$(CONFIG_INTEGRITY) += integrity/
679+
680+subdir-$(CONFIG_CCSECURITY) += ccsecurity
681+obj-$(CONFIG_CCSECURITY) += ccsecurity/
diff --git a/recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto.4.1.patch b/recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto.4.1.patch
new file mode 100644
index 0000000..611d396
--- /dev/null
+++ b/recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto.4.1.patch
@@ -0,0 +1,1029 @@
1From 13c3a21c549a87cf7410bd2ff88eeb6cb1ddda8c Mon Sep 17 00:00:00 2001
2From: invalid_git config <unknown@unknown>
3Date: Sun, 25 Oct 2015 12:34:02 -0700
4Subject: [PATCH] This is TOMOYO Linux patch for kernel 4.1.8.
5
6Source code for this patch is https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.1.8.tar.xz
7---
8 fs/exec.c | 2 +-
9 fs/open.c | 2 +
10 fs/proc/version.c | 7 +++
11 include/linux/init_task.h | 9 ++++
12 include/linux/sched.h | 6 +++
13 include/linux/security.h | 62 ++++++++++++++++----------
14 include/net/ip.h | 4 ++
15 kernel/fork.c | 5 +++
16 kernel/kexec.c | 3 ++
17 kernel/module.c | 5 +++
18 kernel/ptrace.c | 10 +++++
19 kernel/reboot.c | 3 ++
20 kernel/sched/core.c | 2 +
21 kernel/signal.c | 10 +++++
22 kernel/sys.c | 8 ++++
23 kernel/time/ntp.c | 8 ++++
24 net/ipv4/raw.c | 4 ++
25 net/ipv4/udp.c | 4 ++
26 net/ipv6/raw.c | 4 ++
27 net/ipv6/udp.c | 4 ++
28 net/socket.c | 4 ++
29 net/unix/af_unix.c | 4 ++
30 security/Kconfig | 2 +
31 security/Makefile | 3 ++
32 security/security.c | 110 +++++++++++++++++++++++++++++++++++++++++-----
33 25 files changed, 248 insertions(+), 37 deletions(-)
34
35diff --git a/fs/exec.c b/fs/exec.c
36index 1977c2a..5c69bcc 100644
37--- a/fs/exec.c
38+++ b/fs/exec.c
39@@ -1461,7 +1461,7 @@ static int exec_binprm(struct linux_binprm *bprm)
40 old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
41 rcu_read_unlock();
42
43- ret = search_binary_handler(bprm);
44+ ret = ccs_search_binary_handler(bprm);
45 if (ret >= 0) {
46 audit_bprm(bprm);
47 trace_sched_process_exec(current, old_pid, bprm);
48diff --git a/fs/open.c b/fs/open.c
49index a94e2e7..6c79f72c 100644
50--- a/fs/open.c
51+++ b/fs/open.c
52@@ -1108,6 +1108,8 @@ EXPORT_SYMBOL(sys_close);
53 */
54 SYSCALL_DEFINE0(vhangup)
55 {
56+ if (!ccs_capable(CCS_SYS_VHANGUP))
57+ return -EPERM;
58 if (capable(CAP_SYS_TTY_CONFIG)) {
59 tty_vhangup_self();
60 return 0;
61diff --git a/fs/proc/version.c b/fs/proc/version.c
62index d2154eb..a84ba8d 100644
63--- a/fs/proc/version.c
64+++ b/fs/proc/version.c
65@@ -32,3 +32,10 @@ static int __init proc_version_init(void)
66 return 0;
67 }
68 fs_initcall(proc_version_init);
69+
70+static int __init ccs_show_version(void)
71+{
72+ printk(KERN_INFO "Hook version: 4.1.8 2015/09/26\n");
73+ return 0;
74+}
75+fs_initcall(ccs_show_version);
76diff --git a/include/linux/init_task.h b/include/linux/init_task.h
77index 696d223..c112803 100644
78--- a/include/linux/init_task.h
79+++ b/include/linux/init_task.h
80@@ -182,6 +182,14 @@ extern struct task_group root_task_group;
81 # define INIT_KASAN(tsk)
82 #endif
83
84+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
85+#define INIT_CCSECURITY \
86+ .ccs_domain_info = NULL, \
87+ .ccs_flags = 0,
88+#else
89+#define INIT_CCSECURITY
90+#endif
91+
92 /*
93 * INIT_TASK is used to set up the first task table, touch at
94 * your own risk!. Base=0, limit=0x1fffff (=2MB)
95@@ -258,6 +266,7 @@ extern struct task_group root_task_group;
96 INIT_VTIME(tsk) \
97 INIT_NUMA_BALANCING(tsk) \
98 INIT_KASAN(tsk) \
99+ INIT_CCSECURITY \
100 }
101
102
103diff --git a/include/linux/sched.h b/include/linux/sched.h
104index 26a2e61..c32a704 100644
105--- a/include/linux/sched.h
106+++ b/include/linux/sched.h
107@@ -6,6 +6,8 @@
108 #include <linux/sched/prio.h>
109
110
111+struct ccs_domain_info;
112+
113 struct sched_param {
114 int sched_priority;
115 };
116@@ -1724,6 +1726,10 @@ struct task_struct {
117 #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
118 unsigned long task_state_change;
119 #endif
120+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
121+ struct ccs_domain_info *ccs_domain_info;
122+ u32 ccs_flags;
123+#endif
124 };
125
126 /* Future-safe accessor for struct task_struct's cpus_allowed. */
127diff --git a/include/linux/security.h b/include/linux/security.h
128index 18264ea..621562b 100644
129--- a/include/linux/security.h
130+++ b/include/linux/security.h
131@@ -53,6 +53,7 @@ struct msg_queue;
132 struct xattr;
133 struct xfrm_sec_ctx;
134 struct mm_struct;
135+#include <linux/ccsecurity.h>
136
137 /* Maximum number of letters for an LSM name string */
138 #define SECURITY_NAME_MAX 10
139@@ -2042,7 +2043,10 @@ static inline int security_syslog(int type)
140 static inline int security_settime(const struct timespec *ts,
141 const struct timezone *tz)
142 {
143- return cap_settime(ts, tz);
144+ int error = cap_settime(ts, tz);
145+ if (!error)
146+ error = ccs_settime(ts, tz);
147+ return error;
148 }
149
150 static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
151@@ -2111,18 +2115,18 @@ static inline int security_sb_mount(const char *dev_name, struct path *path,
152 const char *type, unsigned long flags,
153 void *data)
154 {
155- return 0;
156+ return ccs_sb_mount(dev_name, path, type, flags, data);
157 }
158
159 static inline int security_sb_umount(struct vfsmount *mnt, int flags)
160 {
161- return 0;
162+ return ccs_sb_umount(mnt, flags);
163 }
164
165 static inline int security_sb_pivotroot(struct path *old_path,
166 struct path *new_path)
167 {
168- return 0;
169+ return ccs_sb_pivotroot(old_path, new_path);
170 }
171
172 static inline int security_sb_set_mnt_opts(struct super_block *sb,
173@@ -2260,7 +2264,7 @@ static inline int security_inode_setattr(struct dentry *dentry,
174
175 static inline int security_inode_getattr(const struct path *path)
176 {
177- return 0;
178+ return ccs_inode_getattr(path);
179 }
180
181 static inline int security_inode_setxattr(struct dentry *dentry,
182@@ -2336,7 +2340,7 @@ static inline void security_file_free(struct file *file)
183 static inline int security_file_ioctl(struct file *file, unsigned int cmd,
184 unsigned long arg)
185 {
186- return 0;
187+ return ccs_file_ioctl(file, cmd, arg);
188 }
189
190 static inline int security_mmap_file(struct file *file, unsigned long prot,
191@@ -2365,7 +2369,7 @@ static inline int security_file_lock(struct file *file, unsigned int cmd)
192 static inline int security_file_fcntl(struct file *file, unsigned int cmd,
193 unsigned long arg)
194 {
195- return 0;
196+ return ccs_file_fcntl(file, cmd, arg);
197 }
198
199 static inline void security_file_set_fowner(struct file *file)
200@@ -2388,7 +2392,7 @@ static inline int security_file_receive(struct file *file)
201 static inline int security_file_open(struct file *file,
202 const struct cred *cred)
203 {
204- return 0;
205+ return ccs_file_open(file, cred);
206 }
207
208 static inline int security_task_create(unsigned long clone_flags)
209@@ -2750,7 +2754,7 @@ static inline int security_unix_may_send(struct socket *sock,
210 static inline int security_socket_create(int family, int type,
211 int protocol, int kern)
212 {
213- return 0;
214+ return ccs_socket_create(family, type, protocol, kern);
215 }
216
217 static inline int security_socket_post_create(struct socket *sock,
218@@ -2765,19 +2769,19 @@ static inline int security_socket_bind(struct socket *sock,
219 struct sockaddr *address,
220 int addrlen)
221 {
222- return 0;
223+ return ccs_socket_bind(sock, address, addrlen);
224 }
225
226 static inline int security_socket_connect(struct socket *sock,
227 struct sockaddr *address,
228 int addrlen)
229 {
230- return 0;
231+ return ccs_socket_connect(sock, address, addrlen);
232 }
233
234 static inline int security_socket_listen(struct socket *sock, int backlog)
235 {
236- return 0;
237+ return ccs_socket_listen(sock, backlog);
238 }
239
240 static inline int security_socket_accept(struct socket *sock,
241@@ -2789,7 +2793,7 @@ static inline int security_socket_accept(struct socket *sock,
242 static inline int security_socket_sendmsg(struct socket *sock,
243 struct msghdr *msg, int size)
244 {
245- return 0;
246+ return ccs_socket_sendmsg(sock, msg, size);
247 }
248
249 static inline int security_socket_recvmsg(struct socket *sock,
250@@ -3031,42 +3035,42 @@ int security_path_chroot(struct path *path);
251 #else /* CONFIG_SECURITY_PATH */
252 static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
253 {
254- return 0;
255+ return ccs_path_unlink(dir, dentry);
256 }
257
258 static inline int security_path_mkdir(struct path *dir, struct dentry *dentry,
259 umode_t mode)
260 {
261- return 0;
262+ return ccs_path_mkdir(dir, dentry, mode);
263 }
264
265 static inline int security_path_rmdir(struct path *dir, struct dentry *dentry)
266 {
267- return 0;
268+ return ccs_path_rmdir(dir, dentry);
269 }
270
271 static inline int security_path_mknod(struct path *dir, struct dentry *dentry,
272 umode_t mode, unsigned int dev)
273 {
274- return 0;
275+ return ccs_path_mknod(dir, dentry, mode, dev);
276 }
277
278 static inline int security_path_truncate(struct path *path)
279 {
280- return 0;
281+ return ccs_path_truncate(path);
282 }
283
284 static inline int security_path_symlink(struct path *dir, struct dentry *dentry,
285 const char *old_name)
286 {
287- return 0;
288+ return ccs_path_symlink(dir, dentry, old_name);
289 }
290
291 static inline int security_path_link(struct dentry *old_dentry,
292 struct path *new_dir,
293 struct dentry *new_dentry)
294 {
295- return 0;
296+ return ccs_path_link(old_dentry, new_dir, new_dentry);
297 }
298
299 static inline int security_path_rename(struct path *old_dir,
300@@ -3075,22 +3079,32 @@ static inline int security_path_rename(struct path *old_dir,
301 struct dentry *new_dentry,
302 unsigned int flags)
303 {
304- return 0;
305+ /*
306+ * Not using RENAME_EXCHANGE here in order to avoid KABI breakage
307+ * by doing "#include <uapi/linux/fs.h>" .
308+ */
309+ if (flags & (1 << 1)) {
310+ int err = ccs_path_rename(new_dir, new_dentry, old_dir,
311+ old_dentry);
312+ if (err)
313+ return err;
314+ }
315+ return ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
316 }
317
318 static inline int security_path_chmod(struct path *path, umode_t mode)
319 {
320- return 0;
321+ return ccs_path_chmod(path, mode);
322 }
323
324 static inline int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
325 {
326- return 0;
327+ return ccs_path_chown(path, uid, gid);
328 }
329
330 static inline int security_path_chroot(struct path *path)
331 {
332- return 0;
333+ return ccs_path_chroot(path);
334 }
335 #endif /* CONFIG_SECURITY_PATH */
336
337diff --git a/include/net/ip.h b/include/net/ip.h
338index d14af7e..34eb1cb 100644
339--- a/include/net/ip.h
340+++ b/include/net/ip.h
341@@ -216,6 +216,8 @@ void inet_get_local_port_range(struct net *net, int *low, int *high);
342 #ifdef CONFIG_SYSCTL
343 static inline int inet_is_local_reserved_port(struct net *net, int port)
344 {
345+ if (ccs_lport_reserved(port))
346+ return 1;
347 if (!net->ipv4.sysctl_local_reserved_ports)
348 return 0;
349 return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
350@@ -229,6 +231,8 @@ static inline bool sysctl_dev_name_is_allowed(const char *name)
351 #else
352 static inline int inet_is_local_reserved_port(struct net *net, int port)
353 {
354+ if (ccs_lport_reserved(port))
355+ return 1;
356 return 0;
357 }
358 #endif
359diff --git a/kernel/fork.c b/kernel/fork.c
360index 7e215ba..9bce902 100644
361--- a/kernel/fork.c
362+++ b/kernel/fork.c
363@@ -257,6 +257,7 @@ void __put_task_struct(struct task_struct *tsk)
364 delayacct_tsk_free(tsk);
365 put_signal_struct(tsk->signal);
366
367+ ccs_free_task_security(tsk);
368 if (!profile_handoff_task(tsk))
369 free_task(tsk);
370 }
371@@ -1423,6 +1424,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
372 goto bad_fork_cleanup_perf;
373 /* copy all the process information */
374 shm_init_task(p);
375+ retval = ccs_alloc_task_security(p);
376+ if (retval)
377+ goto bad_fork_cleanup_audit;
378 retval = copy_semundo(clone_flags, p);
379 if (retval)
380 goto bad_fork_cleanup_audit;
381@@ -1627,6 +1631,7 @@ bad_fork_cleanup_semundo:
382 exit_sem(p);
383 bad_fork_cleanup_audit:
384 audit_free(p);
385+ ccs_free_task_security(p);
386 bad_fork_cleanup_perf:
387 perf_event_free_task(p);
388 bad_fork_cleanup_policy:
389diff --git a/kernel/kexec.c b/kernel/kexec.c
390index 7a36fdc..294444e 100644
391--- a/kernel/kexec.c
392+++ b/kernel/kexec.c
393@@ -41,6 +41,7 @@
394 #include <asm/uaccess.h>
395 #include <asm/io.h>
396 #include <asm/sections.h>
397+#include <linux/ccsecurity.h>
398
399 #include <crypto/hash.h>
400 #include <crypto/sha.h>
401@@ -1245,6 +1246,8 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
402 /* We only trust the superuser with rebooting the system. */
403 if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
404 return -EPERM;
405+ if (!ccs_capable(CCS_SYS_KEXEC_LOAD))
406+ return -EPERM;
407
408 /*
409 * Verify we have a legal set of flags
410diff --git a/kernel/module.c b/kernel/module.c
411index cfc9e84..73fd5f5 100644
412--- a/kernel/module.c
413+++ b/kernel/module.c
414@@ -61,6 +61,7 @@
415 #include <linux/bsearch.h>
416 #include <uapi/linux/module.h>
417 #include "module-internal.h"
418+#include <linux/ccsecurity.h>
419
420 #define CREATE_TRACE_POINTS
421 #include <trace/events/module.h>
422@@ -799,6 +800,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
423
424 if (!capable(CAP_SYS_MODULE) || modules_disabled)
425 return -EPERM;
426+ if (!ccs_capable(CCS_USE_KERNEL_MODULE))
427+ return -EPERM;
428
429 if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
430 return -EFAULT;
431@@ -3155,6 +3158,8 @@ static int may_init_module(void)
432 {
433 if (!capable(CAP_SYS_MODULE) || modules_disabled)
434 return -EPERM;
435+ if (!ccs_capable(CCS_USE_KERNEL_MODULE))
436+ return -EPERM;
437
438 return 0;
439 }
440diff --git a/kernel/ptrace.c b/kernel/ptrace.c
441index c8e0e05..4106a2a 100644
442--- a/kernel/ptrace.c
443+++ b/kernel/ptrace.c
444@@ -1034,6 +1034,11 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
445 {
446 struct task_struct *child;
447 long ret;
448+ {
449+ const int rc = ccs_ptrace_permission(request, pid);
450+ if (rc)
451+ return rc;
452+ }
453
454 if (request == PTRACE_TRACEME) {
455 ret = ptrace_traceme();
456@@ -1180,6 +1185,11 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_long_t, request, compat_long_t, pid,
457 {
458 struct task_struct *child;
459 long ret;
460+ {
461+ const int rc = ccs_ptrace_permission(request, pid);
462+ if (rc)
463+ return rc;
464+ }
465
466 if (request == PTRACE_TRACEME) {
467 ret = ptrace_traceme();
468diff --git a/kernel/reboot.c b/kernel/reboot.c
469index d20c85d..61ffd97 100644
470--- a/kernel/reboot.c
471+++ b/kernel/reboot.c
472@@ -16,6 +16,7 @@
473 #include <linux/syscalls.h>
474 #include <linux/syscore_ops.h>
475 #include <linux/uaccess.h>
476+#include <linux/ccsecurity.h>
477
478 /*
479 * this indicates whether you can reboot with ctrl-alt-del: the default is yes
480@@ -295,6 +296,8 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
481 magic2 != LINUX_REBOOT_MAGIC2B &&
482 magic2 != LINUX_REBOOT_MAGIC2C))
483 return -EINVAL;
484+ if (!ccs_capable(CCS_SYS_REBOOT))
485+ return -EPERM;
486
487 /*
488 * If pid namespaces are enabled and the current task is in a child
489diff --git a/kernel/sched/core.c b/kernel/sched/core.c
490index e691052..c63bbd8 100644
491--- a/kernel/sched/core.c
492+++ b/kernel/sched/core.c
493@@ -3145,6 +3145,8 @@ int can_nice(const struct task_struct *p, const int nice)
494 SYSCALL_DEFINE1(nice, int, increment)
495 {
496 long nice, retval;
497+ if (!ccs_capable(CCS_SYS_NICE))
498+ return -EPERM;
499
500 /*
501 * Setpriority might change our priority at the same moment.
502diff --git a/kernel/signal.c b/kernel/signal.c
503index 0206be7..9e01cca 100644
504--- a/kernel/signal.c
505+++ b/kernel/signal.c
506@@ -2901,6 +2901,8 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
507 SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
508 {
509 struct siginfo info;
510+ if (ccs_kill_permission(pid, sig))
511+ return -EPERM;
512
513 info.si_signo = sig;
514 info.si_errno = 0;
515@@ -2969,6 +2971,8 @@ SYSCALL_DEFINE3(tgkill, pid_t, tgid, pid_t, pid, int, sig)
516 /* This is only valid for single tasks */
517 if (pid <= 0 || tgid <= 0)
518 return -EINVAL;
519+ if (ccs_tgkill_permission(tgid, pid, sig))
520+ return -EPERM;
521
522 return do_tkill(tgid, pid, sig);
523 }
524@@ -2985,6 +2989,8 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int, sig)
525 /* This is only valid for single tasks */
526 if (pid <= 0)
527 return -EINVAL;
528+ if (ccs_tkill_permission(pid, sig))
529+ return -EPERM;
530
531 return do_tkill(0, pid, sig);
532 }
533@@ -2999,6 +3005,8 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info)
534 return -EPERM;
535
536 info->si_signo = sig;
537+ if (ccs_sigqueue_permission(pid, sig))
538+ return -EPERM;
539
540 /* POSIX.1b doesn't mention process groups. */
541 return kill_proc_info(sig, info, pid);
542@@ -3047,6 +3055,8 @@ static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
543 return -EPERM;
544
545 info->si_signo = sig;
546+ if (ccs_tgsigqueue_permission(tgid, pid, sig))
547+ return -EPERM;
548
549 return do_send_specific(tgid, pid, sig, info);
550 }
551diff --git a/kernel/sys.c b/kernel/sys.c
552index a4e372b..77c6970 100644
553--- a/kernel/sys.c
554+++ b/kernel/sys.c
555@@ -183,6 +183,10 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
556
557 if (which > PRIO_USER || which < PRIO_PROCESS)
558 goto out;
559+ if (!ccs_capable(CCS_SYS_NICE)) {
560+ error = -EPERM;
561+ goto out;
562+ }
563
564 /* normalize: avoid signed division (rounding problems) */
565 error = -ESRCH;
566@@ -1222,6 +1226,8 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
567
568 if (len < 0 || len > __NEW_UTS_LEN)
569 return -EINVAL;
570+ if (!ccs_capable(CCS_SYS_SETHOSTNAME))
571+ return -EPERM;
572 down_write(&uts_sem);
573 errno = -EFAULT;
574 if (!copy_from_user(tmp, name, len)) {
575@@ -1272,6 +1278,8 @@ SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
576 return -EPERM;
577 if (len < 0 || len > __NEW_UTS_LEN)
578 return -EINVAL;
579+ if (!ccs_capable(CCS_SYS_SETHOSTNAME))
580+ return -EPERM;
581
582 down_write(&uts_sem);
583 errno = -EFAULT;
584diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
585index 7a68100..3c8766f 100644
586--- a/kernel/time/ntp.c
587+++ b/kernel/time/ntp.c
588@@ -16,6 +16,7 @@
589 #include <linux/mm.h>
590 #include <linux/module.h>
591 #include <linux/rtc.h>
592+#include <linux/ccsecurity.h>
593
594 #include "ntp_internal.h"
595
596@@ -626,10 +627,15 @@ int ntp_validate_timex(struct timex *txc)
597 if (!(txc->modes & ADJ_OFFSET_READONLY) &&
598 !capable(CAP_SYS_TIME))
599 return -EPERM;
600+ if (!(txc->modes & ADJ_OFFSET_READONLY) &&
601+ !ccs_capable(CCS_SYS_SETTIME))
602+ return -EPERM;
603 } else {
604 /* In order to modify anything, you gotta be super-user! */
605 if (txc->modes && !capable(CAP_SYS_TIME))
606 return -EPERM;
607+ if (txc->modes && !ccs_capable(CCS_SYS_SETTIME))
608+ return -EPERM;
609 /*
610 * if the quartz is off by more than 10% then
611 * something is VERY wrong!
612@@ -642,6 +648,8 @@ int ntp_validate_timex(struct timex *txc)
613
614 if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
615 return -EPERM;
616+ if ((txc->modes & ADJ_SETOFFSET) && !ccs_capable(CCS_SYS_SETTIME))
617+ return -EPERM;
618
619 /*
620 * Check for potential multiplication overflows that can
621diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
622index 561cd4b..16e23e5 100644
623--- a/net/ipv4/raw.c
624+++ b/net/ipv4/raw.c
625@@ -727,6 +727,10 @@ static int raw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
626 skb = skb_recv_datagram(sk, flags, noblock, &err);
627 if (!skb)
628 goto out;
629+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
630+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
631+ goto out;
632+ }
633
634 copied = skb->len;
635 if (len < copied) {
636diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
637index 83aa604..0326e29 100644
638--- a/net/ipv4/udp.c
639+++ b/net/ipv4/udp.c
640@@ -1272,6 +1272,10 @@ try_again:
641 &peeked, &off, &err);
642 if (!skb)
643 goto out;
644+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
645+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
646+ goto out;
647+ }
648
649 ulen = skb->len - sizeof(struct udphdr);
650 copied = len;
651diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
652index 8072bd4..fbd33d4 100644
653--- a/net/ipv6/raw.c
654+++ b/net/ipv6/raw.c
655@@ -477,6 +477,10 @@ static int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
656 skb = skb_recv_datagram(sk, flags, noblock, &err);
657 if (!skb)
658 goto out;
659+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
660+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
661+ goto out;
662+ }
663
664 copied = skb->len;
665 if (copied > len) {
666diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
667index e51fc3e..5b09dbb 100644
668--- a/net/ipv6/udp.c
669+++ b/net/ipv6/udp.c
670@@ -413,6 +413,10 @@ try_again:
671 &peeked, &off, &err);
672 if (!skb)
673 goto out;
674+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
675+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
676+ goto out;
677+ }
678
679 ulen = skb->len - sizeof(struct udphdr);
680 copied = len;
681diff --git a/net/socket.c b/net/socket.c
682index 884e329..767338ff 100644
683--- a/net/socket.c
684+++ b/net/socket.c
685@@ -1485,6 +1485,10 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
686 if (err < 0)
687 goto out_fd;
688
689+ if (ccs_socket_post_accept_permission(sock, newsock)) {
690+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
691+ goto out_fd;
692+ }
693 if (upeer_sockaddr) {
694 if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
695 &len, 2) < 0) {
696diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
697index 0643059..ba5d3d0 100644
698--- a/net/unix/af_unix.c
699+++ b/net/unix/af_unix.c
700@@ -1800,6 +1800,10 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
701 wake_up_interruptible_sync_poll(&u->peer_wait,
702 POLLOUT | POLLWRNORM | POLLWRBAND);
703
704+ if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
705+ err = -EAGAIN; /* Hope less harmful than -EPERM. */
706+ goto out_unlock;
707+ }
708 if (msg->msg_name)
709 unix_copy_addr(msg, skb->sk);
710
711diff --git a/security/Kconfig b/security/Kconfig
712index bf4ec46..4ce2bf2 100644
713--- a/security/Kconfig
714+++ b/security/Kconfig
715@@ -168,5 +168,7 @@ config DEFAULT_SECURITY
716 default "yama" if DEFAULT_SECURITY_YAMA
717 default "" if DEFAULT_SECURITY_DAC
718
719+source security/ccsecurity/Kconfig
720+
721 endmenu
722
723diff --git a/security/Makefile b/security/Makefile
724index 05f1c93..4a42724 100644
725--- a/security/Makefile
726+++ b/security/Makefile
727@@ -27,3 +27,6 @@ obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
728 # Object integrity file lists
729 subdir-$(CONFIG_INTEGRITY) += integrity
730 obj-$(CONFIG_INTEGRITY) += integrity/
731+
732+subdir-$(CONFIG_CCSECURITY) += ccsecurity
733+obj-$(CONFIG_CCSECURITY) += ccsecurity/
734diff --git a/security/security.c b/security/security.c
735index c1c7cd1..a8ed3d0 100644
736--- a/security/security.c
737+++ b/security/security.c
738@@ -226,7 +226,10 @@ int security_syslog(int type)
739
740 int security_settime(const struct timespec *ts, const struct timezone *tz)
741 {
742- return security_ops->settime(ts, tz);
743+ int error = security_ops->settime(ts, tz);
744+ if (!error)
745+ error = ccs_settime(ts, tz);
746+ return error;
747 }
748
749 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
750@@ -303,17 +306,26 @@ int security_sb_statfs(struct dentry *dentry)
751 int security_sb_mount(const char *dev_name, struct path *path,
752 const char *type, unsigned long flags, void *data)
753 {
754- return security_ops->sb_mount(dev_name, path, type, flags, data);
755+ int error = security_ops->sb_mount(dev_name, path, type, flags, data);
756+ if (!error)
757+ error = ccs_sb_mount(dev_name, path, type, flags, data);
758+ return error;
759 }
760
761 int security_sb_umount(struct vfsmount *mnt, int flags)
762 {
763- return security_ops->sb_umount(mnt, flags);
764+ int error = security_ops->sb_umount(mnt, flags);
765+ if (!error)
766+ error = ccs_sb_umount(mnt, flags);
767+ return error;
768 }
769
770 int security_sb_pivotroot(struct path *old_path, struct path *new_path)
771 {
772- return security_ops->sb_pivotroot(old_path, new_path);
773+ int error = security_ops->sb_pivotroot(old_path, new_path);
774+ if (!error)
775+ error = ccs_sb_pivotroot(old_path, new_path);
776+ return error;
777 }
778
779 int security_sb_set_mnt_opts(struct super_block *sb,
780@@ -410,32 +422,48 @@ EXPORT_SYMBOL(security_old_inode_init_security);
781 int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
782 unsigned int dev)
783 {
784+ int error;
785 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
786 return 0;
787+ error = ccs_path_mknod(dir, dentry, mode, dev);
788+ if (error)
789+ return error;
790 return security_ops->path_mknod(dir, dentry, mode, dev);
791 }
792 EXPORT_SYMBOL(security_path_mknod);
793
794 int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
795 {
796+ int error;
797 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
798 return 0;
799+ error = ccs_path_mkdir(dir, dentry, mode);
800+ if (error)
801+ return error;
802 return security_ops->path_mkdir(dir, dentry, mode);
803 }
804 EXPORT_SYMBOL(security_path_mkdir);
805
806 int security_path_rmdir(struct path *dir, struct dentry *dentry)
807 {
808+ int error;
809 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
810 return 0;
811+ error = ccs_path_rmdir(dir, dentry);
812+ if (error)
813+ return error;
814 return security_ops->path_rmdir(dir, dentry);
815 }
816 EXPORT_SYMBOL(security_path_rmdir);
817
818 int security_path_unlink(struct path *dir, struct dentry *dentry)
819 {
820+ int error;
821 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
822 return 0;
823+ error = ccs_path_unlink(dir, dentry);
824+ if (error)
825+ return error;
826 return security_ops->path_unlink(dir, dentry);
827 }
828 EXPORT_SYMBOL(security_path_unlink);
829@@ -443,8 +471,12 @@ EXPORT_SYMBOL(security_path_unlink);
830 int security_path_symlink(struct path *dir, struct dentry *dentry,
831 const char *old_name)
832 {
833+ int error;
834 if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
835 return 0;
836+ error = ccs_path_symlink(dir, dentry, old_name);
837+ if (error)
838+ return error;
839 return security_ops->path_symlink(dir, dentry, old_name);
840 }
841 EXPORT_SYMBOL(security_path_symlink);
842@@ -452,8 +484,12 @@ EXPORT_SYMBOL(security_path_symlink);
843 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
844 struct dentry *new_dentry)
845 {
846+ int error;
847 if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
848 return 0;
849+ error = ccs_path_link(old_dentry, new_dir, new_dentry);
850+ if (error)
851+ return error;
852 return security_ops->path_link(old_dentry, new_dir, new_dentry);
853 }
854 EXPORT_SYMBOL(security_path_link);
855@@ -462,6 +498,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
856 struct path *new_dir, struct dentry *new_dentry,
857 unsigned int flags)
858 {
859+ int error;
860 if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
861 (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
862 return 0;
863@@ -471,8 +508,15 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
864 old_dir, old_dentry);
865 if (err)
866 return err;
867+ err = ccs_path_rename(new_dir, new_dentry, old_dir,
868+ old_dentry);
869+ if (err)
870+ return err;
871 }
872
873+ error = ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
874+ if (error)
875+ return error;
876 return security_ops->path_rename(old_dir, old_dentry, new_dir,
877 new_dentry);
878 }
879@@ -480,30 +524,45 @@ EXPORT_SYMBOL(security_path_rename);
880
881 int security_path_truncate(struct path *path)
882 {
883+ int error;
884 if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
885 return 0;
886+ error = ccs_path_truncate(path);
887+ if (error)
888+ return error;
889 return security_ops->path_truncate(path);
890 }
891 EXPORT_SYMBOL(security_path_truncate);
892
893 int security_path_chmod(struct path *path, umode_t mode)
894 {
895+ int error;
896 if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
897 return 0;
898+ error = ccs_path_chmod(path, mode);
899+ if (error)
900+ return error;
901 return security_ops->path_chmod(path, mode);
902 }
903 EXPORT_SYMBOL(security_path_chmod);
904
905 int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
906 {
907+ int error;
908 if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
909 return 0;
910+ error = ccs_path_chown(path, uid, gid);
911+ if (error)
912+ return error;
913 return security_ops->path_chown(path, uid, gid);
914 }
915 EXPORT_SYMBOL(security_path_chown);
916
917 int security_path_chroot(struct path *path)
918 {
919+ int error = ccs_path_chroot(path);
920+ if (error)
921+ return error;
922 return security_ops->path_chroot(path);
923 }
924 #endif
925@@ -618,9 +677,13 @@ EXPORT_SYMBOL_GPL(security_inode_setattr);
926
927 int security_inode_getattr(const struct path *path)
928 {
929+ int error;
930 if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
931 return 0;
932- return security_ops->inode_getattr(path);
933+ error = security_ops->inode_getattr(path);
934+ if (!error)
935+ error = ccs_inode_getattr(path);
936+ return error;
937 }
938
939 int security_inode_setxattr(struct dentry *dentry, const char *name,
940@@ -738,7 +801,10 @@ void security_file_free(struct file *file)
941
942 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
943 {
944- return security_ops->file_ioctl(file, cmd, arg);
945+ int error = security_ops->file_ioctl(file, cmd, arg);
946+ if (!error)
947+ error = ccs_file_ioctl(file, cmd, arg);
948+ return error;
949 }
950
951 static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
952@@ -804,7 +870,10 @@ int security_file_lock(struct file *file, unsigned int cmd)
953
954 int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
955 {
956- return security_ops->file_fcntl(file, cmd, arg);
957+ int error = security_ops->file_fcntl(file, cmd, arg);
958+ if (!error)
959+ error = ccs_file_fcntl(file, cmd, arg);
960+ return error;
961 }
962
963 void security_file_set_fowner(struct file *file)
964@@ -828,6 +897,8 @@ int security_file_open(struct file *file, const struct cred *cred)
965 int ret;
966
967 ret = security_ops->file_open(file, cred);
968+ if (!ret)
969+ ret = ccs_file_open(file, cred);
970 if (ret)
971 return ret;
972
973@@ -1178,7 +1249,10 @@ EXPORT_SYMBOL(security_unix_may_send);
974
975 int security_socket_create(int family, int type, int protocol, int kern)
976 {
977- return security_ops->socket_create(family, type, protocol, kern);
978+ int error = security_ops->socket_create(family, type, protocol, kern);
979+ if (!error)
980+ error = ccs_socket_create(family, type, protocol, kern);
981+ return error;
982 }
983
984 int security_socket_post_create(struct socket *sock, int family,
985@@ -1190,17 +1264,26 @@ int security_socket_post_create(struct socket *sock, int family,
986
987 int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
988 {
989- return security_ops->socket_bind(sock, address, addrlen);
990+ int error = security_ops->socket_bind(sock, address, addrlen);
991+ if (!error)
992+ error = ccs_socket_bind(sock, address, addrlen);
993+ return error;
994 }
995
996 int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
997 {
998- return security_ops->socket_connect(sock, address, addrlen);
999+ int error = security_ops->socket_connect(sock, address, addrlen);
1000+ if (!error)
1001+ error = ccs_socket_connect(sock, address, addrlen);
1002+ return error;
1003 }
1004
1005 int security_socket_listen(struct socket *sock, int backlog)
1006 {
1007- return security_ops->socket_listen(sock, backlog);
1008+ int error = security_ops->socket_listen(sock, backlog);
1009+ if (!error)
1010+ error = ccs_socket_listen(sock, backlog);
1011+ return error;
1012 }
1013
1014 int security_socket_accept(struct socket *sock, struct socket *newsock)
1015@@ -1210,7 +1293,10 @@ int security_socket_accept(struct socket *sock, struct socket *newsock)
1016
1017 int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
1018 {
1019- return security_ops->socket_sendmsg(sock, msg, size);
1020+ int error = security_ops->socket_sendmsg(sock, msg, size);
1021+ if (!error)
1022+ error = ccs_socket_sendmsg(sock, msg, size);
1023+ return error;
1024 }
1025
1026 int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
1027--
10281.9.1
1029
diff --git a/recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto_security.patch b/recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto_security.patch
new file mode 100644
index 0000000..33a69a1
--- /dev/null
+++ b/recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto_security.patch
@@ -0,0 +1,17920 @@
1From d4a329ee417f1b75ba087828bb4b2f62c1ef57bb Mon Sep 17 00:00:00 2001
2From: Auto Configured <auto.configured>
3Date: Sun, 25 Oct 2015 12:19:45 -0700
4Subject: [PATCH] Ci add ccsecuroty
5
6Signed-off-by: Auto Configured <auto.configured>
7---
8 include/linux/ccsecurity.h | 926 +++++
9 include/linux/lsm2ccsecurity.h | 181 +
10 security/ccsecurity/Config.in | 83 +
11 security/ccsecurity/Kconfig | 190 +
12 security/ccsecurity/Makefile | 122 +
13 security/ccsecurity/gc.c | 1036 ++++++
14 security/ccsecurity/internal.h | 2090 +++++++++++
15 security/ccsecurity/load_policy.c | 352 ++
16 security/ccsecurity/lsm2ccsecurity.c | 192 +
17 security/ccsecurity/memory.c | 356 ++
18 security/ccsecurity/permission.c | 5025 ++++++++++++++++++++++++++
19 security/ccsecurity/policy_io.c | 6484 ++++++++++++++++++++++++++++++++++
20 security/ccsecurity/realpath.c | 767 ++++
21 13 files changed, 17804 insertions(+)
22 create mode 100644 include/linux/ccsecurity.h
23 create mode 100644 include/linux/lsm2ccsecurity.h
24 create mode 100644 security/ccsecurity/Config.in
25 create mode 100644 security/ccsecurity/Kconfig
26 create mode 100644 security/ccsecurity/Makefile
27 create mode 100644 security/ccsecurity/gc.c
28 create mode 100644 security/ccsecurity/internal.h
29 create mode 100644 security/ccsecurity/load_policy.c
30 create mode 100644 security/ccsecurity/lsm2ccsecurity.c
31 create mode 100644 security/ccsecurity/memory.c
32 create mode 100644 security/ccsecurity/permission.c
33 create mode 100644 security/ccsecurity/policy_io.c
34 create mode 100644 security/ccsecurity/realpath.c
35
36diff --git a/include/linux/ccsecurity.h b/include/linux/ccsecurity.h
37new file mode 100644
38index 0000000..6c1ca2b
39--- /dev/null
40+++ b/include/linux/ccsecurity.h
41@@ -0,0 +1,926 @@
42+/*
43+ * include/linux/ccsecurity.h
44+ *
45+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
46+ *
47+ * Version: 1.8.4 2015/05/05
48+ */
49+
50+#ifndef _LINUX_CCSECURITY_H
51+#define _LINUX_CCSECURITY_H
52+
53+#include <linux/version.h>
54+
55+#ifndef __user
56+#define __user
57+#endif
58+
59+struct nameidata;
60+struct path;
61+struct dentry;
62+struct vfsmount;
63+struct linux_binprm;
64+struct pt_regs;
65+struct file;
66+struct ctl_table;
67+struct socket;
68+struct sockaddr;
69+struct sock;
70+struct sk_buff;
71+struct msghdr;
72+struct pid_namespace;
73+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
74+int search_binary_handler(struct linux_binprm *bprm);
75+#else
76+int search_binary_handler(struct linux_binprm *bprm, struct pt_regs *regs);
77+#endif
78+
79+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
80+#include <linux/lsm2ccsecurity.h>
81+#endif
82+
83+#ifdef CONFIG_CCSECURITY
84+
85+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
86+/* Obtain prototype of __d_path(). */
87+#include <linux/dcache.h>
88+#endif
89+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
90+/* Obtain definition of kuid_t and kgid_t. */
91+#include <linux/uidgid.h>
92+#endif
93+
94+/* For exporting variables and functions. */
95+struct ccsecurity_exports {
96+ void (*load_policy) (const char *filename);
97+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY)
98+ void (*add_hooks) (void);
99+#endif
100+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
101+ char * (*d_absolute_path) (const struct path *, char *, int);
102+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
103+ typeof(__d_path) (*__d_path);
104+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
105+ spinlock_t *vfsmount_lock;
106+#endif
107+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
108+ struct task_struct * (*find_task_by_vpid) (pid_t nr);
109+ struct task_struct * (*find_task_by_pid_ns) (pid_t nr,
110+ struct pid_namespace *ns);
111+#endif
112+};
113+
114+/* For doing access control. */
115+struct ccsecurity_operations {
116+ void (*check_profile) (void);
117+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
118+ int (*chroot_permission) (struct path *path);
119+ int (*pivot_root_permission) (struct path *old_path,
120+ struct path *new_path);
121+ int (*mount_permission) (const char *dev_name, struct path *path,
122+ const char *type, unsigned long flags,
123+ void *data_page);
124+#else
125+ int (*chroot_permission) (struct nameidata *nd);
126+ int (*pivot_root_permission) (struct nameidata *old_nd,
127+ struct nameidata *new_nd);
128+ int (*mount_permission) (const char *dev_name, struct nameidata *nd,
129+ const char *type, unsigned long flags,
130+ void *data_page);
131+#endif
132+ int (*umount_permission) (struct vfsmount *mnt, int flags);
133+ _Bool (*lport_reserved) (const u16 port);
134+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
135+ void (*save_open_mode) (int mode);
136+ void (*clear_open_mode) (void);
137+ int (*open_permission) (struct dentry *dentry, struct vfsmount *mnt,
138+ const int flag);
139+#else
140+ int (*open_permission) (struct file *file);
141+#endif
142+ int (*ptrace_permission) (long request, long pid);
143+ int (*ioctl_permission) (struct file *filp, unsigned int cmd,
144+ unsigned long arg);
145+ int (*parse_table) (int __user *name, int nlen, void __user *oldval,
146+ void __user *newval, struct ctl_table *table);
147+ _Bool (*capable) (const u8 operation);
148+ int (*mknod_permission) (struct dentry *dentry, struct vfsmount *mnt,
149+ unsigned int mode, unsigned int dev);
150+ int (*mkdir_permission) (struct dentry *dentry, struct vfsmount *mnt,
151+ unsigned int mode);
152+ int (*rmdir_permission) (struct dentry *dentry, struct vfsmount *mnt);
153+ int (*unlink_permission) (struct dentry *dentry, struct vfsmount *mnt);
154+ int (*symlink_permission) (struct dentry *dentry, struct vfsmount *mnt,
155+ const char *from);
156+ int (*truncate_permission) (struct dentry *dentry,
157+ struct vfsmount *mnt);
158+ int (*rename_permission) (struct dentry *old_dentry,
159+ struct dentry *new_dentry,
160+ struct vfsmount *mnt);
161+ int (*link_permission) (struct dentry *old_dentry,
162+ struct dentry *new_dentry,
163+ struct vfsmount *mnt);
164+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
165+ int (*open_exec_permission) (struct dentry *dentry,
166+ struct vfsmount *mnt);
167+ int (*uselib_permission) (struct dentry *dentry, struct vfsmount *mnt);
168+#endif
169+ int (*fcntl_permission) (struct file *file, unsigned int cmd,
170+ unsigned long arg);
171+ int (*kill_permission) (pid_t pid, int sig);
172+ int (*tgkill_permission) (pid_t tgid, pid_t pid, int sig);
173+ int (*tkill_permission) (pid_t pid, int sig);
174+ int (*socket_create_permission) (int family, int type, int protocol);
175+ int (*socket_listen_permission) (struct socket *sock);
176+ int (*socket_connect_permission) (struct socket *sock,
177+ struct sockaddr *addr, int addr_len);
178+ int (*socket_bind_permission) (struct socket *sock,
179+ struct sockaddr *addr, int addr_len);
180+ int (*socket_post_accept_permission) (struct socket *sock,
181+ struct socket *newsock);
182+ int (*socket_sendmsg_permission) (struct socket *sock,
183+ struct msghdr *msg, int size);
184+ int (*socket_post_recvmsg_permission) (struct sock *sk,
185+ struct sk_buff *skb, int flags);
186+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
187+ int (*chown_permission) (struct dentry *dentry, struct vfsmount *mnt,
188+ kuid_t user, kgid_t group);
189+#else
190+ int (*chown_permission) (struct dentry *dentry, struct vfsmount *mnt,
191+ uid_t user, gid_t group);
192+#endif
193+ int (*chmod_permission) (struct dentry *dentry, struct vfsmount *mnt,
194+ mode_t mode);
195+ int (*getattr_permission) (struct vfsmount *mnt,
196+ struct dentry *dentry);
197+ int (*sigqueue_permission) (pid_t pid, int sig);
198+ int (*tgsigqueue_permission) (pid_t tgid, pid_t pid, int sig);
199+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
200+ int (*search_binary_handler) (struct linux_binprm *bprm);
201+#else
202+ int (*search_binary_handler) (struct linux_binprm *bprm,
203+ struct pt_regs *regs);
204+#endif
205+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
206+ int (*alloc_task_security) (const struct task_struct *task);
207+ void (*free_task_security) (const struct task_struct *task);
208+#endif
209+ _Bool disabled;
210+};
211+
212+extern struct ccsecurity_operations ccsecurity_ops;
213+
214+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
215+
216+static inline int ccs_chroot_permission(struct path *path)
217+{
218+ int (*func) (struct path *) = ccsecurity_ops.chroot_permission;
219+ return func ? func(path) : 0;
220+}
221+
222+static inline int ccs_pivot_root_permission(struct path *old_path,
223+ struct path *new_path)
224+{
225+ int (*func) (struct path *, struct path *)
226+ = ccsecurity_ops.pivot_root_permission;
227+ return func ? func(old_path, new_path) : 0;
228+}
229+
230+static inline int ccs_mount_permission(const char *dev_name, struct path *path,
231+ const char *type, unsigned long flags,
232+ void *data_page)
233+{
234+ int (*func) (const char *, struct path *, const char *, unsigned long,
235+ void *) = ccsecurity_ops.mount_permission;
236+ return func ? func(dev_name, path, type, flags, data_page) : 0;
237+}
238+
239+#else
240+
241+static inline int ccs_chroot_permission(struct nameidata *nd)
242+{
243+ int (*func) (struct nameidata *) = ccsecurity_ops.chroot_permission;
244+ return func ? func(nd) : 0;
245+}
246+
247+static inline int ccs_pivot_root_permission(struct nameidata *old_nd,
248+ struct nameidata *new_nd)
249+{
250+ int (*func) (struct nameidata *, struct nameidata *)
251+ = ccsecurity_ops.pivot_root_permission;
252+ return func ? func(old_nd, new_nd) : 0;
253+}
254+
255+static inline int ccs_mount_permission(const char *dev_name,
256+ struct nameidata *nd, const char *type,
257+ unsigned long flags, void *data_page)
258+{
259+ int (*func) (const char *, struct nameidata *, const char *,
260+ unsigned long, void *) = ccsecurity_ops.mount_permission;
261+ return func ? func(dev_name, nd, type, flags, data_page) : 0;
262+}
263+
264+#endif
265+
266+static inline int ccs_umount_permission(struct vfsmount *mnt, int flags)
267+{
268+ int (*func) (struct vfsmount *, int)
269+ = ccsecurity_ops.umount_permission;
270+ return func ? func(mnt, flags) : 0;
271+}
272+
273+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
274+
275+static inline void ccs_save_open_mode(int mode)
276+{
277+ void (*func) (int) = ccsecurity_ops.save_open_mode;
278+ if (func)
279+ func(mode);
280+}
281+
282+static inline void ccs_clear_open_mode(void)
283+{
284+ void (*func) (void) = ccsecurity_ops.clear_open_mode;
285+ if (func)
286+ func();
287+}
288+
289+static inline int ccs_open_permission(struct dentry *dentry,
290+ struct vfsmount *mnt, const int flag)
291+{
292+ int (*func) (struct dentry *, struct vfsmount *, const int)
293+ = ccsecurity_ops.open_permission;
294+ return func ? func(dentry, mnt, flag) : 0;
295+}
296+
297+#else
298+
299+static inline int ccs_open_permission(struct file *filp)
300+{
301+ int (*func) (struct file *) = ccsecurity_ops.open_permission;
302+ return func ? func(filp) : 0;
303+}
304+
305+#endif
306+
307+static inline int ccs_fcntl_permission(struct file *file, unsigned int cmd,
308+ unsigned long arg)
309+{
310+ int (*func) (struct file *, unsigned int, unsigned long)
311+ = ccsecurity_ops.fcntl_permission;
312+ return func ? func(file, cmd, arg) : 0;
313+}
314+
315+static inline int ccs_ioctl_permission(struct file *filp, unsigned int cmd,
316+ unsigned long arg)
317+{
318+ int (*func) (struct file *, unsigned int, unsigned long)
319+ = ccsecurity_ops.ioctl_permission;
320+ return func ? func(filp, cmd, arg) : 0;
321+}
322+
323+static inline int ccs_parse_table(int __user *name, int nlen,
324+ void __user *oldval, void __user *newval,
325+ struct ctl_table *table)
326+{
327+ int (*func) (int __user *, int, void __user *, void __user *,
328+ struct ctl_table *) = ccsecurity_ops.parse_table;
329+ return func ? func(name, nlen, oldval, newval, table) : 0;
330+}
331+
332+static inline int ccs_mknod_permission(struct dentry *dentry,
333+ struct vfsmount *mnt, unsigned int mode,
334+ unsigned int dev)
335+{
336+ int (*func) (struct dentry *, struct vfsmount *, unsigned int,
337+ unsigned int) = ccsecurity_ops.mknod_permission;
338+ return func ? func(dentry, mnt, mode, dev) : 0;
339+}
340+
341+static inline int ccs_mkdir_permission(struct dentry *dentry,
342+ struct vfsmount *mnt, unsigned int mode)
343+{
344+ int (*func) (struct dentry *, struct vfsmount *, unsigned int)
345+ = ccsecurity_ops.mkdir_permission;
346+ return func ? func(dentry, mnt, mode) : 0;
347+}
348+
349+static inline int ccs_rmdir_permission(struct dentry *dentry,
350+ struct vfsmount *mnt)
351+{
352+ int (*func) (struct dentry *, struct vfsmount *)
353+ = ccsecurity_ops.rmdir_permission;
354+ return func ? func(dentry, mnt) : 0;
355+}
356+
357+static inline int ccs_unlink_permission(struct dentry *dentry,
358+ struct vfsmount *mnt)
359+{
360+ int (*func) (struct dentry *, struct vfsmount *)
361+ = ccsecurity_ops.unlink_permission;
362+ return func ? func(dentry, mnt) : 0;
363+}
364+
365+static inline int ccs_symlink_permission(struct dentry *dentry,
366+ struct vfsmount *mnt,
367+ const char *from)
368+{
369+ int (*func) (struct dentry *, struct vfsmount *, const char *)
370+ = ccsecurity_ops.symlink_permission;
371+ return func ? func(dentry, mnt, from) : 0;
372+}
373+
374+static inline int ccs_truncate_permission(struct dentry *dentry,
375+ struct vfsmount *mnt)
376+{
377+ int (*func) (struct dentry *, struct vfsmount *)
378+ = ccsecurity_ops.truncate_permission;
379+ return func ? func(dentry, mnt) : 0;
380+}
381+
382+static inline int ccs_rename_permission(struct dentry *old_dentry,
383+ struct dentry *new_dentry,
384+ struct vfsmount *mnt)
385+{
386+ int (*func) (struct dentry *, struct dentry *, struct vfsmount *)
387+ = ccsecurity_ops.rename_permission;
388+ return func ? func(old_dentry, new_dentry, mnt) : 0;
389+}
390+
391+static inline int ccs_link_permission(struct dentry *old_dentry,
392+ struct dentry *new_dentry,
393+ struct vfsmount *mnt)
394+{
395+ int (*func) (struct dentry *, struct dentry *, struct vfsmount *)
396+ = ccsecurity_ops.link_permission;
397+ return func ? func(old_dentry, new_dentry, mnt) : 0;
398+}
399+
400+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
401+
402+static inline int ccs_open_exec_permission(struct dentry *dentry,
403+ struct vfsmount *mnt)
404+{
405+ int (*func) (struct dentry *, struct vfsmount *)
406+ = ccsecurity_ops.open_exec_permission;
407+ return func ? func(dentry, mnt) : 0;
408+}
409+
410+static inline int ccs_uselib_permission(struct dentry *dentry,
411+ struct vfsmount *mnt)
412+{
413+ int (*func) (struct dentry *, struct vfsmount *)
414+ = ccsecurity_ops.uselib_permission;
415+ return func ? func(dentry, mnt) : 0;
416+}
417+
418+#endif
419+
420+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
421+
422+static inline int ccs_chown_permission(struct dentry *dentry,
423+ struct vfsmount *mnt, kuid_t user,
424+ kgid_t group)
425+{
426+ int (*func) (struct dentry *, struct vfsmount *, kuid_t, kgid_t)
427+ = ccsecurity_ops.chown_permission;
428+ return func ? func(dentry, mnt, user, group) : 0;
429+}
430+
431+#else
432+
433+static inline int ccs_chown_permission(struct dentry *dentry,
434+ struct vfsmount *mnt, uid_t user,
435+ gid_t group)
436+{
437+ int (*func) (struct dentry *, struct vfsmount *, uid_t, gid_t)
438+ = ccsecurity_ops.chown_permission;
439+ return func ? func(dentry, mnt, user, group) : 0;
440+}
441+
442+#endif
443+
444+static inline int ccs_chmod_permission(struct dentry *dentry,
445+ struct vfsmount *mnt, mode_t mode)
446+{
447+ int (*func) (struct dentry *, struct vfsmount *, mode_t)
448+ = ccsecurity_ops.chmod_permission;
449+ return func ? func(dentry, mnt, mode) : 0;
450+}
451+
452+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
453+
454+static inline int ccs_search_binary_handler(struct linux_binprm *bprm)
455+{
456+ return ccsecurity_ops.search_binary_handler(bprm);
457+}
458+
459+#else
460+
461+static inline int ccs_search_binary_handler(struct linux_binprm *bprm,
462+ struct pt_regs *regs)
463+{
464+ return ccsecurity_ops.search_binary_handler(bprm, regs);
465+}
466+
467+#endif
468+
469+#else
470+
471+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
472+
473+static inline int ccs_chroot_permission(struct path *path)
474+{
475+ return 0;
476+}
477+
478+static inline int ccs_pivot_root_permission(struct path *old_path,
479+ struct path *new_path)
480+{
481+ return 0;
482+}
483+
484+static inline int ccs_mount_permission(const char *dev_name, struct path *path,
485+ const char *type, unsigned long flags,
486+ void *data_page)
487+{
488+ return 0;
489+}
490+
491+#else
492+
493+static inline int ccs_chroot_permission(struct nameidata *nd)
494+{
495+ return 0;
496+}
497+
498+static inline int ccs_pivot_root_permission(struct nameidata *old_nd,
499+ struct nameidata *new_nd)
500+{
501+ return 0;
502+}
503+
504+static inline int ccs_mount_permission(const char *dev_name,
505+ struct nameidata *nd, const char *type,
506+ unsigned long flags, void *data_page)
507+{
508+ return 0;
509+}
510+
511+#endif
512+
513+static inline int ccs_umount_permission(struct vfsmount *mnt, int flags)
514+{
515+ return 0;
516+}
517+
518+static inline void ccs_save_open_mode(int mode)
519+{
520+}
521+
522+static inline void ccs_clear_open_mode(void)
523+{
524+}
525+
526+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
527+
528+static inline int ccs_open_permission(struct dentry *dentry,
529+ struct vfsmount *mnt, const int flag)
530+{
531+ return 0;
532+}
533+
534+#else
535+
536+static inline int ccs_open_permission(struct file *filp)
537+{
538+ return 0;
539+}
540+
541+#endif
542+
543+static inline int ccs_ioctl_permission(struct file *filp, unsigned int cmd,
544+ unsigned long arg)
545+{
546+ return 0;
547+}
548+
549+static inline int ccs_parse_table(int __user *name, int nlen,
550+ void __user *oldval, void __user *newval,
551+ struct ctl_table *table)
552+{
553+ return 0;
554+}
555+
556+static inline int ccs_mknod_permission(struct dentry *dentry,
557+ struct vfsmount *mnt, unsigned int mode,
558+ unsigned int dev)
559+{
560+ return 0;
561+}
562+
563+static inline int ccs_mkdir_permission(struct dentry *dentry,
564+ struct vfsmount *mnt, unsigned int mode)
565+{
566+ return 0;
567+}
568+
569+static inline int ccs_rmdir_permission(struct dentry *dentry,
570+ struct vfsmount *mnt)
571+{
572+ return 0;
573+}
574+
575+static inline int ccs_unlink_permission(struct dentry *dentry,
576+ struct vfsmount *mnt)
577+{
578+ return 0;
579+}
580+
581+static inline int ccs_symlink_permission(struct dentry *dentry,
582+ struct vfsmount *mnt,
583+ const char *from)
584+{
585+ return 0;
586+}
587+
588+static inline int ccs_truncate_permission(struct dentry *dentry,
589+ struct vfsmount *mnt)
590+{
591+ return 0;
592+}
593+
594+static inline int ccs_rename_permission(struct dentry *old_dentry,
595+ struct dentry *new_dentry,
596+ struct vfsmount *mnt)
597+{
598+ return 0;
599+}
600+
601+static inline int ccs_link_permission(struct dentry *old_dentry,
602+ struct dentry *new_dentry,
603+ struct vfsmount *mnt)
604+{
605+ return 0;
606+}
607+
608+static inline int ccs_open_exec_permission(struct dentry *dentry,
609+ struct vfsmount *mnt)
610+{
611+ return 0;
612+}
613+
614+static inline int ccs_uselib_permission(struct dentry *dentry,
615+ struct vfsmount *mnt)
616+{
617+ return 0;
618+}
619+
620+static inline int ccs_fcntl_permission(struct file *file, unsigned int cmd,
621+ unsigned long arg)
622+{
623+ return 0;
624+}
625+
626+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
627+
628+static inline int ccs_chown_permission(struct dentry *dentry,
629+ struct vfsmount *mnt, kuid_t user,
630+ kgid_t group)
631+{
632+ return 0;
633+}
634+
635+#else
636+
637+static inline int ccs_chown_permission(struct dentry *dentry,
638+ struct vfsmount *mnt, uid_t user,
639+ gid_t group)
640+{
641+ return 0;
642+}
643+
644+#endif
645+
646+static inline int ccs_chmod_permission(struct dentry *dentry,
647+ struct vfsmount *mnt, mode_t mode)
648+{
649+ return 0;
650+}
651+
652+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
653+
654+static inline int ccs_search_binary_handler(struct linux_binprm *bprm)
655+{
656+ return search_binary_handler(bprm);
657+}
658+
659+#else
660+
661+static inline int ccs_search_binary_handler(struct linux_binprm *bprm,
662+ struct pt_regs *regs)
663+{
664+ return search_binary_handler(bprm, regs);
665+}
666+
667+#endif
668+
669+#endif
670+
671+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
672+
673+static inline int ccs_alloc_task_security(const struct task_struct *task)
674+{
675+ int (*func) (const struct task_struct *)
676+ = ccsecurity_ops.alloc_task_security;
677+ return func ? func(task) : 0;
678+}
679+
680+static inline void ccs_free_task_security(const struct task_struct *task)
681+{
682+ void (*func) (const struct task_struct *)
683+ = ccsecurity_ops.free_task_security;
684+ if (func)
685+ func(task);
686+}
687+
688+#else
689+
690+static inline int ccs_alloc_task_security(const struct task_struct *task)
691+{
692+ return 0;
693+}
694+
695+static inline void ccs_free_task_security(const struct task_struct *task)
696+{
697+}
698+
699+#endif
700+
701+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
702+
703+static inline int ccs_getattr_permission(struct vfsmount *mnt,
704+ struct dentry *dentry)
705+{
706+ int (*func) (struct vfsmount *, struct dentry *)
707+ = ccsecurity_ops.getattr_permission;
708+ return func ? func(mnt, dentry) : 0;
709+}
710+
711+#else
712+
713+static inline int ccs_getattr_permission(struct vfsmount *mnt,
714+ struct dentry *dentry)
715+{
716+ return 0;
717+}
718+
719+#endif
720+
721+#ifdef CONFIG_CCSECURITY_NETWORK
722+
723+static inline int ccs_socket_listen_permission(struct socket *sock)
724+{
725+ int (*func) (struct socket *)
726+ = ccsecurity_ops.socket_listen_permission;
727+ return func ? func(sock) : 0;
728+}
729+
730+static inline int ccs_socket_connect_permission(struct socket *sock,
731+ struct sockaddr *addr,
732+ int addr_len)
733+{
734+ int (*func) (struct socket *, struct sockaddr *, int)
735+ = ccsecurity_ops.socket_connect_permission;
736+ return func ? func(sock, addr, addr_len) : 0;
737+}
738+
739+static inline int ccs_socket_bind_permission(struct socket *sock,
740+ struct sockaddr *addr,
741+ int addr_len)
742+{
743+ int (*func) (struct socket *, struct sockaddr *, int)
744+ = ccsecurity_ops.socket_bind_permission;
745+ return func ? func(sock, addr, addr_len) : 0;
746+}
747+
748+static inline int ccs_socket_post_accept_permission(struct socket *sock,
749+ struct socket *newsock)
750+{
751+ int (*func) (struct socket *, struct socket *)
752+ = ccsecurity_ops.socket_post_accept_permission;
753+ return func ? func(sock, newsock) : 0;
754+}
755+
756+static inline int ccs_socket_sendmsg_permission(struct socket *sock,
757+ struct msghdr *msg,
758+ int size)
759+{
760+ int (*func) (struct socket *, struct msghdr *, int)
761+ = ccsecurity_ops.socket_sendmsg_permission;
762+ return func ? func(sock, msg, size) : 0;
763+}
764+
765+#else
766+
767+static inline int ccs_socket_listen_permission(struct socket *sock)
768+{
769+ return 0;
770+}
771+
772+static inline int ccs_socket_connect_permission(struct socket *sock,
773+ struct sockaddr *addr,
774+ int addr_len)
775+{
776+ return 0;
777+}
778+
779+static inline int ccs_socket_bind_permission(struct socket *sock,
780+ struct sockaddr *addr,
781+ int addr_len)
782+{
783+ return 0;
784+}
785+
786+static inline int ccs_socket_post_accept_permission(struct socket *sock,
787+ struct socket *newsock)
788+{
789+ return 0;
790+}
791+
792+static inline int ccs_socket_sendmsg_permission(struct socket *sock,
793+ struct msghdr *msg,
794+ int size)
795+{
796+ return 0;
797+}
798+
799+#endif
800+
801+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
802+
803+static inline int ccs_socket_post_recvmsg_permission(struct sock *sk,
804+ struct sk_buff *skb,
805+ int flags)
806+{
807+ int (*func) (struct sock *, struct sk_buff *, int)
808+ = ccsecurity_ops.socket_post_recvmsg_permission;
809+ return func ? func(sk, skb, flags) : 0;
810+}
811+
812+#else
813+
814+static inline int ccs_socket_post_recvmsg_permission(struct sock *sk,
815+ struct sk_buff *skb,
816+ int flags)
817+{
818+ return 0;
819+}
820+
821+#endif
822+
823+#ifdef CONFIG_CCSECURITY_PORTRESERVE
824+
825+static inline _Bool ccs_lport_reserved(const u16 port)
826+{
827+ _Bool (*func) (const u16) = ccsecurity_ops.lport_reserved;
828+ return func ? func(port) : 0;
829+}
830+
831+#else
832+
833+static inline _Bool ccs_lport_reserved(const u16 port)
834+{
835+ return 0;
836+}
837+
838+#endif
839+
840+#ifdef CONFIG_CCSECURITY_CAPABILITY
841+
842+static inline _Bool ccs_capable(const u8 operation)
843+{
844+ _Bool (*func) (const u8) = ccsecurity_ops.capable;
845+ return func ? func(operation) : 1;
846+}
847+
848+static inline int ccs_socket_create_permission(int family, int type,
849+ int protocol)
850+{
851+ int (*func) (int, int, int) = ccsecurity_ops.socket_create_permission;
852+ return func ? func(family, type, protocol) : 0;
853+}
854+
855+static inline int ccs_ptrace_permission(long request, long pid)
856+{
857+ int (*func) (long, long) = ccsecurity_ops.ptrace_permission;
858+ return func ? func(request, pid) : 0;
859+}
860+
861+#else
862+
863+static inline _Bool ccs_capable(const u8 operation)
864+{
865+ return 1;
866+}
867+
868+static inline int ccs_socket_create_permission(int family, int type,
869+ int protocol)
870+{
871+ return 0;
872+}
873+
874+static inline int ccs_ptrace_permission(long request, long pid)
875+{
876+ return 0;
877+}
878+
879+#endif
880+
881+#ifdef CONFIG_CCSECURITY_IPC
882+
883+static inline int ccs_kill_permission(pid_t pid, int sig)
884+{
885+ int (*func) (pid_t, int) = ccsecurity_ops.kill_permission;
886+ return func ? func(pid, sig) : 0;
887+}
888+
889+static inline int ccs_tgkill_permission(pid_t tgid, pid_t pid, int sig)
890+{
891+ int (*func) (pid_t, pid_t, int) = ccsecurity_ops.tgkill_permission;
892+ return func ? func(tgid, pid, sig) : 0;
893+}
894+
895+static inline int ccs_tkill_permission(pid_t pid, int sig)
896+{
897+ int (*func) (pid_t, int) = ccsecurity_ops.tkill_permission;
898+ return func ? func(pid, sig) : 0;
899+}
900+
901+static inline int ccs_sigqueue_permission(pid_t pid, int sig)
902+{
903+ int (*func) (pid_t, int) = ccsecurity_ops.sigqueue_permission;
904+ return func ? func(pid, sig) : 0;
905+}
906+
907+static inline int ccs_tgsigqueue_permission(pid_t tgid, pid_t pid, int sig)
908+{
909+ int (*func) (pid_t, pid_t, int) = ccsecurity_ops.tgsigqueue_permission;
910+ return func ? func(tgid, pid, sig) : 0;
911+}
912+
913+#else
914+
915+static inline int ccs_kill_permission(pid_t pid, int sig)
916+{
917+ return 0;
918+}
919+
920+static inline int ccs_tgkill_permission(pid_t tgid, pid_t pid, int sig)
921+{
922+ return 0;
923+}
924+
925+static inline int ccs_tkill_permission(pid_t pid, int sig)
926+{
927+ return 0;
928+}
929+
930+static inline int ccs_sigqueue_permission(pid_t pid, int sig)
931+{
932+ return 0;
933+}
934+
935+static inline int ccs_tgsigqueue_permission(pid_t tgid, pid_t pid, int sig)
936+{
937+ return 0;
938+}
939+
940+#endif
941+
942+/* Index numbers for Capability Controls. */
943+enum ccs_capability_acl_index {
944+ /* socket(PF_ROUTE, *, *) */
945+ CCS_USE_ROUTE_SOCKET,
946+ /* socket(PF_PACKET, *, *) */
947+ CCS_USE_PACKET_SOCKET,
948+ /* sys_reboot() */
949+ CCS_SYS_REBOOT,
950+ /* sys_vhangup() */
951+ CCS_SYS_VHANGUP,
952+ /* do_settimeofday(), sys_adjtimex() */
953+ CCS_SYS_SETTIME,
954+ /* sys_nice(), sys_setpriority() */
955+ CCS_SYS_NICE,
956+ /* sys_sethostname(), sys_setdomainname() */
957+ CCS_SYS_SETHOSTNAME,
958+ /* sys_create_module(), sys_init_module(), sys_delete_module() */
959+ CCS_USE_KERNEL_MODULE,
960+ /* sys_kexec_load() */
961+ CCS_SYS_KEXEC_LOAD,
962+ /* sys_ptrace() */
963+ CCS_SYS_PTRACE,
964+ CCS_MAX_CAPABILITY_INDEX
965+};
966+
967+#endif
968diff --git a/include/linux/lsm2ccsecurity.h b/include/linux/lsm2ccsecurity.h
969new file mode 100644
970index 0000000..ab4ea5c
971--- /dev/null
972+++ b/include/linux/lsm2ccsecurity.h
973@@ -0,0 +1,181 @@
974+/*
975+ * include/linux/lsm2ccsecurity.h
976+ *
977+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
978+ *
979+ * Version: 1.8.4 2015/07/11
980+ */
981+
982+#ifndef _LINUX_LSM2CCSECURITY_H
983+#define _LINUX_LSM2CCSECURITY_H
984+
985+#include <linux/version.h>
986+#include <linux/uidgid.h>
987+
988+#ifdef CONFIG_CCSECURITY
989+
990+int ccs_settime(const struct timespec *ts, const struct timezone *tz);
991+int ccs_sb_mount(const char *dev_name, struct path *path, const char *type,
992+ unsigned long flags, void *data);
993+int ccs_sb_umount(struct vfsmount *mnt, int flags);
994+int ccs_sb_pivotroot(struct path *old_path, struct path *new_path);
995+
996+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
997+int ccs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
998+#else
999+int ccs_inode_getattr(const struct path *path);
1000+#endif
1001+int ccs_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
1002+int ccs_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg);
1003+int ccs_file_open(struct file *file, const struct cred *cred);
1004+int ccs_socket_create(int family, int type, int protocol, int kern);
1005+int ccs_socket_bind(struct socket *sock, struct sockaddr *address,
1006+ int addrlen);
1007+int ccs_socket_connect(struct socket *sock, struct sockaddr *address,
1008+ int addrlen);
1009+int ccs_socket_listen(struct socket *sock, int backlog);
1010+int ccs_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size);
1011+int ccs_path_unlink(struct path *dir, struct dentry *dentry);
1012+int ccs_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode);
1013+int ccs_path_rmdir(struct path *dir, struct dentry *dentry);
1014+int ccs_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
1015+ unsigned int dev);
1016+int ccs_path_truncate(struct path *path);
1017+int ccs_path_symlink(struct path *dir, struct dentry *dentry,
1018+ const char *old_name);
1019+int ccs_path_link(struct dentry *old_dentry, struct path *new_dir,
1020+ struct dentry *new_dentry);
1021+int ccs_path_rename(struct path *old_dir, struct dentry *old_dentry,
1022+ struct path *new_dir, struct dentry *new_dentry);
1023+int ccs_path_chmod(struct path *path, umode_t mode);
1024+int ccs_path_chown(struct path *path, kuid_t uid, kgid_t gid);
1025+int ccs_path_chroot(struct path *path);
1026+
1027+#else
1028+
1029+static inline int ccs_settime(const struct timespec *ts,
1030+ const struct timezone *tz)
1031+{
1032+ return 0;
1033+}
1034+static inline int ccs_sb_mount(const char *dev_name, struct path *path,
1035+ const char *type, unsigned long flags,
1036+ void *data)
1037+{
1038+ return 0;
1039+}
1040+static inline int ccs_sb_umount(struct vfsmount *mnt, int flags)
1041+{
1042+ return 0;
1043+}
1044+static inline int ccs_sb_pivotroot(struct path *old_path,
1045+ struct path *new_path)
1046+{
1047+ return 0;
1048+}
1049+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
1050+static inline int ccs_inode_getattr(struct vfsmount *mnt,
1051+ struct dentry *dentry)
1052+{
1053+ return 0;
1054+}
1055+#else
1056+static inline int ccs_inode_getattr(const struct path *path)
1057+{
1058+ return 0;
1059+}
1060+#endif
1061+static inline int ccs_file_ioctl(struct file *file, unsigned int cmd,
1062+ unsigned long arg)
1063+{
1064+ return 0;
1065+}
1066+static inline int ccs_file_fcntl(struct file *file, unsigned int cmd,
1067+ unsigned long arg)
1068+{
1069+ return 0;
1070+}
1071+static inline int ccs_file_open(struct file *file, const struct cred *cred)
1072+{
1073+ return 0;
1074+}
1075+static inline int ccs_socket_create(int family, int type, int protocol,
1076+ int kern)
1077+{
1078+ return 0;
1079+}
1080+static inline int ccs_socket_bind(struct socket *sock,
1081+ struct sockaddr *address, int addrlen)
1082+{
1083+ return 0;
1084+}
1085+static inline int ccs_socket_connect(struct socket *sock,
1086+ struct sockaddr *address, int addrlen)
1087+{
1088+ return 0;
1089+}
1090+static inline int ccs_socket_listen(struct socket *sock, int backlog)
1091+{
1092+ return 0;
1093+}
1094+static inline int ccs_socket_sendmsg(struct socket *sock, struct msghdr *msg,
1095+ int size)
1096+{
1097+ return 0;
1098+}
1099+static inline int ccs_path_unlink(struct path *dir, struct dentry *dentry)
1100+{
1101+ return 0;
1102+}
1103+static inline int ccs_path_mkdir(struct path *dir, struct dentry *dentry,
1104+ umode_t mode)
1105+{
1106+ return 0;
1107+}
1108+static inline int ccs_path_rmdir(struct path *dir, struct dentry *dentry)
1109+{
1110+ return 0;
1111+}
1112+static inline int ccs_path_mknod(struct path *dir, struct dentry *dentry,
1113+ umode_t mode, unsigned int dev)
1114+{
1115+ return 0;
1116+}
1117+static inline int ccs_path_truncate(struct path *path)
1118+{
1119+ return 0;
1120+}
1121+static inline int ccs_path_symlink(struct path *dir, struct dentry *dentry,
1122+ const char *old_name)
1123+{
1124+ return 0;
1125+}
1126+static inline int ccs_path_link(struct dentry *old_dentry,
1127+ struct path *new_dir,
1128+ struct dentry *new_dentry)
1129+{
1130+ return 0;
1131+}
1132+static inline int ccs_path_rename(struct path *old_dir,
1133+ struct dentry *old_dentry,
1134+ struct path *new_dir,
1135+ struct dentry *new_dentry)
1136+{
1137+ return 0;
1138+}
1139+static inline int ccs_path_chmod(struct path *path, umode_t mode)
1140+{
1141+ return 0;
1142+}
1143+static inline int ccs_path_chown(struct path *path, kuid_t uid, kgid_t gid)
1144+{
1145+ return 0;
1146+}
1147+static inline int ccs_path_chroot(struct path *path)
1148+{
1149+ return 0;
1150+}
1151+
1152+#endif /* defined(CONFIG_CCSECURITY) */
1153+
1154+#endif /* !defined(_LINUX_LSM2CCSECURITY_H) */
1155diff --git a/security/ccsecurity/Config.in b/security/ccsecurity/Config.in
1156new file mode 100644
1157index 0000000..da39bad6
1158--- /dev/null
1159+++ b/security/ccsecurity/Config.in
1160@@ -0,0 +1,83 @@
1161+#
1162+# Mandatory Access Control configuration
1163+#
1164+mainmenu_option next_comment
1165+comment 'Security options'
1166+
1167+[ -z "$CONFIG_CCSECURITY" ] && define_bool CONFIG_CCSECURITY y
1168+bool 'CCSecurity support' CONFIG_CCSECURITY
1169+
1170+if [ "$CONFIG_CCSECURITY" = "y" ]; then
1171+
1172+ [ -z "$CONFIG_CCSECURITY_LKM" ] && define_bool CONFIG_CCSECURITY_LKM n
1173+ bool 'Compile as loadable kernel module' CONFIG_CCSECURITY_LKM
1174+
1175+ [ -z "$CONFIG_CCSECURITY_DISABLE_BY_DEFAULT" ] && define_bool CONFIG_CCSECURITY_DISABLE_BY_DEFAULT n
1176+ bool 'Disable by default' CONFIG_CCSECURITY_DISABLE_BY_DEFAULT
1177+
1178+ [ -z "$CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY" ] && define_int CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY 2048
1179+ [ $CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY -lt 0 ] && define_int CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY 0
1180+ int 'Default maximal count for learning mode' CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY
1181+
1182+ [ -z "$CONFIG_CCSECURITY_MAX_AUDIT_LOG" ] && define_int CONFIG_CCSECURITY_MAX_AUDIT_LOG 1024
1183+ [ $CONFIG_CCSECURITY_MAX_AUDIT_LOG -lt 0 ] && define_int CONFIG_CCSECURITY_MAX_AUDIT_LOG 0
1184+ int 'Default maximal count for audit log' CONFIG_CCSECURITY_MAX_AUDIT_LOG
1185+
1186+ [ -z "$CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER" ] && define_bool CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER n
1187+ bool 'Activate without calling userspace policy loader.' CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
1188+
1189+ if [ "$CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER" = "n" ]; then
1190+
1191+ define_string CONFIG_CCSECURITY_POLICY_LOADER "/sbin/ccs-init"
1192+ string 'Location of userspace policy loader' CONFIG_CCSECURITY_POLICY_LOADER "/sbin/ccs-init"
1193+
1194+ define_string CONFIG_CCSECURITY_ACTIVATION_TRIGGER "/sbin/init"
1195+ string 'Trigger for calling userspace policy loader' CONFIG_CCSECURITY_ACTIVATION_TRIGGER "/sbin/init"
1196+
1197+ fi
1198+
1199+ [ -z "$CONFIG_CCSECURITY_FILE_READDIR" ] && define_bool CONFIG_CCSECURITY_FILE_READDIR y
1200+ bool "Enable readdir operation restriction." CONFIG_CCSECURITY_FILE_READDIR
1201+
1202+ [ -z "$CONFIG_CCSECURITY_FILE_GETATTR" ] && define_bool CONFIG_CCSECURITY_FILE_GETATTR y
1203+ bool "Enable getattr operation restriction." CONFIG_CCSECURITY_FILE_GETATTR
1204+
1205+ if [ "$CONFIG_NET" = "y" ]; then
1206+
1207+ [ -z "$CONFIG_CCSECURITY_NETWORK" ] && define_bool CONFIG_CCSECURITY_NETWORK y
1208+ bool "Enable socket operation restriction." CONFIG_CCSECURITY_NETWORK
1209+
1210+ if [ "$CONFIG_CCSECURITY_NETWORK" = "y" ]; then
1211+
1212+ #[ -z "$CONFIG_CCSECURITY_NETWORK_RECVMSG" ] &&
1213+ define_bool CONFIG_CCSECURITY_NETWORK_RECVMSG y
1214+
1215+ fi
1216+
1217+ fi
1218+
1219+ [ -z "$CONFIG_CCSECURITY_CAPABILITY" ] && define_bool CONFIG_CCSECURITY_CAPABILITY y
1220+ bool "Enable non-POSIX capability operation restriction." CONFIG_CCSECURITY_CAPABILITY
1221+
1222+ [ -z "$CONFIG_CCSECURITY_IPC" ] && define_bool CONFIG_CCSECURITY_IPC y
1223+ bool "Enable IPC operation restriction." CONFIG_CCSECURITY_IPC
1224+
1225+ [ -z "$CONFIG_CCSECURITY_MISC" ] && define_bool CONFIG_CCSECURITY_MISC y
1226+ bool "Enable environment variable names restriction." CONFIG_CCSECURITY_MISC
1227+
1228+ [ -z "$CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER" ] && define_bool CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER y
1229+ bool "Enable execute handler functionality." CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
1230+
1231+ [ -z "$CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION" ] && define_bool CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION y
1232+ bool "Enable domain transition without program execution request." CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
1233+
1234+ if [ "$CONFIG_NET" = "y" ]; then
1235+
1236+ [ -z "$CONFIG_CCSECURITY_PORTRESERVE" ] && define_bool CONFIG_CCSECURITY_PORTRESERVE y
1237+ bool "Enable local port reserver." CONFIG_CCSECURITY_PORTRESERVE
1238+
1239+ fi
1240+
1241+fi
1242+
1243+endmenu
1244diff --git a/security/ccsecurity/Kconfig b/security/ccsecurity/Kconfig
1245new file mode 100644
1246index 0000000..8d7b200
1247--- /dev/null
1248+++ b/security/ccsecurity/Kconfig
1249@@ -0,0 +1,190 @@
1250+config CCSECURITY
1251+ bool "CCSecurity support"
1252+ default y
1253+ help
1254+ Say Y here to support non-LSM version of TOMOYO Linux.
1255+ http://tomoyo.osdn.jp/
1256+
1257+config CCSECURITY_LKM
1258+ bool "Compile as loadable kernel module"
1259+ default n
1260+ depends on CCSECURITY && MODULES
1261+ help
1262+ This version of TOMOYO depends on patching the kernel source in order
1263+ to insert some hooks which LSM does not provide. Therefore,
1264+ recompiling the kernel is inevitable. But if you want to keep
1265+ vmlinux's size as small as possible, you can compile most part of
1266+ TOMOYO as a loadable kernel module by saying Y here.
1267+
1268+config CCSECURITY_DISABLE_BY_DEFAULT
1269+ bool "Disable by default"
1270+ default n
1271+ depends on CCSECURITY
1272+ help
1273+ Say Y here if you want TOMOYO disabled by default.
1274+ To enable TOMOYO, pass ccsecurity=on to kernel command line.
1275+ To disable TOMOYO, pass ccsecurity=off to kernel command line.
1276+
1277+config CCSECURITY_USE_EXTERNAL_TASK_SECURITY
1278+ bool "Do not modify 'struct task_struct' in order to keep KABI"
1279+ default n
1280+ depends on CCSECURITY
1281+ help
1282+ Say Y here if you want to keep KABI for prebuilt kernel modules
1283+ unchanged. TOMOYO needs "struct ccs_domain_info *" and "u32" for each
1284+ "struct task_struct". But embedding these variables into
1285+ "struct task_struct" breaks KABI for prebuilt kernel modules (which
1286+ means that you will need to rebuild prebuilt kernel modules).
1287+ If you say Y here, these variables are managed outside
1288+ "struct task_struct" rather than embedding into "struct task_struct",
1289+ but accessing these variables becomes slower because lookup operation
1290+ is performed every time the current thread needs to access them.
1291+
1292+config CCSECURITY_MAX_ACCEPT_ENTRY
1293+ int "Default maximal count for learning mode"
1294+ default 2048
1295+ range 0 2147483647
1296+ depends on CCSECURITY
1297+ help
1298+ This is the default value for maximal ACL entries
1299+ that are automatically appended into policy at "learning mode".
1300+ Some programs access thousands of objects, so running
1301+ such programs in "learning mode" dulls the system response
1302+ and consumes much memory.
1303+ This is the safeguard for such programs.
1304+
1305+config CCSECURITY_MAX_AUDIT_LOG
1306+ int "Default maximal count for audit log"
1307+ default 1024
1308+ range 0 2147483647
1309+ depends on CCSECURITY
1310+ help
1311+ This is the default value for maximal entries for
1312+ audit logs that the kernel can hold on memory.
1313+ You can read the log via /proc/ccs/audit.
1314+ If you don't need audit logs, you may set this value to 0.
1315+
1316+config CCSECURITY_OMIT_USERSPACE_LOADER
1317+ bool "Activate without calling userspace policy loader."
1318+ default n
1319+ depends on CCSECURITY
1320+ ---help---
1321+ Say Y here if you want to activate access control as soon as built-in
1322+ policy was loaded. This option will be useful for systems where
1323+ operations which can lead to the hijacking of the boot sequence are
1324+ needed before loading the policy. For example, you can activate
1325+ immediately after loading the fixed part of policy which will allow
1326+ only operations needed for mounting a partition which contains the
1327+ variant part of policy and verifying (e.g. running GPG check) and
1328+ loading the variant part of policy. Since you can start using
1329+ enforcing mode from the beginning, you can reduce the possibility of
1330+ hijacking the boot sequence.
1331+
1332+ If you say Y to both "Compile as loadable kernel module" option and
1333+ "Activate without calling userspace policy loader." option, be sure
1334+ to excplicitly load the kernel module from the userspace, for
1335+ the kernel will not call /sbin/ccs-init when /sbin/init starts.
1336+
1337+config CCSECURITY_POLICY_LOADER
1338+ string "Location of userspace policy loader"
1339+ default "/sbin/ccs-init"
1340+ depends on CCSECURITY
1341+ depends on !CCSECURITY_OMIT_USERSPACE_LOADER
1342+ ---help---
1343+ This is the default pathname of policy loader which is called before
1344+ activation. You can override this setting via CCS_loader= kernel
1345+ command line option.
1346+
1347+config CCSECURITY_ACTIVATION_TRIGGER
1348+ string "Trigger for calling userspace policy loader"
1349+ default "/sbin/init"
1350+ depends on CCSECURITY
1351+ depends on !CCSECURITY_OMIT_USERSPACE_LOADER
1352+ ---help---
1353+ This is the default pathname of activation trigger.
1354+ You can override this setting via CCS_trigger= kernel command line
1355+ option. For example, if you pass init=/bin/systemd option, you may
1356+ want to also pass CCS_trigger=/bin/systemd option.
1357+
1358+ Say Y here if you want to enable only specific functionality in order
1359+ to reduce object file size.
1360+
1361+config CCSECURITY_FILE_READDIR
1362+ bool "Enable readdir operation restriction."
1363+ default y
1364+ depends on CCSECURITY
1365+ ---help---
1366+ Say Y here if you want to enable analysis/restriction of opening
1367+ directories for reading. Reading directory entries is a commonly
1368+ requested operation and damage caused by not restricting it as MAC
1369+ might be acceptable for you.
1370+
1371+config CCSECURITY_FILE_GETATTR
1372+ bool "Enable getattr operation restriction."
1373+ default y
1374+ depends on CCSECURITY
1375+ ---help---
1376+ Say Y here if you want to enable analysis/restriction of getting
1377+ information of files. Getting file's information is a commonly
1378+ requested operation and damage caused by not restricting it as MAC
1379+ might be acceptable for you.
1380+
1381+config CCSECURITY_NETWORK
1382+ bool "Enable socket operation restriction."
1383+ default y
1384+ depends on NET
1385+ depends on CCSECURITY
1386+ ---help---
1387+ Say Y here if you want to enable analysis/restriction of INET and
1388+ UNIX domain socket's operations.
1389+
1390+config CCSECURITY_CAPABILITY
1391+ bool "Enable non-POSIX capability operation restriction."
1392+ default y
1393+ depends on CCSECURITY
1394+ ---help---
1395+ Say Y here if you want to enable analysis/restriction of non-POSIX
1396+ capabilities.
1397+
1398+config CCSECURITY_IPC
1399+ bool "Enable IPC operation restriction."
1400+ default y
1401+ depends on CCSECURITY
1402+ ---help---
1403+ Say Y here if you want to enable analysis/restriction of sending
1404+ signals.
1405+
1406+config CCSECURITY_MISC
1407+ bool "Enable environment variable names restriction."
1408+ default y
1409+ depends on CCSECURITY
1410+ ---help---
1411+ Say Y here if you want to enable analysis/restriction of environment
1412+ variable names passed upon program execution request.
1413+
1414+config CCSECURITY_TASK_EXECUTE_HANDLER
1415+ bool "Enable execute handler functionality."
1416+ default y
1417+ depends on CCSECURITY
1418+ ---help---
1419+ Say Y here if you want to enable execute handler functionality.
1420+
1421+config CCSECURITY_TASK_DOMAIN_TRANSITION
1422+ bool "Enable domain transition without program execution request."
1423+ default y
1424+ depends on CCSECURITY
1425+ ---help---
1426+ Say Y here if you want to enable domain transition without involving
1427+ program execution request.
1428+
1429+config CCSECURITY_PORTRESERVE
1430+ bool "Enable local port reserver."
1431+ default y
1432+ depends on NET
1433+ depends on CCSECURITY
1434+ ---help---
1435+ Say Y here if you want to implement
1436+ /proc/sys/net/ipv4/ip_local_reserved_ports as a MAC policy.
1437+
1438+config CCSECURITY_NETWORK_RECVMSG
1439+ def_bool CCSECURITY_NETWORK
1440diff --git a/security/ccsecurity/Makefile b/security/ccsecurity/Makefile
1441new file mode 100644
1442index 0000000..79c3632
1443--- /dev/null
1444+++ b/security/ccsecurity/Makefile
1445@@ -0,0 +1,122 @@
1446+ccsecurity-objs := permission.o gc.o memory.o policy_io.o realpath.o
1447+
1448+ifeq ($(VERSION)$(PATCHLEVEL),24)
1449+
1450+ifdef CONFIG_CCSECURITY
1451+O_TARGET := ccsecurity.o
1452+ifdef CONFIG_CCSECURITY_LKM
1453+all_targets: load_policy.o
1454+obj-m := ccsecurity.o
1455+obj-y := $(ccsecurity-objs)
1456+else
1457+all_targets: ccsecurity.o
1458+obj-y := load_policy.o $(ccsecurity-objs)
1459+endif
1460+export-objs := load_policy.o
1461+endif
1462+include $(TOPDIR)/Rules.make
1463+
1464+policy/profile.conf:
1465+ @mkdir -p policy/
1466+ @echo Creating an empty policy/profile.conf
1467+ @touch $@
1468+
1469+policy/exception_policy.conf:
1470+ @mkdir -p policy/
1471+ @echo Creating a default policy/exception_policy.conf
1472+ @echo initialize_domain /sbin/modprobe from any >> $@
1473+ @echo initialize_domain /sbin/hotplug from any >> $@
1474+
1475+policy/domain_policy.conf:
1476+ @mkdir -p policy/
1477+ @echo Creating an empty policy/domain_policy.conf
1478+ @touch $@
1479+
1480+policy/manager.conf:
1481+ @mkdir -p policy/
1482+ @echo Creating an empty policy/manager.conf
1483+ @touch $@
1484+
1485+policy/stat.conf:
1486+ @mkdir -p policy/
1487+ @echo Creating an empty policy/stat.conf
1488+ @touch $@
1489+
1490+builtin-policy.h: policy/profile.conf policy/exception_policy.conf policy/domain_policy.conf policy/manager.conf policy/stat.conf
1491+ @echo Generating built-in policy for TOMOYO 1.8.x.
1492+ @echo "static char ccs_builtin_profile[] __initdata =" > $@.tmp
1493+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/profile.conf >> $@.tmp
1494+ @echo "\"\";" >> $@.tmp
1495+ @echo "static char ccs_builtin_exception_policy[] __initdata =" >> $@.tmp
1496+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/exception_policy.conf >> $@.tmp
1497+ @echo "\"\";" >> $@.tmp
1498+ @echo "static char ccs_builtin_domain_policy[] __initdata =" >> $@.tmp
1499+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/domain_policy.conf >> $@.tmp
1500+ @echo "\"\";" >> $@.tmp
1501+ @echo "static char ccs_builtin_manager[] __initdata =" >> $@.tmp
1502+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/manager.conf >> $@.tmp
1503+ @echo "\"\";" >> $@.tmp
1504+ @echo "static char ccs_builtin_stat[] __initdata =" >> $@.tmp
1505+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/stat.conf >> $@.tmp
1506+ @echo "\"\";" >> $@.tmp
1507+ @mv $@.tmp $@
1508+
1509+policy_io.o: builtin-policy.h
1510+
1511+else
1512+
1513+obj-y += load_policy.o
1514+ifdef CONFIG_CCSECURITY_LKM
1515+obj-m += ccsecurity.o
1516+else
1517+obj-y += ccsecurity.o
1518+endif
1519+
1520+$(obj)/policy/profile.conf:
1521+ @mkdir -p $(obj)/policy/
1522+ @echo Creating an empty policy/profile.conf
1523+ @touch $@
1524+
1525+$(obj)/policy/exception_policy.conf:
1526+ @mkdir -p $(obj)/policy/
1527+ @echo Creating a default policy/exception_policy.conf
1528+ @echo initialize_domain /sbin/modprobe from any >> $@
1529+ @echo initialize_domain /sbin/hotplug from any >> $@
1530+
1531+$(obj)/policy/domain_policy.conf:
1532+ @mkdir -p $(obj)/policy/
1533+ @echo Creating an empty policy/domain_policy.conf
1534+ @touch $@
1535+
1536+$(obj)/policy/manager.conf:
1537+ @mkdir -p $(obj)/policy/
1538+ @echo Creating an empty policy/manager.conf
1539+ @touch $@
1540+
1541+$(obj)/policy/stat.conf:
1542+ @mkdir -p $(obj)/policy/
1543+ @echo Creating an empty policy/stat.conf
1544+ @touch $@
1545+
1546+$(obj)/builtin-policy.h: $(obj)/policy/profile.conf $(obj)/policy/exception_policy.conf $(obj)/policy/domain_policy.conf $(obj)/policy/manager.conf $(obj)/policy/stat.conf
1547+ @echo Generating built-in policy for TOMOYO 1.8.x.
1548+ @echo "static char ccs_builtin_profile[] __initdata =" > $@.tmp
1549+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp
1550+ @echo "\"\";" >> $@.tmp
1551+ @echo "static char ccs_builtin_exception_policy[] __initdata =" >> $@.tmp
1552+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/exception_policy.conf >> $@.tmp
1553+ @echo "\"\";" >> $@.tmp
1554+ @echo "static char ccs_builtin_domain_policy[] __initdata =" >> $@.tmp
1555+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/domain_policy.conf >> $@.tmp
1556+ @echo "\"\";" >> $@.tmp
1557+ @echo "static char ccs_builtin_manager[] __initdata =" >> $@.tmp
1558+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/manager.conf >> $@.tmp
1559+ @echo "\"\";" >> $@.tmp
1560+ @echo "static char ccs_builtin_stat[] __initdata =" >> $@.tmp
1561+ @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/stat.conf >> $@.tmp
1562+ @echo "\"\";" >> $@.tmp
1563+ @mv $@.tmp $@
1564+
1565+$(obj)/policy_io.o: $(obj)/builtin-policy.h
1566+
1567+endif
1568diff --git a/security/ccsecurity/gc.c b/security/ccsecurity/gc.c
1569new file mode 100644
1570index 0000000..0a578ab
1571--- /dev/null
1572+++ b/security/ccsecurity/gc.c
1573@@ -0,0 +1,1036 @@
1574+/*
1575+ * security/ccsecurity/gc.c
1576+ *
1577+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
1578+ *
1579+ * Version: 1.8.4 2015/05/05
1580+ */
1581+
1582+#include "internal.h"
1583+
1584+/***** SECTION1: Constants definition *****/
1585+
1586+/* For compatibility with older kernels. */
1587+#ifndef for_each_process
1588+#define for_each_process for_each_task
1589+#endif
1590+
1591+/* The list for "struct ccs_io_buffer". */
1592+static LIST_HEAD(ccs_io_buffer_list);
1593+/* Lock for protecting ccs_io_buffer_list. */
1594+static DEFINE_SPINLOCK(ccs_io_buffer_list_lock);
1595+
1596+/***** SECTION2: Structure definition *****/
1597+
1598+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
1599+
1600+/*
1601+ * Lock for syscall users.
1602+ *
1603+ * This lock is used for protecting single SRCU section for 2.6.18 and
1604+ * earlier kernels because they don't have SRCU support.
1605+ */
1606+struct ccs_lock_struct {
1607+ int counter_idx; /* Currently active index (0 or 1). */
1608+ int counter[2]; /* Current users. Protected by ccs_counter_lock. */
1609+};
1610+
1611+#endif
1612+
1613+/***** SECTION3: Prototype definition section *****/
1614+
1615+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
1616+int ccs_lock(void);
1617+#endif
1618+void ccs_del_acl(struct list_head *element);
1619+void ccs_del_condition(struct list_head *element);
1620+void ccs_notify_gc(struct ccs_io_buffer *head, const bool is_register);
1621+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
1622+void ccs_unlock(const int idx);
1623+#endif
1624+
1625+static bool ccs_domain_used_by_task(struct ccs_domain_info *domain);
1626+static bool ccs_name_used_by_io_buffer(const char *string, const size_t size);
1627+static bool ccs_struct_used_by_io_buffer(const struct list_head *element);
1628+static int ccs_gc_thread(void *unused);
1629+static void ccs_collect_acl(struct list_head *list);
1630+static void ccs_collect_entry(void);
1631+static void ccs_collect_member(const enum ccs_policy_id id,
1632+ struct list_head *member_list);
1633+static void ccs_memory_free(const void *ptr, const enum ccs_policy_id type);
1634+static void ccs_put_name_union(struct ccs_name_union *ptr);
1635+static void ccs_put_number_union(struct ccs_number_union *ptr);
1636+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
1637+static void ccs_synchronize_counter(void);
1638+#endif
1639+static void ccs_try_to_gc(const enum ccs_policy_id type,
1640+ struct list_head *element);
1641+
1642+/***** SECTION4: Standalone functions section *****/
1643+
1644+/***** SECTION5: Variables definition section *****/
1645+
1646+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
1647+
1648+/*
1649+ * Lock for syscall users.
1650+ *
1651+ * This lock is held for only protecting single SRCU section.
1652+ */
1653+struct srcu_struct ccs_ss;
1654+
1655+#else
1656+
1657+static struct ccs_lock_struct ccs_counter;
1658+/* Lock for protecting ccs_counter. */
1659+static DEFINE_SPINLOCK(ccs_counter_lock);
1660+
1661+#endif
1662+
1663+/***** SECTION6: Dependent functions section *****/
1664+
1665+/**
1666+ * ccs_memory_free - Free memory for elements.
1667+ *
1668+ * @ptr: Pointer to allocated memory.
1669+ * @type: One of values in "enum ccs_policy_id".
1670+ *
1671+ * Returns nothing.
1672+ *
1673+ * Caller holds ccs_policy_lock mutex.
1674+ */
1675+static void ccs_memory_free(const void *ptr, const enum ccs_policy_id type)
1676+{
1677+ /* Size of an element. */
1678+ static const u8 e[CCS_MAX_POLICY] = {
1679+#ifdef CONFIG_CCSECURITY_PORTRESERVE
1680+ [CCS_ID_RESERVEDPORT] = sizeof(struct ccs_reserved),
1681+#endif
1682+ [CCS_ID_GROUP] = sizeof(struct ccs_group),
1683+#ifdef CONFIG_CCSECURITY_NETWORK
1684+ [CCS_ID_ADDRESS_GROUP] = sizeof(struct ccs_address_group),
1685+#endif
1686+ [CCS_ID_PATH_GROUP] = sizeof(struct ccs_path_group),
1687+ [CCS_ID_NUMBER_GROUP] = sizeof(struct ccs_number_group),
1688+ [CCS_ID_AGGREGATOR] = sizeof(struct ccs_aggregator),
1689+ [CCS_ID_TRANSITION_CONTROL]
1690+ = sizeof(struct ccs_transition_control),
1691+ [CCS_ID_MANAGER] = sizeof(struct ccs_manager),
1692+ /* [CCS_ID_CONDITION] = "struct ccs_condition"->size, */
1693+ /* [CCS_ID_NAME] = "struct ccs_name"->size, */
1694+ /* [CCS_ID_ACL] = a["struct ccs_acl_info"->type], */
1695+ [CCS_ID_DOMAIN] = sizeof(struct ccs_domain_info),
1696+ };
1697+ /* Size of a domain ACL element. */
1698+ static const u8 a[] = {
1699+ [CCS_TYPE_PATH_ACL] = sizeof(struct ccs_path_acl),
1700+ [CCS_TYPE_PATH2_ACL] = sizeof(struct ccs_path2_acl),
1701+ [CCS_TYPE_PATH_NUMBER_ACL]
1702+ = sizeof(struct ccs_path_number_acl),
1703+ [CCS_TYPE_MKDEV_ACL] = sizeof(struct ccs_mkdev_acl),
1704+ [CCS_TYPE_MOUNT_ACL] = sizeof(struct ccs_mount_acl),
1705+#ifdef CONFIG_CCSECURITY_NETWORK
1706+ [CCS_TYPE_INET_ACL] = sizeof(struct ccs_inet_acl),
1707+ [CCS_TYPE_UNIX_ACL] = sizeof(struct ccs_unix_acl),
1708+#endif
1709+#ifdef CONFIG_CCSECURITY_MISC
1710+ [CCS_TYPE_ENV_ACL] = sizeof(struct ccs_env_acl),
1711+#endif
1712+#ifdef CONFIG_CCSECURITY_CAPABILITY
1713+ [CCS_TYPE_CAPABILITY_ACL] = sizeof(struct ccs_capability_acl),
1714+#endif
1715+#ifdef CONFIG_CCSECURITY_IPC
1716+ [CCS_TYPE_SIGNAL_ACL] = sizeof(struct ccs_signal_acl),
1717+#endif
1718+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
1719+ [CCS_TYPE_AUTO_EXECUTE_HANDLER]
1720+ = sizeof(struct ccs_handler_acl),
1721+ [CCS_TYPE_DENIED_EXECUTE_HANDLER]
1722+ = sizeof(struct ccs_handler_acl),
1723+#endif
1724+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
1725+ [CCS_TYPE_AUTO_TASK_ACL] = sizeof(struct ccs_task_acl),
1726+ [CCS_TYPE_MANUAL_TASK_ACL] = sizeof(struct ccs_task_acl),
1727+#endif
1728+ };
1729+ size_t size;
1730+ if (type == CCS_ID_ACL)
1731+ size = a[container_of(ptr, typeof(struct ccs_acl_info),
1732+ list)->type];
1733+ else if (type == CCS_ID_NAME)
1734+ size = container_of(ptr, typeof(struct ccs_name),
1735+ head.list)->size;
1736+ else if (type == CCS_ID_CONDITION)
1737+ size = container_of(ptr, typeof(struct ccs_condition),
1738+ head.list)->size;
1739+ else
1740+ size = e[type];
1741+ ccs_memory_used[CCS_MEMORY_POLICY] -= ccs_round2(size);
1742+ kfree(ptr);
1743+}
1744+
1745+/**
1746+ * ccs_put_name_union - Drop reference on "struct ccs_name_union".
1747+ *
1748+ * @ptr: Pointer to "struct ccs_name_union".
1749+ *
1750+ * Returns nothing.
1751+ */
1752+static void ccs_put_name_union(struct ccs_name_union *ptr)
1753+{
1754+ ccs_put_group(ptr->group);
1755+ ccs_put_name(ptr->filename);
1756+}
1757+
1758+/**
1759+ * ccs_put_number_union - Drop reference on "struct ccs_number_union".
1760+ *
1761+ * @ptr: Pointer to "struct ccs_number_union".
1762+ *
1763+ * Returns nothing.
1764+ */
1765+static void ccs_put_number_union(struct ccs_number_union *ptr)
1766+{
1767+ ccs_put_group(ptr->group);
1768+}
1769+
1770+/**
1771+ * ccs_struct_used_by_io_buffer - Check whether the list element is used by /proc/ccs/ users or not.
1772+ *
1773+ * @element: Pointer to "struct list_head".
1774+ *
1775+ * Returns true if @element is used by /proc/ccs/ users, false otherwise.
1776+ */
1777+static bool ccs_struct_used_by_io_buffer(const struct list_head *element)
1778+{
1779+ struct ccs_io_buffer *head;
1780+ bool in_use = false;
1781+ spin_lock(&ccs_io_buffer_list_lock);
1782+ list_for_each_entry(head, &ccs_io_buffer_list, list) {
1783+ head->users++;
1784+ spin_unlock(&ccs_io_buffer_list_lock);
1785+ mutex_lock(&head->io_sem);
1786+ if (head->r.domain == element || head->r.group == element ||
1787+ head->r.acl == element || &head->w.domain->list == element)
1788+ in_use = true;
1789+ mutex_unlock(&head->io_sem);
1790+ spin_lock(&ccs_io_buffer_list_lock);
1791+ head->users--;
1792+ if (in_use)
1793+ break;
1794+ }
1795+ spin_unlock(&ccs_io_buffer_list_lock);
1796+ return in_use;
1797+}
1798+
1799+/**
1800+ * ccs_name_used_by_io_buffer - Check whether the string is used by /proc/ccs/ users or not.
1801+ *
1802+ * @string: String to check.
1803+ * @size: Memory allocated for @string .
1804+ *
1805+ * Returns true if @string is used by /proc/ccs/ users, false otherwise.
1806+ */
1807+static bool ccs_name_used_by_io_buffer(const char *string, const size_t size)
1808+{
1809+ struct ccs_io_buffer *head;
1810+ bool in_use = false;
1811+ spin_lock(&ccs_io_buffer_list_lock);
1812+ list_for_each_entry(head, &ccs_io_buffer_list, list) {
1813+ int i;
1814+ head->users++;
1815+ spin_unlock(&ccs_io_buffer_list_lock);
1816+ mutex_lock(&head->io_sem);
1817+ for (i = 0; i < CCS_MAX_IO_READ_QUEUE; i++) {
1818+ const char *w = head->r.w[i];
1819+ if (w < string || w > string + size)
1820+ continue;
1821+ in_use = true;
1822+ break;
1823+ }
1824+ mutex_unlock(&head->io_sem);
1825+ spin_lock(&ccs_io_buffer_list_lock);
1826+ head->users--;
1827+ if (in_use)
1828+ break;
1829+ }
1830+ spin_unlock(&ccs_io_buffer_list_lock);
1831+ return in_use;
1832+}
1833+
1834+/**
1835+ * ccs_del_transition_control - Delete members in "struct ccs_transition_control".
1836+ *
1837+ * @element: Pointer to "struct list_head".
1838+ *
1839+ * Returns nothing.
1840+ */
1841+static inline void ccs_del_transition_control(struct list_head *element)
1842+{
1843+ struct ccs_transition_control *ptr =
1844+ container_of(element, typeof(*ptr), head.list);
1845+ ccs_put_name(ptr->domainname);
1846+ ccs_put_name(ptr->program);
1847+}
1848+
1849+/**
1850+ * ccs_del_aggregator - Delete members in "struct ccs_aggregator".
1851+ *
1852+ * @element: Pointer to "struct list_head".
1853+ *
1854+ * Returns nothing.
1855+ */
1856+static inline void ccs_del_aggregator(struct list_head *element)
1857+{
1858+ struct ccs_aggregator *ptr =
1859+ container_of(element, typeof(*ptr), head.list);
1860+ ccs_put_name(ptr->original_name);
1861+ ccs_put_name(ptr->aggregated_name);
1862+}
1863+
1864+/**
1865+ * ccs_del_manager - Delete members in "struct ccs_manager".
1866+ *
1867+ * @element: Pointer to "struct list_head".
1868+ *
1869+ * Returns nothing.
1870+ */
1871+static inline void ccs_del_manager(struct list_head *element)
1872+{
1873+ struct ccs_manager *ptr =
1874+ container_of(element, typeof(*ptr), head.list);
1875+ ccs_put_name(ptr->manager);
1876+}
1877+
1878+/**
1879+ * ccs_domain_used_by_task - Check whether the given pointer is referenced by a task.
1880+ *
1881+ * @domain: Pointer to "struct ccs_domain_info".
1882+ *
1883+ * Returns true if @domain is in use, false otherwise.
1884+ */
1885+static bool ccs_domain_used_by_task(struct ccs_domain_info *domain)
1886+{
1887+ bool in_use = false;
1888+ /*
1889+ * Don't delete this domain if somebody is doing execve().
1890+ *
1891+ * Since ccs_finish_execve() first reverts ccs_domain_info and then
1892+ * updates ccs_flags, we need smp_rmb() to make sure that GC first
1893+ * checks ccs_flags and then checks ccs_domain_info.
1894+ */
1895+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
1896+ int idx;
1897+ rcu_read_lock();
1898+ for (idx = 0; idx < CCS_MAX_TASK_SECURITY_HASH; idx++) {
1899+ struct ccs_security *ptr;
1900+ struct list_head *list = &ccs_task_security_list[idx];
1901+ list_for_each_entry_rcu(ptr, list, list) {
1902+ if (!(ptr->ccs_flags & CCS_TASK_IS_IN_EXECVE)) {
1903+ smp_rmb(); /* Avoid out of order execution. */
1904+ if (ptr->ccs_domain_info != domain)
1905+ continue;
1906+ }
1907+ in_use = true;
1908+ goto out;
1909+ }
1910+ }
1911+out:
1912+ rcu_read_unlock();
1913+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
1914+ struct task_struct *g;
1915+ struct task_struct *t;
1916+ ccs_tasklist_lock();
1917+ do_each_thread(g, t) {
1918+ if (!(t->ccs_flags & CCS_TASK_IS_IN_EXECVE)) {
1919+ smp_rmb(); /* Avoid out of order execution. */
1920+ if (t->ccs_domain_info != domain)
1921+ continue;
1922+ }
1923+ in_use = true;
1924+ goto out;
1925+ } while_each_thread(g, t);
1926+out:
1927+ ccs_tasklist_unlock();
1928+#else
1929+ struct task_struct *p;
1930+ ccs_tasklist_lock();
1931+ for_each_process(p) {
1932+ if (!(p->ccs_flags & CCS_TASK_IS_IN_EXECVE)) {
1933+ smp_rmb(); /* Avoid out of order execution. */
1934+ if (p->ccs_domain_info != domain)
1935+ continue;
1936+ }
1937+ in_use = true;
1938+ break;
1939+ }
1940+ ccs_tasklist_unlock();
1941+#endif
1942+ return in_use;
1943+}
1944+
1945+/**
1946+ * ccs_del_acl - Delete members in "struct ccs_acl_info".
1947+ *
1948+ * @element: Pointer to "struct list_head".
1949+ *
1950+ * Returns nothing.
1951+ */
1952+void ccs_del_acl(struct list_head *element)
1953+{
1954+ struct ccs_acl_info *acl = container_of(element, typeof(*acl), list);
1955+ ccs_put_condition(acl->cond);
1956+ switch (acl->type) {
1957+ case CCS_TYPE_PATH_ACL:
1958+ {
1959+ struct ccs_path_acl *entry =
1960+ container_of(acl, typeof(*entry), head);
1961+ ccs_put_name_union(&entry->name);
1962+ }
1963+ break;
1964+ case CCS_TYPE_PATH2_ACL:
1965+ {
1966+ struct ccs_path2_acl *entry =
1967+ container_of(acl, typeof(*entry), head);
1968+ ccs_put_name_union(&entry->name1);
1969+ ccs_put_name_union(&entry->name2);
1970+ }
1971+ break;
1972+ case CCS_TYPE_PATH_NUMBER_ACL:
1973+ {
1974+ struct ccs_path_number_acl *entry =
1975+ container_of(acl, typeof(*entry), head);
1976+ ccs_put_name_union(&entry->name);
1977+ ccs_put_number_union(&entry->number);
1978+ }
1979+ break;
1980+ case CCS_TYPE_MKDEV_ACL:
1981+ {
1982+ struct ccs_mkdev_acl *entry =
1983+ container_of(acl, typeof(*entry), head);
1984+ ccs_put_name_union(&entry->name);
1985+ ccs_put_number_union(&entry->mode);
1986+ ccs_put_number_union(&entry->major);
1987+ ccs_put_number_union(&entry->minor);
1988+ }
1989+ break;
1990+ case CCS_TYPE_MOUNT_ACL:
1991+ {
1992+ struct ccs_mount_acl *entry =
1993+ container_of(acl, typeof(*entry), head);
1994+ ccs_put_name_union(&entry->dev_name);
1995+ ccs_put_name_union(&entry->dir_name);
1996+ ccs_put_name_union(&entry->fs_type);
1997+ ccs_put_number_union(&entry->flags);
1998+ }
1999+ break;
2000+#ifdef CONFIG_CCSECURITY_NETWORK
2001+ case CCS_TYPE_INET_ACL:
2002+ {
2003+ struct ccs_inet_acl *entry =
2004+ container_of(acl, typeof(*entry), head);
2005+ ccs_put_group(entry->address.group);
2006+ ccs_put_number_union(&entry->port);
2007+ }
2008+ break;
2009+ case CCS_TYPE_UNIX_ACL:
2010+ {
2011+ struct ccs_unix_acl *entry =
2012+ container_of(acl, typeof(*entry), head);
2013+ ccs_put_name_union(&entry->name);
2014+ }
2015+ break;
2016+#endif
2017+#ifdef CONFIG_CCSECURITY_MISC
2018+ case CCS_TYPE_ENV_ACL:
2019+ {
2020+ struct ccs_env_acl *entry =
2021+ container_of(acl, typeof(*entry), head);
2022+ ccs_put_name(entry->env);
2023+ }
2024+ break;
2025+#endif
2026+#ifdef CONFIG_CCSECURITY_CAPABILITY
2027+ case CCS_TYPE_CAPABILITY_ACL:
2028+ {
2029+ /* Nothing to do. */
2030+ }
2031+ break;
2032+#endif
2033+#ifdef CONFIG_CCSECURITY_IPC
2034+ case CCS_TYPE_SIGNAL_ACL:
2035+ {
2036+ struct ccs_signal_acl *entry =
2037+ container_of(acl, typeof(*entry), head);
2038+ ccs_put_number_union(&entry->sig);
2039+ ccs_put_name(entry->domainname);
2040+ }
2041+ break;
2042+#endif
2043+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
2044+ case CCS_TYPE_AUTO_EXECUTE_HANDLER:
2045+ case CCS_TYPE_DENIED_EXECUTE_HANDLER:
2046+ {
2047+ struct ccs_handler_acl *entry =
2048+ container_of(acl, typeof(*entry), head);
2049+ ccs_put_name(entry->handler);
2050+ }
2051+ break;
2052+#endif
2053+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
2054+ case CCS_TYPE_AUTO_TASK_ACL:
2055+ case CCS_TYPE_MANUAL_TASK_ACL:
2056+ {
2057+ struct ccs_task_acl *entry =
2058+ container_of(acl, typeof(*entry), head);
2059+ ccs_put_name(entry->domainname);
2060+ }
2061+ break;
2062+#endif
2063+ }
2064+}
2065+
2066+/**
2067+ * ccs_del_domain - Delete members in "struct ccs_domain_info".
2068+ *
2069+ * @element: Pointer to "struct list_head".
2070+ *
2071+ * Returns nothing.
2072+ *
2073+ * Caller holds ccs_policy_lock mutex.
2074+ */
2075+static inline void ccs_del_domain(struct list_head *element)
2076+{
2077+ struct ccs_domain_info *domain =
2078+ container_of(element, typeof(*domain), list);
2079+ struct ccs_acl_info *acl;
2080+ struct ccs_acl_info *tmp;
2081+ /*
2082+ * Since this domain is referenced from neither "struct ccs_io_buffer"
2083+ * nor "struct task_struct", we can delete elements without checking
2084+ * for is_deleted flag.
2085+ */
2086+ list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
2087+ ccs_del_acl(&acl->list);
2088+ ccs_memory_free(acl, CCS_ID_ACL);
2089+ }
2090+ ccs_put_name(domain->domainname);
2091+}
2092+
2093+/**
2094+ * ccs_del_path_group - Delete members in "struct ccs_path_group".
2095+ *
2096+ * @element: Pointer to "struct list_head".
2097+ *
2098+ * Returns nothing.
2099+ */
2100+static inline void ccs_del_path_group(struct list_head *element)
2101+{
2102+ struct ccs_path_group *member =
2103+ container_of(element, typeof(*member), head.list);
2104+ ccs_put_name(member->member_name);
2105+}
2106+
2107+/**
2108+ * ccs_del_group - Delete "struct ccs_group".
2109+ *
2110+ * @element: Pointer to "struct list_head".
2111+ *
2112+ * Returns nothing.
2113+ */
2114+static inline void ccs_del_group(struct list_head *element)
2115+{
2116+ struct ccs_group *group =
2117+ container_of(element, typeof(*group), head.list);
2118+ ccs_put_name(group->group_name);
2119+}
2120+
2121+/**
2122+ * ccs_del_address_group - Delete members in "struct ccs_address_group".
2123+ *
2124+ * @element: Pointer to "struct list_head".
2125+ *
2126+ * Returns nothing.
2127+ */
2128+static inline void ccs_del_address_group(struct list_head *element)
2129+{
2130+ /* Nothing to do. */
2131+}
2132+
2133+/**
2134+ * ccs_del_number_group - Delete members in "struct ccs_number_group".
2135+ *
2136+ * @element: Pointer to "struct list_head".
2137+ *
2138+ * Returns nothing.
2139+ */
2140+static inline void ccs_del_number_group(struct list_head *element)
2141+{
2142+ /* Nothing to do. */
2143+}
2144+
2145+/**
2146+ * ccs_del_reservedport - Delete members in "struct ccs_reserved".
2147+ *
2148+ * @element: Pointer to "struct list_head".
2149+ *
2150+ * Returns nothing.
2151+ */
2152+static inline void ccs_del_reservedport(struct list_head *element)
2153+{
2154+ /* Nothing to do. */
2155+}
2156+
2157+/**
2158+ * ccs_del_condition - Delete members in "struct ccs_condition".
2159+ *
2160+ * @element: Pointer to "struct list_head".
2161+ *
2162+ * Returns nothing.
2163+ */
2164+void ccs_del_condition(struct list_head *element)
2165+{
2166+ struct ccs_condition *cond = container_of(element, typeof(*cond),
2167+ head.list);
2168+ const u16 condc = cond->condc;
2169+ const u16 numbers_count = cond->numbers_count;
2170+ const u16 names_count = cond->names_count;
2171+ const u16 argc = cond->argc;
2172+ const u16 envc = cond->envc;
2173+ unsigned int i;
2174+ const struct ccs_condition_element *condp
2175+ = (const struct ccs_condition_element *) (cond + 1);
2176+ struct ccs_number_union *numbers_p
2177+ = (struct ccs_number_union *) (condp + condc);
2178+ struct ccs_name_union *names_p
2179+ = (struct ccs_name_union *) (numbers_p + numbers_count);
2180+ const struct ccs_argv *argv
2181+ = (const struct ccs_argv *) (names_p + names_count);
2182+ const struct ccs_envp *envp
2183+ = (const struct ccs_envp *) (argv + argc);
2184+ for (i = 0; i < numbers_count; i++)
2185+ ccs_put_number_union(numbers_p++);
2186+ for (i = 0; i < names_count; i++)
2187+ ccs_put_name_union(names_p++);
2188+ for (i = 0; i < argc; argv++, i++)
2189+ ccs_put_name(argv->value);
2190+ for (i = 0; i < envc; envp++, i++) {
2191+ ccs_put_name(envp->name);
2192+ ccs_put_name(envp->value);
2193+ }
2194+ ccs_put_name(cond->transit);
2195+}
2196+
2197+/**
2198+ * ccs_del_name - Delete members in "struct ccs_name".
2199+ *
2200+ * @element: Pointer to "struct list_head".
2201+ *
2202+ * Returns nothing.
2203+ */
2204+static inline void ccs_del_name(struct list_head *element)
2205+{
2206+ /* Nothing to do. */
2207+}
2208+
2209+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
2210+
2211+/**
2212+ * ccs_lock - Alternative for srcu_read_lock().
2213+ *
2214+ * Returns index number which has to be passed to ccs_unlock().
2215+ */
2216+int ccs_lock(void)
2217+{
2218+ int idx;
2219+ spin_lock(&ccs_counter_lock);
2220+ idx = ccs_counter.counter_idx;
2221+ ccs_counter.counter[idx]++;
2222+ spin_unlock(&ccs_counter_lock);
2223+ return idx;
2224+}
2225+
2226+/**
2227+ * ccs_unlock - Alternative for srcu_read_unlock().
2228+ *
2229+ * @idx: Index number returned by ccs_lock().
2230+ *
2231+ * Returns nothing.
2232+ */
2233+void ccs_unlock(const int idx)
2234+{
2235+ spin_lock(&ccs_counter_lock);
2236+ ccs_counter.counter[idx]--;
2237+ spin_unlock(&ccs_counter_lock);
2238+}
2239+
2240+/**
2241+ * ccs_synchronize_counter - Alternative for synchronize_srcu().
2242+ *
2243+ * Returns nothing.
2244+ */
2245+static void ccs_synchronize_counter(void)
2246+{
2247+ int idx;
2248+ int v;
2249+ /*
2250+ * Change currently active counter's index. Make it visible to other
2251+ * threads by doing it with ccs_counter_lock held.
2252+ * This function is called by garbage collector thread, and the garbage
2253+ * collector thread is exclusive. Therefore, it is guaranteed that
2254+ * SRCU grace period has expired when returning from this function.
2255+ */
2256+ spin_lock(&ccs_counter_lock);
2257+ idx = ccs_counter.counter_idx;
2258+ ccs_counter.counter_idx ^= 1;
2259+ v = ccs_counter.counter[idx];
2260+ spin_unlock(&ccs_counter_lock);
2261+ /* Wait for previously active counter to become 0. */
2262+ while (v) {
2263+ ssleep(1);
2264+ spin_lock(&ccs_counter_lock);
2265+ v = ccs_counter.counter[idx];
2266+ spin_unlock(&ccs_counter_lock);
2267+ }
2268+}
2269+
2270+#endif
2271+
2272+/**
2273+ * ccs_try_to_gc - Try to kfree() an entry.
2274+ *
2275+ * @type: One of values in "enum ccs_policy_id".
2276+ * @element: Pointer to "struct list_head".
2277+ *
2278+ * Returns nothing.
2279+ *
2280+ * Caller holds ccs_policy_lock mutex.
2281+ */
2282+static void ccs_try_to_gc(const enum ccs_policy_id type,
2283+ struct list_head *element)
2284+{
2285+ /*
2286+ * __list_del_entry() guarantees that the list element became no longer
2287+ * reachable from the list which the element was originally on (e.g.
2288+ * ccs_domain_list). Also, synchronize_srcu() guarantees that the list
2289+ * element became no longer referenced by syscall users.
2290+ */
2291+ __list_del_entry(element);
2292+ mutex_unlock(&ccs_policy_lock);
2293+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
2294+ synchronize_srcu(&ccs_ss);
2295+#else
2296+ ccs_synchronize_counter();
2297+#endif
2298+ /*
2299+ * However, there are two users which may still be using the list
2300+ * element. We need to defer until both users forget this element.
2301+ *
2302+ * Don't kfree() until "struct ccs_io_buffer"->r.{domain,group,acl} and
2303+ * "struct ccs_io_buffer"->w.domain forget this element.
2304+ */
2305+ if (ccs_struct_used_by_io_buffer(element))
2306+ goto reinject;
2307+ switch (type) {
2308+ case CCS_ID_TRANSITION_CONTROL:
2309+ ccs_del_transition_control(element);
2310+ break;
2311+ case CCS_ID_MANAGER:
2312+ ccs_del_manager(element);
2313+ break;
2314+ case CCS_ID_AGGREGATOR:
2315+ ccs_del_aggregator(element);
2316+ break;
2317+ case CCS_ID_GROUP:
2318+ ccs_del_group(element);
2319+ break;
2320+ case CCS_ID_PATH_GROUP:
2321+ ccs_del_path_group(element);
2322+ break;
2323+#ifdef CONFIG_CCSECURITY_NETWORK
2324+ case CCS_ID_ADDRESS_GROUP:
2325+ ccs_del_address_group(element);
2326+ break;
2327+#endif
2328+ case CCS_ID_NUMBER_GROUP:
2329+ ccs_del_number_group(element);
2330+ break;
2331+#ifdef CONFIG_CCSECURITY_PORTRESERVE
2332+ case CCS_ID_RESERVEDPORT:
2333+ ccs_del_reservedport(element);
2334+ break;
2335+#endif
2336+ case CCS_ID_CONDITION:
2337+ ccs_del_condition(element);
2338+ break;
2339+ case CCS_ID_NAME:
2340+ /*
2341+ * Don't kfree() until all "struct ccs_io_buffer"->r.w[] forget
2342+ * this element.
2343+ */
2344+ if (ccs_name_used_by_io_buffer
2345+ (container_of(element, typeof(struct ccs_name),
2346+ head.list)->entry.name,
2347+ container_of(element, typeof(struct ccs_name),
2348+ head.list)->size))
2349+ goto reinject;
2350+ ccs_del_name(element);
2351+ break;
2352+ case CCS_ID_ACL:
2353+ ccs_del_acl(element);
2354+ break;
2355+ case CCS_ID_DOMAIN:
2356+ /*
2357+ * Don't kfree() until all "struct task_struct" forget this
2358+ * element.
2359+ */
2360+ if (ccs_domain_used_by_task
2361+ (container_of(element, typeof(struct ccs_domain_info),
2362+ list)))
2363+ goto reinject;
2364+ break;
2365+ case CCS_MAX_POLICY:
2366+ break;
2367+ }
2368+ mutex_lock(&ccs_policy_lock);
2369+ if (type == CCS_ID_DOMAIN)
2370+ ccs_del_domain(element);
2371+ ccs_memory_free(element, type);
2372+ return;
2373+reinject:
2374+ /*
2375+ * We can safely reinject this element here bacause
2376+ * (1) Appending list elements and removing list elements are protected
2377+ * by ccs_policy_lock mutex.
2378+ * (2) Only this function removes list elements and this function is
2379+ * exclusively executed by ccs_gc_mutex mutex.
2380+ * are true.
2381+ */
2382+ mutex_lock(&ccs_policy_lock);
2383+ list_add_rcu(element, element->prev);
2384+}
2385+
2386+/**
2387+ * ccs_collect_member - Delete elements with "struct ccs_acl_head".
2388+ *
2389+ * @id: One of values in "enum ccs_policy_id".
2390+ * @member_list: Pointer to "struct list_head".
2391+ *
2392+ * Returns nothing.
2393+ *
2394+ * Caller holds ccs_policy_lock mutex.
2395+ */
2396+static void ccs_collect_member(const enum ccs_policy_id id,
2397+ struct list_head *member_list)
2398+{
2399+ struct ccs_acl_head *member;
2400+ struct ccs_acl_head *tmp;
2401+ list_for_each_entry_safe(member, tmp, member_list, list) {
2402+ if (!member->is_deleted)
2403+ continue;
2404+ member->is_deleted = CCS_GC_IN_PROGRESS;
2405+ ccs_try_to_gc(id, &member->list);
2406+ }
2407+}
2408+
2409+/**
2410+ * ccs_collect_acl - Delete elements in "struct ccs_domain_info".
2411+ *
2412+ * @list: Pointer to "struct list_head".
2413+ *
2414+ * Returns nothing.
2415+ *
2416+ * Caller holds ccs_policy_lock mutex.
2417+ */
2418+static void ccs_collect_acl(struct list_head *list)
2419+{
2420+ struct ccs_acl_info *acl;
2421+ struct ccs_acl_info *tmp;
2422+ list_for_each_entry_safe(acl, tmp, list, list) {
2423+ if (!acl->is_deleted)
2424+ continue;
2425+ acl->is_deleted = CCS_GC_IN_PROGRESS;
2426+ ccs_try_to_gc(CCS_ID_ACL, &acl->list);
2427+ }
2428+}
2429+
2430+/**
2431+ * ccs_collect_entry - Try to kfree() deleted elements.
2432+ *
2433+ * Returns nothing.
2434+ */
2435+static void ccs_collect_entry(void)
2436+{
2437+ int i;
2438+ enum ccs_policy_id id;
2439+ struct ccs_policy_namespace *ns;
2440+ mutex_lock(&ccs_policy_lock);
2441+ {
2442+ struct ccs_domain_info *domain;
2443+ struct ccs_domain_info *tmp;
2444+ list_for_each_entry_safe(domain, tmp, &ccs_domain_list, list) {
2445+ ccs_collect_acl(&domain->acl_info_list);
2446+ if (!domain->is_deleted ||
2447+ ccs_domain_used_by_task(domain))
2448+ continue;
2449+ ccs_try_to_gc(CCS_ID_DOMAIN, &domain->list);
2450+ }
2451+ }
2452+ list_for_each_entry(ns, &ccs_namespace_list, namespace_list) {
2453+ for (id = 0; id < CCS_MAX_POLICY; id++)
2454+ ccs_collect_member(id, &ns->policy_list[id]);
2455+ for (i = 0; i < CCS_MAX_ACL_GROUPS; i++)
2456+ ccs_collect_acl(&ns->acl_group[i]);
2457+ }
2458+ {
2459+ struct ccs_shared_acl_head *ptr;
2460+ struct ccs_shared_acl_head *tmp;
2461+ list_for_each_entry_safe(ptr, tmp, &ccs_condition_list, list) {
2462+ if (atomic_read(&ptr->users) > 0)
2463+ continue;
2464+ atomic_set(&ptr->users, CCS_GC_IN_PROGRESS);
2465+ ccs_try_to_gc(CCS_ID_CONDITION, &ptr->list);
2466+ }
2467+ }
2468+ list_for_each_entry(ns, &ccs_namespace_list, namespace_list) {
2469+ for (i = 0; i < CCS_MAX_GROUP; i++) {
2470+ struct list_head *list = &ns->group_list[i];
2471+ struct ccs_group *group;
2472+ struct ccs_group *tmp;
2473+ switch (i) {
2474+ case 0:
2475+ id = CCS_ID_PATH_GROUP;
2476+ break;
2477+ case 1:
2478+ id = CCS_ID_NUMBER_GROUP;
2479+ break;
2480+ default:
2481+#ifdef CONFIG_CCSECURITY_NETWORK
2482+ id = CCS_ID_ADDRESS_GROUP;
2483+#else
2484+ continue;
2485+#endif
2486+ break;
2487+ }
2488+ list_for_each_entry_safe(group, tmp, list, head.list) {
2489+ ccs_collect_member(id, &group->member_list);
2490+ if (!list_empty(&group->member_list) ||
2491+ atomic_read(&group->head.users) > 0)
2492+ continue;
2493+ atomic_set(&group->head.users,
2494+ CCS_GC_IN_PROGRESS);
2495+ ccs_try_to_gc(CCS_ID_GROUP, &group->head.list);
2496+ }
2497+ }
2498+ }
2499+ for (i = 0; i < CCS_MAX_HASH; i++) {
2500+ struct list_head *list = &ccs_name_list[i];
2501+ struct ccs_shared_acl_head *ptr;
2502+ struct ccs_shared_acl_head *tmp;
2503+ list_for_each_entry_safe(ptr, tmp, list, list) {
2504+ if (atomic_read(&ptr->users) > 0)
2505+ continue;
2506+ atomic_set(&ptr->users, CCS_GC_IN_PROGRESS);
2507+ ccs_try_to_gc(CCS_ID_NAME, &ptr->list);
2508+ }
2509+ }
2510+ mutex_unlock(&ccs_policy_lock);
2511+}
2512+
2513+/**
2514+ * ccs_gc_thread - Garbage collector thread function.
2515+ *
2516+ * @unused: Unused.
2517+ *
2518+ * Returns 0.
2519+ */
2520+static int ccs_gc_thread(void *unused)
2521+{
2522+ /* Garbage collector thread is exclusive. */
2523+ static DEFINE_MUTEX(ccs_gc_mutex);
2524+ if (!mutex_trylock(&ccs_gc_mutex))
2525+ goto out;
2526+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 6)
2527+ /* daemonize() not needed. */
2528+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
2529+ daemonize("GC for CCS");
2530+#else
2531+ daemonize();
2532+ reparent_to_init();
2533+#if defined(TASK_DEAD)
2534+ {
2535+ struct task_struct *task = current;
2536+ spin_lock_irq(&task->sighand->siglock);
2537+ siginitsetinv(&task->blocked, 0);
2538+ recalc_sigpending();
2539+ spin_unlock_irq(&task->sighand->siglock);
2540+ }
2541+#else
2542+ {
2543+ struct task_struct *task = current;
2544+ spin_lock_irq(&task->sigmask_lock);
2545+ siginitsetinv(&task->blocked, 0);
2546+ recalc_sigpending(task);
2547+ spin_unlock_irq(&task->sigmask_lock);
2548+ }
2549+#endif
2550+ snprintf(current->comm, sizeof(current->comm) - 1, "GC for CCS");
2551+#endif
2552+ ccs_collect_entry();
2553+ {
2554+ struct ccs_io_buffer *head;
2555+ struct ccs_io_buffer *tmp;
2556+ spin_lock(&ccs_io_buffer_list_lock);
2557+ list_for_each_entry_safe(head, tmp, &ccs_io_buffer_list,
2558+ list) {
2559+ if (head->users)
2560+ continue;
2561+ list_del(&head->list);
2562+ kfree(head->read_buf);
2563+ kfree(head->write_buf);
2564+ kfree(head);
2565+ }
2566+ spin_unlock(&ccs_io_buffer_list_lock);
2567+ }
2568+ mutex_unlock(&ccs_gc_mutex);
2569+out:
2570+ /* This acts as do_exit(0). */
2571+ return 0;
2572+}
2573+
2574+/**
2575+ * ccs_notify_gc - Register/unregister /proc/ccs/ users.
2576+ *
2577+ * @head: Pointer to "struct ccs_io_buffer".
2578+ * @is_register: True if register, false if unregister.
2579+ *
2580+ * Returns nothing.
2581+ */
2582+void ccs_notify_gc(struct ccs_io_buffer *head, const bool is_register)
2583+{
2584+ bool is_write = false;
2585+ spin_lock(&ccs_io_buffer_list_lock);
2586+ if (is_register) {
2587+ head->users = 1;
2588+ list_add(&head->list, &ccs_io_buffer_list);
2589+ } else {
2590+ is_write = head->write_buf != NULL;
2591+ if (!--head->users) {
2592+ list_del(&head->list);
2593+ kfree(head->read_buf);
2594+ kfree(head->write_buf);
2595+ kfree(head);
2596+ }
2597+ }
2598+ spin_unlock(&ccs_io_buffer_list_lock);
2599+ if (is_write) {
2600+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 6)
2601+ struct task_struct *task = kthread_create(ccs_gc_thread, NULL,
2602+ "GC for CCS");
2603+ if (!IS_ERR(task))
2604+ wake_up_process(task);
2605+#else
2606+ kernel_thread(ccs_gc_thread, NULL, 0);
2607+#endif
2608+ }
2609+}
2610diff --git a/security/ccsecurity/internal.h b/security/ccsecurity/internal.h
2611new file mode 100644
2612index 0000000..3f703f2
2613--- /dev/null
2614+++ b/security/ccsecurity/internal.h
2615@@ -0,0 +1,2090 @@
2616+/*
2617+ * security/ccsecurity/internal.h
2618+ *
2619+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
2620+ *
2621+ * Version: 1.8.4 2015/05/05
2622+ */
2623+
2624+#ifndef _SECURITY_CCSECURITY_INTERNAL_H
2625+#define _SECURITY_CCSECURITY_INTERNAL_H
2626+
2627+#include <linux/version.h>
2628+#include <linux/types.h>
2629+#include <linux/kernel.h>
2630+#include <linux/string.h>
2631+#include <linux/mm.h>
2632+#include <linux/utime.h>
2633+#include <linux/file.h>
2634+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 38)
2635+#include <linux/smp_lock.h>
2636+#endif
2637+#include <linux/module.h>
2638+#include <linux/init.h>
2639+#include <linux/slab.h>
2640+#include <linux/highmem.h>
2641+#include <linux/poll.h>
2642+#include <linux/binfmts.h>
2643+#include <linux/delay.h>
2644+#include <linux/sched.h>
2645+#include <linux/dcache.h>
2646+#include <linux/mount.h>
2647+#include <linux/net.h>
2648+#include <linux/inet.h>
2649+#include <linux/in.h>
2650+#include <linux/in6.h>
2651+#include <linux/un.h>
2652+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
2653+#include <linux/fs.h>
2654+#endif
2655+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
2656+#include <linux/namei.h>
2657+#endif
2658+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
2659+#include <linux/fs_struct.h>
2660+#endif
2661+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
2662+#include <linux/namespace.h>
2663+#endif
2664+#include <linux/proc_fs.h>
2665+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(RHEL_MAJOR)
2666+#include <linux/hash.h>
2667+#endif
2668+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
2669+#include <linux/sysctl.h>
2670+#endif
2671+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 6)
2672+#include <linux/kthread.h>
2673+#endif
2674+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
2675+#include <linux/magic.h>
2676+#endif
2677+#include <stdarg.h>
2678+#include <asm/uaccess.h>
2679+#include <net/sock.h>
2680+#include <net/af_unix.h>
2681+#include <net/ip.h>
2682+#include <net/ipv6.h>
2683+#include <net/udp.h>
2684+
2685+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
2686+#define sk_family family
2687+#define sk_protocol protocol
2688+#define sk_type type
2689+#endif
2690+
2691+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
2692+
2693+/* Structure for holding "struct vfsmount *" and "struct dentry *". */
2694+struct path {
2695+ struct vfsmount *mnt;
2696+ struct dentry *dentry;
2697+};
2698+
2699+#endif
2700+
2701+#ifndef __printf
2702+#define __printf(a,b) __attribute__((format(printf,a,b)))
2703+#endif
2704+#ifndef __packed
2705+#define __packed __attribute__((__packed__))
2706+#endif
2707+#ifndef bool
2708+#define bool _Bool
2709+#endif
2710+#ifndef false
2711+#define false 0
2712+#endif
2713+#ifndef true
2714+#define true 1
2715+#endif
2716+
2717+#ifndef __user
2718+#define __user
2719+#endif
2720+
2721+#ifndef current_uid
2722+#define current_uid() (current->uid)
2723+#endif
2724+#ifndef current_gid
2725+#define current_gid() (current->gid)
2726+#endif
2727+#ifndef current_euid
2728+#define current_euid() (current->euid)
2729+#endif
2730+#ifndef current_egid
2731+#define current_egid() (current->egid)
2732+#endif
2733+#ifndef current_suid
2734+#define current_suid() (current->suid)
2735+#endif
2736+#ifndef current_sgid
2737+#define current_sgid() (current->sgid)
2738+#endif
2739+#ifndef current_fsuid
2740+#define current_fsuid() (current->fsuid)
2741+#endif
2742+#ifndef current_fsgid
2743+#define current_fsgid() (current->fsgid)
2744+#endif
2745+
2746+#ifndef DEFINE_SPINLOCK
2747+#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
2748+#endif
2749+
2750+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
2751+#define mutex semaphore
2752+#define mutex_init(mutex) init_MUTEX(mutex)
2753+#define mutex_unlock(mutex) up(mutex)
2754+#define mutex_lock(mutex) down(mutex)
2755+#define mutex_lock_interruptible(mutex) down_interruptible(mutex)
2756+#define mutex_trylock(mutex) (!down_trylock(mutex))
2757+#define DEFINE_MUTEX(mutexname) DECLARE_MUTEX(mutexname)
2758+#endif
2759+
2760+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
2761+#define MS_UNBINDABLE (1<<17) /* change to unbindable */
2762+#define MS_PRIVATE (1<<18) /* change to private */
2763+#define MS_SLAVE (1<<19) /* change to slave */
2764+#define MS_SHARED (1<<20) /* change to shared */
2765+#endif
2766+
2767+#ifndef container_of
2768+#define container_of(ptr, type, member) ({ \
2769+ const typeof(((type *)0)->member) *__mptr = (ptr); \
2770+ (type *)((char *)__mptr - offsetof(type, member)); })
2771+#endif
2772+
2773+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
2774+#define smp_read_barrier_depends smp_rmb
2775+#endif
2776+
2777+#ifndef ACCESS_ONCE
2778+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
2779+#endif
2780+
2781+#ifndef rcu_dereference
2782+#define rcu_dereference(p) ({ \
2783+ typeof(p) _________p1 = ACCESS_ONCE(p); \
2784+ smp_read_barrier_depends(); /* see RCU */ \
2785+ (_________p1); \
2786+ })
2787+#endif
2788+
2789+#ifndef rcu_assign_pointer
2790+#define rcu_assign_pointer(p, v) \
2791+ ({ \
2792+ if (!__builtin_constant_p(v) || \
2793+ ((v) != NULL)) \
2794+ smp_wmb(); /* see RCU */ \
2795+ (p) = (v); \
2796+ })
2797+#endif
2798+
2799+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
2800+#define f_vfsmnt f_path.mnt
2801+#endif
2802+
2803+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
2804+
2805+/**
2806+ * kzalloc() - Allocate memory. The memory is set to zero.
2807+ *
2808+ * @size: Size to allocate.
2809+ * @flags: GFP flags.
2810+ *
2811+ * Returns pointer to allocated memory on success, NULL otherwise.
2812+ *
2813+ * This is for compatibility with older kernels.
2814+ *
2815+ * Since several distributions backported kzalloc(), I define it as a macro
2816+ * rather than an inlined function in order to avoid multiple definition error.
2817+ */
2818+#define kzalloc(size, flags) ({ \
2819+ void *ret = kmalloc((size), (flags)); \
2820+ if (ret) \
2821+ memset(ret, 0, (size)); \
2822+ ret; })
2823+
2824+#endif
2825+
2826+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
2827+
2828+/**
2829+ * path_put - Drop reference on "struct path".
2830+ *
2831+ * @path: Pointer to "struct path".
2832+ *
2833+ * Returns nothing.
2834+ *
2835+ * This is for compatibility with older kernels.
2836+ */
2837+static inline void path_put(struct path *path)
2838+{
2839+ dput(path->dentry);
2840+ mntput(path->mnt);
2841+}
2842+
2843+#endif
2844+
2845+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
2846+
2847+/**
2848+ * __list_add_rcu - Insert a new entry between two known consecutive entries.
2849+ *
2850+ * @new: Pointer to "struct list_head".
2851+ * @prev: Pointer to "struct list_head".
2852+ * @next: Pointer to "struct list_head".
2853+ *
2854+ * Returns nothing.
2855+ *
2856+ * This is for compatibility with older kernels.
2857+ */
2858+static inline void __list_add_rcu(struct list_head *new,
2859+ struct list_head *prev,
2860+ struct list_head *next)
2861+{
2862+ new->next = next;
2863+ new->prev = prev;
2864+ rcu_assign_pointer(prev->next, new);
2865+ next->prev = new;
2866+}
2867+
2868+/**
2869+ * list_add_tail_rcu - Add a new entry to rcu-protected list.
2870+ *
2871+ * @new: Pointer to "struct list_head".
2872+ * @head: Pointer to "struct list_head".
2873+ *
2874+ * Returns nothing.
2875+ *
2876+ * This is for compatibility with older kernels.
2877+ */
2878+static inline void list_add_tail_rcu(struct list_head *new,
2879+ struct list_head *head)
2880+{
2881+ __list_add_rcu(new, head->prev, head);
2882+}
2883+
2884+/**
2885+ * list_add_rcu - Add a new entry to rcu-protected list.
2886+ *
2887+ * @new: Pointer to "struct list_head".
2888+ * @head: Pointer to "struct list_head".
2889+ *
2890+ * Returns nothing.
2891+ *
2892+ * This is for compatibility with older kernels.
2893+ */
2894+static inline void list_add_rcu(struct list_head *new, struct list_head *head)
2895+{
2896+ __list_add_rcu(new, head, head->next);
2897+}
2898+
2899+#endif
2900+
2901+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
2902+
2903+/**
2904+ * __list_del_entry - Deletes entry from list without re-initialization.
2905+ *
2906+ * @entry: Pointer to "struct list_head".
2907+ *
2908+ * Returns nothing.
2909+ *
2910+ * This is for compatibility with older kernels.
2911+ */
2912+static inline void __list_del_entry(struct list_head *entry)
2913+{
2914+ __list_del(entry->prev, entry->next);
2915+}
2916+
2917+#endif
2918+
2919+#ifndef list_for_each_entry_safe
2920+
2921+/**
2922+ * list_for_each_entry_safe - Iterate over list of given type safe against removal of list entry.
2923+ *
2924+ * @pos: The "type *" to use as a loop cursor.
2925+ * @n: Another "type *" to use as temporary storage.
2926+ * @head: Pointer to "struct list_head".
2927+ * @member: The name of the list_struct within the struct.
2928+ *
2929+ * This is for compatibility with older kernels.
2930+ */
2931+#define list_for_each_entry_safe(pos, n, head, member) \
2932+ for (pos = list_entry((head)->next, typeof(*pos), member), \
2933+ n = list_entry(pos->member.next, typeof(*pos), member); \
2934+ &pos->member != (head); \
2935+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
2936+
2937+#endif
2938+
2939+#ifndef srcu_dereference
2940+
2941+/**
2942+ * srcu_dereference - Fetch SRCU-protected pointer with checking.
2943+ *
2944+ * @p: The pointer to read, prior to dereferencing.
2945+ * @ss: Pointer to "struct srcu_struct".
2946+ *
2947+ * Returns @p.
2948+ *
2949+ * This is for compatibility with older kernels.
2950+ */
2951+#define srcu_dereference(p, ss) rcu_dereference(p)
2952+
2953+#endif
2954+
2955+#ifndef list_for_each_entry_srcu
2956+
2957+/**
2958+ * list_for_each_entry_srcu - Iterate over rcu list of given type.
2959+ *
2960+ * @pos: The type * to use as a loop cursor.
2961+ * @head: The head for your list.
2962+ * @member: The name of the list_struct within the struct.
2963+ * @ss: Pointer to "struct srcu_struct".
2964+ *
2965+ * As of 2.6.36, this macro is not provided because only TOMOYO wants it.
2966+ */
2967+#define list_for_each_entry_srcu(pos, head, member, ss) \
2968+ for (pos = list_entry(srcu_dereference((head)->next, ss), \
2969+ typeof(*pos), member); \
2970+ prefetch(pos->member.next), &pos->member != (head); \
2971+ pos = list_entry(srcu_dereference(pos->member.next, ss), \
2972+ typeof(*pos), member))
2973+
2974+#endif
2975+
2976+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 30) || (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 9))
2977+
2978+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 4, 21)
2979+#undef ssleep
2980+#endif
2981+
2982+#ifndef ssleep
2983+
2984+/**
2985+ * ssleep - Sleep for specified seconds.
2986+ *
2987+ * @secs: Seconds to sleep.
2988+ *
2989+ * Returns nothing.
2990+ *
2991+ * This is for compatibility with older kernels.
2992+ *
2993+ * Since several distributions backported ssleep(), I define it as a macro
2994+ * rather than an inlined function in order to avoid multiple definition error.
2995+ */
2996+#define ssleep(secs) { \
2997+ set_current_state(TASK_UNINTERRUPTIBLE); \
2998+ schedule_timeout((HZ * secs) + 1); \
2999+ }
3000+
3001+#endif
3002+
3003+#endif
3004+
3005+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
3006+
3007+/**
3008+ * from_kuid - Convert kuid_t to uid_t.
3009+ *
3010+ * @ns: Unused.
3011+ * @uid: kuid_t value.
3012+ *
3013+ * Returns uid seen from init's user namespace.
3014+ */
3015+#define from_kuid(ns, uid) (uid)
3016+
3017+/**
3018+ * from_kgid - Convert kgid_t to gid_t.
3019+ *
3020+ * @ns: Unused.
3021+ * @gid: kgid_t value.
3022+ *
3023+ * Returns gid seen from init's user namespace.
3024+ */
3025+#define from_kgid(ns, gid) (gid)
3026+
3027+/**
3028+ * uid_eq - Check whether the uids are equals or not.
3029+ *
3030+ * @left: Uid seen from current user namespace.
3031+ * @right: Uid seen from current user namespace.
3032+ *
3033+ * Returns true if uid is root in init's user namespace, false otherwise.
3034+ */
3035+#define uid_eq(left, right) ((left) == (right))
3036+#define GLOBAL_ROOT_UID 0
3037+
3038+#endif
3039+
3040+/*
3041+ * TOMOYO specific part start.
3042+ */
3043+
3044+#include <linux/ccsecurity.h>
3045+
3046+/* Enumeration definition for internal use. */
3047+
3048+/* Index numbers for Access Controls. */
3049+enum ccs_acl_entry_type_index {
3050+ CCS_TYPE_PATH_ACL,
3051+ CCS_TYPE_PATH2_ACL,
3052+ CCS_TYPE_PATH_NUMBER_ACL,
3053+ CCS_TYPE_MKDEV_ACL,
3054+ CCS_TYPE_MOUNT_ACL,
3055+#ifdef CONFIG_CCSECURITY_MISC
3056+ CCS_TYPE_ENV_ACL,
3057+#endif
3058+#ifdef CONFIG_CCSECURITY_CAPABILITY
3059+ CCS_TYPE_CAPABILITY_ACL,
3060+#endif
3061+#ifdef CONFIG_CCSECURITY_NETWORK
3062+ CCS_TYPE_INET_ACL,
3063+ CCS_TYPE_UNIX_ACL,
3064+#endif
3065+#ifdef CONFIG_CCSECURITY_IPC
3066+ CCS_TYPE_SIGNAL_ACL,
3067+#endif
3068+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3069+ CCS_TYPE_AUTO_EXECUTE_HANDLER,
3070+ CCS_TYPE_DENIED_EXECUTE_HANDLER,
3071+#endif
3072+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
3073+ CCS_TYPE_AUTO_TASK_ACL,
3074+ CCS_TYPE_MANUAL_TASK_ACL,
3075+#endif
3076+};
3077+
3078+/* Index numbers for "struct ccs_condition". */
3079+enum ccs_conditions_index {
3080+ CCS_TASK_UID, /* current_uid() */
3081+ CCS_TASK_EUID, /* current_euid() */
3082+ CCS_TASK_SUID, /* current_suid() */
3083+ CCS_TASK_FSUID, /* current_fsuid() */
3084+ CCS_TASK_GID, /* current_gid() */
3085+ CCS_TASK_EGID, /* current_egid() */
3086+ CCS_TASK_SGID, /* current_sgid() */
3087+ CCS_TASK_FSGID, /* current_fsgid() */
3088+ CCS_TASK_PID, /* sys_getpid() */
3089+ CCS_TASK_PPID, /* sys_getppid() */
3090+ CCS_EXEC_ARGC, /* "struct linux_binprm *"->argc */
3091+ CCS_EXEC_ENVC, /* "struct linux_binprm *"->envc */
3092+ CCS_TYPE_IS_SOCKET, /* S_IFSOCK */
3093+ CCS_TYPE_IS_SYMLINK, /* S_IFLNK */
3094+ CCS_TYPE_IS_FILE, /* S_IFREG */
3095+ CCS_TYPE_IS_BLOCK_DEV, /* S_IFBLK */
3096+ CCS_TYPE_IS_DIRECTORY, /* S_IFDIR */
3097+ CCS_TYPE_IS_CHAR_DEV, /* S_IFCHR */
3098+ CCS_TYPE_IS_FIFO, /* S_IFIFO */
3099+ CCS_MODE_SETUID, /* S_ISUID */
3100+ CCS_MODE_SETGID, /* S_ISGID */
3101+ CCS_MODE_STICKY, /* S_ISVTX */
3102+ CCS_MODE_OWNER_READ, /* S_IRUSR */
3103+ CCS_MODE_OWNER_WRITE, /* S_IWUSR */
3104+ CCS_MODE_OWNER_EXECUTE, /* S_IXUSR */
3105+ CCS_MODE_GROUP_READ, /* S_IRGRP */
3106+ CCS_MODE_GROUP_WRITE, /* S_IWGRP */
3107+ CCS_MODE_GROUP_EXECUTE, /* S_IXGRP */
3108+ CCS_MODE_OTHERS_READ, /* S_IROTH */
3109+ CCS_MODE_OTHERS_WRITE, /* S_IWOTH */
3110+ CCS_MODE_OTHERS_EXECUTE, /* S_IXOTH */
3111+ CCS_TASK_TYPE, /* ((u8) task->ccs_flags) &
3112+ CCS_TASK_IS_EXECUTE_HANDLER */
3113+ CCS_TASK_EXECUTE_HANDLER, /* CCS_TASK_IS_EXECUTE_HANDLER */
3114+ CCS_EXEC_REALPATH,
3115+ CCS_SYMLINK_TARGET,
3116+ CCS_PATH1_UID,
3117+ CCS_PATH1_GID,
3118+ CCS_PATH1_INO,
3119+ CCS_PATH1_MAJOR,
3120+ CCS_PATH1_MINOR,
3121+ CCS_PATH1_PERM,
3122+ CCS_PATH1_TYPE,
3123+ CCS_PATH1_DEV_MAJOR,
3124+ CCS_PATH1_DEV_MINOR,
3125+ CCS_PATH2_UID,
3126+ CCS_PATH2_GID,
3127+ CCS_PATH2_INO,
3128+ CCS_PATH2_MAJOR,
3129+ CCS_PATH2_MINOR,
3130+ CCS_PATH2_PERM,
3131+ CCS_PATH2_TYPE,
3132+ CCS_PATH2_DEV_MAJOR,
3133+ CCS_PATH2_DEV_MINOR,
3134+ CCS_PATH1_PARENT_UID,
3135+ CCS_PATH1_PARENT_GID,
3136+ CCS_PATH1_PARENT_INO,
3137+ CCS_PATH1_PARENT_PERM,
3138+ CCS_PATH2_PARENT_UID,
3139+ CCS_PATH2_PARENT_GID,
3140+ CCS_PATH2_PARENT_INO,
3141+ CCS_PATH2_PARENT_PERM,
3142+ CCS_MAX_CONDITION_KEYWORD,
3143+ CCS_NUMBER_UNION,
3144+ CCS_NAME_UNION,
3145+ CCS_ARGV_ENTRY,
3146+ CCS_ENVP_ENTRY,
3147+};
3148+
3149+/* Index numbers for domain's attributes. */
3150+enum ccs_domain_info_flags_index {
3151+ /* Quota warnning flag. */
3152+ CCS_DIF_QUOTA_WARNED,
3153+ /*
3154+ * This domain was unable to create a new domain at
3155+ * ccs_find_next_domain() because the name of the domain to be created
3156+ * was too long or it could not allocate memory.
3157+ * More than one process continued execve() without domain transition.
3158+ */
3159+ CCS_DIF_TRANSITION_FAILED,
3160+ CCS_MAX_DOMAIN_INFO_FLAGS
3161+};
3162+
3163+/* Index numbers for audit type. */
3164+enum ccs_grant_log {
3165+ /* Follow profile's configuration. */
3166+ CCS_GRANTLOG_AUTO,
3167+ /* Do not generate grant log. */
3168+ CCS_GRANTLOG_NO,
3169+ /* Generate grant_log. */
3170+ CCS_GRANTLOG_YES,
3171+};
3172+
3173+/* Index numbers for group entries. */
3174+enum ccs_group_id {
3175+ CCS_PATH_GROUP,
3176+ CCS_NUMBER_GROUP,
3177+#ifdef CONFIG_CCSECURITY_NETWORK
3178+ CCS_ADDRESS_GROUP,
3179+#endif
3180+ CCS_MAX_GROUP
3181+};
3182+
3183+/* Index numbers for category of functionality. */
3184+enum ccs_mac_category_index {
3185+ CCS_MAC_CATEGORY_FILE,
3186+#ifdef CONFIG_CCSECURITY_NETWORK
3187+ CCS_MAC_CATEGORY_NETWORK,
3188+#endif
3189+#ifdef CONFIG_CCSECURITY_MISC
3190+ CCS_MAC_CATEGORY_MISC,
3191+#endif
3192+#ifdef CONFIG_CCSECURITY_IPC
3193+ CCS_MAC_CATEGORY_IPC,
3194+#endif
3195+#ifdef CONFIG_CCSECURITY_CAPABILITY
3196+ CCS_MAC_CATEGORY_CAPABILITY,
3197+#endif
3198+ CCS_MAX_MAC_CATEGORY_INDEX
3199+};
3200+
3201+/* Index numbers for functionality. */
3202+enum ccs_mac_index {
3203+ CCS_MAC_FILE_EXECUTE,
3204+ CCS_MAC_FILE_OPEN,
3205+ CCS_MAC_FILE_CREATE,
3206+ CCS_MAC_FILE_UNLINK,
3207+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
3208+ CCS_MAC_FILE_GETATTR,
3209+#endif
3210+ CCS_MAC_FILE_MKDIR,
3211+ CCS_MAC_FILE_RMDIR,
3212+ CCS_MAC_FILE_MKFIFO,
3213+ CCS_MAC_FILE_MKSOCK,
3214+ CCS_MAC_FILE_TRUNCATE,
3215+ CCS_MAC_FILE_SYMLINK,
3216+ CCS_MAC_FILE_MKBLOCK,
3217+ CCS_MAC_FILE_MKCHAR,
3218+ CCS_MAC_FILE_LINK,
3219+ CCS_MAC_FILE_RENAME,
3220+ CCS_MAC_FILE_CHMOD,
3221+ CCS_MAC_FILE_CHOWN,
3222+ CCS_MAC_FILE_CHGRP,
3223+ CCS_MAC_FILE_IOCTL,
3224+ CCS_MAC_FILE_CHROOT,
3225+ CCS_MAC_FILE_MOUNT,
3226+ CCS_MAC_FILE_UMOUNT,
3227+ CCS_MAC_FILE_PIVOT_ROOT,
3228+#ifdef CONFIG_CCSECURITY_NETWORK
3229+ CCS_MAC_NETWORK_INET_STREAM_BIND,
3230+ CCS_MAC_NETWORK_INET_STREAM_LISTEN,
3231+ CCS_MAC_NETWORK_INET_STREAM_CONNECT,
3232+ CCS_MAC_NETWORK_INET_STREAM_ACCEPT,
3233+ CCS_MAC_NETWORK_INET_DGRAM_BIND,
3234+ CCS_MAC_NETWORK_INET_DGRAM_SEND,
3235+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
3236+ CCS_MAC_NETWORK_INET_DGRAM_RECV,
3237+#endif
3238+ CCS_MAC_NETWORK_INET_RAW_BIND,
3239+ CCS_MAC_NETWORK_INET_RAW_SEND,
3240+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
3241+ CCS_MAC_NETWORK_INET_RAW_RECV,
3242+#endif
3243+ CCS_MAC_NETWORK_UNIX_STREAM_BIND,
3244+ CCS_MAC_NETWORK_UNIX_STREAM_LISTEN,
3245+ CCS_MAC_NETWORK_UNIX_STREAM_CONNECT,
3246+ CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT,
3247+ CCS_MAC_NETWORK_UNIX_DGRAM_BIND,
3248+ CCS_MAC_NETWORK_UNIX_DGRAM_SEND,
3249+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
3250+ CCS_MAC_NETWORK_UNIX_DGRAM_RECV,
3251+#endif
3252+ CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND,
3253+ CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
3254+ CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
3255+ CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT,
3256+#endif
3257+#ifdef CONFIG_CCSECURITY_MISC
3258+ CCS_MAC_ENVIRON,
3259+#endif
3260+#ifdef CONFIG_CCSECURITY_IPC
3261+ CCS_MAC_SIGNAL,
3262+#endif
3263+#ifdef CONFIG_CCSECURITY_CAPABILITY
3264+ CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET,
3265+ CCS_MAC_CAPABILITY_USE_PACKET_SOCKET,
3266+ CCS_MAC_CAPABILITY_SYS_REBOOT,
3267+ CCS_MAC_CAPABILITY_SYS_VHANGUP,
3268+ CCS_MAC_CAPABILITY_SYS_SETTIME,
3269+ CCS_MAC_CAPABILITY_SYS_NICE,
3270+ CCS_MAC_CAPABILITY_SYS_SETHOSTNAME,
3271+ CCS_MAC_CAPABILITY_USE_KERNEL_MODULE,
3272+ CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD,
3273+ CCS_MAC_CAPABILITY_SYS_PTRACE,
3274+#endif
3275+ CCS_MAX_MAC_INDEX
3276+};
3277+
3278+/* Index numbers for /proc/ccs/stat interface. */
3279+enum ccs_memory_stat_type {
3280+ CCS_MEMORY_POLICY,
3281+ CCS_MEMORY_AUDIT,
3282+ CCS_MEMORY_QUERY,
3283+ CCS_MAX_MEMORY_STAT
3284+};
3285+
3286+/* Index numbers for access controls with one pathname and three numbers. */
3287+enum ccs_mkdev_acl_index {
3288+ CCS_TYPE_MKBLOCK,
3289+ CCS_TYPE_MKCHAR,
3290+ CCS_MAX_MKDEV_OPERATION
3291+};
3292+
3293+/* Index numbers for operation mode. */
3294+enum ccs_mode_value {
3295+ CCS_CONFIG_DISABLED,
3296+ CCS_CONFIG_LEARNING,
3297+ CCS_CONFIG_PERMISSIVE,
3298+ CCS_CONFIG_ENFORCING,
3299+ CCS_CONFIG_MAX_MODE,
3300+ CCS_CONFIG_WANT_REJECT_LOG = 64,
3301+ CCS_CONFIG_WANT_GRANT_LOG = 128,
3302+ CCS_CONFIG_USE_DEFAULT = 255,
3303+};
3304+
3305+/* Index numbers for socket operations. */
3306+enum ccs_network_acl_index {
3307+ CCS_NETWORK_BIND, /* bind() operation. */
3308+ CCS_NETWORK_LISTEN, /* listen() operation. */
3309+ CCS_NETWORK_CONNECT, /* connect() operation. */
3310+ CCS_NETWORK_ACCEPT, /* accept() operation. */
3311+ CCS_NETWORK_SEND, /* send() operation. */
3312+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
3313+ CCS_NETWORK_RECV, /* recv() operation. */
3314+#endif
3315+ CCS_MAX_NETWORK_OPERATION
3316+};
3317+
3318+/* Index numbers for access controls with two pathnames. */
3319+enum ccs_path2_acl_index {
3320+ CCS_TYPE_LINK,
3321+ CCS_TYPE_RENAME,
3322+ CCS_TYPE_PIVOT_ROOT,
3323+ CCS_MAX_PATH2_OPERATION
3324+};
3325+
3326+/* Index numbers for access controls with one pathname. */
3327+enum ccs_path_acl_index {
3328+ CCS_TYPE_EXECUTE,
3329+ CCS_TYPE_READ,
3330+ CCS_TYPE_WRITE,
3331+ CCS_TYPE_APPEND,
3332+ CCS_TYPE_UNLINK,
3333+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
3334+ CCS_TYPE_GETATTR,
3335+#endif
3336+ CCS_TYPE_RMDIR,
3337+ CCS_TYPE_TRUNCATE,
3338+ CCS_TYPE_SYMLINK,
3339+ CCS_TYPE_CHROOT,
3340+ CCS_TYPE_UMOUNT,
3341+ CCS_MAX_PATH_OPERATION
3342+};
3343+
3344+/* Index numbers for access controls with one pathname and one number. */
3345+enum ccs_path_number_acl_index {
3346+ CCS_TYPE_CREATE,
3347+ CCS_TYPE_MKDIR,
3348+ CCS_TYPE_MKFIFO,
3349+ CCS_TYPE_MKSOCK,
3350+ CCS_TYPE_IOCTL,
3351+ CCS_TYPE_CHMOD,
3352+ CCS_TYPE_CHOWN,
3353+ CCS_TYPE_CHGRP,
3354+ CCS_MAX_PATH_NUMBER_OPERATION
3355+};
3356+
3357+/* Index numbers for stat(). */
3358+enum ccs_path_stat_index {
3359+ /* Do not change this order. */
3360+ CCS_PATH1,
3361+ CCS_PATH1_PARENT,
3362+ CCS_PATH2,
3363+ CCS_PATH2_PARENT,
3364+ CCS_MAX_PATH_STAT
3365+};
3366+
3367+/* Index numbers for entry type. */
3368+enum ccs_policy_id {
3369+#ifdef CONFIG_CCSECURITY_PORTRESERVE
3370+ CCS_ID_RESERVEDPORT,
3371+#endif
3372+ CCS_ID_GROUP,
3373+#ifdef CONFIG_CCSECURITY_NETWORK
3374+ CCS_ID_ADDRESS_GROUP,
3375+#endif
3376+ CCS_ID_PATH_GROUP,
3377+ CCS_ID_NUMBER_GROUP,
3378+ CCS_ID_AGGREGATOR,
3379+ CCS_ID_TRANSITION_CONTROL,
3380+ CCS_ID_MANAGER,
3381+ CCS_ID_CONDITION,
3382+ CCS_ID_NAME,
3383+ CCS_ID_ACL,
3384+ CCS_ID_DOMAIN,
3385+ CCS_MAX_POLICY
3386+};
3387+
3388+/* Index numbers for /proc/ccs/stat interface. */
3389+enum ccs_policy_stat_type {
3390+ /* Do not change this order. */
3391+ CCS_STAT_POLICY_UPDATES,
3392+ CCS_STAT_POLICY_LEARNING, /* == CCS_CONFIG_LEARNING */
3393+ CCS_STAT_POLICY_PERMISSIVE, /* == CCS_CONFIG_PERMISSIVE */
3394+ CCS_STAT_POLICY_ENFORCING, /* == CCS_CONFIG_ENFORCING */
3395+ CCS_MAX_POLICY_STAT
3396+};
3397+
3398+/* Index numbers for profile's PREFERENCE values. */
3399+enum ccs_pref_index {
3400+ CCS_PREF_MAX_AUDIT_LOG,
3401+ CCS_PREF_MAX_LEARNING_ENTRY,
3402+ CCS_PREF_ENFORCING_PENALTY,
3403+ CCS_MAX_PREF
3404+};
3405+
3406+/* Index numbers for /proc/ccs/ interfaces. */
3407+enum ccs_proc_interface_index {
3408+ CCS_DOMAIN_POLICY,
3409+ CCS_EXCEPTION_POLICY,
3410+ CCS_PROCESS_STATUS,
3411+ CCS_STAT,
3412+ CCS_AUDIT,
3413+ CCS_VERSION,
3414+ CCS_PROFILE,
3415+ CCS_QUERY,
3416+ CCS_MANAGER,
3417+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
3418+ CCS_EXECUTE_HANDLER,
3419+#endif
3420+};
3421+
3422+/* Index numbers for special mount operations. */
3423+enum ccs_special_mount {
3424+ CCS_MOUNT_BIND, /* mount --bind /source /dest */
3425+ CCS_MOUNT_MOVE, /* mount --move /old /new */
3426+ CCS_MOUNT_REMOUNT, /* mount -o remount /dir */
3427+ CCS_MOUNT_MAKE_UNBINDABLE, /* mount --make-unbindable /dir */
3428+ CCS_MOUNT_MAKE_PRIVATE, /* mount --make-private /dir */
3429+ CCS_MOUNT_MAKE_SLAVE, /* mount --make-slave /dir */
3430+ CCS_MOUNT_MAKE_SHARED, /* mount --make-shared /dir */
3431+ CCS_MAX_SPECIAL_MOUNT
3432+};
3433+
3434+/* Index numbers for domain transition control keywords. */
3435+enum ccs_transition_type {
3436+ /* Do not change this order, */
3437+ CCS_TRANSITION_CONTROL_NO_RESET,
3438+ CCS_TRANSITION_CONTROL_RESET,
3439+ CCS_TRANSITION_CONTROL_NO_INITIALIZE,
3440+ CCS_TRANSITION_CONTROL_INITIALIZE,
3441+ CCS_TRANSITION_CONTROL_NO_KEEP,
3442+ CCS_TRANSITION_CONTROL_KEEP,
3443+ CCS_MAX_TRANSITION_TYPE
3444+};
3445+
3446+/* Index numbers for type of numeric values. */
3447+enum ccs_value_type {
3448+ CCS_VALUE_TYPE_INVALID,
3449+ CCS_VALUE_TYPE_DECIMAL,
3450+ CCS_VALUE_TYPE_OCTAL,
3451+ CCS_VALUE_TYPE_HEXADECIMAL,
3452+};
3453+
3454+/* Constants definition for internal use. */
3455+
3456+/*
3457+ * TOMOYO uses this hash only when appending a string into the string table.
3458+ * Frequency of appending strings is very low. So we don't need large (e.g.
3459+ * 64k) hash size. 256 will be sufficient.
3460+ */
3461+#define CCS_HASH_BITS 8
3462+#define CCS_MAX_HASH (1u << CCS_HASH_BITS)
3463+
3464+/*
3465+ * TOMOYO checks only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET.
3466+ * Therefore, we don't need SOCK_MAX.
3467+ */
3468+#define CCS_SOCK_MAX 6
3469+
3470+/* Size of temporary buffer for execve() operation. */
3471+#define CCS_EXEC_TMPSIZE 4096
3472+
3473+/* Garbage collector is trying to kfree() this element. */
3474+#define CCS_GC_IN_PROGRESS -1
3475+
3476+/* Profile number is an integer between 0 and 255. */
3477+#define CCS_MAX_PROFILES 256
3478+
3479+/* Group number is an integer between 0 and 255. */
3480+#define CCS_MAX_ACL_GROUPS 256
3481+
3482+/* Current thread is doing open(O_RDONLY | O_TRUNC) ? */
3483+#define CCS_OPEN_FOR_READ_TRUNCATE 1
3484+/* Current thread is doing open(3) ? */
3485+#define CCS_OPEN_FOR_IOCTL_ONLY 2
3486+/* Current thread is doing do_execve() ? */
3487+#define CCS_TASK_IS_IN_EXECVE 4
3488+/* Current thread is running as an execute handler program? */
3489+#define CCS_TASK_IS_EXECUTE_HANDLER 8
3490+/* Current thread is allowed to modify policy via /proc/ccs/ interface? */
3491+#define CCS_TASK_IS_MANAGER 16
3492+
3493+/*
3494+ * Retry this request. Returned by ccs_supervisor() if policy violation has
3495+ * occurred in enforcing mode and the userspace daemon decided to retry.
3496+ *
3497+ * We must choose a positive value in order to distinguish "granted" (which is
3498+ * 0) and "rejected" (which is a negative value) and "retry".
3499+ */
3500+#define CCS_RETRY_REQUEST 1
3501+
3502+/* Ignore gfp flags which are not supported. */
3503+#ifndef __GFP_HIGHIO
3504+#define __GFP_HIGHIO 0
3505+#endif
3506+#ifndef __GFP_NOWARN
3507+#define __GFP_NOWARN 0
3508+#endif
3509+#ifndef __GFP_NORETRY
3510+#define __GFP_NORETRY 0
3511+#endif
3512+#ifndef __GFP_NOMEMALLOC
3513+#define __GFP_NOMEMALLOC 0
3514+#endif
3515+
3516+/* The gfp flags used by TOMOYO. */
3517+#define CCS_GFP_FLAGS (__GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_NOWARN | \
3518+ __GFP_NORETRY | __GFP_NOMEMALLOC)
3519+
3520+/* Size of read buffer for /proc/ccs/ interface. */
3521+#define CCS_MAX_IO_READ_QUEUE 64
3522+
3523+/* Structure definition for internal use. */
3524+
3525+/* Common header for holding ACL entries. */
3526+struct ccs_acl_head {
3527+ struct list_head list;
3528+ s8 is_deleted; /* true or false or CCS_GC_IN_PROGRESS */
3529+} __packed;
3530+
3531+/* Common header for shared entries. */
3532+struct ccs_shared_acl_head {
3533+ struct list_head list;
3534+ atomic_t users;
3535+} __packed;
3536+
3537+/* Common header for individual entries. */
3538+struct ccs_acl_info {
3539+ struct list_head list;
3540+ struct ccs_condition *cond; /* Maybe NULL. */
3541+ s8 is_deleted; /* true or false or CCS_GC_IN_PROGRESS */
3542+ u8 type; /* One of values in "enum ccs_acl_entry_type_index". */
3543+ u16 perm;
3544+} __packed;
3545+
3546+/* Structure for holding a word. */
3547+struct ccs_name_union {
3548+ /* Either @filename or @group is NULL. */
3549+ const struct ccs_path_info *filename;
3550+ struct ccs_group *group;
3551+};
3552+
3553+/* Structure for holding a number. */
3554+struct ccs_number_union {
3555+ unsigned long values[2];
3556+ struct ccs_group *group; /* Maybe NULL. */
3557+ /* One of values in "enum ccs_value_type". */
3558+ u8 value_type[2];
3559+};
3560+
3561+/* Structure for holding an IP address. */
3562+struct ccs_ipaddr_union {
3563+ struct in6_addr ip[2]; /* Big endian. */
3564+ struct ccs_group *group; /* Pointer to address group. */
3565+ bool is_ipv6; /* Valid only if @group == NULL. */
3566+};
3567+
3568+/* Structure for "path_group"/"number_group"/"address_group" directive. */
3569+struct ccs_group {
3570+ struct ccs_shared_acl_head head;
3571+ /* Name of group (without leading '@'). */
3572+ const struct ccs_path_info *group_name;
3573+ /*
3574+ * List of "struct ccs_path_group" or "struct ccs_number_group" or
3575+ * "struct ccs_address_group".
3576+ */
3577+ struct list_head member_list;
3578+};
3579+
3580+/* Structure for "path_group" directive. */
3581+struct ccs_path_group {
3582+ struct ccs_acl_head head;
3583+ const struct ccs_path_info *member_name;
3584+};
3585+
3586+/* Structure for "number_group" directive. */
3587+struct ccs_number_group {
3588+ struct ccs_acl_head head;
3589+ struct ccs_number_union number;
3590+};
3591+
3592+/* Structure for "address_group" directive. */
3593+struct ccs_address_group {
3594+ struct ccs_acl_head head;
3595+ /* Structure for holding an IP address. */
3596+ struct ccs_ipaddr_union address;
3597+};
3598+
3599+/* Subset of "struct stat". Used by conditional ACL and audit logs. */
3600+struct ccs_mini_stat {
3601+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
3602+ kuid_t uid;
3603+ kgid_t gid;
3604+#else
3605+ uid_t uid;
3606+ gid_t gid;
3607+#endif
3608+ ino_t ino;
3609+ umode_t mode;
3610+ dev_t dev;
3611+ dev_t rdev;
3612+};
3613+
3614+/* Structure for dumping argv[] and envp[] of "struct linux_binprm". */
3615+struct ccs_page_dump {
3616+ struct page *page; /* Previously dumped page. */
3617+ char *data; /* Contents of "page". Size is PAGE_SIZE. */
3618+};
3619+
3620+/* Structure for attribute checks in addition to pathname checks. */
3621+struct ccs_obj_info {
3622+ /* True if ccs_get_attributes() was already called, false otherwise. */
3623+ bool validate_done;
3624+ /* True if @stat[] is valid. */
3625+ bool stat_valid[CCS_MAX_PATH_STAT];
3626+ /* First pathname. Initialized with { NULL, NULL } if no path. */
3627+ struct path path1;
3628+ /* Second pathname. Initialized with { NULL, NULL } if no path. */
3629+ struct path path2;
3630+ /*
3631+ * Information on @path1, @path1's parent directory, @path2, @path2's
3632+ * parent directory.
3633+ */
3634+ struct ccs_mini_stat stat[CCS_MAX_PATH_STAT];
3635+ /*
3636+ * Content of symbolic link to be created. NULL for operations other
3637+ * than symlink().
3638+ */
3639+ struct ccs_path_info *symlink_target;
3640+};
3641+
3642+/* Structure for entries which follows "struct ccs_condition". */
3643+struct ccs_condition_element {
3644+ /*
3645+ * Left hand operand. A "struct ccs_argv" for CCS_ARGV_ENTRY, a
3646+ * "struct ccs_envp" for CCS_ENVP_ENTRY is attached to the tail
3647+ * of the array of this struct.
3648+ */
3649+ u8 left;
3650+ /*
3651+ * Right hand operand. A "struct ccs_number_union" for
3652+ * CCS_NUMBER_UNION, a "struct ccs_name_union" for CCS_NAME_UNION is
3653+ * attached to the tail of the array of this struct.
3654+ */
3655+ u8 right;
3656+ /* Equation operator. True if equals or overlaps, false otherwise. */
3657+ bool equals;
3658+};
3659+
3660+/* Structure for optional arguments. */
3661+struct ccs_condition {
3662+ struct ccs_shared_acl_head head;
3663+ u32 size; /* Memory size allocated for this entry. */
3664+ u16 condc; /* Number of conditions in this struct. */
3665+ u16 numbers_count; /* Number of "struct ccs_number_union values". */
3666+ u16 names_count; /* Number of "struct ccs_name_union names". */
3667+ u16 argc; /* Number of "struct ccs_argv". */
3668+ u16 envc; /* Number of "struct ccs_envp". */
3669+ u8 grant_log; /* One of values in "enum ccs_grant_log". */
3670+ bool exec_transit; /* True if transit is for "file execute". */
3671+ const struct ccs_path_info *transit; /* Maybe NULL. */
3672+ /*
3673+ * struct ccs_condition_element condition[condc];
3674+ * struct ccs_number_union values[numbers_count];
3675+ * struct ccs_name_union names[names_count];
3676+ * struct ccs_argv argv[argc];
3677+ * struct ccs_envp envp[envc];
3678+ */
3679+};
3680+
3681+struct ccs_execve;
3682+struct ccs_policy_namespace;
3683+
3684+/* Structure for request info. */
3685+struct ccs_request_info {
3686+ /*
3687+ * For holding parameters specific to operations which deal files.
3688+ * NULL if not dealing files.
3689+ */
3690+ struct ccs_obj_info *obj;
3691+ /*
3692+ * For holding parameters specific to execve() request.
3693+ * NULL if not dealing do_execve().
3694+ */
3695+ struct ccs_execve *ee;
3696+ /*
3697+ * For holding parameters.
3698+ * Pointers in this union are not NULL except path->matched_path.
3699+ */
3700+ union {
3701+ struct {
3702+ const struct ccs_path_info *filename;
3703+ /*
3704+ * For using wildcards at ccs_find_next_domain().
3705+ *
3706+ * The matched_acl cannot be used because it may refer
3707+ * a "struct ccs_path_acl" with ->is_group == true.
3708+ * We want to use exact "struct ccs_path_info" rather
3709+ * than "struct ccs_path_acl".
3710+ */
3711+ const struct ccs_path_info *matched_path;
3712+ /* One of values in "enum ccs_path_acl_index". */
3713+ u8 operation;
3714+ } path;
3715+ struct {
3716+ const struct ccs_path_info *filename1;
3717+ const struct ccs_path_info *filename2;
3718+ /* One of values in "enum ccs_path2_acl_index". */
3719+ u8 operation;
3720+ } path2;
3721+ struct {
3722+ const struct ccs_path_info *filename;
3723+ unsigned int mode;
3724+ unsigned int major;
3725+ unsigned int minor;
3726+ /* One of values in "enum ccs_mkdev_acl_index". */
3727+ u8 operation;
3728+ } mkdev;
3729+ struct {
3730+ const struct ccs_path_info *filename;
3731+ unsigned long number;
3732+ /*
3733+ * One of values in "enum ccs_path_number_acl_index".
3734+ */
3735+ u8 operation;
3736+ } path_number;
3737+#ifdef CONFIG_CCSECURITY_NETWORK
3738+ struct {
3739+ const u32 *address; /* Big endian. */
3740+ u16 port; /* Host endian. */
3741+ /* One of values smaller than CCS_SOCK_MAX. */
3742+ u8 protocol;
3743+ /* One of values in "enum ccs_network_acl_index". */
3744+ u8 operation;
3745+ bool is_ipv6;
3746+ } inet_network;
3747+ struct {
3748+ const struct ccs_path_info *address;
3749+ /* One of values smaller than CCS_SOCK_MAX. */
3750+ u8 protocol;
3751+ /* One of values in "enum ccs_network_acl_index". */
3752+ u8 operation;
3753+ } unix_network;
3754+#endif
3755+#ifdef CONFIG_CCSECURITY_MISC
3756+ struct {
3757+ const struct ccs_path_info *name;
3758+ } environ;
3759+#endif
3760+#ifdef CONFIG_CCSECURITY_CAPABILITY
3761+ struct {
3762+ /* One of values in "enum ccs_capability_acl_index". */
3763+ u8 operation;
3764+ } capability;
3765+#endif
3766+#ifdef CONFIG_CCSECURITY_IPC
3767+ struct {
3768+ const char *dest_pattern;
3769+ int sig;
3770+ } signal;
3771+#endif
3772+ struct {
3773+ const struct ccs_path_info *type;
3774+ const struct ccs_path_info *dir;
3775+ const struct ccs_path_info *dev;
3776+ unsigned long flags;
3777+ int need_dev;
3778+ } mount;
3779+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
3780+ struct {
3781+ const struct ccs_path_info *domainname;
3782+ } task;
3783+#endif
3784+ } param;
3785+ /*
3786+ * For updating current->ccs_domain_info at ccs_update_task_domain().
3787+ * Initialized to NULL at ccs_init_request_info().
3788+ * Matching "struct ccs_acl_info" is copied if access request was
3789+ * granted. Re-initialized to NULL at ccs_update_task_domain().
3790+ */
3791+ struct ccs_acl_info *matched_acl;
3792+ u8 param_type; /* One of values in "enum ccs_acl_entry_type_index". */
3793+ bool granted; /* True if granted, false otherwise. */
3794+ /* True if current thread should not be carried sleep penalty. */
3795+ bool dont_sleep_on_enforce_error;
3796+ /*
3797+ * For counting number of retries made for this request.
3798+ * This counter is incremented whenever ccs_supervisor() returned
3799+ * CCS_RETRY_REQUEST.
3800+ */
3801+ u8 retry;
3802+ /*
3803+ * For holding profile number used for this request.
3804+ * One of values between 0 and CCS_MAX_PROFILES - 1.
3805+ */
3806+ u8 profile;
3807+ /*
3808+ * For holding operation mode used for this request.
3809+ * One of CCS_CONFIG_DISABLED, CCS_CONFIG_LEARNING,
3810+ * CCS_CONFIG_PERMISSIVE, CCS_CONFIG_ENFORCING.
3811+ */
3812+ u8 mode;
3813+ /*
3814+ * For holding operation index used for this request.
3815+ * Used by ccs_init_request_info() / ccs_get_mode() /
3816+ * ccs_write_log(). One of values in "enum ccs_mac_index".
3817+ */
3818+ u8 type;
3819+};
3820+
3821+/* Structure for holding a token. */
3822+struct ccs_path_info {
3823+ const char *name;
3824+ u32 hash; /* = full_name_hash(name, strlen(name)) */
3825+ u16 total_len; /* = strlen(name) */
3826+ u16 const_len; /* = ccs_const_part_length(name) */
3827+ bool is_dir; /* = ccs_strendswith(name, "/") */
3828+ bool is_patterned; /* = const_len < total_len */
3829+};
3830+
3831+/* Structure for execve() operation. */
3832+struct ccs_execve {
3833+ struct ccs_request_info r;
3834+ struct ccs_obj_info obj;
3835+ struct linux_binprm *bprm;
3836+ struct ccs_domain_info *previous_domain;
3837+ const struct ccs_path_info *transition;
3838+ /* For execute_handler */
3839+ const struct ccs_path_info *handler;
3840+ char *handler_path; /* = kstrdup(handler->name, CCS_GFP_FLAGS) */
3841+ /* For dumping argv[] and envp[]. */
3842+ struct ccs_page_dump dump;
3843+ /* For temporary use. */
3844+ char *tmp; /* Size is CCS_EXEC_TMPSIZE bytes */
3845+};
3846+
3847+/* Structure for domain information. */
3848+struct ccs_domain_info {
3849+ struct list_head list;
3850+ struct list_head acl_info_list;
3851+ /* Name of this domain. Never NULL. */
3852+ const struct ccs_path_info *domainname;
3853+ /* Namespace for this domain. Never NULL. */
3854+ struct ccs_policy_namespace *ns;
3855+ /* Group numbers to use. */
3856+ unsigned long group[CCS_MAX_ACL_GROUPS / BITS_PER_LONG];
3857+ u8 profile; /* Profile number to use. */
3858+ bool is_deleted; /* Delete flag. */
3859+ bool flags[CCS_MAX_DOMAIN_INFO_FLAGS];
3860+};
3861+
3862+/*
3863+ * Structure for "reset_domain"/"no_reset_domain"/"initialize_domain"/
3864+ * "no_initialize_domain"/"keep_domain"/"no_keep_domain" keyword.
3865+ */
3866+struct ccs_transition_control {
3867+ struct ccs_acl_head head;
3868+ u8 type; /* One of values in "enum ccs_transition_type" */
3869+ bool is_last_name; /* True if the domainname is ccs_last_word(). */
3870+ const struct ccs_path_info *domainname; /* Maybe NULL */
3871+ const struct ccs_path_info *program; /* Maybe NULL */
3872+};
3873+
3874+/* Structure for "aggregator" keyword. */
3875+struct ccs_aggregator {
3876+ struct ccs_acl_head head;
3877+ const struct ccs_path_info *original_name;
3878+ const struct ccs_path_info *aggregated_name;
3879+};
3880+
3881+/* Structure for "deny_autobind" keyword. */
3882+struct ccs_reserved {
3883+ struct ccs_acl_head head;
3884+ struct ccs_number_union port;
3885+};
3886+
3887+/* Structure for policy manager. */
3888+struct ccs_manager {
3889+ struct ccs_acl_head head;
3890+ /* A path to program or a domainname. */
3891+ const struct ccs_path_info *manager;
3892+};
3893+
3894+/* Structure for argv[]. */
3895+struct ccs_argv {
3896+ unsigned long index;
3897+ const struct ccs_path_info *value;
3898+ bool is_not;
3899+};
3900+
3901+/* Structure for envp[]. */
3902+struct ccs_envp {
3903+ const struct ccs_path_info *name;
3904+ const struct ccs_path_info *value;
3905+ bool is_not;
3906+};
3907+
3908+/*
3909+ * Structure for "task auto_execute_handler" and "task denied_execute_handler"
3910+ * directive.
3911+ *
3912+ * If "task auto_execute_handler" directive exists and the current process is
3913+ * not an execute handler, all execve() requests are replaced by execve()
3914+ * requests of a program specified by "task auto_execute_handler" directive.
3915+ * If the current process is an execute handler, "task auto_execute_handler"
3916+ * and "task denied_execute_handler" directives are ignored.
3917+ * The program specified by "task execute_handler" validates execve()
3918+ * parameters and executes the original execve() requests if appropriate.
3919+ *
3920+ * "task denied_execute_handler" directive is used only when execve() request
3921+ * was rejected in enforcing mode (i.e. CONFIG::file::execute={ mode=enforcing
3922+ * }). The program specified by "task denied_execute_handler" does whatever it
3923+ * wants to do (e.g. silently terminate, change firewall settings, redirect the
3924+ * user to honey pot etc.).
3925+ */
3926+struct ccs_handler_acl {
3927+ struct ccs_acl_info head; /* type = CCS_TYPE_*_EXECUTE_HANDLER */
3928+ const struct ccs_path_info *handler; /* Pointer to single pathname. */
3929+};
3930+
3931+/*
3932+ * Structure for "task auto_domain_transition" and
3933+ * "task manual_domain_transition" directive.
3934+ */
3935+struct ccs_task_acl {
3936+ struct ccs_acl_info head; /* type = CCS_TYPE_*_TASK_ACL */
3937+ /* Pointer to domainname. */
3938+ const struct ccs_path_info *domainname;
3939+};
3940+
3941+/*
3942+ * Structure for "file execute", "file read", "file write", "file append",
3943+ * "file unlink", "file getattr", "file rmdir", "file truncate",
3944+ * "file symlink", "file chroot" and "file unmount" directive.
3945+ */
3946+struct ccs_path_acl {
3947+ struct ccs_acl_info head; /* type = CCS_TYPE_PATH_ACL */
3948+ struct ccs_name_union name;
3949+};
3950+
3951+/*
3952+ * Structure for "file rename", "file link" and "file pivot_root" directive.
3953+ */
3954+struct ccs_path2_acl {
3955+ struct ccs_acl_info head; /* type = CCS_TYPE_PATH2_ACL */
3956+ struct ccs_name_union name1;
3957+ struct ccs_name_union name2;
3958+};
3959+
3960+/*
3961+ * Structure for "file create", "file mkdir", "file mkfifo", "file mksock",
3962+ * "file ioctl", "file chmod", "file chown" and "file chgrp" directive.
3963+ */
3964+struct ccs_path_number_acl {
3965+ struct ccs_acl_info head; /* type = CCS_TYPE_PATH_NUMBER_ACL */
3966+ struct ccs_name_union name;
3967+ struct ccs_number_union number;
3968+};
3969+
3970+/* Structure for "file mkblock" and "file mkchar" directive. */
3971+struct ccs_mkdev_acl {
3972+ struct ccs_acl_info head; /* type = CCS_TYPE_MKDEV_ACL */
3973+ struct ccs_name_union name;
3974+ struct ccs_number_union mode;
3975+ struct ccs_number_union major;
3976+ struct ccs_number_union minor;
3977+};
3978+
3979+/* Structure for "file mount" directive. */
3980+struct ccs_mount_acl {
3981+ struct ccs_acl_info head; /* type = CCS_TYPE_MOUNT_ACL */
3982+ struct ccs_name_union dev_name;
3983+ struct ccs_name_union dir_name;
3984+ struct ccs_name_union fs_type;
3985+ struct ccs_number_union flags;
3986+};
3987+
3988+/* Structure for "misc env" directive in domain policy. */
3989+struct ccs_env_acl {
3990+ struct ccs_acl_info head; /* type = CCS_TYPE_ENV_ACL */
3991+ const struct ccs_path_info *env; /* environment variable */
3992+};
3993+
3994+/* Structure for "capability" directive. */
3995+struct ccs_capability_acl {
3996+ struct ccs_acl_info head; /* type = CCS_TYPE_CAPABILITY_ACL */
3997+ u8 operation; /* One of values in "enum ccs_capability_acl_index". */
3998+};
3999+
4000+/* Structure for "ipc signal" directive. */
4001+struct ccs_signal_acl {
4002+ struct ccs_acl_info head; /* type = CCS_TYPE_SIGNAL_ACL */
4003+ struct ccs_number_union sig;
4004+ /* Pointer to destination pattern. */
4005+ const struct ccs_path_info *domainname;
4006+};
4007+
4008+/* Structure for "network inet" directive. */
4009+struct ccs_inet_acl {
4010+ struct ccs_acl_info head; /* type = CCS_TYPE_INET_ACL */
4011+ u8 protocol;
4012+ struct ccs_ipaddr_union address;
4013+ struct ccs_number_union port;
4014+};
4015+
4016+/* Structure for "network unix" directive. */
4017+struct ccs_unix_acl {
4018+ struct ccs_acl_info head; /* type = CCS_TYPE_UNIX_ACL */
4019+ u8 protocol;
4020+ struct ccs_name_union name;
4021+};
4022+
4023+/* Structure for holding string data. */
4024+struct ccs_name {
4025+ struct ccs_shared_acl_head head;
4026+ int size; /* Memory size allocated for this entry. */
4027+ struct ccs_path_info entry;
4028+};
4029+
4030+/* Structure for holding a line from /proc/ccs/ interface. */
4031+struct ccs_acl_param {
4032+ char *data; /* Unprocessed data. */
4033+ struct list_head *list; /* List to add or remove. */
4034+ struct ccs_policy_namespace *ns; /* Namespace to use. */
4035+ bool is_delete; /* True if it is a delete request. */
4036+ union ccs_acl_union {
4037+ struct ccs_acl_info acl_info;
4038+ struct ccs_handler_acl handler_acl;
4039+ struct ccs_task_acl task_acl;
4040+ struct ccs_path_acl path_acl;
4041+ struct ccs_path2_acl path2_acl;
4042+ struct ccs_path_number_acl path_number_acl;
4043+ struct ccs_mkdev_acl mkdev_acl;
4044+ struct ccs_mount_acl mount_acl;
4045+ struct ccs_env_acl env_acl;
4046+ struct ccs_capability_acl capability_acl;
4047+ struct ccs_signal_acl signal_acl;
4048+ struct ccs_inet_acl inet_acl;
4049+ struct ccs_unix_acl unix_acl;
4050+ /**/
4051+ struct ccs_acl_head acl_head;
4052+ struct ccs_transition_control transition_control;
4053+ struct ccs_aggregator aggregator;
4054+ struct ccs_reserved reserved;
4055+ struct ccs_manager manager;
4056+ struct ccs_path_group path_group;
4057+ struct ccs_number_group number_group;
4058+ struct ccs_address_group address_group;
4059+ } e;
4060+};
4061+
4062+/* Structure for reading/writing policy via /proc/ccs/ interfaces. */
4063+struct ccs_io_buffer {
4064+ /* Exclusive lock for this structure. */
4065+ struct mutex io_sem;
4066+ char __user *read_user_buf;
4067+ size_t read_user_buf_avail;
4068+ struct {
4069+ struct list_head *ns;
4070+ struct list_head *domain;
4071+ struct list_head *group;
4072+ struct list_head *acl;
4073+ size_t avail;
4074+ unsigned int step;
4075+ unsigned int query_index;
4076+ u16 index;
4077+ u16 cond_index;
4078+ u8 acl_group_index;
4079+ u8 cond_step;
4080+ u8 bit;
4081+ u8 w_pos;
4082+ bool eof;
4083+ bool print_this_domain_only;
4084+ bool print_transition_related_only;
4085+ bool print_cond_part;
4086+ const char *w[CCS_MAX_IO_READ_QUEUE];
4087+ } r;
4088+ struct {
4089+ struct ccs_policy_namespace *ns;
4090+ struct ccs_domain_info *domain;
4091+ size_t avail;
4092+ bool is_delete;
4093+ } w;
4094+ /* Buffer for reading. */
4095+ char *read_buf;
4096+ /* Size of read buffer. */
4097+ size_t readbuf_size;
4098+ /* Buffer for writing. */
4099+ char *write_buf;
4100+ /* Size of write buffer. */
4101+ size_t writebuf_size;
4102+ /* Type of interface. */
4103+ enum ccs_proc_interface_index type;
4104+ /* Users counter protected by ccs_io_buffer_list_lock. */
4105+ u8 users;
4106+ /* List for telling GC not to kfree() elements. */
4107+ struct list_head list;
4108+};
4109+
4110+/* Structure for /proc/ccs/profile interface. */
4111+struct ccs_profile {
4112+ const struct ccs_path_info *comment;
4113+ u8 default_config;
4114+ u8 config[CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX];
4115+ unsigned int pref[CCS_MAX_PREF];
4116+};
4117+
4118+/* Structure for representing YYYY/MM/DD hh/mm/ss. */
4119+struct ccs_time {
4120+ u16 year;
4121+ u8 month;
4122+ u8 day;
4123+ u8 hour;
4124+ u8 min;
4125+ u8 sec;
4126+};
4127+
4128+/* Structure for policy namespace. */
4129+struct ccs_policy_namespace {
4130+ /* Profile table. Memory is allocated as needed. */
4131+ struct ccs_profile *profile_ptr[CCS_MAX_PROFILES];
4132+ /* List of "struct ccs_group". */
4133+ struct list_head group_list[CCS_MAX_GROUP];
4134+ /* List of policy. */
4135+ struct list_head policy_list[CCS_MAX_POLICY];
4136+ /* The global ACL referred by "use_group" keyword. */
4137+ struct list_head acl_group[CCS_MAX_ACL_GROUPS];
4138+ /* List for connecting to ccs_namespace_list list. */
4139+ struct list_head namespace_list;
4140+ /* Profile version. Currently only 20150505 is supported. */
4141+ unsigned int profile_version;
4142+ /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */
4143+ const char *name;
4144+};
4145+
4146+/* Prototype definition for "struct ccsecurity_operations". */
4147+
4148+void __init ccs_permission_init(void);
4149+void __init ccs_mm_init(void);
4150+
4151+/* Prototype definition for internal use. */
4152+
4153+bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
4154+ struct ccs_page_dump *dump);
4155+bool ccs_memory_ok(const void *ptr, const unsigned int size);
4156+char *ccs_encode(const char *str);
4157+char *ccs_encode2(const char *str, int str_len);
4158+char *ccs_realpath(const struct path *path);
4159+const char *ccs_get_exe(void);
4160+const struct ccs_path_info *ccs_get_name(const char *name);
4161+int ccs_audit_log(struct ccs_request_info *r);
4162+int ccs_check_acl(struct ccs_request_info *r);
4163+int ccs_init_request_info(struct ccs_request_info *r, const u8 index);
4164+struct ccs_domain_info *ccs_assign_domain(const char *domainname,
4165+ const bool transit);
4166+u8 ccs_get_config(const u8 profile, const u8 index);
4167+void *ccs_commit_ok(void *data, const unsigned int size);
4168+void ccs_del_acl(struct list_head *element);
4169+void ccs_del_condition(struct list_head *element);
4170+void ccs_fill_path_info(struct ccs_path_info *ptr);
4171+void ccs_get_attributes(struct ccs_obj_info *obj);
4172+void ccs_notify_gc(struct ccs_io_buffer *head, const bool is_register);
4173+void ccs_transition_failed(const char *domainname);
4174+void ccs_warn_oom(const char *function);
4175+void ccs_write_log(struct ccs_request_info *r, const char *fmt, ...)
4176+ __printf(2, 3);
4177+
4178+/* Variable definition for internal use. */
4179+
4180+extern bool ccs_policy_loaded;
4181+extern const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS];
4182+extern const u8 ccs_c2mac[CCS_MAX_CAPABILITY_INDEX];
4183+extern const u8 ccs_pn2mac[CCS_MAX_PATH_NUMBER_OPERATION];
4184+extern const u8 ccs_pnnn2mac[CCS_MAX_MKDEV_OPERATION];
4185+extern const u8 ccs_pp2mac[CCS_MAX_PATH2_OPERATION];
4186+extern struct ccs_domain_info ccs_kernel_domain;
4187+extern struct list_head ccs_condition_list;
4188+extern struct list_head ccs_domain_list;
4189+extern struct list_head ccs_name_list[CCS_MAX_HASH];
4190+extern struct list_head ccs_namespace_list;
4191+extern struct mutex ccs_policy_lock;
4192+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
4193+extern struct srcu_struct ccs_ss;
4194+#endif
4195+extern unsigned int ccs_memory_quota[CCS_MAX_MEMORY_STAT];
4196+extern unsigned int ccs_memory_used[CCS_MAX_MEMORY_STAT];
4197+
4198+/* Inlined functions for internal use. */
4199+
4200+/**
4201+ * ccs_pathcmp - strcmp() for "struct ccs_path_info" structure.
4202+ *
4203+ * @a: Pointer to "struct ccs_path_info".
4204+ * @b: Pointer to "struct ccs_path_info".
4205+ *
4206+ * Returns true if @a != @b, false otherwise.
4207+ */
4208+static inline bool ccs_pathcmp(const struct ccs_path_info *a,
4209+ const struct ccs_path_info *b)
4210+{
4211+ return a->hash != b->hash || strcmp(a->name, b->name);
4212+}
4213+
4214+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
4215+
4216+/**
4217+ * ccs_read_lock - Take lock for protecting policy.
4218+ *
4219+ * Returns index number for ccs_read_unlock().
4220+ */
4221+static inline int ccs_read_lock(void)
4222+{
4223+ return srcu_read_lock(&ccs_ss);
4224+}
4225+
4226+/**
4227+ * ccs_read_unlock - Release lock for protecting policy.
4228+ *
4229+ * @idx: Index number returned by ccs_read_lock().
4230+ *
4231+ * Returns nothing.
4232+ */
4233+static inline void ccs_read_unlock(const int idx)
4234+{
4235+ srcu_read_unlock(&ccs_ss, idx);
4236+}
4237+
4238+#else
4239+
4240+int ccs_lock(void);
4241+void ccs_unlock(const int idx);
4242+
4243+/**
4244+ * ccs_read_lock - Take lock for protecting policy.
4245+ *
4246+ * Returns index number for ccs_read_unlock().
4247+ */
4248+static inline int ccs_read_lock(void)
4249+{
4250+ return ccs_lock();
4251+}
4252+
4253+/**
4254+ * ccs_read_unlock - Release lock for protecting policy.
4255+ *
4256+ * @idx: Index number returned by ccs_read_lock().
4257+ *
4258+ * Returns nothing.
4259+ */
4260+static inline void ccs_read_unlock(const int idx)
4261+{
4262+ ccs_unlock(idx);
4263+}
4264+
4265+#endif
4266+
4267+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
4268+
4269+/**
4270+ * ccs_tasklist_lock - Take lock for reading list of "struct task_struct".
4271+ *
4272+ * Returns nothing.
4273+ */
4274+static inline void ccs_tasklist_lock(void)
4275+{
4276+ rcu_read_lock();
4277+}
4278+
4279+/**
4280+ * ccs_tasklist_unlock - Release lock for reading list of "struct task_struct".
4281+ *
4282+ * Returns nothing.
4283+ */
4284+static inline void ccs_tasklist_unlock(void)
4285+{
4286+ rcu_read_unlock();
4287+}
4288+
4289+#else
4290+
4291+/**
4292+ * ccs_tasklist_lock - Take lock for reading list of "struct task_struct".
4293+ *
4294+ * Returns nothing.
4295+ */
4296+static inline void ccs_tasklist_lock(void)
4297+{
4298+ read_lock(&tasklist_lock);
4299+}
4300+
4301+/**
4302+ * ccs_tasklist_unlock - Release lock for reading list of "struct task_struct".
4303+ *
4304+ * Returns nothing.
4305+ */
4306+static inline void ccs_tasklist_unlock(void)
4307+{
4308+ read_unlock(&tasklist_lock);
4309+}
4310+
4311+#endif
4312+
4313+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
4314+
4315+/**
4316+ * ccs_sys_getppid - Copy of getppid().
4317+ *
4318+ * Returns parent process's PID.
4319+ *
4320+ * Alpha does not have getppid() defined. To be able to build this module on
4321+ * Alpha, I have to copy getppid() from kernel/timer.c.
4322+ */
4323+static inline pid_t ccs_sys_getppid(void)
4324+{
4325+ pid_t pid;
4326+ rcu_read_lock();
4327+ pid = task_tgid_vnr(rcu_dereference(current->real_parent));
4328+ rcu_read_unlock();
4329+ return pid;
4330+}
4331+
4332+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
4333+
4334+/**
4335+ * ccs_sys_getppid - Copy of getppid().
4336+ *
4337+ * Returns parent process's PID.
4338+ *
4339+ * This function was rewritten to use RCU in 2.6.16.34. However, distributors
4340+ * which use earlier kernels (e.g. 2.6.8/2.6.9) did not backport the bugfix.
4341+ * Therefore, I'm using code for 2.6.16.34 for earlier kernels.
4342+ */
4343+static inline pid_t ccs_sys_getppid(void)
4344+{
4345+ pid_t pid;
4346+ rcu_read_lock();
4347+#if (defined(RHEL_MAJOR) && RHEL_MAJOR == 5) || (defined(AX_MAJOR) && AX_MAJOR == 3)
4348+ pid = rcu_dereference(current->parent)->tgid;
4349+#elif defined(CONFIG_UTRACE)
4350+ /*
4351+ * RHEL 5.0 kernel does not have RHEL_MAJOR/RHEL_MINOR defined.
4352+ * Assume RHEL 5.0 if CONFIG_UTRACE is defined.
4353+ */
4354+ pid = rcu_dereference(current->parent)->tgid;
4355+#else
4356+ pid = rcu_dereference(current->real_parent)->tgid;
4357+#endif
4358+ rcu_read_unlock();
4359+ return pid;
4360+}
4361+
4362+#else
4363+
4364+/**
4365+ * ccs_sys_getppid - Copy of getppid().
4366+ *
4367+ * Returns parent process's PID.
4368+ *
4369+ * I can't use code for 2.6.16.34 for 2.4 kernels because 2.4 kernels does not
4370+ * have RCU. Therefore, I'm using pessimistic lock (i.e. tasklist_lock
4371+ * spinlock).
4372+ */
4373+static inline pid_t ccs_sys_getppid(void)
4374+{
4375+ pid_t pid;
4376+ read_lock(&tasklist_lock);
4377+#ifdef TASK_DEAD
4378+ pid = current->group_leader->real_parent->tgid;
4379+#else
4380+ pid = current->p_opptr->pid;
4381+#endif
4382+ read_unlock(&tasklist_lock);
4383+ return pid;
4384+}
4385+
4386+#endif
4387+
4388+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
4389+
4390+/**
4391+ * ccs_sys_getpid - Copy of getpid().
4392+ *
4393+ * Returns current thread's PID.
4394+ *
4395+ * Alpha does not have getpid() defined. To be able to build this module on
4396+ * Alpha, I have to copy getpid() from kernel/timer.c.
4397+ */
4398+static inline pid_t ccs_sys_getpid(void)
4399+{
4400+ return task_tgid_vnr(current);
4401+}
4402+
4403+#else
4404+
4405+/**
4406+ * ccs_sys_getpid - Copy of getpid().
4407+ *
4408+ * Returns current thread's PID.
4409+ */
4410+static inline pid_t ccs_sys_getpid(void)
4411+{
4412+ return current->tgid;
4413+}
4414+
4415+#endif
4416+
4417+/**
4418+ * ccs_get_mode - Get mode for specified functionality.
4419+ *
4420+ * @profile: Profile number.
4421+ * @index: Functionality number.
4422+ *
4423+ * Returns mode.
4424+ */
4425+static inline u8 ccs_get_mode(const u8 profile, const u8 index)
4426+{
4427+ return ccs_get_config(profile, index) & (CCS_CONFIG_MAX_MODE - 1);
4428+}
4429+
4430+#if defined(CONFIG_SLOB)
4431+
4432+/**
4433+ * ccs_round2 - Round up to power of 2 for calculating memory usage.
4434+ *
4435+ * @size: Size to be rounded up.
4436+ *
4437+ * Returns @size.
4438+ *
4439+ * Since SLOB does not round up, this function simply returns @size.
4440+ */
4441+static inline int ccs_round2(size_t size)
4442+{
4443+ return size;
4444+}
4445+
4446+#else
4447+
4448+/**
4449+ * ccs_round2 - Round up to power of 2 for calculating memory usage.
4450+ *
4451+ * @size: Size to be rounded up.
4452+ *
4453+ * Returns rounded size.
4454+ *
4455+ * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of
4456+ * (e.g.) 128 bytes.
4457+ */
4458+static inline int ccs_round2(size_t size)
4459+{
4460+#if PAGE_SIZE == 4096
4461+ size_t bsize = 32;
4462+#else
4463+ size_t bsize = 64;
4464+#endif
4465+ if (!size)
4466+ return 0;
4467+ while (size > bsize)
4468+ bsize <<= 1;
4469+ return bsize;
4470+}
4471+
4472+#endif
4473+
4474+/**
4475+ * ccs_put_condition - Drop reference on "struct ccs_condition".
4476+ *
4477+ * @cond: Pointer to "struct ccs_condition". Maybe NULL.
4478+ *
4479+ * Returns nothing.
4480+ */
4481+static inline void ccs_put_condition(struct ccs_condition *cond)
4482+{
4483+ if (cond)
4484+ atomic_dec(&cond->head.users);
4485+}
4486+
4487+/**
4488+ * ccs_put_group - Drop reference on "struct ccs_group".
4489+ *
4490+ * @group: Pointer to "struct ccs_group". Maybe NULL.
4491+ *
4492+ * Returns nothing.
4493+ */
4494+static inline void ccs_put_group(struct ccs_group *group)
4495+{
4496+ if (group)
4497+ atomic_dec(&group->head.users);
4498+}
4499+
4500+/**
4501+ * ccs_put_name - Drop reference on "struct ccs_name".
4502+ *
4503+ * @name: Pointer to "struct ccs_path_info". Maybe NULL.
4504+ *
4505+ * Returns nothing.
4506+ */
4507+static inline void ccs_put_name(const struct ccs_path_info *name)
4508+{
4509+ if (name)
4510+ atomic_dec(&container_of(name, struct ccs_name, entry)->
4511+ head.users);
4512+}
4513+
4514+/* For importing variables and functions. */
4515+extern const struct ccsecurity_exports ccsecurity_exports;
4516+
4517+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
4518+
4519+/*
4520+ * Structure for holding "struct ccs_domain_info *" and "struct ccs_execve *"
4521+ * and "u32 ccs_flags" for each "struct task_struct".
4522+ *
4523+ * "struct ccs_domain_info *" and "u32 ccs_flags" for each "struct task_struct"
4524+ * are maintained outside that "struct task_struct". Therefore, ccs_security
4525+ * != task_struct . This keeps KABI for distributor's prebuilt kernels but
4526+ * entails slow access.
4527+ *
4528+ * Memory for this structure is allocated when current thread tries to access
4529+ * it. Therefore, if memory allocation failed, current thread will be killed by
4530+ * SIGKILL. Note that if current->pid == 1, sending SIGKILL won't work.
4531+ */
4532+struct ccs_security {
4533+ struct list_head list;
4534+ const struct task_struct *task;
4535+ struct ccs_domain_info *ccs_domain_info;
4536+ u32 ccs_flags;
4537+ struct rcu_head rcu;
4538+};
4539+
4540+#define CCS_TASK_SECURITY_HASH_BITS 12
4541+#define CCS_MAX_TASK_SECURITY_HASH (1u << CCS_TASK_SECURITY_HASH_BITS)
4542+extern struct list_head ccs_task_security_list[CCS_MAX_TASK_SECURITY_HASH];
4543+
4544+struct ccs_security *ccs_find_task_security(const struct task_struct *task);
4545+
4546+/**
4547+ * ccs_current_security - Get "struct ccs_security" for current thread.
4548+ *
4549+ * Returns pointer to "struct ccs_security" for current thread.
4550+ */
4551+static inline struct ccs_security *ccs_current_security(void)
4552+{
4553+ return ccs_find_task_security(current);
4554+}
4555+
4556+/**
4557+ * ccs_task_domain - Get "struct ccs_domain_info" for specified thread.
4558+ *
4559+ * @task: Pointer to "struct task_struct".
4560+ *
4561+ * Returns pointer to "struct ccs_security" for specified thread.
4562+ */
4563+static inline struct ccs_domain_info *ccs_task_domain(struct task_struct *task)
4564+{
4565+ struct ccs_domain_info *domain;
4566+ rcu_read_lock();
4567+ domain = ccs_find_task_security(task)->ccs_domain_info;
4568+ rcu_read_unlock();
4569+ return domain;
4570+}
4571+
4572+/**
4573+ * ccs_current_domain - Get "struct ccs_domain_info" for current thread.
4574+ *
4575+ * Returns pointer to "struct ccs_domain_info" for current thread.
4576+ */
4577+static inline struct ccs_domain_info *ccs_current_domain(void)
4578+{
4579+ return ccs_find_task_security(current)->ccs_domain_info;
4580+}
4581+
4582+/**
4583+ * ccs_task_flags - Get flags for specified thread.
4584+ *
4585+ * @task: Pointer to "struct task_struct".
4586+ *
4587+ * Returns flags for specified thread.
4588+ */
4589+static inline u32 ccs_task_flags(struct task_struct *task)
4590+{
4591+ u32 ccs_flags;
4592+ rcu_read_lock();
4593+ ccs_flags = ccs_find_task_security(task)->ccs_flags;
4594+ rcu_read_unlock();
4595+ return ccs_flags;
4596+}
4597+
4598+/**
4599+ * ccs_current_flags - Get flags for current thread.
4600+ *
4601+ * Returns flags for current thread.
4602+ */
4603+static inline u32 ccs_current_flags(void)
4604+{
4605+ return ccs_find_task_security(current)->ccs_flags;
4606+}
4607+
4608+#else
4609+
4610+/*
4611+ * "struct ccs_domain_info *" and "u32 ccs_flags" for each "struct task_struct"
4612+ * are maintained inside that "struct task_struct". Therefore, ccs_security ==
4613+ * task_struct . This allows fast access but breaks KABI checks for
4614+ * distributor's prebuilt kernels due to changes in "struct task_struct".
4615+ */
4616+#define ccs_security task_struct
4617+
4618+/**
4619+ * ccs_find_task_security - Find "struct ccs_security" for given task.
4620+ *
4621+ * @task: Pointer to "struct task_struct".
4622+ *
4623+ * Returns pointer to "struct ccs_security".
4624+ */
4625+static inline struct ccs_security *ccs_find_task_security(struct task_struct *
4626+ task)
4627+{
4628+ return task;
4629+}
4630+
4631+/**
4632+ * ccs_current_security - Get "struct ccs_security" for current thread.
4633+ *
4634+ * Returns pointer to "struct ccs_security" for current thread.
4635+ */
4636+static inline struct ccs_security *ccs_current_security(void)
4637+{
4638+ return ccs_find_task_security(current);
4639+}
4640+
4641+/**
4642+ * ccs_task_domain - Get "struct ccs_domain_info" for specified thread.
4643+ *
4644+ * @task: Pointer to "struct task_struct".
4645+ *
4646+ * Returns pointer to "struct ccs_security" for specified thread.
4647+ */
4648+static inline struct ccs_domain_info *ccs_task_domain(struct task_struct *task)
4649+{
4650+ struct ccs_domain_info *domain = task->ccs_domain_info;
4651+ return domain ? domain : &ccs_kernel_domain;
4652+}
4653+
4654+/**
4655+ * ccs_current_domain - Get "struct ccs_domain_info" for current thread.
4656+ *
4657+ * Returns pointer to "struct ccs_domain_info" for current thread.
4658+ *
4659+ * If current thread does not belong to a domain (which is true for initial
4660+ * init_task in order to hide ccs_kernel_domain from this module),
4661+ * current thread enters into ccs_kernel_domain.
4662+ */
4663+static inline struct ccs_domain_info *ccs_current_domain(void)
4664+{
4665+ struct task_struct *task = current;
4666+ if (!task->ccs_domain_info)
4667+ task->ccs_domain_info = &ccs_kernel_domain;
4668+ return task->ccs_domain_info;
4669+}
4670+
4671+/**
4672+ * ccs_task_flags - Get flags for specified thread.
4673+ *
4674+ * @task: Pointer to "struct task_struct".
4675+ *
4676+ * Returns flags for specified thread.
4677+ */
4678+static inline u32 ccs_task_flags(struct task_struct *task)
4679+{
4680+ return ccs_find_task_security(task)->ccs_flags;
4681+}
4682+
4683+/**
4684+ * ccs_current_flags - Get flags for current thread.
4685+ *
4686+ * Returns flags for current thread.
4687+ */
4688+static inline u32 ccs_current_flags(void)
4689+{
4690+ return ccs_find_task_security(current)->ccs_flags;
4691+}
4692+
4693+#endif
4694+
4695+/**
4696+ * ccs_current_namespace - Get "struct ccs_policy_namespace" for current thread.
4697+ *
4698+ * Returns pointer to "struct ccs_policy_namespace" for current thread.
4699+ */
4700+static inline struct ccs_policy_namespace *ccs_current_namespace(void)
4701+{
4702+ return ccs_current_domain()->ns;
4703+}
4704+
4705+#endif
4706diff --git a/security/ccsecurity/load_policy.c b/security/ccsecurity/load_policy.c
4707new file mode 100644
4708index 0000000..fc4ae30
4709--- /dev/null
4710+++ b/security/ccsecurity/load_policy.c
4711@@ -0,0 +1,352 @@
4712+/*
4713+ * security/ccsecurity/load_policy.c
4714+ *
4715+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
4716+ *
4717+ * Version: 1.8.4 2015/05/05
4718+ */
4719+
4720+#include <linux/version.h>
4721+#include <linux/module.h>
4722+#include <linux/init.h>
4723+#include <linux/binfmts.h>
4724+#include <linux/sched.h>
4725+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
4726+#include <linux/kmod.h>
4727+/*
4728+ * Regarding 2.4 kernels, we need to define __KERNEL_SYSCALLS__ in order to use
4729+ * waitpid() because call_usermodehelper() does not support UMH_WAIT_PROC.
4730+ */
4731+#define __KERNEL_SYSCALLS__
4732+#include <linux/unistd.h>
4733+#else
4734+#include <linux/fs.h>
4735+#include <linux/namei.h>
4736+#endif
4737+#ifndef LOOKUP_POSITIVE
4738+#define LOOKUP_POSITIVE 0
4739+#endif
4740+
4741+/*
4742+ * TOMOYO specific part start.
4743+ */
4744+
4745+#include <linux/ccsecurity.h>
4746+
4747+/**
4748+ * ccs_setup - Set enable/disable upon boot.
4749+ *
4750+ * @str: "off" to disable, "on" to enable.
4751+ *
4752+ * Returns 0.
4753+ */
4754+static int __init ccs_setup(char *str)
4755+{
4756+ if (!strcmp(str, "off"))
4757+ ccsecurity_ops.disabled = 1;
4758+ else if (!strcmp(str, "on"))
4759+ ccsecurity_ops.disabled = 0;
4760+ return 0;
4761+}
4762+
4763+__setup("ccsecurity=", ccs_setup);
4764+
4765+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
4766+#include "lsm2ccsecurity.c"
4767+#endif
4768+
4769+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
4770+
4771+/* Path to the policy loader. (default = CONFIG_CCSECURITY_POLICY_LOADER) */
4772+static const char *ccs_loader;
4773+
4774+/**
4775+ * ccs_loader_setup - Set policy loader.
4776+ *
4777+ * @str: Program to use as a policy loader (e.g. /sbin/ccs-init ).
4778+ *
4779+ * Returns 0.
4780+ */
4781+static int __init ccs_loader_setup(char *str)
4782+{
4783+ ccs_loader = str;
4784+ return 0;
4785+}
4786+
4787+__setup("CCS_loader=", ccs_loader_setup);
4788+
4789+/**
4790+ * ccs_policy_loader_exists - Check whether /sbin/ccs-init exists.
4791+ *
4792+ * Returns true if /sbin/ccs-init exists, false otherwise.
4793+ */
4794+static _Bool ccs_policy_loader_exists(void)
4795+{
4796+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
4797+ struct path path;
4798+ if (!ccs_loader)
4799+ ccs_loader = CONFIG_CCSECURITY_POLICY_LOADER;
4800+ if (kern_path(ccs_loader, LOOKUP_FOLLOW | LOOKUP_POSITIVE,
4801+ &path) == 0) {
4802+ path_put(&path);
4803+ return 1;
4804+ }
4805+#else
4806+ struct nameidata nd;
4807+ if (!ccs_loader)
4808+ ccs_loader = CONFIG_CCSECURITY_POLICY_LOADER;
4809+ if (path_lookup(ccs_loader, LOOKUP_FOLLOW | LOOKUP_POSITIVE,
4810+ &nd) == 0) {
4811+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
4812+ path_put(&nd.path);
4813+#else
4814+ path_release(&nd);
4815+#endif
4816+ return 1;
4817+ }
4818+#endif
4819+ printk(KERN_INFO "Not activating Mandatory Access Control "
4820+ "as %s does not exist.\n", ccs_loader);
4821+ return 0;
4822+}
4823+
4824+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
4825+
4826+/**
4827+ * ccs_run_loader - Start /sbin/ccs-init.
4828+ *
4829+ * @unused: Not used.
4830+ *
4831+ * Returns PID of /sbin/ccs-init on success, negative value otherwise.
4832+ */
4833+static int ccs_run_loader(void *unused)
4834+{
4835+ char *argv[2];
4836+ char *envp[3];
4837+ printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
4838+ ccs_loader);
4839+ argv[0] = (char *) ccs_loader;
4840+ argv[1] = NULL;
4841+ envp[0] = "HOME=/";
4842+ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
4843+ envp[2] = NULL;
4844+ return exec_usermodehelper(argv[0], argv, envp);
4845+}
4846+
4847+#endif
4848+
4849+/* Path to the trigger. (default = CONFIG_CCSECURITY_ACTIVATION_TRIGGER) */
4850+static const char *ccs_trigger;
4851+
4852+/**
4853+ * ccs_trigger_setup - Set trigger for activation.
4854+ *
4855+ * @str: Program to use as an activation trigger (e.g. /sbin/init ).
4856+ *
4857+ * Returns 0.
4858+ */
4859+static int __init ccs_trigger_setup(char *str)
4860+{
4861+ ccs_trigger = str;
4862+ return 0;
4863+}
4864+
4865+__setup("CCS_trigger=", ccs_trigger_setup);
4866+
4867+/**
4868+ * ccs_load_policy - Run external policy loader to load policy.
4869+ *
4870+ * @filename: The program about to start.
4871+ *
4872+ * Returns nothing.
4873+ *
4874+ * This function checks whether @filename is /sbin/init, and if so
4875+ * invoke /sbin/ccs-init and wait for the termination of /sbin/ccs-init
4876+ * and then continues invocation of /sbin/init.
4877+ * /sbin/ccs-init reads policy files in /etc/ccs/ directory and
4878+ * writes to /proc/ccs/ interfaces.
4879+ */
4880+static void ccs_load_policy(const char *filename)
4881+{
4882+ static _Bool done;
4883+ if (ccsecurity_ops.disabled || done)
4884+ return;
4885+ if (!ccs_trigger)
4886+ ccs_trigger = CONFIG_CCSECURITY_ACTIVATION_TRIGGER;
4887+ if (strcmp(filename, ccs_trigger))
4888+ return;
4889+ if (!ccs_policy_loader_exists())
4890+ return;
4891+ done = 1;
4892+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
4893+ {
4894+ char *argv[2];
4895+ char *envp[3];
4896+ printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
4897+ ccs_loader);
4898+ argv[0] = (char *) ccs_loader;
4899+ argv[1] = NULL;
4900+ envp[0] = "HOME=/";
4901+ envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
4902+ envp[2] = NULL;
4903+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) || defined(UMH_WAIT_PROC)
4904+ call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
4905+#else
4906+ call_usermodehelper(argv[0], argv, envp, 1);
4907+#endif
4908+ }
4909+#elif defined(TASK_DEAD)
4910+ {
4911+ /* Copied from kernel/kmod.c */
4912+ struct task_struct *task = current;
4913+ pid_t pid = kernel_thread(ccs_run_loader, NULL, 0);
4914+ sigset_t tmpsig;
4915+ spin_lock_irq(&task->sighand->siglock);
4916+ tmpsig = task->blocked;
4917+ siginitsetinv(&task->blocked,
4918+ sigmask(SIGKILL) | sigmask(SIGSTOP));
4919+ recalc_sigpending();
4920+ spin_unlock_irq(&task->sighand->siglock);
4921+ if (pid >= 0)
4922+ waitpid(pid, NULL, __WCLONE);
4923+ spin_lock_irq(&task->sighand->siglock);
4924+ task->blocked = tmpsig;
4925+ recalc_sigpending();
4926+ spin_unlock_irq(&task->sighand->siglock);
4927+ }
4928+#else
4929+ {
4930+ /* Copied from kernel/kmod.c */
4931+ struct task_struct *task = current;
4932+ pid_t pid = kernel_thread(ccs_run_loader, NULL, 0);
4933+ sigset_t tmpsig;
4934+ spin_lock_irq(&task->sigmask_lock);
4935+ tmpsig = task->blocked;
4936+ siginitsetinv(&task->blocked,
4937+ sigmask(SIGKILL) | sigmask(SIGSTOP));
4938+ recalc_sigpending(task);
4939+ spin_unlock_irq(&task->sigmask_lock);
4940+ if (pid >= 0)
4941+ waitpid(pid, NULL, __WCLONE);
4942+ spin_lock_irq(&task->sigmask_lock);
4943+ task->blocked = tmpsig;
4944+ recalc_sigpending(task);
4945+ spin_unlock_irq(&task->sigmask_lock);
4946+ }
4947+#endif
4948+ if (ccsecurity_ops.check_profile)
4949+ ccsecurity_ops.check_profile();
4950+ else
4951+ panic("Failed to load policy.");
4952+}
4953+
4954+#endif
4955+
4956+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
4957+
4958+/**
4959+ * __ccs_search_binary_handler - Load policy before calling search_binary_handler().
4960+ *
4961+ * @bprm: Pointer to "struct linux_binprm".
4962+ *
4963+ * Returns 0 on success, negative value otherwise.
4964+ */
4965+static int __ccs_search_binary_handler(struct linux_binprm *bprm)
4966+{
4967+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
4968+ ccs_load_policy(bprm->filename);
4969+#endif
4970+ /*
4971+ * ccs_load_policy() executes /sbin/ccs-init if bprm->filename is
4972+ * /sbin/init. /sbin/ccs-init executes /etc/ccs/ccs-load-module to
4973+ * load loadable kernel module. The loadable kernel module modifies
4974+ * "struct ccsecurity_ops". Thus, we need to transfer control to
4975+ * __ccs_search_binary_handler() in security/ccsecurity/permission.c
4976+ * if "struct ccsecurity_ops" was modified.
4977+ */
4978+ if (ccsecurity_ops.search_binary_handler
4979+ != __ccs_search_binary_handler)
4980+ return ccsecurity_ops.search_binary_handler(bprm);
4981+ return search_binary_handler(bprm);
4982+}
4983+
4984+#else
4985+
4986+/**
4987+ * __ccs_search_binary_handler - Load policy before calling search_binary_handler().
4988+ *
4989+ * @bprm: Pointer to "struct linux_binprm".
4990+ * @regs: Pointer to "struct pt_regs".
4991+ *
4992+ * Returns 0 on success, negative value otherwise.
4993+ */
4994+static int __ccs_search_binary_handler(struct linux_binprm *bprm,
4995+ struct pt_regs *regs)
4996+{
4997+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
4998+ ccs_load_policy(bprm->filename);
4999+#endif
5000+ /*
5001+ * ccs_load_policy() executes /sbin/ccs-init if bprm->filename is
5002+ * /sbin/init. /sbin/ccs-init executes /etc/ccs/ccs-load-module to
5003+ * load loadable kernel module. The loadable kernel module modifies
5004+ * "struct ccsecurity_ops". Thus, we need to transfer control to
5005+ * __ccs_search_binary_handler() in security/ccsecurity/permission.c
5006+ * if "struct ccsecurity_ops" was modified.
5007+ */
5008+ if (ccsecurity_ops.search_binary_handler
5009+ != __ccs_search_binary_handler)
5010+ return ccsecurity_ops.search_binary_handler(bprm, regs);
5011+ return search_binary_handler(bprm, regs);
5012+}
5013+
5014+#endif
5015+
5016+/*
5017+ * Some exports for loadable kernel module part.
5018+ *
5019+ * Although scripts/checkpatch.pl complains about use of "extern" in C file,
5020+ * we don't put these into security/ccsecurity/internal.h because we want to
5021+ * split built-in part and loadable kernel module part.
5022+ */
5023+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
5024+extern spinlock_t vfsmount_lock;
5025+#endif
5026+
5027+/* For exporting variables and functions. */
5028+const struct ccsecurity_exports ccsecurity_exports = {
5029+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
5030+ .load_policy = ccs_load_policy,
5031+#endif
5032+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY)
5033+ .add_hooks = ccs_add_hooks,
5034+#endif
5035+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
5036+ .d_absolute_path = d_absolute_path,
5037+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
5038+ .__d_path = __d_path,
5039+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
5040+ .vfsmount_lock = &vfsmount_lock,
5041+#endif
5042+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
5043+ .find_task_by_vpid = find_task_by_vpid,
5044+ .find_task_by_pid_ns = find_task_by_pid_ns,
5045+#endif
5046+};
5047+#ifdef CONFIG_CCSECURITY_LKM
5048+/* Only ccsecurity module need to access this struct. */
5049+EXPORT_SYMBOL_GPL(ccsecurity_exports);
5050+#endif
5051+
5052+/* Members are updated by loadable kernel module. */
5053+struct ccsecurity_operations ccsecurity_ops = {
5054+ .search_binary_handler = __ccs_search_binary_handler,
5055+#ifdef CONFIG_CCSECURITY_DISABLE_BY_DEFAULT
5056+ .disabled = 1,
5057+#endif
5058+};
5059+/*
5060+ * Non-GPL modules might need to access this struct via inlined functions
5061+ * embedded into include/linux/security.h and include/net/ip.h
5062+ */
5063+EXPORT_SYMBOL(ccsecurity_ops);
5064diff --git a/security/ccsecurity/lsm2ccsecurity.c b/security/ccsecurity/lsm2ccsecurity.c
5065new file mode 100644
5066index 0000000..b81d8ed
5067--- /dev/null
5068+++ b/security/ccsecurity/lsm2ccsecurity.c
5069@@ -0,0 +1,192 @@
5070+/*
5071+ * security/ccsecurity/lsm2ccsecurity.c
5072+ *
5073+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
5074+ *
5075+ * Version: 1.8.4 2015/07/11
5076+ */
5077+
5078+#include <linux/path.h>
5079+#include <linux/security.h>
5080+#include <linux/ccsecurity.h>
5081+
5082+int ccs_settime(const struct timespec *ts, const struct timezone *tz)
5083+{
5084+ return ccs_capable(CCS_SYS_SETTIME) ? 0 : -EPERM;
5085+}
5086+
5087+int ccs_sb_mount(const char *dev_name, struct path *path, const char *type,
5088+ unsigned long flags, void *data)
5089+{
5090+ return ccs_mount_permission(dev_name, path, type, flags, data);
5091+}
5092+
5093+int ccs_sb_umount(struct vfsmount *mnt, int flags)
5094+{
5095+ return ccs_umount_permission(mnt, flags);
5096+}
5097+
5098+int ccs_sb_pivotroot(struct path *old_path, struct path *new_path)
5099+{
5100+ return ccs_pivot_root_permission(old_path, new_path);
5101+}
5102+
5103+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
5104+int ccs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
5105+{
5106+ return ccs_getattr_permission(mnt, dentry);
5107+}
5108+#else
5109+int ccs_inode_getattr(const struct path *path)
5110+{
5111+ return ccs_getattr_permission(path->mnt, path->dentry);
5112+}
5113+#endif
5114+
5115+int ccs_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
5116+{
5117+ return ccs_ioctl_permission(file, cmd, arg);
5118+}
5119+
5120+int ccs_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
5121+{
5122+ return ccs_fcntl_permission(file, cmd, arg);
5123+}
5124+
5125+int ccs_file_open(struct file *file, const struct cred *cred)
5126+{
5127+ return ccs_open_permission(file);
5128+}
5129+
5130+int ccs_socket_create(int family, int type, int protocol, int kern)
5131+{
5132+ return ccs_socket_create_permission(family, type, protocol);
5133+}
5134+
5135+int ccs_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
5136+{
5137+ return ccs_socket_bind_permission(sock, address, addrlen);
5138+}
5139+
5140+int ccs_socket_connect(struct socket *sock, struct sockaddr *address,
5141+ int addrlen)
5142+{
5143+ return ccs_socket_connect_permission(sock, address, addrlen);
5144+}
5145+
5146+int ccs_socket_listen(struct socket *sock, int backlog)
5147+{
5148+ return ccs_socket_listen_permission(sock);
5149+}
5150+
5151+int ccs_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
5152+{
5153+ return ccs_socket_sendmsg_permission(sock, msg, size);
5154+}
5155+
5156+int ccs_path_unlink(struct path *dir, struct dentry *dentry)
5157+{
5158+ return ccs_unlink_permission(dentry, dir->mnt);
5159+}
5160+
5161+int ccs_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
5162+{
5163+ return ccs_mkdir_permission(dentry, dir->mnt, mode);
5164+}
5165+
5166+int ccs_path_rmdir(struct path *dir, struct dentry *dentry)
5167+{
5168+ return ccs_rmdir_permission(dentry, dir->mnt);
5169+}
5170+
5171+int ccs_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
5172+ unsigned int dev)
5173+{
5174+ return ccs_mknod_permission(dentry, dir->mnt, mode, dev);
5175+}
5176+
5177+int ccs_path_truncate(struct path *path)
5178+{
5179+ return ccs_truncate_permission(path->dentry, path->mnt);
5180+}
5181+
5182+int ccs_path_symlink(struct path *dir, struct dentry *dentry,
5183+ const char *old_name)
5184+{
5185+ return ccs_symlink_permission(dentry, dir->mnt, old_name);
5186+}
5187+
5188+int ccs_path_link(struct dentry *old_dentry, struct path *new_dir,
5189+ struct dentry *new_dentry)
5190+{
5191+ return ccs_link_permission(old_dentry, new_dentry, new_dir->mnt);
5192+}
5193+
5194+int ccs_path_rename(struct path *old_dir, struct dentry *old_dentry,
5195+ struct path *new_dir, struct dentry *new_dentry)
5196+{
5197+ return ccs_rename_permission(old_dentry, new_dentry, new_dir->mnt);
5198+}
5199+
5200+int ccs_path_chmod(struct path *path, umode_t mode)
5201+{
5202+ return ccs_chmod_permission(path->dentry, path->mnt, mode);
5203+}
5204+
5205+int ccs_path_chown(struct path *path, kuid_t uid, kgid_t gid)
5206+{
5207+ return ccs_chown_permission(path->dentry, path->mnt, uid, gid);
5208+}
5209+
5210+int ccs_path_chroot(struct path *path)
5211+{
5212+ return ccs_chroot_permission(path);
5213+}
5214+
5215+#if !defined(CONFIG_SECURITY_PATH)
5216+EXPORT_SYMBOL(ccs_path_mkdir);
5217+EXPORT_SYMBOL(ccs_path_mknod);
5218+EXPORT_SYMBOL(ccs_path_unlink);
5219+EXPORT_SYMBOL(ccs_path_rename);
5220+#endif
5221+
5222+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY)
5223+
5224+#include <linux/lsm_hooks.h>
5225+
5226+static struct security_hook_list ccsecurity_hooks[] = {
5227+ LSM_HOOK_INIT(settime, ccs_settime),
5228+ LSM_HOOK_INIT(sb_mount, ccs_sb_mount),
5229+ LSM_HOOK_INIT(sb_umount, ccs_sb_umount),
5230+ LSM_HOOK_INIT(sb_pivotroot, ccs_sb_pivotroot),
5231+ LSM_HOOK_INIT(inode_getattr, ccs_inode_getattr),
5232+ LSM_HOOK_INIT(file_ioctl, ccs_file_ioctl),
5233+ LSM_HOOK_INIT(file_fcntl, ccs_file_fcntl),
5234+ LSM_HOOK_INIT(file_open, ccs_file_open),
5235+#if defined(CONFIG_SECURITY_NETWORK)
5236+ LSM_HOOK_INIT(socket_create, ccs_socket_create),
5237+ LSM_HOOK_INIT(socket_bind, ccs_socket_bind),
5238+ LSM_HOOK_INIT(socket_connect, ccs_socket_connect),
5239+ LSM_HOOK_INIT(socket_listen, ccs_socket_listen),
5240+ LSM_HOOK_INIT(socket_sendmsg, ccs_socket_sendmsg),
5241+#endif
5242+#if defined(CONFIG_SECURITY_PATH)
5243+ LSM_HOOK_INIT(path_unlink, ccs_path_unlink),
5244+ LSM_HOOK_INIT(path_mkdir, ccs_path_mkdir),
5245+ LSM_HOOK_INIT(path_rmdir, ccs_path_rmdir),
5246+ LSM_HOOK_INIT(path_mknod, ccs_path_mknod),
5247+ LSM_HOOK_INIT(path_truncate, ccs_path_truncate),
5248+ LSM_HOOK_INIT(path_symlink, ccs_path_symlink),
5249+ LSM_HOOK_INIT(path_link, ccs_path_link),
5250+ LSM_HOOK_INIT(path_rename, ccs_path_rename),
5251+ LSM_HOOK_INIT(path_chmod, ccs_path_chmod),
5252+ LSM_HOOK_INIT(path_chown, ccs_path_chown),
5253+ LSM_HOOK_INIT(path_chroot, ccs_path_chroot),
5254+#endif
5255+};
5256+
5257+static void ccs_add_hooks(void)
5258+{
5259+ security_add_hooks(ccsecurity_hooks, ARRAY_SIZE(ccsecurity_hooks));
5260+}
5261+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY) */
5262diff --git a/security/ccsecurity/memory.c b/security/ccsecurity/memory.c
5263new file mode 100644
5264index 0000000..6514a26
5265--- /dev/null
5266+++ b/security/ccsecurity/memory.c
5267@@ -0,0 +1,356 @@
5268+/*
5269+ * security/ccsecurity/memory.c
5270+ *
5271+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
5272+ *
5273+ * Version: 1.8.4 2015/05/05
5274+ */
5275+
5276+#include "internal.h"
5277+
5278+/***** SECTION1: Constants definition *****/
5279+
5280+/***** SECTION2: Structure definition *****/
5281+
5282+/***** SECTION3: Prototype definition section *****/
5283+
5284+bool ccs_memory_ok(const void *ptr, const unsigned int size);
5285+const struct ccs_path_info *ccs_get_name(const char *name);
5286+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
5287+struct ccs_security *ccs_find_task_security(const struct task_struct *task);
5288+#endif
5289+void *ccs_commit_ok(void *data, const unsigned int size);
5290+void __init ccs_mm_init(void);
5291+void ccs_warn_oom(const char *function);
5292+
5293+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
5294+static int __ccs_alloc_task_security(const struct task_struct *task);
5295+static void __ccs_free_task_security(const struct task_struct *task);
5296+static void ccs_add_task_security(struct ccs_security *ptr,
5297+ struct list_head *list);
5298+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
5299+static void ccs_rcu_free(struct rcu_head *rcu);
5300+#else
5301+static void ccs_rcu_free(void *arg);
5302+#endif
5303+#endif
5304+
5305+/***** SECTION4: Standalone functions section *****/
5306+
5307+/***** SECTION5: Variables definition section *****/
5308+
5309+/* Memoy currently used by policy/audit log/query. */
5310+unsigned int ccs_memory_used[CCS_MAX_MEMORY_STAT];
5311+
5312+/* Memory quota for "policy"/"audit log"/"query". */
5313+unsigned int ccs_memory_quota[CCS_MAX_MEMORY_STAT];
5314+
5315+/* The list for "struct ccs_name". */
5316+struct list_head ccs_name_list[CCS_MAX_HASH];
5317+
5318+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
5319+
5320+/* Dummy security context for avoiding NULL pointer dereference. */
5321+static struct ccs_security ccs_oom_security = {
5322+ .ccs_domain_info = &ccs_kernel_domain
5323+};
5324+
5325+/* Dummy security context for avoiding NULL pointer dereference. */
5326+static struct ccs_security ccs_default_security = {
5327+ .ccs_domain_info = &ccs_kernel_domain
5328+};
5329+
5330+/* List of "struct ccs_security". */
5331+struct list_head ccs_task_security_list[CCS_MAX_TASK_SECURITY_HASH];
5332+/* Lock for protecting ccs_task_security_list[]. */
5333+static DEFINE_SPINLOCK(ccs_task_security_list_lock);
5334+
5335+#endif
5336+
5337+/***** SECTION6: Dependent functions section *****/
5338+
5339+/**
5340+ * ccs_warn_oom - Print out of memory warning message.
5341+ *
5342+ * @function: Function's name.
5343+ *
5344+ * Returns nothing.
5345+ */
5346+void ccs_warn_oom(const char *function)
5347+{
5348+ /* Reduce error messages. */
5349+ static pid_t ccs_last_pid;
5350+ const pid_t pid = current->pid;
5351+ if (ccs_last_pid != pid) {
5352+ printk(KERN_WARNING "ERROR: Out of memory at %s.\n",
5353+ function);
5354+ ccs_last_pid = pid;
5355+ }
5356+ if (!ccs_policy_loaded)
5357+ panic("MAC Initialization failed.\n");
5358+}
5359+
5360+/**
5361+ * ccs_memory_ok - Check memory quota.
5362+ *
5363+ * @ptr: Pointer to allocated memory. Maybe NULL.
5364+ * @size: Size in byte. Not used if @ptr is NULL.
5365+ *
5366+ * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
5367+ *
5368+ * Caller holds ccs_policy_lock mutex.
5369+ */
5370+bool ccs_memory_ok(const void *ptr, const unsigned int size)
5371+{
5372+ if (ptr) {
5373+ const size_t s = ccs_round2(size);
5374+ ccs_memory_used[CCS_MEMORY_POLICY] += s;
5375+ if (!ccs_memory_quota[CCS_MEMORY_POLICY] ||
5376+ ccs_memory_used[CCS_MEMORY_POLICY] <=
5377+ ccs_memory_quota[CCS_MEMORY_POLICY])
5378+ return true;
5379+ ccs_memory_used[CCS_MEMORY_POLICY] -= s;
5380+ }
5381+ ccs_warn_oom(__func__);
5382+ return false;
5383+}
5384+
5385+/**
5386+ * ccs_commit_ok - Allocate memory and check memory quota.
5387+ *
5388+ * @data: Data to copy from.
5389+ * @size: Size in byte.
5390+ *
5391+ * Returns pointer to allocated memory on success, NULL otherwise.
5392+ * @data is zero-cleared on success.
5393+ *
5394+ * Caller holds ccs_policy_lock mutex.
5395+ */
5396+void *ccs_commit_ok(void *data, const unsigned int size)
5397+{
5398+ void *ptr = kmalloc(size, CCS_GFP_FLAGS);
5399+ if (ccs_memory_ok(ptr, size)) {
5400+ memmove(ptr, data, size);
5401+ memset(data, 0, size);
5402+ return ptr;
5403+ }
5404+ kfree(ptr);
5405+ return NULL;
5406+}
5407+
5408+/**
5409+ * ccs_get_name - Allocate memory for string data.
5410+ *
5411+ * @name: The string to store into the permernent memory.
5412+ *
5413+ * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
5414+ */
5415+const struct ccs_path_info *ccs_get_name(const char *name)
5416+{
5417+ struct ccs_name *ptr;
5418+ unsigned int hash;
5419+ int len;
5420+ int allocated_len;
5421+ struct list_head *head;
5422+
5423+ if (!name)
5424+ return NULL;
5425+ len = strlen(name) + 1;
5426+ hash = full_name_hash((const unsigned char *) name, len - 1);
5427+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(RHEL_MAJOR)
5428+ head = &ccs_name_list[hash_long(hash, CCS_HASH_BITS)];
5429+#else
5430+ head = &ccs_name_list[hash % CCS_MAX_HASH];
5431+#endif
5432+ if (mutex_lock_interruptible(&ccs_policy_lock))
5433+ return NULL;
5434+ list_for_each_entry(ptr, head, head.list) {
5435+ if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name) ||
5436+ atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS)
5437+ continue;
5438+ atomic_inc(&ptr->head.users);
5439+ goto out;
5440+ }
5441+ allocated_len = sizeof(*ptr) + len;
5442+ ptr = kzalloc(allocated_len, CCS_GFP_FLAGS);
5443+ if (ccs_memory_ok(ptr, allocated_len)) {
5444+ ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
5445+ memmove((char *) ptr->entry.name, name, len);
5446+ atomic_set(&ptr->head.users, 1);
5447+ ccs_fill_path_info(&ptr->entry);
5448+ ptr->size = allocated_len;
5449+ list_add_tail(&ptr->head.list, head);
5450+ } else {
5451+ kfree(ptr);
5452+ ptr = NULL;
5453+ }
5454+out:
5455+ mutex_unlock(&ccs_policy_lock);
5456+ return ptr ? &ptr->entry : NULL;
5457+}
5458+
5459+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
5460+
5461+/**
5462+ * ccs_add_task_security - Add "struct ccs_security" to list.
5463+ *
5464+ * @ptr: Pointer to "struct ccs_security".
5465+ * @list: Pointer to "struct list_head".
5466+ *
5467+ * Returns nothing.
5468+ */
5469+static void ccs_add_task_security(struct ccs_security *ptr,
5470+ struct list_head *list)
5471+{
5472+ unsigned long flags;
5473+ spin_lock_irqsave(&ccs_task_security_list_lock, flags);
5474+ list_add_rcu(&ptr->list, list);
5475+ spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
5476+}
5477+
5478+/**
5479+ * __ccs_alloc_task_security - Allocate memory for new tasks.
5480+ *
5481+ * @task: Pointer to "struct task_struct".
5482+ *
5483+ * Returns 0 on success, negative value otherwise.
5484+ */
5485+static int __ccs_alloc_task_security(const struct task_struct *task)
5486+{
5487+ struct ccs_security *old_security = ccs_current_security();
5488+ struct ccs_security *new_security = kzalloc(sizeof(*new_security),
5489+ GFP_KERNEL);
5490+ struct list_head *list = &ccs_task_security_list
5491+ [hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
5492+ if (!new_security)
5493+ return -ENOMEM;
5494+ new_security->task = task;
5495+ new_security->ccs_domain_info = old_security->ccs_domain_info;
5496+ new_security->ccs_flags = old_security->ccs_flags;
5497+ ccs_add_task_security(new_security, list);
5498+ return 0;
5499+}
5500+
5501+/**
5502+ * ccs_find_task_security - Find "struct ccs_security" for given task.
5503+ *
5504+ * @task: Pointer to "struct task_struct".
5505+ *
5506+ * Returns pointer to "struct ccs_security" on success, &ccs_oom_security on
5507+ * out of memory, &ccs_default_security otherwise.
5508+ *
5509+ * If @task is current thread and "struct ccs_security" for current thread was
5510+ * not found, I try to allocate it. But if allocation failed, current thread
5511+ * will be killed by SIGKILL. Note that if current->pid == 1, sending SIGKILL
5512+ * won't work.
5513+ */
5514+struct ccs_security *ccs_find_task_security(const struct task_struct *task)
5515+{
5516+ struct ccs_security *ptr;
5517+ struct list_head *list = &ccs_task_security_list
5518+ [hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
5519+ /* Make sure INIT_LIST_HEAD() in ccs_mm_init() takes effect. */
5520+ while (!list->next);
5521+ rcu_read_lock();
5522+ list_for_each_entry_rcu(ptr, list, list) {
5523+ if (ptr->task != task)
5524+ continue;
5525+ rcu_read_unlock();
5526+ return ptr;
5527+ }
5528+ rcu_read_unlock();
5529+ if (task != current)
5530+ return &ccs_default_security;
5531+ /* Use GFP_ATOMIC because caller may have called rcu_read_lock(). */
5532+ ptr = kzalloc(sizeof(*ptr), GFP_ATOMIC);
5533+ if (!ptr) {
5534+ printk(KERN_WARNING "Unable to allocate memory for pid=%u\n",
5535+ task->pid);
5536+ send_sig(SIGKILL, current, 0);
5537+ return &ccs_oom_security;
5538+ }
5539+ *ptr = ccs_default_security;
5540+ ptr->task = task;
5541+ ccs_add_task_security(ptr, list);
5542+ return ptr;
5543+}
5544+
5545+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
5546+
5547+/**
5548+ * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
5549+ *
5550+ * @rcu: Pointer to "struct rcu_head".
5551+ *
5552+ * Returns nothing.
5553+ */
5554+static void ccs_rcu_free(struct rcu_head *rcu)
5555+{
5556+ struct ccs_security *ptr = container_of(rcu, typeof(*ptr), rcu);
5557+ kfree(ptr);
5558+}
5559+
5560+#else
5561+
5562+/**
5563+ * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
5564+ *
5565+ * @arg: Pointer to "void".
5566+ *
5567+ * Returns nothing.
5568+ */
5569+static void ccs_rcu_free(void *arg)
5570+{
5571+ struct ccs_security *ptr = arg;
5572+ kfree(ptr);
5573+}
5574+
5575+#endif
5576+
5577+/**
5578+ * __ccs_free_task_security - Release memory associated with "struct task_struct".
5579+ *
5580+ * @task: Pointer to "struct task_struct".
5581+ *
5582+ * Returns nothing.
5583+ */
5584+static void __ccs_free_task_security(const struct task_struct *task)
5585+{
5586+ unsigned long flags;
5587+ struct ccs_security *ptr = ccs_find_task_security(task);
5588+ if (ptr == &ccs_default_security || ptr == &ccs_oom_security)
5589+ return;
5590+ spin_lock_irqsave(&ccs_task_security_list_lock, flags);
5591+ list_del_rcu(&ptr->list);
5592+ spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
5593+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
5594+ call_rcu(&ptr->rcu, ccs_rcu_free);
5595+#else
5596+ call_rcu(&ptr->rcu, ccs_rcu_free, ptr);
5597+#endif
5598+}
5599+
5600+#endif
5601+
5602+/**
5603+ * ccs_mm_init - Initialize mm related code.
5604+ *
5605+ * Returns nothing.
5606+ */
5607+void __init ccs_mm_init(void)
5608+{
5609+ int idx;
5610+ for (idx = 0; idx < CCS_MAX_HASH; idx++)
5611+ INIT_LIST_HEAD(&ccs_name_list[idx]);
5612+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
5613+ for (idx = 0; idx < CCS_MAX_TASK_SECURITY_HASH; idx++)
5614+ INIT_LIST_HEAD(&ccs_task_security_list[idx]);
5615+#endif
5616+ smp_wmb(); /* Avoid out of order execution. */
5617+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
5618+ ccsecurity_ops.alloc_task_security = __ccs_alloc_task_security;
5619+ ccsecurity_ops.free_task_security = __ccs_free_task_security;
5620+#endif
5621+ ccs_kernel_domain.domainname = ccs_get_name("<kernel>");
5622+ list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
5623+}
5624diff --git a/security/ccsecurity/permission.c b/security/ccsecurity/permission.c
5625new file mode 100644
5626index 0000000..d73c237
5627--- /dev/null
5628+++ b/security/ccsecurity/permission.c
5629@@ -0,0 +1,5025 @@
5630+/*
5631+ * security/ccsecurity/permission.c
5632+ *
5633+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
5634+ *
5635+ * Version: 1.8.4 2015/05/05
5636+ */
5637+
5638+#include "internal.h"
5639+
5640+/***** SECTION1: Constants definition *****/
5641+
5642+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
5643+
5644+/*
5645+ * may_open() receives open flags modified by open_to_namei_flags() until
5646+ * 2.6.32. We stop here in case some distributions backported ACC_MODE changes,
5647+ * for we can't determine whether may_open() receives open flags modified by
5648+ * open_to_namei_flags() or not.
5649+ */
5650+#ifdef ACC_MODE
5651+#error ACC_MODE already defined.
5652+#endif
5653+#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
5654+
5655+#if defined(RHEL_MAJOR) && RHEL_MAJOR == 6
5656+/* RHEL6 passes unmodified flags since 2.6.32-71.14.1.el6 . */
5657+#undef ACC_MODE
5658+#define ACC_MODE(x) ("\004\002\006"[(x)&O_ACCMODE])
5659+#endif
5660+
5661+#endif
5662+
5663+/* String table for special mount operations. */
5664+static const char * const ccs_mounts[CCS_MAX_SPECIAL_MOUNT] = {
5665+ [CCS_MOUNT_BIND] = "--bind",
5666+ [CCS_MOUNT_MOVE] = "--move",
5667+ [CCS_MOUNT_REMOUNT] = "--remount",
5668+ [CCS_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable",
5669+ [CCS_MOUNT_MAKE_PRIVATE] = "--make-private",
5670+ [CCS_MOUNT_MAKE_SLAVE] = "--make-slave",
5671+ [CCS_MOUNT_MAKE_SHARED] = "--make-shared",
5672+};
5673+
5674+/* Mapping table from "enum ccs_path_acl_index" to "enum ccs_mac_index". */
5675+static const u8 ccs_p2mac[CCS_MAX_PATH_OPERATION] = {
5676+ [CCS_TYPE_EXECUTE] = CCS_MAC_FILE_EXECUTE,
5677+ [CCS_TYPE_READ] = CCS_MAC_FILE_OPEN,
5678+ [CCS_TYPE_WRITE] = CCS_MAC_FILE_OPEN,
5679+ [CCS_TYPE_APPEND] = CCS_MAC_FILE_OPEN,
5680+ [CCS_TYPE_UNLINK] = CCS_MAC_FILE_UNLINK,
5681+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
5682+ [CCS_TYPE_GETATTR] = CCS_MAC_FILE_GETATTR,
5683+#endif
5684+ [CCS_TYPE_RMDIR] = CCS_MAC_FILE_RMDIR,
5685+ [CCS_TYPE_TRUNCATE] = CCS_MAC_FILE_TRUNCATE,
5686+ [CCS_TYPE_SYMLINK] = CCS_MAC_FILE_SYMLINK,
5687+ [CCS_TYPE_CHROOT] = CCS_MAC_FILE_CHROOT,
5688+ [CCS_TYPE_UMOUNT] = CCS_MAC_FILE_UMOUNT,
5689+};
5690+
5691+/* Mapping table from "enum ccs_mkdev_acl_index" to "enum ccs_mac_index". */
5692+const u8 ccs_pnnn2mac[CCS_MAX_MKDEV_OPERATION] = {
5693+ [CCS_TYPE_MKBLOCK] = CCS_MAC_FILE_MKBLOCK,
5694+ [CCS_TYPE_MKCHAR] = CCS_MAC_FILE_MKCHAR,
5695+};
5696+
5697+/* Mapping table from "enum ccs_path2_acl_index" to "enum ccs_mac_index". */
5698+const u8 ccs_pp2mac[CCS_MAX_PATH2_OPERATION] = {
5699+ [CCS_TYPE_LINK] = CCS_MAC_FILE_LINK,
5700+ [CCS_TYPE_RENAME] = CCS_MAC_FILE_RENAME,
5701+ [CCS_TYPE_PIVOT_ROOT] = CCS_MAC_FILE_PIVOT_ROOT,
5702+};
5703+
5704+/*
5705+ * Mapping table from "enum ccs_path_number_acl_index" to "enum ccs_mac_index".
5706+ */
5707+const u8 ccs_pn2mac[CCS_MAX_PATH_NUMBER_OPERATION] = {
5708+ [CCS_TYPE_CREATE] = CCS_MAC_FILE_CREATE,
5709+ [CCS_TYPE_MKDIR] = CCS_MAC_FILE_MKDIR,
5710+ [CCS_TYPE_MKFIFO] = CCS_MAC_FILE_MKFIFO,
5711+ [CCS_TYPE_MKSOCK] = CCS_MAC_FILE_MKSOCK,
5712+ [CCS_TYPE_IOCTL] = CCS_MAC_FILE_IOCTL,
5713+ [CCS_TYPE_CHMOD] = CCS_MAC_FILE_CHMOD,
5714+ [CCS_TYPE_CHOWN] = CCS_MAC_FILE_CHOWN,
5715+ [CCS_TYPE_CHGRP] = CCS_MAC_FILE_CHGRP,
5716+};
5717+
5718+#ifdef CONFIG_CCSECURITY_NETWORK
5719+
5720+/*
5721+ * Mapping table from "enum ccs_network_acl_index" to "enum ccs_mac_index" for
5722+ * inet domain socket.
5723+ */
5724+static const u8 ccs_inet2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
5725+ [SOCK_STREAM] = {
5726+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_INET_STREAM_BIND,
5727+ [CCS_NETWORK_LISTEN] = CCS_MAC_NETWORK_INET_STREAM_LISTEN,
5728+ [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_INET_STREAM_CONNECT,
5729+ [CCS_NETWORK_ACCEPT] = CCS_MAC_NETWORK_INET_STREAM_ACCEPT,
5730+ },
5731+ [SOCK_DGRAM] = {
5732+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_INET_DGRAM_BIND,
5733+ [CCS_NETWORK_SEND] = CCS_MAC_NETWORK_INET_DGRAM_SEND,
5734+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
5735+ [CCS_NETWORK_RECV] = CCS_MAC_NETWORK_INET_DGRAM_RECV,
5736+#endif
5737+ },
5738+ [SOCK_RAW] = {
5739+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_INET_RAW_BIND,
5740+ [CCS_NETWORK_SEND] = CCS_MAC_NETWORK_INET_RAW_SEND,
5741+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
5742+ [CCS_NETWORK_RECV] = CCS_MAC_NETWORK_INET_RAW_RECV,
5743+#endif
5744+ },
5745+};
5746+
5747+/*
5748+ * Mapping table from "enum ccs_network_acl_index" to "enum ccs_mac_index" for
5749+ * unix domain socket.
5750+ */
5751+static const u8 ccs_unix2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
5752+ [SOCK_STREAM] = {
5753+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_UNIX_STREAM_BIND,
5754+ [CCS_NETWORK_LISTEN] = CCS_MAC_NETWORK_UNIX_STREAM_LISTEN,
5755+ [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_STREAM_CONNECT,
5756+ [CCS_NETWORK_ACCEPT] = CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT,
5757+ },
5758+ [SOCK_DGRAM] = {
5759+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_UNIX_DGRAM_BIND,
5760+ [CCS_NETWORK_SEND] = CCS_MAC_NETWORK_UNIX_DGRAM_SEND,
5761+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
5762+ [CCS_NETWORK_RECV] = CCS_MAC_NETWORK_UNIX_DGRAM_RECV,
5763+#endif
5764+ },
5765+ [SOCK_SEQPACKET] = {
5766+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND,
5767+ [CCS_NETWORK_LISTEN] = CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
5768+ [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
5769+ [CCS_NETWORK_ACCEPT] = CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT,
5770+ },
5771+};
5772+
5773+#endif
5774+
5775+#ifdef CONFIG_CCSECURITY_CAPABILITY
5776+
5777+/*
5778+ * Mapping table from "enum ccs_capability_acl_index" to "enum ccs_mac_index".
5779+ */
5780+const u8 ccs_c2mac[CCS_MAX_CAPABILITY_INDEX] = {
5781+ [CCS_USE_ROUTE_SOCKET] = CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET,
5782+ [CCS_USE_PACKET_SOCKET] = CCS_MAC_CAPABILITY_USE_PACKET_SOCKET,
5783+ [CCS_SYS_REBOOT] = CCS_MAC_CAPABILITY_SYS_REBOOT,
5784+ [CCS_SYS_VHANGUP] = CCS_MAC_CAPABILITY_SYS_VHANGUP,
5785+ [CCS_SYS_SETTIME] = CCS_MAC_CAPABILITY_SYS_SETTIME,
5786+ [CCS_SYS_NICE] = CCS_MAC_CAPABILITY_SYS_NICE,
5787+ [CCS_SYS_SETHOSTNAME] = CCS_MAC_CAPABILITY_SYS_SETHOSTNAME,
5788+ [CCS_USE_KERNEL_MODULE] = CCS_MAC_CAPABILITY_USE_KERNEL_MODULE,
5789+ [CCS_SYS_KEXEC_LOAD] = CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD,
5790+ [CCS_SYS_PTRACE] = CCS_MAC_CAPABILITY_SYS_PTRACE,
5791+};
5792+
5793+#endif
5794+
5795+/***** SECTION2: Structure definition *****/
5796+
5797+/* Structure for holding inet domain socket's address. */
5798+struct ccs_inet_addr_info {
5799+ u16 port; /* In network byte order. */
5800+ const u32 *address; /* In network byte order. */
5801+ bool is_ipv6;
5802+};
5803+
5804+/* Structure for holding unix domain socket's address. */
5805+struct ccs_unix_addr_info {
5806+ u8 *addr; /* This may not be '\0' terminated string. */
5807+ unsigned int addr_len;
5808+};
5809+
5810+/* Structure for holding socket address. */
5811+struct ccs_addr_info {
5812+ u8 protocol;
5813+ u8 operation;
5814+ struct ccs_inet_addr_info inet;
5815+ struct ccs_unix_addr_info unix0;
5816+};
5817+
5818+/***** SECTION3: Prototype definition section *****/
5819+
5820+bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
5821+ struct ccs_page_dump *dump);
5822+void ccs_get_attributes(struct ccs_obj_info *obj);
5823+
5824+static bool ccs_alphabet_char(const char c);
5825+static bool ccs_argv(const unsigned int index, const char *arg_ptr,
5826+ const int argc, const struct ccs_argv *argv, u8 *checked);
5827+static bool ccs_byte_range(const char *str);
5828+static bool ccs_check_entry(struct ccs_request_info *r,
5829+ struct ccs_acl_info *ptr);
5830+static bool ccs_check_mkdev_acl(struct ccs_request_info *r,
5831+ const struct ccs_acl_info *ptr);
5832+static bool ccs_check_mount_acl(struct ccs_request_info *r,
5833+ const struct ccs_acl_info *ptr);
5834+static bool ccs_check_path2_acl(struct ccs_request_info *r,
5835+ const struct ccs_acl_info *ptr);
5836+static bool ccs_check_path_acl(struct ccs_request_info *r,
5837+ const struct ccs_acl_info *ptr);
5838+static bool ccs_check_path_number_acl(struct ccs_request_info *r,
5839+ const struct ccs_acl_info *ptr);
5840+static bool ccs_compare_number_union(const unsigned long value,
5841+ const struct ccs_number_union *ptr);
5842+static bool ccs_condition(struct ccs_request_info *r,
5843+ const struct ccs_condition *cond);
5844+static bool ccs_decimal(const char c);
5845+static bool ccs_envp(const char *env_name, const char *env_value,
5846+ const int envc, const struct ccs_envp *envp, u8 *checked);
5847+static bool ccs_file_matches_pattern(const char *filename,
5848+ const char *filename_end,
5849+ const char *pattern,
5850+ const char *pattern_end);
5851+static bool ccs_file_matches_pattern2(const char *filename,
5852+ const char *filename_end,
5853+ const char *pattern,
5854+ const char *pattern_end);
5855+static bool ccs_get_realpath(struct ccs_path_info *buf, struct path *path);
5856+static bool ccs_hexadecimal(const char c);
5857+static bool ccs_number_matches_group(const unsigned long min,
5858+ const unsigned long max,
5859+ const struct ccs_group *group);
5860+static bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
5861+ const struct ccs_path_info *pattern);
5862+static bool ccs_path_matches_pattern2(const char *f, const char *p);
5863+static bool ccs_scan_bprm(struct ccs_execve *ee, const u16 argc,
5864+ const struct ccs_argv *argv, const u16 envc,
5865+ const struct ccs_envp *envp);
5866+static bool ccs_scan_exec_realpath(struct file *file,
5867+ const struct ccs_name_union *ptr,
5868+ const bool match);
5869+static bool ccs_scan_transition(const struct list_head *list,
5870+ const struct ccs_path_info *domainname,
5871+ const struct ccs_path_info *program,
5872+ const char *last_name,
5873+ const enum ccs_transition_type type);
5874+static const char *ccs_last_word(const char *name);
5875+static const struct ccs_path_info *ccs_compare_name_union
5876+(const struct ccs_path_info *name, const struct ccs_name_union *ptr);
5877+static const struct ccs_path_info *ccs_path_matches_group
5878+(const struct ccs_path_info *pathname, const struct ccs_group *group);
5879+static enum ccs_transition_type ccs_transition_type
5880+(const struct ccs_policy_namespace *ns, const struct ccs_path_info *domainname,
5881+ const struct ccs_path_info *program);
5882+static int __ccs_chmod_permission(struct dentry *dentry,
5883+ struct vfsmount *vfsmnt, mode_t mode);
5884+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
5885+static int __ccs_chown_permission(struct dentry *dentry,
5886+ struct vfsmount *vfsmnt, kuid_t user,
5887+ kgid_t group);
5888+#else
5889+static int __ccs_chown_permission(struct dentry *dentry,
5890+ struct vfsmount *vfsmnt, uid_t user,
5891+ gid_t group);
5892+#endif
5893+static int __ccs_chroot_permission(struct path *path);
5894+static int __ccs_fcntl_permission(struct file *file, unsigned int cmd,
5895+ unsigned long arg);
5896+static int __ccs_ioctl_permission(struct file *filp, unsigned int cmd,
5897+ unsigned long arg);
5898+static int __ccs_link_permission(struct dentry *old_dentry,
5899+ struct dentry *new_dentry,
5900+ struct vfsmount *mnt);
5901+static int __ccs_mkdir_permission(struct dentry *dentry, struct vfsmount *mnt,
5902+ unsigned int mode);
5903+static int __ccs_mknod_permission(struct dentry *dentry, struct vfsmount *mnt,
5904+ const unsigned int mode, unsigned int dev);
5905+static int __ccs_mount_permission(const char *dev_name, struct path *path,
5906+ const char *type, unsigned long flags,
5907+ void *data_page);
5908+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
5909+static int __ccs_open_exec_permission(struct dentry *dentry,
5910+ struct vfsmount *mnt);
5911+#endif
5912+static int __ccs_open_permission(struct dentry *dentry, struct vfsmount *mnt,
5913+ const int flag);
5914+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
5915+static int __ccs_parse_table(int __user *name, int nlen, void __user *oldval,
5916+ void __user *newval, struct ctl_table *table);
5917+#endif
5918+static int __ccs_pivot_root_permission(struct path *old_path,
5919+ struct path *new_path);
5920+static int __ccs_rename_permission(struct dentry *old_dentry,
5921+ struct dentry *new_dentry,
5922+ struct vfsmount *mnt);
5923+static int __ccs_rmdir_permission(struct dentry *dentry, struct vfsmount *mnt);
5924+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
5925+static int __ccs_search_binary_handler(struct linux_binprm *bprm);
5926+#else
5927+static int __ccs_search_binary_handler(struct linux_binprm *bprm,
5928+ struct pt_regs *regs);
5929+#endif
5930+static int __ccs_symlink_permission(struct dentry *dentry,
5931+ struct vfsmount *mnt, const char *from);
5932+static int __ccs_truncate_permission(struct dentry *dentry,
5933+ struct vfsmount *mnt);
5934+static int __ccs_umount_permission(struct vfsmount *mnt, int flags);
5935+static int __ccs_unlink_permission(struct dentry *dentry,
5936+ struct vfsmount *mnt);
5937+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
5938+static int __ccs_uselib_permission(struct dentry *dentry,
5939+ struct vfsmount *mnt);
5940+#endif
5941+static int ccs_execute_permission(struct ccs_request_info *r,
5942+ const struct ccs_path_info *filename);
5943+static int ccs_find_next_domain(struct ccs_execve *ee);
5944+static int ccs_get_path(const char *pathname, struct path *path);
5945+static int ccs_kern_path(const char *pathname, int flags, struct path *path);
5946+static int ccs_mkdev_perm(const u8 operation, struct dentry *dentry,
5947+ struct vfsmount *mnt, const unsigned int mode,
5948+ unsigned int dev);
5949+static int ccs_mount_acl(struct ccs_request_info *r, const char *dev_name,
5950+ struct path *dir, const char *type,
5951+ unsigned long flags);
5952+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
5953+static int ccs_new_open_permission(struct file *filp);
5954+#endif
5955+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
5956+static int ccs_old_chroot_permission(struct nameidata *nd);
5957+static int ccs_old_mount_permission(const char *dev_name, struct nameidata *nd,
5958+ const char *type, unsigned long flags,
5959+ void *data_page);
5960+static int ccs_old_pivot_root_permission(struct nameidata *old_nd,
5961+ struct nameidata *new_nd);
5962+#endif
5963+static int ccs_path2_perm(const u8 operation, struct dentry *dentry1,
5964+ struct vfsmount *mnt1, struct dentry *dentry2,
5965+ struct vfsmount *mnt2);
5966+static int ccs_path_number_perm(const u8 type, struct dentry *dentry,
5967+ struct vfsmount *vfsmnt, unsigned long number);
5968+static int ccs_path_perm(const u8 operation, struct dentry *dentry,
5969+ struct vfsmount *mnt, const char *target);
5970+static int ccs_path_permission(struct ccs_request_info *r, u8 operation,
5971+ const struct ccs_path_info *filename);
5972+static int ccs_start_execve(struct linux_binprm *bprm,
5973+ struct ccs_execve **eep);
5974+static int ccs_symlink_path(const char *pathname, struct ccs_path_info *name);
5975+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
5976+static void __ccs_clear_open_mode(void);
5977+static void __ccs_save_open_mode(int mode);
5978+#endif
5979+static void ccs_add_slash(struct ccs_path_info *buf);
5980+static void ccs_finish_execve(int retval, struct ccs_execve *ee);
5981+
5982+#ifdef CONFIG_CCSECURITY_MISC
5983+static bool ccs_check_env_acl(struct ccs_request_info *r,
5984+ const struct ccs_acl_info *ptr);
5985+static int ccs_env_perm(struct ccs_request_info *r, const char *env);
5986+static int ccs_environ(struct ccs_execve *ee);
5987+#endif
5988+
5989+#ifdef CONFIG_CCSECURITY_CAPABILITY
5990+static bool __ccs_capable(const u8 operation);
5991+static bool ccs_check_capability_acl(struct ccs_request_info *r,
5992+ const struct ccs_acl_info *ptr);
5993+static bool ccs_kernel_service(void);
5994+static int __ccs_ptrace_permission(long request, long pid);
5995+static int __ccs_socket_create_permission(int family, int type, int protocol);
5996+#endif
5997+
5998+#ifdef CONFIG_CCSECURITY_NETWORK
5999+static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
6000+ const struct ccs_group *group);
6001+static bool ccs_check_inet_acl(struct ccs_request_info *r,
6002+ const struct ccs_acl_info *ptr);
6003+static bool ccs_check_unix_acl(struct ccs_request_info *r,
6004+ const struct ccs_acl_info *ptr);
6005+static bool ccs_kernel_service(void);
6006+static int __ccs_socket_bind_permission(struct socket *sock,
6007+ struct sockaddr *addr, int addr_len);
6008+static int __ccs_socket_connect_permission(struct socket *sock,
6009+ struct sockaddr *addr,
6010+ int addr_len);
6011+static int __ccs_socket_listen_permission(struct socket *sock);
6012+static int __ccs_socket_post_accept_permission(struct socket *sock,
6013+ struct socket *newsock);
6014+static int __ccs_socket_sendmsg_permission(struct socket *sock,
6015+ struct msghdr *msg, int size);
6016+static int ccs_check_inet_address(const struct sockaddr *addr,
6017+ const unsigned int addr_len, const u16 port,
6018+ struct ccs_addr_info *address);
6019+static int ccs_check_unix_address(struct sockaddr *addr,
6020+ const unsigned int addr_len,
6021+ struct ccs_addr_info *address);
6022+static int ccs_inet_entry(const struct ccs_addr_info *address);
6023+static int ccs_unix_entry(const struct ccs_addr_info *address);
6024+static u8 ccs_sock_family(struct sock *sk);
6025+#endif
6026+
6027+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
6028+static int __ccs_socket_post_recvmsg_permission(struct sock *sk,
6029+ struct sk_buff *skb,
6030+ int flags);
6031+#endif
6032+
6033+#ifdef CONFIG_CCSECURITY_IPC
6034+static bool ccs_check_signal_acl(struct ccs_request_info *r,
6035+ const struct ccs_acl_info *ptr);
6036+static int ccs_signal_acl(const int pid, const int sig);
6037+static int ccs_signal_acl0(pid_t tgid, pid_t pid, int sig);
6038+static int ccs_signal_acl2(const int sig, const int pid);
6039+#endif
6040+
6041+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
6042+static int __ccs_getattr_permission(struct vfsmount *mnt,
6043+ struct dentry *dentry);
6044+#endif
6045+
6046+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
6047+static bool ccs_find_execute_handler(struct ccs_execve *ee, const u8 type);
6048+static int ccs_try_alt_exec(struct ccs_execve *ee);
6049+static void ccs_unescape(unsigned char *dest);
6050+#endif
6051+
6052+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
6053+static bool ccs_check_task_acl(struct ccs_request_info *r,
6054+ const struct ccs_acl_info *ptr);
6055+#endif
6056+
6057+/***** SECTION4: Standalone functions section *****/
6058+
6059+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
6060+
6061+/**
6062+ * ccs_copy_argv - Wrapper for copy_strings_kernel().
6063+ *
6064+ * @arg: String to copy.
6065+ * @bprm: Pointer to "struct linux_binprm".
6066+ *
6067+ * Returns return value of copy_strings_kernel().
6068+ */
6069+static inline int ccs_copy_argv(const char *arg, struct linux_binprm *bprm)
6070+{
6071+ const int ret = copy_strings_kernel(1, &arg, bprm);
6072+ if (ret >= 0)
6073+ bprm->argc++;
6074+ return ret;
6075+}
6076+
6077+#else
6078+
6079+/**
6080+ * ccs_copy_argv - Wrapper for copy_strings_kernel().
6081+ *
6082+ * @arg: String to copy.
6083+ * @bprm: Pointer to "struct linux_binprm".
6084+ *
6085+ * Returns return value of copy_strings_kernel().
6086+ */
6087+static inline int ccs_copy_argv(char *arg, struct linux_binprm *bprm)
6088+{
6089+ const int ret = copy_strings_kernel(1, &arg, bprm);
6090+ if (ret >= 0)
6091+ bprm->argc++;
6092+ return ret;
6093+}
6094+
6095+#endif
6096+
6097+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
6098+
6099+/**
6100+ * get_fs_root - Get reference on root directory.
6101+ *
6102+ * @fs: Pointer to "struct fs_struct".
6103+ * @root: Pointer to "struct path".
6104+ *
6105+ * Returns nothing.
6106+ *
6107+ * This is for compatibility with older kernels.
6108+ */
6109+static inline void get_fs_root(struct fs_struct *fs, struct path *root)
6110+{
6111+ read_lock(&fs->lock);
6112+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
6113+ *root = fs->root;
6114+ path_get(root);
6115+#else
6116+ root->dentry = dget(fs->root);
6117+ root->mnt = mntget(fs->rootmnt);
6118+#endif
6119+ read_unlock(&fs->lock);
6120+}
6121+
6122+#endif
6123+
6124+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
6125+
6126+/**
6127+ * module_put - Put a reference on module.
6128+ *
6129+ * @module: Pointer to "struct module". Maybe NULL.
6130+ *
6131+ * Returns nothing.
6132+ *
6133+ * This is for compatibility with older kernels.
6134+ */
6135+static inline void module_put(struct module *module)
6136+{
6137+ if (module)
6138+ __MOD_DEC_USE_COUNT(module);
6139+}
6140+
6141+#endif
6142+
6143+/**
6144+ * ccs_put_filesystem - Wrapper for put_filesystem().
6145+ *
6146+ * @fstype: Pointer to "struct file_system_type".
6147+ *
6148+ * Returns nothing.
6149+ *
6150+ * Since put_filesystem() is not exported, I embed put_filesystem() here.
6151+ */
6152+static inline void ccs_put_filesystem(struct file_system_type *fstype)
6153+{
6154+ module_put(fstype->owner);
6155+}
6156+
6157+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
6158+
6159+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
6160+#if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
6161+#if !defined(AX_MAJOR) || AX_MAJOR != 3
6162+
6163+/**
6164+ * ip_hdr - Get "struct iphdr".
6165+ *
6166+ * @skb: Pointer to "struct sk_buff".
6167+ *
6168+ * Returns pointer to "struct iphdr".
6169+ *
6170+ * This is for compatibility with older kernels.
6171+ */
6172+static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
6173+{
6174+ return skb->nh.iph;
6175+}
6176+
6177+/**
6178+ * udp_hdr - Get "struct udphdr".
6179+ *
6180+ * @skb: Pointer to "struct sk_buff".
6181+ *
6182+ * Returns pointer to "struct udphdr".
6183+ *
6184+ * This is for compatibility with older kernels.
6185+ */
6186+static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
6187+{
6188+ return skb->h.uh;
6189+}
6190+
6191+/**
6192+ * ipv6_hdr - Get "struct ipv6hdr".
6193+ *
6194+ * @skb: Pointer to "struct sk_buff".
6195+ *
6196+ * Returns pointer to "struct ipv6hdr".
6197+ *
6198+ * This is for compatibility with older kernels.
6199+ */
6200+static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
6201+{
6202+ return skb->nh.ipv6h;
6203+}
6204+
6205+#endif
6206+#endif
6207+#endif
6208+
6209+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
6210+
6211+/**
6212+ * skb_kill_datagram - Kill a datagram forcibly.
6213+ *
6214+ * @sk: Pointer to "struct sock".
6215+ * @skb: Pointer to "struct sk_buff".
6216+ * @flags: Flags passed to skb_recv_datagram().
6217+ *
6218+ * Returns nothing.
6219+ */
6220+static inline void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
6221+ int flags)
6222+{
6223+ /* Clear queue. */
6224+ if (flags & MSG_PEEK) {
6225+ int clear = 0;
6226+ spin_lock_irq(&sk->receive_queue.lock);
6227+ if (skb == skb_peek(&sk->receive_queue)) {
6228+ __skb_unlink(skb, &sk->receive_queue);
6229+ clear = 1;
6230+ }
6231+ spin_unlock_irq(&sk->receive_queue.lock);
6232+ if (clear)
6233+ kfree_skb(skb);
6234+ }
6235+ skb_free_datagram(sk, skb);
6236+}
6237+
6238+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
6239+
6240+/**
6241+ * skb_kill_datagram - Kill a datagram forcibly.
6242+ *
6243+ * @sk: Pointer to "struct sock".
6244+ * @skb: Pointer to "struct sk_buff".
6245+ * @flags: Flags passed to skb_recv_datagram().
6246+ *
6247+ * Returns nothing.
6248+ */
6249+static inline void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
6250+ int flags)
6251+{
6252+ /* Clear queue. */
6253+ if (flags & MSG_PEEK) {
6254+ int clear = 0;
6255+ spin_lock_bh(&sk->sk_receive_queue.lock);
6256+ if (skb == skb_peek(&sk->sk_receive_queue)) {
6257+ __skb_unlink(skb, &sk->sk_receive_queue);
6258+ clear = 1;
6259+ }
6260+ spin_unlock_bh(&sk->sk_receive_queue.lock);
6261+ if (clear)
6262+ kfree_skb(skb);
6263+ }
6264+ skb_free_datagram(sk, skb);
6265+}
6266+
6267+#endif
6268+
6269+#endif
6270+
6271+/***** SECTION5: Variables definition section *****/
6272+
6273+/* The initial domain. */
6274+struct ccs_domain_info ccs_kernel_domain;
6275+
6276+/* The list for "struct ccs_domain_info". */
6277+LIST_HEAD(ccs_domain_list);
6278+
6279+/***** SECTION6: Dependent functions section *****/
6280+
6281+/**
6282+ * ccs_path_matches_group - Check whether the given pathname matches members of the given pathname group.
6283+ *
6284+ * @pathname: The name of pathname.
6285+ * @group: Pointer to "struct ccs_path_group".
6286+ *
6287+ * Returns matched member's pathname if @pathname matches pathnames in @group,
6288+ * NULL otherwise.
6289+ *
6290+ * Caller holds ccs_read_lock().
6291+ */
6292+static const struct ccs_path_info *ccs_path_matches_group
6293+(const struct ccs_path_info *pathname, const struct ccs_group *group)
6294+{
6295+ struct ccs_path_group *member;
6296+ list_for_each_entry_srcu(member, &group->member_list, head.list,
6297+ &ccs_ss) {
6298+ if (member->head.is_deleted)
6299+ continue;
6300+ if (!ccs_path_matches_pattern(pathname, member->member_name))
6301+ continue;
6302+ return member->member_name;
6303+ }
6304+ return NULL;
6305+}
6306+
6307+/**
6308+ * ccs_number_matches_group - Check whether the given number matches members of the given number group.
6309+ *
6310+ * @min: Min number.
6311+ * @max: Max number.
6312+ * @group: Pointer to "struct ccs_number_group".
6313+ *
6314+ * Returns true if @min and @max partially overlaps @group, false otherwise.
6315+ *
6316+ * Caller holds ccs_read_lock().
6317+ */
6318+static bool ccs_number_matches_group(const unsigned long min,
6319+ const unsigned long max,
6320+ const struct ccs_group *group)
6321+{
6322+ struct ccs_number_group *member;
6323+ bool matched = false;
6324+ list_for_each_entry_srcu(member, &group->member_list, head.list,
6325+ &ccs_ss) {
6326+ if (member->head.is_deleted)
6327+ continue;
6328+ if (min > member->number.values[1] ||
6329+ max < member->number.values[0])
6330+ continue;
6331+ matched = true;
6332+ break;
6333+ }
6334+ return matched;
6335+}
6336+
6337+/**
6338+ * ccs_check_entry - Do permission check.
6339+ *
6340+ * @r: Pointer to "struct ccs_request_info".
6341+ * @ptr: Pointer to "struct ccs_acl_info".
6342+ *
6343+ * Returns true on match, false otherwise.
6344+ *
6345+ * Caller holds ccs_read_lock().
6346+ */
6347+static bool ccs_check_entry(struct ccs_request_info *r,
6348+ struct ccs_acl_info *ptr)
6349+{
6350+ if (ptr->is_deleted || ptr->type != r->param_type)
6351+ return false;
6352+ switch (r->param_type) {
6353+ case CCS_TYPE_PATH_ACL:
6354+ return ccs_check_path_acl(r, ptr);
6355+ case CCS_TYPE_PATH2_ACL:
6356+ return ccs_check_path2_acl(r, ptr);
6357+ case CCS_TYPE_PATH_NUMBER_ACL:
6358+ return ccs_check_path_number_acl(r, ptr);
6359+ case CCS_TYPE_MKDEV_ACL:
6360+ return ccs_check_mkdev_acl(r, ptr);
6361+ case CCS_TYPE_MOUNT_ACL:
6362+ return ccs_check_mount_acl(r, ptr);
6363+#ifdef CONFIG_CCSECURITY_MISC
6364+ case CCS_TYPE_ENV_ACL:
6365+ return ccs_check_env_acl(r, ptr);
6366+#endif
6367+#ifdef CONFIG_CCSECURITY_CAPABILITY
6368+ case CCS_TYPE_CAPABILITY_ACL:
6369+ return ccs_check_capability_acl(r, ptr);
6370+#endif
6371+#ifdef CONFIG_CCSECURITY_NETWORK
6372+ case CCS_TYPE_INET_ACL:
6373+ return ccs_check_inet_acl(r, ptr);
6374+ case CCS_TYPE_UNIX_ACL:
6375+ return ccs_check_unix_acl(r, ptr);
6376+#endif
6377+#ifdef CONFIG_CCSECURITY_IPC
6378+ case CCS_TYPE_SIGNAL_ACL:
6379+ return ccs_check_signal_acl(r, ptr);
6380+#endif
6381+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
6382+ case CCS_TYPE_MANUAL_TASK_ACL:
6383+ return ccs_check_task_acl(r, ptr);
6384+#endif
6385+ }
6386+ return true;
6387+}
6388+
6389+/**
6390+ * ccs_check_acl - Do permission check.
6391+ *
6392+ * @r: Pointer to "struct ccs_request_info".
6393+ *
6394+ * Returns 0 on success, negative value otherwise.
6395+ *
6396+ * Caller holds ccs_read_lock().
6397+ */
6398+int ccs_check_acl(struct ccs_request_info *r)
6399+{
6400+ const struct ccs_domain_info *domain = ccs_current_domain();
6401+ int error;
6402+ do {
6403+ struct ccs_acl_info *ptr;
6404+ const struct list_head *list = &domain->acl_info_list;
6405+ u16 i = 0;
6406+retry:
6407+ list_for_each_entry_srcu(ptr, list, list, &ccs_ss) {
6408+ if (!ccs_check_entry(r, ptr))
6409+ continue;
6410+ if (!ccs_condition(r, ptr->cond))
6411+ continue;
6412+ r->matched_acl = ptr;
6413+ r->granted = true;
6414+ ccs_audit_log(r);
6415+ return 0;
6416+ }
6417+ for (; i < CCS_MAX_ACL_GROUPS; i++) {
6418+ if (!test_bit(i, domain->group))
6419+ continue;
6420+ list = &domain->ns->acl_group[i++];
6421+ goto retry;
6422+ }
6423+ r->granted = false;
6424+ error = ccs_audit_log(r);
6425+ } while (error == CCS_RETRY_REQUEST &&
6426+ r->type != CCS_MAC_FILE_EXECUTE);
6427+ return error;
6428+}
6429+
6430+/**
6431+ * ccs_last_word - Get last component of a domainname.
6432+ *
6433+ * @name: Domainname to check.
6434+ *
6435+ * Returns the last word of @name.
6436+ */
6437+static const char *ccs_last_word(const char *name)
6438+{
6439+ const char *cp = strrchr(name, ' ');
6440+ if (cp)
6441+ return cp + 1;
6442+ return name;
6443+}
6444+
6445+/**
6446+ * ccs_scan_transition - Try to find specific domain transition type.
6447+ *
6448+ * @list: Pointer to "struct list_head".
6449+ * @domainname: The name of current domain.
6450+ * @program: The name of requested program.
6451+ * @last_name: The last component of @domainname.
6452+ * @type: One of values in "enum ccs_transition_type".
6453+ *
6454+ * Returns true if found one, false otherwise.
6455+ *
6456+ * Caller holds ccs_read_lock().
6457+ */
6458+static bool ccs_scan_transition(const struct list_head *list,
6459+ const struct ccs_path_info *domainname,
6460+ const struct ccs_path_info *program,
6461+ const char *last_name,
6462+ const enum ccs_transition_type type)
6463+{
6464+ const struct ccs_transition_control *ptr;
6465+ list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
6466+ if (ptr->head.is_deleted || ptr->type != type)
6467+ continue;
6468+ if (ptr->domainname) {
6469+ if (!ptr->is_last_name) {
6470+ if (ptr->domainname != domainname)
6471+ continue;
6472+ } else {
6473+ /*
6474+ * Use direct strcmp() since this is
6475+ * unlikely used.
6476+ */
6477+ if (strcmp(ptr->domainname->name, last_name))
6478+ continue;
6479+ }
6480+ }
6481+ if (ptr->program && ccs_pathcmp(ptr->program, program))
6482+ continue;
6483+ return true;
6484+ }
6485+ return false;
6486+}
6487+
6488+/**
6489+ * ccs_transition_type - Get domain transition type.
6490+ *
6491+ * @ns: Pointer to "struct ccs_policy_namespace".
6492+ * @domainname: The name of current domain.
6493+ * @program: The name of requested program.
6494+ *
6495+ * Returns CCS_TRANSITION_CONTROL_TRANSIT if executing @program causes domain
6496+ * transition across namespaces, CCS_TRANSITION_CONTROL_INITIALIZE if executing
6497+ * @program reinitializes domain transition within that namespace,
6498+ * CCS_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname ,
6499+ * others otherwise.
6500+ *
6501+ * Caller holds ccs_read_lock().
6502+ */
6503+static enum ccs_transition_type ccs_transition_type
6504+(const struct ccs_policy_namespace *ns, const struct ccs_path_info *domainname,
6505+ const struct ccs_path_info *program)
6506+{
6507+ const char *last_name = ccs_last_word(domainname->name);
6508+ enum ccs_transition_type type = CCS_TRANSITION_CONTROL_NO_RESET;
6509+ while (type < CCS_MAX_TRANSITION_TYPE) {
6510+ const struct list_head * const list =
6511+ &ns->policy_list[CCS_ID_TRANSITION_CONTROL];
6512+ if (!ccs_scan_transition(list, domainname, program, last_name,
6513+ type)) {
6514+ type++;
6515+ continue;
6516+ }
6517+ if (type != CCS_TRANSITION_CONTROL_NO_RESET &&
6518+ type != CCS_TRANSITION_CONTROL_NO_INITIALIZE)
6519+ break;
6520+ /*
6521+ * Do not check for reset_domain if no_reset_domain matched.
6522+ * Do not check for initialize_domain if no_initialize_domain
6523+ * matched.
6524+ */
6525+ type++;
6526+ type++;
6527+ }
6528+ return type;
6529+}
6530+
6531+/**
6532+ * ccs_find_next_domain - Find a domain.
6533+ *
6534+ * @ee: Pointer to "struct ccs_execve".
6535+ *
6536+ * Returns 0 on success, negative value otherwise.
6537+ *
6538+ * Caller holds ccs_read_lock().
6539+ */
6540+static int ccs_find_next_domain(struct ccs_execve *ee)
6541+{
6542+ struct ccs_request_info *r = &ee->r;
6543+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
6544+ const struct ccs_path_info *handler = ee->handler;
6545+#endif
6546+ struct ccs_domain_info *domain = NULL;
6547+ struct ccs_domain_info * const old_domain = ccs_current_domain();
6548+ struct linux_binprm *bprm = ee->bprm;
6549+ struct ccs_security *task = ccs_current_security();
6550+ const struct ccs_path_info *candidate;
6551+ struct ccs_path_info exename;
6552+ int retval;
6553+ bool reject_on_transition_failure = false;
6554+
6555+ /* Get symlink's pathname of program. */
6556+ retval = ccs_symlink_path(bprm->filename, &exename);
6557+ if (retval < 0)
6558+ return retval;
6559+
6560+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
6561+ if (handler) {
6562+ /* No permission check for execute handler. */
6563+ candidate = &exename;
6564+ if (ccs_pathcmp(candidate, handler)) {
6565+ /* Failed to verify execute handler. */
6566+ static u8 counter = 20;
6567+ if (counter) {
6568+ counter--;
6569+ printk(KERN_WARNING "Failed to verify: %s\n",
6570+ handler->name);
6571+ }
6572+ goto out;
6573+ }
6574+ } else
6575+#endif
6576+ {
6577+ struct ccs_aggregator *ptr;
6578+ struct list_head *list;
6579+retry:
6580+ /* Check 'aggregator' directive. */
6581+ candidate = &exename;
6582+ list = &old_domain->ns->policy_list[CCS_ID_AGGREGATOR];
6583+ list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
6584+ if (ptr->head.is_deleted ||
6585+ !ccs_path_matches_pattern(candidate,
6586+ ptr->original_name))
6587+ continue;
6588+ candidate = ptr->aggregated_name;
6589+ break;
6590+ }
6591+
6592+ /* Check execute permission. */
6593+ retval = ccs_execute_permission(r, candidate);
6594+ if (retval == CCS_RETRY_REQUEST)
6595+ goto retry;
6596+ if (retval < 0)
6597+ goto out;
6598+ /*
6599+ * To be able to specify domainnames with wildcards, use the
6600+ * pathname specified in the policy (which may contain
6601+ * wildcard) rather than the pathname passed to execve()
6602+ * (which never contains wildcard).
6603+ */
6604+ if (r->param.path.matched_path)
6605+ candidate = r->param.path.matched_path;
6606+ }
6607+ /*
6608+ * Check for domain transition preference if "file execute" matched.
6609+ * If preference is given, make do_execve() fail if domain transition
6610+ * has failed, for domain transition preference should be used with
6611+ * destination domain defined.
6612+ */
6613+ if (r->ee->transition) {
6614+ const char *domainname = r->ee->transition->name;
6615+ reject_on_transition_failure = true;
6616+ if (!strcmp(domainname, "keep"))
6617+ goto force_keep_domain;
6618+ if (!strcmp(domainname, "child"))
6619+ goto force_child_domain;
6620+ if (!strcmp(domainname, "reset"))
6621+ goto force_reset_domain;
6622+ if (!strcmp(domainname, "initialize"))
6623+ goto force_initialize_domain;
6624+ if (!strcmp(domainname, "parent")) {
6625+ char *cp;
6626+ strncpy(ee->tmp, old_domain->domainname->name,
6627+ CCS_EXEC_TMPSIZE - 1);
6628+ cp = strrchr(ee->tmp, ' ');
6629+ if (cp)
6630+ *cp = '\0';
6631+ } else if (*domainname == '<')
6632+ strncpy(ee->tmp, domainname, CCS_EXEC_TMPSIZE - 1);
6633+ else
6634+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
6635+ old_domain->domainname->name, domainname);
6636+ goto force_jump_domain;
6637+ }
6638+ /*
6639+ * No domain transition preference specified.
6640+ * Calculate domain to transit to.
6641+ */
6642+ switch (ccs_transition_type(old_domain->ns, old_domain->domainname,
6643+ candidate)) {
6644+ case CCS_TRANSITION_CONTROL_RESET:
6645+force_reset_domain:
6646+ /* Transit to the root of specified namespace. */
6647+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "<%s>",
6648+ candidate->name);
6649+ /*
6650+ * Make do_execve() fail if domain transition across namespaces
6651+ * has failed.
6652+ */
6653+ reject_on_transition_failure = true;
6654+ break;
6655+ case CCS_TRANSITION_CONTROL_INITIALIZE:
6656+force_initialize_domain:
6657+ /* Transit to the child of current namespace's root. */
6658+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
6659+ old_domain->ns->name, candidate->name);
6660+ break;
6661+ case CCS_TRANSITION_CONTROL_KEEP:
6662+force_keep_domain:
6663+ /* Keep current domain. */
6664+ domain = old_domain;
6665+ break;
6666+ default:
6667+ if (old_domain == &ccs_kernel_domain && !ccs_policy_loaded) {
6668+ /*
6669+ * Needn't to transit from kernel domain before
6670+ * starting /sbin/init. But transit from kernel domain
6671+ * if executing initializers because they might start
6672+ * before /sbin/init.
6673+ */
6674+ domain = old_domain;
6675+ break;
6676+ }
6677+force_child_domain:
6678+ /* Normal domain transition. */
6679+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
6680+ old_domain->domainname->name, candidate->name);
6681+ break;
6682+ }
6683+force_jump_domain:
6684+ /*
6685+ * Tell GC that I started execve().
6686+ * Also, tell open_exec() to check read permission.
6687+ */
6688+ task->ccs_flags |= CCS_TASK_IS_IN_EXECVE;
6689+ /*
6690+ * Make task->ccs_flags visible to GC before changing
6691+ * task->ccs_domain_info.
6692+ */
6693+ smp_wmb();
6694+ /*
6695+ * Proceed to the next domain in order to allow reaching via PID.
6696+ * It will be reverted if execve() failed. Reverting is not good.
6697+ * But it is better than being unable to reach via PID in interactive
6698+ * enforcing mode.
6699+ */
6700+ if (!domain)
6701+ domain = ccs_assign_domain(ee->tmp, true);
6702+ if (domain)
6703+ retval = 0;
6704+ else if (reject_on_transition_failure) {
6705+ printk(KERN_WARNING
6706+ "ERROR: Domain '%s' not ready.\n", ee->tmp);
6707+ retval = -ENOMEM;
6708+ } else if (r->mode == CCS_CONFIG_ENFORCING)
6709+ retval = -ENOMEM;
6710+ else {
6711+ retval = 0;
6712+ if (!old_domain->flags[CCS_DIF_TRANSITION_FAILED]) {
6713+ old_domain->flags[CCS_DIF_TRANSITION_FAILED] = true;
6714+ r->granted = false;
6715+ ccs_write_log(r, "%s",
6716+ ccs_dif[CCS_DIF_TRANSITION_FAILED]);
6717+ printk(KERN_WARNING
6718+ "ERROR: Domain '%s' not defined.\n", ee->tmp);
6719+ }
6720+ }
6721+out:
6722+ kfree(exename.name);
6723+ return retval;
6724+}
6725+
6726+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
6727+
6728+/**
6729+ * ccs_unescape - Unescape escaped string.
6730+ *
6731+ * @dest: String to unescape.
6732+ *
6733+ * Returns nothing.
6734+ */
6735+static void ccs_unescape(unsigned char *dest)
6736+{
6737+ unsigned char *src = dest;
6738+ unsigned char c;
6739+ unsigned char d;
6740+ unsigned char e;
6741+ while (1) {
6742+ c = *src++;
6743+ if (!c)
6744+ break;
6745+ if (c != '\\') {
6746+ *dest++ = c;
6747+ continue;
6748+ }
6749+ c = *src++;
6750+ if (c == '\\') {
6751+ *dest++ = c;
6752+ continue;
6753+ }
6754+ if (c < '0' || c > '3')
6755+ break;
6756+ d = *src++;
6757+ if (d < '0' || d > '7')
6758+ break;
6759+ e = *src++;
6760+ if (e < '0' || e > '7')
6761+ break;
6762+ *dest++ = ((c - '0') << 6) + ((d - '0') << 3) + (e - '0');
6763+ }
6764+ *dest = '\0';
6765+}
6766+
6767+/**
6768+ * ccs_try_alt_exec - Try to start execute handler.
6769+ *
6770+ * @ee: Pointer to "struct ccs_execve".
6771+ *
6772+ * Returns 0 on success, negative value otherwise.
6773+ */
6774+static int ccs_try_alt_exec(struct ccs_execve *ee)
6775+{
6776+ /*
6777+ * Contents of modified bprm.
6778+ * The envp[] in original bprm is moved to argv[] so that
6779+ * the alternatively executed program won't be affected by
6780+ * some dangerous environment variables like LD_PRELOAD.
6781+ *
6782+ * modified bprm->argc
6783+ * = original bprm->argc + original bprm->envc + 7
6784+ * modified bprm->envc
6785+ * = 0
6786+ *
6787+ * modified bprm->argv[0]
6788+ * = the program's name specified by *_execute_handler
6789+ * modified bprm->argv[1]
6790+ * = ccs_current_domain()->domainname->name
6791+ * modified bprm->argv[2]
6792+ * = the current process's name
6793+ * modified bprm->argv[3]
6794+ * = the current process's information (e.g. uid/gid).
6795+ * modified bprm->argv[4]
6796+ * = original bprm->filename
6797+ * modified bprm->argv[5]
6798+ * = original bprm->argc in string expression
6799+ * modified bprm->argv[6]
6800+ * = original bprm->envc in string expression
6801+ * modified bprm->argv[7]
6802+ * = original bprm->argv[0]
6803+ * ...
6804+ * modified bprm->argv[bprm->argc + 6]
6805+ * = original bprm->argv[bprm->argc - 1]
6806+ * modified bprm->argv[bprm->argc + 7]
6807+ * = original bprm->envp[0]
6808+ * ...
6809+ * modified bprm->argv[bprm->envc + bprm->argc + 6]
6810+ * = original bprm->envp[bprm->envc - 1]
6811+ */
6812+ struct linux_binprm *bprm = ee->bprm;
6813+ struct file *filp;
6814+ int retval;
6815+ const int original_argc = bprm->argc;
6816+ const int original_envc = bprm->envc;
6817+
6818+ /* Close the requested program's dentry. */
6819+ ee->obj.path1.dentry = NULL;
6820+ ee->obj.path1.mnt = NULL;
6821+ ee->obj.stat_valid[CCS_PATH1] = false;
6822+ ee->obj.stat_valid[CCS_PATH1_PARENT] = false;
6823+ ee->obj.validate_done = false;
6824+ allow_write_access(bprm->file);
6825+ fput(bprm->file);
6826+ bprm->file = NULL;
6827+
6828+ /* Invalidate page dump cache. */
6829+ ee->dump.page = NULL;
6830+
6831+ /* Move envp[] to argv[] */
6832+ bprm->argc += bprm->envc;
6833+ bprm->envc = 0;
6834+
6835+ /* Set argv[6] */
6836+ {
6837+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_envc);
6838+ retval = ccs_copy_argv(ee->tmp, bprm);
6839+ if (retval < 0)
6840+ goto out;
6841+ }
6842+
6843+ /* Set argv[5] */
6844+ {
6845+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_argc);
6846+ retval = ccs_copy_argv(ee->tmp, bprm);
6847+ if (retval < 0)
6848+ goto out;
6849+ }
6850+
6851+ /* Set argv[4] */
6852+ {
6853+ retval = ccs_copy_argv(bprm->filename, bprm);
6854+ if (retval < 0)
6855+ goto out;
6856+ }
6857+
6858+ /* Set argv[3] */
6859+ {
6860+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
6861+ /*
6862+ * Pass uid/gid seen from current user namespace, for these
6863+ * values are used by programs in current user namespace in
6864+ * order to decide whether to execve() or not (rather than by
6865+ * auditing daemon in init's user namespace).
6866+ */
6867+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
6868+ "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
6869+ "sgid=%d fsuid=%d fsgid=%d", ccs_sys_getpid(),
6870+ __kuid_val(current_uid()), __kgid_val(current_gid()),
6871+ __kuid_val(current_euid()),
6872+ __kgid_val(current_egid()),
6873+ __kuid_val(current_suid()),
6874+ __kgid_val(current_sgid()),
6875+ __kuid_val(current_fsuid()),
6876+ __kgid_val(current_fsgid()));
6877+#else
6878+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
6879+ "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
6880+ "sgid=%d fsuid=%d fsgid=%d", ccs_sys_getpid(),
6881+ current_uid(), current_gid(), current_euid(),
6882+ current_egid(), current_suid(), current_sgid(),
6883+ current_fsuid(), current_fsgid());
6884+#endif
6885+ retval = ccs_copy_argv(ee->tmp, bprm);
6886+ if (retval < 0)
6887+ goto out;
6888+ }
6889+
6890+ /* Set argv[2] */
6891+ {
6892+ char *exe = (char *) ccs_get_exe();
6893+ if (exe) {
6894+ retval = ccs_copy_argv(exe, bprm);
6895+ kfree(exe);
6896+ } else {
6897+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
6898+ retval = ccs_copy_argv("<unknown>", bprm);
6899+#else
6900+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "<unknown>");
6901+ retval = ccs_copy_argv(ee->tmp, bprm);
6902+#endif
6903+ }
6904+ if (retval < 0)
6905+ goto out;
6906+ }
6907+
6908+ /* Set argv[1] */
6909+ {
6910+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
6911+ retval = ccs_copy_argv(ccs_current_domain()->domainname->name,
6912+ bprm);
6913+#else
6914+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s",
6915+ ccs_current_domain()->domainname->name);
6916+ retval = ccs_copy_argv(ee->tmp, bprm);
6917+#endif
6918+ if (retval < 0)
6919+ goto out;
6920+ }
6921+
6922+ /* Set argv[0] */
6923+ {
6924+ struct path root;
6925+ char *cp;
6926+ int root_len;
6927+ int handler_len;
6928+ get_fs_root(current->fs, &root);
6929+ cp = ccs_realpath(&root);
6930+ path_put(&root);
6931+ if (!cp) {
6932+ retval = -ENOMEM;
6933+ goto out;
6934+ }
6935+ root_len = strlen(cp);
6936+ retval = strncmp(ee->handler->name, cp, root_len);
6937+ root_len--;
6938+ kfree(cp);
6939+ if (retval) {
6940+ retval = -ENOENT;
6941+ goto out;
6942+ }
6943+ handler_len = ee->handler->total_len + 1;
6944+ cp = kmalloc(handler_len, CCS_GFP_FLAGS);
6945+ if (!cp) {
6946+ retval = -ENOMEM;
6947+ goto out;
6948+ }
6949+ /* ee->handler_path is released by ccs_finish_execve(). */
6950+ ee->handler_path = cp;
6951+ /* Adjust root directory for open_exec(). */
6952+ memmove(cp, ee->handler->name + root_len,
6953+ handler_len - root_len);
6954+ ccs_unescape(cp);
6955+ retval = -ENOENT;
6956+ if (*cp != '/')
6957+ goto out;
6958+ retval = ccs_copy_argv(cp, bprm);
6959+ if (retval < 0)
6960+ goto out;
6961+ }
6962+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
6963+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
6964+ bprm->argv_len = bprm->exec - bprm->p;
6965+#endif
6966+#endif
6967+
6968+ /*
6969+ * OK, now restart the process with execute handler program's dentry.
6970+ */
6971+ filp = open_exec(ee->handler_path);
6972+ if (IS_ERR(filp)) {
6973+ retval = PTR_ERR(filp);
6974+ goto out;
6975+ }
6976+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
6977+ ee->obj.path1 = filp->f_path;
6978+#else
6979+ ee->obj.path1.dentry = filp->f_dentry;
6980+ ee->obj.path1.mnt = filp->f_vfsmnt;
6981+#endif
6982+ bprm->file = filp;
6983+ bprm->filename = ee->handler_path;
6984+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
6985+ bprm->interp = bprm->filename;
6986+#endif
6987+ retval = prepare_binprm(bprm);
6988+ if (retval < 0)
6989+ goto out;
6990+ ee->r.dont_sleep_on_enforce_error = true;
6991+ retval = ccs_find_next_domain(ee);
6992+ ee->r.dont_sleep_on_enforce_error = false;
6993+out:
6994+ return retval;
6995+}
6996+
6997+/**
6998+ * ccs_find_execute_handler - Find an execute handler.
6999+ *
7000+ * @ee: Pointer to "struct ccs_execve".
7001+ * @type: Type of execute handler.
7002+ *
7003+ * Returns true if found, false otherwise.
7004+ *
7005+ * Caller holds ccs_read_lock().
7006+ */
7007+static bool ccs_find_execute_handler(struct ccs_execve *ee, const u8 type)
7008+{
7009+ struct ccs_request_info *r = &ee->r;
7010+ /*
7011+ * To avoid infinite execute handler loop, don't use execute handler
7012+ * if the current process is marked as execute handler.
7013+ */
7014+ if (ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)
7015+ return false;
7016+ r->param_type = type;
7017+ ccs_check_acl(r);
7018+ if (!r->granted)
7019+ return false;
7020+ ee->handler = container_of(r->matched_acl, struct ccs_handler_acl,
7021+ head)->handler;
7022+ ee->transition = r->matched_acl && r->matched_acl->cond &&
7023+ r->matched_acl->cond->exec_transit ?
7024+ r->matched_acl->cond->transit : NULL;
7025+ return true;
7026+}
7027+
7028+#endif
7029+
7030+#ifdef CONFIG_MMU
7031+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
7032+#define CCS_BPRM_MMU
7033+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3
7034+#define CCS_BPRM_MMU
7035+#elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2
7036+#define CCS_BPRM_MMU
7037+#endif
7038+#endif
7039+
7040+/**
7041+ * ccs_dump_page - Dump a page to buffer.
7042+ *
7043+ * @bprm: Pointer to "struct linux_binprm".
7044+ * @pos: Location to dump.
7045+ * @dump: Poiner to "struct ccs_page_dump".
7046+ *
7047+ * Returns true on success, false otherwise.
7048+ */
7049+bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
7050+ struct ccs_page_dump *dump)
7051+{
7052+ struct page *page;
7053+ /* dump->data is released by ccs_start_execve(). */
7054+ if (!dump->data) {
7055+ dump->data = kzalloc(PAGE_SIZE, CCS_GFP_FLAGS);
7056+ if (!dump->data)
7057+ return false;
7058+ }
7059+ /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
7060+#ifdef CCS_BPRM_MMU
7061+ if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
7062+ return false;
7063+#else
7064+ page = bprm->page[pos / PAGE_SIZE];
7065+#endif
7066+ if (page != dump->page) {
7067+ const unsigned int offset = pos % PAGE_SIZE;
7068+ /*
7069+ * Maybe kmap()/kunmap() should be used here.
7070+ * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
7071+ * So do I.
7072+ */
7073+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
7074+ char *kaddr = kmap_atomic(page);
7075+#else
7076+ char *kaddr = kmap_atomic(page, KM_USER0);
7077+#endif
7078+ dump->page = page;
7079+ memcpy(dump->data + offset, kaddr + offset,
7080+ PAGE_SIZE - offset);
7081+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
7082+ kunmap_atomic(kaddr);
7083+#else
7084+ kunmap_atomic(kaddr, KM_USER0);
7085+#endif
7086+ }
7087+ /* Same with put_arg_page(page) in fs/exec.c */
7088+#ifdef CCS_BPRM_MMU
7089+ put_page(page);
7090+#endif
7091+ return true;
7092+}
7093+
7094+/**
7095+ * ccs_start_execve - Prepare for execve() operation.
7096+ *
7097+ * @bprm: Pointer to "struct linux_binprm".
7098+ * @eep: Pointer to "struct ccs_execve *".
7099+ *
7100+ * Returns 0 on success, negative value otherwise.
7101+ */
7102+static int ccs_start_execve(struct linux_binprm *bprm,
7103+ struct ccs_execve **eep)
7104+{
7105+ int retval;
7106+ struct ccs_security *task = ccs_current_security();
7107+ struct ccs_execve *ee;
7108+ int idx;
7109+ *eep = NULL;
7110+ ee = kzalloc(sizeof(*ee), CCS_GFP_FLAGS);
7111+ if (!ee)
7112+ return -ENOMEM;
7113+ ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
7114+ if (!ee->tmp) {
7115+ kfree(ee);
7116+ return -ENOMEM;
7117+ }
7118+ idx = ccs_read_lock();
7119+ /* ee->dump->data is allocated by ccs_dump_page(). */
7120+ ee->previous_domain = task->ccs_domain_info;
7121+ /* Clear manager flag. */
7122+ task->ccs_flags &= ~CCS_TASK_IS_MANAGER;
7123+ *eep = ee;
7124+ ccs_init_request_info(&ee->r, CCS_MAC_FILE_EXECUTE);
7125+ ee->r.ee = ee;
7126+ ee->bprm = bprm;
7127+ ee->r.obj = &ee->obj;
7128+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
7129+ ee->obj.path1 = bprm->file->f_path;
7130+#else
7131+ ee->obj.path1.dentry = bprm->file->f_dentry;
7132+ ee->obj.path1.mnt = bprm->file->f_vfsmnt;
7133+#endif
7134+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
7135+ /*
7136+ * No need to call ccs_environ() for execute handler because envp[] is
7137+ * moved to argv[].
7138+ */
7139+ if (ccs_find_execute_handler(ee, CCS_TYPE_AUTO_EXECUTE_HANDLER)) {
7140+ retval = ccs_try_alt_exec(ee);
7141+ goto done;
7142+ }
7143+#endif
7144+ retval = ccs_find_next_domain(ee);
7145+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
7146+ if (retval == -EPERM &&
7147+ ccs_find_execute_handler(ee, CCS_TYPE_DENIED_EXECUTE_HANDLER)) {
7148+ retval = ccs_try_alt_exec(ee);
7149+ goto done;
7150+ }
7151+#endif
7152+#ifdef CONFIG_CCSECURITY_MISC
7153+ if (!retval)
7154+ retval = ccs_environ(ee);
7155+#endif
7156+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
7157+done:
7158+#endif
7159+ ccs_read_unlock(idx);
7160+ kfree(ee->tmp);
7161+ ee->tmp = NULL;
7162+ kfree(ee->dump.data);
7163+ ee->dump.data = NULL;
7164+ return retval;
7165+}
7166+
7167+/**
7168+ * ccs_finish_execve - Clean up execve() operation.
7169+ *
7170+ * @retval: Return code of an execve() operation.
7171+ * @ee: Pointer to "struct ccs_execve".
7172+ *
7173+ * Returns nothing.
7174+ */
7175+static void ccs_finish_execve(int retval, struct ccs_execve *ee)
7176+{
7177+ struct ccs_security *task = ccs_current_security();
7178+ if (!ee)
7179+ return;
7180+ if (retval < 0) {
7181+ task->ccs_domain_info = ee->previous_domain;
7182+ /*
7183+ * Make task->ccs_domain_info visible to GC before changing
7184+ * task->ccs_flags.
7185+ */
7186+ smp_wmb();
7187+ } else {
7188+ /* Mark the current process as execute handler. */
7189+ if (ee->handler)
7190+ task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
7191+ /* Mark the current process as normal process. */
7192+ else
7193+ task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
7194+ }
7195+ /* Tell GC that I finished execve(). */
7196+ task->ccs_flags &= ~CCS_TASK_IS_IN_EXECVE;
7197+ kfree(ee->handler_path);
7198+ kfree(ee);
7199+}
7200+
7201+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
7202+
7203+/**
7204+ * __ccs_search_binary_handler - Main routine for do_execve().
7205+ *
7206+ * @bprm: Pointer to "struct linux_binprm".
7207+ *
7208+ * Returns 0 on success, negative value otherwise.
7209+ *
7210+ * Performs permission checks for do_execve() and domain transition.
7211+ * Domain transition by "struct ccs_domain_transition_control" and
7212+ * "auto_domain_transition=" parameter of "struct ccs_condition" are reverted
7213+ * if do_execve() failed.
7214+ * Garbage collector does not remove "struct ccs_domain_info" from
7215+ * ccs_domain_list nor kfree("struct ccs_domain_info") if the current thread is
7216+ * marked as CCS_TASK_IS_IN_EXECVE.
7217+ */
7218+static int __ccs_search_binary_handler(struct linux_binprm *bprm)
7219+{
7220+ struct ccs_execve *ee;
7221+ int retval;
7222+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
7223+ if (!ccs_policy_loaded)
7224+ ccsecurity_exports.load_policy(bprm->filename);
7225+#endif
7226+ retval = ccs_start_execve(bprm, &ee);
7227+ if (!retval)
7228+ retval = search_binary_handler(bprm);
7229+ ccs_finish_execve(retval, ee);
7230+ return retval;
7231+}
7232+
7233+#else
7234+
7235+/**
7236+ * __ccs_search_binary_handler - Main routine for do_execve().
7237+ *
7238+ * @bprm: Pointer to "struct linux_binprm".
7239+ * @regs: Pointer to "struct pt_regs".
7240+ *
7241+ * Returns 0 on success, negative value otherwise.
7242+ *
7243+ * Performs permission checks for do_execve() and domain transition.
7244+ * Domain transition by "struct ccs_domain_transition_control" and
7245+ * "auto_domain_transition=" parameter of "struct ccs_condition" are reverted
7246+ * if do_execve() failed.
7247+ * Garbage collector does not remove "struct ccs_domain_info" from
7248+ * ccs_domain_list nor kfree("struct ccs_domain_info") if the current thread is
7249+ * marked as CCS_TASK_IS_IN_EXECVE.
7250+ */
7251+static int __ccs_search_binary_handler(struct linux_binprm *bprm,
7252+ struct pt_regs *regs)
7253+{
7254+ struct ccs_execve *ee;
7255+ int retval;
7256+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
7257+ if (!ccs_policy_loaded)
7258+ ccsecurity_exports.load_policy(bprm->filename);
7259+#endif
7260+ retval = ccs_start_execve(bprm, &ee);
7261+ if (!retval)
7262+ retval = search_binary_handler(bprm, regs);
7263+ ccs_finish_execve(retval, ee);
7264+ return retval;
7265+}
7266+
7267+#endif
7268+
7269+/**
7270+ * ccs_permission_init - Register permission check hooks.
7271+ *
7272+ * Returns nothing.
7273+ */
7274+void __init ccs_permission_init(void)
7275+{
7276+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
7277+ ccsecurity_ops.save_open_mode = __ccs_save_open_mode;
7278+ ccsecurity_ops.clear_open_mode = __ccs_clear_open_mode;
7279+ ccsecurity_ops.open_permission = __ccs_open_permission;
7280+#else
7281+ ccsecurity_ops.open_permission = ccs_new_open_permission;
7282+#endif
7283+ ccsecurity_ops.fcntl_permission = __ccs_fcntl_permission;
7284+ ccsecurity_ops.ioctl_permission = __ccs_ioctl_permission;
7285+ ccsecurity_ops.chmod_permission = __ccs_chmod_permission;
7286+ ccsecurity_ops.chown_permission = __ccs_chown_permission;
7287+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
7288+ ccsecurity_ops.getattr_permission = __ccs_getattr_permission;
7289+#endif
7290+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
7291+ ccsecurity_ops.pivot_root_permission = __ccs_pivot_root_permission;
7292+ ccsecurity_ops.chroot_permission = __ccs_chroot_permission;
7293+#else
7294+ ccsecurity_ops.pivot_root_permission = ccs_old_pivot_root_permission;
7295+ ccsecurity_ops.chroot_permission = ccs_old_chroot_permission;
7296+#endif
7297+ ccsecurity_ops.umount_permission = __ccs_umount_permission;
7298+ ccsecurity_ops.mknod_permission = __ccs_mknod_permission;
7299+ ccsecurity_ops.mkdir_permission = __ccs_mkdir_permission;
7300+ ccsecurity_ops.rmdir_permission = __ccs_rmdir_permission;
7301+ ccsecurity_ops.unlink_permission = __ccs_unlink_permission;
7302+ ccsecurity_ops.symlink_permission = __ccs_symlink_permission;
7303+ ccsecurity_ops.truncate_permission = __ccs_truncate_permission;
7304+ ccsecurity_ops.rename_permission = __ccs_rename_permission;
7305+ ccsecurity_ops.link_permission = __ccs_link_permission;
7306+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
7307+ ccsecurity_ops.open_exec_permission = __ccs_open_exec_permission;
7308+ ccsecurity_ops.uselib_permission = __ccs_uselib_permission;
7309+#endif
7310+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
7311+ ccsecurity_ops.parse_table = __ccs_parse_table;
7312+#endif
7313+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
7314+ ccsecurity_ops.mount_permission = __ccs_mount_permission;
7315+#else
7316+ ccsecurity_ops.mount_permission = ccs_old_mount_permission;
7317+#endif
7318+#ifdef CONFIG_CCSECURITY_CAPABILITY
7319+ ccsecurity_ops.socket_create_permission =
7320+ __ccs_socket_create_permission;
7321+#endif
7322+#ifdef CONFIG_CCSECURITY_NETWORK
7323+ ccsecurity_ops.socket_listen_permission =
7324+ __ccs_socket_listen_permission;
7325+ ccsecurity_ops.socket_connect_permission =
7326+ __ccs_socket_connect_permission;
7327+ ccsecurity_ops.socket_bind_permission = __ccs_socket_bind_permission;
7328+ ccsecurity_ops.socket_post_accept_permission =
7329+ __ccs_socket_post_accept_permission;
7330+ ccsecurity_ops.socket_sendmsg_permission =
7331+ __ccs_socket_sendmsg_permission;
7332+#endif
7333+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
7334+ ccsecurity_ops.socket_post_recvmsg_permission =
7335+ __ccs_socket_post_recvmsg_permission;
7336+#endif
7337+#ifdef CONFIG_CCSECURITY_IPC
7338+ ccsecurity_ops.kill_permission = ccs_signal_acl;
7339+ ccsecurity_ops.tgkill_permission = ccs_signal_acl0;
7340+ ccsecurity_ops.tkill_permission = ccs_signal_acl;
7341+ ccsecurity_ops.sigqueue_permission = ccs_signal_acl;
7342+ ccsecurity_ops.tgsigqueue_permission = ccs_signal_acl0;
7343+#endif
7344+#ifdef CONFIG_CCSECURITY_CAPABILITY
7345+ ccsecurity_ops.capable = __ccs_capable;
7346+ ccsecurity_ops.ptrace_permission = __ccs_ptrace_permission;
7347+#endif
7348+ ccsecurity_ops.search_binary_handler = __ccs_search_binary_handler;
7349+}
7350+
7351+/**
7352+ * ccs_kern_path - Wrapper for kern_path().
7353+ *
7354+ * @pathname: Pathname to resolve. Maybe NULL.
7355+ * @flags: Lookup flags.
7356+ * @path: Pointer to "struct path".
7357+ *
7358+ * Returns 0 on success, negative value otherwise.
7359+ */
7360+static int ccs_kern_path(const char *pathname, int flags, struct path *path)
7361+{
7362+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
7363+ if (!pathname || kern_path(pathname, flags, path))
7364+ return -ENOENT;
7365+#else
7366+ struct nameidata nd;
7367+ if (!pathname || path_lookup(pathname, flags, &nd))
7368+ return -ENOENT;
7369+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
7370+ *path = nd.path;
7371+#else
7372+ path->dentry = nd.dentry;
7373+ path->mnt = nd.mnt;
7374+#endif
7375+#endif
7376+ return 0;
7377+}
7378+
7379+/**
7380+ * ccs_get_path - Get dentry/vfsmmount of a pathname.
7381+ *
7382+ * @pathname: The pathname to solve. Maybe NULL.
7383+ * @path: Pointer to "struct path".
7384+ *
7385+ * Returns 0 on success, negative value otherwise.
7386+ */
7387+static int ccs_get_path(const char *pathname, struct path *path)
7388+{
7389+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
7390+ return ccs_kern_path(pathname, LOOKUP_FOLLOW, path);
7391+#else
7392+ return ccs_kern_path(pathname, LOOKUP_FOLLOW | LOOKUP_POSITIVE, path);
7393+#endif
7394+}
7395+
7396+/**
7397+ * ccs_symlink_path - Get symlink's pathname.
7398+ *
7399+ * @pathname: The pathname to solve. Maybe NULL.
7400+ * @name: Pointer to "struct ccs_path_info".
7401+ *
7402+ * Returns 0 on success, negative value otherwise.
7403+ *
7404+ * This function uses kzalloc(), so caller must kfree() if this function
7405+ * didn't return NULL.
7406+ */
7407+static int ccs_symlink_path(const char *pathname, struct ccs_path_info *name)
7408+{
7409+ char *buf;
7410+ struct path path;
7411+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
7412+ if (ccs_kern_path(pathname, 0, &path))
7413+ return -ENOENT;
7414+#else
7415+ if (ccs_kern_path(pathname, LOOKUP_POSITIVE, &path))
7416+ return -ENOENT;
7417+#endif
7418+ buf = ccs_realpath(&path);
7419+ path_put(&path);
7420+ if (buf) {
7421+ name->name = buf;
7422+ ccs_fill_path_info(name);
7423+ return 0;
7424+ }
7425+ return -ENOMEM;
7426+}
7427+
7428+/**
7429+ * ccs_check_mount_acl - Check permission for path path path number operation.
7430+ *
7431+ * @r: Pointer to "struct ccs_request_info".
7432+ * @ptr: Pointer to "struct ccs_acl_info".
7433+ *
7434+ * Returns true if granted, false otherwise.
7435+ */
7436+static bool ccs_check_mount_acl(struct ccs_request_info *r,
7437+ const struct ccs_acl_info *ptr)
7438+{
7439+ const struct ccs_mount_acl *acl =
7440+ container_of(ptr, typeof(*acl), head);
7441+ return ccs_compare_number_union(r->param.mount.flags, &acl->flags) &&
7442+ ccs_compare_name_union(r->param.mount.type, &acl->fs_type) &&
7443+ ccs_compare_name_union(r->param.mount.dir, &acl->dir_name) &&
7444+ (!r->param.mount.need_dev ||
7445+ ccs_compare_name_union(r->param.mount.dev, &acl->dev_name));
7446+}
7447+
7448+/**
7449+ * ccs_mount_acl - Check permission for mount() operation.
7450+ *
7451+ * @r: Pointer to "struct ccs_request_info".
7452+ * @dev_name: Name of device file. Maybe NULL.
7453+ * @dir: Pointer to "struct path".
7454+ * @type: Name of filesystem type.
7455+ * @flags: Mount options.
7456+ *
7457+ * Returns 0 on success, negative value otherwise.
7458+ *
7459+ * Caller holds ccs_read_lock().
7460+ */
7461+static int ccs_mount_acl(struct ccs_request_info *r, const char *dev_name,
7462+ struct path *dir, const char *type,
7463+ unsigned long flags)
7464+{
7465+ struct ccs_obj_info obj = { };
7466+ struct file_system_type *fstype = NULL;
7467+ const char *requested_type = NULL;
7468+ const char *requested_dir_name = NULL;
7469+ const char *requested_dev_name = NULL;
7470+ struct ccs_path_info rtype;
7471+ struct ccs_path_info rdev;
7472+ struct ccs_path_info rdir;
7473+ int need_dev = 0;
7474+ int error = -ENOMEM;
7475+ r->obj = &obj;
7476+
7477+ /* Get fstype. */
7478+ requested_type = ccs_encode(type);
7479+ if (!requested_type)
7480+ goto out;
7481+ rtype.name = requested_type;
7482+ ccs_fill_path_info(&rtype);
7483+
7484+ /* Get mount point. */
7485+ obj.path2 = *dir;
7486+ requested_dir_name = ccs_realpath(dir);
7487+ if (!requested_dir_name) {
7488+ error = -ENOMEM;
7489+ goto out;
7490+ }
7491+ rdir.name = requested_dir_name;
7492+ ccs_fill_path_info(&rdir);
7493+
7494+ /* Compare fs name. */
7495+ if (type == ccs_mounts[CCS_MOUNT_REMOUNT]) {
7496+ /* dev_name is ignored. */
7497+ } else if (type == ccs_mounts[CCS_MOUNT_MAKE_UNBINDABLE] ||
7498+ type == ccs_mounts[CCS_MOUNT_MAKE_PRIVATE] ||
7499+ type == ccs_mounts[CCS_MOUNT_MAKE_SLAVE] ||
7500+ type == ccs_mounts[CCS_MOUNT_MAKE_SHARED]) {
7501+ /* dev_name is ignored. */
7502+ } else if (type == ccs_mounts[CCS_MOUNT_BIND] ||
7503+ type == ccs_mounts[CCS_MOUNT_MOVE]) {
7504+ need_dev = -1; /* dev_name is a directory */
7505+ } else {
7506+ fstype = get_fs_type(type);
7507+ if (!fstype) {
7508+ error = -ENODEV;
7509+ goto out;
7510+ }
7511+ if (fstype->fs_flags & FS_REQUIRES_DEV)
7512+ /* dev_name is a block device file. */
7513+ need_dev = 1;
7514+ }
7515+ if (need_dev) {
7516+ /* Get mount point or device file. */
7517+ if (ccs_get_path(dev_name, &obj.path1)) {
7518+ error = -ENOENT;
7519+ goto out;
7520+ }
7521+ requested_dev_name = ccs_realpath(&obj.path1);
7522+ if (!requested_dev_name) {
7523+ error = -ENOENT;
7524+ goto out;
7525+ }
7526+ } else {
7527+ /* Map dev_name to "<NULL>" if no dev_name given. */
7528+ if (!dev_name)
7529+ dev_name = "<NULL>";
7530+ requested_dev_name = ccs_encode(dev_name);
7531+ if (!requested_dev_name) {
7532+ error = -ENOMEM;
7533+ goto out;
7534+ }
7535+ }
7536+ rdev.name = requested_dev_name;
7537+ ccs_fill_path_info(&rdev);
7538+ r->param_type = CCS_TYPE_MOUNT_ACL;
7539+ r->param.mount.need_dev = need_dev;
7540+ r->param.mount.dev = &rdev;
7541+ r->param.mount.dir = &rdir;
7542+ r->param.mount.type = &rtype;
7543+ r->param.mount.flags = flags;
7544+ error = ccs_check_acl(r);
7545+out:
7546+ kfree(requested_dev_name);
7547+ kfree(requested_dir_name);
7548+ if (fstype)
7549+ ccs_put_filesystem(fstype);
7550+ kfree(requested_type);
7551+ /* Drop refcount obtained by ccs_get_path(). */
7552+ if (obj.path1.dentry)
7553+ path_put(&obj.path1);
7554+ return error;
7555+}
7556+
7557+/**
7558+ * __ccs_mount_permission - Check permission for mount() operation.
7559+ *
7560+ * @dev_name: Name of device file. Maybe NULL.
7561+ * @path: Pointer to "struct path".
7562+ * @type: Name of filesystem type. Maybe NULL.
7563+ * @flags: Mount options.
7564+ * @data_page: Optional data. Maybe NULL.
7565+ *
7566+ * Returns 0 on success, negative value otherwise.
7567+ */
7568+static int __ccs_mount_permission(const char *dev_name, struct path *path,
7569+ const char *type, unsigned long flags,
7570+ void *data_page)
7571+{
7572+ struct ccs_request_info r;
7573+ int error = 0;
7574+ int idx;
7575+ if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
7576+ flags &= ~MS_MGC_MSK;
7577+ if (flags & MS_REMOUNT) {
7578+ type = ccs_mounts[CCS_MOUNT_REMOUNT];
7579+ flags &= ~MS_REMOUNT;
7580+ } else if (flags & MS_BIND) {
7581+ type = ccs_mounts[CCS_MOUNT_BIND];
7582+ flags &= ~MS_BIND;
7583+ } else if (flags & MS_SHARED) {
7584+ if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
7585+ return -EINVAL;
7586+ type = ccs_mounts[CCS_MOUNT_MAKE_SHARED];
7587+ flags &= ~MS_SHARED;
7588+ } else if (flags & MS_PRIVATE) {
7589+ if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
7590+ return -EINVAL;
7591+ type = ccs_mounts[CCS_MOUNT_MAKE_PRIVATE];
7592+ flags &= ~MS_PRIVATE;
7593+ } else if (flags & MS_SLAVE) {
7594+ if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
7595+ return -EINVAL;
7596+ type = ccs_mounts[CCS_MOUNT_MAKE_SLAVE];
7597+ flags &= ~MS_SLAVE;
7598+ } else if (flags & MS_UNBINDABLE) {
7599+ if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
7600+ return -EINVAL;
7601+ type = ccs_mounts[CCS_MOUNT_MAKE_UNBINDABLE];
7602+ flags &= ~MS_UNBINDABLE;
7603+ } else if (flags & MS_MOVE) {
7604+ type = ccs_mounts[CCS_MOUNT_MOVE];
7605+ flags &= ~MS_MOVE;
7606+ }
7607+ if (!type)
7608+ type = "<NULL>";
7609+ idx = ccs_read_lock();
7610+ if (ccs_init_request_info(&r, CCS_MAC_FILE_MOUNT)
7611+ != CCS_CONFIG_DISABLED)
7612+ error = ccs_mount_acl(&r, dev_name, path, type, flags);
7613+ ccs_read_unlock(idx);
7614+ return error;
7615+}
7616+
7617+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
7618+
7619+/**
7620+ * ccs_old_mount_permission - Check permission for mount() operation.
7621+ *
7622+ * @dev_name: Name of device file.
7623+ * @nd: Pointer to "struct nameidata".
7624+ * @type: Name of filesystem type. Maybe NULL.
7625+ * @flags: Mount options.
7626+ * @data_page: Optional data. Maybe NULL.
7627+ *
7628+ * Returns 0 on success, negative value otherwise.
7629+ */
7630+static int ccs_old_mount_permission(const char *dev_name, struct nameidata *nd,
7631+ const char *type, unsigned long flags,
7632+ void *data_page)
7633+{
7634+ struct path path = { nd->mnt, nd->dentry };
7635+ return __ccs_mount_permission(dev_name, &path, type, flags, data_page);
7636+}
7637+
7638+#endif
7639+
7640+/**
7641+ * ccs_compare_number_union - Check whether a value matches "struct ccs_number_union" or not.
7642+ *
7643+ * @value: Number to check.
7644+ * @ptr: Pointer to "struct ccs_number_union".
7645+ *
7646+ * Returns true if @value matches @ptr, false otherwise.
7647+ */
7648+static bool ccs_compare_number_union(const unsigned long value,
7649+ const struct ccs_number_union *ptr)
7650+{
7651+ if (ptr->group)
7652+ return ccs_number_matches_group(value, value, ptr->group);
7653+ return value >= ptr->values[0] && value <= ptr->values[1];
7654+}
7655+
7656+/**
7657+ * ccs_compare_name_union - Check whether a name matches "struct ccs_name_union" or not.
7658+ *
7659+ * @name: Pointer to "struct ccs_path_info".
7660+ * @ptr: Pointer to "struct ccs_name_union".
7661+ *
7662+ * Returns "struct ccs_path_info" if @name matches @ptr, NULL otherwise.
7663+ */
7664+static const struct ccs_path_info *ccs_compare_name_union
7665+(const struct ccs_path_info *name, const struct ccs_name_union *ptr)
7666+{
7667+ if (ptr->group)
7668+ return ccs_path_matches_group(name, ptr->group);
7669+ if (ccs_path_matches_pattern(name, ptr->filename))
7670+ return ptr->filename;
7671+ return NULL;
7672+}
7673+
7674+/**
7675+ * ccs_add_slash - Add trailing '/' if needed.
7676+ *
7677+ * @buf: Pointer to "struct ccs_path_info".
7678+ *
7679+ * Returns nothing.
7680+ *
7681+ * @buf must be generated by ccs_encode() because this function does not
7682+ * allocate memory for adding '/'.
7683+ */
7684+static void ccs_add_slash(struct ccs_path_info *buf)
7685+{
7686+ if (buf->is_dir)
7687+ return;
7688+ /* This is OK because ccs_encode() reserves space for appending "/". */
7689+ strcat((char *) buf->name, "/");
7690+ ccs_fill_path_info(buf);
7691+}
7692+
7693+/**
7694+ * ccs_get_realpath - Get realpath.
7695+ *
7696+ * @buf: Pointer to "struct ccs_path_info".
7697+ * @path: Pointer to "struct path". @path->mnt may be NULL.
7698+ *
7699+ * Returns true on success, false otherwise.
7700+ */
7701+static bool ccs_get_realpath(struct ccs_path_info *buf, struct path *path)
7702+{
7703+ buf->name = ccs_realpath(path);
7704+ if (buf->name) {
7705+ ccs_fill_path_info(buf);
7706+ return true;
7707+ }
7708+ return false;
7709+}
7710+
7711+/**
7712+ * ccs_check_path_acl - Check permission for path operation.
7713+ *
7714+ * @r: Pointer to "struct ccs_request_info".
7715+ * @ptr: Pointer to "struct ccs_acl_info".
7716+ *
7717+ * Returns true if granted, false otherwise.
7718+ *
7719+ * To be able to use wildcard for domain transition, this function sets
7720+ * matching entry on success. Since the caller holds ccs_read_lock(),
7721+ * it is safe to set matching entry.
7722+ */
7723+static bool ccs_check_path_acl(struct ccs_request_info *r,
7724+ const struct ccs_acl_info *ptr)
7725+{
7726+ const struct ccs_path_acl *acl = container_of(ptr, typeof(*acl), head);
7727+ if (ptr->perm & (1 << r->param.path.operation)) {
7728+ r->param.path.matched_path =
7729+ ccs_compare_name_union(r->param.path.filename,
7730+ &acl->name);
7731+ return r->param.path.matched_path != NULL;
7732+ }
7733+ return false;
7734+}
7735+
7736+/**
7737+ * ccs_check_path_number_acl - Check permission for path number operation.
7738+ *
7739+ * @r: Pointer to "struct ccs_request_info".
7740+ * @ptr: Pointer to "struct ccs_acl_info".
7741+ *
7742+ * Returns true if granted, false otherwise.
7743+ */
7744+static bool ccs_check_path_number_acl(struct ccs_request_info *r,
7745+ const struct ccs_acl_info *ptr)
7746+{
7747+ const struct ccs_path_number_acl *acl =
7748+ container_of(ptr, typeof(*acl), head);
7749+ return (ptr->perm & (1 << r->param.path_number.operation)) &&
7750+ ccs_compare_number_union(r->param.path_number.number,
7751+ &acl->number) &&
7752+ ccs_compare_name_union(r->param.path_number.filename,
7753+ &acl->name);
7754+}
7755+
7756+/**
7757+ * ccs_check_path2_acl - Check permission for path path operation.
7758+ *
7759+ * @r: Pointer to "struct ccs_request_info".
7760+ * @ptr: Pointer to "struct ccs_acl_info".
7761+ *
7762+ * Returns true if granted, false otherwise.
7763+ */
7764+static bool ccs_check_path2_acl(struct ccs_request_info *r,
7765+ const struct ccs_acl_info *ptr)
7766+{
7767+ const struct ccs_path2_acl *acl =
7768+ container_of(ptr, typeof(*acl), head);
7769+ return (ptr->perm & (1 << r->param.path2.operation)) &&
7770+ ccs_compare_name_union(r->param.path2.filename1, &acl->name1)
7771+ && ccs_compare_name_union(r->param.path2.filename2,
7772+ &acl->name2);
7773+}
7774+
7775+/**
7776+ * ccs_check_mkdev_acl - Check permission for path number number number operation.
7777+ *
7778+ * @r: Pointer to "struct ccs_request_info".
7779+ * @ptr: Pointer to "struct ccs_acl_info".
7780+ *
7781+ * Returns true if granted, false otherwise.
7782+ */
7783+static bool ccs_check_mkdev_acl(struct ccs_request_info *r,
7784+ const struct ccs_acl_info *ptr)
7785+{
7786+ const struct ccs_mkdev_acl *acl =
7787+ container_of(ptr, typeof(*acl), head);
7788+ return (ptr->perm & (1 << r->param.mkdev.operation)) &&
7789+ ccs_compare_number_union(r->param.mkdev.mode, &acl->mode) &&
7790+ ccs_compare_number_union(r->param.mkdev.major, &acl->major) &&
7791+ ccs_compare_number_union(r->param.mkdev.minor, &acl->minor) &&
7792+ ccs_compare_name_union(r->param.mkdev.filename, &acl->name);
7793+}
7794+
7795+/**
7796+ * ccs_path_permission - Check permission for path operation.
7797+ *
7798+ * @r: Pointer to "struct ccs_request_info".
7799+ * @operation: Type of operation.
7800+ * @filename: Filename to check.
7801+ *
7802+ * Returns 0 on success, negative value otherwise.
7803+ *
7804+ * Caller holds ccs_read_lock().
7805+ */
7806+static int ccs_path_permission(struct ccs_request_info *r, u8 operation,
7807+ const struct ccs_path_info *filename)
7808+{
7809+ r->type = ccs_p2mac[operation];
7810+ r->mode = ccs_get_mode(r->profile, r->type);
7811+ if (r->mode == CCS_CONFIG_DISABLED)
7812+ return 0;
7813+ r->param_type = CCS_TYPE_PATH_ACL;
7814+ r->param.path.filename = filename;
7815+ r->param.path.operation = operation;
7816+ return ccs_check_acl(r);
7817+}
7818+
7819+/**
7820+ * ccs_execute_permission - Check permission for execute operation.
7821+ *
7822+ * @r: Pointer to "struct ccs_request_info".
7823+ * @filename: Filename to check.
7824+ *
7825+ * Returns 0 on success, CCS_RETRY_REQUEST on retry, negative value otherwise.
7826+ *
7827+ * Caller holds ccs_read_lock().
7828+ */
7829+static int ccs_execute_permission(struct ccs_request_info *r,
7830+ const struct ccs_path_info *filename)
7831+{
7832+ int error;
7833+ /*
7834+ * Unlike other permission checks, this check is done regardless of
7835+ * profile mode settings in order to check for domain transition
7836+ * preference.
7837+ */
7838+ r->type = CCS_MAC_FILE_EXECUTE;
7839+ r->mode = ccs_get_mode(r->profile, r->type);
7840+ r->param_type = CCS_TYPE_PATH_ACL;
7841+ r->param.path.filename = filename;
7842+ r->param.path.operation = CCS_TYPE_EXECUTE;
7843+ error = ccs_check_acl(r);
7844+ r->ee->transition = r->matched_acl && r->matched_acl->cond &&
7845+ r->matched_acl->cond->exec_transit ?
7846+ r->matched_acl->cond->transit : NULL;
7847+ return error;
7848+}
7849+
7850+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
7851+
7852+/**
7853+ * __ccs_save_open_mode - Remember original flags passed to sys_open().
7854+ *
7855+ * @mode: Flags passed to sys_open().
7856+ *
7857+ * Returns nothing.
7858+ *
7859+ * TOMOYO does not check "file write" if open(path, O_TRUNC | O_RDONLY) was
7860+ * requested because write() is not permitted. Instead, TOMOYO checks
7861+ * "file truncate" if O_TRUNC is passed.
7862+ *
7863+ * TOMOYO does not check "file read" and "file write" if open(path, 3) was
7864+ * requested because read()/write() are not permitted. Instead, TOMOYO checks
7865+ * "file ioctl" when ioctl() is requested.
7866+ */
7867+static void __ccs_save_open_mode(int mode)
7868+{
7869+ if ((mode & 3) == 3)
7870+ ccs_current_security()->ccs_flags |= CCS_OPEN_FOR_IOCTL_ONLY;
7871+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 14)
7872+ /* O_TRUNC passes MAY_WRITE to ccs_open_permission(). */
7873+ else if (!(mode & 3) && (mode & O_TRUNC))
7874+ ccs_current_security()->ccs_flags |=
7875+ CCS_OPEN_FOR_READ_TRUNCATE;
7876+#endif
7877+}
7878+
7879+/**
7880+ * __ccs_clear_open_mode - Forget original flags passed to sys_open().
7881+ *
7882+ * Returns nothing.
7883+ */
7884+static void __ccs_clear_open_mode(void)
7885+{
7886+ ccs_current_security()->ccs_flags &= ~(CCS_OPEN_FOR_IOCTL_ONLY |
7887+ CCS_OPEN_FOR_READ_TRUNCATE);
7888+}
7889+
7890+#endif
7891+
7892+/**
7893+ * __ccs_open_permission - Check permission for "read" and "write".
7894+ *
7895+ * @dentry: Pointer to "struct dentry".
7896+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
7897+ * @flag: Flags for open().
7898+ *
7899+ * Returns 0 on success, negative value otherwise.
7900+ */
7901+static int __ccs_open_permission(struct dentry *dentry, struct vfsmount *mnt,
7902+ const int flag)
7903+{
7904+ struct ccs_request_info r;
7905+ struct ccs_obj_info obj = {
7906+ .path1.dentry = dentry,
7907+ .path1.mnt = mnt,
7908+ };
7909+ const u32 ccs_flags = ccs_current_flags();
7910+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
7911+ const u8 acc_mode = (flag & 3) == 3 ? 0 : ACC_MODE(flag);
7912+#else
7913+ const u8 acc_mode = (ccs_flags & CCS_OPEN_FOR_IOCTL_ONLY) ? 0 :
7914+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 14)
7915+ (ccs_flags & CCS_OPEN_FOR_READ_TRUNCATE) ? 4 :
7916+#endif
7917+ ACC_MODE(flag);
7918+#endif
7919+ int error = 0;
7920+ struct ccs_path_info buf;
7921+ int idx;
7922+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
7923+ if (current->in_execve && !(ccs_flags & CCS_TASK_IS_IN_EXECVE))
7924+ return 0;
7925+#endif
7926+#ifndef CONFIG_CCSECURITY_FILE_READDIR
7927+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
7928+ if (d_is_dir(dentry))
7929+ return 0;
7930+#else
7931+ if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
7932+ return 0;
7933+#endif
7934+#endif
7935+ buf.name = NULL;
7936+ r.mode = CCS_CONFIG_DISABLED;
7937+ idx = ccs_read_lock();
7938+ if (acc_mode && ccs_init_request_info(&r, CCS_MAC_FILE_OPEN)
7939+ != CCS_CONFIG_DISABLED) {
7940+ if (!ccs_get_realpath(&buf, &obj.path1)) {
7941+ error = -ENOMEM;
7942+ goto out;
7943+ }
7944+ r.obj = &obj;
7945+ if (acc_mode & MAY_READ)
7946+ error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
7947+ if (!error && (acc_mode & MAY_WRITE))
7948+ error = ccs_path_permission(&r, (flag & O_APPEND) ?
7949+ CCS_TYPE_APPEND :
7950+ CCS_TYPE_WRITE, &buf);
7951+ }
7952+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
7953+ if (!error && (flag & O_TRUNC) &&
7954+ ccs_init_request_info(&r, CCS_MAC_FILE_TRUNCATE)
7955+ != CCS_CONFIG_DISABLED) {
7956+ if (!buf.name && !ccs_get_realpath(&buf, &obj.path1)) {
7957+ error = -ENOMEM;
7958+ goto out;
7959+ }
7960+ r.obj = &obj;
7961+ error = ccs_path_permission(&r, CCS_TYPE_TRUNCATE, &buf);
7962+ }
7963+#endif
7964+out:
7965+ kfree(buf.name);
7966+ ccs_read_unlock(idx);
7967+ if (r.mode != CCS_CONFIG_ENFORCING)
7968+ error = 0;
7969+ return error;
7970+}
7971+
7972+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
7973+
7974+/**
7975+ * ccs_new_open_permission - Check permission for "read" and "write".
7976+ *
7977+ * @filp: Pointer to "struct file".
7978+ *
7979+ * Returns 0 on success, negative value otherwise.
7980+ */
7981+static int ccs_new_open_permission(struct file *filp)
7982+{
7983+ return __ccs_open_permission(filp->f_path.dentry, filp->f_path.mnt,
7984+ filp->f_flags);
7985+}
7986+
7987+#endif
7988+
7989+/**
7990+ * ccs_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "getattr", "chroot" and "unmount".
7991+ *
7992+ * @operation: Type of operation.
7993+ * @dentry: Pointer to "struct dentry".
7994+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
7995+ * @target: Symlink's target if @operation is CCS_TYPE_SYMLINK,
7996+ * NULL otherwise.
7997+ *
7998+ * Returns 0 on success, negative value otherwise.
7999+ */
8000+static int ccs_path_perm(const u8 operation, struct dentry *dentry,
8001+ struct vfsmount *mnt, const char *target)
8002+{
8003+ struct ccs_request_info r;
8004+ struct ccs_obj_info obj = {
8005+ .path1.dentry = dentry,
8006+ .path1.mnt = mnt,
8007+ };
8008+ int error = 0;
8009+ struct ccs_path_info buf;
8010+ bool is_enforce = false;
8011+ struct ccs_path_info symlink_target;
8012+ int idx;
8013+ buf.name = NULL;
8014+ symlink_target.name = NULL;
8015+ idx = ccs_read_lock();
8016+ if (ccs_init_request_info(&r, ccs_p2mac[operation])
8017+ == CCS_CONFIG_DISABLED)
8018+ goto out;
8019+ is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
8020+ error = -ENOMEM;
8021+ if (!ccs_get_realpath(&buf, &obj.path1))
8022+ goto out;
8023+ r.obj = &obj;
8024+ switch (operation) {
8025+ case CCS_TYPE_RMDIR:
8026+ case CCS_TYPE_CHROOT:
8027+ ccs_add_slash(&buf);
8028+ break;
8029+ case CCS_TYPE_SYMLINK:
8030+ symlink_target.name = ccs_encode(target);
8031+ if (!symlink_target.name)
8032+ goto out;
8033+ ccs_fill_path_info(&symlink_target);
8034+ obj.symlink_target = &symlink_target;
8035+ break;
8036+ }
8037+ error = ccs_path_permission(&r, operation, &buf);
8038+ if (operation == CCS_TYPE_SYMLINK)
8039+ kfree(symlink_target.name);
8040+out:
8041+ kfree(buf.name);
8042+ ccs_read_unlock(idx);
8043+ if (!is_enforce)
8044+ error = 0;
8045+ return error;
8046+}
8047+
8048+/**
8049+ * ccs_mkdev_perm - Check permission for "mkblock" and "mkchar".
8050+ *
8051+ * @operation: Type of operation. (CCS_TYPE_MKCHAR or CCS_TYPE_MKBLOCK)
8052+ * @dentry: Pointer to "struct dentry".
8053+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8054+ * @mode: Create mode.
8055+ * @dev: Device number.
8056+ *
8057+ * Returns 0 on success, negative value otherwise.
8058+ */
8059+static int ccs_mkdev_perm(const u8 operation, struct dentry *dentry,
8060+ struct vfsmount *mnt, const unsigned int mode,
8061+ unsigned int dev)
8062+{
8063+ struct ccs_request_info r;
8064+ struct ccs_obj_info obj = {
8065+ .path1.dentry = dentry,
8066+ .path1.mnt = mnt,
8067+ };
8068+ int error = 0;
8069+ struct ccs_path_info buf;
8070+ bool is_enforce = false;
8071+ int idx;
8072+ idx = ccs_read_lock();
8073+ if (ccs_init_request_info(&r, ccs_pnnn2mac[operation])
8074+ == CCS_CONFIG_DISABLED)
8075+ goto out;
8076+ is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
8077+ error = -EPERM;
8078+ if (!capable(CAP_MKNOD))
8079+ goto out;
8080+ error = -ENOMEM;
8081+ if (!ccs_get_realpath(&buf, &obj.path1))
8082+ goto out;
8083+ r.obj = &obj;
8084+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
8085+ dev = new_decode_dev(dev);
8086+#endif
8087+ r.param_type = CCS_TYPE_MKDEV_ACL;
8088+ r.param.mkdev.filename = &buf;
8089+ r.param.mkdev.operation = operation;
8090+ r.param.mkdev.mode = mode;
8091+ r.param.mkdev.major = MAJOR(dev);
8092+ r.param.mkdev.minor = MINOR(dev);
8093+ error = ccs_check_acl(&r);
8094+ kfree(buf.name);
8095+out:
8096+ ccs_read_unlock(idx);
8097+ if (!is_enforce)
8098+ error = 0;
8099+ return error;
8100+}
8101+
8102+/**
8103+ * ccs_path2_perm - Check permission for "rename", "link" and "pivot_root".
8104+ *
8105+ * @operation: Type of operation.
8106+ * @dentry1: Pointer to "struct dentry".
8107+ * @mnt1: Pointer to "struct vfsmount". Maybe NULL.
8108+ * @dentry2: Pointer to "struct dentry".
8109+ * @mnt2: Pointer to "struct vfsmount". Maybe NULL.
8110+ *
8111+ * Returns 0 on success, negative value otherwise.
8112+ */
8113+static int ccs_path2_perm(const u8 operation, struct dentry *dentry1,
8114+ struct vfsmount *mnt1, struct dentry *dentry2,
8115+ struct vfsmount *mnt2)
8116+{
8117+ struct ccs_request_info r;
8118+ int error = 0;
8119+ struct ccs_path_info buf1;
8120+ struct ccs_path_info buf2;
8121+ bool is_enforce = false;
8122+ struct ccs_obj_info obj = {
8123+ .path1.dentry = dentry1,
8124+ .path1.mnt = mnt1,
8125+ .path2.dentry = dentry2,
8126+ .path2.mnt = mnt2,
8127+ };
8128+ int idx;
8129+ buf1.name = NULL;
8130+ buf2.name = NULL;
8131+ idx = ccs_read_lock();
8132+ if (ccs_init_request_info(&r, ccs_pp2mac[operation])
8133+ == CCS_CONFIG_DISABLED)
8134+ goto out;
8135+ is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
8136+ error = -ENOMEM;
8137+ if (!ccs_get_realpath(&buf1, &obj.path1) ||
8138+ !ccs_get_realpath(&buf2, &obj.path2))
8139+ goto out;
8140+ switch (operation) {
8141+ case CCS_TYPE_RENAME:
8142+ case CCS_TYPE_LINK:
8143+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
8144+ if (!d_is_dir(dentry1))
8145+ break;
8146+#else
8147+ if (!dentry1->d_inode || !S_ISDIR(dentry1->d_inode->i_mode))
8148+ break;
8149+#endif
8150+ /* fall through */
8151+ case CCS_TYPE_PIVOT_ROOT:
8152+ ccs_add_slash(&buf1);
8153+ ccs_add_slash(&buf2);
8154+ break;
8155+ }
8156+ r.obj = &obj;
8157+ r.param_type = CCS_TYPE_PATH2_ACL;
8158+ r.param.path2.operation = operation;
8159+ r.param.path2.filename1 = &buf1;
8160+ r.param.path2.filename2 = &buf2;
8161+ error = ccs_check_acl(&r);
8162+out:
8163+ kfree(buf1.name);
8164+ kfree(buf2.name);
8165+ ccs_read_unlock(idx);
8166+ if (!is_enforce)
8167+ error = 0;
8168+ return error;
8169+}
8170+
8171+/**
8172+ * ccs_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
8173+ *
8174+ * @type: Type of operation.
8175+ * @dentry: Pointer to "struct dentry".
8176+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
8177+ * @number: Number.
8178+ *
8179+ * Returns 0 on success, negative value otherwise.
8180+ */
8181+static int ccs_path_number_perm(const u8 type, struct dentry *dentry,
8182+ struct vfsmount *vfsmnt, unsigned long number)
8183+{
8184+ struct ccs_request_info r;
8185+ struct ccs_obj_info obj = {
8186+ .path1.dentry = dentry,
8187+ .path1.mnt = vfsmnt,
8188+ };
8189+ int error = 0;
8190+ struct ccs_path_info buf;
8191+ int idx;
8192+ if (!dentry)
8193+ return 0;
8194+ idx = ccs_read_lock();
8195+ if (ccs_init_request_info(&r, ccs_pn2mac[type]) == CCS_CONFIG_DISABLED)
8196+ goto out;
8197+ error = -ENOMEM;
8198+ if (!ccs_get_realpath(&buf, &obj.path1))
8199+ goto out;
8200+ r.obj = &obj;
8201+ if (type == CCS_TYPE_MKDIR)
8202+ ccs_add_slash(&buf);
8203+ r.param_type = CCS_TYPE_PATH_NUMBER_ACL;
8204+ r.param.path_number.operation = type;
8205+ r.param.path_number.filename = &buf;
8206+ r.param.path_number.number = number;
8207+ error = ccs_check_acl(&r);
8208+ kfree(buf.name);
8209+out:
8210+ ccs_read_unlock(idx);
8211+ if (r.mode != CCS_CONFIG_ENFORCING)
8212+ error = 0;
8213+ return error;
8214+}
8215+
8216+/**
8217+ * __ccs_ioctl_permission - Check permission for "ioctl".
8218+ *
8219+ * @filp: Pointer to "struct file".
8220+ * @cmd: Ioctl command number.
8221+ * @arg: Param for @cmd.
8222+ *
8223+ * Returns 0 on success, negative value otherwise.
8224+ */
8225+static int __ccs_ioctl_permission(struct file *filp, unsigned int cmd,
8226+ unsigned long arg)
8227+{
8228+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
8229+ return ccs_path_number_perm(CCS_TYPE_IOCTL, filp->f_path.dentry,
8230+ filp->f_path.mnt, cmd);
8231+#else
8232+ return ccs_path_number_perm(CCS_TYPE_IOCTL, filp->f_dentry,
8233+ filp->f_vfsmnt, cmd);
8234+#endif
8235+}
8236+
8237+/**
8238+ * __ccs_chmod_permission - Check permission for "chmod".
8239+ *
8240+ * @dentry: Pointer to "struct dentry".
8241+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
8242+ * @mode: Mode.
8243+ *
8244+ * Returns 0 on success, negative value otherwise.
8245+ */
8246+static int __ccs_chmod_permission(struct dentry *dentry,
8247+ struct vfsmount *vfsmnt, mode_t mode)
8248+{
8249+ return ccs_path_number_perm(CCS_TYPE_CHMOD, dentry, vfsmnt,
8250+ mode & S_IALLUGO);
8251+}
8252+
8253+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
8254+
8255+/**
8256+ * __ccs_chown_permission - Check permission for "chown/chgrp".
8257+ *
8258+ * @dentry: Pointer to "struct dentry".
8259+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
8260+ * @user: User ID.
8261+ * @group: Group ID.
8262+ *
8263+ * Returns 0 on success, negative value otherwise.
8264+ */
8265+static int __ccs_chown_permission(struct dentry *dentry,
8266+ struct vfsmount *vfsmnt, kuid_t user,
8267+ kgid_t group)
8268+{
8269+ int error = 0;
8270+ if (uid_valid(user))
8271+ error = ccs_path_number_perm(CCS_TYPE_CHOWN, dentry, vfsmnt,
8272+ from_kuid(&init_user_ns, user));
8273+ if (!error && gid_valid(group))
8274+ error = ccs_path_number_perm(CCS_TYPE_CHGRP, dentry, vfsmnt,
8275+ from_kgid(&init_user_ns, group));
8276+ return error;
8277+}
8278+
8279+#else
8280+
8281+/**
8282+ * __ccs_chown_permission - Check permission for "chown/chgrp".
8283+ *
8284+ * @dentry: Pointer to "struct dentry".
8285+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
8286+ * @user: User ID.
8287+ * @group: Group ID.
8288+ *
8289+ * Returns 0 on success, negative value otherwise.
8290+ */
8291+static int __ccs_chown_permission(struct dentry *dentry,
8292+ struct vfsmount *vfsmnt, uid_t user,
8293+ gid_t group)
8294+{
8295+ int error = 0;
8296+ if (user == (uid_t) -1 && group == (gid_t) -1)
8297+ return 0;
8298+ if (user != (uid_t) -1)
8299+ error = ccs_path_number_perm(CCS_TYPE_CHOWN, dentry, vfsmnt,
8300+ user);
8301+ if (!error && group != (gid_t) -1)
8302+ error = ccs_path_number_perm(CCS_TYPE_CHGRP, dentry, vfsmnt,
8303+ group);
8304+ return error;
8305+}
8306+
8307+#endif
8308+
8309+/**
8310+ * __ccs_fcntl_permission - Check permission for changing O_APPEND flag.
8311+ *
8312+ * @file: Pointer to "struct file".
8313+ * @cmd: Command number.
8314+ * @arg: Value for @cmd.
8315+ *
8316+ * Returns 0 on success, negative value otherwise.
8317+ */
8318+static int __ccs_fcntl_permission(struct file *file, unsigned int cmd,
8319+ unsigned long arg)
8320+{
8321+ if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)))
8322+ return 0;
8323+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
8324+ return __ccs_open_permission(file->f_path.dentry, file->f_path.mnt,
8325+ O_WRONLY | (arg & O_APPEND));
8326+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 6
8327+ return __ccs_open_permission(file->f_dentry, file->f_vfsmnt,
8328+ O_WRONLY | (arg & O_APPEND));
8329+#else
8330+ return __ccs_open_permission(file->f_dentry, file->f_vfsmnt,
8331+ (O_WRONLY + 1) | (arg & O_APPEND));
8332+#endif
8333+}
8334+
8335+/**
8336+ * __ccs_pivot_root_permission - Check permission for pivot_root().
8337+ *
8338+ * @old_path: Pointer to "struct path".
8339+ * @new_path: Pointer to "struct path".
8340+ *
8341+ * Returns 0 on success, negative value otherwise.
8342+ */
8343+static int __ccs_pivot_root_permission(struct path *old_path,
8344+ struct path *new_path)
8345+{
8346+ return ccs_path2_perm(CCS_TYPE_PIVOT_ROOT, new_path->dentry,
8347+ new_path->mnt, old_path->dentry, old_path->mnt);
8348+}
8349+
8350+/**
8351+ * __ccs_chroot_permission - Check permission for chroot().
8352+ *
8353+ * @path: Pointer to "struct path".
8354+ *
8355+ * Returns 0 on success, negative value otherwise.
8356+ */
8357+static int __ccs_chroot_permission(struct path *path)
8358+{
8359+ return ccs_path_perm(CCS_TYPE_CHROOT, path->dentry, path->mnt, NULL);
8360+}
8361+
8362+/**
8363+ * __ccs_umount_permission - Check permission for unmount.
8364+ *
8365+ * @mnt: Pointer to "struct vfsmount".
8366+ * @flags: Unused.
8367+ *
8368+ * Returns 0 on success, negative value otherwise.
8369+ */
8370+static int __ccs_umount_permission(struct vfsmount *mnt, int flags)
8371+{
8372+ return ccs_path_perm(CCS_TYPE_UMOUNT, mnt->mnt_root, mnt, NULL);
8373+}
8374+
8375+/**
8376+ * __ccs_mknod_permission - Check permission for vfs_mknod().
8377+ *
8378+ * @dentry: Pointer to "struct dentry".
8379+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8380+ * @mode: Device type and permission.
8381+ * @dev: Device number for block or character device.
8382+ *
8383+ * Returns 0 on success, negative value otherwise.
8384+ */
8385+static int __ccs_mknod_permission(struct dentry *dentry, struct vfsmount *mnt,
8386+ const unsigned int mode, unsigned int dev)
8387+{
8388+ int error = 0;
8389+ const unsigned int perm = mode & S_IALLUGO;
8390+ switch (mode & S_IFMT) {
8391+ case S_IFCHR:
8392+ error = ccs_mkdev_perm(CCS_TYPE_MKCHAR, dentry, mnt, perm,
8393+ dev);
8394+ break;
8395+ case S_IFBLK:
8396+ error = ccs_mkdev_perm(CCS_TYPE_MKBLOCK, dentry, mnt, perm,
8397+ dev);
8398+ break;
8399+ case S_IFIFO:
8400+ error = ccs_path_number_perm(CCS_TYPE_MKFIFO, dentry, mnt,
8401+ perm);
8402+ break;
8403+ case S_IFSOCK:
8404+ error = ccs_path_number_perm(CCS_TYPE_MKSOCK, dentry, mnt,
8405+ perm);
8406+ break;
8407+ case 0:
8408+ case S_IFREG:
8409+ error = ccs_path_number_perm(CCS_TYPE_CREATE, dentry, mnt,
8410+ perm);
8411+ break;
8412+ }
8413+ return error;
8414+}
8415+
8416+/**
8417+ * __ccs_mkdir_permission - Check permission for vfs_mkdir().
8418+ *
8419+ * @dentry: Pointer to "struct dentry".
8420+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8421+ * @mode: Create mode.
8422+ *
8423+ * Returns 0 on success, negative value otherwise.
8424+ */
8425+static int __ccs_mkdir_permission(struct dentry *dentry, struct vfsmount *mnt,
8426+ unsigned int mode)
8427+{
8428+ return ccs_path_number_perm(CCS_TYPE_MKDIR, dentry, mnt, mode);
8429+}
8430+
8431+/**
8432+ * __ccs_rmdir_permission - Check permission for vfs_rmdir().
8433+ *
8434+ * @dentry: Pointer to "struct dentry".
8435+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8436+ *
8437+ * Returns 0 on success, negative value otherwise.
8438+ */
8439+static int __ccs_rmdir_permission(struct dentry *dentry, struct vfsmount *mnt)
8440+{
8441+ return ccs_path_perm(CCS_TYPE_RMDIR, dentry, mnt, NULL);
8442+}
8443+
8444+/**
8445+ * __ccs_unlink_permission - Check permission for vfs_unlink().
8446+ *
8447+ * @dentry: Pointer to "struct dentry".
8448+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8449+ *
8450+ * Returns 0 on success, negative value otherwise.
8451+ */
8452+static int __ccs_unlink_permission(struct dentry *dentry, struct vfsmount *mnt)
8453+{
8454+ return ccs_path_perm(CCS_TYPE_UNLINK, dentry, mnt, NULL);
8455+}
8456+
8457+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
8458+
8459+/**
8460+ * __ccs_getattr_permission - Check permission for vfs_getattr().
8461+ *
8462+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8463+ * @dentry: Pointer to "struct dentry".
8464+ *
8465+ * Returns 0 on success, negative value otherwise.
8466+ */
8467+static int __ccs_getattr_permission(struct vfsmount *mnt,
8468+ struct dentry *dentry)
8469+{
8470+ return ccs_path_perm(CCS_TYPE_GETATTR, dentry, mnt, NULL);
8471+}
8472+
8473+#endif
8474+
8475+/**
8476+ * __ccs_symlink_permission - Check permission for vfs_symlink().
8477+ *
8478+ * @dentry: Pointer to "struct dentry".
8479+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8480+ * @from: Content of symlink.
8481+ *
8482+ * Returns 0 on success, negative value otherwise.
8483+ */
8484+static int __ccs_symlink_permission(struct dentry *dentry,
8485+ struct vfsmount *mnt, const char *from)
8486+{
8487+ return ccs_path_perm(CCS_TYPE_SYMLINK, dentry, mnt, from);
8488+}
8489+
8490+/**
8491+ * __ccs_truncate_permission - Check permission for notify_change().
8492+ *
8493+ * @dentry: Pointer to "struct dentry".
8494+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8495+ *
8496+ * Returns 0 on success, negative value otherwise.
8497+ */
8498+static int __ccs_truncate_permission(struct dentry *dentry,
8499+ struct vfsmount *mnt)
8500+{
8501+ return ccs_path_perm(CCS_TYPE_TRUNCATE, dentry, mnt, NULL);
8502+}
8503+
8504+/**
8505+ * __ccs_rename_permission - Check permission for vfs_rename().
8506+ *
8507+ * @old_dentry: Pointer to "struct dentry".
8508+ * @new_dentry: Pointer to "struct dentry".
8509+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8510+ *
8511+ * Returns 0 on success, negative value otherwise.
8512+ */
8513+static int __ccs_rename_permission(struct dentry *old_dentry,
8514+ struct dentry *new_dentry,
8515+ struct vfsmount *mnt)
8516+{
8517+ return ccs_path2_perm(CCS_TYPE_RENAME, old_dentry, mnt, new_dentry,
8518+ mnt);
8519+}
8520+
8521+/**
8522+ * __ccs_link_permission - Check permission for vfs_link().
8523+ *
8524+ * @old_dentry: Pointer to "struct dentry".
8525+ * @new_dentry: Pointer to "struct dentry".
8526+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
8527+ *
8528+ * Returns 0 on success, negative value otherwise.
8529+ */
8530+static int __ccs_link_permission(struct dentry *old_dentry,
8531+ struct dentry *new_dentry,
8532+ struct vfsmount *mnt)
8533+{
8534+ return ccs_path2_perm(CCS_TYPE_LINK, old_dentry, mnt, new_dentry, mnt);
8535+}
8536+
8537+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
8538+
8539+/**
8540+ * __ccs_open_exec_permission - Check permission for open_exec().
8541+ *
8542+ * @dentry: Pointer to "struct dentry".
8543+ * @mnt: Pointer to "struct vfsmount".
8544+ *
8545+ * Returns 0 on success, negative value otherwise.
8546+ */
8547+static int __ccs_open_exec_permission(struct dentry *dentry,
8548+ struct vfsmount *mnt)
8549+{
8550+ return (ccs_current_flags() & CCS_TASK_IS_IN_EXECVE) ?
8551+ __ccs_open_permission(dentry, mnt, O_RDONLY + 1) : 0;
8552+}
8553+
8554+/**
8555+ * __ccs_uselib_permission - Check permission for sys_uselib().
8556+ *
8557+ * @dentry: Pointer to "struct dentry".
8558+ * @mnt: Pointer to "struct vfsmount".
8559+ *
8560+ * Returns 0 on success, negative value otherwise.
8561+ */
8562+static int __ccs_uselib_permission(struct dentry *dentry, struct vfsmount *mnt)
8563+{
8564+ return __ccs_open_permission(dentry, mnt, O_RDONLY + 1);
8565+}
8566+
8567+#endif
8568+
8569+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
8570+
8571+/**
8572+ * __ccs_parse_table - Check permission for parse_table().
8573+ *
8574+ * @name: Pointer to "int __user".
8575+ * @nlen: Number of elements in @name.
8576+ * @oldval: Pointer to "void __user".
8577+ * @newval: Pointer to "void __user".
8578+ * @table: Pointer to "struct ctl_table".
8579+ *
8580+ * Returns 0 on success, negative value otherwise.
8581+ *
8582+ * Note that this function is racy because this function checks values in
8583+ * userspace memory which could be changed after permission check.
8584+ */
8585+static int __ccs_parse_table(int __user *name, int nlen, void __user *oldval,
8586+ void __user *newval, struct ctl_table *table)
8587+{
8588+ int n;
8589+ int error = -ENOMEM;
8590+ int op = 0;
8591+ struct ccs_path_info buf;
8592+ char *buffer = NULL;
8593+ struct ccs_request_info r;
8594+ int idx;
8595+ if (oldval)
8596+ op |= 004;
8597+ if (newval)
8598+ op |= 002;
8599+ if (!op) /* Neither read nor write */
8600+ return 0;
8601+ idx = ccs_read_lock();
8602+ if (ccs_init_request_info(&r, CCS_MAC_FILE_OPEN)
8603+ == CCS_CONFIG_DISABLED) {
8604+ error = 0;
8605+ goto out;
8606+ }
8607+ buffer = kmalloc(PAGE_SIZE, CCS_GFP_FLAGS);
8608+ if (!buffer)
8609+ goto out;
8610+ snprintf(buffer, PAGE_SIZE - 1, "proc:/sys");
8611+repeat:
8612+ if (!nlen) {
8613+ error = -ENOTDIR;
8614+ goto out;
8615+ }
8616+ if (get_user(n, name)) {
8617+ error = -EFAULT;
8618+ goto out;
8619+ }
8620+ for ( ; table->ctl_name
8621+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)
8622+ || table->procname
8623+#endif
8624+ ; table++) {
8625+ int pos;
8626+ const char *cp;
8627+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21)
8628+ if (n != table->ctl_name && table->ctl_name != CTL_ANY)
8629+ continue;
8630+#else
8631+ if (!n || n != table->ctl_name)
8632+ continue;
8633+#endif
8634+ pos = strlen(buffer);
8635+ cp = table->procname;
8636+ error = -ENOMEM;
8637+ if (cp) {
8638+ int len = strlen(cp);
8639+ if (len + 2 > PAGE_SIZE - 1)
8640+ goto out;
8641+ buffer[pos++] = '/';
8642+ memmove(buffer + pos, cp, len + 1);
8643+ } else {
8644+ /* Assume nobody assigns "=\$=" for procname. */
8645+ snprintf(buffer + pos, PAGE_SIZE - pos - 1,
8646+ "/=%d=", table->ctl_name);
8647+ if (!memchr(buffer, '\0', PAGE_SIZE - 2))
8648+ goto out;
8649+ }
8650+ if (!table->child)
8651+ goto no_child;
8652+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21)
8653+ if (!table->strategy)
8654+ goto no_strategy;
8655+ /* printk("sysctl='%s'\n", buffer); */
8656+ buf.name = ccs_encode(buffer);
8657+ if (!buf.name)
8658+ goto out;
8659+ ccs_fill_path_info(&buf);
8660+ if (op & MAY_READ)
8661+ error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
8662+ else
8663+ error = 0;
8664+ if (!error && (op & MAY_WRITE))
8665+ error = ccs_path_permission(&r, CCS_TYPE_WRITE, &buf);
8666+ kfree(buf.name);
8667+ if (error)
8668+ goto out;
8669+no_strategy:
8670+#endif
8671+ name++;
8672+ nlen--;
8673+ table = table->child;
8674+ goto repeat;
8675+no_child:
8676+ /* printk("sysctl='%s'\n", buffer); */
8677+ buf.name = ccs_encode(buffer);
8678+ if (!buf.name)
8679+ goto out;
8680+ ccs_fill_path_info(&buf);
8681+ if (op & MAY_READ)
8682+ error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
8683+ else
8684+ error = 0;
8685+ if (!error && (op & MAY_WRITE))
8686+ error = ccs_path_permission(&r, CCS_TYPE_WRITE, &buf);
8687+ kfree(buf.name);
8688+ goto out;
8689+ }
8690+ error = -ENOTDIR;
8691+out:
8692+ ccs_read_unlock(idx);
8693+ kfree(buffer);
8694+ return error;
8695+}
8696+
8697+#endif
8698+
8699+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
8700+
8701+/**
8702+ * ccs_old_pivot_root_permission - Check permission for pivot_root().
8703+ *
8704+ * @old_nd: Pointer to "struct nameidata".
8705+ * @new_nd: Pointer to "struct nameidata".
8706+ *
8707+ * Returns 0 on success, negative value otherwise.
8708+ */
8709+static int ccs_old_pivot_root_permission(struct nameidata *old_nd,
8710+ struct nameidata *new_nd)
8711+{
8712+ struct path old_path = { old_nd->mnt, old_nd->dentry };
8713+ struct path new_path = { new_nd->mnt, new_nd->dentry };
8714+ return __ccs_pivot_root_permission(&old_path, &new_path);
8715+}
8716+
8717+/**
8718+ * ccs_old_chroot_permission - Check permission for chroot().
8719+ *
8720+ * @nd: Pointer to "struct nameidata".
8721+ *
8722+ * Returns 0 on success, negative value otherwise.
8723+ */
8724+static int ccs_old_chroot_permission(struct nameidata *nd)
8725+{
8726+ struct path path = { nd->mnt, nd->dentry };
8727+ return __ccs_chroot_permission(&path);
8728+}
8729+
8730+#endif
8731+
8732+#ifdef CONFIG_CCSECURITY_NETWORK
8733+
8734+/**
8735+ * ccs_address_matches_group - Check whether the given address matches members of the given address group.
8736+ *
8737+ * @is_ipv6: True if @address is an IPv6 address.
8738+ * @address: An IPv4 or IPv6 address.
8739+ * @group: Pointer to "struct ccs_address_group".
8740+ *
8741+ * Returns true if @address matches addresses in @group group, false otherwise.
8742+ *
8743+ * Caller holds ccs_read_lock().
8744+ */
8745+static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
8746+ const struct ccs_group *group)
8747+{
8748+ struct ccs_address_group *member;
8749+ bool matched = false;
8750+ const u8 size = is_ipv6 ? 16 : 4;
8751+ list_for_each_entry_srcu(member, &group->member_list, head.list,
8752+ &ccs_ss) {
8753+ if (member->head.is_deleted)
8754+ continue;
8755+ if (member->address.is_ipv6 != is_ipv6)
8756+ continue;
8757+ if (memcmp(&member->address.ip[0], address, size) > 0 ||
8758+ memcmp(address, &member->address.ip[1], size) > 0)
8759+ continue;
8760+ matched = true;
8761+ break;
8762+ }
8763+ return matched;
8764+}
8765+
8766+/**
8767+ * ccs_check_inet_acl - Check permission for inet domain socket operation.
8768+ *
8769+ * @r: Pointer to "struct ccs_request_info".
8770+ * @ptr: Pointer to "struct ccs_acl_info".
8771+ *
8772+ * Returns true if granted, false otherwise.
8773+ */
8774+static bool ccs_check_inet_acl(struct ccs_request_info *r,
8775+ const struct ccs_acl_info *ptr)
8776+{
8777+ const struct ccs_inet_acl *acl = container_of(ptr, typeof(*acl), head);
8778+ const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4;
8779+ if (!(ptr->perm & (1 << r->param.inet_network.operation)) ||
8780+ !ccs_compare_number_union(r->param.inet_network.port, &acl->port))
8781+ return false;
8782+ if (acl->address.group)
8783+ return ccs_address_matches_group(r->param.inet_network.is_ipv6,
8784+ r->param.inet_network.address,
8785+ acl->address.group);
8786+ return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 &&
8787+ memcmp(&acl->address.ip[0],
8788+ r->param.inet_network.address, size) <= 0 &&
8789+ memcmp(r->param.inet_network.address,
8790+ &acl->address.ip[1], size) <= 0;
8791+}
8792+
8793+/**
8794+ * ccs_check_unix_acl - Check permission for unix domain socket operation.
8795+ *
8796+ * @r: Pointer to "struct ccs_request_info".
8797+ * @ptr: Pointer to "struct ccs_acl_info".
8798+ *
8799+ * Returns true if granted, false otherwise.
8800+ */
8801+static bool ccs_check_unix_acl(struct ccs_request_info *r,
8802+ const struct ccs_acl_info *ptr)
8803+{
8804+ const struct ccs_unix_acl *acl = container_of(ptr, typeof(*acl), head);
8805+ return (ptr->perm & (1 << r->param.unix_network.operation)) &&
8806+ ccs_compare_name_union(r->param.unix_network.address,
8807+ &acl->name);
8808+}
8809+
8810+/**
8811+ * ccs_inet_entry - Check permission for INET network operation.
8812+ *
8813+ * @address: Pointer to "struct ccs_addr_info".
8814+ *
8815+ * Returns 0 on success, negative value otherwise.
8816+ */
8817+static int ccs_inet_entry(const struct ccs_addr_info *address)
8818+{
8819+ const int idx = ccs_read_lock();
8820+ struct ccs_request_info r;
8821+ int error = 0;
8822+ const u8 type = ccs_inet2mac[address->protocol][address->operation];
8823+ if (type && ccs_init_request_info(&r, type) != CCS_CONFIG_DISABLED) {
8824+ r.param_type = CCS_TYPE_INET_ACL;
8825+ r.param.inet_network.protocol = address->protocol;
8826+ r.param.inet_network.operation = address->operation;
8827+ r.param.inet_network.is_ipv6 = address->inet.is_ipv6;
8828+ r.param.inet_network.address = address->inet.address;
8829+ r.param.inet_network.port = ntohs(address->inet.port);
8830+ r.dont_sleep_on_enforce_error =
8831+ address->operation == CCS_NETWORK_ACCEPT
8832+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
8833+ || address->operation == CCS_NETWORK_RECV
8834+#endif
8835+ ;
8836+ error = ccs_check_acl(&r);
8837+ }
8838+ ccs_read_unlock(idx);
8839+ return error;
8840+}
8841+
8842+/**
8843+ * ccs_check_inet_address - Check permission for inet domain socket's operation.
8844+ *
8845+ * @addr: Pointer to "struct sockaddr".
8846+ * @addr_len: Size of @addr.
8847+ * @port: Port number.
8848+ * @address: Pointer to "struct ccs_addr_info".
8849+ *
8850+ * Returns 0 on success, negative value otherwise.
8851+ */
8852+static int ccs_check_inet_address(const struct sockaddr *addr,
8853+ const unsigned int addr_len, const u16 port,
8854+ struct ccs_addr_info *address)
8855+{
8856+ struct ccs_inet_addr_info *i = &address->inet;
8857+ switch (addr->sa_family) {
8858+ case AF_INET6:
8859+ if (addr_len < SIN6_LEN_RFC2133)
8860+ goto skip;
8861+ i->is_ipv6 = true;
8862+ i->address = (u32 *)
8863+ ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
8864+ i->port = ((struct sockaddr_in6 *) addr)->sin6_port;
8865+ break;
8866+ case AF_INET:
8867+ if (addr_len < sizeof(struct sockaddr_in))
8868+ goto skip;
8869+ i->is_ipv6 = false;
8870+ i->address = (u32 *) &((struct sockaddr_in *) addr)->sin_addr;
8871+ i->port = ((struct sockaddr_in *) addr)->sin_port;
8872+ break;
8873+ default:
8874+ goto skip;
8875+ }
8876+ if (address->protocol == SOCK_RAW)
8877+ i->port = htons(port);
8878+ return ccs_inet_entry(address);
8879+skip:
8880+ return 0;
8881+}
8882+
8883+/**
8884+ * ccs_unix_entry - Check permission for UNIX network operation.
8885+ *
8886+ * @address: Pointer to "struct ccs_addr_info".
8887+ *
8888+ * Returns 0 on success, negative value otherwise.
8889+ */
8890+static int ccs_unix_entry(const struct ccs_addr_info *address)
8891+{
8892+ const int idx = ccs_read_lock();
8893+ struct ccs_request_info r;
8894+ int error = 0;
8895+ const u8 type = ccs_unix2mac[address->protocol][address->operation];
8896+ if (type && ccs_init_request_info(&r, type) != CCS_CONFIG_DISABLED) {
8897+ char *buf = address->unix0.addr;
8898+ int len = address->unix0.addr_len - sizeof(sa_family_t);
8899+ if (len <= 0) {
8900+ buf = "anonymous";
8901+ len = 9;
8902+ } else if (buf[0]) {
8903+ len = strnlen(buf, len);
8904+ }
8905+ buf = ccs_encode2(buf, len);
8906+ if (buf) {
8907+ struct ccs_path_info addr;
8908+ addr.name = buf;
8909+ ccs_fill_path_info(&addr);
8910+ r.param_type = CCS_TYPE_UNIX_ACL;
8911+ r.param.unix_network.protocol = address->protocol;
8912+ r.param.unix_network.operation = address->operation;
8913+ r.param.unix_network.address = &addr;
8914+ r.dont_sleep_on_enforce_error =
8915+ address->operation == CCS_NETWORK_ACCEPT
8916+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
8917+ || address->operation == CCS_NETWORK_RECV
8918+#endif
8919+ ;
8920+ error = ccs_check_acl(&r);
8921+ kfree(buf);
8922+ } else
8923+ error = -ENOMEM;
8924+ }
8925+ ccs_read_unlock(idx);
8926+ return error;
8927+}
8928+
8929+/**
8930+ * ccs_check_unix_address - Check permission for unix domain socket's operation.
8931+ *
8932+ * @addr: Pointer to "struct sockaddr".
8933+ * @addr_len: Size of @addr.
8934+ * @address: Pointer to "struct ccs_addr_info".
8935+ *
8936+ * Returns 0 on success, negative value otherwise.
8937+ */
8938+static int ccs_check_unix_address(struct sockaddr *addr,
8939+ const unsigned int addr_len,
8940+ struct ccs_addr_info *address)
8941+{
8942+ struct ccs_unix_addr_info *u = &address->unix0;
8943+ if (addr->sa_family != AF_UNIX)
8944+ return 0;
8945+ u->addr = ((struct sockaddr_un *) addr)->sun_path;
8946+ u->addr_len = addr_len;
8947+ return ccs_unix_entry(address);
8948+}
8949+
8950+/**
8951+ * ccs_sock_family - Get socket's family.
8952+ *
8953+ * @sk: Pointer to "struct sock".
8954+ *
8955+ * Returns one of PF_INET, PF_INET6, PF_UNIX or 0.
8956+ */
8957+static u8 ccs_sock_family(struct sock *sk)
8958+{
8959+ u8 family;
8960+ if (ccs_kernel_service())
8961+ return 0;
8962+ family = sk->sk_family;
8963+ switch (family) {
8964+ case PF_INET:
8965+ case PF_INET6:
8966+ case PF_UNIX:
8967+ return family;
8968+ default:
8969+ return 0;
8970+ }
8971+}
8972+
8973+/**
8974+ * __ccs_socket_listen_permission - Check permission for listening a socket.
8975+ *
8976+ * @sock: Pointer to "struct socket".
8977+ *
8978+ * Returns 0 on success, negative value otherwise.
8979+ */
8980+static int __ccs_socket_listen_permission(struct socket *sock)
8981+{
8982+ struct ccs_addr_info address;
8983+ const u8 family = ccs_sock_family(sock->sk);
8984+ const unsigned int type = sock->type;
8985+ struct sockaddr_storage addr;
8986+ int addr_len;
8987+ if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
8988+ return 0;
8989+ {
8990+ const int error = sock->ops->getname(sock, (struct sockaddr *)
8991+ &addr, &addr_len, 0);
8992+ if (error)
8993+ return error;
8994+ }
8995+ address.protocol = type;
8996+ address.operation = CCS_NETWORK_LISTEN;
8997+ if (family == PF_UNIX)
8998+ return ccs_check_unix_address((struct sockaddr *) &addr,
8999+ addr_len, &address);
9000+ return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
9001+ &address);
9002+}
9003+
9004+/**
9005+ * __ccs_socket_connect_permission - Check permission for setting the remote address of a socket.
9006+ *
9007+ * @sock: Pointer to "struct socket".
9008+ * @addr: Pointer to "struct sockaddr".
9009+ * @addr_len: Size of @addr.
9010+ *
9011+ * Returns 0 on success, negative value otherwise.
9012+ */
9013+static int __ccs_socket_connect_permission(struct socket *sock,
9014+ struct sockaddr *addr, int addr_len)
9015+{
9016+ struct ccs_addr_info address;
9017+ const u8 family = ccs_sock_family(sock->sk);
9018+ const unsigned int type = sock->type;
9019+ if (!family)
9020+ return 0;
9021+ address.protocol = type;
9022+ switch (type) {
9023+ case SOCK_DGRAM:
9024+ case SOCK_RAW:
9025+ address.operation = CCS_NETWORK_SEND;
9026+ break;
9027+ case SOCK_STREAM:
9028+ case SOCK_SEQPACKET:
9029+ address.operation = CCS_NETWORK_CONNECT;
9030+ break;
9031+ default:
9032+ return 0;
9033+ }
9034+ if (family == PF_UNIX)
9035+ return ccs_check_unix_address(addr, addr_len, &address);
9036+ return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
9037+ &address);
9038+}
9039+
9040+/**
9041+ * __ccs_socket_bind_permission - Check permission for setting the local address of a socket.
9042+ *
9043+ * @sock: Pointer to "struct socket".
9044+ * @addr: Pointer to "struct sockaddr".
9045+ * @addr_len: Size of @addr.
9046+ *
9047+ * Returns 0 on success, negative value otherwise.
9048+ */
9049+static int __ccs_socket_bind_permission(struct socket *sock,
9050+ struct sockaddr *addr, int addr_len)
9051+{
9052+ struct ccs_addr_info address;
9053+ const u8 family = ccs_sock_family(sock->sk);
9054+ const unsigned int type = sock->type;
9055+ if (!family)
9056+ return 0;
9057+ switch (type) {
9058+ case SOCK_STREAM:
9059+ case SOCK_DGRAM:
9060+ case SOCK_RAW:
9061+ case SOCK_SEQPACKET:
9062+ address.protocol = type;
9063+ address.operation = CCS_NETWORK_BIND;
9064+ break;
9065+ default:
9066+ return 0;
9067+ }
9068+ if (family == PF_UNIX)
9069+ return ccs_check_unix_address(addr, addr_len, &address);
9070+ return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
9071+ &address);
9072+}
9073+
9074+/**
9075+ * __ccs_socket_sendmsg_permission - Check permission for sending a datagram.
9076+ *
9077+ * @sock: Pointer to "struct socket".
9078+ * @msg: Pointer to "struct msghdr".
9079+ * @size: Unused.
9080+ *
9081+ * Returns 0 on success, negative value otherwise.
9082+ */
9083+static int __ccs_socket_sendmsg_permission(struct socket *sock,
9084+ struct msghdr *msg, int size)
9085+{
9086+ struct ccs_addr_info address;
9087+ const u8 family = ccs_sock_family(sock->sk);
9088+ const unsigned int type = sock->type;
9089+ if (!msg->msg_name || !family ||
9090+ (type != SOCK_DGRAM && type != SOCK_RAW))
9091+ return 0;
9092+ address.protocol = type;
9093+ address.operation = CCS_NETWORK_SEND;
9094+ if (family == PF_UNIX)
9095+ return ccs_check_unix_address((struct sockaddr *)
9096+ msg->msg_name, msg->msg_namelen,
9097+ &address);
9098+ return ccs_check_inet_address((struct sockaddr *) msg->msg_name,
9099+ msg->msg_namelen, sock->sk->sk_protocol,
9100+ &address);
9101+}
9102+
9103+/**
9104+ * __ccs_socket_post_accept_permission - Check permission for accepting a socket.
9105+ *
9106+ * @sock: Pointer to "struct socket".
9107+ * @newsock: Pointer to "struct socket".
9108+ *
9109+ * Returns 0 on success, negative value otherwise.
9110+ */
9111+static int __ccs_socket_post_accept_permission(struct socket *sock,
9112+ struct socket *newsock)
9113+{
9114+ struct ccs_addr_info address;
9115+ const u8 family = ccs_sock_family(sock->sk);
9116+ const unsigned int type = sock->type;
9117+ struct sockaddr_storage addr;
9118+ int addr_len;
9119+ if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
9120+ return 0;
9121+ {
9122+ const int error = newsock->ops->getname(newsock,
9123+ (struct sockaddr *)
9124+ &addr, &addr_len, 2);
9125+ if (error)
9126+ return error;
9127+ }
9128+ address.protocol = type;
9129+ address.operation = CCS_NETWORK_ACCEPT;
9130+ if (family == PF_UNIX)
9131+ return ccs_check_unix_address((struct sockaddr *) &addr,
9132+ addr_len, &address);
9133+ return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
9134+ &address);
9135+}
9136+
9137+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
9138+
9139+/**
9140+ * __ccs_socket_post_recvmsg_permission - Check permission for receiving a datagram.
9141+ *
9142+ * @sk: Pointer to "struct sock".
9143+ * @skb: Pointer to "struct sk_buff".
9144+ * @flags: Flags passed to skb_recv_datagram().
9145+ *
9146+ * Returns 0 on success, negative value otherwise.
9147+ */
9148+static int __ccs_socket_post_recvmsg_permission(struct sock *sk,
9149+ struct sk_buff *skb, int flags)
9150+{
9151+ struct ccs_addr_info address;
9152+ const u8 family = ccs_sock_family(sk);
9153+ const unsigned int type = sk->sk_type;
9154+ struct sockaddr_storage addr;
9155+ if (!family)
9156+ return 0;
9157+ switch (type) {
9158+ case SOCK_DGRAM:
9159+ case SOCK_RAW:
9160+ address.protocol = type;
9161+ break;
9162+ default:
9163+ return 0;
9164+ }
9165+ address.operation = CCS_NETWORK_RECV;
9166+ switch (family) {
9167+ case PF_INET6:
9168+ {
9169+ struct in6_addr *sin6 = (struct in6_addr *) &addr;
9170+ address.inet.is_ipv6 = true;
9171+ if (type == SOCK_DGRAM &&
9172+ skb->protocol == htons(ETH_P_IP))
9173+ ipv6_addr_set(sin6, 0, 0, htonl(0xffff),
9174+ ip_hdr(skb)->saddr);
9175+ else
9176+ *sin6 = ipv6_hdr(skb)->saddr;
9177+ break;
9178+ }
9179+ case PF_INET:
9180+ {
9181+ struct in_addr *sin4 = (struct in_addr *) &addr;
9182+ address.inet.is_ipv6 = false;
9183+ sin4->s_addr = ip_hdr(skb)->saddr;
9184+ break;
9185+ }
9186+ default: /* == PF_UNIX */
9187+ {
9188+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
9189+ struct unix_address *u = unix_sk(skb->sk)->addr;
9190+#else
9191+ struct unix_address *u =
9192+ skb->sk->protinfo.af_unix.addr;
9193+#endif
9194+ unsigned int addr_len;
9195+ if (u && u->len <= sizeof(addr)) {
9196+ addr_len = u->len;
9197+ memcpy(&addr, u->name, addr_len);
9198+ } else {
9199+ addr_len = 0;
9200+ addr.ss_family = AF_UNIX;
9201+ }
9202+ if (ccs_check_unix_address((struct sockaddr *) &addr,
9203+ addr_len, &address))
9204+ goto out;
9205+ return 0;
9206+ }
9207+ }
9208+ address.inet.address = (u32 *) &addr;
9209+ if (type == SOCK_DGRAM)
9210+ address.inet.port = udp_hdr(skb)->source;
9211+ else
9212+ address.inet.port = htons(sk->sk_protocol);
9213+ if (ccs_inet_entry(&address))
9214+ goto out;
9215+ return 0;
9216+out:
9217+ /*
9218+ * Remove from queue if MSG_PEEK is used so that
9219+ * the head message from unwanted source in receive queue will not
9220+ * prevent the caller from picking up next message from wanted source
9221+ * when the caller is using MSG_PEEK flag for picking up.
9222+ */
9223+ {
9224+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
9225+ bool slow = false;
9226+ if (type == SOCK_DGRAM && family != PF_UNIX)
9227+ slow = lock_sock_fast(sk);
9228+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
9229+ if (type == SOCK_DGRAM && family != PF_UNIX)
9230+ lock_sock(sk);
9231+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 2
9232+ if (type == SOCK_DGRAM && family != PF_UNIX)
9233+ lock_sock(sk);
9234+#endif
9235+ skb_kill_datagram(sk, skb, flags);
9236+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
9237+ if (type == SOCK_DGRAM && family != PF_UNIX)
9238+ unlock_sock_fast(sk, slow);
9239+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
9240+ if (type == SOCK_DGRAM && family != PF_UNIX)
9241+ release_sock(sk);
9242+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 2
9243+ if (type == SOCK_DGRAM && family != PF_UNIX)
9244+ release_sock(sk);
9245+#endif
9246+ }
9247+ return -EPERM;
9248+}
9249+
9250+#endif
9251+
9252+#endif
9253+
9254+#if defined(CONFIG_CCSECURITY_CAPABILITY) || defined(CONFIG_CCSECURITY_NETWORK)
9255+
9256+/**
9257+ * ccs_kernel_service - Check whether I'm kernel service or not.
9258+ *
9259+ * Returns true if I'm kernel service, false otherwise.
9260+ */
9261+static bool ccs_kernel_service(void)
9262+{
9263+ /* Nothing to do if I am a kernel service. */
9264+ return segment_eq(get_fs(), KERNEL_DS);
9265+}
9266+
9267+#endif
9268+
9269+#ifdef CONFIG_CCSECURITY_CAPABILITY
9270+
9271+/**
9272+ * ccs_check_capability_acl - Check permission for capability operation.
9273+ *
9274+ * @r: Pointer to "struct ccs_request_info".
9275+ * @ptr: Pointer to "struct ccs_acl_info".
9276+ *
9277+ * Returns true if granted, false otherwise.
9278+ */
9279+static bool ccs_check_capability_acl(struct ccs_request_info *r,
9280+ const struct ccs_acl_info *ptr)
9281+{
9282+ const struct ccs_capability_acl *acl =
9283+ container_of(ptr, typeof(*acl), head);
9284+ return acl->operation == r->param.capability.operation;
9285+}
9286+
9287+/**
9288+ * ccs_capable - Check permission for capability.
9289+ *
9290+ * @operation: Type of operation.
9291+ *
9292+ * Returns true on success, false otherwise.
9293+ */
9294+static bool __ccs_capable(const u8 operation)
9295+{
9296+ struct ccs_request_info r;
9297+ int error = 0;
9298+ const int idx = ccs_read_lock();
9299+ if (ccs_init_request_info(&r, ccs_c2mac[operation])
9300+ != CCS_CONFIG_DISABLED) {
9301+ r.param_type = CCS_TYPE_CAPABILITY_ACL;
9302+ r.param.capability.operation = operation;
9303+ error = ccs_check_acl(&r);
9304+ }
9305+ ccs_read_unlock(idx);
9306+ return !error;
9307+}
9308+
9309+/**
9310+ * __ccs_socket_create_permission - Check permission for creating a socket.
9311+ *
9312+ * @family: Protocol family.
9313+ * @type: Unused.
9314+ * @protocol: Unused.
9315+ *
9316+ * Returns 0 on success, negative value otherwise.
9317+ */
9318+static int __ccs_socket_create_permission(int family, int type, int protocol)
9319+{
9320+ if (ccs_kernel_service())
9321+ return 0;
9322+ if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
9323+ return -EPERM;
9324+ if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
9325+ return -EPERM;
9326+ return 0;
9327+}
9328+
9329+/**
9330+ * __ccs_ptrace_permission - Check permission for ptrace().
9331+ *
9332+ * @request: Unused.
9333+ * @pid: Unused.
9334+ *
9335+ * Returns 0 on success, negative value otherwise.
9336+ *
9337+ * Since this function is called from location where it is permitted to sleep,
9338+ * it is racy to check target process's domainname anyway. Therefore, we don't
9339+ * use target process's domainname.
9340+ */
9341+static int __ccs_ptrace_permission(long request, long pid)
9342+{
9343+ return __ccs_capable(CCS_SYS_PTRACE) ? 0 : -EPERM;
9344+}
9345+
9346+#endif
9347+
9348+#ifdef CONFIG_CCSECURITY_IPC
9349+
9350+/**
9351+ * ccs_check_signal_acl - Check permission for signal operation.
9352+ *
9353+ * @r: Pointer to "struct ccs_request_info".
9354+ * @ptr: Pointer to "struct ccs_acl_info".
9355+ *
9356+ * Returns true if granted, false otherwise.
9357+ */
9358+static bool ccs_check_signal_acl(struct ccs_request_info *r,
9359+ const struct ccs_acl_info *ptr)
9360+{
9361+ const struct ccs_signal_acl *acl =
9362+ container_of(ptr, typeof(*acl), head);
9363+ if (ccs_compare_number_union(r->param.signal.sig, &acl->sig)) {
9364+ const int len = acl->domainname->total_len;
9365+ if (!strncmp(acl->domainname->name,
9366+ r->param.signal.dest_pattern, len)) {
9367+ switch (r->param.signal.dest_pattern[len]) {
9368+ case ' ':
9369+ case '\0':
9370+ return true;
9371+ }
9372+ }
9373+ }
9374+ return false;
9375+}
9376+
9377+/**
9378+ * ccs_signal_acl2 - Check permission for signal.
9379+ *
9380+ * @sig: Signal number.
9381+ * @pid: Target's PID.
9382+ *
9383+ * Returns 0 on success, negative value otherwise.
9384+ *
9385+ * Caller holds ccs_read_lock().
9386+ */
9387+static int ccs_signal_acl2(const int sig, const int pid)
9388+{
9389+ struct ccs_request_info r;
9390+ struct ccs_domain_info *dest = NULL;
9391+ const struct ccs_domain_info * const domain = ccs_current_domain();
9392+ if (ccs_init_request_info(&r, CCS_MAC_SIGNAL) == CCS_CONFIG_DISABLED)
9393+ return 0;
9394+ if (!sig)
9395+ return 0; /* No check for NULL signal. */
9396+ r.param_type = CCS_TYPE_SIGNAL_ACL;
9397+ r.param.signal.sig = sig;
9398+ r.param.signal.dest_pattern = domain->domainname->name;
9399+ r.granted = true;
9400+ if (ccs_sys_getpid() == pid) {
9401+ ccs_audit_log(&r);
9402+ return 0; /* No check for self process. */
9403+ }
9404+ { /* Simplified checking. */
9405+ struct task_struct *p = NULL;
9406+ ccs_tasklist_lock();
9407+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
9408+ if (pid > 0)
9409+ p = ccsecurity_exports.find_task_by_vpid((pid_t) pid);
9410+ else if (pid == 0)
9411+ p = current;
9412+ else if (pid == -1)
9413+ dest = &ccs_kernel_domain;
9414+ else
9415+ p = ccsecurity_exports.find_task_by_vpid((pid_t) -pid);
9416+#else
9417+ if (pid > 0)
9418+ p = find_task_by_pid((pid_t) pid);
9419+ else if (pid == 0)
9420+ p = current;
9421+ else if (pid == -1)
9422+ dest = &ccs_kernel_domain;
9423+ else
9424+ p = find_task_by_pid((pid_t) -pid);
9425+#endif
9426+ if (p)
9427+ dest = ccs_task_domain(p);
9428+ ccs_tasklist_unlock();
9429+ }
9430+ if (!dest)
9431+ return 0; /* I can't find destinatioin. */
9432+ if (domain == dest) {
9433+ ccs_audit_log(&r);
9434+ return 0; /* No check for self domain. */
9435+ }
9436+ r.param.signal.dest_pattern = dest->domainname->name;
9437+ return ccs_check_acl(&r);
9438+}
9439+
9440+/**
9441+ * ccs_signal_acl - Check permission for signal.
9442+ *
9443+ * @pid: Target's PID.
9444+ * @sig: Signal number.
9445+ *
9446+ * Returns 0 on success, negative value otherwise.
9447+ */
9448+static int ccs_signal_acl(const int pid, const int sig)
9449+{
9450+ int error;
9451+ if (!sig)
9452+ error = 0;
9453+ else {
9454+ const int idx = ccs_read_lock();
9455+ error = ccs_signal_acl2(sig, pid);
9456+ ccs_read_unlock(idx);
9457+ }
9458+ return error;
9459+}
9460+
9461+/**
9462+ * ccs_signal_acl0 - Permission check for signal().
9463+ *
9464+ * @tgid: Unused.
9465+ * @pid: Target's PID.
9466+ * @sig: Signal number.
9467+ *
9468+ * Returns 0 on success, negative value otherwise.
9469+ */
9470+static int ccs_signal_acl0(pid_t tgid, pid_t pid, int sig)
9471+{
9472+ return ccs_signal_acl(pid, sig);
9473+}
9474+
9475+#endif
9476+
9477+#ifdef CONFIG_CCSECURITY_MISC
9478+
9479+/**
9480+ * ccs_check_env_acl - Check permission for environment variable's name.
9481+ *
9482+ * @r: Pointer to "struct ccs_request_info".
9483+ * @ptr: Pointer to "struct ccs_acl_info".
9484+ *
9485+ * Returns true if granted, false otherwise.
9486+ */
9487+static bool ccs_check_env_acl(struct ccs_request_info *r,
9488+ const struct ccs_acl_info *ptr)
9489+{
9490+ const struct ccs_env_acl *acl = container_of(ptr, typeof(*acl), head);
9491+ return ccs_path_matches_pattern(r->param.environ.name, acl->env);
9492+}
9493+
9494+/**
9495+ * ccs_env_perm - Check permission for environment variable's name.
9496+ *
9497+ * @r: Pointer to "struct ccs_request_info".
9498+ * @env: The name of environment variable.
9499+ *
9500+ * Returns 0 on success, negative value otherwise.
9501+ *
9502+ * Caller holds ccs_read_lock().
9503+ */
9504+static int ccs_env_perm(struct ccs_request_info *r, const char *env)
9505+{
9506+ struct ccs_path_info environ;
9507+ if (!env || !*env)
9508+ return 0;
9509+ environ.name = env;
9510+ ccs_fill_path_info(&environ);
9511+ r->param_type = CCS_TYPE_ENV_ACL;
9512+ r->param.environ.name = &environ;
9513+ return ccs_check_acl(r);
9514+}
9515+
9516+/**
9517+ * ccs_environ - Check permission for environment variable names.
9518+ *
9519+ * @ee: Pointer to "struct ccs_execve".
9520+ *
9521+ * Returns 0 on success, negative value otherwise.
9522+ */
9523+static int ccs_environ(struct ccs_execve *ee)
9524+{
9525+ struct ccs_request_info *r = &ee->r;
9526+ struct linux_binprm *bprm = ee->bprm;
9527+ /* env_page.data is allocated by ccs_dump_page(). */
9528+ struct ccs_page_dump env_page = { };
9529+ char *arg_ptr; /* Size is CCS_EXEC_TMPSIZE bytes */
9530+ int arg_len = 0;
9531+ unsigned long pos = bprm->p;
9532+ int offset = pos % PAGE_SIZE;
9533+ int argv_count = bprm->argc;
9534+ int envp_count = bprm->envc;
9535+ /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
9536+ int error = -ENOMEM;
9537+ ee->r.type = CCS_MAC_ENVIRON;
9538+ ee->r.profile = ccs_current_domain()->profile;
9539+ ee->r.mode = ccs_get_mode(ee->r.profile, CCS_MAC_ENVIRON);
9540+ if (!r->mode || !envp_count)
9541+ return 0;
9542+ arg_ptr = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
9543+ if (!arg_ptr)
9544+ goto out;
9545+ while (error == -ENOMEM) {
9546+ if (!ccs_dump_page(bprm, pos, &env_page))
9547+ goto out;
9548+ pos += PAGE_SIZE - offset;
9549+ /* Read. */
9550+ while (argv_count && offset < PAGE_SIZE) {
9551+ if (!env_page.data[offset++])
9552+ argv_count--;
9553+ }
9554+ if (argv_count) {
9555+ offset = 0;
9556+ continue;
9557+ }
9558+ while (offset < PAGE_SIZE) {
9559+ const unsigned char c = env_page.data[offset++];
9560+ if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
9561+ if (c == '=') {
9562+ arg_ptr[arg_len++] = '\0';
9563+ } else if (c == '\\') {
9564+ arg_ptr[arg_len++] = '\\';
9565+ arg_ptr[arg_len++] = '\\';
9566+ } else if (c > ' ' && c < 127) {
9567+ arg_ptr[arg_len++] = c;
9568+ } else {
9569+ arg_ptr[arg_len++] = '\\';
9570+ arg_ptr[arg_len++] = (c >> 6) + '0';
9571+ arg_ptr[arg_len++]
9572+ = ((c >> 3) & 7) + '0';
9573+ arg_ptr[arg_len++] = (c & 7) + '0';
9574+ }
9575+ } else {
9576+ arg_ptr[arg_len] = '\0';
9577+ }
9578+ if (c)
9579+ continue;
9580+ if (ccs_env_perm(r, arg_ptr)) {
9581+ error = -EPERM;
9582+ break;
9583+ }
9584+ if (!--envp_count) {
9585+ error = 0;
9586+ break;
9587+ }
9588+ arg_len = 0;
9589+ }
9590+ offset = 0;
9591+ }
9592+out:
9593+ if (r->mode != CCS_CONFIG_ENFORCING)
9594+ error = 0;
9595+ kfree(env_page.data);
9596+ kfree(arg_ptr);
9597+ return error;
9598+}
9599+
9600+#endif
9601+
9602+/**
9603+ * ccs_argv - Check argv[] in "struct linux_binbrm".
9604+ *
9605+ * @index: Index number of @arg_ptr.
9606+ * @arg_ptr: Contents of argv[@index].
9607+ * @argc: Length of @argv.
9608+ * @argv: Pointer to "struct ccs_argv".
9609+ * @checked: Set to true if @argv[@index] was found.
9610+ *
9611+ * Returns true on success, false otherwise.
9612+ */
9613+static bool ccs_argv(const unsigned int index, const char *arg_ptr,
9614+ const int argc, const struct ccs_argv *argv,
9615+ u8 *checked)
9616+{
9617+ int i;
9618+ struct ccs_path_info arg;
9619+ arg.name = arg_ptr;
9620+ for (i = 0; i < argc; argv++, checked++, i++) {
9621+ bool result;
9622+ if (index != argv->index)
9623+ continue;
9624+ *checked = 1;
9625+ ccs_fill_path_info(&arg);
9626+ result = ccs_path_matches_pattern(&arg, argv->value);
9627+ if (argv->is_not)
9628+ result = !result;
9629+ if (!result)
9630+ return false;
9631+ }
9632+ return true;
9633+}
9634+
9635+/**
9636+ * ccs_envp - Check envp[] in "struct linux_binbrm".
9637+ *
9638+ * @env_name: The name of environment variable.
9639+ * @env_value: The value of environment variable.
9640+ * @envc: Length of @envp.
9641+ * @envp: Pointer to "struct ccs_envp".
9642+ * @checked: Set to true if @envp[@env_name] was found.
9643+ *
9644+ * Returns true on success, false otherwise.
9645+ */
9646+static bool ccs_envp(const char *env_name, const char *env_value,
9647+ const int envc, const struct ccs_envp *envp,
9648+ u8 *checked)
9649+{
9650+ int i;
9651+ struct ccs_path_info name;
9652+ struct ccs_path_info value;
9653+ name.name = env_name;
9654+ ccs_fill_path_info(&name);
9655+ value.name = env_value;
9656+ ccs_fill_path_info(&value);
9657+ for (i = 0; i < envc; envp++, checked++, i++) {
9658+ bool result;
9659+ if (!ccs_path_matches_pattern(&name, envp->name))
9660+ continue;
9661+ *checked = 1;
9662+ if (envp->value) {
9663+ result = ccs_path_matches_pattern(&value, envp->value);
9664+ if (envp->is_not)
9665+ result = !result;
9666+ } else {
9667+ result = true;
9668+ if (!envp->is_not)
9669+ result = !result;
9670+ }
9671+ if (!result)
9672+ return false;
9673+ }
9674+ return true;
9675+}
9676+
9677+/**
9678+ * ccs_scan_bprm - Scan "struct linux_binprm".
9679+ *
9680+ * @ee: Pointer to "struct ccs_execve".
9681+ * @argc: Length of @argc.
9682+ * @argv: Pointer to "struct ccs_argv".
9683+ * @envc: Length of @envp.
9684+ * @envp: Poiner to "struct ccs_envp".
9685+ *
9686+ * Returns true on success, false otherwise.
9687+ */
9688+static bool ccs_scan_bprm(struct ccs_execve *ee,
9689+ const u16 argc, const struct ccs_argv *argv,
9690+ const u16 envc, const struct ccs_envp *envp)
9691+{
9692+ struct linux_binprm *bprm = ee->bprm;
9693+ struct ccs_page_dump *dump = &ee->dump;
9694+ char *arg_ptr = ee->tmp;
9695+ int arg_len = 0;
9696+ unsigned long pos = bprm->p;
9697+ int offset = pos % PAGE_SIZE;
9698+ int argv_count = bprm->argc;
9699+ int envp_count = bprm->envc;
9700+ bool result = true;
9701+ u8 local_checked[32];
9702+ u8 *checked;
9703+ if (argc + envc <= sizeof(local_checked)) {
9704+ checked = local_checked;
9705+ memset(local_checked, 0, sizeof(local_checked));
9706+ } else {
9707+ checked = kzalloc(argc + envc, CCS_GFP_FLAGS);
9708+ if (!checked)
9709+ return false;
9710+ }
9711+ while (argv_count || envp_count) {
9712+ if (!ccs_dump_page(bprm, pos, dump)) {
9713+ result = false;
9714+ goto out;
9715+ }
9716+ pos += PAGE_SIZE - offset;
9717+ while (offset < PAGE_SIZE) {
9718+ /* Read. */
9719+ const char *kaddr = dump->data;
9720+ const unsigned char c = kaddr[offset++];
9721+ if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
9722+ if (c == '\\') {
9723+ arg_ptr[arg_len++] = '\\';
9724+ arg_ptr[arg_len++] = '\\';
9725+ } else if (c > ' ' && c < 127) {
9726+ arg_ptr[arg_len++] = c;
9727+ } else {
9728+ arg_ptr[arg_len++] = '\\';
9729+ arg_ptr[arg_len++] = (c >> 6) + '0';
9730+ arg_ptr[arg_len++] =
9731+ ((c >> 3) & 7) + '0';
9732+ arg_ptr[arg_len++] = (c & 7) + '0';
9733+ }
9734+ } else {
9735+ arg_ptr[arg_len] = '\0';
9736+ }
9737+ if (c)
9738+ continue;
9739+ /* Check. */
9740+ if (argv_count) {
9741+ if (!ccs_argv(bprm->argc - argv_count,
9742+ arg_ptr, argc, argv,
9743+ checked)) {
9744+ result = false;
9745+ break;
9746+ }
9747+ argv_count--;
9748+ } else if (envp_count) {
9749+ char *cp = strchr(arg_ptr, '=');
9750+ if (cp) {
9751+ *cp = '\0';
9752+ if (!ccs_envp(arg_ptr, cp + 1,
9753+ envc, envp,
9754+ checked + argc)) {
9755+ result = false;
9756+ break;
9757+ }
9758+ }
9759+ envp_count--;
9760+ } else {
9761+ break;
9762+ }
9763+ arg_len = 0;
9764+ }
9765+ offset = 0;
9766+ if (!result)
9767+ break;
9768+ }
9769+out:
9770+ if (result) {
9771+ int i;
9772+ /* Check not-yet-checked entries. */
9773+ for (i = 0; i < argc; i++) {
9774+ if (checked[i])
9775+ continue;
9776+ /*
9777+ * Return true only if all unchecked indexes in
9778+ * bprm->argv[] are not matched.
9779+ */
9780+ if (argv[i].is_not)
9781+ continue;
9782+ result = false;
9783+ break;
9784+ }
9785+ for (i = 0; i < envc; envp++, i++) {
9786+ if (checked[argc + i])
9787+ continue;
9788+ /*
9789+ * Return true only if all unchecked environ variables
9790+ * in bprm->envp[] are either undefined or not matched.
9791+ */
9792+ if ((!envp->value && !envp->is_not) ||
9793+ (envp->value && envp->is_not))
9794+ continue;
9795+ result = false;
9796+ break;
9797+ }
9798+ }
9799+ if (checked != local_checked)
9800+ kfree(checked);
9801+ return result;
9802+}
9803+
9804+/**
9805+ * ccs_scan_exec_realpath - Check "exec.realpath" parameter of "struct ccs_condition".
9806+ *
9807+ * @file: Pointer to "struct file".
9808+ * @ptr: Pointer to "struct ccs_name_union".
9809+ * @match: True if "exec.realpath=", false if "exec.realpath!=".
9810+ *
9811+ * Returns true on success, false otherwise.
9812+ */
9813+static bool ccs_scan_exec_realpath(struct file *file,
9814+ const struct ccs_name_union *ptr,
9815+ const bool match)
9816+{
9817+ bool result;
9818+ struct ccs_path_info exe;
9819+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
9820+ struct path path;
9821+#endif
9822+ if (!file)
9823+ return false;
9824+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
9825+ exe.name = ccs_realpath(&file->f_path);
9826+#else
9827+ path.mnt = file->f_vfsmnt;
9828+ path.dentry = file->f_dentry;
9829+ exe.name = ccs_realpath(&path);
9830+#endif
9831+ if (!exe.name)
9832+ return false;
9833+ ccs_fill_path_info(&exe);
9834+ result = ccs_compare_name_union(&exe, ptr);
9835+ kfree(exe.name);
9836+ return result == match;
9837+}
9838+
9839+/**
9840+ * ccs_get_attributes - Revalidate "struct inode".
9841+ *
9842+ * @obj: Pointer to "struct ccs_obj_info".
9843+ *
9844+ * Returns nothing.
9845+ */
9846+void ccs_get_attributes(struct ccs_obj_info *obj)
9847+{
9848+ u8 i;
9849+ struct dentry *dentry = NULL;
9850+
9851+ for (i = 0; i < CCS_MAX_PATH_STAT; i++) {
9852+ struct inode *inode;
9853+ switch (i) {
9854+ case CCS_PATH1:
9855+ dentry = obj->path1.dentry;
9856+ if (!dentry)
9857+ continue;
9858+ break;
9859+ case CCS_PATH2:
9860+ dentry = obj->path2.dentry;
9861+ if (!dentry)
9862+ continue;
9863+ break;
9864+ default:
9865+ if (!dentry)
9866+ continue;
9867+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
9868+ spin_lock(&dcache_lock);
9869+ dentry = dget(dentry->d_parent);
9870+ spin_unlock(&dcache_lock);
9871+#else
9872+ dentry = dget_parent(dentry);
9873+#endif
9874+ break;
9875+ }
9876+ inode = dentry->d_inode;
9877+ if (inode) {
9878+ struct ccs_mini_stat *stat = &obj->stat[i];
9879+ stat->uid = inode->i_uid;
9880+ stat->gid = inode->i_gid;
9881+ stat->ino = inode->i_ino;
9882+ stat->mode = inode->i_mode;
9883+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
9884+ stat->dev = inode->i_dev;
9885+#else
9886+ stat->dev = inode->i_sb->s_dev;
9887+#endif
9888+ stat->rdev = inode->i_rdev;
9889+ obj->stat_valid[i] = true;
9890+ }
9891+ if (i & 1) /* i == CCS_PATH1_PARENT || i == CCS_PATH2_PARENT */
9892+ dput(dentry);
9893+ }
9894+}
9895+
9896+/**
9897+ * ccs_condition - Check condition part.
9898+ *
9899+ * @r: Pointer to "struct ccs_request_info".
9900+ * @cond: Pointer to "struct ccs_condition". Maybe NULL.
9901+ *
9902+ * Returns true on success, false otherwise.
9903+ *
9904+ * Caller holds ccs_read_lock().
9905+ */
9906+static bool ccs_condition(struct ccs_request_info *r,
9907+ const struct ccs_condition *cond)
9908+{
9909+ const u32 ccs_flags = ccs_current_flags();
9910+ u32 i;
9911+ unsigned long min_v[2] = { 0, 0 };
9912+ unsigned long max_v[2] = { 0, 0 };
9913+ const struct ccs_condition_element *condp;
9914+ const struct ccs_number_union *numbers_p;
9915+ const struct ccs_name_union *names_p;
9916+ const struct ccs_argv *argv;
9917+ const struct ccs_envp *envp;
9918+ struct ccs_obj_info *obj;
9919+ u16 condc;
9920+ u16 argc;
9921+ u16 envc;
9922+ struct linux_binprm *bprm = NULL;
9923+ if (!cond)
9924+ return true;
9925+ condc = cond->condc;
9926+ argc = cond->argc;
9927+ envc = cond->envc;
9928+ obj = r->obj;
9929+ if (r->ee)
9930+ bprm = r->ee->bprm;
9931+ if (!bprm && (argc || envc))
9932+ return false;
9933+ condp = (struct ccs_condition_element *) (cond + 1);
9934+ numbers_p = (const struct ccs_number_union *) (condp + condc);
9935+ names_p = (const struct ccs_name_union *)
9936+ (numbers_p + cond->numbers_count);
9937+ argv = (const struct ccs_argv *) (names_p + cond->names_count);
9938+ envp = (const struct ccs_envp *) (argv + argc);
9939+ for (i = 0; i < condc; i++) {
9940+ const bool match = condp->equals;
9941+ const u8 left = condp->left;
9942+ const u8 right = condp->right;
9943+ bool is_bitop[2] = { false, false };
9944+ u8 j;
9945+ condp++;
9946+ /* Check argv[] and envp[] later. */
9947+ if (left == CCS_ARGV_ENTRY || left == CCS_ENVP_ENTRY)
9948+ continue;
9949+ /* Check string expressions. */
9950+ if (right == CCS_NAME_UNION) {
9951+ const struct ccs_name_union *ptr = names_p++;
9952+ switch (left) {
9953+ struct ccs_path_info *symlink;
9954+ struct ccs_execve *ee;
9955+ struct file *file;
9956+ case CCS_SYMLINK_TARGET:
9957+ symlink = obj ? obj->symlink_target : NULL;
9958+ if (!symlink ||
9959+ !ccs_compare_name_union(symlink, ptr)
9960+ == match)
9961+ goto out;
9962+ break;
9963+ case CCS_EXEC_REALPATH:
9964+ ee = r->ee;
9965+ file = ee ? ee->bprm->file : NULL;
9966+ if (!ccs_scan_exec_realpath(file, ptr, match))
9967+ goto out;
9968+ break;
9969+ }
9970+ continue;
9971+ }
9972+ /* Check numeric or bit-op expressions. */
9973+ for (j = 0; j < 2; j++) {
9974+ const u8 index = j ? right : left;
9975+ unsigned long value = 0;
9976+ switch (index) {
9977+ case CCS_TASK_UID:
9978+ value = from_kuid(&init_user_ns,
9979+ current_uid());
9980+ break;
9981+ case CCS_TASK_EUID:
9982+ value = from_kuid(&init_user_ns,
9983+ current_euid());
9984+ break;
9985+ case CCS_TASK_SUID:
9986+ value = from_kuid(&init_user_ns,
9987+ current_suid());
9988+ break;
9989+ case CCS_TASK_FSUID:
9990+ value = from_kuid(&init_user_ns,
9991+ current_fsuid());
9992+ break;
9993+ case CCS_TASK_GID:
9994+ value = from_kgid(&init_user_ns,
9995+ current_gid());
9996+ break;
9997+ case CCS_TASK_EGID:
9998+ value = from_kgid(&init_user_ns,
9999+ current_egid());
10000+ break;
10001+ case CCS_TASK_SGID:
10002+ value = from_kgid(&init_user_ns,
10003+ current_sgid());
10004+ break;
10005+ case CCS_TASK_FSGID:
10006+ value = from_kgid(&init_user_ns,
10007+ current_fsgid());
10008+ break;
10009+ case CCS_TASK_PID:
10010+ value = ccs_sys_getpid();
10011+ break;
10012+ case CCS_TASK_PPID:
10013+ value = ccs_sys_getppid();
10014+ break;
10015+ case CCS_TYPE_IS_SOCKET:
10016+ value = S_IFSOCK;
10017+ break;
10018+ case CCS_TYPE_IS_SYMLINK:
10019+ value = S_IFLNK;
10020+ break;
10021+ case CCS_TYPE_IS_FILE:
10022+ value = S_IFREG;
10023+ break;
10024+ case CCS_TYPE_IS_BLOCK_DEV:
10025+ value = S_IFBLK;
10026+ break;
10027+ case CCS_TYPE_IS_DIRECTORY:
10028+ value = S_IFDIR;
10029+ break;
10030+ case CCS_TYPE_IS_CHAR_DEV:
10031+ value = S_IFCHR;
10032+ break;
10033+ case CCS_TYPE_IS_FIFO:
10034+ value = S_IFIFO;
10035+ break;
10036+ case CCS_MODE_SETUID:
10037+ value = S_ISUID;
10038+ break;
10039+ case CCS_MODE_SETGID:
10040+ value = S_ISGID;
10041+ break;
10042+ case CCS_MODE_STICKY:
10043+ value = S_ISVTX;
10044+ break;
10045+ case CCS_MODE_OWNER_READ:
10046+ value = S_IRUSR;
10047+ break;
10048+ case CCS_MODE_OWNER_WRITE:
10049+ value = S_IWUSR;
10050+ break;
10051+ case CCS_MODE_OWNER_EXECUTE:
10052+ value = S_IXUSR;
10053+ break;
10054+ case CCS_MODE_GROUP_READ:
10055+ value = S_IRGRP;
10056+ break;
10057+ case CCS_MODE_GROUP_WRITE:
10058+ value = S_IWGRP;
10059+ break;
10060+ case CCS_MODE_GROUP_EXECUTE:
10061+ value = S_IXGRP;
10062+ break;
10063+ case CCS_MODE_OTHERS_READ:
10064+ value = S_IROTH;
10065+ break;
10066+ case CCS_MODE_OTHERS_WRITE:
10067+ value = S_IWOTH;
10068+ break;
10069+ case CCS_MODE_OTHERS_EXECUTE:
10070+ value = S_IXOTH;
10071+ break;
10072+ case CCS_EXEC_ARGC:
10073+ if (!bprm)
10074+ goto out;
10075+ value = bprm->argc;
10076+ break;
10077+ case CCS_EXEC_ENVC:
10078+ if (!bprm)
10079+ goto out;
10080+ value = bprm->envc;
10081+ break;
10082+ case CCS_TASK_TYPE:
10083+ value = ((u8) ccs_flags)
10084+ & CCS_TASK_IS_EXECUTE_HANDLER;
10085+ break;
10086+ case CCS_TASK_EXECUTE_HANDLER:
10087+ value = CCS_TASK_IS_EXECUTE_HANDLER;
10088+ break;
10089+ case CCS_NUMBER_UNION:
10090+ /* Fetch values later. */
10091+ break;
10092+ default:
10093+ if (!obj)
10094+ goto out;
10095+ if (!obj->validate_done) {
10096+ ccs_get_attributes(obj);
10097+ obj->validate_done = true;
10098+ }
10099+ {
10100+ u8 stat_index;
10101+ struct ccs_mini_stat *stat;
10102+ switch (index) {
10103+ case CCS_PATH1_UID:
10104+ case CCS_PATH1_GID:
10105+ case CCS_PATH1_INO:
10106+ case CCS_PATH1_MAJOR:
10107+ case CCS_PATH1_MINOR:
10108+ case CCS_PATH1_TYPE:
10109+ case CCS_PATH1_DEV_MAJOR:
10110+ case CCS_PATH1_DEV_MINOR:
10111+ case CCS_PATH1_PERM:
10112+ stat_index = CCS_PATH1;
10113+ break;
10114+ case CCS_PATH2_UID:
10115+ case CCS_PATH2_GID:
10116+ case CCS_PATH2_INO:
10117+ case CCS_PATH2_MAJOR:
10118+ case CCS_PATH2_MINOR:
10119+ case CCS_PATH2_TYPE:
10120+ case CCS_PATH2_DEV_MAJOR:
10121+ case CCS_PATH2_DEV_MINOR:
10122+ case CCS_PATH2_PERM:
10123+ stat_index = CCS_PATH2;
10124+ break;
10125+ case CCS_PATH1_PARENT_UID:
10126+ case CCS_PATH1_PARENT_GID:
10127+ case CCS_PATH1_PARENT_INO:
10128+ case CCS_PATH1_PARENT_PERM:
10129+ stat_index = CCS_PATH1_PARENT;
10130+ break;
10131+ case CCS_PATH2_PARENT_UID:
10132+ case CCS_PATH2_PARENT_GID:
10133+ case CCS_PATH2_PARENT_INO:
10134+ case CCS_PATH2_PARENT_PERM:
10135+ stat_index = CCS_PATH2_PARENT;
10136+ break;
10137+ default:
10138+ goto out;
10139+ }
10140+ if (!obj->stat_valid[stat_index])
10141+ goto out;
10142+ stat = &obj->stat[stat_index];
10143+ switch (index) {
10144+ case CCS_PATH1_UID:
10145+ case CCS_PATH2_UID:
10146+ case CCS_PATH1_PARENT_UID:
10147+ case CCS_PATH2_PARENT_UID:
10148+ value = from_kuid
10149+ (&init_user_ns,
10150+ stat->uid);
10151+ break;
10152+ case CCS_PATH1_GID:
10153+ case CCS_PATH2_GID:
10154+ case CCS_PATH1_PARENT_GID:
10155+ case CCS_PATH2_PARENT_GID:
10156+ value = from_kgid
10157+ (&init_user_ns,
10158+ stat->gid);
10159+ break;
10160+ case CCS_PATH1_INO:
10161+ case CCS_PATH2_INO:
10162+ case CCS_PATH1_PARENT_INO:
10163+ case CCS_PATH2_PARENT_INO:
10164+ value = stat->ino;
10165+ break;
10166+ case CCS_PATH1_MAJOR:
10167+ case CCS_PATH2_MAJOR:
10168+ value = MAJOR(stat->dev);
10169+ break;
10170+ case CCS_PATH1_MINOR:
10171+ case CCS_PATH2_MINOR:
10172+ value = MINOR(stat->dev);
10173+ break;
10174+ case CCS_PATH1_TYPE:
10175+ case CCS_PATH2_TYPE:
10176+ value = stat->mode & S_IFMT;
10177+ break;
10178+ case CCS_PATH1_DEV_MAJOR:
10179+ case CCS_PATH2_DEV_MAJOR:
10180+ value = MAJOR(stat->rdev);
10181+ break;
10182+ case CCS_PATH1_DEV_MINOR:
10183+ case CCS_PATH2_DEV_MINOR:
10184+ value = MINOR(stat->rdev);
10185+ break;
10186+ case CCS_PATH1_PERM:
10187+ case CCS_PATH2_PERM:
10188+ case CCS_PATH1_PARENT_PERM:
10189+ case CCS_PATH2_PARENT_PERM:
10190+ value = stat->mode & S_IALLUGO;
10191+ break;
10192+ }
10193+ }
10194+ break;
10195+ }
10196+ max_v[j] = value;
10197+ min_v[j] = value;
10198+ switch (index) {
10199+ case CCS_MODE_SETUID:
10200+ case CCS_MODE_SETGID:
10201+ case CCS_MODE_STICKY:
10202+ case CCS_MODE_OWNER_READ:
10203+ case CCS_MODE_OWNER_WRITE:
10204+ case CCS_MODE_OWNER_EXECUTE:
10205+ case CCS_MODE_GROUP_READ:
10206+ case CCS_MODE_GROUP_WRITE:
10207+ case CCS_MODE_GROUP_EXECUTE:
10208+ case CCS_MODE_OTHERS_READ:
10209+ case CCS_MODE_OTHERS_WRITE:
10210+ case CCS_MODE_OTHERS_EXECUTE:
10211+ is_bitop[j] = true;
10212+ }
10213+ }
10214+ if (left == CCS_NUMBER_UNION) {
10215+ /* Fetch values now. */
10216+ const struct ccs_number_union *ptr = numbers_p++;
10217+ min_v[0] = ptr->values[0];
10218+ max_v[0] = ptr->values[1];
10219+ }
10220+ if (right == CCS_NUMBER_UNION) {
10221+ /* Fetch values now. */
10222+ const struct ccs_number_union *ptr = numbers_p++;
10223+ if (ptr->group) {
10224+ if (ccs_number_matches_group(min_v[0],
10225+ max_v[0],
10226+ ptr->group)
10227+ == match)
10228+ continue;
10229+ } else {
10230+ if ((min_v[0] <= ptr->values[1] &&
10231+ max_v[0] >= ptr->values[0]) == match)
10232+ continue;
10233+ }
10234+ goto out;
10235+ }
10236+ /*
10237+ * Bit operation is valid only when counterpart value
10238+ * represents permission.
10239+ */
10240+ if (is_bitop[0] && is_bitop[1]) {
10241+ goto out;
10242+ } else if (is_bitop[0]) {
10243+ switch (right) {
10244+ case CCS_PATH1_PERM:
10245+ case CCS_PATH1_PARENT_PERM:
10246+ case CCS_PATH2_PERM:
10247+ case CCS_PATH2_PARENT_PERM:
10248+ if (!(max_v[0] & max_v[1]) == !match)
10249+ continue;
10250+ }
10251+ goto out;
10252+ } else if (is_bitop[1]) {
10253+ switch (left) {
10254+ case CCS_PATH1_PERM:
10255+ case CCS_PATH1_PARENT_PERM:
10256+ case CCS_PATH2_PERM:
10257+ case CCS_PATH2_PARENT_PERM:
10258+ if (!(max_v[0] & max_v[1]) == !match)
10259+ continue;
10260+ }
10261+ goto out;
10262+ }
10263+ /* Normal value range comparison. */
10264+ if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
10265+ continue;
10266+out:
10267+ return false;
10268+ }
10269+ /* Check argv[] and envp[] now. */
10270+ if (r->ee && (argc || envc))
10271+ return ccs_scan_bprm(r->ee, argc, argv, envc, envp);
10272+ return true;
10273+}
10274+
10275+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
10276+
10277+/**
10278+ * ccs_check_task_acl - Check permission for task operation.
10279+ *
10280+ * @r: Pointer to "struct ccs_request_info".
10281+ * @ptr: Pointer to "struct ccs_acl_info".
10282+ *
10283+ * Returns true if granted, false otherwise.
10284+ */
10285+static bool ccs_check_task_acl(struct ccs_request_info *r,
10286+ const struct ccs_acl_info *ptr)
10287+{
10288+ const struct ccs_task_acl *acl = container_of(ptr, typeof(*acl), head);
10289+ return !ccs_pathcmp(r->param.task.domainname, acl->domainname);
10290+}
10291+
10292+#endif
10293+
10294+/**
10295+ * ccs_init_request_info - Initialize "struct ccs_request_info" members.
10296+ *
10297+ * @r: Pointer to "struct ccs_request_info" to initialize.
10298+ * @index: Index number of functionality.
10299+ *
10300+ * Returns mode.
10301+ *
10302+ * "task auto_domain_transition" keyword is evaluated before returning mode for
10303+ * @index. If "task auto_domain_transition" keyword was specified and
10304+ * transition to that domain failed, the current thread will be killed by
10305+ * SIGKILL. Note that if current->pid == 1, sending SIGKILL won't work.
10306+ */
10307+int ccs_init_request_info(struct ccs_request_info *r, const u8 index)
10308+{
10309+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
10310+ u8 i;
10311+ const char *buf;
10312+ for (i = 0; i < 255; i++) {
10313+ const u8 profile = ccs_current_domain()->profile;
10314+ memset(r, 0, sizeof(*r));
10315+ r->profile = profile;
10316+ r->type = index;
10317+ r->mode = ccs_get_mode(profile, index);
10318+ r->param_type = CCS_TYPE_AUTO_TASK_ACL;
10319+ ccs_check_acl(r);
10320+ if (!r->granted)
10321+ return r->mode;
10322+ buf = container_of(r->matched_acl, typeof(struct ccs_task_acl),
10323+ head)->domainname->name;
10324+ if (!ccs_assign_domain(buf, true))
10325+ break;
10326+ }
10327+ ccs_transition_failed(buf);
10328+ return CCS_CONFIG_DISABLED;
10329+#else
10330+ const u8 profile = ccs_current_domain()->profile;
10331+ memset(r, 0, sizeof(*r));
10332+ r->profile = profile;
10333+ r->type = index;
10334+ r->mode = ccs_get_mode(profile, index);
10335+ return r->mode;
10336+#endif
10337+}
10338+
10339+/**
10340+ * ccs_byte_range - Check whether the string is a \ooo style octal value.
10341+ *
10342+ * @str: Pointer to the string.
10343+ *
10344+ * Returns true if @str is a \ooo style octal value, false otherwise.
10345+ */
10346+static bool ccs_byte_range(const char *str)
10347+{
10348+ return *str >= '0' && *str++ <= '3' &&
10349+ *str >= '0' && *str++ <= '7' &&
10350+ *str >= '0' && *str <= '7';
10351+}
10352+
10353+/**
10354+ * ccs_decimal - Check whether the character is a decimal character.
10355+ *
10356+ * @c: The character to check.
10357+ *
10358+ * Returns true if @c is a decimal character, false otherwise.
10359+ */
10360+static bool ccs_decimal(const char c)
10361+{
10362+ return c >= '0' && c <= '9';
10363+}
10364+
10365+/**
10366+ * ccs_hexadecimal - Check whether the character is a hexadecimal character.
10367+ *
10368+ * @c: The character to check.
10369+ *
10370+ * Returns true if @c is a hexadecimal character, false otherwise.
10371+ */
10372+static bool ccs_hexadecimal(const char c)
10373+{
10374+ return (c >= '0' && c <= '9') ||
10375+ (c >= 'A' && c <= 'F') ||
10376+ (c >= 'a' && c <= 'f');
10377+}
10378+
10379+/**
10380+ * ccs_alphabet_char - Check whether the character is an alphabet.
10381+ *
10382+ * @c: The character to check.
10383+ *
10384+ * Returns true if @c is an alphabet character, false otherwise.
10385+ */
10386+static bool ccs_alphabet_char(const char c)
10387+{
10388+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
10389+}
10390+
10391+/**
10392+ * ccs_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
10393+ *
10394+ * @filename: The start of string to check.
10395+ * @filename_end: The end of string to check.
10396+ * @pattern: The start of pattern to compare.
10397+ * @pattern_end: The end of pattern to compare.
10398+ *
10399+ * Returns true if @filename matches @pattern, false otherwise.
10400+ */
10401+static bool ccs_file_matches_pattern2(const char *filename,
10402+ const char *filename_end,
10403+ const char *pattern,
10404+ const char *pattern_end)
10405+{
10406+ while (filename < filename_end && pattern < pattern_end) {
10407+ char c;
10408+ if (*pattern != '\\') {
10409+ if (*filename++ != *pattern++)
10410+ return false;
10411+ continue;
10412+ }
10413+ c = *filename;
10414+ pattern++;
10415+ switch (*pattern) {
10416+ int i;
10417+ int j;
10418+ case '?':
10419+ if (c == '/') {
10420+ return false;
10421+ } else if (c == '\\') {
10422+ if (filename[1] == '\\')
10423+ filename++;
10424+ else if (ccs_byte_range(filename + 1))
10425+ filename += 3;
10426+ else
10427+ return false;
10428+ }
10429+ break;
10430+ case '\\':
10431+ if (c != '\\')
10432+ return false;
10433+ if (*++filename != '\\')
10434+ return false;
10435+ break;
10436+ case '+':
10437+ if (!ccs_decimal(c))
10438+ return false;
10439+ break;
10440+ case 'x':
10441+ if (!ccs_hexadecimal(c))
10442+ return false;
10443+ break;
10444+ case 'a':
10445+ if (!ccs_alphabet_char(c))
10446+ return false;
10447+ break;
10448+ case '0':
10449+ case '1':
10450+ case '2':
10451+ case '3':
10452+ if (c == '\\' && ccs_byte_range(filename + 1)
10453+ && !strncmp(filename + 1, pattern, 3)) {
10454+ filename += 3;
10455+ pattern += 2;
10456+ break;
10457+ }
10458+ return false; /* Not matched. */
10459+ case '*':
10460+ case '@':
10461+ for (i = 0; i <= filename_end - filename; i++) {
10462+ if (ccs_file_matches_pattern2(filename + i,
10463+ filename_end,
10464+ pattern + 1,
10465+ pattern_end))
10466+ return true;
10467+ c = filename[i];
10468+ if (c == '.' && *pattern == '@')
10469+ break;
10470+ if (c != '\\')
10471+ continue;
10472+ if (filename[i + 1] == '\\')
10473+ i++;
10474+ else if (ccs_byte_range(filename + i + 1))
10475+ i += 3;
10476+ else
10477+ break; /* Bad pattern. */
10478+ }
10479+ return false; /* Not matched. */
10480+ default:
10481+ j = 0;
10482+ c = *pattern;
10483+ if (c == '$') {
10484+ while (ccs_decimal(filename[j]))
10485+ j++;
10486+ } else if (c == 'X') {
10487+ while (ccs_hexadecimal(filename[j]))
10488+ j++;
10489+ } else if (c == 'A') {
10490+ while (ccs_alphabet_char(filename[j]))
10491+ j++;
10492+ }
10493+ for (i = 1; i <= j; i++) {
10494+ if (ccs_file_matches_pattern2(filename + i,
10495+ filename_end,
10496+ pattern + 1,
10497+ pattern_end))
10498+ return true;
10499+ }
10500+ return false; /* Not matched or bad pattern. */
10501+ }
10502+ filename++;
10503+ pattern++;
10504+ }
10505+ while (*pattern == '\\' &&
10506+ (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
10507+ pattern += 2;
10508+ return filename == filename_end && pattern == pattern_end;
10509+}
10510+
10511+/**
10512+ * ccs_file_matches_pattern - Pattern matching without '/' character.
10513+ *
10514+ * @filename: The start of string to check.
10515+ * @filename_end: The end of string to check.
10516+ * @pattern: The start of pattern to compare.
10517+ * @pattern_end: The end of pattern to compare.
10518+ *
10519+ * Returns true if @filename matches @pattern, false otherwise.
10520+ */
10521+static bool ccs_file_matches_pattern(const char *filename,
10522+ const char *filename_end,
10523+ const char *pattern,
10524+ const char *pattern_end)
10525+{
10526+ const char *pattern_start = pattern;
10527+ bool first = true;
10528+ bool result;
10529+ while (pattern < pattern_end - 1) {
10530+ /* Split at "\-" pattern. */
10531+ if (*pattern++ != '\\' || *pattern++ != '-')
10532+ continue;
10533+ result = ccs_file_matches_pattern2(filename, filename_end,
10534+ pattern_start, pattern - 2);
10535+ if (first)
10536+ result = !result;
10537+ if (result)
10538+ return false;
10539+ first = false;
10540+ pattern_start = pattern;
10541+ }
10542+ result = ccs_file_matches_pattern2(filename, filename_end,
10543+ pattern_start, pattern_end);
10544+ return first ? result : !result;
10545+}
10546+
10547+/**
10548+ * ccs_path_matches_pattern2 - Do pathname pattern matching.
10549+ *
10550+ * @f: The start of string to check.
10551+ * @p: The start of pattern to compare.
10552+ *
10553+ * Returns true if @f matches @p, false otherwise.
10554+ */
10555+static bool ccs_path_matches_pattern2(const char *f, const char *p)
10556+{
10557+ const char *f_delimiter;
10558+ const char *p_delimiter;
10559+ while (*f && *p) {
10560+ f_delimiter = strchr(f, '/');
10561+ if (!f_delimiter)
10562+ f_delimiter = f + strlen(f);
10563+ p_delimiter = strchr(p, '/');
10564+ if (!p_delimiter)
10565+ p_delimiter = p + strlen(p);
10566+ if (*p == '\\' && *(p + 1) == '{')
10567+ goto recursive;
10568+ if (!ccs_file_matches_pattern(f, f_delimiter, p, p_delimiter))
10569+ return false;
10570+ f = f_delimiter;
10571+ if (*f)
10572+ f++;
10573+ p = p_delimiter;
10574+ if (*p)
10575+ p++;
10576+ }
10577+ /* Ignore trailing "\*" and "\@" in @pattern. */
10578+ while (*p == '\\' &&
10579+ (*(p + 1) == '*' || *(p + 1) == '@'))
10580+ p += 2;
10581+ return !*f && !*p;
10582+recursive:
10583+ /*
10584+ * The "\{" pattern is permitted only after '/' character.
10585+ * This guarantees that below "*(p - 1)" is safe.
10586+ * Also, the "\}" pattern is permitted only before '/' character
10587+ * so that "\{" + "\}" pair will not break the "\-" operator.
10588+ */
10589+ if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
10590+ *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
10591+ return false; /* Bad pattern. */
10592+ do {
10593+ /* Compare current component with pattern. */
10594+ if (!ccs_file_matches_pattern(f, f_delimiter, p + 2,
10595+ p_delimiter - 2))
10596+ break;
10597+ /* Proceed to next component. */
10598+ f = f_delimiter;
10599+ if (!*f)
10600+ break;
10601+ f++;
10602+ /* Continue comparison. */
10603+ if (ccs_path_matches_pattern2(f, p_delimiter + 1))
10604+ return true;
10605+ f_delimiter = strchr(f, '/');
10606+ } while (f_delimiter);
10607+ return false; /* Not matched. */
10608+}
10609+
10610+/**
10611+ * ccs_path_matches_pattern - Check whether the given filename matches the given pattern.
10612+ *
10613+ * @filename: The filename to check.
10614+ * @pattern: The pattern to compare.
10615+ *
10616+ * Returns true if matches, false otherwise.
10617+ *
10618+ * The following patterns are available.
10619+ * \\ \ itself.
10620+ * \ooo Octal representation of a byte.
10621+ * \* Zero or more repetitions of characters other than '/'.
10622+ * \@ Zero or more repetitions of characters other than '/' or '.'.
10623+ * \? 1 byte character other than '/'.
10624+ * \$ One or more repetitions of decimal digits.
10625+ * \+ 1 decimal digit.
10626+ * \X One or more repetitions of hexadecimal digits.
10627+ * \x 1 hexadecimal digit.
10628+ * \A One or more repetitions of alphabet characters.
10629+ * \a 1 alphabet character.
10630+ *
10631+ * \- Subtraction operator.
10632+ *
10633+ * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
10634+ * /dir/dir/dir/ ).
10635+ */
10636+static bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
10637+ const struct ccs_path_info *pattern)
10638+{
10639+ const char *f = filename->name;
10640+ const char *p = pattern->name;
10641+ const int len = pattern->const_len;
10642+ /* If @pattern doesn't contain pattern, I can use strcmp(). */
10643+ if (!pattern->is_patterned)
10644+ return !ccs_pathcmp(filename, pattern);
10645+ /* Don't compare directory and non-directory. */
10646+ if (filename->is_dir != pattern->is_dir)
10647+ return false;
10648+ /* Compare the initial length without patterns. */
10649+ if (strncmp(f, p, len))
10650+ return false;
10651+ f += len;
10652+ p += len;
10653+ return ccs_path_matches_pattern2(f, p);
10654+}
10655diff --git a/security/ccsecurity/policy_io.c b/security/ccsecurity/policy_io.c
10656new file mode 100644
10657index 0000000..67adb50
10658--- /dev/null
10659+++ b/security/ccsecurity/policy_io.c
10660@@ -0,0 +1,6484 @@
10661+/*
10662+ * security/ccsecurity/policy_io.c
10663+ *
10664+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
10665+ *
10666+ * Version: 1.8.4 2015/05/05
10667+ */
10668+
10669+#include "internal.h"
10670+
10671+/***** SECTION1: Constants definition *****/
10672+
10673+/* Define this to enable debug mode. */
10674+/* #define DEBUG_CONDITION */
10675+
10676+#ifdef DEBUG_CONDITION
10677+#define dprintk printk
10678+#else
10679+#define dprintk(...) do { } while (0)
10680+#endif
10681+
10682+/* Mapping table from "enum ccs_mac_index" to "enum ccs_mac_category_index". */
10683+static const u8 ccs_index2category[CCS_MAX_MAC_INDEX] = {
10684+ /* CONFIG::file group */
10685+ [CCS_MAC_FILE_EXECUTE] = CCS_MAC_CATEGORY_FILE,
10686+ [CCS_MAC_FILE_OPEN] = CCS_MAC_CATEGORY_FILE,
10687+ [CCS_MAC_FILE_CREATE] = CCS_MAC_CATEGORY_FILE,
10688+ [CCS_MAC_FILE_UNLINK] = CCS_MAC_CATEGORY_FILE,
10689+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
10690+ [CCS_MAC_FILE_GETATTR] = CCS_MAC_CATEGORY_FILE,
10691+#endif
10692+ [CCS_MAC_FILE_MKDIR] = CCS_MAC_CATEGORY_FILE,
10693+ [CCS_MAC_FILE_RMDIR] = CCS_MAC_CATEGORY_FILE,
10694+ [CCS_MAC_FILE_MKFIFO] = CCS_MAC_CATEGORY_FILE,
10695+ [CCS_MAC_FILE_MKSOCK] = CCS_MAC_CATEGORY_FILE,
10696+ [CCS_MAC_FILE_TRUNCATE] = CCS_MAC_CATEGORY_FILE,
10697+ [CCS_MAC_FILE_SYMLINK] = CCS_MAC_CATEGORY_FILE,
10698+ [CCS_MAC_FILE_MKBLOCK] = CCS_MAC_CATEGORY_FILE,
10699+ [CCS_MAC_FILE_MKCHAR] = CCS_MAC_CATEGORY_FILE,
10700+ [CCS_MAC_FILE_LINK] = CCS_MAC_CATEGORY_FILE,
10701+ [CCS_MAC_FILE_RENAME] = CCS_MAC_CATEGORY_FILE,
10702+ [CCS_MAC_FILE_CHMOD] = CCS_MAC_CATEGORY_FILE,
10703+ [CCS_MAC_FILE_CHOWN] = CCS_MAC_CATEGORY_FILE,
10704+ [CCS_MAC_FILE_CHGRP] = CCS_MAC_CATEGORY_FILE,
10705+ [CCS_MAC_FILE_IOCTL] = CCS_MAC_CATEGORY_FILE,
10706+ [CCS_MAC_FILE_CHROOT] = CCS_MAC_CATEGORY_FILE,
10707+ [CCS_MAC_FILE_MOUNT] = CCS_MAC_CATEGORY_FILE,
10708+ [CCS_MAC_FILE_UMOUNT] = CCS_MAC_CATEGORY_FILE,
10709+ [CCS_MAC_FILE_PIVOT_ROOT] = CCS_MAC_CATEGORY_FILE,
10710+#ifdef CONFIG_CCSECURITY_MISC
10711+ /* CONFIG::misc group */
10712+ [CCS_MAC_ENVIRON] = CCS_MAC_CATEGORY_MISC,
10713+#endif
10714+#ifdef CONFIG_CCSECURITY_NETWORK
10715+ /* CONFIG::network group */
10716+ [CCS_MAC_NETWORK_INET_STREAM_BIND] = CCS_MAC_CATEGORY_NETWORK,
10717+ [CCS_MAC_NETWORK_INET_STREAM_LISTEN] = CCS_MAC_CATEGORY_NETWORK,
10718+ [CCS_MAC_NETWORK_INET_STREAM_CONNECT] = CCS_MAC_CATEGORY_NETWORK,
10719+ [CCS_MAC_NETWORK_INET_STREAM_ACCEPT] = CCS_MAC_CATEGORY_NETWORK,
10720+ [CCS_MAC_NETWORK_INET_DGRAM_BIND] = CCS_MAC_CATEGORY_NETWORK,
10721+ [CCS_MAC_NETWORK_INET_DGRAM_SEND] = CCS_MAC_CATEGORY_NETWORK,
10722+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
10723+ [CCS_MAC_NETWORK_INET_DGRAM_RECV] = CCS_MAC_CATEGORY_NETWORK,
10724+#endif
10725+ [CCS_MAC_NETWORK_INET_RAW_BIND] = CCS_MAC_CATEGORY_NETWORK,
10726+ [CCS_MAC_NETWORK_INET_RAW_SEND] = CCS_MAC_CATEGORY_NETWORK,
10727+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
10728+ [CCS_MAC_NETWORK_INET_RAW_RECV] = CCS_MAC_CATEGORY_NETWORK,
10729+#endif
10730+ [CCS_MAC_NETWORK_UNIX_STREAM_BIND] = CCS_MAC_CATEGORY_NETWORK,
10731+ [CCS_MAC_NETWORK_UNIX_STREAM_LISTEN] = CCS_MAC_CATEGORY_NETWORK,
10732+ [CCS_MAC_NETWORK_UNIX_STREAM_CONNECT] = CCS_MAC_CATEGORY_NETWORK,
10733+ [CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT] = CCS_MAC_CATEGORY_NETWORK,
10734+ [CCS_MAC_NETWORK_UNIX_DGRAM_BIND] = CCS_MAC_CATEGORY_NETWORK,
10735+ [CCS_MAC_NETWORK_UNIX_DGRAM_SEND] = CCS_MAC_CATEGORY_NETWORK,
10736+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
10737+ [CCS_MAC_NETWORK_UNIX_DGRAM_RECV] = CCS_MAC_CATEGORY_NETWORK,
10738+#endif
10739+ [CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND] = CCS_MAC_CATEGORY_NETWORK,
10740+ [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = CCS_MAC_CATEGORY_NETWORK,
10741+ [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = CCS_MAC_CATEGORY_NETWORK,
10742+ [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT] = CCS_MAC_CATEGORY_NETWORK,
10743+#endif
10744+#ifdef CONFIG_CCSECURITY_IPC
10745+ /* CONFIG::ipc group */
10746+ [CCS_MAC_SIGNAL] = CCS_MAC_CATEGORY_IPC,
10747+#endif
10748+#ifdef CONFIG_CCSECURITY_CAPABILITY
10749+ /* CONFIG::capability group */
10750+ [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET] = CCS_MAC_CATEGORY_CAPABILITY,
10751+ [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = CCS_MAC_CATEGORY_CAPABILITY,
10752+ [CCS_MAC_CAPABILITY_SYS_REBOOT] = CCS_MAC_CATEGORY_CAPABILITY,
10753+ [CCS_MAC_CAPABILITY_SYS_VHANGUP] = CCS_MAC_CATEGORY_CAPABILITY,
10754+ [CCS_MAC_CAPABILITY_SYS_SETTIME] = CCS_MAC_CATEGORY_CAPABILITY,
10755+ [CCS_MAC_CAPABILITY_SYS_NICE] = CCS_MAC_CATEGORY_CAPABILITY,
10756+ [CCS_MAC_CAPABILITY_SYS_SETHOSTNAME] = CCS_MAC_CATEGORY_CAPABILITY,
10757+ [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = CCS_MAC_CATEGORY_CAPABILITY,
10758+ [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD] = CCS_MAC_CATEGORY_CAPABILITY,
10759+ [CCS_MAC_CAPABILITY_SYS_PTRACE] = CCS_MAC_CATEGORY_CAPABILITY,
10760+#endif
10761+};
10762+
10763+/* String table for operation mode. */
10764+static const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {
10765+ [CCS_CONFIG_DISABLED] = "disabled",
10766+ [CCS_CONFIG_LEARNING] = "learning",
10767+ [CCS_CONFIG_PERMISSIVE] = "permissive",
10768+ [CCS_CONFIG_ENFORCING] = "enforcing"
10769+};
10770+
10771+/* String table for /proc/ccs/profile interface. */
10772+static const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX
10773+ + CCS_MAX_MAC_CATEGORY_INDEX] = {
10774+ /* CONFIG::file group */
10775+ [CCS_MAC_FILE_EXECUTE] = "execute",
10776+ [CCS_MAC_FILE_OPEN] = "open",
10777+ [CCS_MAC_FILE_CREATE] = "create",
10778+ [CCS_MAC_FILE_UNLINK] = "unlink",
10779+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
10780+ [CCS_MAC_FILE_GETATTR] = "getattr",
10781+#endif
10782+ [CCS_MAC_FILE_MKDIR] = "mkdir",
10783+ [CCS_MAC_FILE_RMDIR] = "rmdir",
10784+ [CCS_MAC_FILE_MKFIFO] = "mkfifo",
10785+ [CCS_MAC_FILE_MKSOCK] = "mksock",
10786+ [CCS_MAC_FILE_TRUNCATE] = "truncate",
10787+ [CCS_MAC_FILE_SYMLINK] = "symlink",
10788+ [CCS_MAC_FILE_MKBLOCK] = "mkblock",
10789+ [CCS_MAC_FILE_MKCHAR] = "mkchar",
10790+ [CCS_MAC_FILE_LINK] = "link",
10791+ [CCS_MAC_FILE_RENAME] = "rename",
10792+ [CCS_MAC_FILE_CHMOD] = "chmod",
10793+ [CCS_MAC_FILE_CHOWN] = "chown",
10794+ [CCS_MAC_FILE_CHGRP] = "chgrp",
10795+ [CCS_MAC_FILE_IOCTL] = "ioctl",
10796+ [CCS_MAC_FILE_CHROOT] = "chroot",
10797+ [CCS_MAC_FILE_MOUNT] = "mount",
10798+ [CCS_MAC_FILE_UMOUNT] = "unmount",
10799+ [CCS_MAC_FILE_PIVOT_ROOT] = "pivot_root",
10800+#ifdef CONFIG_CCSECURITY_MISC
10801+ /* CONFIG::misc group */
10802+ [CCS_MAC_ENVIRON] = "env",
10803+#endif
10804+#ifdef CONFIG_CCSECURITY_NETWORK
10805+ /* CONFIG::network group */
10806+ [CCS_MAC_NETWORK_INET_STREAM_BIND] = "inet_stream_bind",
10807+ [CCS_MAC_NETWORK_INET_STREAM_LISTEN] = "inet_stream_listen",
10808+ [CCS_MAC_NETWORK_INET_STREAM_CONNECT] = "inet_stream_connect",
10809+ [CCS_MAC_NETWORK_INET_STREAM_ACCEPT] = "inet_stream_accept",
10810+ [CCS_MAC_NETWORK_INET_DGRAM_BIND] = "inet_dgram_bind",
10811+ [CCS_MAC_NETWORK_INET_DGRAM_SEND] = "inet_dgram_send",
10812+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
10813+ [CCS_MAC_NETWORK_INET_DGRAM_RECV] = "inet_dgram_recv",
10814+#endif
10815+ [CCS_MAC_NETWORK_INET_RAW_BIND] = "inet_raw_bind",
10816+ [CCS_MAC_NETWORK_INET_RAW_SEND] = "inet_raw_send",
10817+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
10818+ [CCS_MAC_NETWORK_INET_RAW_RECV] = "inet_raw_recv",
10819+#endif
10820+ [CCS_MAC_NETWORK_UNIX_STREAM_BIND] = "unix_stream_bind",
10821+ [CCS_MAC_NETWORK_UNIX_STREAM_LISTEN] = "unix_stream_listen",
10822+ [CCS_MAC_NETWORK_UNIX_STREAM_CONNECT] = "unix_stream_connect",
10823+ [CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT] = "unix_stream_accept",
10824+ [CCS_MAC_NETWORK_UNIX_DGRAM_BIND] = "unix_dgram_bind",
10825+ [CCS_MAC_NETWORK_UNIX_DGRAM_SEND] = "unix_dgram_send",
10826+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
10827+ [CCS_MAC_NETWORK_UNIX_DGRAM_RECV] = "unix_dgram_recv",
10828+#endif
10829+ [CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND] = "unix_seqpacket_bind",
10830+ [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = "unix_seqpacket_listen",
10831+ [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect",
10832+ [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT] = "unix_seqpacket_accept",
10833+#endif
10834+#ifdef CONFIG_CCSECURITY_IPC
10835+ /* CONFIG::ipc group */
10836+ [CCS_MAC_SIGNAL] = "signal",
10837+#endif
10838+#ifdef CONFIG_CCSECURITY_CAPABILITY
10839+ /* CONFIG::capability group */
10840+ [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET] = "use_route",
10841+ [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = "use_packet",
10842+ [CCS_MAC_CAPABILITY_SYS_REBOOT] = "SYS_REBOOT",
10843+ [CCS_MAC_CAPABILITY_SYS_VHANGUP] = "SYS_VHANGUP",
10844+ [CCS_MAC_CAPABILITY_SYS_SETTIME] = "SYS_TIME",
10845+ [CCS_MAC_CAPABILITY_SYS_NICE] = "SYS_NICE",
10846+ [CCS_MAC_CAPABILITY_SYS_SETHOSTNAME] = "SYS_SETHOSTNAME",
10847+ [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = "use_kernel_module",
10848+ [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD] = "SYS_KEXEC_LOAD",
10849+ [CCS_MAC_CAPABILITY_SYS_PTRACE] = "SYS_PTRACE",
10850+#endif
10851+ /* CONFIG group */
10852+ [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_FILE] = "file",
10853+#ifdef CONFIG_CCSECURITY_NETWORK
10854+ [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_NETWORK] = "network",
10855+#endif
10856+#ifdef CONFIG_CCSECURITY_MISC
10857+ [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_MISC] = "misc",
10858+#endif
10859+#ifdef CONFIG_CCSECURITY_IPC
10860+ [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_IPC] = "ipc",
10861+#endif
10862+#ifdef CONFIG_CCSECURITY_CAPABILITY
10863+ [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
10864+#endif
10865+};
10866+
10867+/* String table for path operation. */
10868+static const char * const ccs_path_keyword[CCS_MAX_PATH_OPERATION] = {
10869+ [CCS_TYPE_EXECUTE] = "execute",
10870+ [CCS_TYPE_READ] = "read",
10871+ [CCS_TYPE_WRITE] = "write",
10872+ [CCS_TYPE_APPEND] = "append",
10873+ [CCS_TYPE_UNLINK] = "unlink",
10874+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
10875+ [CCS_TYPE_GETATTR] = "getattr",
10876+#endif
10877+ [CCS_TYPE_RMDIR] = "rmdir",
10878+ [CCS_TYPE_TRUNCATE] = "truncate",
10879+ [CCS_TYPE_SYMLINK] = "symlink",
10880+ [CCS_TYPE_CHROOT] = "chroot",
10881+ [CCS_TYPE_UMOUNT] = "unmount",
10882+};
10883+
10884+#ifdef CONFIG_CCSECURITY_NETWORK
10885+
10886+/* String table for socket's operation. */
10887+static const char * const ccs_socket_keyword[CCS_MAX_NETWORK_OPERATION] = {
10888+ [CCS_NETWORK_BIND] = "bind",
10889+ [CCS_NETWORK_LISTEN] = "listen",
10890+ [CCS_NETWORK_CONNECT] = "connect",
10891+ [CCS_NETWORK_ACCEPT] = "accept",
10892+ [CCS_NETWORK_SEND] = "send",
10893+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
10894+ [CCS_NETWORK_RECV] = "recv",
10895+#endif
10896+};
10897+
10898+/* String table for socket's protocols. */
10899+static const char * const ccs_proto_keyword[CCS_SOCK_MAX] = {
10900+ [SOCK_STREAM] = "stream",
10901+ [SOCK_DGRAM] = "dgram",
10902+ [SOCK_RAW] = "raw",
10903+ [SOCK_SEQPACKET] = "seqpacket",
10904+ [0] = " ", /* Dummy for avoiding NULL pointer dereference. */
10905+ [4] = " ", /* Dummy for avoiding NULL pointer dereference. */
10906+};
10907+
10908+#endif
10909+
10910+/* String table for categories. */
10911+static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {
10912+ [CCS_MAC_CATEGORY_FILE] = "file",
10913+#ifdef CONFIG_CCSECURITY_NETWORK
10914+ [CCS_MAC_CATEGORY_NETWORK] = "network",
10915+#endif
10916+#ifdef CONFIG_CCSECURITY_MISC
10917+ [CCS_MAC_CATEGORY_MISC] = "misc",
10918+#endif
10919+#ifdef CONFIG_CCSECURITY_IPC
10920+ [CCS_MAC_CATEGORY_IPC] = "ipc",
10921+#endif
10922+#ifdef CONFIG_CCSECURITY_CAPABILITY
10923+ [CCS_MAC_CATEGORY_CAPABILITY] = "capability",
10924+#endif
10925+};
10926+
10927+/* String table for conditions. */
10928+static const char * const ccs_condition_keyword[CCS_MAX_CONDITION_KEYWORD] = {
10929+ [CCS_TASK_UID] = "task.uid",
10930+ [CCS_TASK_EUID] = "task.euid",
10931+ [CCS_TASK_SUID] = "task.suid",
10932+ [CCS_TASK_FSUID] = "task.fsuid",
10933+ [CCS_TASK_GID] = "task.gid",
10934+ [CCS_TASK_EGID] = "task.egid",
10935+ [CCS_TASK_SGID] = "task.sgid",
10936+ [CCS_TASK_FSGID] = "task.fsgid",
10937+ [CCS_TASK_PID] = "task.pid",
10938+ [CCS_TASK_PPID] = "task.ppid",
10939+ [CCS_EXEC_ARGC] = "exec.argc",
10940+ [CCS_EXEC_ENVC] = "exec.envc",
10941+ [CCS_TYPE_IS_SOCKET] = "socket",
10942+ [CCS_TYPE_IS_SYMLINK] = "symlink",
10943+ [CCS_TYPE_IS_FILE] = "file",
10944+ [CCS_TYPE_IS_BLOCK_DEV] = "block",
10945+ [CCS_TYPE_IS_DIRECTORY] = "directory",
10946+ [CCS_TYPE_IS_CHAR_DEV] = "char",
10947+ [CCS_TYPE_IS_FIFO] = "fifo",
10948+ [CCS_MODE_SETUID] = "setuid",
10949+ [CCS_MODE_SETGID] = "setgid",
10950+ [CCS_MODE_STICKY] = "sticky",
10951+ [CCS_MODE_OWNER_READ] = "owner_read",
10952+ [CCS_MODE_OWNER_WRITE] = "owner_write",
10953+ [CCS_MODE_OWNER_EXECUTE] = "owner_execute",
10954+ [CCS_MODE_GROUP_READ] = "group_read",
10955+ [CCS_MODE_GROUP_WRITE] = "group_write",
10956+ [CCS_MODE_GROUP_EXECUTE] = "group_execute",
10957+ [CCS_MODE_OTHERS_READ] = "others_read",
10958+ [CCS_MODE_OTHERS_WRITE] = "others_write",
10959+ [CCS_MODE_OTHERS_EXECUTE] = "others_execute",
10960+ [CCS_TASK_TYPE] = "task.type",
10961+ [CCS_TASK_EXECUTE_HANDLER] = "execute_handler",
10962+ [CCS_EXEC_REALPATH] = "exec.realpath",
10963+ [CCS_SYMLINK_TARGET] = "symlink.target",
10964+ [CCS_PATH1_UID] = "path1.uid",
10965+ [CCS_PATH1_GID] = "path1.gid",
10966+ [CCS_PATH1_INO] = "path1.ino",
10967+ [CCS_PATH1_MAJOR] = "path1.major",
10968+ [CCS_PATH1_MINOR] = "path1.minor",
10969+ [CCS_PATH1_PERM] = "path1.perm",
10970+ [CCS_PATH1_TYPE] = "path1.type",
10971+ [CCS_PATH1_DEV_MAJOR] = "path1.dev_major",
10972+ [CCS_PATH1_DEV_MINOR] = "path1.dev_minor",
10973+ [CCS_PATH2_UID] = "path2.uid",
10974+ [CCS_PATH2_GID] = "path2.gid",
10975+ [CCS_PATH2_INO] = "path2.ino",
10976+ [CCS_PATH2_MAJOR] = "path2.major",
10977+ [CCS_PATH2_MINOR] = "path2.minor",
10978+ [CCS_PATH2_PERM] = "path2.perm",
10979+ [CCS_PATH2_TYPE] = "path2.type",
10980+ [CCS_PATH2_DEV_MAJOR] = "path2.dev_major",
10981+ [CCS_PATH2_DEV_MINOR] = "path2.dev_minor",
10982+ [CCS_PATH1_PARENT_UID] = "path1.parent.uid",
10983+ [CCS_PATH1_PARENT_GID] = "path1.parent.gid",
10984+ [CCS_PATH1_PARENT_INO] = "path1.parent.ino",
10985+ [CCS_PATH1_PARENT_PERM] = "path1.parent.perm",
10986+ [CCS_PATH2_PARENT_UID] = "path2.parent.uid",
10987+ [CCS_PATH2_PARENT_GID] = "path2.parent.gid",
10988+ [CCS_PATH2_PARENT_INO] = "path2.parent.ino",
10989+ [CCS_PATH2_PARENT_PERM] = "path2.parent.perm",
10990+};
10991+
10992+/* String table for PREFERENCE keyword. */
10993+static const char * const ccs_pref_keywords[CCS_MAX_PREF] = {
10994+ [CCS_PREF_MAX_AUDIT_LOG] = "max_audit_log",
10995+ [CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
10996+ [CCS_PREF_ENFORCING_PENALTY] = "enforcing_penalty",
10997+};
10998+
10999+/* String table for domain flags. */
11000+const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
11001+ [CCS_DIF_QUOTA_WARNED] = "quota_exceeded\n",
11002+ [CCS_DIF_TRANSITION_FAILED] = "transition_failed\n",
11003+};
11004+
11005+/* String table for domain transition control keywords. */
11006+static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
11007+ [CCS_TRANSITION_CONTROL_NO_RESET] = "no_reset_domain ",
11008+ [CCS_TRANSITION_CONTROL_RESET] = "reset_domain ",
11009+ [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
11010+ [CCS_TRANSITION_CONTROL_INITIALIZE] = "initialize_domain ",
11011+ [CCS_TRANSITION_CONTROL_NO_KEEP] = "no_keep_domain ",
11012+ [CCS_TRANSITION_CONTROL_KEEP] = "keep_domain ",
11013+};
11014+
11015+/* String table for grouping keywords. */
11016+static const char * const ccs_group_name[CCS_MAX_GROUP] = {
11017+ [CCS_PATH_GROUP] = "path_group ",
11018+ [CCS_NUMBER_GROUP] = "number_group ",
11019+#ifdef CONFIG_CCSECURITY_NETWORK
11020+ [CCS_ADDRESS_GROUP] = "address_group ",
11021+#endif
11022+};
11023+
11024+/* String table for /proc/ccs/stat interface. */
11025+static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {
11026+ [CCS_STAT_POLICY_UPDATES] = "update:",
11027+ [CCS_STAT_POLICY_LEARNING] = "violation in learning mode:",
11028+ [CCS_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:",
11029+ [CCS_STAT_POLICY_ENFORCING] = "violation in enforcing mode:",
11030+};
11031+
11032+/* String table for /proc/ccs/stat interface. */
11033+static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
11034+ [CCS_MEMORY_POLICY] = "policy:",
11035+ [CCS_MEMORY_AUDIT] = "audit log:",
11036+ [CCS_MEMORY_QUERY] = "query message:",
11037+};
11038+
11039+/***** SECTION2: Structure definition *****/
11040+
11041+struct iattr;
11042+
11043+/* Structure for query. */
11044+struct ccs_query {
11045+ struct list_head list;
11046+ struct ccs_domain_info *domain;
11047+ char *query;
11048+ size_t query_len;
11049+ unsigned int serial;
11050+ u8 timer;
11051+ u8 answer;
11052+ u8 retry;
11053+};
11054+
11055+/* Structure for audit log. */
11056+struct ccs_log {
11057+ struct list_head list;
11058+ char *log;
11059+ int size;
11060+};
11061+
11062+/***** SECTION3: Prototype definition section *****/
11063+
11064+int ccs_audit_log(struct ccs_request_info *r);
11065+struct ccs_domain_info *ccs_assign_domain(const char *domainname,
11066+ const bool transit);
11067+u8 ccs_get_config(const u8 profile, const u8 index);
11068+void ccs_transition_failed(const char *domainname);
11069+void ccs_write_log(struct ccs_request_info *r, const char *fmt, ...);
11070+
11071+static bool ccs_correct_domain(const unsigned char *domainname);
11072+static bool ccs_correct_path(const char *filename);
11073+static bool ccs_correct_word(const char *string);
11074+static bool ccs_correct_word2(const char *string, size_t len);
11075+static bool ccs_domain_def(const unsigned char *buffer);
11076+static bool ccs_domain_quota_ok(struct ccs_request_info *r);
11077+static bool ccs_flush(struct ccs_io_buffer *head);
11078+static bool ccs_get_audit(const struct ccs_request_info *r);
11079+static bool ccs_has_more_namespace(struct ccs_io_buffer *head);
11080+static bool ccs_manager(void);
11081+static bool ccs_namespace_jump(const char *domainname);
11082+static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv);
11083+static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp);
11084+static bool ccs_parse_name_union(struct ccs_acl_param *param,
11085+ struct ccs_name_union *ptr);
11086+static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param,
11087+ struct ccs_name_union *ptr);
11088+static bool ccs_parse_number_union(struct ccs_acl_param *param,
11089+ struct ccs_number_union *ptr);
11090+static bool ccs_permstr(const char *string, const char *keyword);
11091+static bool ccs_print_condition(struct ccs_io_buffer *head,
11092+ const struct ccs_condition *cond);
11093+static bool ccs_print_entry(struct ccs_io_buffer *head,
11094+ const struct ccs_acl_info *acl);
11095+static bool ccs_print_group(struct ccs_io_buffer *head,
11096+ const struct ccs_group *group);
11097+static bool ccs_read_acl(struct ccs_io_buffer *head, struct list_head *list);
11098+static bool ccs_read_group(struct ccs_io_buffer *head, const int idx);
11099+static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx);
11100+static bool ccs_same_condition(const struct ccs_condition *a,
11101+ const struct ccs_condition *b);
11102+static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data);
11103+static bool ccs_set_lf(struct ccs_io_buffer *head);
11104+static bool ccs_str_starts(char **src, const char *find);
11105+static char *ccs_get_transit_preference(struct ccs_acl_param *param,
11106+ struct ccs_condition *e);
11107+static char *ccs_init_log(struct ccs_request_info *r, int len, const char *fmt,
11108+ va_list args);
11109+static char *ccs_print_bprm(struct linux_binprm *bprm,
11110+ struct ccs_page_dump *dump);
11111+static char *ccs_print_header(struct ccs_request_info *r);
11112+static char *ccs_read_token(struct ccs_acl_param *param);
11113+static const char *ccs_yesno(const unsigned int value);
11114+static const struct ccs_path_info *ccs_get_domainname
11115+(struct ccs_acl_param *param);
11116+static const struct ccs_path_info *ccs_get_dqword(char *start);
11117+static int __init ccs_init_module(void);
11118+static int ccs_delete_domain(char *domainname);
11119+static int ccs_open(struct inode *inode, struct file *file);
11120+static int ccs_parse_policy(struct ccs_io_buffer *head, char *line);
11121+static int ccs_release(struct inode *inode, struct file *file);
11122+static int ccs_set_mode(char *name, const char *value,
11123+ struct ccs_profile *profile);
11124+static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
11125+ __printf(2, 3);
11126+static int ccs_truncate(char *str);
11127+static int ccs_update_acl(const int size, struct ccs_acl_param *param);
11128+static int ccs_update_manager_entry(const char *manager, const bool is_delete);
11129+static int ccs_update_policy(const int size, struct ccs_acl_param *param);
11130+static int ccs_write_acl(struct ccs_policy_namespace *ns,
11131+ struct list_head *list, char *data,
11132+ const bool is_delete);
11133+static int ccs_write_aggregator(struct ccs_acl_param *param);
11134+static int ccs_write_answer(struct ccs_io_buffer *head);
11135+static int ccs_write_domain(struct ccs_io_buffer *head);
11136+static int ccs_write_exception(struct ccs_io_buffer *head);
11137+static int ccs_write_file(struct ccs_acl_param *param);
11138+static int ccs_write_group(struct ccs_acl_param *param, const u8 type);
11139+static int ccs_write_manager(struct ccs_io_buffer *head);
11140+static int ccs_write_pid(struct ccs_io_buffer *head);
11141+static int ccs_write_profile(struct ccs_io_buffer *head);
11142+static int ccs_write_stat(struct ccs_io_buffer *head);
11143+static int ccs_write_task(struct ccs_acl_param *param);
11144+static int ccs_write_transition_control(struct ccs_acl_param *param,
11145+ const u8 type);
11146+static s8 ccs_find_yesno(const char *string, const char *find);
11147+static ssize_t ccs_read(struct file *file, char __user *buf, size_t count,
11148+ loff_t *ppos);
11149+static ssize_t ccs_read_self(struct file *file, char __user *buf, size_t count,
11150+ loff_t *ppos);
11151+static ssize_t ccs_write(struct file *file, const char __user *buf,
11152+ size_t count, loff_t *ppos);
11153+static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry);
11154+static struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param);
11155+static struct ccs_domain_info *ccs_find_domain(const char *domainname);
11156+static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial);
11157+static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
11158+ const u8 idx);
11159+static struct ccs_policy_namespace *ccs_assign_namespace
11160+(const char *domainname);
11161+static struct ccs_policy_namespace *ccs_find_namespace(const char *name,
11162+ const unsigned int len);
11163+static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
11164+ const unsigned int profile);
11165+static struct ccs_profile *ccs_profile(const u8 profile);
11166+static u8 ccs_condition_type(const char *word);
11167+static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3);
11168+static u8 ccs_parse_ulong(unsigned long *result, char **str);
11169+static unsigned int ccs_poll(struct file *file, poll_table *wait);
11170+static void __init ccs_create_entry(const char *name, const umode_t mode,
11171+ struct proc_dir_entry *parent,
11172+ const u8 key);
11173+static void __init ccs_load_builtin_policy(void);
11174+static void __init ccs_policy_io_init(void);
11175+static void __init ccs_proc_init(void);
11176+static void ccs_add_entry(char *header);
11177+static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
11178+ __printf(3, 4);
11179+static void ccs_addprintf(char *buffer, int len, const char *fmt, ...);
11180+static void ccs_check_profile(void);
11181+static void ccs_convert_time(time_t time, struct ccs_time *stamp);
11182+static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns);
11183+static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
11184+ __printf(2, 3);
11185+static void ccs_normalize_line(unsigned char *buffer);
11186+static void ccs_print_config(struct ccs_io_buffer *head, const u8 config);
11187+static void ccs_print_name_union(struct ccs_io_buffer *head,
11188+ const struct ccs_name_union *ptr);
11189+static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
11190+ const struct ccs_name_union *ptr);
11191+static void ccs_print_namespace(struct ccs_io_buffer *head);
11192+static void ccs_print_number_union(struct ccs_io_buffer *head,
11193+ const struct ccs_number_union *ptr);
11194+static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
11195+ const struct ccs_number_union *ptr);
11196+static void ccs_read_domain(struct ccs_io_buffer *head);
11197+static void ccs_read_exception(struct ccs_io_buffer *head);
11198+static void ccs_read_log(struct ccs_io_buffer *head);
11199+static void ccs_read_manager(struct ccs_io_buffer *head);
11200+static void ccs_read_pid(struct ccs_io_buffer *head);
11201+static void ccs_read_profile(struct ccs_io_buffer *head);
11202+static void ccs_read_query(struct ccs_io_buffer *head);
11203+static void ccs_read_stat(struct ccs_io_buffer *head);
11204+static void ccs_read_version(struct ccs_io_buffer *head);
11205+static void ccs_set_group(struct ccs_io_buffer *head, const char *category);
11206+static void ccs_set_namespace_cursor(struct ccs_io_buffer *head);
11207+static void ccs_set_slash(struct ccs_io_buffer *head);
11208+static void ccs_set_space(struct ccs_io_buffer *head);
11209+static void ccs_set_string(struct ccs_io_buffer *head, const char *string);
11210+static void ccs_set_uint(unsigned int *i, const char *string,
11211+ const char *find);
11212+static void ccs_update_stat(const u8 index);
11213+static void ccs_update_task_domain(struct ccs_request_info *r);
11214+static void ccs_write_log2(struct ccs_request_info *r, int len,
11215+ const char *fmt, va_list args);
11216+
11217+#ifdef CONFIG_CCSECURITY_PORTRESERVE
11218+static bool __ccs_lport_reserved(const u16 port);
11219+static int ccs_write_reserved_port(struct ccs_acl_param *param);
11220+#endif
11221+
11222+#ifdef CONFIG_CCSECURITY_NETWORK
11223+static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
11224+ struct ccs_ipaddr_union *ptr);
11225+static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
11226+ const u32 *ip);
11227+static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
11228+ const struct in6_addr *ip);
11229+static int ccs_write_inet_network(struct ccs_acl_param *param);
11230+static int ccs_write_unix_network(struct ccs_acl_param *param);
11231+static void ccs_print_ip(char *buf, const unsigned int size,
11232+ const struct ccs_ipaddr_union *ptr);
11233+#endif
11234+
11235+#ifdef CONFIG_CCSECURITY_CAPABILITY
11236+static int ccs_write_capability(struct ccs_acl_param *param);
11237+#endif
11238+
11239+#ifdef CONFIG_CCSECURITY_MISC
11240+static int ccs_write_misc(struct ccs_acl_param *param);
11241+#endif
11242+
11243+#ifdef CONFIG_CCSECURITY_IPC
11244+static int ccs_write_ipc(struct ccs_acl_param *param);
11245+#endif
11246+
11247+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
11248+static ssize_t ccs_write_self(struct file *file, const char __user *buf,
11249+ size_t count, loff_t *ppos);
11250+#endif
11251+
11252+/***** SECTION4: Standalone functions section *****/
11253+
11254+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
11255+
11256+/**
11257+ * fatal_signal_pending - Check whether SIGKILL is pending or not.
11258+ *
11259+ * @p: Pointer to "struct task_struct".
11260+ *
11261+ * Returns true if SIGKILL is pending on @p, false otherwise.
11262+ *
11263+ * This is for compatibility with older kernels.
11264+ */
11265+#define fatal_signal_pending(p) (signal_pending(p) && \
11266+ sigismember(&p->pending.signal, SIGKILL))
11267+
11268+#endif
11269+
11270+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
11271+
11272+/**
11273+ * __wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
11274+ *
11275+ * @wq: The waitqueue to wait on.
11276+ * @condition: A C expression for the event to wait for.
11277+ * @ret: Timeout, in jiffies.
11278+ *
11279+ * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
11280+ * signal, and the remaining jiffies otherwise if the condition evaluated to
11281+ * true before the timeout elapsed.
11282+ *
11283+ * This is for compatibility with older kernels.
11284+ */
11285+#define __wait_event_interruptible_timeout(wq, condition, ret) \
11286+do { \
11287+ wait_queue_t __wait; \
11288+ init_waitqueue_entry(&__wait, current); \
11289+ \
11290+ add_wait_queue(&wq, &__wait); \
11291+ for (;;) { \
11292+ set_current_state(TASK_INTERRUPTIBLE); \
11293+ if (condition) \
11294+ break; \
11295+ if (!signal_pending(current)) { \
11296+ ret = schedule_timeout(ret); \
11297+ if (!ret) \
11298+ break; \
11299+ continue; \
11300+ } \
11301+ ret = -ERESTARTSYS; \
11302+ break; \
11303+ } \
11304+ current->state = TASK_RUNNING; \
11305+ remove_wait_queue(&wq, &__wait); \
11306+} while (0)
11307+
11308+/**
11309+ * wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
11310+ *
11311+ * @wq: The waitqueue to wait on.
11312+ * @condition: A C expression for the event to wait for.
11313+ * @timeout: Timeout, in jiffies.
11314+ *
11315+ * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
11316+ * signal, and the remaining jiffies otherwise if the condition evaluated to
11317+ * true before the timeout elapsed.
11318+ *
11319+ * This is for compatibility with older kernels.
11320+ */
11321+#define wait_event_interruptible_timeout(wq, condition, timeout) \
11322+({ \
11323+ long __ret = timeout; \
11324+ if (!(condition)) \
11325+ __wait_event_interruptible_timeout(wq, condition, __ret); \
11326+ __ret; \
11327+})
11328+
11329+#endif
11330+
11331+/**
11332+ * ccs_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
11333+ *
11334+ * @time: Seconds since 1970/01/01 00:00:00.
11335+ * @stamp: Pointer to "struct ccs_time".
11336+ *
11337+ * Returns nothing.
11338+ *
11339+ * This function does not handle Y2038 problem.
11340+ */
11341+static void ccs_convert_time(time_t time, struct ccs_time *stamp)
11342+{
11343+ static const u16 ccs_eom[2][12] = {
11344+ { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
11345+ { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
11346+ };
11347+ u16 y;
11348+ u8 m;
11349+ bool r;
11350+ stamp->sec = time % 60;
11351+ time /= 60;
11352+ stamp->min = time % 60;
11353+ time /= 60;
11354+ stamp->hour = time % 24;
11355+ time /= 24;
11356+ for (y = 1970; ; y++) {
11357+ const unsigned short days = (y & 3) ? 365 : 366;
11358+ if (time < days)
11359+ break;
11360+ time -= days;
11361+ }
11362+ r = (y & 3) == 0;
11363+ for (m = 0; m < 11 && time >= ccs_eom[r][m]; m++);
11364+ if (m)
11365+ time -= ccs_eom[r][m - 1];
11366+ stamp->year = y;
11367+ stamp->month = ++m;
11368+ stamp->day = ++time;
11369+}
11370+
11371+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 23)
11372+#if !defined(RHEL_VERSION) || RHEL_VERSION != 3
11373+
11374+/**
11375+ * PDE - Get "struct proc_dir_entry".
11376+ *
11377+ * @inode: Pointer to "struct inode".
11378+ *
11379+ * Returns pointer to "struct proc_dir_entry".
11380+ *
11381+ * This is for compatibility with older kernels.
11382+ */
11383+static inline struct proc_dir_entry *PDE(const struct inode *inode)
11384+{
11385+ return (struct proc_dir_entry *) inode->u.generic_ip;
11386+}
11387+
11388+#endif
11389+#endif
11390+
11391+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
11392+
11393+/**
11394+ * proc_notify_change - Update inode's attributes and reflect to the dentry.
11395+ *
11396+ * @dentry: Pointer to "struct dentry".
11397+ * @iattr: Pointer to "struct iattr".
11398+ *
11399+ * Returns 0 on success, negative value otherwise.
11400+ *
11401+ * The 2.4 kernels don't allow chmod()/chown() for files in /proc,
11402+ * while the 2.6 kernels allow.
11403+ * To permit management of /proc/ccs/ interface by non-root user,
11404+ * I modified to allow chmod()/chown() of /proc/ccs/ interface like 2.6 kernels
11405+ * by adding "struct inode_operations"->setattr hook.
11406+ */
11407+static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
11408+{
11409+ struct inode *inode = dentry->d_inode;
11410+ struct proc_dir_entry *de = PDE(inode);
11411+ int error;
11412+
11413+ error = inode_change_ok(inode, iattr);
11414+ if (error)
11415+ goto out;
11416+
11417+ error = inode_setattr(inode, iattr);
11418+ if (error)
11419+ goto out;
11420+
11421+ de->uid = inode->i_uid;
11422+ de->gid = inode->i_gid;
11423+ de->mode = inode->i_mode;
11424+out:
11425+ return error;
11426+}
11427+
11428+#endif
11429+
11430+#ifdef CONFIG_CCSECURITY_NETWORK
11431+
11432+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && defined(CONFIG_NET)
11433+#define ccs_in4_pton in4_pton
11434+#define ccs_in6_pton in6_pton
11435+#else
11436+/*
11437+ * Routines for parsing IPv4 or IPv6 address.
11438+ * These are copied from lib/hexdump.c net/core/utils.c .
11439+ */
11440+#include <linux/ctype.h>
11441+
11442+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
11443+static int hex_to_bin(char ch)
11444+{
11445+ if ((ch >= '0') && (ch <= '9'))
11446+ return ch - '0';
11447+ ch = tolower(ch);
11448+ if ((ch >= 'a') && (ch <= 'f'))
11449+ return ch - 'a' + 10;
11450+ return -1;
11451+}
11452+#endif
11453+
11454+#define IN6PTON_XDIGIT 0x00010000
11455+#define IN6PTON_DIGIT 0x00020000
11456+#define IN6PTON_COLON_MASK 0x00700000
11457+#define IN6PTON_COLON_1 0x00100000 /* single : requested */
11458+#define IN6PTON_COLON_2 0x00200000 /* second : requested */
11459+#define IN6PTON_COLON_1_2 0x00400000 /* :: requested */
11460+#define IN6PTON_DOT 0x00800000 /* . */
11461+#define IN6PTON_DELIM 0x10000000
11462+#define IN6PTON_NULL 0x20000000 /* first/tail */
11463+#define IN6PTON_UNKNOWN 0x40000000
11464+
11465+static inline int xdigit2bin(char c, int delim)
11466+{
11467+ int val;
11468+
11469+ if (c == delim || c == '\0')
11470+ return IN6PTON_DELIM;
11471+ if (c == ':')
11472+ return IN6PTON_COLON_MASK;
11473+ if (c == '.')
11474+ return IN6PTON_DOT;
11475+
11476+ val = hex_to_bin(c);
11477+ if (val >= 0)
11478+ return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0);
11479+
11480+ if (delim == -1)
11481+ return IN6PTON_DELIM;
11482+ return IN6PTON_UNKNOWN;
11483+}
11484+
11485+static int ccs_in4_pton(const char *src, int srclen, u8 *dst, int delim,
11486+ const char **end)
11487+{
11488+ const char *s;
11489+ u8 *d;
11490+ u8 dbuf[4];
11491+ int ret = 0;
11492+ int i;
11493+ int w = 0;
11494+
11495+ if (srclen < 0)
11496+ srclen = strlen(src);
11497+ s = src;
11498+ d = dbuf;
11499+ i = 0;
11500+ while (1) {
11501+ int c;
11502+ c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
11503+ if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM |
11504+ IN6PTON_COLON_MASK)))
11505+ goto out;
11506+ if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
11507+ if (w == 0)
11508+ goto out;
11509+ *d++ = w & 0xff;
11510+ w = 0;
11511+ i++;
11512+ if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
11513+ if (i != 4)
11514+ goto out;
11515+ break;
11516+ }
11517+ goto cont;
11518+ }
11519+ w = (w * 10) + c;
11520+ if ((w & 0xffff) > 255)
11521+ goto out;
11522+cont:
11523+ if (i >= 4)
11524+ goto out;
11525+ s++;
11526+ srclen--;
11527+ }
11528+ ret = 1;
11529+ memcpy(dst, dbuf, sizeof(dbuf));
11530+out:
11531+ if (end)
11532+ *end = s;
11533+ return ret;
11534+}
11535+
11536+static int ccs_in6_pton(const char *src, int srclen, u8 *dst, int delim,
11537+ const char **end)
11538+{
11539+ const char *s, *tok = NULL;
11540+ u8 *d, *dc = NULL;
11541+ u8 dbuf[16];
11542+ int ret = 0;
11543+ int i;
11544+ int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL;
11545+ int w = 0;
11546+
11547+ memset(dbuf, 0, sizeof(dbuf));
11548+
11549+ s = src;
11550+ d = dbuf;
11551+ if (srclen < 0)
11552+ srclen = strlen(src);
11553+
11554+ while (1) {
11555+ int c;
11556+
11557+ c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
11558+ if (!(c & state))
11559+ goto out;
11560+ if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
11561+ /* process one 16-bit word */
11562+ if (!(state & IN6PTON_NULL)) {
11563+ *d++ = (w >> 8) & 0xff;
11564+ *d++ = w & 0xff;
11565+ }
11566+ w = 0;
11567+ if (c & IN6PTON_DELIM) {
11568+ /* We've processed last word */
11569+ break;
11570+ }
11571+ /*
11572+ * COLON_1 => XDIGIT
11573+ * COLON_2 => XDIGIT|DELIM
11574+ * COLON_1_2 => COLON_2
11575+ */
11576+ switch (state & IN6PTON_COLON_MASK) {
11577+ case IN6PTON_COLON_2:
11578+ dc = d;
11579+ state = IN6PTON_XDIGIT | IN6PTON_DELIM;
11580+ if (dc - dbuf >= sizeof(dbuf))
11581+ state |= IN6PTON_NULL;
11582+ break;
11583+ case IN6PTON_COLON_1|IN6PTON_COLON_1_2:
11584+ state = IN6PTON_XDIGIT | IN6PTON_COLON_2;
11585+ break;
11586+ case IN6PTON_COLON_1:
11587+ state = IN6PTON_XDIGIT;
11588+ break;
11589+ case IN6PTON_COLON_1_2:
11590+ state = IN6PTON_COLON_2;
11591+ break;
11592+ default:
11593+ state = 0;
11594+ }
11595+ tok = s + 1;
11596+ goto cont;
11597+ }
11598+
11599+ if (c & IN6PTON_DOT) {
11600+ ret = ccs_in4_pton(tok ? tok : s, srclen +
11601+ (int)(s - tok), d, delim, &s);
11602+ if (ret > 0) {
11603+ d += 4;
11604+ break;
11605+ }
11606+ goto out;
11607+ }
11608+
11609+ w = (w << 4) | (0xff & c);
11610+ state = IN6PTON_COLON_1 | IN6PTON_DELIM;
11611+ if (!(w & 0xf000))
11612+ state |= IN6PTON_XDIGIT;
11613+ if (!dc && d + 2 < dbuf + sizeof(dbuf)) {
11614+ state |= IN6PTON_COLON_1_2;
11615+ state &= ~IN6PTON_DELIM;
11616+ }
11617+ if (d + 2 >= dbuf + sizeof(dbuf))
11618+ state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2);
11619+cont:
11620+ if ((dc && d + 4 < dbuf + sizeof(dbuf)) ||
11621+ d + 4 == dbuf + sizeof(dbuf))
11622+ state |= IN6PTON_DOT;
11623+ if (d >= dbuf + sizeof(dbuf))
11624+ state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK);
11625+ s++;
11626+ srclen--;
11627+ }
11628+
11629+ i = 15; d--;
11630+
11631+ if (dc) {
11632+ while (d >= dc)
11633+ dst[i--] = *d--;
11634+ while (i >= dc - dbuf)
11635+ dst[i--] = 0;
11636+ while (i >= 0)
11637+ dst[i--] = *d--;
11638+ } else
11639+ memcpy(dst, dbuf, sizeof(dbuf));
11640+
11641+ ret = 1;
11642+out:
11643+ if (end)
11644+ *end = s;
11645+ return ret;
11646+}
11647+#endif
11648+
11649+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
11650+
11651+/*
11652+ * Routines for printing IPv4 or IPv6 address.
11653+ * These are copied from include/linux/kernel.h include/net/ipv6.h
11654+ * include/net/addrconf.h lib/hexdump.c lib/vsprintf.c and simplified.
11655+ */
11656+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
11657+#if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5 || !defined(RHEL_MINOR) || RHEL_MINOR < 9
11658+static const char hex_asc[] = "0123456789abcdef";
11659+#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
11660+#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
11661+
11662+static inline char *pack_hex_byte(char *buf, u8 byte)
11663+{
11664+ *buf++ = hex_asc_hi(byte);
11665+ *buf++ = hex_asc_lo(byte);
11666+ return buf;
11667+}
11668+#endif
11669+#endif
11670+
11671+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
11672+static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
11673+{
11674+ return (a->s6_addr32[0] | a->s6_addr32[1] |
11675+ (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0;
11676+}
11677+#endif
11678+
11679+static inline int ipv6_addr_is_isatap(const struct in6_addr *addr)
11680+{
11681+ return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
11682+}
11683+
11684+static char *ip4_string(char *p, const u8 *addr)
11685+{
11686+ /*
11687+ * Since this function is called outside vsnprintf(), I can use
11688+ * sprintf() here.
11689+ */
11690+ return p +
11691+ sprintf(p, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
11692+}
11693+
11694+static char *ip6_compressed_string(char *p, const char *addr)
11695+{
11696+ int i, j, range;
11697+ unsigned char zerolength[8];
11698+ int longest = 1;
11699+ int colonpos = -1;
11700+ u16 word;
11701+ u8 hi, lo;
11702+ bool needcolon = false;
11703+ bool useIPv4;
11704+ struct in6_addr in6;
11705+
11706+ memcpy(&in6, addr, sizeof(struct in6_addr));
11707+
11708+ useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
11709+
11710+ memset(zerolength, 0, sizeof(zerolength));
11711+
11712+ if (useIPv4)
11713+ range = 6;
11714+ else
11715+ range = 8;
11716+
11717+ /* find position of longest 0 run */
11718+ for (i = 0; i < range; i++) {
11719+ for (j = i; j < range; j++) {
11720+ if (in6.s6_addr16[j] != 0)
11721+ break;
11722+ zerolength[i]++;
11723+ }
11724+ }
11725+ for (i = 0; i < range; i++) {
11726+ if (zerolength[i] > longest) {
11727+ longest = zerolength[i];
11728+ colonpos = i;
11729+ }
11730+ }
11731+ if (longest == 1) /* don't compress a single 0 */
11732+ colonpos = -1;
11733+
11734+ /* emit address */
11735+ for (i = 0; i < range; i++) {
11736+ if (i == colonpos) {
11737+ if (needcolon || i == 0)
11738+ *p++ = ':';
11739+ *p++ = ':';
11740+ needcolon = false;
11741+ i += longest - 1;
11742+ continue;
11743+ }
11744+ if (needcolon) {
11745+ *p++ = ':';
11746+ needcolon = false;
11747+ }
11748+ /* hex u16 without leading 0s */
11749+ word = ntohs(in6.s6_addr16[i]);
11750+ hi = word >> 8;
11751+ lo = word & 0xff;
11752+ if (hi) {
11753+ if (hi > 0x0f)
11754+ p = pack_hex_byte(p, hi);
11755+ else
11756+ *p++ = hex_asc_lo(hi);
11757+ p = pack_hex_byte(p, lo);
11758+ } else if (lo > 0x0f)
11759+ p = pack_hex_byte(p, lo);
11760+ else
11761+ *p++ = hex_asc_lo(lo);
11762+ needcolon = true;
11763+ }
11764+
11765+ if (useIPv4) {
11766+ if (needcolon)
11767+ *p++ = ':';
11768+ p = ip4_string(p, &in6.s6_addr[12]);
11769+ }
11770+ *p = '\0';
11771+
11772+ return p;
11773+}
11774+#endif
11775+
11776+/**
11777+ * ccs_print_ipv4 - Print an IPv4 address.
11778+ *
11779+ * @buffer: Buffer to write to.
11780+ * @buffer_len: Size of @buffer.
11781+ * @ip: Pointer to "u32 in network byte order".
11782+ *
11783+ * Returns written length.
11784+ */
11785+static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
11786+ const u32 *ip)
11787+{
11788+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
11789+ return snprintf(buffer, buffer_len, "%pI4", ip);
11790+#else
11791+ char addr[sizeof("255.255.255.255")];
11792+ ip4_string(addr, (const u8 *) ip);
11793+ return snprintf(buffer, buffer_len, "%s", addr);
11794+#endif
11795+}
11796+
11797+/**
11798+ * ccs_print_ipv6 - Print an IPv6 address.
11799+ *
11800+ * @buffer: Buffer to write to.
11801+ * @buffer_len: Size of @buffer.
11802+ * @ip: Pointer to "struct in6_addr".
11803+ *
11804+ * Returns written length.
11805+ */
11806+static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
11807+ const struct in6_addr *ip)
11808+{
11809+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
11810+ return snprintf(buffer, buffer_len, "%pI6c", ip);
11811+#else
11812+ char addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
11813+ ip6_compressed_string(addr, (const u8 *) ip);
11814+ return snprintf(buffer, buffer_len, "%s", addr);
11815+#endif
11816+}
11817+
11818+/**
11819+ * ccs_print_ip - Print an IP address.
11820+ *
11821+ * @buf: Buffer to write to.
11822+ * @size: Size of @buf.
11823+ * @ptr: Pointer to "struct ipaddr_union".
11824+ *
11825+ * Returns nothing.
11826+ */
11827+static void ccs_print_ip(char *buf, const unsigned int size,
11828+ const struct ccs_ipaddr_union *ptr)
11829+{
11830+ int len;
11831+ if (ptr->is_ipv6)
11832+ len = ccs_print_ipv6(buf, size, &ptr->ip[0]);
11833+ else
11834+ len = ccs_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0]);
11835+ if (!memcmp(&ptr->ip[0], &ptr->ip[1], 16) || len >= size / 2)
11836+ return;
11837+ buf[len++] = '-';
11838+ if (ptr->is_ipv6)
11839+ ccs_print_ipv6(buf + len, size - len, &ptr->ip[1]);
11840+ else
11841+ ccs_print_ipv4(buf + len, size - len,
11842+ &ptr->ip[1].s6_addr32[0]);
11843+}
11844+
11845+#endif
11846+
11847+/***** SECTION5: Variables definition section *****/
11848+
11849+/* Permit policy management by non-root user? */
11850+static bool ccs_manage_by_non_root;
11851+
11852+/* Lock for protecting policy. */
11853+DEFINE_MUTEX(ccs_policy_lock);
11854+
11855+/* Has /sbin/init started? */
11856+bool ccs_policy_loaded;
11857+
11858+/* List of namespaces. */
11859+LIST_HEAD(ccs_namespace_list);
11860+/* True if namespace other than ccs_kernel_namespace is defined. */
11861+static bool ccs_namespace_enabled;
11862+
11863+/* Initial namespace.*/
11864+static struct ccs_policy_namespace ccs_kernel_namespace;
11865+
11866+/* List of "struct ccs_condition". */
11867+LIST_HEAD(ccs_condition_list);
11868+
11869+#ifdef CONFIG_CCSECURITY_PORTRESERVE
11870+/* Bitmap for reserved local port numbers.*/
11871+static u8 ccs_reserved_port_map[8192];
11872+#endif
11873+
11874+/* Wait queue for kernel -> userspace notification. */
11875+static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
11876+/* Wait queue for userspace -> kernel notification. */
11877+static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);
11878+
11879+/* The list for "struct ccs_query". */
11880+static LIST_HEAD(ccs_query_list);
11881+
11882+/* Lock for manipulating ccs_query_list. */
11883+static DEFINE_SPINLOCK(ccs_query_list_lock);
11884+
11885+/* Number of "struct file" referring /proc/ccs/query interface. */
11886+static atomic_t ccs_query_observers = ATOMIC_INIT(0);
11887+
11888+/* Wait queue for /proc/ccs/audit. */
11889+static DECLARE_WAIT_QUEUE_HEAD(ccs_log_wait);
11890+
11891+/* The list for "struct ccs_log". */
11892+static LIST_HEAD(ccs_log);
11893+
11894+/* Lock for "struct list_head ccs_log". */
11895+static DEFINE_SPINLOCK(ccs_log_lock);
11896+
11897+/* Length of "stuct list_head ccs_log". */
11898+static unsigned int ccs_log_count;
11899+
11900+/* Timestamp counter for last updated. */
11901+static unsigned int ccs_stat_updated[CCS_MAX_POLICY_STAT];
11902+
11903+/* Counter for number of updates. */
11904+static unsigned int ccs_stat_modified[CCS_MAX_POLICY_STAT];
11905+
11906+/* Operations for /proc/ccs/self_domain interface. */
11907+static
11908+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
11909+const
11910+#endif
11911+struct file_operations ccs_self_operations = {
11912+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
11913+ .write = ccs_write_self,
11914+#endif
11915+ .read = ccs_read_self,
11916+};
11917+
11918+/* Operations for /proc/ccs/ interface. */
11919+static
11920+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
11921+const
11922+#endif
11923+struct file_operations ccs_operations = {
11924+ .open = ccs_open,
11925+ .release = ccs_release,
11926+ .poll = ccs_poll,
11927+ .read = ccs_read,
11928+ .write = ccs_write,
11929+};
11930+
11931+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
11932+
11933+/* The inode operations for /proc/ccs/ directory. */
11934+static struct inode_operations ccs_dir_inode_operations;
11935+
11936+/* The inode operations for files under /proc/ccs/ directory. */
11937+static struct inode_operations ccs_file_inode_operations;
11938+
11939+#endif
11940+
11941+/***** SECTION6: Dependent functions section *****/
11942+
11943+/**
11944+ * list_for_each_cookie - iterate over a list with cookie.
11945+ *
11946+ * @pos: Pointer to "struct list_head".
11947+ * @head: Pointer to "struct list_head".
11948+ */
11949+#define list_for_each_cookie(pos, head) \
11950+ for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \
11951+ pos != (head); pos = srcu_dereference(pos->next, &ccs_ss))
11952+
11953+/**
11954+ * ccs_read_token - Read a word from a line.
11955+ *
11956+ * @param: Pointer to "struct ccs_acl_param".
11957+ *
11958+ * Returns a word on success, "" otherwise.
11959+ *
11960+ * To allow the caller to skip NULL check, this function returns "" rather than
11961+ * NULL if there is no more words to read.
11962+ */
11963+static char *ccs_read_token(struct ccs_acl_param *param)
11964+{
11965+ char *pos = param->data;
11966+ char *del = strchr(pos, ' ');
11967+ if (del)
11968+ *del++ = '\0';
11969+ else
11970+ del = pos + strlen(pos);
11971+ param->data = del;
11972+ return pos;
11973+}
11974+
11975+/**
11976+ * ccs_make_byte - Make byte value from three octal characters.
11977+ *
11978+ * @c1: The first character.
11979+ * @c2: The second character.
11980+ * @c3: The third character.
11981+ *
11982+ * Returns byte value.
11983+ */
11984+static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3)
11985+{
11986+ return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
11987+}
11988+
11989+/**
11990+ * ccs_correct_word2 - Check whether the given string follows the naming rules.
11991+ *
11992+ * @string: The byte sequence to check. Not '\0'-terminated.
11993+ * @len: Length of @string.
11994+ *
11995+ * Returns true if @string follows the naming rules, false otherwise.
11996+ */
11997+static bool ccs_correct_word2(const char *string, size_t len)
11998+{
11999+ const char *const start = string;
12000+ bool in_repetition = false;
12001+ unsigned char c;
12002+ unsigned char d;
12003+ unsigned char e;
12004+ if (!len)
12005+ goto out;
12006+ while (len--) {
12007+ c = *string++;
12008+ if (c == '\\') {
12009+ if (!len--)
12010+ goto out;
12011+ c = *string++;
12012+ switch (c) {
12013+ case '\\': /* "\\" */
12014+ continue;
12015+ case '$': /* "\$" */
12016+ case '+': /* "\+" */
12017+ case '?': /* "\?" */
12018+ case '*': /* "\*" */
12019+ case '@': /* "\@" */
12020+ case 'x': /* "\x" */
12021+ case 'X': /* "\X" */
12022+ case 'a': /* "\a" */
12023+ case 'A': /* "\A" */
12024+ case '-': /* "\-" */
12025+ continue;
12026+ case '{': /* "/\{" */
12027+ if (string - 3 < start || *(string - 3) != '/')
12028+ break;
12029+ in_repetition = true;
12030+ continue;
12031+ case '}': /* "\}/" */
12032+ if (*string != '/')
12033+ break;
12034+ if (!in_repetition)
12035+ break;
12036+ in_repetition = false;
12037+ continue;
12038+ case '0': /* "\ooo" */
12039+ case '1':
12040+ case '2':
12041+ case '3':
12042+ if (!len-- || !len--)
12043+ break;
12044+ d = *string++;
12045+ e = *string++;
12046+ if (d < '0' || d > '7' || e < '0' || e > '7')
12047+ break;
12048+ c = ccs_make_byte(c, d, e);
12049+ if (c <= ' ' || c >= 127)
12050+ continue;
12051+ }
12052+ goto out;
12053+ } else if (in_repetition && c == '/') {
12054+ goto out;
12055+ } else if (c <= ' ' || c >= 127) {
12056+ goto out;
12057+ }
12058+ }
12059+ if (in_repetition)
12060+ goto out;
12061+ return true;
12062+out:
12063+ return false;
12064+}
12065+
12066+/**
12067+ * ccs_correct_word - Check whether the given string follows the naming rules.
12068+ *
12069+ * @string: The string to check.
12070+ *
12071+ * Returns true if @string follows the naming rules, false otherwise.
12072+ */
12073+static bool ccs_correct_word(const char *string)
12074+{
12075+ return ccs_correct_word2(string, strlen(string));
12076+}
12077+
12078+/**
12079+ * ccs_get_group - Allocate memory for "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group".
12080+ *
12081+ * @param: Pointer to "struct ccs_acl_param".
12082+ * @idx: Index number.
12083+ *
12084+ * Returns pointer to "struct ccs_group" on success, NULL otherwise.
12085+ */
12086+static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
12087+ const u8 idx)
12088+{
12089+ struct ccs_group e = { };
12090+ struct ccs_group *group = NULL;
12091+ struct list_head *list;
12092+ const char *group_name = ccs_read_token(param);
12093+ bool found = false;
12094+ if (!ccs_correct_word(group_name) || idx >= CCS_MAX_GROUP)
12095+ return NULL;
12096+ e.group_name = ccs_get_name(group_name);
12097+ if (!e.group_name)
12098+ return NULL;
12099+ if (mutex_lock_interruptible(&ccs_policy_lock))
12100+ goto out;
12101+ list = &param->ns->group_list[idx];
12102+ list_for_each_entry(group, list, head.list) {
12103+ if (e.group_name != group->group_name ||
12104+ atomic_read(&group->head.users) == CCS_GC_IN_PROGRESS)
12105+ continue;
12106+ atomic_inc(&group->head.users);
12107+ found = true;
12108+ break;
12109+ }
12110+ if (!found) {
12111+ struct ccs_group *entry = ccs_commit_ok(&e, sizeof(e));
12112+ if (entry) {
12113+ INIT_LIST_HEAD(&entry->member_list);
12114+ atomic_set(&entry->head.users, 1);
12115+ list_add_tail_rcu(&entry->head.list, list);
12116+ group = entry;
12117+ found = true;
12118+ }
12119+ }
12120+ mutex_unlock(&ccs_policy_lock);
12121+out:
12122+ ccs_put_name(e.group_name);
12123+ return found ? group : NULL;
12124+}
12125+
12126+/**
12127+ * ccs_parse_name_union - Parse a ccs_name_union.
12128+ *
12129+ * @param: Pointer to "struct ccs_acl_param".
12130+ * @ptr: Pointer to "struct ccs_name_union".
12131+ *
12132+ * Returns true on success, false otherwise.
12133+ */
12134+static bool ccs_parse_name_union(struct ccs_acl_param *param,
12135+ struct ccs_name_union *ptr)
12136+{
12137+ char *filename;
12138+ if (param->data[0] == '@') {
12139+ param->data++;
12140+ ptr->group = ccs_get_group(param, CCS_PATH_GROUP);
12141+ return ptr->group != NULL;
12142+ }
12143+ filename = ccs_read_token(param);
12144+ if (!ccs_correct_word(filename))
12145+ return false;
12146+ ptr->filename = ccs_get_name(filename);
12147+ return ptr->filename != NULL;
12148+}
12149+
12150+/**
12151+ * ccs_parse_ulong - Parse an "unsigned long" value.
12152+ *
12153+ * @result: Pointer to "unsigned long".
12154+ * @str: Pointer to string to parse.
12155+ *
12156+ * Returns one of values in "enum ccs_value_type".
12157+ *
12158+ * The @src is updated to point the first character after the value
12159+ * on success.
12160+ */
12161+static u8 ccs_parse_ulong(unsigned long *result, char **str)
12162+{
12163+ const char *cp = *str;
12164+ char *ep;
12165+ int base = 10;
12166+ if (*cp == '0') {
12167+ char c = *(cp + 1);
12168+ if (c == 'x' || c == 'X') {
12169+ base = 16;
12170+ cp += 2;
12171+ } else if (c >= '0' && c <= '7') {
12172+ base = 8;
12173+ cp++;
12174+ }
12175+ }
12176+ *result = simple_strtoul(cp, &ep, base);
12177+ if (cp == ep)
12178+ return CCS_VALUE_TYPE_INVALID;
12179+ *str = ep;
12180+ switch (base) {
12181+ case 16:
12182+ return CCS_VALUE_TYPE_HEXADECIMAL;
12183+ case 8:
12184+ return CCS_VALUE_TYPE_OCTAL;
12185+ default:
12186+ return CCS_VALUE_TYPE_DECIMAL;
12187+ }
12188+}
12189+
12190+/**
12191+ * ccs_parse_number_union - Parse a ccs_number_union.
12192+ *
12193+ * @param: Pointer to "struct ccs_acl_param".
12194+ * @ptr: Pointer to "struct ccs_number_union".
12195+ *
12196+ * Returns true on success, false otherwise.
12197+ */
12198+static bool ccs_parse_number_union(struct ccs_acl_param *param,
12199+ struct ccs_number_union *ptr)
12200+{
12201+ char *data;
12202+ u8 type;
12203+ unsigned long v;
12204+ memset(ptr, 0, sizeof(*ptr));
12205+ if (param->data[0] == '@') {
12206+ param->data++;
12207+ ptr->group = ccs_get_group(param, CCS_NUMBER_GROUP);
12208+ return ptr->group != NULL;
12209+ }
12210+ data = ccs_read_token(param);
12211+ type = ccs_parse_ulong(&v, &data);
12212+ if (type == CCS_VALUE_TYPE_INVALID)
12213+ return false;
12214+ ptr->values[0] = v;
12215+ ptr->value_type[0] = type;
12216+ if (!*data) {
12217+ ptr->values[1] = v;
12218+ ptr->value_type[1] = type;
12219+ return true;
12220+ }
12221+ if (*data++ != '-')
12222+ return false;
12223+ type = ccs_parse_ulong(&v, &data);
12224+ if (type == CCS_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
12225+ return false;
12226+ ptr->values[1] = v;
12227+ ptr->value_type[1] = type;
12228+ return true;
12229+}
12230+
12231+#ifdef CONFIG_CCSECURITY_NETWORK
12232+
12233+/**
12234+ * ccs_parse_ipaddr_union - Parse an IP address.
12235+ *
12236+ * @param: Pointer to "struct ccs_acl_param".
12237+ * @ptr: Pointer to "struct ccs_ipaddr_union".
12238+ *
12239+ * Returns true on success, false otherwise.
12240+ */
12241+static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
12242+ struct ccs_ipaddr_union *ptr)
12243+{
12244+ u8 * const min = ptr->ip[0].in6_u.u6_addr8;
12245+ u8 * const max = ptr->ip[1].in6_u.u6_addr8;
12246+ char *address = ccs_read_token(param);
12247+ const char *end;
12248+ if (!strchr(address, ':') &&
12249+ ccs_in4_pton(address, -1, min, '-', &end) > 0) {
12250+ ptr->is_ipv6 = false;
12251+ if (!*end)
12252+ ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
12253+ else if (*end++ != '-' ||
12254+ ccs_in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
12255+ return false;
12256+ return true;
12257+ }
12258+ if (ccs_in6_pton(address, -1, min, '-', &end) > 0) {
12259+ ptr->is_ipv6 = true;
12260+ if (!*end)
12261+ memmove(max, min, sizeof(u16) * 8);
12262+ else if (*end++ != '-' ||
12263+ ccs_in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
12264+ return false;
12265+ return true;
12266+ }
12267+ return false;
12268+}
12269+
12270+#endif
12271+
12272+/**
12273+ * ccs_get_dqword - ccs_get_name() for a quoted string.
12274+ *
12275+ * @start: String to save.
12276+ *
12277+ * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
12278+ */
12279+static const struct ccs_path_info *ccs_get_dqword(char *start)
12280+{
12281+ char *cp = start + strlen(start) - 1;
12282+ if (cp == start || *start++ != '"' || *cp != '"')
12283+ return NULL;
12284+ *cp = '\0';
12285+ if (*start && !ccs_correct_word(start))
12286+ return NULL;
12287+ return ccs_get_name(start);
12288+}
12289+
12290+/**
12291+ * ccs_parse_name_union_quoted - Parse a quoted word.
12292+ *
12293+ * @param: Pointer to "struct ccs_acl_param".
12294+ * @ptr: Pointer to "struct ccs_name_union".
12295+ *
12296+ * Returns true on success, false otherwise.
12297+ */
12298+static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param,
12299+ struct ccs_name_union *ptr)
12300+{
12301+ char *filename = param->data;
12302+ if (*filename == '@')
12303+ return ccs_parse_name_union(param, ptr);
12304+ ptr->filename = ccs_get_dqword(filename);
12305+ return ptr->filename != NULL;
12306+}
12307+
12308+/**
12309+ * ccs_parse_argv - Parse an argv[] condition part.
12310+ *
12311+ * @left: Lefthand value.
12312+ * @right: Righthand value.
12313+ * @argv: Pointer to "struct ccs_argv".
12314+ *
12315+ * Returns true on success, false otherwise.
12316+ */
12317+static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv)
12318+{
12319+ if (ccs_parse_ulong(&argv->index, &left) != CCS_VALUE_TYPE_DECIMAL ||
12320+ *left++ != ']' || *left)
12321+ return false;
12322+ argv->value = ccs_get_dqword(right);
12323+ return argv->value != NULL;
12324+}
12325+
12326+/**
12327+ * ccs_parse_envp - Parse an envp[] condition part.
12328+ *
12329+ * @left: Lefthand value.
12330+ * @right: Righthand value.
12331+ * @envp: Pointer to "struct ccs_envp".
12332+ *
12333+ * Returns true on success, false otherwise.
12334+ */
12335+static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp)
12336+{
12337+ const struct ccs_path_info *name;
12338+ const struct ccs_path_info *value;
12339+ char *cp = left + strlen(left) - 1;
12340+ if (*cp-- != ']' || *cp != '"')
12341+ goto out;
12342+ *cp = '\0';
12343+ if (!ccs_correct_word(left))
12344+ goto out;
12345+ name = ccs_get_name(left);
12346+ if (!name)
12347+ goto out;
12348+ if (!strcmp(right, "NULL")) {
12349+ value = NULL;
12350+ } else {
12351+ value = ccs_get_dqword(right);
12352+ if (!value) {
12353+ ccs_put_name(name);
12354+ goto out;
12355+ }
12356+ }
12357+ envp->name = name;
12358+ envp->value = value;
12359+ return true;
12360+out:
12361+ return false;
12362+}
12363+
12364+/**
12365+ * ccs_same_condition - Check for duplicated "struct ccs_condition" entry.
12366+ *
12367+ * @a: Pointer to "struct ccs_condition".
12368+ * @b: Pointer to "struct ccs_condition".
12369+ *
12370+ * Returns true if @a == @b, false otherwise.
12371+ */
12372+static bool ccs_same_condition(const struct ccs_condition *a,
12373+ const struct ccs_condition *b)
12374+{
12375+ return a->size == b->size && a->condc == b->condc &&
12376+ a->numbers_count == b->numbers_count &&
12377+ a->names_count == b->names_count &&
12378+ a->argc == b->argc && a->envc == b->envc &&
12379+ a->grant_log == b->grant_log &&
12380+ a->exec_transit == b->exec_transit && a->transit == b->transit
12381+ && !memcmp(a + 1, b + 1, a->size - sizeof(*a));
12382+}
12383+
12384+/**
12385+ * ccs_condition_type - Get condition type.
12386+ *
12387+ * @word: Keyword string.
12388+ *
12389+ * Returns one of values in "enum ccs_conditions_index" on success,
12390+ * CCS_MAX_CONDITION_KEYWORD otherwise.
12391+ */
12392+static u8 ccs_condition_type(const char *word)
12393+{
12394+ u8 i;
12395+ for (i = 0; i < CCS_MAX_CONDITION_KEYWORD; i++) {
12396+ if (!strcmp(word, ccs_condition_keyword[i]))
12397+ break;
12398+ }
12399+ return i;
12400+}
12401+
12402+/**
12403+ * ccs_commit_condition - Commit "struct ccs_condition".
12404+ *
12405+ * @entry: Pointer to "struct ccs_condition".
12406+ *
12407+ * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
12408+ *
12409+ * This function merges duplicated entries. This function returns NULL if
12410+ * @entry is not duplicated but memory quota for policy has exceeded.
12411+ */
12412+static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry)
12413+{
12414+ struct ccs_condition *ptr;
12415+ bool found = false;
12416+ if (mutex_lock_interruptible(&ccs_policy_lock)) {
12417+ dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
12418+ ptr = NULL;
12419+ found = true;
12420+ goto out;
12421+ }
12422+ list_for_each_entry(ptr, &ccs_condition_list, head.list) {
12423+ if (!ccs_same_condition(ptr, entry) ||
12424+ atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS)
12425+ continue;
12426+ /* Same entry found. Share this entry. */
12427+ atomic_inc(&ptr->head.users);
12428+ found = true;
12429+ break;
12430+ }
12431+ if (!found) {
12432+ if (ccs_memory_ok(entry, entry->size)) {
12433+ atomic_set(&entry->head.users, 1);
12434+ list_add(&entry->head.list, &ccs_condition_list);
12435+ } else {
12436+ found = true;
12437+ ptr = NULL;
12438+ }
12439+ }
12440+ mutex_unlock(&ccs_policy_lock);
12441+out:
12442+ if (found) {
12443+ ccs_del_condition(&entry->head.list);
12444+ kfree(entry);
12445+ entry = ptr;
12446+ }
12447+ return entry;
12448+}
12449+
12450+/**
12451+ * ccs_correct_path - Check whether the given pathname follows the naming rules.
12452+ *
12453+ * @filename: The pathname to check.
12454+ *
12455+ * Returns true if @filename follows the naming rules, false otherwise.
12456+ */
12457+static bool ccs_correct_path(const char *filename)
12458+{
12459+ return *filename == '/' && ccs_correct_word(filename);
12460+}
12461+
12462+/**
12463+ * ccs_domain_def - Check whether the given token can be a domainname.
12464+ *
12465+ * @buffer: The token to check.
12466+ *
12467+ * Returns true if @buffer possibly be a domainname, false otherwise.
12468+ */
12469+static bool ccs_domain_def(const unsigned char *buffer)
12470+{
12471+ const unsigned char *cp;
12472+ int len;
12473+ if (*buffer != '<')
12474+ return false;
12475+ cp = strchr(buffer, ' ');
12476+ if (!cp)
12477+ len = strlen(buffer);
12478+ else
12479+ len = cp - buffer;
12480+ if (buffer[len - 1] != '>' || !ccs_correct_word2(buffer + 1, len - 2))
12481+ return false;
12482+ return true;
12483+}
12484+
12485+/**
12486+ * ccs_correct_domain - Check whether the given domainname follows the naming rules.
12487+ *
12488+ * @domainname: The domainname to check.
12489+ *
12490+ * Returns true if @domainname follows the naming rules, false otherwise.
12491+ */
12492+static bool ccs_correct_domain(const unsigned char *domainname)
12493+{
12494+ if (!domainname || !ccs_domain_def(domainname))
12495+ return false;
12496+ domainname = strchr(domainname, ' ');
12497+ if (!domainname++)
12498+ return true;
12499+ while (1) {
12500+ const unsigned char *cp = strchr(domainname, ' ');
12501+ if (!cp)
12502+ break;
12503+ if (*domainname != '/' ||
12504+ !ccs_correct_word2(domainname, cp - domainname))
12505+ return false;
12506+ domainname = cp + 1;
12507+ }
12508+ return ccs_correct_path(domainname);
12509+}
12510+
12511+/**
12512+ * ccs_normalize_line - Format string.
12513+ *
12514+ * @buffer: The line to normalize.
12515+ *
12516+ * Returns nothing.
12517+ *
12518+ * Leading and trailing whitespaces are removed.
12519+ * Multiple whitespaces are packed into single space.
12520+ */
12521+static void ccs_normalize_line(unsigned char *buffer)
12522+{
12523+ unsigned char *sp = buffer;
12524+ unsigned char *dp = buffer;
12525+ bool first = true;
12526+ while (*sp && (*sp <= ' ' || *sp >= 127))
12527+ sp++;
12528+ while (*sp) {
12529+ if (!first)
12530+ *dp++ = ' ';
12531+ first = false;
12532+ while (*sp > ' ' && *sp < 127)
12533+ *dp++ = *sp++;
12534+ while (*sp && (*sp <= ' ' || *sp >= 127))
12535+ sp++;
12536+ }
12537+ *dp = '\0';
12538+}
12539+
12540+/**
12541+ * ccs_get_domainname - Read a domainname from a line.
12542+ *
12543+ * @param: Pointer to "struct ccs_acl_param".
12544+ *
12545+ * Returns a domainname on success, NULL otherwise.
12546+ */
12547+static const struct ccs_path_info *ccs_get_domainname
12548+(struct ccs_acl_param *param)
12549+{
12550+ char *start = param->data;
12551+ char *pos = start;
12552+ while (*pos) {
12553+ if (*pos++ != ' ' || *pos++ == '/')
12554+ continue;
12555+ pos -= 2;
12556+ *pos++ = '\0';
12557+ break;
12558+ }
12559+ param->data = pos;
12560+ if (ccs_correct_domain(start))
12561+ return ccs_get_name(start);
12562+ return NULL;
12563+}
12564+
12565+/**
12566+ * ccs_get_transit_preference - Parse domain transition preference for execve().
12567+ *
12568+ * @param: Pointer to "struct ccs_acl_param".
12569+ * @e: Pointer to "struct ccs_condition".
12570+ *
12571+ * Returns the condition string part.
12572+ */
12573+static char *ccs_get_transit_preference(struct ccs_acl_param *param,
12574+ struct ccs_condition *e)
12575+{
12576+ char * const pos = param->data;
12577+ bool flag;
12578+ if (*pos == '<') {
12579+ e->transit = ccs_get_domainname(param);
12580+ goto done;
12581+ }
12582+ {
12583+ char *cp = strchr(pos, ' ');
12584+ if (cp)
12585+ *cp = '\0';
12586+ flag = ccs_correct_path(pos) || !strcmp(pos, "keep") ||
12587+ !strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
12588+ !strcmp(pos, "child") || !strcmp(pos, "parent");
12589+ if (cp)
12590+ *cp = ' ';
12591+ }
12592+ if (!flag)
12593+ return pos;
12594+ e->transit = ccs_get_name(ccs_read_token(param));
12595+done:
12596+ if (e->transit) {
12597+ e->exec_transit = true;
12598+ return param->data;
12599+ }
12600+ /*
12601+ * Return a bad read-only condition string that will let
12602+ * ccs_get_condition() return NULL.
12603+ */
12604+ return "/";
12605+}
12606+
12607+/**
12608+ * ccs_get_condition - Parse condition part.
12609+ *
12610+ * @param: Pointer to "struct ccs_acl_param".
12611+ *
12612+ * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
12613+ */
12614+struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param)
12615+{
12616+ struct ccs_condition *entry = NULL;
12617+ struct ccs_condition_element *condp = NULL;
12618+ struct ccs_number_union *numbers_p = NULL;
12619+ struct ccs_name_union *names_p = NULL;
12620+ struct ccs_argv *argv = NULL;
12621+ struct ccs_envp *envp = NULL;
12622+ struct ccs_condition e = { };
12623+ char * const start_of_string = ccs_get_transit_preference(param, &e);
12624+ char * const end_of_string = start_of_string + strlen(start_of_string);
12625+ char *pos;
12626+rerun:
12627+ pos = start_of_string;
12628+ while (1) {
12629+ u8 left = -1;
12630+ u8 right = -1;
12631+ char *left_word = pos;
12632+ char *cp;
12633+ char *right_word;
12634+ bool is_not;
12635+ if (!*left_word)
12636+ break;
12637+ /*
12638+ * Since left-hand condition does not allow use of "path_group"
12639+ * or "number_group" and environment variable's names do not
12640+ * accept '=', it is guaranteed that the original line consists
12641+ * of one or more repetition of $left$operator$right blocks
12642+ * where "$left is free from '=' and ' '" and "$operator is
12643+ * either '=' or '!='" and "$right is free from ' '".
12644+ * Therefore, we can reconstruct the original line at the end
12645+ * of dry run even if we overwrite $operator with '\0'.
12646+ */
12647+ cp = strchr(pos, ' ');
12648+ if (cp) {
12649+ *cp = '\0'; /* Will restore later. */
12650+ pos = cp + 1;
12651+ } else {
12652+ pos = "";
12653+ }
12654+ right_word = strchr(left_word, '=');
12655+ if (!right_word || right_word == left_word)
12656+ goto out;
12657+ is_not = *(right_word - 1) == '!';
12658+ if (is_not)
12659+ *(right_word++ - 1) = '\0'; /* Will restore later. */
12660+ else if (*(right_word + 1) != '=')
12661+ *right_word++ = '\0'; /* Will restore later. */
12662+ else
12663+ goto out;
12664+ dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
12665+ is_not ? "!" : "", right_word);
12666+ if (!strcmp(left_word, "grant_log")) {
12667+ if (entry) {
12668+ if (is_not ||
12669+ entry->grant_log != CCS_GRANTLOG_AUTO)
12670+ goto out;
12671+ else if (!strcmp(right_word, "yes"))
12672+ entry->grant_log = CCS_GRANTLOG_YES;
12673+ else if (!strcmp(right_word, "no"))
12674+ entry->grant_log = CCS_GRANTLOG_NO;
12675+ else
12676+ goto out;
12677+ }
12678+ continue;
12679+ }
12680+ if (!strcmp(left_word, "auto_domain_transition")) {
12681+ if (entry) {
12682+ if (is_not || entry->transit)
12683+ goto out;
12684+ entry->transit = ccs_get_dqword(right_word);
12685+ if (!entry->transit ||
12686+ (entry->transit->name[0] != '/' &&
12687+ !ccs_domain_def(entry->transit->name)))
12688+ goto out;
12689+ }
12690+ continue;
12691+ }
12692+ if (!strncmp(left_word, "exec.argv[", 10)) {
12693+ if (!argv) {
12694+ e.argc++;
12695+ e.condc++;
12696+ } else {
12697+ e.argc--;
12698+ e.condc--;
12699+ left = CCS_ARGV_ENTRY;
12700+ argv->is_not = is_not;
12701+ if (!ccs_parse_argv(left_word + 10,
12702+ right_word, argv++))
12703+ goto out;
12704+ }
12705+ goto store_value;
12706+ }
12707+ if (!strncmp(left_word, "exec.envp[\"", 11)) {
12708+ if (!envp) {
12709+ e.envc++;
12710+ e.condc++;
12711+ } else {
12712+ e.envc--;
12713+ e.condc--;
12714+ left = CCS_ENVP_ENTRY;
12715+ envp->is_not = is_not;
12716+ if (!ccs_parse_envp(left_word + 11,
12717+ right_word, envp++))
12718+ goto out;
12719+ }
12720+ goto store_value;
12721+ }
12722+ left = ccs_condition_type(left_word);
12723+ dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
12724+ left);
12725+ if (left == CCS_MAX_CONDITION_KEYWORD) {
12726+ if (!numbers_p) {
12727+ e.numbers_count++;
12728+ } else {
12729+ e.numbers_count--;
12730+ left = CCS_NUMBER_UNION;
12731+ param->data = left_word;
12732+ if (*left_word == '@' ||
12733+ !ccs_parse_number_union(param,
12734+ numbers_p++))
12735+ goto out;
12736+ }
12737+ }
12738+ if (!condp)
12739+ e.condc++;
12740+ else
12741+ e.condc--;
12742+ if (left == CCS_EXEC_REALPATH || left == CCS_SYMLINK_TARGET) {
12743+ if (!names_p) {
12744+ e.names_count++;
12745+ } else {
12746+ e.names_count--;
12747+ right = CCS_NAME_UNION;
12748+ param->data = right_word;
12749+ if (!ccs_parse_name_union_quoted(param,
12750+ names_p++))
12751+ goto out;
12752+ }
12753+ goto store_value;
12754+ }
12755+ right = ccs_condition_type(right_word);
12756+ if (right == CCS_MAX_CONDITION_KEYWORD) {
12757+ if (!numbers_p) {
12758+ e.numbers_count++;
12759+ } else {
12760+ e.numbers_count--;
12761+ right = CCS_NUMBER_UNION;
12762+ param->data = right_word;
12763+ if (!ccs_parse_number_union(param,
12764+ numbers_p++))
12765+ goto out;
12766+ }
12767+ }
12768+store_value:
12769+ if (!condp) {
12770+ dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
12771+ "match=%u\n", __LINE__, left, right, !is_not);
12772+ continue;
12773+ }
12774+ condp->left = left;
12775+ condp->right = right;
12776+ condp->equals = !is_not;
12777+ dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
12778+ __LINE__, condp->left, condp->right,
12779+ condp->equals);
12780+ condp++;
12781+ }
12782+ dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
12783+ __LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
12784+ e.envc);
12785+ if (entry) {
12786+ BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
12787+ e.condc);
12788+ return ccs_commit_condition(entry);
12789+ }
12790+ e.size = sizeof(*entry)
12791+ + e.condc * sizeof(struct ccs_condition_element)
12792+ + e.numbers_count * sizeof(struct ccs_number_union)
12793+ + e.names_count * sizeof(struct ccs_name_union)
12794+ + e.argc * sizeof(struct ccs_argv)
12795+ + e.envc * sizeof(struct ccs_envp);
12796+ entry = kzalloc(e.size, CCS_GFP_FLAGS);
12797+ if (!entry)
12798+ goto out2;
12799+ *entry = e;
12800+ e.transit = NULL;
12801+ condp = (struct ccs_condition_element *) (entry + 1);
12802+ numbers_p = (struct ccs_number_union *) (condp + e.condc);
12803+ names_p = (struct ccs_name_union *) (numbers_p + e.numbers_count);
12804+ argv = (struct ccs_argv *) (names_p + e.names_count);
12805+ envp = (struct ccs_envp *) (argv + e.argc);
12806+ {
12807+ bool flag = false;
12808+ for (pos = start_of_string; pos < end_of_string; pos++) {
12809+ if (*pos)
12810+ continue;
12811+ if (flag) /* Restore " ". */
12812+ *pos = ' ';
12813+ else if (*(pos + 1) == '=') /* Restore "!=". */
12814+ *pos = '!';
12815+ else /* Restore "=". */
12816+ *pos = '=';
12817+ flag = !flag;
12818+ }
12819+ }
12820+ goto rerun;
12821+out:
12822+ dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
12823+ if (entry) {
12824+ ccs_del_condition(&entry->head.list);
12825+ kfree(entry);
12826+ }
12827+out2:
12828+ ccs_put_name(e.transit);
12829+ return NULL;
12830+}
12831+
12832+/**
12833+ * ccs_yesno - Return "yes" or "no".
12834+ *
12835+ * @value: Bool value.
12836+ *
12837+ * Returns "yes" if @value is not 0, "no" otherwise.
12838+ */
12839+static const char *ccs_yesno(const unsigned int value)
12840+{
12841+ return value ? "yes" : "no";
12842+}
12843+
12844+/**
12845+ * ccs_addprintf - strncat()-like-snprintf().
12846+ *
12847+ * @buffer: Buffer to write to. Must be '\0'-terminated.
12848+ * @len: Size of @buffer.
12849+ * @fmt: The printf()'s format string, followed by parameters.
12850+ *
12851+ * Returns nothing.
12852+ */
12853+static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
12854+{
12855+ va_list args;
12856+ const int pos = strlen(buffer);
12857+ va_start(args, fmt);
12858+ vsnprintf(buffer + pos, len - pos - 1, fmt, args);
12859+ va_end(args);
12860+}
12861+
12862+/**
12863+ * ccs_flush - Flush queued string to userspace's buffer.
12864+ *
12865+ * @head: Pointer to "struct ccs_io_buffer".
12866+ *
12867+ * Returns true if all data was flushed, false otherwise.
12868+ */
12869+static bool ccs_flush(struct ccs_io_buffer *head)
12870+{
12871+ while (head->r.w_pos) {
12872+ const char *w = head->r.w[0];
12873+ size_t len = strlen(w);
12874+ if (len) {
12875+ if (len > head->read_user_buf_avail)
12876+ len = head->read_user_buf_avail;
12877+ if (!len)
12878+ return false;
12879+ if (copy_to_user(head->read_user_buf, w, len))
12880+ return false;
12881+ head->read_user_buf_avail -= len;
12882+ head->read_user_buf += len;
12883+ w += len;
12884+ }
12885+ head->r.w[0] = w;
12886+ if (*w)
12887+ return false;
12888+ /* Add '\0' for audit logs and query. */
12889+ if (head->type == CCS_AUDIT || head->type == CCS_QUERY) {
12890+ if (!head->read_user_buf_avail ||
12891+ copy_to_user(head->read_user_buf, "", 1))
12892+ return false;
12893+ head->read_user_buf_avail--;
12894+ head->read_user_buf++;
12895+ }
12896+ head->r.w_pos--;
12897+ for (len = 0; len < head->r.w_pos; len++)
12898+ head->r.w[len] = head->r.w[len + 1];
12899+ }
12900+ head->r.avail = 0;
12901+ return true;
12902+}
12903+
12904+/**
12905+ * ccs_set_string - Queue string to "struct ccs_io_buffer" structure.
12906+ *
12907+ * @head: Pointer to "struct ccs_io_buffer".
12908+ * @string: String to print.
12909+ *
12910+ * Returns nothing.
12911+ *
12912+ * Note that @string has to be kept valid until @head is kfree()d.
12913+ * This means that char[] allocated on stack memory cannot be passed to
12914+ * this function. Use ccs_io_printf() for char[] allocated on stack memory.
12915+ */
12916+static void ccs_set_string(struct ccs_io_buffer *head, const char *string)
12917+{
12918+ if (head->r.w_pos < CCS_MAX_IO_READ_QUEUE) {
12919+ head->r.w[head->r.w_pos++] = string;
12920+ ccs_flush(head);
12921+ } else
12922+ printk(KERN_WARNING "Too many words in a line.\n");
12923+}
12924+
12925+/**
12926+ * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
12927+ *
12928+ * @head: Pointer to "struct ccs_io_buffer".
12929+ * @fmt: The printf()'s format string, followed by parameters.
12930+ *
12931+ * Returns nothing.
12932+ */
12933+static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
12934+{
12935+ va_list args;
12936+ size_t len;
12937+ size_t pos = head->r.avail;
12938+ int size = head->readbuf_size - pos;
12939+ if (size <= 0)
12940+ return;
12941+ va_start(args, fmt);
12942+ len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1;
12943+ va_end(args);
12944+ if (pos + len >= head->readbuf_size) {
12945+ printk(KERN_WARNING "Too many words in a line.\n");
12946+ return;
12947+ }
12948+ head->r.avail += len;
12949+ ccs_set_string(head, head->read_buf + pos);
12950+}
12951+
12952+/**
12953+ * ccs_set_space - Put a space to "struct ccs_io_buffer" structure.
12954+ *
12955+ * @head: Pointer to "struct ccs_io_buffer".
12956+ *
12957+ * Returns nothing.
12958+ */
12959+static void ccs_set_space(struct ccs_io_buffer *head)
12960+{
12961+ ccs_set_string(head, " ");
12962+}
12963+
12964+/**
12965+ * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure.
12966+ *
12967+ * @head: Pointer to "struct ccs_io_buffer".
12968+ *
12969+ * Returns true if all data was flushed, false otherwise.
12970+ */
12971+static bool ccs_set_lf(struct ccs_io_buffer *head)
12972+{
12973+ ccs_set_string(head, "\n");
12974+ return !head->r.w_pos;
12975+}
12976+
12977+/**
12978+ * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure.
12979+ *
12980+ * @head: Pointer to "struct ccs_io_buffer".
12981+ *
12982+ * Returns nothing.
12983+ */
12984+static void ccs_set_slash(struct ccs_io_buffer *head)
12985+{
12986+ ccs_set_string(head, "/");
12987+}
12988+
12989+/**
12990+ * ccs_init_policy_namespace - Initialize namespace.
12991+ *
12992+ * @ns: Pointer to "struct ccs_policy_namespace".
12993+ *
12994+ * Returns nothing.
12995+ */
12996+static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns)
12997+{
12998+ unsigned int idx;
12999+ for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++)
13000+ INIT_LIST_HEAD(&ns->acl_group[idx]);
13001+ for (idx = 0; idx < CCS_MAX_GROUP; idx++)
13002+ INIT_LIST_HEAD(&ns->group_list[idx]);
13003+ for (idx = 0; idx < CCS_MAX_POLICY; idx++)
13004+ INIT_LIST_HEAD(&ns->policy_list[idx]);
13005+ ns->profile_version = 20150505;
13006+ ccs_namespace_enabled = !list_empty(&ccs_namespace_list);
13007+ list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list);
13008+}
13009+
13010+/**
13011+ * ccs_print_namespace - Print namespace header.
13012+ *
13013+ * @head: Pointer to "struct ccs_io_buffer".
13014+ *
13015+ * Returns nothing.
13016+ */
13017+static void ccs_print_namespace(struct ccs_io_buffer *head)
13018+{
13019+ if (!ccs_namespace_enabled)
13020+ return;
13021+ ccs_set_string(head,
13022+ container_of(head->r.ns, struct ccs_policy_namespace,
13023+ namespace_list)->name);
13024+ ccs_set_space(head);
13025+}
13026+
13027+/**
13028+ * ccs_assign_profile - Create a new profile.
13029+ *
13030+ * @ns: Pointer to "struct ccs_policy_namespace".
13031+ * @profile: Profile number to create.
13032+ *
13033+ * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
13034+ */
13035+static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
13036+ const unsigned int profile)
13037+{
13038+ struct ccs_profile *ptr;
13039+ struct ccs_profile *entry;
13040+ if (profile >= CCS_MAX_PROFILES)
13041+ return NULL;
13042+ ptr = ns->profile_ptr[profile];
13043+ if (ptr)
13044+ return ptr;
13045+ entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
13046+ if (mutex_lock_interruptible(&ccs_policy_lock))
13047+ goto out;
13048+ ptr = ns->profile_ptr[profile];
13049+ if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
13050+ ptr = entry;
13051+ ptr->default_config = CCS_CONFIG_DISABLED |
13052+ CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
13053+ memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
13054+ sizeof(ptr->config));
13055+ ptr->pref[CCS_PREF_MAX_AUDIT_LOG] =
13056+ CONFIG_CCSECURITY_MAX_AUDIT_LOG;
13057+ ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
13058+ CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
13059+ mb(); /* Avoid out-of-order execution. */
13060+ ns->profile_ptr[profile] = ptr;
13061+ entry = NULL;
13062+ }
13063+ mutex_unlock(&ccs_policy_lock);
13064+out:
13065+ kfree(entry);
13066+ return ptr;
13067+}
13068+
13069+/**
13070+ * ccs_check_profile - Check all profiles currently assigned to domains are defined.
13071+ *
13072+ * Returns nothing.
13073+ */
13074+static void ccs_check_profile(void)
13075+{
13076+ struct ccs_domain_info *domain;
13077+ const int idx = ccs_read_lock();
13078+ ccs_policy_loaded = true;
13079+ printk(KERN_INFO "CCSecurity: 1.8.4 2015/05/05\n");
13080+ list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
13081+ const u8 profile = domain->profile;
13082+ struct ccs_policy_namespace *ns = domain->ns;
13083+ if (ns->profile_version == 20100903) {
13084+ static bool done;
13085+ if (!done)
13086+ printk(KERN_INFO "Converting profile version "
13087+ "from %u to %u.\n", 20100903, 20150505);
13088+ done = true;
13089+ ns->profile_version = 20150505;
13090+ }
13091+ if (ns->profile_version != 20150505)
13092+ printk(KERN_ERR
13093+ "Profile version %u is not supported.\n",
13094+ ns->profile_version);
13095+ else if (!ns->profile_ptr[profile])
13096+ printk(KERN_ERR
13097+ "Profile %u (used by '%s') is not defined.\n",
13098+ profile, domain->domainname->name);
13099+ else
13100+ continue;
13101+ printk(KERN_ERR
13102+ "Userland tools for TOMOYO 1.8 must be installed and "
13103+ "policy must be initialized.\n");
13104+ printk(KERN_ERR "Please see http://tomoyo.osdn.jp/1.8/ "
13105+ "for more information.\n");
13106+ panic("STOP!");
13107+ }
13108+ ccs_read_unlock(idx);
13109+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY)
13110+ ccsecurity_exports.add_hooks();
13111+#endif
13112+ printk(KERN_INFO "Mandatory Access Control activated.\n");
13113+}
13114+
13115+/**
13116+ * ccs_profile - Find a profile.
13117+ *
13118+ * @profile: Profile number to find.
13119+ *
13120+ * Returns pointer to "struct ccs_profile".
13121+ */
13122+static struct ccs_profile *ccs_profile(const u8 profile)
13123+{
13124+ static struct ccs_profile ccs_null_profile;
13125+ struct ccs_profile *ptr = ccs_current_namespace()->
13126+ profile_ptr[profile];
13127+ if (!ptr)
13128+ ptr = &ccs_null_profile;
13129+ return ptr;
13130+}
13131+
13132+/**
13133+ * ccs_get_config - Get config for specified profile's specified functionality.
13134+ *
13135+ * @profile: Profile number.
13136+ * @index: Index number of functionality.
13137+ *
13138+ * Returns config.
13139+ *
13140+ * First, check for CONFIG::category::functionality.
13141+ * If CONFIG::category::functionality is set to use default, then check
13142+ * CONFIG::category. If CONFIG::category is set to use default, then use
13143+ * CONFIG. CONFIG cannot be set to use default.
13144+ */
13145+u8 ccs_get_config(const u8 profile, const u8 index)
13146+{
13147+ u8 config;
13148+ const struct ccs_profile *p;
13149+ if (!ccs_policy_loaded)
13150+ return CCS_CONFIG_DISABLED;
13151+ p = ccs_profile(profile);
13152+ config = p->config[index];
13153+ if (config == CCS_CONFIG_USE_DEFAULT)
13154+ config = p->config[ccs_index2category[index]
13155+ + CCS_MAX_MAC_INDEX];
13156+ if (config == CCS_CONFIG_USE_DEFAULT)
13157+ config = p->default_config;
13158+ return config;
13159+}
13160+
13161+/**
13162+ * ccs_find_yesno - Find values for specified keyword.
13163+ *
13164+ * @string: String to check.
13165+ * @find: Name of keyword.
13166+ *
13167+ * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
13168+ */
13169+static s8 ccs_find_yesno(const char *string, const char *find)
13170+{
13171+ const char *cp = strstr(string, find);
13172+ if (cp) {
13173+ cp += strlen(find);
13174+ if (!strncmp(cp, "=yes", 4))
13175+ return 1;
13176+ else if (!strncmp(cp, "=no", 3))
13177+ return 0;
13178+ }
13179+ return -1;
13180+}
13181+
13182+/**
13183+ * ccs_set_uint - Set value for specified preference.
13184+ *
13185+ * @i: Pointer to "unsigned int".
13186+ * @string: String to check.
13187+ * @find: Name of keyword.
13188+ *
13189+ * Returns nothing.
13190+ */
13191+static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
13192+{
13193+ const char *cp = strstr(string, find);
13194+ if (cp)
13195+ sscanf(cp + strlen(find), "=%u", i);
13196+}
13197+
13198+/**
13199+ * ccs_str_starts - Check whether the given string starts with the given keyword.
13200+ *
13201+ * @src: Pointer to pointer to the string.
13202+ * @find: Pointer to the keyword.
13203+ *
13204+ * Returns true if @src starts with @find, false otherwise.
13205+ *
13206+ * The @src is updated to point the first character after the @find
13207+ * if @src starts with @find.
13208+ */
13209+static bool ccs_str_starts(char **src, const char *find)
13210+{
13211+ const int len = strlen(find);
13212+ char *tmp = *src;
13213+ if (strncmp(tmp, find, len))
13214+ return false;
13215+ tmp += len;
13216+ *src = tmp;
13217+ return true;
13218+}
13219+
13220+/**
13221+ * ccs_print_group - Print group's name.
13222+ *
13223+ * @head: Pointer to "struct ccs_io_buffer".
13224+ * @group: Pointer to "struct ccsgroup". Maybe NULL.
13225+ *
13226+ * Returns true if @group is not NULL. false otherwise.
13227+ */
13228+static bool ccs_print_group(struct ccs_io_buffer *head,
13229+ const struct ccs_group *group)
13230+{
13231+ if (group) {
13232+ ccs_set_string(head, "@");
13233+ ccs_set_string(head, group->group_name->name);
13234+ return true;
13235+ }
13236+ return false;
13237+}
13238+
13239+/**
13240+ * ccs_set_mode - Set mode for specified profile.
13241+ *
13242+ * @name: Name of functionality.
13243+ * @value: Mode for @name.
13244+ * @profile: Pointer to "struct ccs_profile".
13245+ *
13246+ * Returns 0 on success, negative value otherwise.
13247+ */
13248+static int ccs_set_mode(char *name, const char *value,
13249+ struct ccs_profile *profile)
13250+{
13251+ u8 i;
13252+ u8 config;
13253+ if (!strcmp(name, "CONFIG")) {
13254+ i = CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
13255+ config = profile->default_config;
13256+ } else if (ccs_str_starts(&name, "CONFIG::")) {
13257+ config = 0;
13258+ for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
13259+ i++) {
13260+ int len = 0;
13261+ if (i < CCS_MAX_MAC_INDEX) {
13262+ const u8 c = ccs_index2category[i];
13263+ const char *category =
13264+ ccs_category_keywords[c];
13265+ len = strlen(category);
13266+ if (strncmp(name, category, len) ||
13267+ name[len++] != ':' || name[len++] != ':')
13268+ continue;
13269+ }
13270+ if (strcmp(name + len, ccs_mac_keywords[i]))
13271+ continue;
13272+ config = profile->config[i];
13273+ break;
13274+ }
13275+ if (i == CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
13276+ return -EINVAL;
13277+ } else {
13278+ return -EINVAL;
13279+ }
13280+ if (strstr(value, "use_default")) {
13281+ config = CCS_CONFIG_USE_DEFAULT;
13282+ } else {
13283+ u8 mode;
13284+ for (mode = 0; mode < CCS_CONFIG_MAX_MODE; mode++)
13285+ if (strstr(value, ccs_mode[mode]))
13286+ /*
13287+ * Update lower 3 bits in order to distinguish
13288+ * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
13289+ */
13290+ config = (config & ~7) | mode;
13291+ if (config != CCS_CONFIG_USE_DEFAULT) {
13292+ switch (ccs_find_yesno(value, "grant_log")) {
13293+ case 1:
13294+ config |= CCS_CONFIG_WANT_GRANT_LOG;
13295+ break;
13296+ case 0:
13297+ config &= ~CCS_CONFIG_WANT_GRANT_LOG;
13298+ break;
13299+ }
13300+ switch (ccs_find_yesno(value, "reject_log")) {
13301+ case 1:
13302+ config |= CCS_CONFIG_WANT_REJECT_LOG;
13303+ break;
13304+ case 0:
13305+ config &= ~CCS_CONFIG_WANT_REJECT_LOG;
13306+ break;
13307+ }
13308+ }
13309+ }
13310+ if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
13311+ profile->config[i] = config;
13312+ else if (config != CCS_CONFIG_USE_DEFAULT)
13313+ profile->default_config = config;
13314+ return 0;
13315+}
13316+
13317+/**
13318+ * ccs_write_profile - Write profile table.
13319+ *
13320+ * @head: Pointer to "struct ccs_io_buffer".
13321+ *
13322+ * Returns 0 on success, negative value otherwise.
13323+ */
13324+static int ccs_write_profile(struct ccs_io_buffer *head)
13325+{
13326+ char *data = head->write_buf;
13327+ unsigned int i;
13328+ char *cp;
13329+ struct ccs_profile *profile;
13330+ if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
13331+ == 1)
13332+ return 0;
13333+ i = simple_strtoul(data, &cp, 10);
13334+ if (*cp != '-')
13335+ return -EINVAL;
13336+ data = cp + 1;
13337+ profile = ccs_assign_profile(head->w.ns, i);
13338+ if (!profile)
13339+ return -EINVAL;
13340+ cp = strchr(data, '=');
13341+ if (!cp)
13342+ return -EINVAL;
13343+ *cp++ = '\0';
13344+ if (!strcmp(data, "COMMENT")) {
13345+ static DEFINE_SPINLOCK(lock);
13346+ const struct ccs_path_info *new_comment = ccs_get_name(cp);
13347+ const struct ccs_path_info *old_comment;
13348+ if (!new_comment)
13349+ return -ENOMEM;
13350+ spin_lock(&lock);
13351+ old_comment = profile->comment;
13352+ profile->comment = new_comment;
13353+ spin_unlock(&lock);
13354+ ccs_put_name(old_comment);
13355+ return 0;
13356+ }
13357+ if (!strcmp(data, "PREFERENCE")) {
13358+ for (i = 0; i < CCS_MAX_PREF; i++)
13359+ ccs_set_uint(&profile->pref[i], cp,
13360+ ccs_pref_keywords[i]);
13361+ return 0;
13362+ }
13363+ return ccs_set_mode(data, cp, profile);
13364+}
13365+
13366+/**
13367+ * ccs_print_config - Print mode for specified functionality.
13368+ *
13369+ * @head: Pointer to "struct ccs_io_buffer".
13370+ * @config: Mode for that functionality.
13371+ *
13372+ * Returns nothing.
13373+ *
13374+ * Caller prints functionality's name.
13375+ */
13376+static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)
13377+{
13378+ ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
13379+ ccs_mode[config & 3],
13380+ ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),
13381+ ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));
13382+}
13383+
13384+/**
13385+ * ccs_read_profile - Read profile table.
13386+ *
13387+ * @head: Pointer to "struct ccs_io_buffer".
13388+ *
13389+ * Returns nothing.
13390+ */
13391+static void ccs_read_profile(struct ccs_io_buffer *head)
13392+{
13393+ u8 index;
13394+ struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
13395+ namespace_list);
13396+ const struct ccs_profile *profile;
13397+ if (head->r.eof)
13398+ return;
13399+next:
13400+ index = head->r.index;
13401+ profile = ns->profile_ptr[index];
13402+ switch (head->r.step) {
13403+ case 0:
13404+ ccs_print_namespace(head);
13405+ ccs_io_printf(head, "PROFILE_VERSION=%u\n",
13406+ ns->profile_version);
13407+ head->r.step++;
13408+ break;
13409+ case 1:
13410+ for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++)
13411+ if (ns->profile_ptr[head->r.index])
13412+ break;
13413+ if (head->r.index == CCS_MAX_PROFILES) {
13414+ head->r.eof = true;
13415+ return;
13416+ }
13417+ head->r.step++;
13418+ break;
13419+ case 2:
13420+ {
13421+ u8 i;
13422+ const struct ccs_path_info *comment = profile->comment;
13423+ ccs_print_namespace(head);
13424+ ccs_io_printf(head, "%u-COMMENT=", index);
13425+ ccs_set_string(head, comment ? comment->name : "");
13426+ ccs_set_lf(head);
13427+ ccs_print_namespace(head);
13428+ ccs_io_printf(head, "%u-PREFERENCE={ ", index);
13429+ for (i = 0; i < CCS_MAX_PREF; i++)
13430+ ccs_io_printf(head, "%s=%u ",
13431+ ccs_pref_keywords[i],
13432+ profile->pref[i]);
13433+ ccs_set_string(head, "}\n");
13434+ head->r.step++;
13435+ }
13436+ break;
13437+ case 3:
13438+ {
13439+ ccs_print_namespace(head);
13440+ ccs_io_printf(head, "%u-%s", index, "CONFIG");
13441+ ccs_print_config(head, profile->default_config);
13442+ head->r.bit = 0;
13443+ head->r.step++;
13444+ }
13445+ break;
13446+ case 4:
13447+ for ( ; head->r.bit < CCS_MAX_MAC_INDEX
13448+ + CCS_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {
13449+ const u8 i = head->r.bit;
13450+ const u8 config = profile->config[i];
13451+ if (config == CCS_CONFIG_USE_DEFAULT)
13452+ continue;
13453+ ccs_print_namespace(head);
13454+ if (i < CCS_MAX_MAC_INDEX)
13455+ ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
13456+ ccs_category_keywords
13457+ [ccs_index2category[i]],
13458+ ccs_mac_keywords[i]);
13459+ else
13460+ ccs_io_printf(head, "%u-CONFIG::%s", index,
13461+ ccs_mac_keywords[i]);
13462+ ccs_print_config(head, config);
13463+ head->r.bit++;
13464+ break;
13465+ }
13466+ if (head->r.bit == CCS_MAX_MAC_INDEX
13467+ + CCS_MAX_MAC_CATEGORY_INDEX) {
13468+ head->r.index++;
13469+ head->r.step = 1;
13470+ }
13471+ break;
13472+ }
13473+ if (ccs_flush(head))
13474+ goto next;
13475+}
13476+
13477+/**
13478+ * ccs_update_policy - Update an entry for exception policy.
13479+ *
13480+ * @size: Size of new entry in bytes.
13481+ * @param: Pointer to "struct ccs_acl_param".
13482+ *
13483+ * Returns 0 on success, negative value otherwise.
13484+ *
13485+ * Caller holds ccs_read_lock().
13486+ */
13487+static int ccs_update_policy(const int size, struct ccs_acl_param *param)
13488+{
13489+ struct ccs_acl_head *new_entry = &param->e.acl_head;
13490+ int error = param->is_delete ? -ENOENT : -ENOMEM;
13491+ struct ccs_acl_head *entry;
13492+ struct list_head *list = param->list;
13493+ BUG_ON(size < sizeof(*entry));
13494+ if (mutex_lock_interruptible(&ccs_policy_lock))
13495+ return -ENOMEM;
13496+ list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
13497+ if (entry->is_deleted == CCS_GC_IN_PROGRESS)
13498+ continue;
13499+ if (memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
13500+ continue;
13501+ entry->is_deleted = param->is_delete;
13502+ error = 0;
13503+ break;
13504+ }
13505+ if (error && !param->is_delete) {
13506+ entry = ccs_commit_ok(new_entry, size);
13507+ if (entry) {
13508+ list_add_tail_rcu(&entry->list, list);
13509+ error = 0;
13510+ }
13511+ }
13512+ mutex_unlock(&ccs_policy_lock);
13513+ return error;
13514+}
13515+
13516+/**
13517+ * ccs_update_manager_entry - Add a manager entry.
13518+ *
13519+ * @manager: The path to manager or the domainnamme.
13520+ * @is_delete: True if it is a delete request.
13521+ *
13522+ * Returns 0 on success, negative value otherwise.
13523+ */
13524+static int ccs_update_manager_entry(const char *manager,
13525+ const bool is_delete)
13526+{
13527+ struct ccs_acl_param param = {
13528+ /* .ns = &ccs_kernel_namespace, */
13529+ .is_delete = is_delete,
13530+ .list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER],
13531+ };
13532+ struct ccs_manager *e = &param.e.manager;
13533+ int error = is_delete ? -ENOENT : -ENOMEM;
13534+ /* Forced zero clear for using memcmp() at ccs_update_policy(). */
13535+ memset(&param.e, 0, sizeof(param.e));
13536+ if (!ccs_correct_domain(manager) && !ccs_correct_word(manager))
13537+ return -EINVAL;
13538+ e->manager = ccs_get_name(manager);
13539+ if (e->manager) {
13540+ error = ccs_update_policy(sizeof(*e), &param);
13541+ ccs_put_name(e->manager);
13542+ }
13543+ return error;
13544+}
13545+
13546+/**
13547+ * ccs_write_manager - Write manager policy.
13548+ *
13549+ * @head: Pointer to "struct ccs_io_buffer".
13550+ *
13551+ * Returns 0 on success, negative value otherwise.
13552+ */
13553+static int ccs_write_manager(struct ccs_io_buffer *head)
13554+{
13555+ const char *data = head->write_buf;
13556+ if (!strcmp(data, "manage_by_non_root")) {
13557+ ccs_manage_by_non_root = !head->w.is_delete;
13558+ return 0;
13559+ }
13560+ return ccs_update_manager_entry(data, head->w.is_delete);
13561+}
13562+
13563+/**
13564+ * ccs_read_manager - Read manager policy.
13565+ *
13566+ * @head: Pointer to "struct ccs_io_buffer".
13567+ *
13568+ * Returns nothing.
13569+ *
13570+ * Caller holds ccs_read_lock().
13571+ */
13572+static void ccs_read_manager(struct ccs_io_buffer *head)
13573+{
13574+ if (head->r.eof)
13575+ return;
13576+ list_for_each_cookie(head->r.acl, &ccs_kernel_namespace.
13577+ policy_list[CCS_ID_MANAGER]) {
13578+ struct ccs_manager *ptr =
13579+ list_entry(head->r.acl, typeof(*ptr), head.list);
13580+ if (ptr->head.is_deleted)
13581+ continue;
13582+ if (!ccs_flush(head))
13583+ return;
13584+ ccs_set_string(head, ptr->manager->name);
13585+ ccs_set_lf(head);
13586+ }
13587+ head->r.eof = true;
13588+}
13589+
13590+/**
13591+ * ccs_manager - Check whether the current process is a policy manager.
13592+ *
13593+ * Returns true if the current process is permitted to modify policy
13594+ * via /proc/ccs/ interface.
13595+ *
13596+ * Caller holds ccs_read_lock().
13597+ */
13598+static bool ccs_manager(void)
13599+{
13600+ struct ccs_manager *ptr;
13601+ struct ccs_path_info exe;
13602+ struct ccs_security *task = ccs_current_security();
13603+ const struct ccs_path_info *domainname
13604+ = ccs_current_domain()->domainname;
13605+ bool found = false;
13606+ if (!ccs_policy_loaded)
13607+ return true;
13608+ if (task->ccs_flags & CCS_TASK_IS_MANAGER)
13609+ return true;
13610+ if (!ccs_manage_by_non_root &&
13611+ (!uid_eq(current_uid(), GLOBAL_ROOT_UID) ||
13612+ !uid_eq(current_euid(), GLOBAL_ROOT_UID)))
13613+ return false;
13614+ exe.name = ccs_get_exe();
13615+ if (!exe.name)
13616+ return false;
13617+ ccs_fill_path_info(&exe);
13618+ list_for_each_entry_srcu(ptr, &ccs_kernel_namespace.
13619+ policy_list[CCS_ID_MANAGER], head.list,
13620+ &ccs_ss) {
13621+ if (ptr->head.is_deleted)
13622+ continue;
13623+ if (ccs_pathcmp(domainname, ptr->manager) &&
13624+ ccs_pathcmp(&exe, ptr->manager))
13625+ continue;
13626+ /* Set manager flag. */
13627+ task->ccs_flags |= CCS_TASK_IS_MANAGER;
13628+ found = true;
13629+ break;
13630+ }
13631+ if (!found) { /* Reduce error messages. */
13632+ static pid_t ccs_last_pid;
13633+ const pid_t pid = current->pid;
13634+ if (ccs_last_pid != pid) {
13635+ printk(KERN_WARNING "%s ( %s ) is not permitted to "
13636+ "update policies.\n", domainname->name,
13637+ exe.name);
13638+ ccs_last_pid = pid;
13639+ }
13640+ }
13641+ kfree(exe.name);
13642+ return found;
13643+}
13644+
13645+/**
13646+ * ccs_find_domain - Find a domain by the given name.
13647+ *
13648+ * @domainname: The domainname to find.
13649+ *
13650+ * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
13651+ *
13652+ * Caller holds ccs_read_lock().
13653+ */
13654+static struct ccs_domain_info *ccs_find_domain(const char *domainname)
13655+{
13656+ struct ccs_domain_info *domain;
13657+ struct ccs_path_info name;
13658+ name.name = domainname;
13659+ ccs_fill_path_info(&name);
13660+ list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
13661+ if (!domain->is_deleted &&
13662+ !ccs_pathcmp(&name, domain->domainname))
13663+ return domain;
13664+ }
13665+ return NULL;
13666+}
13667+
13668+/**
13669+ * ccs_select_domain - Parse select command.
13670+ *
13671+ * @head: Pointer to "struct ccs_io_buffer".
13672+ * @data: String to parse.
13673+ *
13674+ * Returns true on success, false otherwise.
13675+ *
13676+ * Caller holds ccs_read_lock().
13677+ */
13678+static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data)
13679+{
13680+ unsigned int pid;
13681+ struct ccs_domain_info *domain = NULL;
13682+ bool global_pid = false;
13683+ if (strncmp(data, "select ", 7))
13684+ return false;
13685+ data += 7;
13686+ if (sscanf(data, "pid=%u", &pid) == 1 ||
13687+ (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
13688+ struct task_struct *p;
13689+ ccs_tasklist_lock();
13690+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
13691+ if (global_pid)
13692+ p = ccsecurity_exports.find_task_by_pid_ns(pid,
13693+ &init_pid_ns);
13694+ else
13695+ p = ccsecurity_exports.find_task_by_vpid(pid);
13696+#else
13697+ p = find_task_by_pid(pid);
13698+#endif
13699+ if (p)
13700+ domain = ccs_task_domain(p);
13701+ ccs_tasklist_unlock();
13702+ } else if (!strncmp(data, "domain=", 7)) {
13703+ if (*(data + 7) == '<')
13704+ domain = ccs_find_domain(data + 7);
13705+ } else if (sscanf(data, "Q=%u", &pid) == 1) {
13706+ domain = ccs_find_domain_by_qid(pid);
13707+ } else
13708+ return false;
13709+ head->w.domain = domain;
13710+ /* Accessing read_buf is safe because head->io_sem is held. */
13711+ if (!head->read_buf)
13712+ return true; /* Do nothing if open(O_WRONLY). */
13713+ memset(&head->r, 0, sizeof(head->r));
13714+ head->r.print_this_domain_only = true;
13715+ if (domain)
13716+ head->r.domain = &domain->list;
13717+ else
13718+ head->r.eof = true;
13719+ ccs_io_printf(head, "# select %s\n", data);
13720+ if (domain && domain->is_deleted)
13721+ ccs_set_string(head, "# This is a deleted domain.\n");
13722+ return true;
13723+}
13724+
13725+/**
13726+ * ccs_update_acl - Update "struct ccs_acl_info" entry.
13727+ *
13728+ * @size: Size of new entry in bytes.
13729+ * @param: Pointer to "struct ccs_acl_param".
13730+ *
13731+ * Returns 0 on success, negative value otherwise.
13732+ *
13733+ * Caller holds ccs_read_lock().
13734+ */
13735+static int ccs_update_acl(const int size, struct ccs_acl_param *param)
13736+{
13737+ struct ccs_acl_info *new_entry = &param->e.acl_info;
13738+ const bool is_delete = param->is_delete;
13739+ int error = is_delete ? -ENOENT : -ENOMEM;
13740+ struct ccs_acl_info *entry;
13741+ struct list_head * const list = param->list;
13742+ BUG_ON(size < sizeof(*entry));
13743+ if (param->data[0]) {
13744+ new_entry->cond = ccs_get_condition(param);
13745+ if (!new_entry->cond)
13746+ return -EINVAL;
13747+ /*
13748+ * Domain transition preference is allowed for only
13749+ * "file execute"/"task auto_execute_handler"/
13750+ * "task denied_auto_execute_handler" entries.
13751+ */
13752+ if (new_entry->cond->exec_transit &&
13753+ !(new_entry->type == CCS_TYPE_PATH_ACL &&
13754+ new_entry->perm == 1 << CCS_TYPE_EXECUTE)
13755+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
13756+ && new_entry->type != CCS_TYPE_AUTO_EXECUTE_HANDLER &&
13757+ new_entry->type != CCS_TYPE_DENIED_EXECUTE_HANDLER
13758+#endif
13759+ )
13760+ return -EINVAL;
13761+ }
13762+ if (mutex_lock_interruptible(&ccs_policy_lock))
13763+ return -ENOMEM;
13764+ list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
13765+ if (entry->is_deleted == CCS_GC_IN_PROGRESS)
13766+ continue;
13767+ if (entry->type != new_entry->type ||
13768+ entry->cond != new_entry->cond ||
13769+ memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
13770+ continue;
13771+ if (is_delete)
13772+ entry->perm &= ~new_entry->perm;
13773+ else
13774+ entry->perm |= new_entry->perm;
13775+ entry->is_deleted = !entry->perm;
13776+ error = 0;
13777+ break;
13778+ }
13779+ if (error && !is_delete) {
13780+ entry = ccs_commit_ok(new_entry, size);
13781+ if (entry) {
13782+ list_add_tail_rcu(&entry->list, list);
13783+ error = 0;
13784+ }
13785+ }
13786+ mutex_unlock(&ccs_policy_lock);
13787+ return error;
13788+}
13789+
13790+/**
13791+ * ccs_permstr - Find permission keywords.
13792+ *
13793+ * @string: String representation for permissions in foo/bar/buz format.
13794+ * @keyword: Keyword to find from @string/
13795+ *
13796+ * Returns ture if @keyword was found in @string, false otherwise.
13797+ *
13798+ * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
13799+ */
13800+static bool ccs_permstr(const char *string, const char *keyword)
13801+{
13802+ const char *cp = strstr(string, keyword);
13803+ if (cp)
13804+ return cp == string || *(cp - 1) == '/';
13805+ return false;
13806+}
13807+
13808+/**
13809+ * ccs_write_task - Update task related list.
13810+ *
13811+ * @param: Pointer to "struct ccs_acl_param".
13812+ *
13813+ * Returns 0 on success, negative value otherwise.
13814+ *
13815+ * Caller holds ccs_read_lock().
13816+ */
13817+static int ccs_write_task(struct ccs_acl_param *param)
13818+{
13819+ int error;
13820+ const bool is_auto = ccs_str_starts(&param->data,
13821+ "auto_domain_transition ");
13822+ if (!is_auto && !ccs_str_starts(&param->data,
13823+ "manual_domain_transition ")) {
13824+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
13825+ struct ccs_handler_acl *e = &param->e.handler_acl;
13826+ char *handler;
13827+ if (ccs_str_starts(&param->data, "auto_execute_handler "))
13828+ e->head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER;
13829+ else if (ccs_str_starts(&param->data,
13830+ "denied_execute_handler "))
13831+ e->head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER;
13832+ else
13833+ return -EINVAL;
13834+ handler = ccs_read_token(param);
13835+ if (!ccs_correct_path(handler))
13836+ return -EINVAL;
13837+ e->handler = ccs_get_name(handler);
13838+ if (!e->handler)
13839+ return -ENOMEM;
13840+ if (e->handler->is_patterned)
13841+ return -EINVAL; /* No patterns allowed. */
13842+ return ccs_update_acl(sizeof(*e), param);
13843+#else
13844+ error = -EINVAL;
13845+#endif
13846+ } else {
13847+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
13848+ struct ccs_task_acl *e = &param->e.task_acl;
13849+ e->head.type = is_auto ?
13850+ CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL;
13851+ e->domainname = ccs_get_domainname(param);
13852+ if (!e->domainname)
13853+ return -EINVAL;
13854+ return ccs_update_acl(sizeof(*e), param);
13855+#else
13856+ error = -EINVAL;
13857+#endif
13858+ }
13859+ return error;
13860+}
13861+
13862+#ifdef CONFIG_CCSECURITY_NETWORK
13863+
13864+/**
13865+ * ccs_write_inet_network - Write "struct ccs_inet_acl" list.
13866+ *
13867+ * @param: Pointer to "struct ccs_acl_param".
13868+ *
13869+ * Returns 0 on success, negative value otherwise.
13870+ *
13871+ * Caller holds ccs_read_lock().
13872+ */
13873+static int ccs_write_inet_network(struct ccs_acl_param *param)
13874+{
13875+ struct ccs_inet_acl *e = &param->e.inet_acl;
13876+ u8 type;
13877+ const char *protocol = ccs_read_token(param);
13878+ const char *operation = ccs_read_token(param);
13879+ e->head.type = CCS_TYPE_INET_ACL;
13880+ for (type = 0; type < CCS_SOCK_MAX; type++)
13881+ if (!strcmp(protocol, ccs_proto_keyword[type]))
13882+ break;
13883+ if (type == CCS_SOCK_MAX)
13884+ return -EINVAL;
13885+ e->protocol = type;
13886+ e->head.perm = 0;
13887+ for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
13888+ if (ccs_permstr(operation, ccs_socket_keyword[type]))
13889+ e->head.perm |= 1 << type;
13890+ if (!e->head.perm)
13891+ return -EINVAL;
13892+ if (param->data[0] == '@') {
13893+ param->data++;
13894+ e->address.group = ccs_get_group(param, CCS_ADDRESS_GROUP);
13895+ if (!e->address.group)
13896+ return -ENOMEM;
13897+ } else {
13898+ if (!ccs_parse_ipaddr_union(param, &e->address))
13899+ return -EINVAL;
13900+ }
13901+ if (!ccs_parse_number_union(param, &e->port) ||
13902+ e->port.values[1] > 65535)
13903+ return -EINVAL;
13904+ return ccs_update_acl(sizeof(*e), param);
13905+}
13906+
13907+/**
13908+ * ccs_write_unix_network - Write "struct ccs_unix_acl" list.
13909+ *
13910+ * @param: Pointer to "struct ccs_acl_param".
13911+ *
13912+ * Returns 0 on success, negative value otherwise.
13913+ */
13914+static int ccs_write_unix_network(struct ccs_acl_param *param)
13915+{
13916+ struct ccs_unix_acl *e = &param->e.unix_acl;
13917+ u8 type;
13918+ const char *protocol = ccs_read_token(param);
13919+ const char *operation = ccs_read_token(param);
13920+ e->head.type = CCS_TYPE_UNIX_ACL;
13921+ for (type = 0; type < CCS_SOCK_MAX; type++)
13922+ if (!strcmp(protocol, ccs_proto_keyword[type]))
13923+ break;
13924+ if (type == CCS_SOCK_MAX)
13925+ return -EINVAL;
13926+ e->protocol = type;
13927+ e->head.perm = 0;
13928+ for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
13929+ if (ccs_permstr(operation, ccs_socket_keyword[type]))
13930+ e->head.perm |= 1 << type;
13931+ if (!e->head.perm)
13932+ return -EINVAL;
13933+ if (!ccs_parse_name_union(param, &e->name))
13934+ return -EINVAL;
13935+ return ccs_update_acl(sizeof(*e), param);
13936+}
13937+
13938+#endif
13939+
13940+/**
13941+ * ccs_write_file - Update file related list.
13942+ *
13943+ * @param: Pointer to "struct ccs_acl_param".
13944+ *
13945+ * Returns 0 on success, negative value otherwise.
13946+ *
13947+ * Caller holds ccs_read_lock().
13948+ */
13949+static int ccs_write_file(struct ccs_acl_param *param)
13950+{
13951+ u16 perm = 0;
13952+ u8 type;
13953+ const char *operation = ccs_read_token(param);
13954+ for (type = 0; type < CCS_MAX_PATH_OPERATION; type++)
13955+ if (ccs_permstr(operation, ccs_path_keyword[type]))
13956+ perm |= 1 << type;
13957+ if (perm) {
13958+ struct ccs_path_acl *e = &param->e.path_acl;
13959+ e->head.type = CCS_TYPE_PATH_ACL;
13960+ e->head.perm = perm;
13961+ if (!ccs_parse_name_union(param, &e->name))
13962+ return -EINVAL;
13963+ return ccs_update_acl(sizeof(*e), param);
13964+ }
13965+ for (type = 0; type < CCS_MAX_PATH2_OPERATION; type++)
13966+ if (ccs_permstr(operation, ccs_mac_keywords[ccs_pp2mac[type]]))
13967+ perm |= 1 << type;
13968+ if (perm) {
13969+ struct ccs_path2_acl *e = &param->e.path2_acl;
13970+ e->head.type = CCS_TYPE_PATH2_ACL;
13971+ e->head.perm = perm;
13972+ if (!ccs_parse_name_union(param, &e->name1) ||
13973+ !ccs_parse_name_union(param, &e->name2))
13974+ return -EINVAL;
13975+ return ccs_update_acl(sizeof(*e), param);
13976+ }
13977+ for (type = 0; type < CCS_MAX_PATH_NUMBER_OPERATION; type++)
13978+ if (ccs_permstr(operation, ccs_mac_keywords[ccs_pn2mac[type]]))
13979+ perm |= 1 << type;
13980+ if (perm) {
13981+ struct ccs_path_number_acl *e = &param->e.path_number_acl;
13982+ e->head.type = CCS_TYPE_PATH_NUMBER_ACL;
13983+ e->head.perm = perm;
13984+ if (!ccs_parse_name_union(param, &e->name) ||
13985+ !ccs_parse_number_union(param, &e->number))
13986+ return -EINVAL;
13987+ return ccs_update_acl(sizeof(*e), param);
13988+ }
13989+ for (type = 0; type < CCS_MAX_MKDEV_OPERATION; type++)
13990+ if (ccs_permstr(operation,
13991+ ccs_mac_keywords[ccs_pnnn2mac[type]]))
13992+ perm |= 1 << type;
13993+ if (perm) {
13994+ struct ccs_mkdev_acl *e = &param->e.mkdev_acl;
13995+ e->head.type = CCS_TYPE_MKDEV_ACL;
13996+ e->head.perm = perm;
13997+ if (!ccs_parse_name_union(param, &e->name) ||
13998+ !ccs_parse_number_union(param, &e->mode) ||
13999+ !ccs_parse_number_union(param, &e->major) ||
14000+ !ccs_parse_number_union(param, &e->minor))
14001+ return -EINVAL;
14002+ return ccs_update_acl(sizeof(*e), param);
14003+ }
14004+ if (ccs_permstr(operation, ccs_mac_keywords[CCS_MAC_FILE_MOUNT])) {
14005+ struct ccs_mount_acl *e = &param->e.mount_acl;
14006+ e->head.type = CCS_TYPE_MOUNT_ACL;
14007+ if (!ccs_parse_name_union(param, &e->dev_name) ||
14008+ !ccs_parse_name_union(param, &e->dir_name) ||
14009+ !ccs_parse_name_union(param, &e->fs_type) ||
14010+ !ccs_parse_number_union(param, &e->flags))
14011+ return -EINVAL;
14012+ return ccs_update_acl(sizeof(*e), param);
14013+ }
14014+ return -EINVAL;
14015+}
14016+
14017+#ifdef CONFIG_CCSECURITY_MISC
14018+
14019+/**
14020+ * ccs_write_misc - Update environment variable list.
14021+ *
14022+ * @param: Pointer to "struct ccs_acl_param".
14023+ *
14024+ * Returns 0 on success, negative value otherwise.
14025+ */
14026+static int ccs_write_misc(struct ccs_acl_param *param)
14027+{
14028+ if (ccs_str_starts(&param->data, "env ")) {
14029+ struct ccs_env_acl *e = &param->e.env_acl;
14030+ const char *data = ccs_read_token(param);
14031+ e->head.type = CCS_TYPE_ENV_ACL;
14032+ if (!ccs_correct_word(data) || strchr(data, '='))
14033+ return -EINVAL;
14034+ e->env = ccs_get_name(data);
14035+ if (!e->env)
14036+ return -ENOMEM;
14037+ return ccs_update_acl(sizeof(*e), param);
14038+ }
14039+ return -EINVAL;
14040+}
14041+
14042+#endif
14043+
14044+#ifdef CONFIG_CCSECURITY_IPC
14045+
14046+/**
14047+ * ccs_write_ipc - Update "struct ccs_signal_acl" list.
14048+ *
14049+ * @param: Pointer to "struct ccs_acl_param".
14050+ *
14051+ * Returns 0 on success, negative value otherwise.
14052+ */
14053+static int ccs_write_ipc(struct ccs_acl_param *param)
14054+{
14055+ struct ccs_signal_acl *e = &param->e.signal_acl;
14056+ e->head.type = CCS_TYPE_SIGNAL_ACL;
14057+ if (!ccs_parse_number_union(param, &e->sig))
14058+ return -EINVAL;
14059+ e->domainname = ccs_get_domainname(param);
14060+ if (!e->domainname)
14061+ return -EINVAL;
14062+ return ccs_update_acl(sizeof(*e), param);
14063+}
14064+
14065+#endif
14066+
14067+#ifdef CONFIG_CCSECURITY_CAPABILITY
14068+
14069+/**
14070+ * ccs_write_capability - Write "struct ccs_capability_acl" list.
14071+ *
14072+ * @param: Pointer to "struct ccs_acl_param".
14073+ *
14074+ * Returns 0 on success, negative value otherwise.
14075+ *
14076+ * Caller holds ccs_read_lock().
14077+ */
14078+static int ccs_write_capability(struct ccs_acl_param *param)
14079+{
14080+ struct ccs_capability_acl *e = &param->e.capability_acl;
14081+ const char *operation = ccs_read_token(param);
14082+ u8 type;
14083+ e->head.type = CCS_TYPE_CAPABILITY_ACL;
14084+ for (type = 0; type < CCS_MAX_CAPABILITY_INDEX; type++) {
14085+ if (strcmp(operation, ccs_mac_keywords[ccs_c2mac[type]]))
14086+ continue;
14087+ e->operation = type;
14088+ return ccs_update_acl(sizeof(*e), param);
14089+ }
14090+ return -EINVAL;
14091+}
14092+
14093+#endif
14094+
14095+/**
14096+ * ccs_write_acl - Write "struct ccs_acl_info" list.
14097+ *
14098+ * @ns: Pointer to "struct ccs_policy_namespace".
14099+ * @list: Pointer to "struct list_head".
14100+ * @data: Policy to be interpreted.
14101+ * @is_delete: True if it is a delete request.
14102+ *
14103+ * Returns 0 on success, negative value otherwise.
14104+ *
14105+ * Caller holds ccs_read_lock().
14106+ */
14107+static int ccs_write_acl(struct ccs_policy_namespace *ns,
14108+ struct list_head *list, char *data,
14109+ const bool is_delete)
14110+{
14111+ struct ccs_acl_param param = {
14112+ .ns = ns,
14113+ .list = list,
14114+ .data = data,
14115+ .is_delete = is_delete,
14116+ };
14117+ static const struct {
14118+ const char *keyword;
14119+ int (*write) (struct ccs_acl_param *);
14120+ } ccs_callback[] = {
14121+ { "file ", ccs_write_file },
14122+#ifdef CONFIG_CCSECURITY_NETWORK
14123+ { "network inet ", ccs_write_inet_network },
14124+ { "network unix ", ccs_write_unix_network },
14125+#endif
14126+#ifdef CONFIG_CCSECURITY_MISC
14127+ { "misc ", ccs_write_misc },
14128+#endif
14129+#ifdef CONFIG_CCSECURITY_CAPABILITY
14130+ { "capability ", ccs_write_capability },
14131+#endif
14132+#ifdef CONFIG_CCSECURITY_IPC
14133+ { "ipc signal ", ccs_write_ipc },
14134+#endif
14135+ { "task ", ccs_write_task },
14136+ };
14137+ u8 i;
14138+ /* Forced zero clear for using memcmp() at ccs_update_acl(). */
14139+ memset(&param.e, 0, sizeof(param.e));
14140+ param.e.acl_info.perm = 1;
14141+ for (i = 0; i < ARRAY_SIZE(ccs_callback); i++) {
14142+ int error;
14143+ if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))
14144+ continue;
14145+ error = ccs_callback[i].write(&param);
14146+ ccs_del_acl(&param.e.acl_info.list);
14147+ return error;
14148+ }
14149+ return -EINVAL;
14150+}
14151+
14152+/**
14153+ * ccs_delete_domain - Delete a domain.
14154+ *
14155+ * @domainname: The name of domain.
14156+ *
14157+ * Returns 0.
14158+ */
14159+static int ccs_delete_domain(char *domainname)
14160+{
14161+ struct ccs_domain_info *domain;
14162+ struct ccs_path_info name;
14163+ name.name = domainname;
14164+ ccs_fill_path_info(&name);
14165+ if (mutex_lock_interruptible(&ccs_policy_lock))
14166+ return 0;
14167+ /* Is there an active domain? */
14168+ list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
14169+ /* Never delete ccs_kernel_domain. */
14170+ if (domain == &ccs_kernel_domain)
14171+ continue;
14172+ if (domain->is_deleted ||
14173+ ccs_pathcmp(domain->domainname, &name))
14174+ continue;
14175+ domain->is_deleted = true;
14176+ break;
14177+ }
14178+ mutex_unlock(&ccs_policy_lock);
14179+ return 0;
14180+}
14181+
14182+/**
14183+ * ccs_write_domain - Write domain policy.
14184+ *
14185+ * @head: Pointer to "struct ccs_io_buffer".
14186+ *
14187+ * Returns 0 on success, negative value otherwise.
14188+ *
14189+ * Caller holds ccs_read_lock().
14190+ */
14191+static int ccs_write_domain(struct ccs_io_buffer *head)
14192+{
14193+ char *data = head->write_buf;
14194+ struct ccs_policy_namespace *ns;
14195+ struct ccs_domain_info *domain = head->w.domain;
14196+ const bool is_delete = head->w.is_delete;
14197+ const bool is_select = !is_delete && ccs_str_starts(&data, "select ");
14198+ unsigned int idx;
14199+ if (*data == '<') {
14200+ domain = NULL;
14201+ if (is_delete)
14202+ ccs_delete_domain(data);
14203+ else if (is_select)
14204+ domain = ccs_find_domain(data);
14205+ else
14206+ domain = ccs_assign_domain(data, false);
14207+ head->w.domain = domain;
14208+ return 0;
14209+ }
14210+ if (!domain)
14211+ return -EINVAL;
14212+ ns = domain->ns;
14213+ if (sscanf(data, "use_profile %u\n", &idx) == 1 &&
14214+ idx < CCS_MAX_PROFILES) {
14215+ if (!ccs_policy_loaded || ns->profile_ptr[(u8) idx])
14216+ if (!is_delete)
14217+ domain->profile = (u8) idx;
14218+ return 0;
14219+ }
14220+ if (sscanf(data, "use_group %u\n", &idx) == 1 &&
14221+ idx < CCS_MAX_ACL_GROUPS) {
14222+ if (!is_delete)
14223+ set_bit(idx, domain->group);
14224+ else
14225+ clear_bit(idx, domain->group);
14226+ return 0;
14227+ }
14228+ for (idx = 0; idx < CCS_MAX_DOMAIN_INFO_FLAGS; idx++) {
14229+ const char *cp = ccs_dif[idx];
14230+ if (strncmp(data, cp, strlen(cp) - 1))
14231+ continue;
14232+ domain->flags[idx] = !is_delete;
14233+ return 0;
14234+ }
14235+ return ccs_write_acl(ns, &domain->acl_info_list, data, is_delete);
14236+}
14237+
14238+/**
14239+ * ccs_print_name_union - Print a ccs_name_union.
14240+ *
14241+ * @head: Pointer to "struct ccs_io_buffer".
14242+ * @ptr: Pointer to "struct ccs_name_union".
14243+ *
14244+ * Returns nothing.
14245+ */
14246+static void ccs_print_name_union(struct ccs_io_buffer *head,
14247+ const struct ccs_name_union *ptr)
14248+{
14249+ ccs_set_space(head);
14250+ if (!ccs_print_group(head, ptr->group))
14251+ ccs_set_string(head, ptr->filename->name);
14252+}
14253+
14254+/**
14255+ * ccs_print_name_union_quoted - Print a ccs_name_union with a quote.
14256+ *
14257+ * @head: Pointer to "struct ccs_io_buffer".
14258+ * @ptr: Pointer to "struct ccs_name_union".
14259+ *
14260+ * Returns nothing.
14261+ */
14262+static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
14263+ const struct ccs_name_union *ptr)
14264+{
14265+ if (!ccs_print_group(head, ptr->group)) {
14266+ ccs_set_string(head, "\"");
14267+ ccs_set_string(head, ptr->filename->name);
14268+ ccs_set_string(head, "\"");
14269+ }
14270+}
14271+
14272+/**
14273+ * ccs_print_number_union_nospace - Print a ccs_number_union without a space.
14274+ *
14275+ * @head: Pointer to "struct ccs_io_buffer".
14276+ * @ptr: Pointer to "struct ccs_number_union".
14277+ *
14278+ * Returns nothing.
14279+ */
14280+static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
14281+ const struct ccs_number_union *ptr)
14282+{
14283+ if (!ccs_print_group(head, ptr->group)) {
14284+ int i;
14285+ unsigned long min = ptr->values[0];
14286+ const unsigned long max = ptr->values[1];
14287+ u8 min_type = ptr->value_type[0];
14288+ const u8 max_type = ptr->value_type[1];
14289+ char buffer[128];
14290+ buffer[0] = '\0';
14291+ for (i = 0; i < 2; i++) {
14292+ switch (min_type) {
14293+ case CCS_VALUE_TYPE_HEXADECIMAL:
14294+ ccs_addprintf(buffer, sizeof(buffer), "0x%lX",
14295+ min);
14296+ break;
14297+ case CCS_VALUE_TYPE_OCTAL:
14298+ ccs_addprintf(buffer, sizeof(buffer), "0%lo",
14299+ min);
14300+ break;
14301+ default:
14302+ ccs_addprintf(buffer, sizeof(buffer), "%lu",
14303+ min);
14304+ break;
14305+ }
14306+ if (min == max && min_type == max_type)
14307+ break;
14308+ ccs_addprintf(buffer, sizeof(buffer), "-");
14309+ min_type = max_type;
14310+ min = max;
14311+ }
14312+ ccs_io_printf(head, "%s", buffer);
14313+ }
14314+}
14315+
14316+/**
14317+ * ccs_print_number_union - Print a ccs_number_union.
14318+ *
14319+ * @head: Pointer to "struct ccs_io_buffer".
14320+ * @ptr: Pointer to "struct ccs_number_union".
14321+ *
14322+ * Returns nothing.
14323+ */
14324+static void ccs_print_number_union(struct ccs_io_buffer *head,
14325+ const struct ccs_number_union *ptr)
14326+{
14327+ ccs_set_space(head);
14328+ ccs_print_number_union_nospace(head, ptr);
14329+}
14330+
14331+/**
14332+ * ccs_print_condition - Print condition part.
14333+ *
14334+ * @head: Pointer to "struct ccs_io_buffer".
14335+ * @cond: Pointer to "struct ccs_condition".
14336+ *
14337+ * Returns true on success, false otherwise.
14338+ */
14339+static bool ccs_print_condition(struct ccs_io_buffer *head,
14340+ const struct ccs_condition *cond)
14341+{
14342+ switch (head->r.cond_step) {
14343+ case 0:
14344+ head->r.cond_index = 0;
14345+ head->r.cond_step++;
14346+ if (cond->transit && cond->exec_transit) {
14347+ ccs_set_space(head);
14348+ ccs_set_string(head, cond->transit->name);
14349+ }
14350+ /* fall through */
14351+ case 1:
14352+ {
14353+ const u16 condc = cond->condc;
14354+ const struct ccs_condition_element *condp =
14355+ (typeof(condp)) (cond + 1);
14356+ const struct ccs_number_union *numbers_p =
14357+ (typeof(numbers_p)) (condp + condc);
14358+ const struct ccs_name_union *names_p =
14359+ (typeof(names_p))
14360+ (numbers_p + cond->numbers_count);
14361+ const struct ccs_argv *argv =
14362+ (typeof(argv)) (names_p + cond->names_count);
14363+ const struct ccs_envp *envp =
14364+ (typeof(envp)) (argv + cond->argc);
14365+ u16 skip;
14366+ for (skip = 0; skip < head->r.cond_index; skip++) {
14367+ const u8 left = condp->left;
14368+ const u8 right = condp->right;
14369+ condp++;
14370+ switch (left) {
14371+ case CCS_ARGV_ENTRY:
14372+ argv++;
14373+ continue;
14374+ case CCS_ENVP_ENTRY:
14375+ envp++;
14376+ continue;
14377+ case CCS_NUMBER_UNION:
14378+ numbers_p++;
14379+ break;
14380+ }
14381+ switch (right) {
14382+ case CCS_NAME_UNION:
14383+ names_p++;
14384+ break;
14385+ case CCS_NUMBER_UNION:
14386+ numbers_p++;
14387+ break;
14388+ }
14389+ }
14390+ while (head->r.cond_index < condc) {
14391+ const u8 match = condp->equals;
14392+ const u8 left = condp->left;
14393+ const u8 right = condp->right;
14394+ if (!ccs_flush(head))
14395+ return false;
14396+ condp++;
14397+ head->r.cond_index++;
14398+ ccs_set_space(head);
14399+ switch (left) {
14400+ case CCS_ARGV_ENTRY:
14401+ ccs_io_printf(head,
14402+ "exec.argv[%lu]%s=\"",
14403+ argv->index,
14404+ argv->is_not ? "!" : "");
14405+ ccs_set_string(head,
14406+ argv->value->name);
14407+ ccs_set_string(head, "\"");
14408+ argv++;
14409+ continue;
14410+ case CCS_ENVP_ENTRY:
14411+ ccs_set_string(head, "exec.envp[\"");
14412+ ccs_set_string(head, envp->name->name);
14413+ ccs_io_printf(head, "\"]%s=",
14414+ envp->is_not ? "!" : "");
14415+ if (envp->value) {
14416+ ccs_set_string(head, "\"");
14417+ ccs_set_string(head, envp->
14418+ value->name);
14419+ ccs_set_string(head, "\"");
14420+ } else {
14421+ ccs_set_string(head, "NULL");
14422+ }
14423+ envp++;
14424+ continue;
14425+ case CCS_NUMBER_UNION:
14426+ ccs_print_number_union_nospace
14427+ (head, numbers_p++);
14428+ break;
14429+ default:
14430+ ccs_set_string(head,
14431+ ccs_condition_keyword[left]);
14432+ break;
14433+ }
14434+ ccs_set_string(head, match ? "=" : "!=");
14435+ switch (right) {
14436+ case CCS_NAME_UNION:
14437+ ccs_print_name_union_quoted
14438+ (head, names_p++);
14439+ break;
14440+ case CCS_NUMBER_UNION:
14441+ ccs_print_number_union_nospace
14442+ (head, numbers_p++);
14443+ break;
14444+ default:
14445+ ccs_set_string(head,
14446+ ccs_condition_keyword[right]);
14447+ break;
14448+ }
14449+ }
14450+ }
14451+ head->r.cond_step++;
14452+ /* fall through */
14453+ case 2:
14454+ if (!ccs_flush(head))
14455+ break;
14456+ head->r.cond_step++;
14457+ /* fall through */
14458+ case 3:
14459+ if (cond->grant_log != CCS_GRANTLOG_AUTO)
14460+ ccs_io_printf(head, " grant_log=%s",
14461+ ccs_yesno(cond->grant_log ==
14462+ CCS_GRANTLOG_YES));
14463+ if (cond->transit && !cond->exec_transit) {
14464+ const char *name = cond->transit->name;
14465+ ccs_set_string(head, " auto_domain_transition=\"");
14466+ ccs_set_string(head, name);
14467+ ccs_set_string(head, "\"");
14468+ }
14469+ ccs_set_lf(head);
14470+ return true;
14471+ }
14472+ return false;
14473+}
14474+
14475+/**
14476+ * ccs_set_group - Print "acl_group " header keyword and category name.
14477+ *
14478+ * @head: Pointer to "struct ccs_io_buffer".
14479+ * @category: Category name.
14480+ *
14481+ * Returns nothing.
14482+ */
14483+static void ccs_set_group(struct ccs_io_buffer *head, const char *category)
14484+{
14485+ if (head->type == CCS_EXCEPTION_POLICY) {
14486+ ccs_print_namespace(head);
14487+ ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
14488+ }
14489+ ccs_set_string(head, category);
14490+}
14491+
14492+/**
14493+ * ccs_print_entry - Print an ACL entry.
14494+ *
14495+ * @head: Pointer to "struct ccs_io_buffer".
14496+ * @acl: Pointer to an ACL entry.
14497+ *
14498+ * Returns true on success, false otherwise.
14499+ */
14500+static bool ccs_print_entry(struct ccs_io_buffer *head,
14501+ const struct ccs_acl_info *acl)
14502+{
14503+ const u8 acl_type = acl->type;
14504+ const bool may_trigger_transition = acl->cond && acl->cond->transit;
14505+ bool first = true;
14506+ u8 bit;
14507+ if (head->r.print_cond_part)
14508+ goto print_cond_part;
14509+ if (acl->is_deleted)
14510+ return true;
14511+ if (!ccs_flush(head))
14512+ return false;
14513+ else if (acl_type == CCS_TYPE_PATH_ACL) {
14514+ struct ccs_path_acl *ptr
14515+ = container_of(acl, typeof(*ptr), head);
14516+ for (bit = 0; bit < CCS_MAX_PATH_OPERATION; bit++) {
14517+ if (!(acl->perm & (1 << bit)))
14518+ continue;
14519+ if (head->r.print_transition_related_only &&
14520+ bit != CCS_TYPE_EXECUTE && !may_trigger_transition)
14521+ continue;
14522+ if (first) {
14523+ ccs_set_group(head, "file ");
14524+ first = false;
14525+ } else {
14526+ ccs_set_slash(head);
14527+ }
14528+ ccs_set_string(head, ccs_path_keyword[bit]);
14529+ }
14530+ if (first)
14531+ return true;
14532+ ccs_print_name_union(head, &ptr->name);
14533+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
14534+ } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||
14535+ acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
14536+ struct ccs_handler_acl *ptr
14537+ = container_of(acl, typeof(*ptr), head);
14538+ ccs_set_group(head, "task ");
14539+ ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER
14540+ ? "auto_execute_handler " :
14541+ "denied_execute_handler ");
14542+ ccs_set_string(head, ptr->handler->name);
14543+#endif
14544+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
14545+ } else if (acl_type == CCS_TYPE_AUTO_TASK_ACL ||
14546+ acl_type == CCS_TYPE_MANUAL_TASK_ACL) {
14547+ struct ccs_task_acl *ptr =
14548+ container_of(acl, typeof(*ptr), head);
14549+ ccs_set_group(head, "task ");
14550+ ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?
14551+ "auto_domain_transition " :
14552+ "manual_domain_transition ");
14553+ ccs_set_string(head, ptr->domainname->name);
14554+#endif
14555+ } else if (head->r.print_transition_related_only &&
14556+ !may_trigger_transition) {
14557+ return true;
14558+ } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
14559+ struct ccs_mkdev_acl *ptr =
14560+ container_of(acl, typeof(*ptr), head);
14561+ for (bit = 0; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
14562+ if (!(acl->perm & (1 << bit)))
14563+ continue;
14564+ if (first) {
14565+ ccs_set_group(head, "file ");
14566+ first = false;
14567+ } else {
14568+ ccs_set_slash(head);
14569+ }
14570+ ccs_set_string(head, ccs_mac_keywords
14571+ [ccs_pnnn2mac[bit]]);
14572+ }
14573+ if (first)
14574+ return true;
14575+ ccs_print_name_union(head, &ptr->name);
14576+ ccs_print_number_union(head, &ptr->mode);
14577+ ccs_print_number_union(head, &ptr->major);
14578+ ccs_print_number_union(head, &ptr->minor);
14579+ } else if (acl_type == CCS_TYPE_PATH2_ACL) {
14580+ struct ccs_path2_acl *ptr =
14581+ container_of(acl, typeof(*ptr), head);
14582+ for (bit = 0; bit < CCS_MAX_PATH2_OPERATION; bit++) {
14583+ if (!(acl->perm & (1 << bit)))
14584+ continue;
14585+ if (first) {
14586+ ccs_set_group(head, "file ");
14587+ first = false;
14588+ } else {
14589+ ccs_set_slash(head);
14590+ }
14591+ ccs_set_string(head, ccs_mac_keywords
14592+ [ccs_pp2mac[bit]]);
14593+ }
14594+ if (first)
14595+ return true;
14596+ ccs_print_name_union(head, &ptr->name1);
14597+ ccs_print_name_union(head, &ptr->name2);
14598+ } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
14599+ struct ccs_path_number_acl *ptr =
14600+ container_of(acl, typeof(*ptr), head);
14601+ for (bit = 0; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
14602+ if (!(acl->perm & (1 << bit)))
14603+ continue;
14604+ if (first) {
14605+ ccs_set_group(head, "file ");
14606+ first = false;
14607+ } else {
14608+ ccs_set_slash(head);
14609+ }
14610+ ccs_set_string(head, ccs_mac_keywords
14611+ [ccs_pn2mac[bit]]);
14612+ }
14613+ if (first)
14614+ return true;
14615+ ccs_print_name_union(head, &ptr->name);
14616+ ccs_print_number_union(head, &ptr->number);
14617+#ifdef CONFIG_CCSECURITY_MISC
14618+ } else if (acl_type == CCS_TYPE_ENV_ACL) {
14619+ struct ccs_env_acl *ptr =
14620+ container_of(acl, typeof(*ptr), head);
14621+ ccs_set_group(head, "misc env ");
14622+ ccs_set_string(head, ptr->env->name);
14623+#endif
14624+#ifdef CONFIG_CCSECURITY_CAPABILITY
14625+ } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
14626+ struct ccs_capability_acl *ptr =
14627+ container_of(acl, typeof(*ptr), head);
14628+ ccs_set_group(head, "capability ");
14629+ ccs_set_string(head, ccs_mac_keywords
14630+ [ccs_c2mac[ptr->operation]]);
14631+#endif
14632+#ifdef CONFIG_CCSECURITY_NETWORK
14633+ } else if (acl_type == CCS_TYPE_INET_ACL) {
14634+ struct ccs_inet_acl *ptr =
14635+ container_of(acl, typeof(*ptr), head);
14636+ for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
14637+ if (!(acl->perm & (1 << bit)))
14638+ continue;
14639+ if (first) {
14640+ ccs_set_group(head, "network inet ");
14641+ ccs_set_string(head, ccs_proto_keyword
14642+ [ptr->protocol]);
14643+ ccs_set_space(head);
14644+ first = false;
14645+ } else {
14646+ ccs_set_slash(head);
14647+ }
14648+ ccs_set_string(head, ccs_socket_keyword[bit]);
14649+ }
14650+ if (first)
14651+ return true;
14652+ ccs_set_space(head);
14653+ if (!ccs_print_group(head, ptr->address.group)) {
14654+ char buf[128];
14655+ ccs_print_ip(buf, sizeof(buf), &ptr->address);
14656+ ccs_io_printf(head, "%s", buf);
14657+ }
14658+ ccs_print_number_union(head, &ptr->port);
14659+ } else if (acl_type == CCS_TYPE_UNIX_ACL) {
14660+ struct ccs_unix_acl *ptr =
14661+ container_of(acl, typeof(*ptr), head);
14662+ for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
14663+ if (!(acl->perm & (1 << bit)))
14664+ continue;
14665+ if (first) {
14666+ ccs_set_group(head, "network unix ");
14667+ ccs_set_string(head, ccs_proto_keyword
14668+ [ptr->protocol]);
14669+ ccs_set_space(head);
14670+ first = false;
14671+ } else {
14672+ ccs_set_slash(head);
14673+ }
14674+ ccs_set_string(head, ccs_socket_keyword[bit]);
14675+ }
14676+ if (first)
14677+ return true;
14678+ ccs_print_name_union(head, &ptr->name);
14679+#endif
14680+#ifdef CONFIG_CCSECURITY_IPC
14681+ } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
14682+ struct ccs_signal_acl *ptr =
14683+ container_of(acl, typeof(*ptr), head);
14684+ ccs_set_group(head, "ipc signal ");
14685+ ccs_print_number_union_nospace(head, &ptr->sig);
14686+ ccs_set_space(head);
14687+ ccs_set_string(head, ptr->domainname->name);
14688+#endif
14689+ } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
14690+ struct ccs_mount_acl *ptr =
14691+ container_of(acl, typeof(*ptr), head);
14692+ ccs_set_group(head, "file mount");
14693+ ccs_print_name_union(head, &ptr->dev_name);
14694+ ccs_print_name_union(head, &ptr->dir_name);
14695+ ccs_print_name_union(head, &ptr->fs_type);
14696+ ccs_print_number_union(head, &ptr->flags);
14697+ }
14698+ if (acl->cond) {
14699+ head->r.print_cond_part = true;
14700+ head->r.cond_step = 0;
14701+ if (!ccs_flush(head))
14702+ return false;
14703+print_cond_part:
14704+ if (!ccs_print_condition(head, acl->cond))
14705+ return false;
14706+ head->r.print_cond_part = false;
14707+ } else {
14708+ ccs_set_lf(head);
14709+ }
14710+ return true;
14711+}
14712+
14713+/**
14714+ * ccs_read_acl - Read "struct ccs_acl_info" list.
14715+ *
14716+ * @head: Pointer to "struct ccs_io_buffer".
14717+ * @list: Pointer to "struct list_head".
14718+ *
14719+ * Returns true on success, false otherwise.
14720+ *
14721+ * Caller holds ccs_read_lock().
14722+ */
14723+static bool ccs_read_acl(struct ccs_io_buffer *head, struct list_head *list)
14724+{
14725+ list_for_each_cookie(head->r.acl, list) {
14726+ struct ccs_acl_info *ptr =
14727+ list_entry(head->r.acl, typeof(*ptr), list);
14728+ if (!ccs_print_entry(head, ptr))
14729+ return false;
14730+ }
14731+ head->r.acl = NULL;
14732+ return true;
14733+}
14734+
14735+/**
14736+ * ccs_read_domain - Read domain policy.
14737+ *
14738+ * @head: Pointer to "struct ccs_io_buffer".
14739+ *
14740+ * Returns nothing.
14741+ *
14742+ * Caller holds ccs_read_lock().
14743+ */
14744+static void ccs_read_domain(struct ccs_io_buffer *head)
14745+{
14746+ if (head->r.eof)
14747+ return;
14748+ list_for_each_cookie(head->r.domain, &ccs_domain_list) {
14749+ struct ccs_domain_info *domain =
14750+ list_entry(head->r.domain, typeof(*domain), list);
14751+ switch (head->r.step) {
14752+ u8 i;
14753+ case 0:
14754+ if (domain->is_deleted &&
14755+ !head->r.print_this_domain_only)
14756+ continue;
14757+ /* Print domainname and flags. */
14758+ ccs_set_string(head, domain->domainname->name);
14759+ ccs_set_lf(head);
14760+ ccs_io_printf(head, "use_profile %u\n",
14761+ domain->profile);
14762+ for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)
14763+ if (domain->flags[i])
14764+ ccs_set_string(head, ccs_dif[i]);
14765+ head->r.index = 0;
14766+ head->r.step++;
14767+ /* fall through */
14768+ case 1:
14769+ while (head->r.index < CCS_MAX_ACL_GROUPS) {
14770+ i = head->r.index++;
14771+ if (!test_bit(i, domain->group))
14772+ continue;
14773+ ccs_io_printf(head, "use_group %u\n", i);
14774+ if (!ccs_flush(head))
14775+ return;
14776+ }
14777+ head->r.index = 0;
14778+ head->r.step++;
14779+ ccs_set_lf(head);
14780+ /* fall through */
14781+ case 2:
14782+ if (!ccs_read_acl(head, &domain->acl_info_list))
14783+ return;
14784+ head->r.step++;
14785+ if (!ccs_set_lf(head))
14786+ return;
14787+ /* fall through */
14788+ case 3:
14789+ head->r.step = 0;
14790+ if (head->r.print_this_domain_only)
14791+ goto done;
14792+ }
14793+ }
14794+done:
14795+ head->r.eof = true;
14796+}
14797+
14798+/**
14799+ * ccs_write_pid - Specify PID to obtain domainname.
14800+ *
14801+ * @head: Pointer to "struct ccs_io_buffer".
14802+ *
14803+ * Returns 0.
14804+ */
14805+static int ccs_write_pid(struct ccs_io_buffer *head)
14806+{
14807+ head->r.eof = false;
14808+ return 0;
14809+}
14810+
14811+/**
14812+ * ccs_read_pid - Read information of a process.
14813+ *
14814+ * @head: Pointer to "struct ccs_io_buffer".
14815+ *
14816+ * Returns the domainname which the specified PID is in or
14817+ * process information of the specified PID on success,
14818+ * empty string otherwise.
14819+ *
14820+ * Caller holds ccs_read_lock().
14821+ */
14822+static void ccs_read_pid(struct ccs_io_buffer *head)
14823+{
14824+ char *buf = head->write_buf;
14825+ bool task_info = false;
14826+ bool global_pid = false;
14827+ unsigned int pid;
14828+ struct task_struct *p;
14829+ struct ccs_domain_info *domain = NULL;
14830+ u32 ccs_flags = 0;
14831+ /* Accessing write_buf is safe because head->io_sem is held. */
14832+ if (!buf) {
14833+ head->r.eof = true;
14834+ return; /* Do nothing if open(O_RDONLY). */
14835+ }
14836+ if (head->r.w_pos || head->r.eof)
14837+ return;
14838+ head->r.eof = true;
14839+ if (ccs_str_starts(&buf, "info "))
14840+ task_info = true;
14841+ if (ccs_str_starts(&buf, "global-pid "))
14842+ global_pid = true;
14843+ pid = (unsigned int) simple_strtoul(buf, NULL, 10);
14844+ ccs_tasklist_lock();
14845+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
14846+ if (global_pid)
14847+ p = ccsecurity_exports.find_task_by_pid_ns(pid, &init_pid_ns);
14848+ else
14849+ p = ccsecurity_exports.find_task_by_vpid(pid);
14850+#else
14851+ p = find_task_by_pid(pid);
14852+#endif
14853+ if (p) {
14854+ domain = ccs_task_domain(p);
14855+ ccs_flags = ccs_task_flags(p);
14856+ }
14857+ ccs_tasklist_unlock();
14858+ if (!domain)
14859+ return;
14860+ if (!task_info) {
14861+ ccs_io_printf(head, "%u %u ", pid, domain->profile);
14862+ ccs_set_string(head, domain->domainname->name);
14863+ } else {
14864+ ccs_io_printf(head, "%u manager=%s execute_handler=%s ", pid,
14865+ ccs_yesno(ccs_flags &
14866+ CCS_TASK_IS_MANAGER),
14867+ ccs_yesno(ccs_flags &
14868+ CCS_TASK_IS_EXECUTE_HANDLER));
14869+ }
14870+}
14871+
14872+/**
14873+ * ccs_write_group - Write "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
14874+ *
14875+ * @param: Pointer to "struct ccs_acl_param".
14876+ * @type: Type of this group.
14877+ *
14878+ * Returns 0 on success, negative value otherwise.
14879+ */
14880+static int ccs_write_group(struct ccs_acl_param *param, const u8 type)
14881+{
14882+ struct ccs_group *group = ccs_get_group(param, type);
14883+ int error = -EINVAL;
14884+ if (!group)
14885+ return -ENOMEM;
14886+ param->list = &group->member_list;
14887+ if (type == CCS_PATH_GROUP) {
14888+ struct ccs_path_group *e = &param->e.path_group;
14889+ e->member_name = ccs_get_name(ccs_read_token(param));
14890+ if (!e->member_name) {
14891+ error = -ENOMEM;
14892+ goto out;
14893+ }
14894+ error = ccs_update_policy(sizeof(*e), param);
14895+ ccs_put_name(e->member_name);
14896+ } else if (type == CCS_NUMBER_GROUP) {
14897+ struct ccs_number_group *e = &param->e.number_group;
14898+ if (param->data[0] == '@' ||
14899+ !ccs_parse_number_union(param, &e->number))
14900+ goto out;
14901+ error = ccs_update_policy(sizeof(*e), param);
14902+#ifdef CONFIG_CCSECURITY_NETWORK
14903+ } else {
14904+ struct ccs_address_group *e = &param->e.address_group;
14905+ if (param->data[0] == '@' ||
14906+ !ccs_parse_ipaddr_union(param, &e->address))
14907+ goto out;
14908+ error = ccs_update_policy(sizeof(*e), param);
14909+#endif
14910+ }
14911+out:
14912+ ccs_put_group(group);
14913+ return error;
14914+}
14915+
14916+#ifdef CONFIG_CCSECURITY_PORTRESERVE
14917+/**
14918+ * ccs_lport_reserved - Check whether local port is reserved or not.
14919+ *
14920+ * @port: Port number.
14921+ *
14922+ * Returns true if local port is reserved, false otherwise.
14923+ */
14924+static bool __ccs_lport_reserved(const u16 port)
14925+{
14926+ return ccs_reserved_port_map[port >> 3] & (1 << (port & 7))
14927+ ? true : false;
14928+}
14929+
14930+/**
14931+ * ccs_write_reserved_port - Update "struct ccs_reserved" list.
14932+ *
14933+ * @param: Pointer to "struct ccs_acl_param".
14934+ *
14935+ * Returns 0 on success, negative value otherwise.
14936+ *
14937+ * Caller holds ccs_read_lock().
14938+ */
14939+static int ccs_write_reserved_port(struct ccs_acl_param *param)
14940+{
14941+ struct ccs_reserved *e = &param->e.reserved;
14942+ struct ccs_policy_namespace *ns = param->ns;
14943+ int error;
14944+ u8 *tmp;
14945+ if (param->data[0] == '@' ||
14946+ !ccs_parse_number_union(param, &e->port) ||
14947+ e->port.values[1] > 65535 || param->data[0])
14948+ return -EINVAL;
14949+ param->list = &ns->policy_list[CCS_ID_RESERVEDPORT];
14950+ error = ccs_update_policy(sizeof(*e), param);
14951+ if (error)
14952+ return error;
14953+ tmp = kzalloc(sizeof(ccs_reserved_port_map), CCS_GFP_FLAGS);
14954+ if (!tmp)
14955+ return -ENOMEM;
14956+ list_for_each_entry_srcu(ns, &ccs_namespace_list, namespace_list,
14957+ &ccs_ss) {
14958+ struct ccs_reserved *ptr;
14959+ struct list_head *list = &ns->policy_list[CCS_ID_RESERVEDPORT];
14960+ list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
14961+ unsigned int port;
14962+ if (ptr->head.is_deleted)
14963+ continue;
14964+ for (port = ptr->port.values[0];
14965+ port <= ptr->port.values[1]; port++)
14966+ tmp[port >> 3] |= 1 << (port & 7);
14967+ }
14968+ }
14969+ memmove(ccs_reserved_port_map, tmp, sizeof(ccs_reserved_port_map));
14970+ kfree(tmp);
14971+ /*
14972+ * Since this feature is no-op by default, we don't need to register
14973+ * this callback hook unless the first entry is added.
14974+ */
14975+ ccsecurity_ops.lport_reserved = __ccs_lport_reserved;
14976+ return 0;
14977+}
14978+#endif
14979+
14980+/**
14981+ * ccs_write_aggregator - Write "struct ccs_aggregator" list.
14982+ *
14983+ * @param: Pointer to "struct ccs_acl_param".
14984+ *
14985+ * Returns 0 on success, negative value otherwise.
14986+ */
14987+static int ccs_write_aggregator(struct ccs_acl_param *param)
14988+{
14989+ struct ccs_aggregator *e = &param->e.aggregator;
14990+ int error = param->is_delete ? -ENOENT : -ENOMEM;
14991+ const char *original_name = ccs_read_token(param);
14992+ const char *aggregated_name = ccs_read_token(param);
14993+ if (!ccs_correct_word(original_name) ||
14994+ !ccs_correct_path(aggregated_name))
14995+ return -EINVAL;
14996+ e->original_name = ccs_get_name(original_name);
14997+ e->aggregated_name = ccs_get_name(aggregated_name);
14998+ if (!e->original_name || !e->aggregated_name ||
14999+ e->aggregated_name->is_patterned) /* No patterns allowed. */
15000+ goto out;
15001+ param->list = &param->ns->policy_list[CCS_ID_AGGREGATOR];
15002+ error = ccs_update_policy(sizeof(*e), param);
15003+out:
15004+ ccs_put_name(e->original_name);
15005+ ccs_put_name(e->aggregated_name);
15006+ return error;
15007+}
15008+
15009+/**
15010+ * ccs_write_transition_control - Write "struct ccs_transition_control" list.
15011+ *
15012+ * @param: Pointer to "struct ccs_acl_param".
15013+ * @type: Type of this entry.
15014+ *
15015+ * Returns 0 on success, negative value otherwise.
15016+ */
15017+static int ccs_write_transition_control(struct ccs_acl_param *param,
15018+ const u8 type)
15019+{
15020+ struct ccs_transition_control *e = &param->e.transition_control;
15021+ int error = param->is_delete ? -ENOENT : -ENOMEM;
15022+ char *program = param->data;
15023+ char *domainname = strstr(program, " from ");
15024+ e->type = type;
15025+ if (domainname) {
15026+ *domainname = '\0';
15027+ domainname += 6;
15028+ } else if (type == CCS_TRANSITION_CONTROL_NO_KEEP ||
15029+ type == CCS_TRANSITION_CONTROL_KEEP) {
15030+ domainname = program;
15031+ program = NULL;
15032+ }
15033+ if (program && strcmp(program, "any")) {
15034+ if (!ccs_correct_path(program))
15035+ return -EINVAL;
15036+ e->program = ccs_get_name(program);
15037+ if (!e->program)
15038+ goto out;
15039+ }
15040+ if (domainname && strcmp(domainname, "any")) {
15041+ if (!ccs_correct_domain(domainname)) {
15042+ if (!ccs_correct_path(domainname))
15043+ goto out;
15044+ e->is_last_name = true;
15045+ }
15046+ e->domainname = ccs_get_name(domainname);
15047+ if (!e->domainname)
15048+ goto out;
15049+ }
15050+ param->list = &param->ns->policy_list[CCS_ID_TRANSITION_CONTROL];
15051+ error = ccs_update_policy(sizeof(*e), param);
15052+out:
15053+ ccs_put_name(e->domainname);
15054+ ccs_put_name(e->program);
15055+ return error;
15056+}
15057+
15058+/**
15059+ * ccs_write_exception - Write exception policy.
15060+ *
15061+ * @head: Pointer to "struct ccs_io_buffer".
15062+ *
15063+ * Returns 0 on success, negative value otherwise.
15064+ */
15065+static int ccs_write_exception(struct ccs_io_buffer *head)
15066+{
15067+ const bool is_delete = head->w.is_delete;
15068+ struct ccs_acl_param param = {
15069+ .ns = head->w.ns,
15070+ .is_delete = is_delete,
15071+ .data = head->write_buf,
15072+ };
15073+ u8 i;
15074+ /* Forced zero clear for using memcmp() at ccs_update_policy(). */
15075+ memset(&param.e, 0, sizeof(param.e));
15076+ if (ccs_str_starts(&param.data, "aggregator "))
15077+ return ccs_write_aggregator(&param);
15078+#ifdef CONFIG_CCSECURITY_PORTRESERVE
15079+ if (ccs_str_starts(&param.data, "deny_autobind "))
15080+ return ccs_write_reserved_port(&param);
15081+#endif
15082+ for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
15083+ if (ccs_str_starts(&param.data, ccs_transition_type[i]))
15084+ return ccs_write_transition_control(&param, i);
15085+ for (i = 0; i < CCS_MAX_GROUP; i++)
15086+ if (ccs_str_starts(&param.data, ccs_group_name[i]))
15087+ return ccs_write_group(&param, i);
15088+ if (ccs_str_starts(&param.data, "acl_group ")) {
15089+ unsigned int group;
15090+ char *data;
15091+ group = simple_strtoul(param.data, &data, 10);
15092+ if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
15093+ return ccs_write_acl(head->w.ns,
15094+ &head->w.ns->acl_group[group],
15095+ data, is_delete);
15096+ }
15097+ return -EINVAL;
15098+}
15099+
15100+/**
15101+ * ccs_read_group - Read "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
15102+ *
15103+ * @head: Pointer to "struct ccs_io_buffer".
15104+ * @idx: Index number.
15105+ *
15106+ * Returns true on success, false otherwise.
15107+ *
15108+ * Caller holds ccs_read_lock().
15109+ */
15110+static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)
15111+{
15112+ struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
15113+ namespace_list);
15114+ struct list_head *list = &ns->group_list[idx];
15115+ list_for_each_cookie(head->r.group, list) {
15116+ struct ccs_group *group =
15117+ list_entry(head->r.group, typeof(*group), head.list);
15118+ list_for_each_cookie(head->r.acl, &group->member_list) {
15119+ struct ccs_acl_head *ptr =
15120+ list_entry(head->r.acl, typeof(*ptr), list);
15121+ if (ptr->is_deleted)
15122+ continue;
15123+ if (!ccs_flush(head))
15124+ return false;
15125+ ccs_print_namespace(head);
15126+ ccs_set_string(head, ccs_group_name[idx]);
15127+ ccs_set_string(head, group->group_name->name);
15128+ if (idx == CCS_PATH_GROUP) {
15129+ ccs_set_space(head);
15130+ ccs_set_string(head, container_of
15131+ (ptr, struct ccs_path_group,
15132+ head)->member_name->name);
15133+ } else if (idx == CCS_NUMBER_GROUP) {
15134+ ccs_print_number_union(head, &container_of
15135+ (ptr, struct ccs_number_group,
15136+ head)->number);
15137+#ifdef CONFIG_CCSECURITY_NETWORK
15138+ } else if (idx == CCS_ADDRESS_GROUP) {
15139+ char buffer[128];
15140+ struct ccs_address_group *member =
15141+ container_of(ptr, typeof(*member),
15142+ head);
15143+ ccs_print_ip(buffer, sizeof(buffer),
15144+ &member->address);
15145+ ccs_io_printf(head, " %s", buffer);
15146+#endif
15147+ }
15148+ ccs_set_lf(head);
15149+ }
15150+ head->r.acl = NULL;
15151+ }
15152+ head->r.group = NULL;
15153+ return true;
15154+}
15155+
15156+/**
15157+ * ccs_read_policy - Read "struct ccs_..._entry" list.
15158+ *
15159+ * @head: Pointer to "struct ccs_io_buffer".
15160+ * @idx: Index number.
15161+ *
15162+ * Returns true on success, false otherwise.
15163+ *
15164+ * Caller holds ccs_read_lock().
15165+ */
15166+static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)
15167+{
15168+ struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
15169+ namespace_list);
15170+ struct list_head *list = &ns->policy_list[idx];
15171+ list_for_each_cookie(head->r.acl, list) {
15172+ struct ccs_acl_head *acl =
15173+ container_of(head->r.acl, typeof(*acl), list);
15174+ if (acl->is_deleted)
15175+ continue;
15176+ if (head->r.print_transition_related_only &&
15177+ idx != CCS_ID_TRANSITION_CONTROL)
15178+ continue;
15179+ if (!ccs_flush(head))
15180+ return false;
15181+ switch (idx) {
15182+ case CCS_ID_TRANSITION_CONTROL:
15183+ {
15184+ struct ccs_transition_control *ptr =
15185+ container_of(acl, typeof(*ptr), head);
15186+ ccs_print_namespace(head);
15187+ ccs_set_string(head,
15188+ ccs_transition_type[ptr->type]);
15189+ ccs_set_string(head, ptr->program ?
15190+ ptr->program->name : "any");
15191+ ccs_set_string(head, " from ");
15192+ ccs_set_string(head, ptr->domainname ?
15193+ ptr->domainname->name : "any");
15194+ }
15195+ break;
15196+ case CCS_ID_AGGREGATOR:
15197+ {
15198+ struct ccs_aggregator *ptr =
15199+ container_of(acl, typeof(*ptr), head);
15200+ ccs_print_namespace(head);
15201+ ccs_set_string(head, "aggregator ");
15202+ ccs_set_string(head, ptr->original_name->name);
15203+ ccs_set_space(head);
15204+ ccs_set_string(head,
15205+ ptr->aggregated_name->name);
15206+ }
15207+ break;
15208+#ifdef CONFIG_CCSECURITY_PORTRESERVE
15209+ case CCS_ID_RESERVEDPORT:
15210+ {
15211+ struct ccs_reserved *ptr =
15212+ container_of(acl, typeof(*ptr), head);
15213+ ccs_print_namespace(head);
15214+ ccs_set_string(head, "deny_autobind ");
15215+ ccs_print_number_union_nospace(head,
15216+ &ptr->port);
15217+ }
15218+ break;
15219+#endif
15220+ default:
15221+ continue;
15222+ }
15223+ ccs_set_lf(head);
15224+ }
15225+ head->r.acl = NULL;
15226+ return true;
15227+}
15228+
15229+/**
15230+ * ccs_read_exception - Read exception policy.
15231+ *
15232+ * @head: Pointer to "struct ccs_io_buffer".
15233+ *
15234+ * Returns nothing.
15235+ *
15236+ * Caller holds ccs_read_lock().
15237+ */
15238+static void ccs_read_exception(struct ccs_io_buffer *head)
15239+{
15240+ struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
15241+ namespace_list);
15242+ if (head->r.eof)
15243+ return;
15244+ while (head->r.step < CCS_MAX_POLICY &&
15245+ ccs_read_policy(head, head->r.step))
15246+ head->r.step++;
15247+ if (head->r.step < CCS_MAX_POLICY)
15248+ return;
15249+ while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP &&
15250+ ccs_read_group(head, head->r.step - CCS_MAX_POLICY))
15251+ head->r.step++;
15252+ if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)
15253+ return;
15254+ while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
15255+ + CCS_MAX_ACL_GROUPS) {
15256+ head->r.acl_group_index =
15257+ head->r.step - CCS_MAX_POLICY - CCS_MAX_GROUP;
15258+ if (!ccs_read_acl(head, &ns->acl_group
15259+ [head->r.acl_group_index]))
15260+ return;
15261+ head->r.step++;
15262+ }
15263+ head->r.eof = true;
15264+}
15265+
15266+/**
15267+ * ccs_truncate - Truncate a line.
15268+ *
15269+ * @str: String to truncate.
15270+ *
15271+ * Returns length of truncated @str.
15272+ */
15273+static int ccs_truncate(char *str)
15274+{
15275+ char *start = str;
15276+ while (*(unsigned char *) str > (unsigned char) ' ')
15277+ str++;
15278+ *str = '\0';
15279+ return strlen(start) + 1;
15280+}
15281+
15282+/**
15283+ * ccs_add_entry - Add an ACL to current thread's domain. Used by learning mode.
15284+ *
15285+ * @header: Lines containing ACL.
15286+ *
15287+ * Returns nothing.
15288+ */
15289+static void ccs_add_entry(char *header)
15290+{
15291+ char *buffer;
15292+ char *realpath = NULL;
15293+ char *argv0 = NULL;
15294+ char *symlink = NULL;
15295+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
15296+ char *handler;
15297+#endif
15298+ char *cp = strchr(header, '\n');
15299+ int len;
15300+ if (!cp)
15301+ return;
15302+ cp = strchr(cp + 1, '\n');
15303+ if (!cp)
15304+ return;
15305+ *cp++ = '\0';
15306+ len = strlen(cp) + 1;
15307+ /* strstr() will return NULL if ordering is wrong. */
15308+ if (*cp == 'f') {
15309+ argv0 = strstr(header, " argv[]={ \"");
15310+ if (argv0) {
15311+ argv0 += 10;
15312+ len += ccs_truncate(argv0) + 14;
15313+ }
15314+ realpath = strstr(header, " exec={ realpath=\"");
15315+ if (realpath) {
15316+ realpath += 8;
15317+ len += ccs_truncate(realpath) + 6;
15318+ }
15319+ symlink = strstr(header, " symlink.target=\"");
15320+ if (symlink)
15321+ len += ccs_truncate(symlink + 1) + 1;
15322+ }
15323+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
15324+ handler = strstr(header, "type=execute_handler");
15325+ if (handler)
15326+ len += ccs_truncate(handler) + 6;
15327+#endif
15328+ buffer = kmalloc(len, CCS_GFP_FLAGS);
15329+ if (!buffer)
15330+ return;
15331+ snprintf(buffer, len - 1, "%s", cp);
15332+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
15333+ if (handler)
15334+ ccs_addprintf(buffer, len, " task.%s", handler);
15335+#endif
15336+ if (realpath)
15337+ ccs_addprintf(buffer, len, " exec.%s", realpath);
15338+ if (argv0)
15339+ ccs_addprintf(buffer, len, " exec.argv[0]=%s", argv0);
15340+ if (symlink)
15341+ ccs_addprintf(buffer, len, "%s", symlink);
15342+ ccs_normalize_line(buffer);
15343+ {
15344+ struct ccs_domain_info *domain = ccs_current_domain();
15345+ if (!ccs_write_acl(domain->ns, &domain->acl_info_list,
15346+ buffer, false))
15347+ ccs_update_stat(CCS_STAT_POLICY_UPDATES);
15348+ }
15349+ kfree(buffer);
15350+}
15351+
15352+/**
15353+ * ccs_domain_quota_ok - Check for domain's quota.
15354+ *
15355+ * @r: Pointer to "struct ccs_request_info".
15356+ *
15357+ * Returns true if the domain is not exceeded quota, false otherwise.
15358+ *
15359+ * Caller holds ccs_read_lock().
15360+ */
15361+static bool ccs_domain_quota_ok(struct ccs_request_info *r)
15362+{
15363+ unsigned int count = 0;
15364+ struct ccs_domain_info * const domain = ccs_current_domain();
15365+ struct ccs_acl_info *ptr;
15366+ if (r->mode != CCS_CONFIG_LEARNING)
15367+ return false;
15368+ if (!domain)
15369+ return true;
15370+ list_for_each_entry_srcu(ptr, &domain->acl_info_list, list, &ccs_ss) {
15371+ u16 perm;
15372+ u8 i;
15373+ if (ptr->is_deleted)
15374+ continue;
15375+ switch (ptr->type) {
15376+ case CCS_TYPE_PATH_ACL:
15377+ case CCS_TYPE_PATH2_ACL:
15378+ case CCS_TYPE_PATH_NUMBER_ACL:
15379+ case CCS_TYPE_MKDEV_ACL:
15380+#ifdef CONFIG_CCSECURITY_NETWORK
15381+ case CCS_TYPE_INET_ACL:
15382+ case CCS_TYPE_UNIX_ACL:
15383+#endif
15384+ perm = ptr->perm;
15385+ break;
15386+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
15387+ case CCS_TYPE_AUTO_EXECUTE_HANDLER:
15388+ case CCS_TYPE_DENIED_EXECUTE_HANDLER:
15389+#endif
15390+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
15391+ case CCS_TYPE_AUTO_TASK_ACL:
15392+ case CCS_TYPE_MANUAL_TASK_ACL:
15393+#endif
15394+ perm = 0;
15395+ break;
15396+ default:
15397+ perm = 1;
15398+ }
15399+ for (i = 0; i < 16; i++)
15400+ if (perm & (1 << i))
15401+ count++;
15402+ }
15403+ if (count < ccs_profile(r->profile)->pref[CCS_PREF_MAX_LEARNING_ENTRY])
15404+ return true;
15405+ if (!domain->flags[CCS_DIF_QUOTA_WARNED]) {
15406+ domain->flags[CCS_DIF_QUOTA_WARNED] = true;
15407+ /* r->granted = false; */
15408+ ccs_write_log(r, "%s", ccs_dif[CCS_DIF_QUOTA_WARNED]);
15409+ printk(KERN_WARNING "WARNING: "
15410+ "Domain '%s' has too many ACLs to hold. "
15411+ "Stopped learning mode.\n", domain->domainname->name);
15412+ }
15413+ return false;
15414+}
15415+
15416+/**
15417+ * ccs_supervisor - Ask for the supervisor's decision.
15418+ *
15419+ * @r: Pointer to "struct ccs_request_info".
15420+ * @fmt: The printf()'s format string, followed by parameters.
15421+ *
15422+ * Returns 0 if the supervisor decided to permit the access request which
15423+ * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor
15424+ * decided to retry the access request which violated the policy in enforcing
15425+ * mode, 0 if it is not in enforcing mode, -EPERM otherwise.
15426+ */
15427+static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
15428+{
15429+ va_list args;
15430+ int error;
15431+ int len;
15432+ static unsigned int ccs_serial;
15433+ struct ccs_query entry = { };
15434+ bool quota_exceeded = false;
15435+ va_start(args, fmt);
15436+ len = vsnprintf((char *) &len, 1, fmt, args) + 1;
15437+ va_end(args);
15438+ /* Write /proc/ccs/audit. */
15439+ va_start(args, fmt);
15440+ ccs_write_log2(r, len, fmt, args);
15441+ va_end(args);
15442+ /* Nothing more to do if granted. */
15443+ if (r->granted)
15444+ return 0;
15445+ if (r->mode)
15446+ ccs_update_stat(r->mode);
15447+ switch (r->mode) {
15448+ int i;
15449+ struct ccs_profile *p;
15450+ case CCS_CONFIG_ENFORCING:
15451+ error = -EPERM;
15452+ if (atomic_read(&ccs_query_observers))
15453+ break;
15454+ if (r->dont_sleep_on_enforce_error)
15455+ goto out;
15456+ p = ccs_profile(r->profile);
15457+ /* Check enforcing_penalty parameter. */
15458+ for (i = 0; i < p->pref[CCS_PREF_ENFORCING_PENALTY]; i++) {
15459+ set_current_state(TASK_INTERRUPTIBLE);
15460+ schedule_timeout(HZ / 10);
15461+ }
15462+ goto out;
15463+ case CCS_CONFIG_LEARNING:
15464+ error = 0;
15465+ /* Check max_learning_entry parameter. */
15466+ if (ccs_domain_quota_ok(r))
15467+ break;
15468+ /* fall through */
15469+ default:
15470+ return 0;
15471+ }
15472+ /* Get message. */
15473+ va_start(args, fmt);
15474+ entry.query = ccs_init_log(r, len, fmt, args);
15475+ va_end(args);
15476+ if (!entry.query)
15477+ goto out;
15478+ entry.query_len = strlen(entry.query) + 1;
15479+ if (!error) {
15480+ ccs_add_entry(entry.query);
15481+ goto out;
15482+ }
15483+ len = ccs_round2(entry.query_len);
15484+ entry.domain = ccs_current_domain();
15485+ spin_lock(&ccs_query_list_lock);
15486+ if (ccs_memory_quota[CCS_MEMORY_QUERY] &&
15487+ ccs_memory_used[CCS_MEMORY_QUERY] + len
15488+ >= ccs_memory_quota[CCS_MEMORY_QUERY]) {
15489+ quota_exceeded = true;
15490+ } else {
15491+ entry.serial = ccs_serial++;
15492+ entry.retry = r->retry;
15493+ ccs_memory_used[CCS_MEMORY_QUERY] += len;
15494+ list_add_tail(&entry.list, &ccs_query_list);
15495+ }
15496+ spin_unlock(&ccs_query_list_lock);
15497+ if (quota_exceeded)
15498+ goto out;
15499+ /* Give 10 seconds for supervisor's opinion. */
15500+ while (entry.timer < 10) {
15501+ wake_up_all(&ccs_query_wait);
15502+ if (wait_event_interruptible_timeout
15503+ (ccs_answer_wait, entry.answer ||
15504+ !atomic_read(&ccs_query_observers), HZ))
15505+ break;
15506+ else
15507+ entry.timer++;
15508+ }
15509+ spin_lock(&ccs_query_list_lock);
15510+ list_del(&entry.list);
15511+ ccs_memory_used[CCS_MEMORY_QUERY] -= len;
15512+ spin_unlock(&ccs_query_list_lock);
15513+ switch (entry.answer) {
15514+ case 3: /* Asked to retry by administrator. */
15515+ error = CCS_RETRY_REQUEST;
15516+ r->retry++;
15517+ break;
15518+ case 1:
15519+ /* Granted by administrator. */
15520+ error = 0;
15521+ break;
15522+ default:
15523+ /* Timed out or rejected by administrator. */
15524+ break;
15525+ }
15526+out:
15527+ kfree(entry.query);
15528+ return error;
15529+}
15530+
15531+/**
15532+ * ccs_audit_log - Audit permission check log.
15533+ *
15534+ * @r: Pointer to "struct ccs_request_info".
15535+ *
15536+ * Returns return value of ccs_supervisor().
15537+ */
15538+int ccs_audit_log(struct ccs_request_info *r)
15539+{
15540+ switch (r->param_type) {
15541+ u8 type;
15542+ char buf[48];
15543+#ifdef CONFIG_CCSECURITY_NETWORK
15544+ const u32 *address;
15545+#endif
15546+ case CCS_TYPE_PATH_ACL:
15547+ return ccs_supervisor(r, "file %s %s\n", ccs_path_keyword
15548+ [r->param.path.operation],
15549+ r->param.path.filename->name);
15550+ case CCS_TYPE_PATH2_ACL:
15551+ return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords
15552+ [ccs_pp2mac[r->param.path2.operation]],
15553+ r->param.path2.filename1->name,
15554+ r->param.path2.filename2->name);
15555+ case CCS_TYPE_PATH_NUMBER_ACL:
15556+ type = r->param.path_number.operation;
15557+ switch (type) {
15558+ case CCS_TYPE_CREATE:
15559+ case CCS_TYPE_MKDIR:
15560+ case CCS_TYPE_MKFIFO:
15561+ case CCS_TYPE_MKSOCK:
15562+ case CCS_TYPE_CHMOD:
15563+ snprintf(buf, sizeof(buf), "0%lo",
15564+ r->param.path_number.number);
15565+ break;
15566+ case CCS_TYPE_IOCTL:
15567+ snprintf(buf, sizeof(buf), "0x%lX",
15568+ r->param.path_number.number);
15569+ break;
15570+ default:
15571+ snprintf(buf, sizeof(buf), "%lu",
15572+ r->param.path_number.number);
15573+ break;
15574+ }
15575+ return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords
15576+ [ccs_pn2mac[type]],
15577+ r->param.path_number.filename->name,
15578+ buf);
15579+ case CCS_TYPE_MKDEV_ACL:
15580+ return ccs_supervisor(r, "file %s %s 0%o %u %u\n",
15581+ ccs_mac_keywords
15582+ [ccs_pnnn2mac[r->param.mkdev.operation]],
15583+ r->param.mkdev.filename->name,
15584+ r->param.mkdev.mode,
15585+ r->param.mkdev.major,
15586+ r->param.mkdev.minor);
15587+ case CCS_TYPE_MOUNT_ACL:
15588+ return ccs_supervisor(r, "file mount %s %s %s 0x%lX\n",
15589+ r->param.mount.dev->name,
15590+ r->param.mount.dir->name,
15591+ r->param.mount.type->name,
15592+ r->param.mount.flags);
15593+#ifdef CONFIG_CCSECURITY_MISC
15594+ case CCS_TYPE_ENV_ACL:
15595+ return ccs_supervisor(r, "misc env %s\n",
15596+ r->param.environ.name->name);
15597+#endif
15598+#ifdef CONFIG_CCSECURITY_CAPABILITY
15599+ case CCS_TYPE_CAPABILITY_ACL:
15600+ return ccs_supervisor(r, "capability %s\n", ccs_mac_keywords
15601+ [ccs_c2mac[r->param.capability.
15602+ operation]]);
15603+#endif
15604+#ifdef CONFIG_CCSECURITY_NETWORK
15605+ case CCS_TYPE_INET_ACL:
15606+ address = r->param.inet_network.address;
15607+ if (r->param.inet_network.is_ipv6)
15608+ ccs_print_ipv6(buf, sizeof(buf),
15609+ (const struct in6_addr *) address);
15610+ else
15611+ ccs_print_ipv4(buf, sizeof(buf), address);
15612+ return ccs_supervisor(r, "network inet %s %s %s %u\n",
15613+ ccs_proto_keyword[r->param.inet_network.
15614+ protocol],
15615+ ccs_socket_keyword[r->param.inet_network.
15616+ operation],
15617+ buf, r->param.inet_network.port);
15618+ case CCS_TYPE_UNIX_ACL:
15619+ return ccs_supervisor(r, "network unix %s %s %s\n",
15620+ ccs_proto_keyword[r->param.
15621+ unix_network.protocol],
15622+ ccs_socket_keyword[r->param.unix_network.
15623+ operation],
15624+ r->param.unix_network.address->name);
15625+#endif
15626+#ifdef CONFIG_CCSECURITY_IPC
15627+ case CCS_TYPE_SIGNAL_ACL:
15628+ return ccs_supervisor(r, "ipc signal %d %s\n",
15629+ r->param.signal.sig,
15630+ r->param.signal.dest_pattern);
15631+#endif
15632+ }
15633+ return 0;
15634+}
15635+
15636+/**
15637+ * ccs_find_domain_by_qid - Get domain by query id.
15638+ *
15639+ * @serial: Query ID assigned by ccs_supervisor().
15640+ *
15641+ * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
15642+ */
15643+static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial)
15644+{
15645+ struct ccs_query *ptr;
15646+ struct ccs_domain_info *domain = NULL;
15647+ spin_lock(&ccs_query_list_lock);
15648+ list_for_each_entry(ptr, &ccs_query_list, list) {
15649+ if (ptr->serial != serial)
15650+ continue;
15651+ domain = ptr->domain;
15652+ break;
15653+ }
15654+ spin_unlock(&ccs_query_list_lock);
15655+ return domain;
15656+}
15657+
15658+/**
15659+ * ccs_read_query - Read access requests which violated policy in enforcing mode.
15660+ *
15661+ * @head: Pointer to "struct ccs_io_buffer".
15662+ *
15663+ * Returns nothing.
15664+ */
15665+static void ccs_read_query(struct ccs_io_buffer *head)
15666+{
15667+ struct list_head *tmp;
15668+ unsigned int pos = 0;
15669+ size_t len = 0;
15670+ char *buf;
15671+ if (head->r.w_pos)
15672+ return;
15673+ kfree(head->read_buf);
15674+ head->read_buf = NULL;
15675+ spin_lock(&ccs_query_list_lock);
15676+ list_for_each(tmp, &ccs_query_list) {
15677+ struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
15678+ if (pos++ != head->r.query_index)
15679+ continue;
15680+ len = ptr->query_len;
15681+ break;
15682+ }
15683+ spin_unlock(&ccs_query_list_lock);
15684+ if (!len) {
15685+ head->r.query_index = 0;
15686+ return;
15687+ }
15688+ buf = kzalloc(len + 32, CCS_GFP_FLAGS);
15689+ if (!buf)
15690+ return;
15691+ pos = 0;
15692+ spin_lock(&ccs_query_list_lock);
15693+ list_for_each(tmp, &ccs_query_list) {
15694+ struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
15695+ if (pos++ != head->r.query_index)
15696+ continue;
15697+ /*
15698+ * Some query can be skipped because ccs_query_list
15699+ * can change, but I don't care.
15700+ */
15701+ if (len == ptr->query_len)
15702+ snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
15703+ ptr->retry, ptr->query);
15704+ break;
15705+ }
15706+ spin_unlock(&ccs_query_list_lock);
15707+ if (buf[0]) {
15708+ head->read_buf = buf;
15709+ head->r.w[head->r.w_pos++] = buf;
15710+ head->r.query_index++;
15711+ } else {
15712+ kfree(buf);
15713+ }
15714+}
15715+
15716+/**
15717+ * ccs_write_answer - Write the supervisor's decision.
15718+ *
15719+ * @head: Pointer to "struct ccs_io_buffer".
15720+ *
15721+ * Returns 0 on success, -EINVAL otherwise.
15722+ */
15723+static int ccs_write_answer(struct ccs_io_buffer *head)
15724+{
15725+ char *data = head->write_buf;
15726+ struct list_head *tmp;
15727+ unsigned int serial;
15728+ unsigned int answer;
15729+ spin_lock(&ccs_query_list_lock);
15730+ list_for_each(tmp, &ccs_query_list) {
15731+ struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
15732+ ptr->timer = 0;
15733+ }
15734+ spin_unlock(&ccs_query_list_lock);
15735+ if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
15736+ return -EINVAL;
15737+ spin_lock(&ccs_query_list_lock);
15738+ list_for_each(tmp, &ccs_query_list) {
15739+ struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
15740+ if (ptr->serial != serial)
15741+ continue;
15742+ ptr->answer = (u8) answer;
15743+ /* Remove from ccs_query_list. */
15744+ if (ptr->answer) {
15745+ list_del(&ptr->list);
15746+ INIT_LIST_HEAD(&ptr->list);
15747+ }
15748+ break;
15749+ }
15750+ spin_unlock(&ccs_query_list_lock);
15751+ wake_up_all(&ccs_answer_wait);
15752+ return 0;
15753+}
15754+
15755+/**
15756+ * ccs_read_version - Get version.
15757+ *
15758+ * @head: Pointer to "struct ccs_io_buffer".
15759+ *
15760+ * Returns nothing.
15761+ */
15762+static void ccs_read_version(struct ccs_io_buffer *head)
15763+{
15764+ if (head->r.eof)
15765+ return;
15766+ ccs_set_string(head, "1.8.4");
15767+ head->r.eof = true;
15768+}
15769+
15770+/**
15771+ * ccs_update_stat - Update statistic counters.
15772+ *
15773+ * @index: Index for policy type.
15774+ *
15775+ * Returns nothing.
15776+ */
15777+static void ccs_update_stat(const u8 index)
15778+{
15779+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
15780+ struct timeval tv;
15781+ do_gettimeofday(&tv);
15782+ /*
15783+ * I don't use atomic operations because race condition is not fatal.
15784+ */
15785+ ccs_stat_updated[index]++;
15786+ ccs_stat_modified[index] = tv.tv_sec;
15787+#else
15788+ /*
15789+ * I don't use atomic operations because race condition is not fatal.
15790+ */
15791+ ccs_stat_updated[index]++;
15792+ ccs_stat_modified[index] = get_seconds();
15793+#endif
15794+}
15795+
15796+/**
15797+ * ccs_read_stat - Read statistic data.
15798+ *
15799+ * @head: Pointer to "struct ccs_io_buffer".
15800+ *
15801+ * Returns nothing.
15802+ */
15803+static void ccs_read_stat(struct ccs_io_buffer *head)
15804+{
15805+ u8 i;
15806+ unsigned int total = 0;
15807+ if (head->r.eof)
15808+ return;
15809+ for (i = 0; i < CCS_MAX_POLICY_STAT; i++) {
15810+ ccs_io_printf(head, "Policy %-30s %10u", ccs_policy_headers[i],
15811+ ccs_stat_updated[i]);
15812+ if (ccs_stat_modified[i]) {
15813+ struct ccs_time stamp;
15814+ ccs_convert_time(ccs_stat_modified[i], &stamp);
15815+ ccs_io_printf(head, " (Last: %04u/%02u/%02u "
15816+ "%02u:%02u:%02u)",
15817+ stamp.year, stamp.month, stamp.day,
15818+ stamp.hour, stamp.min, stamp.sec);
15819+ }
15820+ ccs_set_lf(head);
15821+ }
15822+ for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) {
15823+ unsigned int used = ccs_memory_used[i];
15824+ total += used;
15825+ ccs_io_printf(head, "Memory used by %-22s %10u",
15826+ ccs_memory_headers[i], used);
15827+ used = ccs_memory_quota[i];
15828+ if (used)
15829+ ccs_io_printf(head, " (Quota: %10u)", used);
15830+ ccs_set_lf(head);
15831+ }
15832+ ccs_io_printf(head, "Total memory used: %10u\n",
15833+ total);
15834+ head->r.eof = true;
15835+}
15836+
15837+/**
15838+ * ccs_write_stat - Set memory quota.
15839+ *
15840+ * @head: Pointer to "struct ccs_io_buffer".
15841+ *
15842+ * Returns 0.
15843+ */
15844+static int ccs_write_stat(struct ccs_io_buffer *head)
15845+{
15846+ char *data = head->write_buf;
15847+ u8 i;
15848+ if (ccs_str_starts(&data, "Memory used by "))
15849+ for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
15850+ if (ccs_str_starts(&data, ccs_memory_headers[i])) {
15851+ if (*data == ' ')
15852+ data++;
15853+ ccs_memory_quota[i] =
15854+ simple_strtoul(data, NULL, 10);
15855+ }
15856+ return 0;
15857+}
15858+
15859+/**
15860+ * ccs_print_bprm - Print "struct linux_binprm" for auditing.
15861+ *
15862+ * @bprm: Pointer to "struct linux_binprm".
15863+ * @dump: Pointer to "struct ccs_page_dump".
15864+ *
15865+ * Returns the contents of @bprm on success, NULL otherwise.
15866+ *
15867+ * This function uses kzalloc(), so caller must kfree() if this function
15868+ * didn't return NULL.
15869+ */
15870+static char *ccs_print_bprm(struct linux_binprm *bprm,
15871+ struct ccs_page_dump *dump)
15872+{
15873+ static const int ccs_buffer_len = 4096 * 2;
15874+ char *buffer = kzalloc(ccs_buffer_len, CCS_GFP_FLAGS);
15875+ char *cp;
15876+ char *last_start;
15877+ int len;
15878+ unsigned long pos = bprm->p;
15879+ int offset = pos % PAGE_SIZE;
15880+ int argv_count = bprm->argc;
15881+ int envp_count = bprm->envc;
15882+ bool truncated = false;
15883+ if (!buffer)
15884+ return NULL;
15885+ len = snprintf(buffer, ccs_buffer_len - 1, "argv[]={ ");
15886+ cp = buffer + len;
15887+ if (!argv_count) {
15888+ memmove(cp, "} envp[]={ ", 11);
15889+ cp += 11;
15890+ }
15891+ last_start = cp;
15892+ while (argv_count || envp_count) {
15893+ if (!ccs_dump_page(bprm, pos, dump))
15894+ goto out;
15895+ pos += PAGE_SIZE - offset;
15896+ /* Read. */
15897+ while (offset < PAGE_SIZE) {
15898+ const char *kaddr = dump->data;
15899+ const unsigned char c = kaddr[offset++];
15900+ if (cp == last_start)
15901+ *cp++ = '"';
15902+ if (cp >= buffer + ccs_buffer_len - 32) {
15903+ /* Reserve some room for "..." string. */
15904+ truncated = true;
15905+ } else if (c == '\\') {
15906+ *cp++ = '\\';
15907+ *cp++ = '\\';
15908+ } else if (c > ' ' && c < 127) {
15909+ *cp++ = c;
15910+ } else if (!c) {
15911+ *cp++ = '"';
15912+ *cp++ = ' ';
15913+ last_start = cp;
15914+ } else {
15915+ *cp++ = '\\';
15916+ *cp++ = (c >> 6) + '0';
15917+ *cp++ = ((c >> 3) & 7) + '0';
15918+ *cp++ = (c & 7) + '0';
15919+ }
15920+ if (c)
15921+ continue;
15922+ if (argv_count) {
15923+ if (--argv_count == 0) {
15924+ if (truncated) {
15925+ cp = last_start;
15926+ memmove(cp, "... ", 4);
15927+ cp += 4;
15928+ }
15929+ memmove(cp, "} envp[]={ ", 11);
15930+ cp += 11;
15931+ last_start = cp;
15932+ truncated = false;
15933+ }
15934+ } else if (envp_count) {
15935+ if (--envp_count == 0) {
15936+ if (truncated) {
15937+ cp = last_start;
15938+ memmove(cp, "... ", 4);
15939+ cp += 4;
15940+ }
15941+ }
15942+ }
15943+ if (!argv_count && !envp_count)
15944+ break;
15945+ }
15946+ offset = 0;
15947+ }
15948+ *cp++ = '}';
15949+ *cp = '\0';
15950+ return buffer;
15951+out:
15952+ snprintf(buffer, ccs_buffer_len - 1, "argv[]={ ... } envp[]= { ... }");
15953+ return buffer;
15954+}
15955+
15956+/**
15957+ * ccs_filetype - Get string representation of file type.
15958+ *
15959+ * @mode: Mode value for stat().
15960+ *
15961+ * Returns file type string.
15962+ */
15963+static inline const char *ccs_filetype(const umode_t mode)
15964+{
15965+ switch (mode & S_IFMT) {
15966+ case S_IFREG:
15967+ case 0:
15968+ return ccs_condition_keyword[CCS_TYPE_IS_FILE];
15969+ case S_IFDIR:
15970+ return ccs_condition_keyword[CCS_TYPE_IS_DIRECTORY];
15971+ case S_IFLNK:
15972+ return ccs_condition_keyword[CCS_TYPE_IS_SYMLINK];
15973+ case S_IFIFO:
15974+ return ccs_condition_keyword[CCS_TYPE_IS_FIFO];
15975+ case S_IFSOCK:
15976+ return ccs_condition_keyword[CCS_TYPE_IS_SOCKET];
15977+ case S_IFBLK:
15978+ return ccs_condition_keyword[CCS_TYPE_IS_BLOCK_DEV];
15979+ case S_IFCHR:
15980+ return ccs_condition_keyword[CCS_TYPE_IS_CHAR_DEV];
15981+ }
15982+ return "unknown"; /* This should not happen. */
15983+}
15984+
15985+/**
15986+ * ccs_print_header - Get header line of audit log.
15987+ *
15988+ * @r: Pointer to "struct ccs_request_info".
15989+ *
15990+ * Returns string representation.
15991+ *
15992+ * This function uses kmalloc(), so caller must kfree() if this function
15993+ * didn't return NULL.
15994+ */
15995+static char *ccs_print_header(struct ccs_request_info *r)
15996+{
15997+ struct ccs_time stamp;
15998+ struct ccs_obj_info *obj = r->obj;
15999+ const u32 ccs_flags = ccs_current_flags();
16000+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
16001+ const pid_t gpid = ccs_sys_getpid();
16002+#else
16003+ const pid_t gpid = task_pid_nr(current);
16004+#endif
16005+ static const int ccs_buffer_len = 4096;
16006+ char *buffer = kmalloc(ccs_buffer_len, CCS_GFP_FLAGS);
16007+ int pos;
16008+ u8 i;
16009+ if (!buffer)
16010+ return NULL;
16011+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
16012+ {
16013+ struct timeval tv;
16014+ do_gettimeofday(&tv);
16015+ ccs_convert_time(tv.tv_sec, &stamp);
16016+ }
16017+#else
16018+ ccs_convert_time(get_seconds(), &stamp);
16019+#endif
16020+ pos = snprintf(buffer, ccs_buffer_len - 1,
16021+ "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
16022+ "granted=%s (global-pid=%u) task={ pid=%u ppid=%u "
16023+ "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
16024+ "fsuid=%u fsgid=%u type%s=execute_handler }",
16025+ stamp.year, stamp.month, stamp.day, stamp.hour,
16026+ stamp.min, stamp.sec, r->profile, ccs_mode[r->mode],
16027+ ccs_yesno(r->granted), gpid, ccs_sys_getpid(),
16028+ ccs_sys_getppid(),
16029+ from_kuid(&init_user_ns, current_uid()),
16030+ from_kgid(&init_user_ns, current_gid()),
16031+ from_kuid(&init_user_ns, current_euid()),
16032+ from_kgid(&init_user_ns, current_egid()),
16033+ from_kuid(&init_user_ns, current_suid()),
16034+ from_kgid(&init_user_ns, current_sgid()),
16035+ from_kuid(&init_user_ns, current_fsuid()),
16036+ from_kgid(&init_user_ns, current_fsgid()),
16037+ ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER ? "" : "!");
16038+ if (!obj)
16039+ goto no_obj_info;
16040+ if (!obj->validate_done) {
16041+ ccs_get_attributes(obj);
16042+ obj->validate_done = true;
16043+ }
16044+ for (i = 0; i < CCS_MAX_PATH_STAT; i++) {
16045+ struct ccs_mini_stat *stat;
16046+ unsigned int dev;
16047+ umode_t mode;
16048+ if (!obj->stat_valid[i])
16049+ continue;
16050+ stat = &obj->stat[i];
16051+ dev = stat->dev;
16052+ mode = stat->mode;
16053+ if (i & 1) {
16054+ pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos,
16055+ " path%u.parent={ uid=%u gid=%u "
16056+ "ino=%lu perm=0%o }", (i >> 1) + 1,
16057+ from_kuid(&init_user_ns, stat->uid),
16058+ from_kgid(&init_user_ns, stat->gid),
16059+ (unsigned long) stat->ino,
16060+ stat->mode & S_IALLUGO);
16061+ continue;
16062+ }
16063+ pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos,
16064+ " path%u={ uid=%u gid=%u ino=%lu major=%u"
16065+ " minor=%u perm=0%o type=%s", (i >> 1) + 1,
16066+ from_kuid(&init_user_ns, stat->uid),
16067+ from_kgid(&init_user_ns, stat->gid),
16068+ (unsigned long) stat->ino, MAJOR(dev),
16069+ MINOR(dev), mode & S_IALLUGO,
16070+ ccs_filetype(mode));
16071+ if (S_ISCHR(mode) || S_ISBLK(mode)) {
16072+ dev = stat->rdev;
16073+ pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos,
16074+ " dev_major=%u dev_minor=%u",
16075+ MAJOR(dev), MINOR(dev));
16076+ }
16077+ pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos, " }");
16078+ }
16079+no_obj_info:
16080+ if (pos < ccs_buffer_len - 1)
16081+ return buffer;
16082+ kfree(buffer);
16083+ return NULL;
16084+}
16085+
16086+/**
16087+ * ccs_init_log - Allocate buffer for audit logs.
16088+ *
16089+ * @r: Pointer to "struct ccs_request_info".
16090+ * @len: Buffer size needed for @fmt and @args.
16091+ * @fmt: The printf()'s format string.
16092+ * @args: va_list structure for @fmt.
16093+ *
16094+ * Returns pointer to allocated memory.
16095+ *
16096+ * This function uses kzalloc(), so caller must kfree() if this function
16097+ * didn't return NULL.
16098+ */
16099+static char *ccs_init_log(struct ccs_request_info *r, int len, const char *fmt,
16100+ va_list args)
16101+{
16102+ char *buf = NULL;
16103+ char *bprm_info = NULL;
16104+ char *realpath = NULL;
16105+ const char *symlink = NULL;
16106+ const char *header = NULL;
16107+ int pos;
16108+ const char *domainname = ccs_current_domain()->domainname->name;
16109+ header = ccs_print_header(r);
16110+ if (!header)
16111+ return NULL;
16112+ /* +10 is for '\n' etc. and '\0'. */
16113+ len += strlen(domainname) + strlen(header) + 10;
16114+ if (r->ee) {
16115+ struct file *file = r->ee->bprm->file;
16116+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
16117+ struct path path = { file->f_vfsmnt, file->f_dentry };
16118+ realpath = ccs_realpath(&path);
16119+#else
16120+ realpath = ccs_realpath(&file->f_path);
16121+#endif
16122+ bprm_info = ccs_print_bprm(r->ee->bprm, &r->ee->dump);
16123+ if (!realpath || !bprm_info)
16124+ goto out;
16125+ /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */
16126+ len += strlen(realpath) + 80 + strlen(bprm_info);
16127+ } else if (r->obj && r->obj->symlink_target) {
16128+ symlink = r->obj->symlink_target->name;
16129+ /* +18 is for " symlink.target=\"%s\"" */
16130+ len += 18 + strlen(symlink);
16131+ }
16132+ len = ccs_round2(len);
16133+ buf = kzalloc(len, CCS_GFP_FLAGS);
16134+ if (!buf)
16135+ goto out;
16136+ len--;
16137+ pos = snprintf(buf, len, "%s", header);
16138+ if (realpath) {
16139+ struct linux_binprm *bprm = r->ee->bprm;
16140+ pos += snprintf(buf + pos, len - pos,
16141+ " exec={ realpath=\"%s\" argc=%d envc=%d %s }",
16142+ realpath, bprm->argc, bprm->envc, bprm_info);
16143+ } else if (symlink)
16144+ pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"",
16145+ symlink);
16146+ pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname);
16147+ vsnprintf(buf + pos, len - pos, fmt, args);
16148+out:
16149+ kfree(realpath);
16150+ kfree(bprm_info);
16151+ kfree(header);
16152+ return buf;
16153+}
16154+
16155+/**
16156+ * ccs_transition_failed - Print waning message and send signal when domain transition failed.
16157+ *
16158+ * @domainname: Name of domain to transit.
16159+ *
16160+ * Returns nothing.
16161+ *
16162+ * Note that if current->pid == 1, sending SIGKILL won't work.
16163+ */
16164+void ccs_transition_failed(const char *domainname)
16165+{
16166+ printk(KERN_WARNING
16167+ "ERROR: Unable to transit to '%s' domain.\n", domainname);
16168+ force_sig(SIGKILL, current);
16169+}
16170+
16171+/**
16172+ * ccs_update_task_domain - Update task's domain.
16173+ *
16174+ * @r: Pointer to "struct ccs_request_info".
16175+ *
16176+ * Returns nothing.
16177+ *
16178+ * The task will retry as hard as possible. But if domain transition failed,
16179+ * the task will be killed by SIGKILL.
16180+ */
16181+static void ccs_update_task_domain(struct ccs_request_info *r)
16182+{
16183+ char *buf;
16184+ const char *cp;
16185+ const struct ccs_acl_info *acl = r->matched_acl;
16186+ r->matched_acl = NULL;
16187+ if (!acl || !acl->cond || !acl->cond->transit ||
16188+ acl->cond->exec_transit)
16189+ return;
16190+ while (1) {
16191+ buf = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
16192+ if (buf)
16193+ break;
16194+ ssleep(1);
16195+ if (fatal_signal_pending(current))
16196+ return;
16197+ }
16198+ cp = acl->cond->transit->name;
16199+ if (*cp == '/')
16200+ snprintf(buf, CCS_EXEC_TMPSIZE - 1, "%s %s",
16201+ ccs_current_domain()->domainname->name, cp);
16202+ else
16203+ strncpy(buf, cp, CCS_EXEC_TMPSIZE - 1);
16204+ if (!ccs_assign_domain(buf, true))
16205+ ccs_transition_failed(buf);
16206+ kfree(buf);
16207+}
16208+
16209+/**
16210+ * ccs_get_audit - Get audit mode.
16211+ *
16212+ * @r: Pointer to "struct ccs_request_info".
16213+ *
16214+ * Returns true if this request should be audited, false otherwise.
16215+ */
16216+static bool ccs_get_audit(const struct ccs_request_info *r)
16217+{
16218+ const struct ccs_acl_info *matched_acl = r->matched_acl;
16219+ const u8 profile = r->profile;
16220+ const u8 index = r->type;
16221+ const bool is_granted = r->granted;
16222+ u8 mode;
16223+ struct ccs_profile *p;
16224+ if (!ccs_policy_loaded)
16225+ return false;
16226+ p = ccs_profile(profile);
16227+ if (ccs_log_count >= p->pref[CCS_PREF_MAX_AUDIT_LOG])
16228+ return false;
16229+ if (is_granted && matched_acl && matched_acl->cond &&
16230+ matched_acl->cond->grant_log != CCS_GRANTLOG_AUTO)
16231+ return matched_acl->cond->grant_log == CCS_GRANTLOG_YES;
16232+ mode = p->config[index];
16233+ if (mode == CCS_CONFIG_USE_DEFAULT)
16234+ mode = p->config
16235+ [ccs_index2category[index] + CCS_MAX_MAC_INDEX];
16236+ if (mode == CCS_CONFIG_USE_DEFAULT)
16237+ mode = p->default_config;
16238+ if (is_granted)
16239+ return mode & CCS_CONFIG_WANT_GRANT_LOG;
16240+ return mode & CCS_CONFIG_WANT_REJECT_LOG;
16241+}
16242+
16243+/**
16244+ * ccs_write_log2 - Write an audit log.
16245+ *
16246+ * @r: Pointer to "struct ccs_request_info".
16247+ * @len: Buffer size needed for @fmt and @args.
16248+ * @fmt: The printf()'s format string.
16249+ * @args: va_list structure for @fmt.
16250+ *
16251+ * Returns nothing.
16252+ */
16253+static void ccs_write_log2(struct ccs_request_info *r, int len,
16254+ const char *fmt, va_list args)
16255+{
16256+ char *buf;
16257+ struct ccs_log *entry;
16258+ bool quota_exceeded = false;
16259+ if (!ccs_get_audit(r))
16260+ goto out;
16261+ buf = ccs_init_log(r, len, fmt, args);
16262+ if (!buf)
16263+ goto out;
16264+ entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
16265+ if (!entry) {
16266+ kfree(buf);
16267+ goto out;
16268+ }
16269+ entry->log = buf;
16270+ len = ccs_round2(strlen(buf) + 1);
16271+ /*
16272+ * The entry->size is used for memory quota checks.
16273+ * Don't go beyond strlen(entry->log).
16274+ */
16275+ entry->size = len + ccs_round2(sizeof(*entry));
16276+ spin_lock(&ccs_log_lock);
16277+ if (ccs_memory_quota[CCS_MEMORY_AUDIT] &&
16278+ ccs_memory_used[CCS_MEMORY_AUDIT] + entry->size >=
16279+ ccs_memory_quota[CCS_MEMORY_AUDIT]) {
16280+ quota_exceeded = true;
16281+ } else {
16282+ ccs_memory_used[CCS_MEMORY_AUDIT] += entry->size;
16283+ list_add_tail(&entry->list, &ccs_log);
16284+ ccs_log_count++;
16285+ }
16286+ spin_unlock(&ccs_log_lock);
16287+ if (quota_exceeded) {
16288+ kfree(buf);
16289+ kfree(entry);
16290+ goto out;
16291+ }
16292+ wake_up(&ccs_log_wait);
16293+out:
16294+ ccs_update_task_domain(r);
16295+}
16296+
16297+/**
16298+ * ccs_write_log - Write an audit log.
16299+ *
16300+ * @r: Pointer to "struct ccs_request_info".
16301+ * @fmt: The printf()'s format string, followed by parameters.
16302+ *
16303+ * Returns nothing.
16304+ */
16305+void ccs_write_log(struct ccs_request_info *r, const char *fmt, ...)
16306+{
16307+ va_list args;
16308+ int len;
16309+ va_start(args, fmt);
16310+ len = vsnprintf((char *) &len, 1, fmt, args) + 1;
16311+ va_end(args);
16312+ va_start(args, fmt);
16313+ ccs_write_log2(r, len, fmt, args);
16314+ va_end(args);
16315+}
16316+
16317+/**
16318+ * ccs_read_log - Read an audit log.
16319+ *
16320+ * @head: Pointer to "struct ccs_io_buffer".
16321+ *
16322+ * Returns nothing.
16323+ */
16324+static void ccs_read_log(struct ccs_io_buffer *head)
16325+{
16326+ struct ccs_log *ptr = NULL;
16327+ if (head->r.w_pos)
16328+ return;
16329+ kfree(head->read_buf);
16330+ head->read_buf = NULL;
16331+ spin_lock(&ccs_log_lock);
16332+ if (!list_empty(&ccs_log)) {
16333+ ptr = list_entry(ccs_log.next, typeof(*ptr), list);
16334+ list_del(&ptr->list);
16335+ ccs_log_count--;
16336+ ccs_memory_used[CCS_MEMORY_AUDIT] -= ptr->size;
16337+ }
16338+ spin_unlock(&ccs_log_lock);
16339+ if (ptr) {
16340+ head->read_buf = ptr->log;
16341+ head->r.w[head->r.w_pos++] = head->read_buf;
16342+ kfree(ptr);
16343+ }
16344+}
16345+
16346+/**
16347+ * ccs_set_namespace_cursor - Set namespace to read.
16348+ *
16349+ * @head: Pointer to "struct ccs_io_buffer".
16350+ *
16351+ * Returns nothing.
16352+ */
16353+static void ccs_set_namespace_cursor(struct ccs_io_buffer *head)
16354+{
16355+ struct list_head *ns;
16356+ if (head->type != CCS_EXCEPTION_POLICY && head->type != CCS_PROFILE)
16357+ return;
16358+ /*
16359+ * If this is the first read, or reading previous namespace finished
16360+ * and has more namespaces to read, update the namespace cursor.
16361+ */
16362+ ns = head->r.ns;
16363+ if (!ns || (head->r.eof && ns->next != &ccs_namespace_list)) {
16364+ /* Clearing is OK because ccs_flush() returned true. */
16365+ memset(&head->r, 0, sizeof(head->r));
16366+ head->r.ns = ns ? ns->next : ccs_namespace_list.next;
16367+ }
16368+}
16369+
16370+/**
16371+ * ccs_has_more_namespace - Check for unread namespaces.
16372+ *
16373+ * @head: Pointer to "struct ccs_io_buffer".
16374+ *
16375+ * Returns true if we have more entries to print, false otherwise.
16376+ */
16377+static bool ccs_has_more_namespace(struct ccs_io_buffer *head)
16378+{
16379+ return (head->type == CCS_EXCEPTION_POLICY ||
16380+ head->type == CCS_PROFILE) && head->r.eof &&
16381+ head->r.ns->next != &ccs_namespace_list;
16382+}
16383+
16384+/**
16385+ * ccs_find_namespace - Find specified namespace.
16386+ *
16387+ * @name: Name of namespace to find.
16388+ * @len: Length of @name.
16389+ *
16390+ * Returns pointer to "struct ccs_policy_namespace" if found, NULL otherwise.
16391+ *
16392+ * Caller holds ccs_read_lock().
16393+ */
16394+static struct ccs_policy_namespace *ccs_find_namespace(const char *name,
16395+ const unsigned int len)
16396+{
16397+ struct ccs_policy_namespace *ns;
16398+ list_for_each_entry_srcu(ns, &ccs_namespace_list, namespace_list,
16399+ &ccs_ss) {
16400+ if (strncmp(name, ns->name, len) ||
16401+ (name[len] && name[len] != ' '))
16402+ continue;
16403+ return ns;
16404+ }
16405+ return NULL;
16406+}
16407+
16408+/**
16409+ * ccs_assign_namespace - Create a new namespace.
16410+ *
16411+ * @domainname: Name of namespace to create.
16412+ *
16413+ * Returns pointer to "struct ccs_policy_namespace" on success, NULL otherwise.
16414+ *
16415+ * Caller holds ccs_read_lock().
16416+ */
16417+static struct ccs_policy_namespace *ccs_assign_namespace
16418+(const char *domainname)
16419+{
16420+ struct ccs_policy_namespace *ptr;
16421+ struct ccs_policy_namespace *entry;
16422+ const char *cp = domainname;
16423+ unsigned int len = 0;
16424+ while (*cp && *cp++ != ' ')
16425+ len++;
16426+ ptr = ccs_find_namespace(domainname, len);
16427+ if (ptr)
16428+ return ptr;
16429+ if (len >= CCS_EXEC_TMPSIZE - 10 || !ccs_domain_def(domainname))
16430+ return NULL;
16431+ entry = kzalloc(sizeof(*entry) + len + 1, CCS_GFP_FLAGS);
16432+ if (!entry)
16433+ return NULL;
16434+ if (mutex_lock_interruptible(&ccs_policy_lock))
16435+ goto out;
16436+ ptr = ccs_find_namespace(domainname, len);
16437+ if (!ptr && ccs_memory_ok(entry, sizeof(*entry) + len + 1)) {
16438+ char *name = (char *) (entry + 1);
16439+ ptr = entry;
16440+ memmove(name, domainname, len);
16441+ name[len] = '\0';
16442+ entry->name = name;
16443+ ccs_init_policy_namespace(entry);
16444+ entry = NULL;
16445+ }
16446+ mutex_unlock(&ccs_policy_lock);
16447+out:
16448+ kfree(entry);
16449+ return ptr;
16450+}
16451+
16452+/**
16453+ * ccs_namespace_jump - Check for namespace jump.
16454+ *
16455+ * @domainname: Name of domain.
16456+ *
16457+ * Returns true if namespace differs, false otherwise.
16458+ */
16459+static bool ccs_namespace_jump(const char *domainname)
16460+{
16461+ const char *namespace = ccs_current_namespace()->name;
16462+ const int len = strlen(namespace);
16463+ return strncmp(domainname, namespace, len) ||
16464+ (domainname[len] && domainname[len] != ' ');
16465+}
16466+
16467+/**
16468+ * ccs_assign_domain - Create a domain or a namespace.
16469+ *
16470+ * @domainname: The name of domain.
16471+ * @transit: True if transit to domain found or created.
16472+ *
16473+ * Returns pointer to "struct ccs_domain_info" on success, NULL otherwise.
16474+ *
16475+ * Caller holds ccs_read_lock().
16476+ */
16477+struct ccs_domain_info *ccs_assign_domain(const char *domainname,
16478+ const bool transit)
16479+{
16480+ struct ccs_security *security = ccs_current_security();
16481+ struct ccs_domain_info e = { };
16482+ struct ccs_domain_info *entry = ccs_find_domain(domainname);
16483+ bool created = false;
16484+ if (entry) {
16485+ if (transit) {
16486+ /*
16487+ * Since namespace is created at runtime, profiles may
16488+ * not be created by the moment the process transits to
16489+ * that domain. Do not perform domain transition if
16490+ * profile for that domain is not yet created.
16491+ */
16492+ if (ccs_policy_loaded &&
16493+ !entry->ns->profile_ptr[entry->profile])
16494+ return NULL;
16495+ security->ccs_domain_info = entry;
16496+ }
16497+ return entry;
16498+ }
16499+ /* Requested domain does not exist. */
16500+ /* Don't create requested domain if domainname is invalid. */
16501+ if (strlen(domainname) >= CCS_EXEC_TMPSIZE - 10 ||
16502+ !ccs_correct_domain(domainname))
16503+ return NULL;
16504+ /*
16505+ * Since definition of profiles and acl_groups may differ across
16506+ * namespaces, do not inherit "use_profile" and "use_group" settings
16507+ * by automatically creating requested domain upon domain transition.
16508+ */
16509+ if (transit && ccs_namespace_jump(domainname))
16510+ return NULL;
16511+ e.ns = ccs_assign_namespace(domainname);
16512+ if (!e.ns)
16513+ return NULL;
16514+ /*
16515+ * "use_profile" and "use_group" settings for automatically created
16516+ * domains are inherited from current domain. These are 0 for manually
16517+ * created domains.
16518+ */
16519+ if (transit) {
16520+ const struct ccs_domain_info *domain =
16521+ security->ccs_domain_info;
16522+ e.profile = domain->profile;
16523+ memcpy(e.group, domain->group, sizeof(e.group));
16524+ }
16525+ e.domainname = ccs_get_name(domainname);
16526+ if (!e.domainname)
16527+ return NULL;
16528+ if (mutex_lock_interruptible(&ccs_policy_lock))
16529+ goto out;
16530+ entry = ccs_find_domain(domainname);
16531+ if (!entry) {
16532+ entry = ccs_commit_ok(&e, sizeof(e));
16533+ if (entry) {
16534+ INIT_LIST_HEAD(&entry->acl_info_list);
16535+ list_add_tail_rcu(&entry->list, &ccs_domain_list);
16536+ created = true;
16537+ }
16538+ }
16539+ mutex_unlock(&ccs_policy_lock);
16540+out:
16541+ ccs_put_name(e.domainname);
16542+ if (entry && transit) {
16543+ security->ccs_domain_info = entry;
16544+ if (created) {
16545+ struct ccs_request_info r;
16546+ int i;
16547+ ccs_init_request_info(&r, CCS_MAC_FILE_EXECUTE);
16548+ r.granted = false;
16549+ ccs_write_log(&r, "use_profile %u\n", entry->profile);
16550+ for (i = 0; i < CCS_MAX_ACL_GROUPS; i++)
16551+ if (test_bit(i, entry->group))
16552+ ccs_write_log(&r, "use_group %u\n", i);
16553+ ccs_update_stat(CCS_STAT_POLICY_UPDATES);
16554+ }
16555+ }
16556+ return entry;
16557+}
16558+
16559+/**
16560+ * ccs_parse_policy - Parse a policy line.
16561+ *
16562+ * @head: Poiter to "struct ccs_io_buffer".
16563+ * @line: Line to parse.
16564+ *
16565+ * Returns 0 on success, negative value otherwise.
16566+ *
16567+ * Caller holds ccs_read_lock().
16568+ */
16569+static int ccs_parse_policy(struct ccs_io_buffer *head, char *line)
16570+{
16571+ /* Delete request? */
16572+ head->w.is_delete = !strncmp(line, "delete ", 7);
16573+ if (head->w.is_delete)
16574+ memmove(line, line + 7, strlen(line + 7) + 1);
16575+ /* Selecting namespace to update. */
16576+ if (head->type == CCS_EXCEPTION_POLICY || head->type == CCS_PROFILE) {
16577+ if (*line == '<') {
16578+ char *cp = strchr(line, ' ');
16579+ if (cp) {
16580+ *cp++ = '\0';
16581+ head->w.ns = ccs_assign_namespace(line);
16582+ memmove(line, cp, strlen(cp) + 1);
16583+ } else
16584+ head->w.ns = NULL;
16585+ } else
16586+ head->w.ns = &ccs_kernel_namespace;
16587+ /* Don't allow updating if namespace is invalid. */
16588+ if (!head->w.ns)
16589+ return -ENOENT;
16590+ }
16591+ /* Do the update. */
16592+ switch (head->type) {
16593+ case CCS_DOMAIN_POLICY:
16594+ return ccs_write_domain(head);
16595+ case CCS_EXCEPTION_POLICY:
16596+ return ccs_write_exception(head);
16597+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
16598+ case CCS_EXECUTE_HANDLER:
16599+#endif
16600+ case CCS_PROCESS_STATUS:
16601+ return ccs_write_pid(head);
16602+ case CCS_STAT:
16603+ return ccs_write_stat(head);
16604+ case CCS_PROFILE:
16605+ return ccs_write_profile(head);
16606+ case CCS_QUERY:
16607+ return ccs_write_answer(head);
16608+ case CCS_MANAGER:
16609+ return ccs_write_manager(head);
16610+ default:
16611+ return -ENOSYS;
16612+ }
16613+}
16614+
16615+/**
16616+ * ccs_policy_io_init - Register hooks for policy I/O.
16617+ *
16618+ * Returns nothing.
16619+ */
16620+static void __init ccs_policy_io_init(void)
16621+{
16622+ ccsecurity_ops.check_profile = ccs_check_profile;
16623+}
16624+
16625+/**
16626+ * ccs_load_builtin_policy - Load built-in policy.
16627+ *
16628+ * Returns nothing.
16629+ */
16630+static void __init ccs_load_builtin_policy(void)
16631+{
16632+ /*
16633+ * This include file is manually created and contains built-in policy
16634+ * named "ccs_builtin_profile", "ccs_builtin_exception_policy",
16635+ * "ccs_builtin_domain_policy", "ccs_builtin_manager",
16636+ * "ccs_builtin_stat" in the form of "static char [] __initdata".
16637+ */
16638+#include "builtin-policy.h"
16639+ u8 i;
16640+ const int idx = ccs_read_lock();
16641+ for (i = 0; i < 5; i++) {
16642+ struct ccs_io_buffer head = { };
16643+ char *start = "";
16644+ switch (i) {
16645+ case 0:
16646+ start = ccs_builtin_profile;
16647+ head.type = CCS_PROFILE;
16648+ break;
16649+ case 1:
16650+ start = ccs_builtin_exception_policy;
16651+ head.type = CCS_EXCEPTION_POLICY;
16652+ break;
16653+ case 2:
16654+ start = ccs_builtin_domain_policy;
16655+ head.type = CCS_DOMAIN_POLICY;
16656+ break;
16657+ case 3:
16658+ start = ccs_builtin_manager;
16659+ head.type = CCS_MANAGER;
16660+ break;
16661+ case 4:
16662+ start = ccs_builtin_stat;
16663+ head.type = CCS_STAT;
16664+ break;
16665+ }
16666+ while (1) {
16667+ char *end = strchr(start, '\n');
16668+ if (!end)
16669+ break;
16670+ *end = '\0';
16671+ ccs_normalize_line(start);
16672+ head.write_buf = start;
16673+ ccs_parse_policy(&head, start);
16674+ start = end + 1;
16675+ }
16676+ }
16677+ ccs_read_unlock(idx);
16678+#ifdef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
16679+ ccs_check_profile();
16680+#endif
16681+}
16682+
16683+/**
16684+ * ccs_read_self - read() for /proc/ccs/self_domain interface.
16685+ *
16686+ * @file: Pointer to "struct file".
16687+ * @buf: Domainname which current thread belongs to.
16688+ * @count: Size of @buf.
16689+ * @ppos: Bytes read by now.
16690+ *
16691+ * Returns read size on success, negative value otherwise.
16692+ */
16693+static ssize_t ccs_read_self(struct file *file, char __user *buf, size_t count,
16694+ loff_t *ppos)
16695+{
16696+ const char *domain = ccs_current_domain()->domainname->name;
16697+ loff_t len = strlen(domain);
16698+ loff_t pos = *ppos;
16699+ if (pos >= len || !count)
16700+ return 0;
16701+ len -= pos;
16702+ if (count < len)
16703+ len = count;
16704+ if (copy_to_user(buf, domain + pos, len))
16705+ return -EFAULT;
16706+ *ppos += len;
16707+ return len;
16708+}
16709+
16710+/**
16711+ * ccs_open - open() for /proc/ccs/ interface.
16712+ *
16713+ * @inode: Pointer to "struct inode".
16714+ * @file: Pointer to "struct file".
16715+ *
16716+ * Returns 0 on success, negative value otherwise.
16717+ */
16718+static int ccs_open(struct inode *inode, struct file *file)
16719+{
16720+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
16721+ const u8 type = (unsigned long) PDE_DATA(inode);
16722+#else
16723+ const u8 type = (unsigned long) PDE(inode)->data;
16724+#endif
16725+ struct ccs_io_buffer *head = kzalloc(sizeof(*head), CCS_GFP_FLAGS);
16726+ if (!head)
16727+ return -ENOMEM;
16728+ mutex_init(&head->io_sem);
16729+ head->type = type;
16730+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
16731+ if (type == CCS_EXECUTE_HANDLER) {
16732+ /* Allow execute_handler to read process's status. */
16733+ if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {
16734+ kfree(head);
16735+ return -EPERM;
16736+ }
16737+ }
16738+#endif
16739+ if ((file->f_mode & FMODE_READ) && type != CCS_AUDIT &&
16740+ type != CCS_QUERY) {
16741+ /* Don't allocate read_buf for poll() access. */
16742+ head->readbuf_size = 4096;
16743+ head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);
16744+ if (!head->read_buf) {
16745+ kfree(head);
16746+ return -ENOMEM;
16747+ }
16748+ }
16749+ if (file->f_mode & FMODE_WRITE) {
16750+ head->writebuf_size = 4096;
16751+ head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);
16752+ if (!head->write_buf) {
16753+ kfree(head->read_buf);
16754+ kfree(head);
16755+ return -ENOMEM;
16756+ }
16757+ }
16758+ /*
16759+ * If the file is /proc/ccs/query, increment the observer counter.
16760+ * The obserber counter is used by ccs_supervisor() to see if
16761+ * there is some process monitoring /proc/ccs/query.
16762+ */
16763+ if (type == CCS_QUERY)
16764+ atomic_inc(&ccs_query_observers);
16765+ file->private_data = head;
16766+ ccs_notify_gc(head, true);
16767+ return 0;
16768+}
16769+
16770+/**
16771+ * ccs_release - close() for /proc/ccs/ interface.
16772+ *
16773+ * @inode: Pointer to "struct inode".
16774+ * @file: Pointer to "struct file".
16775+ *
16776+ * Returns 0.
16777+ */
16778+static int ccs_release(struct inode *inode, struct file *file)
16779+{
16780+ struct ccs_io_buffer *head = file->private_data;
16781+ /*
16782+ * If the file is /proc/ccs/query, decrement the observer counter.
16783+ */
16784+ if (head->type == CCS_QUERY &&
16785+ atomic_dec_and_test(&ccs_query_observers))
16786+ wake_up_all(&ccs_answer_wait);
16787+ ccs_notify_gc(head, false);
16788+ return 0;
16789+}
16790+
16791+/**
16792+ * ccs_poll - poll() for /proc/ccs/ interface.
16793+ *
16794+ * @file: Pointer to "struct file".
16795+ * @wait: Pointer to "poll_table". Maybe NULL.
16796+ *
16797+ * Returns POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM if ready to read/write,
16798+ * POLLOUT | POLLWRNORM otherwise.
16799+ */
16800+static unsigned int ccs_poll(struct file *file, poll_table *wait)
16801+{
16802+ struct ccs_io_buffer *head = file->private_data;
16803+ if (head->type == CCS_AUDIT) {
16804+ if (!ccs_memory_used[CCS_MEMORY_AUDIT]) {
16805+ poll_wait(file, &ccs_log_wait, wait);
16806+ if (!ccs_memory_used[CCS_MEMORY_AUDIT])
16807+ return POLLOUT | POLLWRNORM;
16808+ }
16809+ } else if (head->type == CCS_QUERY) {
16810+ if (list_empty(&ccs_query_list)) {
16811+ poll_wait(file, &ccs_query_wait, wait);
16812+ if (list_empty(&ccs_query_list))
16813+ return POLLOUT | POLLWRNORM;
16814+ }
16815+ }
16816+ return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
16817+}
16818+
16819+/**
16820+ * ccs_read - read() for /proc/ccs/ interface.
16821+ *
16822+ * @file: Pointer to "struct file".
16823+ * @buf: Pointer to buffer.
16824+ * @count: Size of @buf.
16825+ * @ppos: Unused.
16826+ *
16827+ * Returns bytes read on success, negative value otherwise.
16828+ */
16829+static ssize_t ccs_read(struct file *file, char __user *buf, size_t count,
16830+ loff_t *ppos)
16831+{
16832+ struct ccs_io_buffer *head = file->private_data;
16833+ int len;
16834+ int idx;
16835+ if (mutex_lock_interruptible(&head->io_sem))
16836+ return -EINTR;
16837+ head->read_user_buf = buf;
16838+ head->read_user_buf_avail = count;
16839+ idx = ccs_read_lock();
16840+ if (ccs_flush(head))
16841+ /* Call the policy handler. */
16842+ do {
16843+ ccs_set_namespace_cursor(head);
16844+ switch (head->type) {
16845+ case CCS_DOMAIN_POLICY:
16846+ ccs_read_domain(head);
16847+ break;
16848+ case CCS_EXCEPTION_POLICY:
16849+ ccs_read_exception(head);
16850+ break;
16851+ case CCS_AUDIT:
16852+ ccs_read_log(head);
16853+ break;
16854+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
16855+ case CCS_EXECUTE_HANDLER:
16856+#endif
16857+ case CCS_PROCESS_STATUS:
16858+ ccs_read_pid(head);
16859+ break;
16860+ case CCS_VERSION:
16861+ ccs_read_version(head);
16862+ break;
16863+ case CCS_STAT:
16864+ ccs_read_stat(head);
16865+ break;
16866+ case CCS_PROFILE:
16867+ ccs_read_profile(head);
16868+ break;
16869+ case CCS_QUERY:
16870+ ccs_read_query(head);
16871+ break;
16872+ case CCS_MANAGER:
16873+ ccs_read_manager(head);
16874+ break;
16875+ }
16876+ } while (ccs_flush(head) && ccs_has_more_namespace(head));
16877+ ccs_read_unlock(idx);
16878+ len = head->read_user_buf - buf;
16879+ mutex_unlock(&head->io_sem);
16880+ return len;
16881+}
16882+
16883+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
16884+
16885+/**
16886+ * ccs_write_self - write() for /proc/ccs/self_domain interface.
16887+ *
16888+ * @file: Pointer to "struct file".
16889+ * @buf: Domainname to transit to.
16890+ * @count: Size of @buf.
16891+ * @ppos: Unused.
16892+ *
16893+ * Returns @count on success, negative value otherwise.
16894+ *
16895+ * If domain transition was permitted but the domain transition failed, this
16896+ * function returns error rather than terminating current thread with SIGKILL.
16897+ */
16898+static ssize_t ccs_write_self(struct file *file, const char __user *buf,
16899+ size_t count, loff_t *ppos)
16900+{
16901+ char *data;
16902+ int error;
16903+ if (!count || count >= CCS_EXEC_TMPSIZE - 10)
16904+ return -ENOMEM;
16905+ data = kzalloc(count + 1, CCS_GFP_FLAGS);
16906+ if (!data)
16907+ return -ENOMEM;
16908+ if (copy_from_user(data, buf, count)) {
16909+ error = -EFAULT;
16910+ goto out;
16911+ }
16912+ ccs_normalize_line(data);
16913+ if (ccs_correct_domain(data)) {
16914+ const int idx = ccs_read_lock();
16915+ struct ccs_path_info name;
16916+ struct ccs_request_info r;
16917+ name.name = data;
16918+ ccs_fill_path_info(&name);
16919+ /* Check "task manual_domain_transition" permission. */
16920+ ccs_init_request_info(&r, CCS_MAC_FILE_EXECUTE);
16921+ r.param_type = CCS_TYPE_MANUAL_TASK_ACL;
16922+ r.param.task.domainname = &name;
16923+ ccs_check_acl(&r);
16924+ if (!r.granted)
16925+ error = -EPERM;
16926+ else
16927+ error = ccs_assign_domain(data, true) ? 0 : -ENOENT;
16928+ ccs_read_unlock(idx);
16929+ } else
16930+ error = -EINVAL;
16931+out:
16932+ kfree(data);
16933+ return error ? error : count;
16934+}
16935+
16936+#endif
16937+
16938+/**
16939+ * ccs_write - write() for /proc/ccs/ interface.
16940+ *
16941+ * @file: Pointer to "struct file".
16942+ * @buf: Pointer to buffer.
16943+ * @count: Size of @buf.
16944+ * @ppos: Unused.
16945+ *
16946+ * Returns @count on success, negative value otherwise.
16947+ */
16948+static ssize_t ccs_write(struct file *file, const char __user *buf,
16949+ size_t count, loff_t *ppos)
16950+{
16951+ struct ccs_io_buffer *head = file->private_data;
16952+ int error = count;
16953+ char *cp0 = head->write_buf;
16954+ int idx;
16955+ if (mutex_lock_interruptible(&head->io_sem))
16956+ return -EINTR;
16957+ head->read_user_buf_avail = 0;
16958+ idx = ccs_read_lock();
16959+ /* Read a line and dispatch it to the policy handler. */
16960+ while (count) {
16961+ char c;
16962+ if (head->w.avail >= head->writebuf_size - 1) {
16963+ const int len = head->writebuf_size * 2;
16964+ char *cp = kzalloc(len, CCS_GFP_FLAGS);
16965+ if (!cp) {
16966+ error = -ENOMEM;
16967+ break;
16968+ }
16969+ memmove(cp, cp0, head->w.avail);
16970+ kfree(cp0);
16971+ head->write_buf = cp;
16972+ cp0 = cp;
16973+ head->writebuf_size = len;
16974+ }
16975+ if (get_user(c, buf)) {
16976+ error = -EFAULT;
16977+ break;
16978+ }
16979+ buf++;
16980+ count--;
16981+ cp0[head->w.avail++] = c;
16982+ if (c != '\n')
16983+ continue;
16984+ cp0[head->w.avail - 1] = '\0';
16985+ head->w.avail = 0;
16986+ ccs_normalize_line(cp0);
16987+ if (!strcmp(cp0, "reset")) {
16988+ head->w.ns = &ccs_kernel_namespace;
16989+ head->w.domain = NULL;
16990+ memset(&head->r, 0, sizeof(head->r));
16991+ continue;
16992+ }
16993+ /* Don't allow updating policies by non manager programs. */
16994+ switch (head->type) {
16995+ case CCS_PROCESS_STATUS:
16996+ /* This does not write anything. */
16997+ break;
16998+ case CCS_DOMAIN_POLICY:
16999+ if (ccs_select_domain(head, cp0))
17000+ continue;
17001+ /* fall through */
17002+ case CCS_EXCEPTION_POLICY:
17003+ if (!strcmp(cp0, "select transition_only")) {
17004+ head->r.print_transition_related_only = true;
17005+ continue;
17006+ }
17007+ /* fall through */
17008+ default:
17009+ if (!ccs_manager()) {
17010+ error = -EPERM;
17011+ goto out;
17012+ }
17013+ }
17014+ switch (ccs_parse_policy(head, cp0)) {
17015+ case -EPERM:
17016+ error = -EPERM;
17017+ goto out;
17018+ case 0:
17019+ /* Update statistics. */
17020+ switch (head->type) {
17021+ case CCS_DOMAIN_POLICY:
17022+ case CCS_EXCEPTION_POLICY:
17023+ case CCS_STAT:
17024+ case CCS_PROFILE:
17025+ case CCS_MANAGER:
17026+ ccs_update_stat(CCS_STAT_POLICY_UPDATES);
17027+ break;
17028+ default:
17029+ break;
17030+ }
17031+ break;
17032+ }
17033+ }
17034+out:
17035+ ccs_read_unlock(idx);
17036+ mutex_unlock(&head->io_sem);
17037+ return error;
17038+}
17039+
17040+/**
17041+ * ccs_create_entry - Create interface files under /proc/ccs/ directory.
17042+ *
17043+ * @name: The name of the interface file.
17044+ * @mode: The permission of the interface file.
17045+ * @parent: The parent directory.
17046+ * @key: Type of interface.
17047+ *
17048+ * Returns nothing.
17049+ */
17050+static void __init ccs_create_entry(const char *name, const umode_t mode,
17051+ struct proc_dir_entry *parent,
17052+ const u8 key)
17053+{
17054+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
17055+ proc_create_data(name, mode, parent, &ccs_operations,
17056+ ((u8 *) NULL) + key);
17057+#else
17058+ struct proc_dir_entry *entry = create_proc_entry(name, mode, parent);
17059+ if (entry) {
17060+ entry->proc_fops = &ccs_operations;
17061+ entry->data = ((u8 *) NULL) + key;
17062+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
17063+ if (entry->proc_iops)
17064+ ccs_file_inode_operations = *entry->proc_iops;
17065+ if (!ccs_file_inode_operations.setattr)
17066+ ccs_file_inode_operations.setattr = proc_notify_change;
17067+ entry->proc_iops = &ccs_file_inode_operations;
17068+#endif
17069+ }
17070+#endif
17071+}
17072+
17073+/**
17074+ * ccs_proc_init - Initialize /proc/ccs/ interface.
17075+ *
17076+ * Returns nothing.
17077+ */
17078+static void __init ccs_proc_init(void)
17079+{
17080+ struct proc_dir_entry *ccs_dir = proc_mkdir("ccs", NULL);
17081+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
17082+ if (ccs_dir->proc_iops)
17083+ ccs_dir_inode_operations = *ccs_dir->proc_iops;
17084+ if (!ccs_dir_inode_operations.setattr)
17085+ ccs_dir_inode_operations.setattr = proc_notify_change;
17086+ ccs_dir->proc_iops = &ccs_dir_inode_operations;
17087+#endif
17088+ ccs_create_entry("query", 0600, ccs_dir, CCS_QUERY);
17089+ ccs_create_entry("domain_policy", 0600, ccs_dir, CCS_DOMAIN_POLICY);
17090+ ccs_create_entry("exception_policy", 0600, ccs_dir,
17091+ CCS_EXCEPTION_POLICY);
17092+ ccs_create_entry("audit", 0400, ccs_dir, CCS_AUDIT);
17093+ ccs_create_entry(".process_status", 0600, ccs_dir,
17094+ CCS_PROCESS_STATUS);
17095+ ccs_create_entry("stat", 0644, ccs_dir, CCS_STAT);
17096+ ccs_create_entry("profile", 0600, ccs_dir, CCS_PROFILE);
17097+ ccs_create_entry("manager", 0600, ccs_dir, CCS_MANAGER);
17098+ ccs_create_entry("version", 0400, ccs_dir, CCS_VERSION);
17099+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
17100+ ccs_create_entry(".execute_handler", 0666, ccs_dir,
17101+ CCS_EXECUTE_HANDLER);
17102+#endif
17103+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
17104+ proc_create("self_domain", 0666, ccs_dir, &ccs_self_operations);
17105+#else
17106+ {
17107+ struct proc_dir_entry *e = create_proc_entry("self_domain",
17108+ 0666, ccs_dir);
17109+ if (e)
17110+ e->proc_fops = &ccs_self_operations;
17111+ }
17112+#endif
17113+}
17114+
17115+/**
17116+ * ccs_init_module - Initialize this module.
17117+ *
17118+ * Returns 0 on success, negative value otherwise.
17119+ */
17120+static int __init ccs_init_module(void)
17121+{
17122+ if (ccsecurity_ops.disabled)
17123+ return -EINVAL;
17124+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
17125+ MOD_INC_USE_COUNT;
17126+#endif
17127+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
17128+ if (init_srcu_struct(&ccs_ss))
17129+ panic("Out of memory.");
17130+#endif
17131+ ccs_kernel_namespace.name = "<kernel>";
17132+ ccs_init_policy_namespace(&ccs_kernel_namespace);
17133+ ccs_kernel_domain.ns = &ccs_kernel_namespace;
17134+ INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
17135+ ccs_mm_init();
17136+ ccs_policy_io_init();
17137+ ccs_permission_init();
17138+ ccs_proc_init();
17139+ ccs_load_builtin_policy();
17140+ return 0;
17141+}
17142+
17143+MODULE_LICENSE("GPL");
17144+module_init(ccs_init_module);
17145diff --git a/security/ccsecurity/realpath.c b/security/ccsecurity/realpath.c
17146new file mode 100644
17147index 0000000..df821ed
17148--- /dev/null
17149+++ b/security/ccsecurity/realpath.c
17150@@ -0,0 +1,767 @@
17151+/*
17152+ * security/ccsecurity/realpath.c
17153+ *
17154+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
17155+ *
17156+ * Version: 1.8.4 2015/05/05
17157+ */
17158+
17159+#include "internal.h"
17160+
17161+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
17162+#include <linux/nsproxy.h>
17163+#include <linux/mnt_namespace.h>
17164+#endif
17165+
17166+/***** SECTION1: Constants definition *****/
17167+
17168+#define SOCKFS_MAGIC 0x534F434B
17169+
17170+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
17171+#define s_fs_info u.generic_sbp
17172+#endif
17173+
17174+/***** SECTION2: Structure definition *****/
17175+
17176+/***** SECTION3: Prototype definition section *****/
17177+
17178+char *ccs_encode(const char *str);
17179+char *ccs_encode2(const char *str, int str_len);
17180+char *ccs_realpath(const struct path *path);
17181+const char *ccs_get_exe(void);
17182+void ccs_fill_path_info(struct ccs_path_info *ptr);
17183+
17184+static char *ccs_get_absolute_path(const struct path *path,
17185+ char * const buffer, const int buflen);
17186+static char *ccs_get_dentry_path(struct dentry *dentry, char * const buffer,
17187+ const int buflen);
17188+static char *ccs_get_local_path(struct dentry *dentry, char * const buffer,
17189+ const int buflen);
17190+static char *ccs_get_socket_name(const struct path *path, char * const buffer,
17191+ const int buflen);
17192+static int ccs_const_part_length(const char *filename);
17193+
17194+/***** SECTION4: Standalone functions section *****/
17195+
17196+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
17197+
17198+/**
17199+ * SOCKET_I - Get "struct socket".
17200+ *
17201+ * @inode: Pointer to "struct inode".
17202+ *
17203+ * Returns pointer to "struct socket".
17204+ *
17205+ * This is for compatibility with older kernels.
17206+ */
17207+static inline struct socket *SOCKET_I(struct inode *inode)
17208+{
17209+ return inode->i_sock ? &inode->u.socket_i : NULL;
17210+}
17211+
17212+#endif
17213+
17214+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
17215+
17216+/**
17217+ * ccs_realpath_lock - Take locks for __d_path().
17218+ *
17219+ * Returns nothing.
17220+ */
17221+static inline void ccs_realpath_lock(void)
17222+{
17223+ /* dcache_lock is locked by __d_path(). */
17224+ /* vfsmount_lock is locked by __d_path(). */
17225+}
17226+
17227+/**
17228+ * ccs_realpath_unlock - Release locks for __d_path().
17229+ *
17230+ * Returns nothing.
17231+ */
17232+static inline void ccs_realpath_unlock(void)
17233+{
17234+ /* vfsmount_lock is unlocked by __d_path(). */
17235+ /* dcache_lock is unlocked by __d_path(). */
17236+}
17237+
17238+#elif LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 36)
17239+
17240+/**
17241+ * ccs_realpath_lock - Take locks for __d_path().
17242+ *
17243+ * Returns nothing.
17244+ */
17245+static inline void ccs_realpath_lock(void)
17246+{
17247+ spin_lock(&dcache_lock);
17248+ /* vfsmount_lock is locked by __d_path(). */
17249+}
17250+
17251+/**
17252+ * ccs_realpath_unlock - Release locks for __d_path().
17253+ *
17254+ * Returns nothing.
17255+ */
17256+static inline void ccs_realpath_unlock(void)
17257+{
17258+ /* vfsmount_lock is unlocked by __d_path(). */
17259+ spin_unlock(&dcache_lock);
17260+}
17261+
17262+#elif defined(D_PATH_DISCONNECT) && !defined(CONFIG_SUSE_KERNEL)
17263+
17264+/**
17265+ * ccs_realpath_lock - Take locks for __d_path().
17266+ *
17267+ * Returns nothing.
17268+ *
17269+ * Original unambiguous-__d_path.diff in patches.apparmor.tar.bz2 inversed the
17270+ * order of holding dcache_lock and vfsmount_lock. That patch was applied on
17271+ * (at least) SUSE 11.1 and Ubuntu 8.10 and Ubuntu 9.04 kernels.
17272+ *
17273+ * However, that patch was updated to use original order and the updated patch
17274+ * is applied to (as far as I know) only SUSE kernels.
17275+ *
17276+ * Therefore, I need to use original order for SUSE 11.1 kernels and inversed
17277+ * order for other kernels. I detect it by checking D_PATH_DISCONNECT and
17278+ * CONFIG_SUSE_KERNEL. I don't know whether other distributions are using the
17279+ * updated patch or not. If you got deadlock, check fs/dcache.c for locking
17280+ * order, and add " && 0" to this "#elif " block if fs/dcache.c uses original
17281+ * order.
17282+ */
17283+static inline void ccs_realpath_lock(void)
17284+{
17285+ spin_lock(ccsecurity_exports.vfsmount_lock);
17286+ spin_lock(&dcache_lock);
17287+}
17288+
17289+/**
17290+ * ccs_realpath_unlock - Release locks for __d_path().
17291+ *
17292+ * Returns nothing.
17293+ */
17294+static inline void ccs_realpath_unlock(void)
17295+{
17296+ spin_unlock(&dcache_lock);
17297+ spin_unlock(ccsecurity_exports.vfsmount_lock);
17298+}
17299+
17300+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
17301+
17302+/**
17303+ * ccs_realpath_lock - Take locks for __d_path().
17304+ *
17305+ * Returns nothing.
17306+ */
17307+static inline void ccs_realpath_lock(void)
17308+{
17309+ spin_lock(&dcache_lock);
17310+ spin_lock(ccsecurity_exports.vfsmount_lock);
17311+}
17312+
17313+/**
17314+ * ccs_realpath_unlock - Release locks for __d_path().
17315+ *
17316+ * Returns nothing.
17317+ */
17318+static inline void ccs_realpath_unlock(void)
17319+{
17320+ spin_unlock(ccsecurity_exports.vfsmount_lock);
17321+ spin_unlock(&dcache_lock);
17322+}
17323+
17324+#else
17325+
17326+/**
17327+ * ccs_realpath_lock - Take locks for __d_path().
17328+ *
17329+ * Returns nothing.
17330+ */
17331+static inline void ccs_realpath_lock(void)
17332+{
17333+ spin_lock(&dcache_lock);
17334+}
17335+
17336+/**
17337+ * ccs_realpath_unlock - Release locks for __d_path().
17338+ *
17339+ * Returns nothing.
17340+ */
17341+static inline void ccs_realpath_unlock(void)
17342+{
17343+ spin_unlock(&dcache_lock);
17344+}
17345+
17346+#endif
17347+
17348+/***** SECTION5: Variables definition section *****/
17349+
17350+/***** SECTION6: Dependent functions section *****/
17351+
17352+/**
17353+ * ccs_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
17354+ *
17355+ * @path: Pointer to "struct path".
17356+ * @buffer: Pointer to buffer to return value in.
17357+ * @buflen: Sizeof @buffer.
17358+ *
17359+ * Returns the buffer on success, an error code otherwise.
17360+ *
17361+ * Caller holds the dcache_lock and vfsmount_lock.
17362+ * Based on __d_path() in fs/dcache.c
17363+ *
17364+ * If dentry is a directory, trailing '/' is appended.
17365+ */
17366+static char *ccs_get_absolute_path(const struct path *path,
17367+ char * const buffer, const int buflen)
17368+{
17369+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
17370+ char *pos = ERR_PTR(-ENOMEM);
17371+ if (buflen >= 256) {
17372+ pos = ccsecurity_exports.d_absolute_path(path, buffer,
17373+ buflen - 1);
17374+ if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
17375+ struct inode *inode = path->dentry->d_inode;
17376+ if (inode && S_ISDIR(inode->i_mode)) {
17377+ buffer[buflen - 2] = '/';
17378+ buffer[buflen - 1] = '\0';
17379+ }
17380+ }
17381+ }
17382+ return pos;
17383+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
17384+ /*
17385+ * __d_path() will start returning NULL by backporting commit 02125a82
17386+ * "fix apparmor dereferencing potentially freed dentry, sanitize
17387+ * __d_path() API".
17388+ *
17389+ * Unfortunately, __d_path() after applying that commit always returns
17390+ * NULL when root is empty. d_absolute_path() is provided for TOMOYO
17391+ * 2.x and AppArmor but TOMOYO 1.x does not use it, for TOMOYO 1.x
17392+ * might be built as a loadable kernel module and there is no warrantee
17393+ * that TOMOYO 1.x is recompiled after applying that commit. Also,
17394+ * I don't want to search /proc/kallsyms for d_absolute_path() because
17395+ * I want to keep TOMOYO 1.x architecture independent. Thus, supply
17396+ * non empty root like AppArmor's d_namespace_path() did.
17397+ */
17398+ char *pos = ERR_PTR(-ENOMEM);
17399+ if (buflen >= 256) {
17400+ static bool ccs_no_empty;
17401+ if (!ccs_no_empty) {
17402+ struct path root = { };
17403+ pos = ccsecurity_exports.__d_path(path, &root, buffer,
17404+ buflen - 1);
17405+ } else {
17406+ pos = NULL;
17407+ }
17408+ if (!pos) {
17409+ struct task_struct *task = current;
17410+ struct path root;
17411+ struct path tmp;
17412+ spin_lock(&task->fs->lock);
17413+ root.mnt = task->nsproxy->mnt_ns->root;
17414+ root.dentry = root.mnt->mnt_root;
17415+ path_get(&root);
17416+ spin_unlock(&task->fs->lock);
17417+ tmp = root;
17418+ pos = ccsecurity_exports.__d_path(path, &tmp, buffer,
17419+ buflen - 1);
17420+ path_put(&root);
17421+ if (!pos)
17422+ return ERR_PTR(-EINVAL);
17423+ /* Remember if __d_path() needs non empty root. */
17424+ ccs_no_empty = true;
17425+ }
17426+ if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
17427+ struct inode *inode = path->dentry->d_inode;
17428+ if (inode && S_ISDIR(inode->i_mode)) {
17429+ buffer[buflen - 2] = '/';
17430+ buffer[buflen - 1] = '\0';
17431+ }
17432+ }
17433+ }
17434+ return pos;
17435+#else
17436+ char *pos = buffer + buflen - 1;
17437+ struct dentry *dentry = path->dentry;
17438+ struct vfsmount *vfsmnt = path->mnt;
17439+ const char *name;
17440+ int len;
17441+
17442+ if (buflen < 256)
17443+ goto out;
17444+
17445+ *pos = '\0';
17446+ if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
17447+ *--pos = '/';
17448+ for (;;) {
17449+ struct dentry *parent;
17450+ if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
17451+ if (vfsmnt->mnt_parent == vfsmnt)
17452+ break;
17453+ dentry = vfsmnt->mnt_mountpoint;
17454+ vfsmnt = vfsmnt->mnt_parent;
17455+ continue;
17456+ }
17457+ parent = dentry->d_parent;
17458+ name = dentry->d_name.name;
17459+ len = dentry->d_name.len;
17460+ pos -= len;
17461+ if (pos <= buffer)
17462+ goto out;
17463+ memmove(pos, name, len);
17464+ *--pos = '/';
17465+ dentry = parent;
17466+ }
17467+ if (*pos == '/')
17468+ pos++;
17469+ len = dentry->d_name.len;
17470+ pos -= len;
17471+ if (pos < buffer)
17472+ goto out;
17473+ memmove(pos, dentry->d_name.name, len);
17474+ return pos;
17475+out:
17476+ return ERR_PTR(-ENOMEM);
17477+#endif
17478+}
17479+
17480+/**
17481+ * ccs_get_dentry_path - Get the path of a dentry.
17482+ *
17483+ * @dentry: Pointer to "struct dentry".
17484+ * @buffer: Pointer to buffer to return value in.
17485+ * @buflen: Sizeof @buffer.
17486+ *
17487+ * Returns the buffer on success, an error code otherwise.
17488+ *
17489+ * Based on dentry_path() in fs/dcache.c
17490+ *
17491+ * If dentry is a directory, trailing '/' is appended.
17492+ */
17493+static char *ccs_get_dentry_path(struct dentry *dentry, char * const buffer,
17494+ const int buflen)
17495+{
17496+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
17497+ char *pos = ERR_PTR(-ENOMEM);
17498+ if (buflen >= 256) {
17499+ pos = dentry_path_raw(dentry, buffer, buflen - 1);
17500+ if (!IS_ERR(pos) && *pos == '/' && pos[1] &&
17501+ d_is_dir(dentry)) {
17502+ buffer[buflen - 2] = '/';
17503+ buffer[buflen - 1] = '\0';
17504+ }
17505+ }
17506+ return pos;
17507+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
17508+ char *pos = ERR_PTR(-ENOMEM);
17509+ if (buflen >= 256) {
17510+ /* rename_lock is locked/unlocked by dentry_path_raw(). */
17511+ pos = dentry_path_raw(dentry, buffer, buflen - 1);
17512+ if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
17513+ struct inode *inode = dentry->d_inode;
17514+ if (inode && S_ISDIR(inode->i_mode)) {
17515+ buffer[buflen - 2] = '/';
17516+ buffer[buflen - 1] = '\0';
17517+ }
17518+ }
17519+ }
17520+ return pos;
17521+#else
17522+ char *pos = buffer + buflen - 1;
17523+ if (buflen < 256)
17524+ return ERR_PTR(-ENOMEM);
17525+ *pos = '\0';
17526+ if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
17527+ *--pos = '/';
17528+ spin_lock(&dcache_lock);
17529+ while (!IS_ROOT(dentry)) {
17530+ struct dentry *parent = dentry->d_parent;
17531+ const char *name = dentry->d_name.name;
17532+ const int len = dentry->d_name.len;
17533+ pos -= len;
17534+ if (pos <= buffer) {
17535+ pos = ERR_PTR(-ENOMEM);
17536+ break;
17537+ }
17538+ memmove(pos, name, len);
17539+ *--pos = '/';
17540+ dentry = parent;
17541+ }
17542+ spin_unlock(&dcache_lock);
17543+ return pos;
17544+#endif
17545+}
17546+
17547+/**
17548+ * ccs_get_local_path - Get the path of a dentry.
17549+ *
17550+ * @dentry: Pointer to "struct dentry".
17551+ * @buffer: Pointer to buffer to return value in.
17552+ * @buflen: Sizeof @buffer.
17553+ *
17554+ * Returns the buffer on success, an error code otherwise.
17555+ */
17556+static char *ccs_get_local_path(struct dentry *dentry, char * const buffer,
17557+ const int buflen)
17558+{
17559+ struct super_block *sb = dentry->d_sb;
17560+ char *pos = ccs_get_dentry_path(dentry, buffer, buflen);
17561+ if (IS_ERR(pos))
17562+ return pos;
17563+ /* Convert from $PID to self if $PID is current thread. */
17564+ if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') {
17565+ char *ep;
17566+ const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10);
17567+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
17568+ if (*ep == '/' && pid && pid ==
17569+ task_tgid_nr_ns(current, sb->s_fs_info)) {
17570+ pos = ep - 5;
17571+ if (pos < buffer)
17572+ goto out;
17573+ memmove(pos, "/self", 5);
17574+ }
17575+#else
17576+ if (*ep == '/' && pid == ccs_sys_getpid()) {
17577+ pos = ep - 5;
17578+ if (pos < buffer)
17579+ goto out;
17580+ memmove(pos, "/self", 5);
17581+ }
17582+#endif
17583+ goto prepend_filesystem_name;
17584+ }
17585+ /* Use filesystem name for unnamed devices. */
17586+ if (!MAJOR(sb->s_dev))
17587+ goto prepend_filesystem_name;
17588+ {
17589+ struct inode *inode = sb->s_root->d_inode;
17590+ /*
17591+ * Use filesystem name if filesystems does not support rename()
17592+ * operation.
17593+ */
17594+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
17595+ if (inode->i_op && !inode->i_op->rename)
17596+ goto prepend_filesystem_name;
17597+#else
17598+ if (!inode->i_op->rename && !inode->i_op->rename2)
17599+ goto prepend_filesystem_name;
17600+#endif
17601+ }
17602+ /* Prepend device name. */
17603+ {
17604+ char name[64];
17605+ int name_len;
17606+ const dev_t dev = sb->s_dev;
17607+ name[sizeof(name) - 1] = '\0';
17608+ snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev),
17609+ MINOR(dev));
17610+ name_len = strlen(name);
17611+ pos -= name_len;
17612+ if (pos < buffer)
17613+ goto out;
17614+ memmove(pos, name, name_len);
17615+ return pos;
17616+ }
17617+ /* Prepend filesystem name. */
17618+prepend_filesystem_name:
17619+ {
17620+ const char *name = sb->s_type->name;
17621+ const int name_len = strlen(name);
17622+ pos -= name_len + 1;
17623+ if (pos < buffer)
17624+ goto out;
17625+ memmove(pos, name, name_len);
17626+ pos[name_len] = ':';
17627+ }
17628+ return pos;
17629+out:
17630+ return ERR_PTR(-ENOMEM);
17631+}
17632+
17633+/**
17634+ * ccs_get_socket_name - Get the name of a socket.
17635+ *
17636+ * @path: Pointer to "struct path".
17637+ * @buffer: Pointer to buffer to return value in.
17638+ * @buflen: Sizeof @buffer.
17639+ *
17640+ * Returns the buffer.
17641+ */
17642+static char *ccs_get_socket_name(const struct path *path, char * const buffer,
17643+ const int buflen)
17644+{
17645+ struct inode *inode = path->dentry->d_inode;
17646+ struct socket *sock = inode ? SOCKET_I(inode) : NULL;
17647+ struct sock *sk = sock ? sock->sk : NULL;
17648+ if (sk) {
17649+ snprintf(buffer, buflen, "socket:[family=%u:type=%u:"
17650+ "protocol=%u]", sk->sk_family, sk->sk_type,
17651+ sk->sk_protocol);
17652+ } else {
17653+ snprintf(buffer, buflen, "socket:[unknown]");
17654+ }
17655+ return buffer;
17656+}
17657+
17658+#define SOCKFS_MAGIC 0x534F434B
17659+
17660+/**
17661+ * ccs_realpath - Returns realpath(3) of the given pathname but ignores chroot'ed root.
17662+ *
17663+ * @path: Pointer to "struct path".
17664+ *
17665+ * Returns the realpath of the given @path on success, NULL otherwise.
17666+ *
17667+ * This function uses kzalloc(), so caller must kfree() if this function
17668+ * didn't return NULL.
17669+ */
17670+char *ccs_realpath(const struct path *path)
17671+{
17672+ char *buf = NULL;
17673+ char *name = NULL;
17674+ unsigned int buf_len = PAGE_SIZE / 2;
17675+ struct dentry *dentry = path->dentry;
17676+ struct super_block *sb;
17677+ if (!dentry)
17678+ return NULL;
17679+ sb = dentry->d_sb;
17680+ while (1) {
17681+ char *pos;
17682+ struct inode *inode;
17683+ buf_len <<= 1;
17684+ kfree(buf);
17685+ buf = kmalloc(buf_len, CCS_GFP_FLAGS);
17686+ if (!buf)
17687+ break;
17688+ /* To make sure that pos is '\0' terminated. */
17689+ buf[buf_len - 1] = '\0';
17690+ /* Get better name for socket. */
17691+ if (sb->s_magic == SOCKFS_MAGIC) {
17692+ pos = ccs_get_socket_name(path, buf, buf_len - 1);
17693+ goto encode;
17694+ }
17695+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
17696+ /* For "pipe:[\$]". */
17697+ if (dentry->d_op && dentry->d_op->d_dname) {
17698+ pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
17699+ goto encode;
17700+ }
17701+#endif
17702+ inode = sb->s_root->d_inode;
17703+ /*
17704+ * Use local name for "filesystems without rename() operation"
17705+ * or "path without vfsmount" or "absolute name is unavailable"
17706+ * cases.
17707+ */
17708+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
17709+ if (!path->mnt || (inode->i_op && !inode->i_op->rename))
17710+ pos = ERR_PTR(-EINVAL);
17711+ else {
17712+ /* Get absolute name for the rest. */
17713+ ccs_realpath_lock();
17714+ pos = ccs_get_absolute_path(path, buf, buf_len - 1);
17715+ ccs_realpath_unlock();
17716+ }
17717+ if (pos == ERR_PTR(-EINVAL))
17718+ pos = ccs_get_local_path(path->dentry, buf,
17719+ buf_len - 1);
17720+#else
17721+ if (!path->mnt ||
17722+ (!inode->i_op->rename && !inode->i_op->rename2))
17723+ pos = ccs_get_local_path(path->dentry, buf,
17724+ buf_len - 1);
17725+ else
17726+ pos = ccs_get_absolute_path(path, buf, buf_len - 1);
17727+#endif
17728+encode:
17729+ if (IS_ERR(pos))
17730+ continue;
17731+ name = ccs_encode(pos);
17732+ break;
17733+ }
17734+ kfree(buf);
17735+ if (!name)
17736+ ccs_warn_oom(__func__);
17737+ return name;
17738+}
17739+
17740+/**
17741+ * ccs_encode2 - Encode binary string to ascii string.
17742+ *
17743+ * @str: String in binary format.
17744+ * @str_len: Size of @str in byte.
17745+ *
17746+ * Returns pointer to @str in ascii format on success, NULL otherwise.
17747+ *
17748+ * This function uses kzalloc(), so caller must kfree() if this function
17749+ * didn't return NULL.
17750+ */
17751+char *ccs_encode2(const char *str, int str_len)
17752+{
17753+ int i;
17754+ int len = 0;
17755+ const char *p = str;
17756+ char *cp;
17757+ char *cp0;
17758+ if (!p)
17759+ return NULL;
17760+ for (i = 0; i < str_len; i++) {
17761+ const unsigned char c = p[i];
17762+ if (c == '\\')
17763+ len += 2;
17764+ else if (c > ' ' && c < 127)
17765+ len++;
17766+ else
17767+ len += 4;
17768+ }
17769+ len++;
17770+ /* Reserve space for appending "/". */
17771+ cp = kzalloc(len + 10, CCS_GFP_FLAGS);
17772+ if (!cp)
17773+ return NULL;
17774+ cp0 = cp;
17775+ p = str;
17776+ for (i = 0; i < str_len; i++) {
17777+ const unsigned char c = p[i];
17778+ if (c == '\\') {
17779+ *cp++ = '\\';
17780+ *cp++ = '\\';
17781+ } else if (c > ' ' && c < 127) {
17782+ *cp++ = c;
17783+ } else {
17784+ *cp++ = '\\';
17785+ *cp++ = (c >> 6) + '0';
17786+ *cp++ = ((c >> 3) & 7) + '0';
17787+ *cp++ = (c & 7) + '0';
17788+ }
17789+ }
17790+ return cp0;
17791+}
17792+
17793+/**
17794+ * ccs_encode - Encode binary string to ascii string.
17795+ *
17796+ * @str: String in binary format.
17797+ *
17798+ * Returns pointer to @str in ascii format on success, NULL otherwise.
17799+ *
17800+ * This function uses kzalloc(), so caller must kfree() if this function
17801+ * didn't return NULL.
17802+ */
17803+char *ccs_encode(const char *str)
17804+{
17805+ return str ? ccs_encode2(str, strlen(str)) : NULL;
17806+}
17807+
17808+/**
17809+ * ccs_const_part_length - Evaluate the initial length without a pattern in a token.
17810+ *
17811+ * @filename: The string to evaluate.
17812+ *
17813+ * Returns the initial length without a pattern in @filename.
17814+ */
17815+static int ccs_const_part_length(const char *filename)
17816+{
17817+ char c;
17818+ int len = 0;
17819+ if (!filename)
17820+ return 0;
17821+ while (1) {
17822+ c = *filename++;
17823+ if (!c)
17824+ break;
17825+ if (c != '\\') {
17826+ len++;
17827+ continue;
17828+ }
17829+ c = *filename++;
17830+ switch (c) {
17831+ case '\\': /* "\\" */
17832+ len += 2;
17833+ continue;
17834+ case '0': /* "\ooo" */
17835+ case '1':
17836+ case '2':
17837+ case '3':
17838+ c = *filename++;
17839+ if (c < '0' || c > '7')
17840+ break;
17841+ c = *filename++;
17842+ if (c < '0' || c > '7')
17843+ break;
17844+ len += 4;
17845+ continue;
17846+ }
17847+ break;
17848+ }
17849+ return len;
17850+}
17851+
17852+/**
17853+ * ccs_fill_path_info - Fill in "struct ccs_path_info" members.
17854+ *
17855+ * @ptr: Pointer to "struct ccs_path_info" to fill in.
17856+ *
17857+ * The caller sets "struct ccs_path_info"->name.
17858+ */
17859+void ccs_fill_path_info(struct ccs_path_info *ptr)
17860+{
17861+ const char *name = ptr->name;
17862+ const int len = strlen(name);
17863+ ptr->total_len = len;
17864+ ptr->const_len = ccs_const_part_length(name);
17865+ ptr->is_dir = len && (name[len - 1] == '/');
17866+ ptr->is_patterned = (ptr->const_len < len);
17867+ ptr->hash = full_name_hash(name, len);
17868+}
17869+
17870+/**
17871+ * ccs_get_exe - Get ccs_realpath() of current process.
17872+ *
17873+ * Returns the ccs_realpath() of current process on success, NULL otherwise.
17874+ *
17875+ * This function uses kzalloc(), so the caller must kfree()
17876+ * if this function didn't return NULL.
17877+ */
17878+const char *ccs_get_exe(void)
17879+{
17880+ struct mm_struct *mm = current->mm;
17881+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
17882+ struct vm_area_struct *vma;
17883+#endif
17884+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
17885+ struct path path;
17886+#endif
17887+ struct file *exe_file = NULL;
17888+ const char *cp;
17889+ if (!mm)
17890+ return NULL;
17891+ down_read(&mm->mmap_sem);
17892+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
17893+ /* Not using get_mm_exe_file() as it is not exported. */
17894+ exe_file = mm->exe_file;
17895+#else
17896+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
17897+ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
17898+ exe_file = vma->vm_file;
17899+ break;
17900+ }
17901+ }
17902+#endif
17903+ if (exe_file)
17904+ get_file(exe_file);
17905+ up_read(&mm->mmap_sem);
17906+ if (!exe_file)
17907+ return NULL;
17908+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
17909+ cp = ccs_realpath(&exe_file->f_path);
17910+#else
17911+ path.mnt = exe_file->f_vfsmnt;
17912+ path.dentry = exe_file->f_dentry;
17913+ cp = ccs_realpath(&path);
17914+#endif
17915+ fput(exe_file);
17916+ return cp;
17917+}
17918--
179191.9.1
17920
diff --git a/recipes-kernel/linux/linux-yocto-4.1/tomoyo.cfg b/recipes-kernel/linux/linux-yocto-4.1/tomoyo.cfg
new file mode 100644
index 0000000..8f78270
--- /dev/null
+++ b/recipes-kernel/linux/linux-yocto-4.1/tomoyo.cfg
@@ -0,0 +1,16 @@
1CONFIG_CCSECURITY=y
2CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY=y
3CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY=2048
4CONFIG_CCSECURITY_MAX_AUDIT_LOG=1024
5CONFIG_CCSECURITY_POLICY_LOADER="/sbin/ccs-init"
6CONFIG_CCSECURITY_ACTIVATION_TRIGGER="/sbin/init"
7CONFIG_CCSECURITY_FILE_READDIR=y
8CONFIG_CCSECURITY_FILE_GETATTR=y
9CONFIG_CCSECURITY_NETWORK=y
10CONFIG_CCSECURITY_NETWORK_RECVMSG=y
11CONFIG_CCSECURITY_CAPABILITY=y
12CONFIG_CCSECURITY_IPC=y
13CONFIG_CCSECURITY_MISC=y
14CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER=y
15CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION=y
16CONFIG_CCSECURITY_PORTRESERVE=y
diff --git a/recipes-kernel/linux/linux-yocto-4.1/tomoyo.scc b/recipes-kernel/linux/linux-yocto-4.1/tomoyo.scc
new file mode 100644
index 0000000..588864c
--- /dev/null
+++ b/recipes-kernel/linux/linux-yocto-4.1/tomoyo.scc
@@ -0,0 +1,4 @@
1define KFEATURE_DESCRIPTION "Tomoyo Kernel Support"
2define KFEATURE_COMPATIBILITY arch
3
4kconf non-hardware tomoyo.cfg
diff --git a/recipes-kernel/linux/linux-yocto_4.1.bbappend b/recipes-kernel/linux/linux-yocto_4.1.bbappend
new file mode 100644
index 0000000..1043d5c
--- /dev/null
+++ b/recipes-kernel/linux/linux-yocto_4.1.bbappend
@@ -0,0 +1,9 @@
1FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-4.1:"
2
3# Tomoyo kernel support
4SRC_URI += "\
5 ${@base_contains('DISTRO_FEATURES', 'tomoyo', ' file://ccs-tools-yocto.4.1.patch', '', d)} \
6 ${@base_contains('DISTRO_FEATURES', 'tomoyo', ' file://ccs-tools-yocto_security.patch', '', d)} \
7 ${@base_contains('DISTRO_FEATURES', 'tomoyo', ' file://tomoyo.cfg', '', d)} \
8 ${@base_contains('DISTRO_FEATURES', 'tomoyo', ' file://tomoyo.scc', '', d)} \
9 "