[yocto] [meta-security][PATCH] linux-yocto: drop all 4.1 content

akuster808 akuster808 at gmail.com
Thu Aug 31 22:12:32 PDT 2017


merged

On 08/29/2017 05:45 AM, Mikko Ylinen wrote:
> linux-yocto_4.1.bb recipe has been removed from oe-core master
> and that triggers a bitbake error due to orphan bbappends
> maintained in meta-security.
>
> To fix the error, drop linux-yocto_4.1.bbappend plus the patches
> and the config fragments for it.
>
> Signed-off-by: Mikko Ylinen <mikko.ylinen at linux.intel.com>
> ---
>   .../linux/linux-yocto-4.1/ccs-patch-4.1.diff       |   968 -
>   .../linux/linux-yocto-4.1/ccs-patch-4.2.diff       |   681 -
>   .../linux-yocto-4.1/ccs-tools-yocto.4.1.patch      |  1029 --
>   .../linux-yocto-4.1/ccs-tools-yocto_security.patch | 17920 -------------------
>   recipes-kernel/linux/linux-yocto-4.1/tomoyo.cfg    |    16 -
>   recipes-kernel/linux/linux-yocto-4.1/tomoyo.scc    |     4 -
>   recipes-kernel/linux/linux-yocto_4.1.bbappend      |     9 -
>   7 files changed, 20627 deletions(-)
>   delete mode 100644 recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.1.diff
>   delete mode 100644 recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.2.diff
>   delete mode 100644 recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto.4.1.patch
>   delete mode 100644 recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto_security.patch
>   delete mode 100644 recipes-kernel/linux/linux-yocto-4.1/tomoyo.cfg
>   delete mode 100644 recipes-kernel/linux/linux-yocto-4.1/tomoyo.scc
>   delete mode 100644 recipes-kernel/linux/linux-yocto_4.1.bbappend
>
> 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
> deleted file mode 100644
> index 9ad49fd..0000000
> --- a/recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.1.diff
> +++ /dev/null
> @@ -1,968 +0,0 @@
> -This is TOMOYO Linux patch for kernel 4.1.8.
> -
> -Source code for this patch is https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.1.8.tar.xz
> ----
> - fs/exec.c                 |    2
> - fs/open.c                 |    2
> - fs/proc/version.c         |    7 ++
> - include/linux/init_task.h |    9 +++
> - include/linux/sched.h     |    6 ++
> - include/linux/security.h  |   62 +++++++++++++++----------
> - include/net/ip.h          |    4 +
> - kernel/fork.c             |    5 ++
> - kernel/kexec.c            |    3 +
> - kernel/module.c           |    5 ++
> - kernel/ptrace.c           |   10 ++++
> - kernel/reboot.c           |    3 +
> - kernel/sched/core.c       |    2
> - kernel/signal.c           |   10 ++++
> - kernel/sys.c              |    8 +++
> - kernel/time/ntp.c         |    8 +++
> - net/ipv4/raw.c            |    4 +
> - net/ipv4/udp.c            |    4 +
> - net/ipv6/raw.c            |    4 +
> - net/ipv6/udp.c            |    4 +
> - net/socket.c              |    4 +
> - net/unix/af_unix.c        |    4 +
> - security/Kconfig          |    2
> - security/Makefile         |    3 +
> - security/security.c       |  110 ++++++++++++++++++++++++++++++++++++++++------
> - 25 files changed, 248 insertions(+), 37 deletions(-)
> -
> ---- linux-4.1.8.orig/fs/exec.c
> -+++ linux-4.1.8/fs/exec.c
> -@@ -1461,7 +1461,7 @@ static int exec_binprm(struct linux_binp
> - 	old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
> - 	rcu_read_unlock();
> -
> --	ret = search_binary_handler(bprm);
> -+	ret = ccs_search_binary_handler(bprm);
> - 	if (ret >= 0) {
> - 		audit_bprm(bprm);
> - 		trace_sched_process_exec(current, old_pid, bprm);
> ---- linux-4.1.8.orig/fs/open.c
> -+++ linux-4.1.8/fs/open.c
> -@@ -1106,6 +1106,8 @@ EXPORT_SYMBOL(sys_close);
> -  */
> - SYSCALL_DEFINE0(vhangup)
> - {
> -+	if (!ccs_capable(CCS_SYS_VHANGUP))
> -+		return -EPERM;
> - 	if (capable(CAP_SYS_TTY_CONFIG)) {
> - 		tty_vhangup_self();
> - 		return 0;
> ---- linux-4.1.8.orig/fs/proc/version.c
> -+++ linux-4.1.8/fs/proc/version.c
> -@@ -32,3 +32,10 @@ static int __init proc_version_init(void
> - 	return 0;
> - }
> - fs_initcall(proc_version_init);
> -+
> -+static int __init ccs_show_version(void)
> -+{
> -+	printk(KERN_INFO "Hook version: 4.1.8 2015/09/26\n");
> -+	return 0;
> -+}
> -+fs_initcall(ccs_show_version);
> ---- linux-4.1.8.orig/include/linux/init_task.h
> -+++ linux-4.1.8/include/linux/init_task.h
> -@@ -182,6 +182,14 @@ extern struct task_group root_task_group
> - # define INIT_KASAN(tsk)
> - #endif
> -
> -+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
> -+#define INIT_CCSECURITY          \
> -+	.ccs_domain_info = NULL, \
> -+	.ccs_flags = 0,
> -+#else
> -+#define INIT_CCSECURITY
> -+#endif
> -+
> - /*
> -  *  INIT_TASK is used to set up the first task table, touch at
> -  * your own risk!. Base=0, limit=0x1fffff (=2MB)
> -@@ -258,6 +266,7 @@ extern struct task_group root_task_group
> - 	INIT_VTIME(tsk)							\
> - 	INIT_NUMA_BALANCING(tsk)					\
> - 	INIT_KASAN(tsk)							\
> -+	INIT_CCSECURITY                                                 \
> - }
> -
> -
> ---- linux-4.1.8.orig/include/linux/sched.h
> -+++ linux-4.1.8/include/linux/sched.h
> -@@ -6,6 +6,8 @@
> - #include <linux/sched/prio.h>
> -
> -
> -+struct ccs_domain_info;
> -+
> - struct sched_param {
> - 	int sched_priority;
> - };
> -@@ -1724,6 +1726,10 @@ struct task_struct {
> - #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
> - 	unsigned long	task_state_change;
> - #endif
> -+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
> -+	struct ccs_domain_info *ccs_domain_info;
> -+	u32 ccs_flags;
> -+#endif
> - };
> -
> - /* Future-safe accessor for struct task_struct's cpus_allowed. */
> ---- linux-4.1.8.orig/include/linux/security.h
> -+++ linux-4.1.8/include/linux/security.h
> -@@ -53,6 +53,7 @@ struct msg_queue;
> - struct xattr;
> - struct xfrm_sec_ctx;
> - struct mm_struct;
> -+#include <linux/ccsecurity.h>
> -
> - /* Maximum number of letters for an LSM name string */
> - #define SECURITY_NAME_MAX	10
> -@@ -2042,7 +2043,10 @@ static inline int security_syslog(int ty
> - static inline int security_settime(const struct timespec *ts,
> - 				   const struct timezone *tz)
> - {
> --	return cap_settime(ts, tz);
> -+	int error = cap_settime(ts, tz);
> -+	if (!error)
> -+		error = ccs_settime(ts, tz);
> -+	return error;
> - }
> -
> - static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
> -@@ -2111,18 +2115,18 @@ static inline int security_sb_mount(cons
> - 				    const char *type, unsigned long flags,
> - 				    void *data)
> - {
> --	return 0;
> -+	return ccs_sb_mount(dev_name, path, type, flags, data);
> - }
> -
> - static inline int security_sb_umount(struct vfsmount *mnt, int flags)
> - {
> --	return 0;
> -+	return ccs_sb_umount(mnt, flags);
> - }
> -
> - static inline int security_sb_pivotroot(struct path *old_path,
> - 					struct path *new_path)
> - {
> --	return 0;
> -+	return ccs_sb_pivotroot(old_path, new_path);
> - }
> -
> - static inline int security_sb_set_mnt_opts(struct super_block *sb,
> -@@ -2260,7 +2264,7 @@ static inline int security_inode_setattr
> -
> - static inline int security_inode_getattr(const struct path *path)
> - {
> --	return 0;
> -+	return ccs_inode_getattr(path);
> - }
> -
> - static inline int security_inode_setxattr(struct dentry *dentry,
> -@@ -2336,7 +2340,7 @@ static inline void security_file_free(st
> - static inline int security_file_ioctl(struct file *file, unsigned int cmd,
> - 				      unsigned long arg)
> - {
> --	return 0;
> -+	return ccs_file_ioctl(file, cmd, arg);
> - }
> -
> - static inline int security_mmap_file(struct file *file, unsigned long prot,
> -@@ -2365,7 +2369,7 @@ static inline int security_file_lock(str
> - static inline int security_file_fcntl(struct file *file, unsigned int cmd,
> - 				      unsigned long arg)
> - {
> --	return 0;
> -+	return ccs_file_fcntl(file, cmd, arg);
> - }
> -
> - static inline void security_file_set_fowner(struct file *file)
> -@@ -2388,7 +2392,7 @@ static inline int security_file_receive(
> - static inline int security_file_open(struct file *file,
> - 				     const struct cred *cred)
> - {
> --	return 0;
> -+	return ccs_file_open(file, cred);
> - }
> -
> - static inline int security_task_create(unsigned long clone_flags)
> -@@ -2750,7 +2754,7 @@ static inline int security_unix_may_send
> - static inline int security_socket_create(int family, int type,
> - 					 int protocol, int kern)
> - {
> --	return 0;
> -+	return ccs_socket_create(family, type, protocol, kern);
> - }
> -
> - static inline int security_socket_post_create(struct socket *sock,
> -@@ -2765,19 +2769,19 @@ static inline int security_socket_bind(s
> - 				       struct sockaddr *address,
> - 				       int addrlen)
> - {
> --	return 0;
> -+	return ccs_socket_bind(sock, address, addrlen);
> - }
> -
> - static inline int security_socket_connect(struct socket *sock,
> - 					  struct sockaddr *address,
> - 					  int addrlen)
> - {
> --	return 0;
> -+	return ccs_socket_connect(sock, address, addrlen);
> - }
> -
> - static inline int security_socket_listen(struct socket *sock, int backlog)
> - {
> --	return 0;
> -+	return ccs_socket_listen(sock, backlog);
> - }
> -
> - static inline int security_socket_accept(struct socket *sock,
> -@@ -2789,7 +2793,7 @@ static inline int security_socket_accept
> - static inline int security_socket_sendmsg(struct socket *sock,
> - 					  struct msghdr *msg, int size)
> - {
> --	return 0;
> -+	return ccs_socket_sendmsg(sock, msg, size);
> - }
> -
> - static inline int security_socket_recvmsg(struct socket *sock,
> -@@ -3031,42 +3035,42 @@ int security_path_chroot(struct path *pa
> - #else	/* CONFIG_SECURITY_PATH */
> - static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
> - {
> --	return 0;
> -+	return ccs_path_unlink(dir, dentry);
> - }
> -
> - static inline int security_path_mkdir(struct path *dir, struct dentry *dentry,
> - 				      umode_t mode)
> - {
> --	return 0;
> -+	return ccs_path_mkdir(dir, dentry, mode);
> - }
> -
> - static inline int security_path_rmdir(struct path *dir, struct dentry *dentry)
> - {
> --	return 0;
> -+	return ccs_path_rmdir(dir, dentry);
> - }
> -
> - static inline int security_path_mknod(struct path *dir, struct dentry *dentry,
> - 				      umode_t mode, unsigned int dev)
> - {
> --	return 0;
> -+	return ccs_path_mknod(dir, dentry, mode, dev);
> - }
> -
> - static inline int security_path_truncate(struct path *path)
> - {
> --	return 0;
> -+	return ccs_path_truncate(path);
> - }
> -
> - static inline int security_path_symlink(struct path *dir, struct dentry *dentry,
> - 					const char *old_name)
> - {
> --	return 0;
> -+	return ccs_path_symlink(dir, dentry, old_name);
> - }
> -
> - static inline int security_path_link(struct dentry *old_dentry,
> - 				     struct path *new_dir,
> - 				     struct dentry *new_dentry)
> - {
> --	return 0;
> -+	return ccs_path_link(old_dentry, new_dir, new_dentry);
> - }
> -
> - static inline int security_path_rename(struct path *old_dir,
> -@@ -3075,22 +3079,32 @@ static inline int security_path_rename(s
> - 				       struct dentry *new_dentry,
> - 				       unsigned int flags)
> - {
> --	return 0;
> -+	/*
> -+	 * Not using RENAME_EXCHANGE here in order to avoid KABI breakage
> -+	 * by doing "#include <uapi/linux/fs.h>" .
> -+	 */
> -+	if (flags & (1 << 1)) {
> -+		int err = ccs_path_rename(new_dir, new_dentry, old_dir,
> -+					  old_dentry);
> -+		if (err)
> -+			return err;
> -+	}
> -+	return ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
> - }
> -
> - static inline int security_path_chmod(struct path *path, umode_t mode)
> - {
> --	return 0;
> -+	return ccs_path_chmod(path, mode);
> - }
> -
> - static inline int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
> - {
> --	return 0;
> -+	return ccs_path_chown(path, uid, gid);
> - }
> -
> - static inline int security_path_chroot(struct path *path)
> - {
> --	return 0;
> -+	return ccs_path_chroot(path);
> - }
> - #endif	/* CONFIG_SECURITY_PATH */
> -
> ---- linux-4.1.8.orig/include/net/ip.h
> -+++ linux-4.1.8/include/net/ip.h
> -@@ -216,6 +216,8 @@ void inet_get_local_port_range(struct ne
> - #ifdef CONFIG_SYSCTL
> - static inline int inet_is_local_reserved_port(struct net *net, int port)
> - {
> -+	if (ccs_lport_reserved(port))
> -+		return 1;
> - 	if (!net->ipv4.sysctl_local_reserved_ports)
> - 		return 0;
> - 	return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
> -@@ -229,6 +231,8 @@ static inline bool sysctl_dev_name_is_al
> - #else
> - static inline int inet_is_local_reserved_port(struct net *net, int port)
> - {
> -+	if (ccs_lport_reserved(port))
> -+		return 1;
> - 	return 0;
> - }
> - #endif
> ---- linux-4.1.8.orig/kernel/fork.c
> -+++ linux-4.1.8/kernel/fork.c
> -@@ -257,6 +257,7 @@ void __put_task_struct(struct task_struc
> - 	delayacct_tsk_free(tsk);
> - 	put_signal_struct(tsk->signal);
> -
> -+	ccs_free_task_security(tsk);
> - 	if (!profile_handoff_task(tsk))
> - 		free_task(tsk);
> - }
> -@@ -1423,6 +1424,9 @@ static struct task_struct *copy_process(
> - 		goto bad_fork_cleanup_perf;
> - 	/* copy all the process information */
> - 	shm_init_task(p);
> -+	retval = ccs_alloc_task_security(p);
> -+	if (retval)
> -+		goto bad_fork_cleanup_audit;
> - 	retval = copy_semundo(clone_flags, p);
> - 	if (retval)
> - 		goto bad_fork_cleanup_audit;
> -@@ -1627,6 +1631,7 @@ bad_fork_cleanup_semundo:
> - 	exit_sem(p);
> - bad_fork_cleanup_audit:
> - 	audit_free(p);
> -+	ccs_free_task_security(p);
> - bad_fork_cleanup_perf:
> - 	perf_event_free_task(p);
> - bad_fork_cleanup_policy:
> ---- linux-4.1.8.orig/kernel/kexec.c
> -+++ linux-4.1.8/kernel/kexec.c
> -@@ -41,6 +41,7 @@
> - #include <asm/uaccess.h>
> - #include <asm/io.h>
> - #include <asm/sections.h>
> -+#include <linux/ccsecurity.h>
> -
> - #include <crypto/hash.h>
> - #include <crypto/sha.h>
> -@@ -1245,6 +1246,8 @@ SYSCALL_DEFINE4(kexec_load, unsigned lon
> - 	/* We only trust the superuser with rebooting the system. */
> - 	if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
> - 		return -EPERM;
> -+	if (!ccs_capable(CCS_SYS_KEXEC_LOAD))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * Verify we have a legal set of flags
> ---- linux-4.1.8.orig/kernel/module.c
> -+++ linux-4.1.8/kernel/module.c
> -@@ -61,6 +61,7 @@
> - #include <linux/bsearch.h>
> - #include <uapi/linux/module.h>
> - #include "module-internal.h"
> -+#include <linux/ccsecurity.h>
> -
> - #define CREATE_TRACE_POINTS
> - #include <trace/events/module.h>
> -@@ -799,6 +800,8 @@ SYSCALL_DEFINE2(delete_module, const cha
> -
> - 	if (!capable(CAP_SYS_MODULE) || modules_disabled)
> - 		return -EPERM;
> -+	if (!ccs_capable(CCS_USE_KERNEL_MODULE))
> -+		return -EPERM;
> -
> - 	if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
> - 		return -EFAULT;
> -@@ -3155,6 +3158,8 @@ static int may_init_module(void)
> - {
> - 	if (!capable(CAP_SYS_MODULE) || modules_disabled)
> - 		return -EPERM;
> -+	if (!ccs_capable(CCS_USE_KERNEL_MODULE))
> -+		return -EPERM;
> -
> - 	return 0;
> - }
> ---- linux-4.1.8.orig/kernel/ptrace.c
> -+++ linux-4.1.8/kernel/ptrace.c
> -@@ -1034,6 +1034,11 @@ SYSCALL_DEFINE4(ptrace, long, request, l
> - {
> - 	struct task_struct *child;
> - 	long ret;
> -+	{
> -+		const int rc = ccs_ptrace_permission(request, pid);
> -+		if (rc)
> -+			return rc;
> -+	}
> -
> - 	if (request == PTRACE_TRACEME) {
> - 		ret = ptrace_traceme();
> -@@ -1180,6 +1185,11 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_lo
> - {
> - 	struct task_struct *child;
> - 	long ret;
> -+	{
> -+		const int rc = ccs_ptrace_permission(request, pid);
> -+		if (rc)
> -+			return rc;
> -+	}
> -
> - 	if (request == PTRACE_TRACEME) {
> - 		ret = ptrace_traceme();
> ---- linux-4.1.8.orig/kernel/reboot.c
> -+++ linux-4.1.8/kernel/reboot.c
> -@@ -16,6 +16,7 @@
> - #include <linux/syscalls.h>
> - #include <linux/syscore_ops.h>
> - #include <linux/uaccess.h>
> -+#include <linux/ccsecurity.h>
> -
> - /*
> -  * this indicates whether you can reboot with ctrl-alt-del: the default is yes
> -@@ -295,6 +296,8 @@ SYSCALL_DEFINE4(reboot, int, magic1, int
> - 			magic2 != LINUX_REBOOT_MAGIC2B &&
> - 			magic2 != LINUX_REBOOT_MAGIC2C))
> - 		return -EINVAL;
> -+	if (!ccs_capable(CCS_SYS_REBOOT))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * If pid namespaces are enabled and the current task is in a child
> ---- linux-4.1.8.orig/kernel/sched/core.c
> -+++ linux-4.1.8/kernel/sched/core.c
> -@@ -3145,6 +3145,8 @@ int can_nice(const struct task_struct *p
> - SYSCALL_DEFINE1(nice, int, increment)
> - {
> - 	long nice, retval;
> -+	if (!ccs_capable(CCS_SYS_NICE))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * Setpriority might change our priority at the same moment.
> ---- linux-4.1.8.orig/kernel/signal.c
> -+++ linux-4.1.8/kernel/signal.c
> -@@ -2901,6 +2901,8 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const s
> - SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
> - {
> - 	struct siginfo info;
> -+	if (ccs_kill_permission(pid, sig))
> -+		return -EPERM;
> -
> - 	info.si_signo = sig;
> - 	info.si_errno = 0;
> -@@ -2969,6 +2971,8 @@ SYSCALL_DEFINE3(tgkill, pid_t, tgid, pid
> - 	/* This is only valid for single tasks */
> - 	if (pid <= 0 || tgid <= 0)
> - 		return -EINVAL;
> -+	if (ccs_tgkill_permission(tgid, pid, sig))
> -+		return -EPERM;
> -
> - 	return do_tkill(tgid, pid, sig);
> - }
> -@@ -2985,6 +2989,8 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int,
> - 	/* This is only valid for single tasks */
> - 	if (pid <= 0)
> - 		return -EINVAL;
> -+	if (ccs_tkill_permission(pid, sig))
> -+		return -EPERM;
> -
> - 	return do_tkill(0, pid, sig);
> - }
> -@@ -2999,6 +3005,8 @@ static int do_rt_sigqueueinfo(pid_t pid,
> - 		return -EPERM;
> -
> - 	info->si_signo = sig;
> -+	if (ccs_sigqueue_permission(pid, sig))
> -+		return -EPERM;
> -
> - 	/* POSIX.1b doesn't mention process groups.  */
> - 	return kill_proc_info(sig, info, pid);
> -@@ -3047,6 +3055,8 @@ static int do_rt_tgsigqueueinfo(pid_t tg
> - 		return -EPERM;
> -
> - 	info->si_signo = sig;
> -+	if (ccs_tgsigqueue_permission(tgid, pid, sig))
> -+		return -EPERM;
> -
> - 	return do_send_specific(tgid, pid, sig, info);
> - }
> ---- linux-4.1.8.orig/kernel/sys.c
> -+++ linux-4.1.8/kernel/sys.c
> -@@ -183,6 +183,10 @@ SYSCALL_DEFINE3(setpriority, int, which,
> -
> - 	if (which > PRIO_USER || which < PRIO_PROCESS)
> - 		goto out;
> -+	if (!ccs_capable(CCS_SYS_NICE)) {
> -+		error = -EPERM;
> -+		goto out;
> -+	}
> -
> - 	/* normalize: avoid signed division (rounding problems) */
> - 	error = -ESRCH;
> -@@ -1222,6 +1226,8 @@ SYSCALL_DEFINE2(sethostname, char __user
> -
> - 	if (len < 0 || len > __NEW_UTS_LEN)
> - 		return -EINVAL;
> -+	if (!ccs_capable(CCS_SYS_SETHOSTNAME))
> -+		return -EPERM;
> - 	down_write(&uts_sem);
> - 	errno = -EFAULT;
> - 	if (!copy_from_user(tmp, name, len)) {
> -@@ -1272,6 +1278,8 @@ SYSCALL_DEFINE2(setdomainname, char __us
> - 		return -EPERM;
> - 	if (len < 0 || len > __NEW_UTS_LEN)
> - 		return -EINVAL;
> -+	if (!ccs_capable(CCS_SYS_SETHOSTNAME))
> -+		return -EPERM;
> -
> - 	down_write(&uts_sem);
> - 	errno = -EFAULT;
> ---- linux-4.1.8.orig/kernel/time/ntp.c
> -+++ linux-4.1.8/kernel/time/ntp.c
> -@@ -16,6 +16,7 @@
> - #include <linux/mm.h>
> - #include <linux/module.h>
> - #include <linux/rtc.h>
> -+#include <linux/ccsecurity.h>
> -
> - #include "ntp_internal.h"
> -
> -@@ -626,10 +627,15 @@ int ntp_validate_timex(struct timex *txc
> - 		if (!(txc->modes & ADJ_OFFSET_READONLY) &&
> - 		    !capable(CAP_SYS_TIME))
> - 			return -EPERM;
> -+		if (!(txc->modes & ADJ_OFFSET_READONLY) &&
> -+		    !ccs_capable(CCS_SYS_SETTIME))
> -+			return -EPERM;
> - 	} else {
> - 		/* In order to modify anything, you gotta be super-user! */
> - 		 if (txc->modes && !capable(CAP_SYS_TIME))
> - 			return -EPERM;
> -+		if (txc->modes && !ccs_capable(CCS_SYS_SETTIME))
> -+			return -EPERM;
> - 		/*
> - 		 * if the quartz is off by more than 10% then
> - 		 * something is VERY wrong!
> -@@ -642,6 +648,8 @@ int ntp_validate_timex(struct timex *txc
> -
> - 	if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
> - 		return -EPERM;
> -+	if ((txc->modes & ADJ_SETOFFSET) && !ccs_capable(CCS_SYS_SETTIME))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * Check for potential multiplication overflows that can
> ---- linux-4.1.8.orig/net/ipv4/raw.c
> -+++ linux-4.1.8/net/ipv4/raw.c
> -@@ -727,6 +727,10 @@ static int raw_recvmsg(struct sock *sk,
> - 	skb = skb_recv_datagram(sk, flags, noblock, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	copied = skb->len;
> - 	if (len < copied) {
> ---- linux-4.1.8.orig/net/ipv4/udp.c
> -+++ linux-4.1.8/net/ipv4/udp.c
> -@@ -1272,6 +1272,10 @@ try_again:
> - 				  &peeked, &off, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	ulen = skb->len - sizeof(struct udphdr);
> - 	copied = len;
> ---- linux-4.1.8.orig/net/ipv6/raw.c
> -+++ linux-4.1.8/net/ipv6/raw.c
> -@@ -477,6 +477,10 @@ static int rawv6_recvmsg(struct sock *sk
> - 	skb = skb_recv_datagram(sk, flags, noblock, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	copied = skb->len;
> - 	if (copied > len) {
> ---- linux-4.1.8.orig/net/ipv6/udp.c
> -+++ linux-4.1.8/net/ipv6/udp.c
> -@@ -413,6 +413,10 @@ try_again:
> - 				  &peeked, &off, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	ulen = skb->len - sizeof(struct udphdr);
> - 	copied = len;
> ---- linux-4.1.8.orig/net/socket.c
> -+++ linux-4.1.8/net/socket.c
> -@@ -1485,6 +1485,10 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
> - 	if (err < 0)
> - 		goto out_fd;
> -
> -+	if (ccs_socket_post_accept_permission(sock, newsock)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out_fd;
> -+	}
> - 	if (upeer_sockaddr) {
> - 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
> - 					  &len, 2) < 0) {
> ---- linux-4.1.8.orig/net/unix/af_unix.c
> -+++ linux-4.1.8/net/unix/af_unix.c
> -@@ -1800,6 +1800,10 @@ static int unix_dgram_recvmsg(struct soc
> - 	wake_up_interruptible_sync_poll(&u->peer_wait,
> - 					POLLOUT | POLLWRNORM | POLLWRBAND);
> -
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out_unlock;
> -+	}
> - 	if (msg->msg_name)
> - 		unix_copy_addr(msg, skb->sk);
> -
> ---- linux-4.1.8.orig/security/Kconfig
> -+++ linux-4.1.8/security/Kconfig
> -@@ -168,5 +168,7 @@ config DEFAULT_SECURITY
> - 	default "yama" if DEFAULT_SECURITY_YAMA
> - 	default "" if DEFAULT_SECURITY_DAC
> -
> -+source security/ccsecurity/Kconfig
> -+
> - endmenu
> -
> ---- linux-4.1.8.orig/security/Makefile
> -+++ linux-4.1.8/security/Makefile
> -@@ -27,3 +27,6 @@ obj-$(CONFIG_CGROUP_DEVICE)		+= device_c
> - # Object integrity file lists
> - subdir-$(CONFIG_INTEGRITY)		+= integrity
> - obj-$(CONFIG_INTEGRITY)			+= integrity/
> -+
> -+subdir-$(CONFIG_CCSECURITY)		+= ccsecurity
> -+obj-$(CONFIG_CCSECURITY)		+= ccsecurity/
> ---- linux-4.1.8.orig/security/security.c
> -+++ linux-4.1.8/security/security.c
> -@@ -226,7 +226,10 @@ int security_syslog(int type)
> -
> - int security_settime(const struct timespec *ts, const struct timezone *tz)
> - {
> --	return security_ops->settime(ts, tz);
> -+	int error = security_ops->settime(ts, tz);
> -+	if (!error)
> -+		error = ccs_settime(ts, tz);
> -+	return error;
> - }
> -
> - int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
> -@@ -303,17 +306,26 @@ int security_sb_statfs(struct dentry *de
> - int security_sb_mount(const char *dev_name, struct path *path,
> -                        const char *type, unsigned long flags, void *data)
> - {
> --	return security_ops->sb_mount(dev_name, path, type, flags, data);
> -+	int error = security_ops->sb_mount(dev_name, path, type, flags, data);
> -+	if (!error)
> -+		error = ccs_sb_mount(dev_name, path, type, flags, data);
> -+	return error;
> - }
> -
> - int security_sb_umount(struct vfsmount *mnt, int flags)
> - {
> --	return security_ops->sb_umount(mnt, flags);
> -+	int error = security_ops->sb_umount(mnt, flags);
> -+	if (!error)
> -+		error = ccs_sb_umount(mnt, flags);
> -+	return error;
> - }
> -
> - int security_sb_pivotroot(struct path *old_path, struct path *new_path)
> - {
> --	return security_ops->sb_pivotroot(old_path, new_path);
> -+	int error = security_ops->sb_pivotroot(old_path, new_path);
> -+	if (!error)
> -+		error = ccs_sb_pivotroot(old_path, new_path);
> -+	return error;
> - }
> -
> - int security_sb_set_mnt_opts(struct super_block *sb,
> -@@ -410,31 +422,47 @@ EXPORT_SYMBOL(security_old_inode_init_se
> - int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
> - 			unsigned int dev)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_mknod(dir, dentry, mode, dev);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_mknod(dir, dentry, mode, dev);
> - }
> - EXPORT_SYMBOL(security_path_mknod);
> -
> - int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_mkdir(dir, dentry, mode);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_mkdir(dir, dentry, mode);
> - }
> - EXPORT_SYMBOL(security_path_mkdir);
> -
> - int security_path_rmdir(struct path *dir, struct dentry *dentry)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_rmdir(dir, dentry);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_rmdir(dir, dentry);
> - }
> -
> - int security_path_unlink(struct path *dir, struct dentry *dentry)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_unlink(dir, dentry);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_unlink(dir, dentry);
> - }
> - EXPORT_SYMBOL(security_path_unlink);
> -@@ -442,16 +470,24 @@ EXPORT_SYMBOL(security_path_unlink);
> - int security_path_symlink(struct path *dir, struct dentry *dentry,
> - 			  const char *old_name)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_symlink(dir, dentry, old_name);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_symlink(dir, dentry, old_name);
> - }
> -
> - int security_path_link(struct dentry *old_dentry, struct path *new_dir,
> - 		       struct dentry *new_dentry)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
> - 		return 0;
> -+	error = ccs_path_link(old_dentry, new_dir, new_dentry);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_link(old_dentry, new_dir, new_dentry);
> - }
> -
> -@@ -459,6 +495,7 @@ int security_path_rename(struct path *ol
> - 			 struct path *new_dir, struct dentry *new_dentry,
> - 			 unsigned int flags)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
> - 		     (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
> - 		return 0;
> -@@ -468,8 +505,15 @@ int security_path_rename(struct path *ol
> - 						    old_dir, old_dentry);
> - 		if (err)
> - 			return err;
> -+		err = ccs_path_rename(new_dir, new_dentry, old_dir,
> -+				      old_dentry);
> -+		if (err)
> -+			return err;
> - 	}
> -
> -+	error = ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_rename(old_dir, old_dentry, new_dir,
> - 					 new_dentry);
> - }
> -@@ -477,27 +521,42 @@ EXPORT_SYMBOL(security_path_rename);
> -
> - int security_path_truncate(struct path *path)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - 		return 0;
> -+	error = ccs_path_truncate(path);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_truncate(path);
> - }
> -
> - int security_path_chmod(struct path *path, umode_t mode)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - 		return 0;
> -+	error = ccs_path_chmod(path, mode);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_chmod(path, mode);
> - }
> -
> - int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - 		return 0;
> -+	error = ccs_path_chown(path, uid, gid);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_chown(path, uid, gid);
> - }
> -
> - int security_path_chroot(struct path *path)
> - {
> -+	int error = ccs_path_chroot(path);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_chroot(path);
> - }
> - #endif
> -@@ -610,9 +669,13 @@ EXPORT_SYMBOL_GPL(security_inode_setattr
> -
> - int security_inode_getattr(const struct path *path)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - 		return 0;
> --	return security_ops->inode_getattr(path);
> -+	error = security_ops->inode_getattr(path);
> -+	if (!error)
> -+		error = ccs_inode_getattr(path);
> -+	return error;
> - }
> -
> - int security_inode_setxattr(struct dentry *dentry, const char *name,
> -@@ -729,7 +792,10 @@ void security_file_free(struct file *fil
> -
> - int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> - {
> --	return security_ops->file_ioctl(file, cmd, arg);
> -+	int error = security_ops->file_ioctl(file, cmd, arg);
> -+	if (!error)
> -+		error = ccs_file_ioctl(file, cmd, arg);
> -+	return error;
> - }
> -
> - static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
> -@@ -794,7 +860,10 @@ int security_file_lock(struct file *file
> -
> - int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
> - {
> --	return security_ops->file_fcntl(file, cmd, arg);
> -+	int error = security_ops->file_fcntl(file, cmd, arg);
> -+	if (!error)
> -+		error = ccs_file_fcntl(file, cmd, arg);
> -+	return error;
> - }
> -
> - void security_file_set_fowner(struct file *file)
> -@@ -818,6 +887,8 @@ int security_file_open(struct file *file
> - 	int ret;
> -
> - 	ret = security_ops->file_open(file, cred);
> -+	if (!ret)
> -+		ret = ccs_file_open(file, cred);
> - 	if (ret)
> - 		return ret;
> -
> -@@ -1168,7 +1239,10 @@ EXPORT_SYMBOL(security_unix_may_send);
> -
> - int security_socket_create(int family, int type, int protocol, int kern)
> - {
> --	return security_ops->socket_create(family, type, protocol, kern);
> -+	int error = security_ops->socket_create(family, type, protocol, kern);
> -+	if (!error)
> -+		error = ccs_socket_create(family, type, protocol, kern);
> -+	return error;
> - }
> -
> - int security_socket_post_create(struct socket *sock, int family,
> -@@ -1180,17 +1254,26 @@ int security_socket_post_create(struct s
> -
> - int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
> - {
> --	return security_ops->socket_bind(sock, address, addrlen);
> -+	int error = security_ops->socket_bind(sock, address, addrlen);
> -+	if (!error)
> -+		error = ccs_socket_bind(sock, address, addrlen);
> -+	return error;
> - }
> -
> - int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
> - {
> --	return security_ops->socket_connect(sock, address, addrlen);
> -+	int error = security_ops->socket_connect(sock, address, addrlen);
> -+	if (!error)
> -+		error = ccs_socket_connect(sock, address, addrlen);
> -+	return error;
> - }
> -
> - int security_socket_listen(struct socket *sock, int backlog)
> - {
> --	return security_ops->socket_listen(sock, backlog);
> -+	int error = security_ops->socket_listen(sock, backlog);
> -+	if (!error)
> -+		error = ccs_socket_listen(sock, backlog);
> -+	return error;
> - }
> -
> - int security_socket_accept(struct socket *sock, struct socket *newsock)
> -@@ -1200,7 +1283,10 @@ int security_socket_accept(struct socket
> -
> - int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
> - {
> --	return security_ops->socket_sendmsg(sock, msg, size);
> -+	int error = security_ops->socket_sendmsg(sock, msg, size);
> -+	if (!error)
> -+		error = ccs_socket_sendmsg(sock, msg, size);
> -+	return error;
> - }
> -
> - 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
> deleted file mode 100644
> index d1b021a..0000000
> --- a/recipes-kernel/linux/linux-yocto-4.1/ccs-patch-4.2.diff
> +++ /dev/null
> @@ -1,681 +0,0 @@
> -This is TOMOYO Linux patch for kernel 4.2.1.
> -
> -Source code for this patch is https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.2.1.tar.xz
> ----
> - fs/exec.c                 |    2 -
> - fs/open.c                 |    2 +
> - fs/proc/version.c         |    7 +++++
> - include/linux/init_task.h |    9 ++++++
> - include/linux/sched.h     |    6 ++++
> - include/linux/security.h  |   62 ++++++++++++++++++++++++++++------------------
> - include/net/ip.h          |    4 ++
> - kernel/fork.c             |    5 +++
> - kernel/kexec.c            |    3 ++
> - kernel/module.c           |    5 +++
> - kernel/ptrace.c           |   10 +++++++
> - kernel/reboot.c           |    3 ++
> - kernel/sched/core.c       |    2 +
> - kernel/signal.c           |   10 +++++++
> - kernel/sys.c              |    8 +++++
> - kernel/time/ntp.c         |    8 +++++
> - net/ipv4/raw.c            |    4 ++
> - net/ipv4/udp.c            |    4 ++
> - net/ipv6/raw.c            |    4 ++
> - net/ipv6/udp.c            |    4 ++
> - net/socket.c              |    4 ++
> - net/unix/af_unix.c        |    4 ++
> - security/Kconfig          |    2 +
> - security/Makefile         |    3 ++
> - 24 files changed, 150 insertions(+), 25 deletions(-)
> -
> ---- linux-4.2.1.orig/fs/exec.c
> -+++ linux-4.2.1/fs/exec.c
> -@@ -1461,7 +1461,7 @@ static int exec_binprm(struct linux_binp
> - 	old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
> - 	rcu_read_unlock();
> -
> --	ret = search_binary_handler(bprm);
> -+	ret = ccs_search_binary_handler(bprm);
> - 	if (ret >= 0) {
> - 		audit_bprm(bprm);
> - 		trace_sched_process_exec(current, old_pid, bprm);
> ---- linux-4.2.1.orig/fs/open.c
> -+++ linux-4.2.1/fs/open.c
> -@@ -1117,6 +1117,8 @@ EXPORT_SYMBOL(sys_close);
> -  */
> - SYSCALL_DEFINE0(vhangup)
> - {
> -+	if (!ccs_capable(CCS_SYS_VHANGUP))
> -+		return -EPERM;
> - 	if (capable(CAP_SYS_TTY_CONFIG)) {
> - 		tty_vhangup_self();
> - 		return 0;
> ---- linux-4.2.1.orig/fs/proc/version.c
> -+++ linux-4.2.1/fs/proc/version.c
> -@@ -32,3 +32,10 @@ static int __init proc_version_init(void
> - 	return 0;
> - }
> - fs_initcall(proc_version_init);
> -+
> -+static int __init ccs_show_version(void)
> -+{
> -+	printk(KERN_INFO "Hook version: 4.2 2015/09/26\n");
> -+	return 0;
> -+}
> -+fs_initcall(ccs_show_version);
> ---- linux-4.2.1.orig/include/linux/init_task.h
> -+++ linux-4.2.1/include/linux/init_task.h
> -@@ -173,6 +173,14 @@ extern struct task_group root_task_group
> - # define INIT_KASAN(tsk)
> - #endif
> -
> -+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
> -+#define INIT_CCSECURITY          \
> -+	.ccs_domain_info = NULL, \
> -+	.ccs_flags = 0,
> -+#else
> -+#define INIT_CCSECURITY
> -+#endif
> -+
> - /*
> -  *  INIT_TASK is used to set up the first task table, touch at
> -  * your own risk!. Base=0, limit=0x1fffff (=2MB)
> -@@ -249,6 +257,7 @@ extern struct task_group root_task_group
> - 	INIT_VTIME(tsk)							\
> - 	INIT_NUMA_BALANCING(tsk)					\
> - 	INIT_KASAN(tsk)							\
> -+	INIT_CCSECURITY                                                 \
> - }
> -
> -
> ---- linux-4.2.1.orig/include/linux/sched.h
> -+++ linux-4.2.1/include/linux/sched.h
> -@@ -6,6 +6,8 @@
> - #include <linux/sched/prio.h>
> -
> -
> -+struct ccs_domain_info;
> -+
> - struct sched_param {
> - 	int sched_priority;
> - };
> -@@ -1776,6 +1778,10 @@ struct task_struct {
> - 	unsigned long	task_state_change;
> - #endif
> - 	int pagefault_disabled;
> -+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
> -+	struct ccs_domain_info *ccs_domain_info;
> -+	u32 ccs_flags;
> -+#endif
> - /* CPU-specific state of this task */
> - 	struct thread_struct thread;
> - /*
> ---- linux-4.2.1.orig/include/linux/security.h
> -+++ linux-4.2.1/include/linux/security.h
> -@@ -53,6 +53,7 @@ struct msg_queue;
> - struct xattr;
> - struct xfrm_sec_ctx;
> - struct mm_struct;
> -+#include <linux/ccsecurity.h>
> -
> - /* If capable should audit the security request */
> - #define SECURITY_CAP_NOAUDIT 0
> -@@ -460,7 +461,10 @@ static inline int security_syslog(int ty
> - static inline int security_settime(const struct timespec *ts,
> - 				   const struct timezone *tz)
> - {
> --	return cap_settime(ts, tz);
> -+	int error = cap_settime(ts, tz);
> -+	if (!error)
> -+		error = ccs_settime(ts, tz);
> -+	return error;
> - }
> -
> - static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
> -@@ -529,18 +533,18 @@ static inline int security_sb_mount(cons
> - 				    const char *type, unsigned long flags,
> - 				    void *data)
> - {
> --	return 0;
> -+	return ccs_sb_mount(dev_name, path, type, flags, data);
> - }
> -
> - static inline int security_sb_umount(struct vfsmount *mnt, int flags)
> - {
> --	return 0;
> -+	return ccs_sb_umount(mnt, flags);
> - }
> -
> - static inline int security_sb_pivotroot(struct path *old_path,
> - 					struct path *new_path)
> - {
> --	return 0;
> -+	return ccs_sb_pivotroot(old_path, new_path);
> - }
> -
> - static inline int security_sb_set_mnt_opts(struct super_block *sb,
> -@@ -679,7 +683,7 @@ static inline int security_inode_setattr
> -
> - static inline int security_inode_getattr(const struct path *path)
> - {
> --	return 0;
> -+	return ccs_inode_getattr(path);
> - }
> -
> - static inline int security_inode_setxattr(struct dentry *dentry,
> -@@ -755,7 +759,7 @@ static inline void security_file_free(st
> - static inline int security_file_ioctl(struct file *file, unsigned int cmd,
> - 				      unsigned long arg)
> - {
> --	return 0;
> -+	return ccs_file_ioctl(file, cmd, arg);
> - }
> -
> - static inline int security_mmap_file(struct file *file, unsigned long prot,
> -@@ -784,7 +788,7 @@ static inline int security_file_lock(str
> - static inline int security_file_fcntl(struct file *file, unsigned int cmd,
> - 				      unsigned long arg)
> - {
> --	return 0;
> -+	return ccs_file_fcntl(file, cmd, arg);
> - }
> -
> - static inline void security_file_set_fowner(struct file *file)
> -@@ -807,7 +811,7 @@ static inline int security_file_receive(
> - static inline int security_file_open(struct file *file,
> - 				     const struct cred *cred)
> - {
> --	return 0;
> -+	return ccs_file_open(file, cred);
> - }
> -
> - static inline int security_task_create(unsigned long clone_flags)
> -@@ -1169,7 +1173,7 @@ static inline int security_unix_may_send
> - static inline int security_socket_create(int family, int type,
> - 					 int protocol, int kern)
> - {
> --	return 0;
> -+	return ccs_socket_create(family, type, protocol, kern);
> - }
> -
> - static inline int security_socket_post_create(struct socket *sock,
> -@@ -1184,19 +1188,19 @@ static inline int security_socket_bind(s
> - 				       struct sockaddr *address,
> - 				       int addrlen)
> - {
> --	return 0;
> -+	return ccs_socket_bind(sock, address, addrlen);
> - }
> -
> - static inline int security_socket_connect(struct socket *sock,
> - 					  struct sockaddr *address,
> - 					  int addrlen)
> - {
> --	return 0;
> -+	return ccs_socket_connect(sock, address, addrlen);
> - }
> -
> - static inline int security_socket_listen(struct socket *sock, int backlog)
> - {
> --	return 0;
> -+	return ccs_socket_listen(sock, backlog);
> - }
> -
> - static inline int security_socket_accept(struct socket *sock,
> -@@ -1208,7 +1212,7 @@ static inline int security_socket_accept
> - static inline int security_socket_sendmsg(struct socket *sock,
> - 					  struct msghdr *msg, int size)
> - {
> --	return 0;
> -+	return ccs_socket_sendmsg(sock, msg, size);
> - }
> -
> - static inline int security_socket_recvmsg(struct socket *sock,
> -@@ -1450,42 +1454,42 @@ int security_path_chroot(struct path *pa
> - #else	/* CONFIG_SECURITY_PATH */
> - static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
> - {
> --	return 0;
> -+	return ccs_path_unlink(dir, dentry);
> - }
> -
> - static inline int security_path_mkdir(struct path *dir, struct dentry *dentry,
> - 				      umode_t mode)
> - {
> --	return 0;
> -+	return ccs_path_mkdir(dir, dentry, mode);
> - }
> -
> - static inline int security_path_rmdir(struct path *dir, struct dentry *dentry)
> - {
> --	return 0;
> -+	return ccs_path_rmdir(dir, dentry);
> - }
> -
> - static inline int security_path_mknod(struct path *dir, struct dentry *dentry,
> - 				      umode_t mode, unsigned int dev)
> - {
> --	return 0;
> -+	return ccs_path_mknod(dir, dentry, mode, dev);
> - }
> -
> - static inline int security_path_truncate(struct path *path)
> - {
> --	return 0;
> -+	return ccs_path_truncate(path);
> - }
> -
> - static inline int security_path_symlink(struct path *dir, struct dentry *dentry,
> - 					const char *old_name)
> - {
> --	return 0;
> -+	return ccs_path_symlink(dir, dentry, old_name);
> - }
> -
> - static inline int security_path_link(struct dentry *old_dentry,
> - 				     struct path *new_dir,
> - 				     struct dentry *new_dentry)
> - {
> --	return 0;
> -+	return ccs_path_link(old_dentry, new_dir, new_dentry);
> - }
> -
> - static inline int security_path_rename(struct path *old_dir,
> -@@ -1494,22 +1498,32 @@ static inline int security_path_rename(s
> - 				       struct dentry *new_dentry,
> - 				       unsigned int flags)
> - {
> --	return 0;
> -+	/*
> -+	 * Not using RENAME_EXCHANGE here in order to avoid KABI breakage
> -+	 * by doing "#include <uapi/linux/fs.h>" .
> -+	 */
> -+	if (flags & (1 << 1)) {
> -+		int err = ccs_path_rename(new_dir, new_dentry, old_dir,
> -+					  old_dentry);
> -+		if (err)
> -+			return err;
> -+	}
> -+	return ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
> - }
> -
> - static inline int security_path_chmod(struct path *path, umode_t mode)
> - {
> --	return 0;
> -+	return ccs_path_chmod(path, mode);
> - }
> -
> - static inline int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
> - {
> --	return 0;
> -+	return ccs_path_chown(path, uid, gid);
> - }
> -
> - static inline int security_path_chroot(struct path *path)
> - {
> --	return 0;
> -+	return ccs_path_chroot(path);
> - }
> - #endif	/* CONFIG_SECURITY_PATH */
> -
> ---- linux-4.2.1.orig/include/net/ip.h
> -+++ linux-4.2.1/include/net/ip.h
> -@@ -217,6 +217,8 @@ void inet_get_local_port_range(struct ne
> - #ifdef CONFIG_SYSCTL
> - static inline int inet_is_local_reserved_port(struct net *net, int port)
> - {
> -+	if (ccs_lport_reserved(port))
> -+		return 1;
> - 	if (!net->ipv4.sysctl_local_reserved_ports)
> - 		return 0;
> - 	return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
> -@@ -230,6 +232,8 @@ static inline bool sysctl_dev_name_is_al
> - #else
> - static inline int inet_is_local_reserved_port(struct net *net, int port)
> - {
> -+	if (ccs_lport_reserved(port))
> -+		return 1;
> - 	return 0;
> - }
> - #endif
> ---- linux-4.2.1.orig/kernel/fork.c
> -+++ linux-4.2.1/kernel/fork.c
> -@@ -257,6 +257,7 @@ void __put_task_struct(struct task_struc
> - 	delayacct_tsk_free(tsk);
> - 	put_signal_struct(tsk->signal);
> -
> -+	ccs_free_task_security(tsk);
> - 	if (!profile_handoff_task(tsk))
> - 		free_task(tsk);
> - }
> -@@ -1425,6 +1426,9 @@ static struct task_struct *copy_process(
> - 		goto bad_fork_cleanup_perf;
> - 	/* copy all the process information */
> - 	shm_init_task(p);
> -+	retval = ccs_alloc_task_security(p);
> -+	if (retval)
> -+		goto bad_fork_cleanup_audit;
> - 	retval = copy_semundo(clone_flags, p);
> - 	if (retval)
> - 		goto bad_fork_cleanup_audit;
> -@@ -1629,6 +1633,7 @@ bad_fork_cleanup_semundo:
> - 	exit_sem(p);
> - bad_fork_cleanup_audit:
> - 	audit_free(p);
> -+	ccs_free_task_security(p);
> - bad_fork_cleanup_perf:
> - 	perf_event_free_task(p);
> - bad_fork_cleanup_policy:
> ---- linux-4.2.1.orig/kernel/kexec.c
> -+++ linux-4.2.1/kernel/kexec.c
> -@@ -41,6 +41,7 @@
> - #include <asm/uaccess.h>
> - #include <asm/io.h>
> - #include <asm/sections.h>
> -+#include <linux/ccsecurity.h>
> -
> - #include <crypto/hash.h>
> - #include <crypto/sha.h>
> -@@ -1256,6 +1257,8 @@ SYSCALL_DEFINE4(kexec_load, unsigned lon
> - 	/* We only trust the superuser with rebooting the system. */
> - 	if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
> - 		return -EPERM;
> -+	if (!ccs_capable(CCS_SYS_KEXEC_LOAD))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * Verify we have a legal set of flags
> ---- linux-4.2.1.orig/kernel/module.c
> -+++ linux-4.2.1/kernel/module.c
> -@@ -61,6 +61,7 @@
> - #include <linux/bsearch.h>
> - #include <uapi/linux/module.h>
> - #include "module-internal.h"
> -+#include <linux/ccsecurity.h>
> -
> - #define CREATE_TRACE_POINTS
> - #include <trace/events/module.h>
> -@@ -956,6 +957,8 @@ SYSCALL_DEFINE2(delete_module, const cha
> -
> - 	if (!capable(CAP_SYS_MODULE) || modules_disabled)
> - 		return -EPERM;
> -+	if (!ccs_capable(CCS_USE_KERNEL_MODULE))
> -+		return -EPERM;
> -
> - 	if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
> - 		return -EFAULT;
> -@@ -3311,6 +3314,8 @@ static int may_init_module(void)
> - {
> - 	if (!capable(CAP_SYS_MODULE) || modules_disabled)
> - 		return -EPERM;
> -+	if (!ccs_capable(CCS_USE_KERNEL_MODULE))
> -+		return -EPERM;
> -
> - 	return 0;
> - }
> ---- linux-4.2.1.orig/kernel/ptrace.c
> -+++ linux-4.2.1/kernel/ptrace.c
> -@@ -1034,6 +1034,11 @@ SYSCALL_DEFINE4(ptrace, long, request, l
> - {
> - 	struct task_struct *child;
> - 	long ret;
> -+	{
> -+		const int rc = ccs_ptrace_permission(request, pid);
> -+		if (rc)
> -+			return rc;
> -+	}
> -
> - 	if (request == PTRACE_TRACEME) {
> - 		ret = ptrace_traceme();
> -@@ -1180,6 +1185,11 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_lo
> - {
> - 	struct task_struct *child;
> - 	long ret;
> -+	{
> -+		const int rc = ccs_ptrace_permission(request, pid);
> -+		if (rc)
> -+			return rc;
> -+	}
> -
> - 	if (request == PTRACE_TRACEME) {
> - 		ret = ptrace_traceme();
> ---- linux-4.2.1.orig/kernel/reboot.c
> -+++ linux-4.2.1/kernel/reboot.c
> -@@ -16,6 +16,7 @@
> - #include <linux/syscalls.h>
> - #include <linux/syscore_ops.h>
> - #include <linux/uaccess.h>
> -+#include <linux/ccsecurity.h>
> -
> - /*
> -  * this indicates whether you can reboot with ctrl-alt-del: the default is yes
> -@@ -295,6 +296,8 @@ SYSCALL_DEFINE4(reboot, int, magic1, int
> - 			magic2 != LINUX_REBOOT_MAGIC2B &&
> - 			magic2 != LINUX_REBOOT_MAGIC2C))
> - 		return -EINVAL;
> -+	if (!ccs_capable(CCS_SYS_REBOOT))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * If pid namespaces are enabled and the current task is in a child
> ---- linux-4.2.1.orig/kernel/sched/core.c
> -+++ linux-4.2.1/kernel/sched/core.c
> -@@ -3402,6 +3402,8 @@ int can_nice(const struct task_struct *p
> - SYSCALL_DEFINE1(nice, int, increment)
> - {
> - 	long nice, retval;
> -+	if (!ccs_capable(CCS_SYS_NICE))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * Setpriority might change our priority at the same moment.
> ---- linux-4.2.1.orig/kernel/signal.c
> -+++ linux-4.2.1/kernel/signal.c
> -@@ -2896,6 +2896,8 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const s
> - SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
> - {
> - 	struct siginfo info;
> -+	if (ccs_kill_permission(pid, sig))
> -+		return -EPERM;
> -
> - 	info.si_signo = sig;
> - 	info.si_errno = 0;
> -@@ -2964,6 +2966,8 @@ SYSCALL_DEFINE3(tgkill, pid_t, tgid, pid
> - 	/* This is only valid for single tasks */
> - 	if (pid <= 0 || tgid <= 0)
> - 		return -EINVAL;
> -+	if (ccs_tgkill_permission(tgid, pid, sig))
> -+		return -EPERM;
> -
> - 	return do_tkill(tgid, pid, sig);
> - }
> -@@ -2980,6 +2984,8 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int,
> - 	/* This is only valid for single tasks */
> - 	if (pid <= 0)
> - 		return -EINVAL;
> -+	if (ccs_tkill_permission(pid, sig))
> -+		return -EPERM;
> -
> - 	return do_tkill(0, pid, sig);
> - }
> -@@ -2994,6 +3000,8 @@ static int do_rt_sigqueueinfo(pid_t pid,
> - 		return -EPERM;
> -
> - 	info->si_signo = sig;
> -+	if (ccs_sigqueue_permission(pid, sig))
> -+		return -EPERM;
> -
> - 	/* POSIX.1b doesn't mention process groups.  */
> - 	return kill_proc_info(sig, info, pid);
> -@@ -3042,6 +3050,8 @@ static int do_rt_tgsigqueueinfo(pid_t tg
> - 		return -EPERM;
> -
> - 	info->si_signo = sig;
> -+	if (ccs_tgsigqueue_permission(tgid, pid, sig))
> -+		return -EPERM;
> -
> - 	return do_send_specific(tgid, pid, sig, info);
> - }
> ---- linux-4.2.1.orig/kernel/sys.c
> -+++ linux-4.2.1/kernel/sys.c
> -@@ -183,6 +183,10 @@ SYSCALL_DEFINE3(setpriority, int, which,
> -
> - 	if (which > PRIO_USER || which < PRIO_PROCESS)
> - 		goto out;
> -+	if (!ccs_capable(CCS_SYS_NICE)) {
> -+		error = -EPERM;
> -+		goto out;
> -+	}
> -
> - 	/* normalize: avoid signed division (rounding problems) */
> - 	error = -ESRCH;
> -@@ -1222,6 +1226,8 @@ SYSCALL_DEFINE2(sethostname, char __user
> -
> - 	if (len < 0 || len > __NEW_UTS_LEN)
> - 		return -EINVAL;
> -+	if (!ccs_capable(CCS_SYS_SETHOSTNAME))
> -+		return -EPERM;
> - 	down_write(&uts_sem);
> - 	errno = -EFAULT;
> - 	if (!copy_from_user(tmp, name, len)) {
> -@@ -1272,6 +1278,8 @@ SYSCALL_DEFINE2(setdomainname, char __us
> - 		return -EPERM;
> - 	if (len < 0 || len > __NEW_UTS_LEN)
> - 		return -EINVAL;
> -+	if (!ccs_capable(CCS_SYS_SETHOSTNAME))
> -+		return -EPERM;
> -
> - 	down_write(&uts_sem);
> - 	errno = -EFAULT;
> ---- linux-4.2.1.orig/kernel/time/ntp.c
> -+++ linux-4.2.1/kernel/time/ntp.c
> -@@ -16,6 +16,7 @@
> - #include <linux/mm.h>
> - #include <linux/module.h>
> - #include <linux/rtc.h>
> -+#include <linux/ccsecurity.h>
> -
> - #include "ntp_internal.h"
> -
> -@@ -655,10 +656,15 @@ int ntp_validate_timex(struct timex *txc
> - 		if (!(txc->modes & ADJ_OFFSET_READONLY) &&
> - 		    !capable(CAP_SYS_TIME))
> - 			return -EPERM;
> -+		if (!(txc->modes & ADJ_OFFSET_READONLY) &&
> -+		    !ccs_capable(CCS_SYS_SETTIME))
> -+			return -EPERM;
> - 	} else {
> - 		/* In order to modify anything, you gotta be super-user! */
> - 		 if (txc->modes && !capable(CAP_SYS_TIME))
> - 			return -EPERM;
> -+		if (txc->modes && !ccs_capable(CCS_SYS_SETTIME))
> -+			return -EPERM;
> - 		/*
> - 		 * if the quartz is off by more than 10% then
> - 		 * something is VERY wrong!
> -@@ -671,6 +677,8 @@ int ntp_validate_timex(struct timex *txc
> -
> - 	if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
> - 		return -EPERM;
> -+	if ((txc->modes & ADJ_SETOFFSET) && !ccs_capable(CCS_SYS_SETTIME))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * Check for potential multiplication overflows that can
> ---- linux-4.2.1.orig/net/ipv4/raw.c
> -+++ linux-4.2.1/net/ipv4/raw.c
> -@@ -727,6 +727,10 @@ static int raw_recvmsg(struct sock *sk,
> - 	skb = skb_recv_datagram(sk, flags, noblock, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	copied = skb->len;
> - 	if (len < copied) {
> ---- linux-4.2.1.orig/net/ipv4/udp.c
> -+++ linux-4.2.1/net/ipv4/udp.c
> -@@ -1272,6 +1272,10 @@ try_again:
> - 				  &peeked, &off, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	ulen = skb->len - sizeof(struct udphdr);
> - 	copied = len;
> ---- linux-4.2.1.orig/net/ipv6/raw.c
> -+++ linux-4.2.1/net/ipv6/raw.c
> -@@ -477,6 +477,10 @@ static int rawv6_recvmsg(struct sock *sk
> - 	skb = skb_recv_datagram(sk, flags, noblock, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	copied = skb->len;
> - 	if (copied > len) {
> ---- linux-4.2.1.orig/net/ipv6/udp.c
> -+++ linux-4.2.1/net/ipv6/udp.c
> -@@ -413,6 +413,10 @@ try_again:
> - 				  &peeked, &off, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	ulen = skb->len - sizeof(struct udphdr);
> - 	copied = len;
> ---- linux-4.2.1.orig/net/socket.c
> -+++ linux-4.2.1/net/socket.c
> -@@ -1482,6 +1482,10 @@ SYSCALL_DEFINE4(accept4, int, fd, struct
> - 	if (err < 0)
> - 		goto out_fd;
> -
> -+	if (ccs_socket_post_accept_permission(sock, newsock)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out_fd;
> -+	}
> - 	if (upeer_sockaddr) {
> - 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
> - 					  &len, 2) < 0) {
> ---- linux-4.2.1.orig/net/unix/af_unix.c
> -+++ linux-4.2.1/net/unix/af_unix.c
> -@@ -1911,6 +1911,10 @@ static int unix_dgram_recvmsg(struct soc
> - 	wake_up_interruptible_sync_poll(&u->peer_wait,
> - 					POLLOUT | POLLWRNORM | POLLWRBAND);
> -
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out_unlock;
> -+	}
> - 	if (msg->msg_name)
> - 		unix_copy_addr(msg, skb->sk);
> -
> ---- linux-4.2.1.orig/security/Kconfig
> -+++ linux-4.2.1/security/Kconfig
> -@@ -168,5 +168,7 @@ config DEFAULT_SECURITY
> - 	default "yama" if DEFAULT_SECURITY_YAMA
> - 	default "" if DEFAULT_SECURITY_DAC
> -
> -+source security/ccsecurity/Kconfig
> -+
> - endmenu
> -
> ---- linux-4.2.1.orig/security/Makefile
> -+++ linux-4.2.1/security/Makefile
> -@@ -27,3 +27,6 @@ obj-$(CONFIG_CGROUP_DEVICE)		+= device_c
> - # Object integrity file lists
> - subdir-$(CONFIG_INTEGRITY)		+= integrity
> - obj-$(CONFIG_INTEGRITY)			+= integrity/
> -+
> -+subdir-$(CONFIG_CCSECURITY)		+= ccsecurity
> -+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
> deleted file mode 100644
> index 611d396..0000000
> --- a/recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto.4.1.patch
> +++ /dev/null
> @@ -1,1029 +0,0 @@
> -From 13c3a21c549a87cf7410bd2ff88eeb6cb1ddda8c Mon Sep 17 00:00:00 2001
> -From: invalid_git config <unknown at unknown>
> -Date: Sun, 25 Oct 2015 12:34:02 -0700
> -Subject: [PATCH] This is TOMOYO Linux patch for kernel 4.1.8.
> -
> -Source code for this patch is https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.1.8.tar.xz
> ----
> - fs/exec.c                 |   2 +-
> - fs/open.c                 |   2 +
> - fs/proc/version.c         |   7 +++
> - include/linux/init_task.h |   9 ++++
> - include/linux/sched.h     |   6 +++
> - include/linux/security.h  |  62 ++++++++++++++++----------
> - include/net/ip.h          |   4 ++
> - kernel/fork.c             |   5 +++
> - kernel/kexec.c            |   3 ++
> - kernel/module.c           |   5 +++
> - kernel/ptrace.c           |  10 +++++
> - kernel/reboot.c           |   3 ++
> - kernel/sched/core.c       |   2 +
> - kernel/signal.c           |  10 +++++
> - kernel/sys.c              |   8 ++++
> - kernel/time/ntp.c         |   8 ++++
> - net/ipv4/raw.c            |   4 ++
> - net/ipv4/udp.c            |   4 ++
> - net/ipv6/raw.c            |   4 ++
> - net/ipv6/udp.c            |   4 ++
> - net/socket.c              |   4 ++
> - net/unix/af_unix.c        |   4 ++
> - security/Kconfig          |   2 +
> - security/Makefile         |   3 ++
> - security/security.c       | 110 +++++++++++++++++++++++++++++++++++++++++-----
> - 25 files changed, 248 insertions(+), 37 deletions(-)
> -
> -diff --git a/fs/exec.c b/fs/exec.c
> -index 1977c2a..5c69bcc 100644
> ---- a/fs/exec.c
> -+++ b/fs/exec.c
> -@@ -1461,7 +1461,7 @@ static int exec_binprm(struct linux_binprm *bprm)
> - 	old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
> - 	rcu_read_unlock();
> -
> --	ret = search_binary_handler(bprm);
> -+	ret = ccs_search_binary_handler(bprm);
> - 	if (ret >= 0) {
> - 		audit_bprm(bprm);
> - 		trace_sched_process_exec(current, old_pid, bprm);
> -diff --git a/fs/open.c b/fs/open.c
> -index a94e2e7..6c79f72c 100644
> ---- a/fs/open.c
> -+++ b/fs/open.c
> -@@ -1108,6 +1108,8 @@ EXPORT_SYMBOL(sys_close);
> -  */
> - SYSCALL_DEFINE0(vhangup)
> - {
> -+	if (!ccs_capable(CCS_SYS_VHANGUP))
> -+		return -EPERM;
> - 	if (capable(CAP_SYS_TTY_CONFIG)) {
> - 		tty_vhangup_self();
> - 		return 0;
> -diff --git a/fs/proc/version.c b/fs/proc/version.c
> -index d2154eb..a84ba8d 100644
> ---- a/fs/proc/version.c
> -+++ b/fs/proc/version.c
> -@@ -32,3 +32,10 @@ static int __init proc_version_init(void)
> - 	return 0;
> - }
> - fs_initcall(proc_version_init);
> -+
> -+static int __init ccs_show_version(void)
> -+{
> -+	printk(KERN_INFO "Hook version: 4.1.8 2015/09/26\n");
> -+	return 0;
> -+}
> -+fs_initcall(ccs_show_version);
> -diff --git a/include/linux/init_task.h b/include/linux/init_task.h
> -index 696d223..c112803 100644
> ---- a/include/linux/init_task.h
> -+++ b/include/linux/init_task.h
> -@@ -182,6 +182,14 @@ extern struct task_group root_task_group;
> - # define INIT_KASAN(tsk)
> - #endif
> -
> -+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
> -+#define INIT_CCSECURITY          \
> -+	.ccs_domain_info = NULL, \
> -+	.ccs_flags = 0,
> -+#else
> -+#define INIT_CCSECURITY
> -+#endif
> -+
> - /*
> -  *  INIT_TASK is used to set up the first task table, touch at
> -  * your own risk!. Base=0, limit=0x1fffff (=2MB)
> -@@ -258,6 +266,7 @@ extern struct task_group root_task_group;
> - 	INIT_VTIME(tsk)							\
> - 	INIT_NUMA_BALANCING(tsk)					\
> - 	INIT_KASAN(tsk)							\
> -+	INIT_CCSECURITY                                                 \
> - }
> -
> -
> -diff --git a/include/linux/sched.h b/include/linux/sched.h
> -index 26a2e61..c32a704 100644
> ---- a/include/linux/sched.h
> -+++ b/include/linux/sched.h
> -@@ -6,6 +6,8 @@
> - #include <linux/sched/prio.h>
> -
> -
> -+struct ccs_domain_info;
> -+
> - struct sched_param {
> - 	int sched_priority;
> - };
> -@@ -1724,6 +1726,10 @@ struct task_struct {
> - #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
> - 	unsigned long	task_state_change;
> - #endif
> -+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
> -+	struct ccs_domain_info *ccs_domain_info;
> -+	u32 ccs_flags;
> -+#endif
> - };
> -
> - /* Future-safe accessor for struct task_struct's cpus_allowed. */
> -diff --git a/include/linux/security.h b/include/linux/security.h
> -index 18264ea..621562b 100644
> ---- a/include/linux/security.h
> -+++ b/include/linux/security.h
> -@@ -53,6 +53,7 @@ struct msg_queue;
> - struct xattr;
> - struct xfrm_sec_ctx;
> - struct mm_struct;
> -+#include <linux/ccsecurity.h>
> -
> - /* Maximum number of letters for an LSM name string */
> - #define SECURITY_NAME_MAX	10
> -@@ -2042,7 +2043,10 @@ static inline int security_syslog(int type)
> - static inline int security_settime(const struct timespec *ts,
> - 				   const struct timezone *tz)
> - {
> --	return cap_settime(ts, tz);
> -+	int error = cap_settime(ts, tz);
> -+	if (!error)
> -+		error = ccs_settime(ts, tz);
> -+	return error;
> - }
> -
> - static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
> -@@ -2111,18 +2115,18 @@ static inline int security_sb_mount(const char *dev_name, struct path *path,
> - 				    const char *type, unsigned long flags,
> - 				    void *data)
> - {
> --	return 0;
> -+	return ccs_sb_mount(dev_name, path, type, flags, data);
> - }
> -
> - static inline int security_sb_umount(struct vfsmount *mnt, int flags)
> - {
> --	return 0;
> -+	return ccs_sb_umount(mnt, flags);
> - }
> -
> - static inline int security_sb_pivotroot(struct path *old_path,
> - 					struct path *new_path)
> - {
> --	return 0;
> -+	return ccs_sb_pivotroot(old_path, new_path);
> - }
> -
> - static inline int security_sb_set_mnt_opts(struct super_block *sb,
> -@@ -2260,7 +2264,7 @@ static inline int security_inode_setattr(struct dentry *dentry,
> -
> - static inline int security_inode_getattr(const struct path *path)
> - {
> --	return 0;
> -+	return ccs_inode_getattr(path);
> - }
> -
> - static inline int security_inode_setxattr(struct dentry *dentry,
> -@@ -2336,7 +2340,7 @@ static inline void security_file_free(struct file *file)
> - static inline int security_file_ioctl(struct file *file, unsigned int cmd,
> - 				      unsigned long arg)
> - {
> --	return 0;
> -+	return ccs_file_ioctl(file, cmd, arg);
> - }
> -
> - static inline int security_mmap_file(struct file *file, unsigned long prot,
> -@@ -2365,7 +2369,7 @@ static inline int security_file_lock(struct file *file, unsigned int cmd)
> - static inline int security_file_fcntl(struct file *file, unsigned int cmd,
> - 				      unsigned long arg)
> - {
> --	return 0;
> -+	return ccs_file_fcntl(file, cmd, arg);
> - }
> -
> - static inline void security_file_set_fowner(struct file *file)
> -@@ -2388,7 +2392,7 @@ static inline int security_file_receive(struct file *file)
> - static inline int security_file_open(struct file *file,
> - 				     const struct cred *cred)
> - {
> --	return 0;
> -+	return ccs_file_open(file, cred);
> - }
> -
> - static inline int security_task_create(unsigned long clone_flags)
> -@@ -2750,7 +2754,7 @@ static inline int security_unix_may_send(struct socket *sock,
> - static inline int security_socket_create(int family, int type,
> - 					 int protocol, int kern)
> - {
> --	return 0;
> -+	return ccs_socket_create(family, type, protocol, kern);
> - }
> -
> - static inline int security_socket_post_create(struct socket *sock,
> -@@ -2765,19 +2769,19 @@ static inline int security_socket_bind(struct socket *sock,
> - 				       struct sockaddr *address,
> - 				       int addrlen)
> - {
> --	return 0;
> -+	return ccs_socket_bind(sock, address, addrlen);
> - }
> -
> - static inline int security_socket_connect(struct socket *sock,
> - 					  struct sockaddr *address,
> - 					  int addrlen)
> - {
> --	return 0;
> -+	return ccs_socket_connect(sock, address, addrlen);
> - }
> -
> - static inline int security_socket_listen(struct socket *sock, int backlog)
> - {
> --	return 0;
> -+	return ccs_socket_listen(sock, backlog);
> - }
> -
> - static inline int security_socket_accept(struct socket *sock,
> -@@ -2789,7 +2793,7 @@ static inline int security_socket_accept(struct socket *sock,
> - static inline int security_socket_sendmsg(struct socket *sock,
> - 					  struct msghdr *msg, int size)
> - {
> --	return 0;
> -+	return ccs_socket_sendmsg(sock, msg, size);
> - }
> -
> - static inline int security_socket_recvmsg(struct socket *sock,
> -@@ -3031,42 +3035,42 @@ int security_path_chroot(struct path *path);
> - #else	/* CONFIG_SECURITY_PATH */
> - static inline int security_path_unlink(struct path *dir, struct dentry *dentry)
> - {
> --	return 0;
> -+	return ccs_path_unlink(dir, dentry);
> - }
> -
> - static inline int security_path_mkdir(struct path *dir, struct dentry *dentry,
> - 				      umode_t mode)
> - {
> --	return 0;
> -+	return ccs_path_mkdir(dir, dentry, mode);
> - }
> -
> - static inline int security_path_rmdir(struct path *dir, struct dentry *dentry)
> - {
> --	return 0;
> -+	return ccs_path_rmdir(dir, dentry);
> - }
> -
> - static inline int security_path_mknod(struct path *dir, struct dentry *dentry,
> - 				      umode_t mode, unsigned int dev)
> - {
> --	return 0;
> -+	return ccs_path_mknod(dir, dentry, mode, dev);
> - }
> -
> - static inline int security_path_truncate(struct path *path)
> - {
> --	return 0;
> -+	return ccs_path_truncate(path);
> - }
> -
> - static inline int security_path_symlink(struct path *dir, struct dentry *dentry,
> - 					const char *old_name)
> - {
> --	return 0;
> -+	return ccs_path_symlink(dir, dentry, old_name);
> - }
> -
> - static inline int security_path_link(struct dentry *old_dentry,
> - 				     struct path *new_dir,
> - 				     struct dentry *new_dentry)
> - {
> --	return 0;
> -+	return ccs_path_link(old_dentry, new_dir, new_dentry);
> - }
> -
> - static inline int security_path_rename(struct path *old_dir,
> -@@ -3075,22 +3079,32 @@ static inline int security_path_rename(struct path *old_dir,
> - 				       struct dentry *new_dentry,
> - 				       unsigned int flags)
> - {
> --	return 0;
> -+	/*
> -+	 * Not using RENAME_EXCHANGE here in order to avoid KABI breakage
> -+	 * by doing "#include <uapi/linux/fs.h>" .
> -+	 */
> -+	if (flags & (1 << 1)) {
> -+		int err = ccs_path_rename(new_dir, new_dentry, old_dir,
> -+					  old_dentry);
> -+		if (err)
> -+			return err;
> -+	}
> -+	return ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
> - }
> -
> - static inline int security_path_chmod(struct path *path, umode_t mode)
> - {
> --	return 0;
> -+	return ccs_path_chmod(path, mode);
> - }
> -
> - static inline int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
> - {
> --	return 0;
> -+	return ccs_path_chown(path, uid, gid);
> - }
> -
> - static inline int security_path_chroot(struct path *path)
> - {
> --	return 0;
> -+	return ccs_path_chroot(path);
> - }
> - #endif	/* CONFIG_SECURITY_PATH */
> -
> -diff --git a/include/net/ip.h b/include/net/ip.h
> -index d14af7e..34eb1cb 100644
> ---- a/include/net/ip.h
> -+++ b/include/net/ip.h
> -@@ -216,6 +216,8 @@ void inet_get_local_port_range(struct net *net, int *low, int *high);
> - #ifdef CONFIG_SYSCTL
> - static inline int inet_is_local_reserved_port(struct net *net, int port)
> - {
> -+	if (ccs_lport_reserved(port))
> -+		return 1;
> - 	if (!net->ipv4.sysctl_local_reserved_ports)
> - 		return 0;
> - 	return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
> -@@ -229,6 +231,8 @@ static inline bool sysctl_dev_name_is_allowed(const char *name)
> - #else
> - static inline int inet_is_local_reserved_port(struct net *net, int port)
> - {
> -+	if (ccs_lport_reserved(port))
> -+		return 1;
> - 	return 0;
> - }
> - #endif
> -diff --git a/kernel/fork.c b/kernel/fork.c
> -index 7e215ba..9bce902 100644
> ---- a/kernel/fork.c
> -+++ b/kernel/fork.c
> -@@ -257,6 +257,7 @@ void __put_task_struct(struct task_struct *tsk)
> - 	delayacct_tsk_free(tsk);
> - 	put_signal_struct(tsk->signal);
> -
> -+	ccs_free_task_security(tsk);
> - 	if (!profile_handoff_task(tsk))
> - 		free_task(tsk);
> - }
> -@@ -1423,6 +1424,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
> - 		goto bad_fork_cleanup_perf;
> - 	/* copy all the process information */
> - 	shm_init_task(p);
> -+	retval = ccs_alloc_task_security(p);
> -+	if (retval)
> -+		goto bad_fork_cleanup_audit;
> - 	retval = copy_semundo(clone_flags, p);
> - 	if (retval)
> - 		goto bad_fork_cleanup_audit;
> -@@ -1627,6 +1631,7 @@ bad_fork_cleanup_semundo:
> - 	exit_sem(p);
> - bad_fork_cleanup_audit:
> - 	audit_free(p);
> -+	ccs_free_task_security(p);
> - bad_fork_cleanup_perf:
> - 	perf_event_free_task(p);
> - bad_fork_cleanup_policy:
> -diff --git a/kernel/kexec.c b/kernel/kexec.c
> -index 7a36fdc..294444e 100644
> ---- a/kernel/kexec.c
> -+++ b/kernel/kexec.c
> -@@ -41,6 +41,7 @@
> - #include <asm/uaccess.h>
> - #include <asm/io.h>
> - #include <asm/sections.h>
> -+#include <linux/ccsecurity.h>
> -
> - #include <crypto/hash.h>
> - #include <crypto/sha.h>
> -@@ -1245,6 +1246,8 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments,
> - 	/* We only trust the superuser with rebooting the system. */
> - 	if (!capable(CAP_SYS_BOOT) || kexec_load_disabled)
> - 		return -EPERM;
> -+	if (!ccs_capable(CCS_SYS_KEXEC_LOAD))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * Verify we have a legal set of flags
> -diff --git a/kernel/module.c b/kernel/module.c
> -index cfc9e84..73fd5f5 100644
> ---- a/kernel/module.c
> -+++ b/kernel/module.c
> -@@ -61,6 +61,7 @@
> - #include <linux/bsearch.h>
> - #include <uapi/linux/module.h>
> - #include "module-internal.h"
> -+#include <linux/ccsecurity.h>
> -
> - #define CREATE_TRACE_POINTS
> - #include <trace/events/module.h>
> -@@ -799,6 +800,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
> -
> - 	if (!capable(CAP_SYS_MODULE) || modules_disabled)
> - 		return -EPERM;
> -+	if (!ccs_capable(CCS_USE_KERNEL_MODULE))
> -+		return -EPERM;
> -
> - 	if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
> - 		return -EFAULT;
> -@@ -3155,6 +3158,8 @@ static int may_init_module(void)
> - {
> - 	if (!capable(CAP_SYS_MODULE) || modules_disabled)
> - 		return -EPERM;
> -+	if (!ccs_capable(CCS_USE_KERNEL_MODULE))
> -+		return -EPERM;
> -
> - 	return 0;
> - }
> -diff --git a/kernel/ptrace.c b/kernel/ptrace.c
> -index c8e0e05..4106a2a 100644
> ---- a/kernel/ptrace.c
> -+++ b/kernel/ptrace.c
> -@@ -1034,6 +1034,11 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
> - {
> - 	struct task_struct *child;
> - 	long ret;
> -+	{
> -+		const int rc = ccs_ptrace_permission(request, pid);
> -+		if (rc)
> -+			return rc;
> -+	}
> -
> - 	if (request == PTRACE_TRACEME) {
> - 		ret = ptrace_traceme();
> -@@ -1180,6 +1185,11 @@ COMPAT_SYSCALL_DEFINE4(ptrace, compat_long_t, request, compat_long_t, pid,
> - {
> - 	struct task_struct *child;
> - 	long ret;
> -+	{
> -+		const int rc = ccs_ptrace_permission(request, pid);
> -+		if (rc)
> -+			return rc;
> -+	}
> -
> - 	if (request == PTRACE_TRACEME) {
> - 		ret = ptrace_traceme();
> -diff --git a/kernel/reboot.c b/kernel/reboot.c
> -index d20c85d..61ffd97 100644
> ---- a/kernel/reboot.c
> -+++ b/kernel/reboot.c
> -@@ -16,6 +16,7 @@
> - #include <linux/syscalls.h>
> - #include <linux/syscore_ops.h>
> - #include <linux/uaccess.h>
> -+#include <linux/ccsecurity.h>
> -
> - /*
> -  * this indicates whether you can reboot with ctrl-alt-del: the default is yes
> -@@ -295,6 +296,8 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
> - 			magic2 != LINUX_REBOOT_MAGIC2B &&
> - 			magic2 != LINUX_REBOOT_MAGIC2C))
> - 		return -EINVAL;
> -+	if (!ccs_capable(CCS_SYS_REBOOT))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * If pid namespaces are enabled and the current task is in a child
> -diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> -index e691052..c63bbd8 100644
> ---- a/kernel/sched/core.c
> -+++ b/kernel/sched/core.c
> -@@ -3145,6 +3145,8 @@ int can_nice(const struct task_struct *p, const int nice)
> - SYSCALL_DEFINE1(nice, int, increment)
> - {
> - 	long nice, retval;
> -+	if (!ccs_capable(CCS_SYS_NICE))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * Setpriority might change our priority at the same moment.
> -diff --git a/kernel/signal.c b/kernel/signal.c
> -index 0206be7..9e01cca 100644
> ---- a/kernel/signal.c
> -+++ b/kernel/signal.c
> -@@ -2901,6 +2901,8 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
> - SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
> - {
> - 	struct siginfo info;
> -+	if (ccs_kill_permission(pid, sig))
> -+		return -EPERM;
> -
> - 	info.si_signo = sig;
> - 	info.si_errno = 0;
> -@@ -2969,6 +2971,8 @@ SYSCALL_DEFINE3(tgkill, pid_t, tgid, pid_t, pid, int, sig)
> - 	/* This is only valid for single tasks */
> - 	if (pid <= 0 || tgid <= 0)
> - 		return -EINVAL;
> -+	if (ccs_tgkill_permission(tgid, pid, sig))
> -+		return -EPERM;
> -
> - 	return do_tkill(tgid, pid, sig);
> - }
> -@@ -2985,6 +2989,8 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int, sig)
> - 	/* This is only valid for single tasks */
> - 	if (pid <= 0)
> - 		return -EINVAL;
> -+	if (ccs_tkill_permission(pid, sig))
> -+		return -EPERM;
> -
> - 	return do_tkill(0, pid, sig);
> - }
> -@@ -2999,6 +3005,8 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info)
> - 		return -EPERM;
> -
> - 	info->si_signo = sig;
> -+	if (ccs_sigqueue_permission(pid, sig))
> -+		return -EPERM;
> -
> - 	/* POSIX.1b doesn't mention process groups.  */
> - 	return kill_proc_info(sig, info, pid);
> -@@ -3047,6 +3055,8 @@ static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
> - 		return -EPERM;
> -
> - 	info->si_signo = sig;
> -+	if (ccs_tgsigqueue_permission(tgid, pid, sig))
> -+		return -EPERM;
> -
> - 	return do_send_specific(tgid, pid, sig, info);
> - }
> -diff --git a/kernel/sys.c b/kernel/sys.c
> -index a4e372b..77c6970 100644
> ---- a/kernel/sys.c
> -+++ b/kernel/sys.c
> -@@ -183,6 +183,10 @@ SYSCALL_DEFINE3(setpriority, int, which, int, who, int, niceval)
> -
> - 	if (which > PRIO_USER || which < PRIO_PROCESS)
> - 		goto out;
> -+	if (!ccs_capable(CCS_SYS_NICE)) {
> -+		error = -EPERM;
> -+		goto out;
> -+	}
> -
> - 	/* normalize: avoid signed division (rounding problems) */
> - 	error = -ESRCH;
> -@@ -1222,6 +1226,8 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len)
> -
> - 	if (len < 0 || len > __NEW_UTS_LEN)
> - 		return -EINVAL;
> -+	if (!ccs_capable(CCS_SYS_SETHOSTNAME))
> -+		return -EPERM;
> - 	down_write(&uts_sem);
> - 	errno = -EFAULT;
> - 	if (!copy_from_user(tmp, name, len)) {
> -@@ -1272,6 +1278,8 @@ SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len)
> - 		return -EPERM;
> - 	if (len < 0 || len > __NEW_UTS_LEN)
> - 		return -EINVAL;
> -+	if (!ccs_capable(CCS_SYS_SETHOSTNAME))
> -+		return -EPERM;
> -
> - 	down_write(&uts_sem);
> - 	errno = -EFAULT;
> -diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
> -index 7a68100..3c8766f 100644
> ---- a/kernel/time/ntp.c
> -+++ b/kernel/time/ntp.c
> -@@ -16,6 +16,7 @@
> - #include <linux/mm.h>
> - #include <linux/module.h>
> - #include <linux/rtc.h>
> -+#include <linux/ccsecurity.h>
> -
> - #include "ntp_internal.h"
> -
> -@@ -626,10 +627,15 @@ int ntp_validate_timex(struct timex *txc)
> - 		if (!(txc->modes & ADJ_OFFSET_READONLY) &&
> - 		    !capable(CAP_SYS_TIME))
> - 			return -EPERM;
> -+		if (!(txc->modes & ADJ_OFFSET_READONLY) &&
> -+		    !ccs_capable(CCS_SYS_SETTIME))
> -+			return -EPERM;
> - 	} else {
> - 		/* In order to modify anything, you gotta be super-user! */
> - 		 if (txc->modes && !capable(CAP_SYS_TIME))
> - 			return -EPERM;
> -+		if (txc->modes && !ccs_capable(CCS_SYS_SETTIME))
> -+			return -EPERM;
> - 		/*
> - 		 * if the quartz is off by more than 10% then
> - 		 * something is VERY wrong!
> -@@ -642,6 +648,8 @@ int ntp_validate_timex(struct timex *txc)
> -
> - 	if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
> - 		return -EPERM;
> -+	if ((txc->modes & ADJ_SETOFFSET) && !ccs_capable(CCS_SYS_SETTIME))
> -+		return -EPERM;
> -
> - 	/*
> - 	 * Check for potential multiplication overflows that can
> -diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
> -index 561cd4b..16e23e5 100644
> ---- a/net/ipv4/raw.c
> -+++ b/net/ipv4/raw.c
> -@@ -727,6 +727,10 @@ static int raw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
> - 	skb = skb_recv_datagram(sk, flags, noblock, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	copied = skb->len;
> - 	if (len < copied) {
> -diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> -index 83aa604..0326e29 100644
> ---- a/net/ipv4/udp.c
> -+++ b/net/ipv4/udp.c
> -@@ -1272,6 +1272,10 @@ try_again:
> - 				  &peeked, &off, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	ulen = skb->len - sizeof(struct udphdr);
> - 	copied = len;
> -diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
> -index 8072bd4..fbd33d4 100644
> ---- a/net/ipv6/raw.c
> -+++ b/net/ipv6/raw.c
> -@@ -477,6 +477,10 @@ static int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
> - 	skb = skb_recv_datagram(sk, flags, noblock, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	copied = skb->len;
> - 	if (copied > len) {
> -diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
> -index e51fc3e..5b09dbb 100644
> ---- a/net/ipv6/udp.c
> -+++ b/net/ipv6/udp.c
> -@@ -413,6 +413,10 @@ try_again:
> - 				  &peeked, &off, &err);
> - 	if (!skb)
> - 		goto out;
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out;
> -+	}
> -
> - 	ulen = skb->len - sizeof(struct udphdr);
> - 	copied = len;
> -diff --git a/net/socket.c b/net/socket.c
> -index 884e329..767338ff 100644
> ---- a/net/socket.c
> -+++ b/net/socket.c
> -@@ -1485,6 +1485,10 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
> - 	if (err < 0)
> - 		goto out_fd;
> -
> -+	if (ccs_socket_post_accept_permission(sock, newsock)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out_fd;
> -+	}
> - 	if (upeer_sockaddr) {
> - 		if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
> - 					  &len, 2) < 0) {
> -diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
> -index 0643059..ba5d3d0 100644
> ---- a/net/unix/af_unix.c
> -+++ b/net/unix/af_unix.c
> -@@ -1800,6 +1800,10 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
> - 	wake_up_interruptible_sync_poll(&u->peer_wait,
> - 					POLLOUT | POLLWRNORM | POLLWRBAND);
> -
> -+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags)) {
> -+		err = -EAGAIN; /* Hope less harmful than -EPERM. */
> -+		goto out_unlock;
> -+	}
> - 	if (msg->msg_name)
> - 		unix_copy_addr(msg, skb->sk);
> -
> -diff --git a/security/Kconfig b/security/Kconfig
> -index bf4ec46..4ce2bf2 100644
> ---- a/security/Kconfig
> -+++ b/security/Kconfig
> -@@ -168,5 +168,7 @@ config DEFAULT_SECURITY
> - 	default "yama" if DEFAULT_SECURITY_YAMA
> - 	default "" if DEFAULT_SECURITY_DAC
> -
> -+source security/ccsecurity/Kconfig
> -+
> - endmenu
> -
> -diff --git a/security/Makefile b/security/Makefile
> -index 05f1c93..4a42724 100644
> ---- a/security/Makefile
> -+++ b/security/Makefile
> -@@ -27,3 +27,6 @@ obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
> - # Object integrity file lists
> - subdir-$(CONFIG_INTEGRITY)		+= integrity
> - obj-$(CONFIG_INTEGRITY)			+= integrity/
> -+
> -+subdir-$(CONFIG_CCSECURITY)		+= ccsecurity
> -+obj-$(CONFIG_CCSECURITY)		+= ccsecurity/
> -diff --git a/security/security.c b/security/security.c
> -index c1c7cd1..a8ed3d0 100644
> ---- a/security/security.c
> -+++ b/security/security.c
> -@@ -226,7 +226,10 @@ int security_syslog(int type)
> -
> - int security_settime(const struct timespec *ts, const struct timezone *tz)
> - {
> --	return security_ops->settime(ts, tz);
> -+	int error = security_ops->settime(ts, tz);
> -+	if (!error)
> -+		error = ccs_settime(ts, tz);
> -+	return error;
> - }
> -
> - int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
> -@@ -303,17 +306,26 @@ int security_sb_statfs(struct dentry *dentry)
> - int security_sb_mount(const char *dev_name, struct path *path,
> -                        const char *type, unsigned long flags, void *data)
> - {
> --	return security_ops->sb_mount(dev_name, path, type, flags, data);
> -+	int error = security_ops->sb_mount(dev_name, path, type, flags, data);
> -+	if (!error)
> -+		error = ccs_sb_mount(dev_name, path, type, flags, data);
> -+	return error;
> - }
> -
> - int security_sb_umount(struct vfsmount *mnt, int flags)
> - {
> --	return security_ops->sb_umount(mnt, flags);
> -+	int error = security_ops->sb_umount(mnt, flags);
> -+	if (!error)
> -+		error = ccs_sb_umount(mnt, flags);
> -+	return error;
> - }
> -
> - int security_sb_pivotroot(struct path *old_path, struct path *new_path)
> - {
> --	return security_ops->sb_pivotroot(old_path, new_path);
> -+	int error = security_ops->sb_pivotroot(old_path, new_path);
> -+	if (!error)
> -+		error = ccs_sb_pivotroot(old_path, new_path);
> -+	return error;
> - }
> -
> - int security_sb_set_mnt_opts(struct super_block *sb,
> -@@ -410,32 +422,48 @@ EXPORT_SYMBOL(security_old_inode_init_security);
> - int security_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
> - 			unsigned int dev)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_mknod(dir, dentry, mode, dev);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_mknod(dir, dentry, mode, dev);
> - }
> - EXPORT_SYMBOL(security_path_mknod);
> -
> - int security_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_mkdir(dir, dentry, mode);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_mkdir(dir, dentry, mode);
> - }
> - EXPORT_SYMBOL(security_path_mkdir);
> -
> - int security_path_rmdir(struct path *dir, struct dentry *dentry)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_rmdir(dir, dentry);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_rmdir(dir, dentry);
> - }
> - EXPORT_SYMBOL(security_path_rmdir);
> -
> - int security_path_unlink(struct path *dir, struct dentry *dentry)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_unlink(dir, dentry);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_unlink(dir, dentry);
> - }
> - EXPORT_SYMBOL(security_path_unlink);
> -@@ -443,8 +471,12 @@ EXPORT_SYMBOL(security_path_unlink);
> - int security_path_symlink(struct path *dir, struct dentry *dentry,
> - 			  const char *old_name)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
> - 		return 0;
> -+	error = ccs_path_symlink(dir, dentry, old_name);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_symlink(dir, dentry, old_name);
> - }
> - EXPORT_SYMBOL(security_path_symlink);
> -@@ -452,8 +484,12 @@ EXPORT_SYMBOL(security_path_symlink);
> - int security_path_link(struct dentry *old_dentry, struct path *new_dir,
> - 		       struct dentry *new_dentry)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
> - 		return 0;
> -+	error = ccs_path_link(old_dentry, new_dir, new_dentry);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_link(old_dentry, new_dir, new_dentry);
> - }
> - EXPORT_SYMBOL(security_path_link);
> -@@ -462,6 +498,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
> - 			 struct path *new_dir, struct dentry *new_dentry,
> - 			 unsigned int flags)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) ||
> - 		     (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry)))))
> - 		return 0;
> -@@ -471,8 +508,15 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
> - 						    old_dir, old_dentry);
> - 		if (err)
> - 			return err;
> -+		err = ccs_path_rename(new_dir, new_dentry, old_dir,
> -+				      old_dentry);
> -+		if (err)
> -+			return err;
> - 	}
> -
> -+	error = ccs_path_rename(old_dir, old_dentry, new_dir, new_dentry);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_rename(old_dir, old_dentry, new_dir,
> - 					 new_dentry);
> - }
> -@@ -480,30 +524,45 @@ EXPORT_SYMBOL(security_path_rename);
> -
> - int security_path_truncate(struct path *path)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - 		return 0;
> -+	error = ccs_path_truncate(path);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_truncate(path);
> - }
> - EXPORT_SYMBOL(security_path_truncate);
> -
> - int security_path_chmod(struct path *path, umode_t mode)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - 		return 0;
> -+	error = ccs_path_chmod(path, mode);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_chmod(path, mode);
> - }
> - EXPORT_SYMBOL(security_path_chmod);
> -
> - int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - 		return 0;
> -+	error = ccs_path_chown(path, uid, gid);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_chown(path, uid, gid);
> - }
> - EXPORT_SYMBOL(security_path_chown);
> -
> - int security_path_chroot(struct path *path)
> - {
> -+	int error = ccs_path_chroot(path);
> -+	if (error)
> -+		return error;
> - 	return security_ops->path_chroot(path);
> - }
> - #endif
> -@@ -618,9 +677,13 @@ EXPORT_SYMBOL_GPL(security_inode_setattr);
> -
> - int security_inode_getattr(const struct path *path)
> - {
> -+	int error;
> - 	if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
> - 		return 0;
> --	return security_ops->inode_getattr(path);
> -+	error = security_ops->inode_getattr(path);
> -+	if (!error)
> -+		error = ccs_inode_getattr(path);
> -+	return error;
> - }
> -
> - int security_inode_setxattr(struct dentry *dentry, const char *name,
> -@@ -738,7 +801,10 @@ void security_file_free(struct file *file)
> -
> - int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> - {
> --	return security_ops->file_ioctl(file, cmd, arg);
> -+	int error = security_ops->file_ioctl(file, cmd, arg);
> -+	if (!error)
> -+		error = ccs_file_ioctl(file, cmd, arg);
> -+	return error;
> - }
> -
> - static inline unsigned long mmap_prot(struct file *file, unsigned long prot)
> -@@ -804,7 +870,10 @@ int security_file_lock(struct file *file, unsigned int cmd)
> -
> - int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
> - {
> --	return security_ops->file_fcntl(file, cmd, arg);
> -+	int error = security_ops->file_fcntl(file, cmd, arg);
> -+	if (!error)
> -+		error = ccs_file_fcntl(file, cmd, arg);
> -+	return error;
> - }
> -
> - void security_file_set_fowner(struct file *file)
> -@@ -828,6 +897,8 @@ int security_file_open(struct file *file, const struct cred *cred)
> - 	int ret;
> -
> - 	ret = security_ops->file_open(file, cred);
> -+	if (!ret)
> -+		ret = ccs_file_open(file, cred);
> - 	if (ret)
> - 		return ret;
> -
> -@@ -1178,7 +1249,10 @@ EXPORT_SYMBOL(security_unix_may_send);
> -
> - int security_socket_create(int family, int type, int protocol, int kern)
> - {
> --	return security_ops->socket_create(family, type, protocol, kern);
> -+	int error = security_ops->socket_create(family, type, protocol, kern);
> -+	if (!error)
> -+		error = ccs_socket_create(family, type, protocol, kern);
> -+	return error;
> - }
> -
> - int security_socket_post_create(struct socket *sock, int family,
> -@@ -1190,17 +1264,26 @@ int security_socket_post_create(struct socket *sock, int family,
> -
> - int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
> - {
> --	return security_ops->socket_bind(sock, address, addrlen);
> -+	int error = security_ops->socket_bind(sock, address, addrlen);
> -+	if (!error)
> -+		error = ccs_socket_bind(sock, address, addrlen);
> -+	return error;
> - }
> -
> - int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
> - {
> --	return security_ops->socket_connect(sock, address, addrlen);
> -+	int error = security_ops->socket_connect(sock, address, addrlen);
> -+	if (!error)
> -+		error = ccs_socket_connect(sock, address, addrlen);
> -+	return error;
> - }
> -
> - int security_socket_listen(struct socket *sock, int backlog)
> - {
> --	return security_ops->socket_listen(sock, backlog);
> -+	int error = security_ops->socket_listen(sock, backlog);
> -+	if (!error)
> -+		error = ccs_socket_listen(sock, backlog);
> -+	return error;
> - }
> -
> - int security_socket_accept(struct socket *sock, struct socket *newsock)
> -@@ -1210,7 +1293,10 @@ int security_socket_accept(struct socket *sock, struct socket *newsock)
> -
> - int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
> - {
> --	return security_ops->socket_sendmsg(sock, msg, size);
> -+	int error = security_ops->socket_sendmsg(sock, msg, size);
> -+	if (!error)
> -+		error = ccs_socket_sendmsg(sock, msg, size);
> -+	return error;
> - }
> -
> - int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
> ---
> -1.9.1
> -
> 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
> deleted file mode 100644
> index 33a69a1..0000000
> --- a/recipes-kernel/linux/linux-yocto-4.1/ccs-tools-yocto_security.patch
> +++ /dev/null
> @@ -1,17920 +0,0 @@
> -From d4a329ee417f1b75ba087828bb4b2f62c1ef57bb Mon Sep 17 00:00:00 2001
> -From: Auto Configured <auto.configured>
> -Date: Sun, 25 Oct 2015 12:19:45 -0700
> -Subject: [PATCH] Ci add ccsecuroty
> -
> -Signed-off-by: Auto Configured <auto.configured>
> ----
> - include/linux/ccsecurity.h           |  926 +++++
> - include/linux/lsm2ccsecurity.h       |  181 +
> - security/ccsecurity/Config.in        |   83 +
> - security/ccsecurity/Kconfig          |  190 +
> - security/ccsecurity/Makefile         |  122 +
> - security/ccsecurity/gc.c             | 1036 ++++++
> - security/ccsecurity/internal.h       | 2090 +++++++++++
> - security/ccsecurity/load_policy.c    |  352 ++
> - security/ccsecurity/lsm2ccsecurity.c |  192 +
> - security/ccsecurity/memory.c         |  356 ++
> - security/ccsecurity/permission.c     | 5025 ++++++++++++++++++++++++++
> - security/ccsecurity/policy_io.c      | 6484 ++++++++++++++++++++++++++++++++++
> - security/ccsecurity/realpath.c       |  767 ++++
> - 13 files changed, 17804 insertions(+)
> - create mode 100644 include/linux/ccsecurity.h
> - create mode 100644 include/linux/lsm2ccsecurity.h
> - create mode 100644 security/ccsecurity/Config.in
> - create mode 100644 security/ccsecurity/Kconfig
> - create mode 100644 security/ccsecurity/Makefile
> - create mode 100644 security/ccsecurity/gc.c
> - create mode 100644 security/ccsecurity/internal.h
> - create mode 100644 security/ccsecurity/load_policy.c
> - create mode 100644 security/ccsecurity/lsm2ccsecurity.c
> - create mode 100644 security/ccsecurity/memory.c
> - create mode 100644 security/ccsecurity/permission.c
> - create mode 100644 security/ccsecurity/policy_io.c
> - create mode 100644 security/ccsecurity/realpath.c
> -
> -diff --git a/include/linux/ccsecurity.h b/include/linux/ccsecurity.h
> -new file mode 100644
> -index 0000000..6c1ca2b
> ---- /dev/null
> -+++ b/include/linux/ccsecurity.h
> -@@ -0,0 +1,926 @@
> -+/*
> -+ * include/linux/ccsecurity.h
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/05/05
> -+ */
> -+
> -+#ifndef _LINUX_CCSECURITY_H
> -+#define _LINUX_CCSECURITY_H
> -+
> -+#include <linux/version.h>
> -+
> -+#ifndef __user
> -+#define __user
> -+#endif
> -+
> -+struct nameidata;
> -+struct path;
> -+struct dentry;
> -+struct vfsmount;
> -+struct linux_binprm;
> -+struct pt_regs;
> -+struct file;
> -+struct ctl_table;
> -+struct socket;
> -+struct sockaddr;
> -+struct sock;
> -+struct sk_buff;
> -+struct msghdr;
> -+struct pid_namespace;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
> -+int search_binary_handler(struct linux_binprm *bprm);
> -+#else
> -+int search_binary_handler(struct linux_binprm *bprm, struct pt_regs *regs);
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
> -+#include <linux/lsm2ccsecurity.h>
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
> -+/* Obtain prototype of __d_path(). */
> -+#include <linux/dcache.h>
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
> -+/* Obtain definition of kuid_t and kgid_t. */
> -+#include <linux/uidgid.h>
> -+#endif
> -+
> -+/* For exporting variables and functions. */
> -+struct ccsecurity_exports {
> -+	void (*load_policy) (const char *filename);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY)
> -+	void (*add_hooks) (void);
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
> -+	char * (*d_absolute_path) (const struct path *, char *, int);
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
> -+	typeof(__d_path) (*__d_path);
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+	spinlock_t *vfsmount_lock;
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
> -+	struct task_struct * (*find_task_by_vpid) (pid_t nr);
> -+	struct task_struct * (*find_task_by_pid_ns) (pid_t nr,
> -+						     struct pid_namespace *ns);
> -+#endif
> -+};
> -+
> -+/* For doing access control. */
> -+struct ccsecurity_operations {
> -+	void (*check_profile) (void);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+	int (*chroot_permission) (struct path *path);
> -+	int (*pivot_root_permission) (struct path *old_path,
> -+				      struct path *new_path);
> -+	int (*mount_permission) (const char *dev_name, struct path *path,
> -+				 const char *type, unsigned long flags,
> -+				 void *data_page);
> -+#else
> -+	int (*chroot_permission) (struct nameidata *nd);
> -+	int (*pivot_root_permission) (struct nameidata *old_nd,
> -+				      struct nameidata *new_nd);
> -+	int (*mount_permission) (const char *dev_name, struct nameidata *nd,
> -+				 const char *type, unsigned long flags,
> -+				 void *data_page);
> -+#endif
> -+	int (*umount_permission) (struct vfsmount *mnt, int flags);
> -+	_Bool (*lport_reserved) (const u16 port);
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
> -+	void (*save_open_mode) (int mode);
> -+	void (*clear_open_mode) (void);
> -+	int (*open_permission) (struct dentry *dentry, struct vfsmount *mnt,
> -+				const int flag);
> -+#else
> -+	int (*open_permission) (struct file *file);
> -+#endif
> -+	int (*ptrace_permission) (long request, long pid);
> -+	int (*ioctl_permission) (struct file *filp, unsigned int cmd,
> -+				 unsigned long arg);
> -+	int (*parse_table) (int __user *name, int nlen, void __user *oldval,
> -+			    void __user *newval, struct ctl_table *table);
> -+	_Bool (*capable) (const u8 operation);
> -+	int (*mknod_permission) (struct dentry *dentry, struct vfsmount *mnt,
> -+				 unsigned int mode, unsigned int dev);
> -+	int (*mkdir_permission) (struct dentry *dentry, struct vfsmount *mnt,
> -+				 unsigned int mode);
> -+	int (*rmdir_permission) (struct dentry *dentry, struct vfsmount *mnt);
> -+	int (*unlink_permission) (struct dentry *dentry, struct vfsmount *mnt);
> -+	int (*symlink_permission) (struct dentry *dentry, struct vfsmount *mnt,
> -+				   const char *from);
> -+	int (*truncate_permission) (struct dentry *dentry,
> -+				    struct vfsmount *mnt);
> -+	int (*rename_permission) (struct dentry *old_dentry,
> -+				  struct dentry *new_dentry,
> -+				  struct vfsmount *mnt);
> -+	int (*link_permission) (struct dentry *old_dentry,
> -+				struct dentry *new_dentry,
> -+				struct vfsmount *mnt);
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
> -+	int (*open_exec_permission) (struct dentry *dentry,
> -+				     struct vfsmount *mnt);
> -+	int (*uselib_permission) (struct dentry *dentry, struct vfsmount *mnt);
> -+#endif
> -+	int (*fcntl_permission) (struct file *file, unsigned int cmd,
> -+				 unsigned long arg);
> -+	int (*kill_permission) (pid_t pid, int sig);
> -+	int (*tgkill_permission) (pid_t tgid, pid_t pid, int sig);
> -+	int (*tkill_permission) (pid_t pid, int sig);
> -+	int (*socket_create_permission) (int family, int type, int protocol);
> -+	int (*socket_listen_permission) (struct socket *sock);
> -+	int (*socket_connect_permission) (struct socket *sock,
> -+					  struct sockaddr *addr, int addr_len);
> -+	int (*socket_bind_permission) (struct socket *sock,
> -+				       struct sockaddr *addr, int addr_len);
> -+	int (*socket_post_accept_permission) (struct socket *sock,
> -+					      struct socket *newsock);
> -+	int (*socket_sendmsg_permission) (struct socket *sock,
> -+					  struct msghdr *msg, int size);
> -+	int (*socket_post_recvmsg_permission) (struct sock *sk,
> -+					       struct sk_buff *skb, int flags);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
> -+	int (*chown_permission) (struct dentry *dentry, struct vfsmount *mnt,
> -+				 kuid_t user, kgid_t group);
> -+#else
> -+	int (*chown_permission) (struct dentry *dentry, struct vfsmount *mnt,
> -+				 uid_t user, gid_t group);
> -+#endif
> -+	int (*chmod_permission) (struct dentry *dentry, struct vfsmount *mnt,
> -+				 mode_t mode);
> -+	int (*getattr_permission) (struct vfsmount *mnt,
> -+				   struct dentry *dentry);
> -+	int (*sigqueue_permission) (pid_t pid, int sig);
> -+	int (*tgsigqueue_permission) (pid_t tgid, pid_t pid, int sig);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
> -+	int (*search_binary_handler) (struct linux_binprm *bprm);
> -+#else
> -+	int (*search_binary_handler) (struct linux_binprm *bprm,
> -+				      struct pt_regs *regs);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+	int (*alloc_task_security) (const struct task_struct *task);
> -+	void (*free_task_security) (const struct task_struct *task);
> -+#endif
> -+	_Bool disabled;
> -+};
> -+
> -+extern struct ccsecurity_operations ccsecurity_ops;
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+
> -+static inline int ccs_chroot_permission(struct path *path)
> -+{
> -+	int (*func) (struct path *) = ccsecurity_ops.chroot_permission;
> -+	return func ? func(path) : 0;
> -+}
> -+
> -+static inline int ccs_pivot_root_permission(struct path *old_path,
> -+					    struct path *new_path)
> -+{
> -+	int (*func) (struct path *, struct path *)
> -+		= ccsecurity_ops.pivot_root_permission;
> -+	return func ? func(old_path, new_path) : 0;
> -+}
> -+
> -+static inline int ccs_mount_permission(const char *dev_name, struct path *path,
> -+				       const char *type, unsigned long flags,
> -+				       void *data_page)
> -+{
> -+	int (*func) (const char *, struct path *, const char *, unsigned long,
> -+		     void *) = ccsecurity_ops.mount_permission;
> -+	return func ? func(dev_name, path, type, flags, data_page) : 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_chroot_permission(struct nameidata *nd)
> -+{
> -+	int (*func) (struct nameidata *) = ccsecurity_ops.chroot_permission;
> -+	return func ? func(nd) : 0;
> -+}
> -+
> -+static inline int ccs_pivot_root_permission(struct nameidata *old_nd,
> -+					    struct nameidata *new_nd)
> -+{
> -+	int (*func) (struct nameidata *, struct nameidata *)
> -+		= ccsecurity_ops.pivot_root_permission;
> -+	return func ? func(old_nd, new_nd) : 0;
> -+}
> -+
> -+static inline int ccs_mount_permission(const char *dev_name,
> -+				       struct nameidata *nd, const char *type,
> -+				       unsigned long flags, void *data_page)
> -+{
> -+	int (*func) (const char *, struct nameidata *, const char *,
> -+		     unsigned long, void *) = ccsecurity_ops.mount_permission;
> -+	return func ? func(dev_name, nd, type, flags, data_page) : 0;
> -+}
> -+
> -+#endif
> -+
> -+static inline int ccs_umount_permission(struct vfsmount *mnt, int flags)
> -+{
> -+	int (*func) (struct vfsmount *, int)
> -+		= ccsecurity_ops.umount_permission;
> -+	return func ? func(mnt, flags) : 0;
> -+}
> -+
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
> -+
> -+static inline void ccs_save_open_mode(int mode)
> -+{
> -+	void (*func) (int) = ccsecurity_ops.save_open_mode;
> -+	if (func)
> -+		func(mode);
> -+}
> -+
> -+static inline void ccs_clear_open_mode(void)
> -+{
> -+	void (*func) (void) = ccsecurity_ops.clear_open_mode;
> -+	if (func)
> -+		func();
> -+}
> -+
> -+static inline int ccs_open_permission(struct dentry *dentry,
> -+				      struct vfsmount *mnt, const int flag)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *, const int)
> -+		= ccsecurity_ops.open_permission;
> -+	return func ? func(dentry, mnt, flag) : 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_open_permission(struct file *filp)
> -+{
> -+	int (*func) (struct file *) = ccsecurity_ops.open_permission;
> -+	return func ? func(filp) : 0;
> -+}
> -+
> -+#endif
> -+
> -+static inline int ccs_fcntl_permission(struct file *file, unsigned int cmd,
> -+				       unsigned long arg)
> -+{
> -+	int (*func) (struct file *, unsigned int, unsigned long)
> -+		= ccsecurity_ops.fcntl_permission;
> -+	return func ? func(file, cmd, arg) : 0;
> -+}
> -+
> -+static inline int ccs_ioctl_permission(struct file *filp, unsigned int cmd,
> -+				       unsigned long arg)
> -+{
> -+	int (*func) (struct file *, unsigned int, unsigned long)
> -+		= ccsecurity_ops.ioctl_permission;
> -+	return func ? func(filp, cmd, arg) : 0;
> -+}
> -+
> -+static inline int ccs_parse_table(int __user *name, int nlen,
> -+				  void __user *oldval, void __user *newval,
> -+				  struct ctl_table *table)
> -+{
> -+	int (*func) (int __user *, int, void __user *, void __user *,
> -+		     struct ctl_table *) = ccsecurity_ops.parse_table;
> -+	return func ? func(name, nlen, oldval, newval, table) : 0;
> -+}
> -+
> -+static inline int ccs_mknod_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, unsigned int mode,
> -+				       unsigned int dev)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *, unsigned int,
> -+		     unsigned int) = ccsecurity_ops.mknod_permission;
> -+	return func ? func(dentry, mnt, mode, dev) : 0;
> -+}
> -+
> -+static inline int ccs_mkdir_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, unsigned int mode)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *, unsigned int)
> -+		= ccsecurity_ops.mkdir_permission;
> -+	return func ? func(dentry, mnt, mode) : 0;
> -+}
> -+
> -+static inline int ccs_rmdir_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *)
> -+		= ccsecurity_ops.rmdir_permission;
> -+	return func ? func(dentry, mnt) : 0;
> -+}
> -+
> -+static inline int ccs_unlink_permission(struct dentry *dentry,
> -+					struct vfsmount *mnt)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *)
> -+		= ccsecurity_ops.unlink_permission;
> -+	return func ? func(dentry, mnt) : 0;
> -+}
> -+
> -+static inline int ccs_symlink_permission(struct dentry *dentry,
> -+					 struct vfsmount *mnt,
> -+					 const char *from)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *, const char *)
> -+		= ccsecurity_ops.symlink_permission;
> -+	return func ? func(dentry, mnt, from) : 0;
> -+}
> -+
> -+static inline int ccs_truncate_permission(struct dentry *dentry,
> -+					  struct vfsmount *mnt)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *)
> -+		= ccsecurity_ops.truncate_permission;
> -+	return func ? func(dentry, mnt) : 0;
> -+}
> -+
> -+static inline int ccs_rename_permission(struct dentry *old_dentry,
> -+					struct dentry *new_dentry,
> -+					struct vfsmount *mnt)
> -+{
> -+	int (*func) (struct dentry *, struct dentry *, struct vfsmount *)
> -+		= ccsecurity_ops.rename_permission;
> -+	return func ? func(old_dentry, new_dentry, mnt) : 0;
> -+}
> -+
> -+static inline int ccs_link_permission(struct dentry *old_dentry,
> -+				      struct dentry *new_dentry,
> -+				      struct vfsmount *mnt)
> -+{
> -+	int (*func) (struct dentry *, struct dentry *, struct vfsmount *)
> -+		= ccsecurity_ops.link_permission;
> -+	return func ? func(old_dentry, new_dentry, mnt) : 0;
> -+}
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
> -+
> -+static inline int ccs_open_exec_permission(struct dentry *dentry,
> -+					   struct vfsmount *mnt)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *)
> -+		= ccsecurity_ops.open_exec_permission;
> -+	return func ? func(dentry, mnt) : 0;
> -+}
> -+
> -+static inline int ccs_uselib_permission(struct dentry *dentry,
> -+					struct vfsmount *mnt)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *)
> -+		= ccsecurity_ops.uselib_permission;
> -+	return func ? func(dentry, mnt) : 0;
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
> -+
> -+static inline int ccs_chown_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, kuid_t user,
> -+				       kgid_t group)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *, kuid_t, kgid_t)
> -+		= ccsecurity_ops.chown_permission;
> -+	return func ? func(dentry, mnt, user, group) : 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_chown_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, uid_t user,
> -+				       gid_t group)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *, uid_t, gid_t)
> -+		= ccsecurity_ops.chown_permission;
> -+	return func ? func(dentry, mnt, user, group) : 0;
> -+}
> -+
> -+#endif
> -+
> -+static inline int ccs_chmod_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, mode_t mode)
> -+{
> -+	int (*func) (struct dentry *, struct vfsmount *, mode_t)
> -+		= ccsecurity_ops.chmod_permission;
> -+	return func ? func(dentry, mnt, mode) : 0;
> -+}
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
> -+
> -+static inline int ccs_search_binary_handler(struct linux_binprm *bprm)
> -+{
> -+	return ccsecurity_ops.search_binary_handler(bprm);
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_search_binary_handler(struct linux_binprm *bprm,
> -+					    struct pt_regs *regs)
> -+{
> -+	return ccsecurity_ops.search_binary_handler(bprm, regs);
> -+}
> -+
> -+#endif
> -+
> -+#else
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+
> -+static inline int ccs_chroot_permission(struct path *path)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_pivot_root_permission(struct path *old_path,
> -+					    struct path *new_path)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_mount_permission(const char *dev_name, struct path *path,
> -+				       const char *type, unsigned long flags,
> -+				       void *data_page)
> -+{
> -+	return 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_chroot_permission(struct nameidata *nd)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_pivot_root_permission(struct nameidata *old_nd,
> -+					    struct nameidata *new_nd)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_mount_permission(const char *dev_name,
> -+				       struct nameidata *nd, const char *type,
> -+				       unsigned long flags, void *data_page)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif
> -+
> -+static inline int ccs_umount_permission(struct vfsmount *mnt, int flags)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline void ccs_save_open_mode(int mode)
> -+{
> -+}
> -+
> -+static inline void ccs_clear_open_mode(void)
> -+{
> -+}
> -+
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
> -+
> -+static inline int ccs_open_permission(struct dentry *dentry,
> -+				      struct vfsmount *mnt, const int flag)
> -+{
> -+	return 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_open_permission(struct file *filp)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif
> -+
> -+static inline int ccs_ioctl_permission(struct file *filp, unsigned int cmd,
> -+				       unsigned long arg)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_parse_table(int __user *name, int nlen,
> -+				  void __user *oldval, void __user *newval,
> -+				  struct ctl_table *table)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_mknod_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, unsigned int mode,
> -+				       unsigned int dev)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_mkdir_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, unsigned int mode)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_rmdir_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_unlink_permission(struct dentry *dentry,
> -+					struct vfsmount *mnt)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_symlink_permission(struct dentry *dentry,
> -+					 struct vfsmount *mnt,
> -+					 const char *from)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_truncate_permission(struct dentry *dentry,
> -+					  struct vfsmount *mnt)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_rename_permission(struct dentry *old_dentry,
> -+					struct dentry *new_dentry,
> -+					struct vfsmount *mnt)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_link_permission(struct dentry *old_dentry,
> -+				      struct dentry *new_dentry,
> -+				      struct vfsmount *mnt)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_open_exec_permission(struct dentry *dentry,
> -+					   struct vfsmount *mnt)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_uselib_permission(struct dentry *dentry,
> -+					struct vfsmount *mnt)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_fcntl_permission(struct file *file, unsigned int cmd,
> -+				       unsigned long arg)
> -+{
> -+	return 0;
> -+}
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
> -+
> -+static inline int ccs_chown_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, kuid_t user,
> -+				       kgid_t group)
> -+{
> -+	return 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_chown_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, uid_t user,
> -+				       gid_t group)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif
> -+
> -+static inline int ccs_chmod_permission(struct dentry *dentry,
> -+				       struct vfsmount *mnt, mode_t mode)
> -+{
> -+	return 0;
> -+}
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
> -+
> -+static inline int ccs_search_binary_handler(struct linux_binprm *bprm)
> -+{
> -+	return search_binary_handler(bprm);
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_search_binary_handler(struct linux_binprm *bprm,
> -+					    struct pt_regs *regs)
> -+{
> -+	return search_binary_handler(bprm, regs);
> -+}
> -+
> -+#endif
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+
> -+static inline int ccs_alloc_task_security(const struct task_struct *task)
> -+{
> -+	int (*func) (const struct task_struct *)
> -+		= ccsecurity_ops.alloc_task_security;
> -+	return func ? func(task) : 0;
> -+}
> -+
> -+static inline void ccs_free_task_security(const struct task_struct *task)
> -+{
> -+	void (*func) (const struct task_struct *)
> -+		= ccsecurity_ops.free_task_security;
> -+	if (func)
> -+		func(task);
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_alloc_task_security(const struct task_struct *task)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline void ccs_free_task_security(const struct task_struct *task)
> -+{
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+
> -+static inline int ccs_getattr_permission(struct vfsmount *mnt,
> -+					 struct dentry *dentry)
> -+{
> -+	int (*func) (struct vfsmount *, struct dentry *)
> -+		= ccsecurity_ops.getattr_permission;
> -+	return func ? func(mnt, dentry) : 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_getattr_permission(struct vfsmount *mnt,
> -+					 struct dentry *dentry)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+
> -+static inline int ccs_socket_listen_permission(struct socket *sock)
> -+{
> -+	int (*func) (struct socket *)
> -+		= ccsecurity_ops.socket_listen_permission;
> -+	return func ? func(sock) : 0;
> -+}
> -+
> -+static inline int ccs_socket_connect_permission(struct socket *sock,
> -+						struct sockaddr *addr,
> -+						int addr_len)
> -+{
> -+	int (*func) (struct socket *, struct sockaddr *, int)
> -+		= ccsecurity_ops.socket_connect_permission;
> -+	return func ? func(sock, addr, addr_len) : 0;
> -+}
> -+
> -+static inline int ccs_socket_bind_permission(struct socket *sock,
> -+					     struct sockaddr *addr,
> -+					     int addr_len)
> -+{
> -+	int (*func) (struct socket *, struct sockaddr *, int)
> -+		= ccsecurity_ops.socket_bind_permission;
> -+	return func ? func(sock, addr, addr_len) : 0;
> -+}
> -+
> -+static inline int ccs_socket_post_accept_permission(struct socket *sock,
> -+						    struct socket *newsock)
> -+{
> -+	int (*func) (struct socket *, struct socket *)
> -+		= ccsecurity_ops.socket_post_accept_permission;
> -+	return func ? func(sock, newsock) : 0;
> -+}
> -+
> -+static inline int ccs_socket_sendmsg_permission(struct socket *sock,
> -+						struct msghdr *msg,
> -+						int size)
> -+{
> -+	int (*func) (struct socket *, struct msghdr *, int)
> -+		= ccsecurity_ops.socket_sendmsg_permission;
> -+	return func ? func(sock, msg, size) : 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_socket_listen_permission(struct socket *sock)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_socket_connect_permission(struct socket *sock,
> -+						struct sockaddr *addr,
> -+						int addr_len)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_socket_bind_permission(struct socket *sock,
> -+					     struct sockaddr *addr,
> -+					     int addr_len)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_socket_post_accept_permission(struct socket *sock,
> -+						    struct socket *newsock)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_socket_sendmsg_permission(struct socket *sock,
> -+						struct msghdr *msg,
> -+						int size)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+
> -+static inline int ccs_socket_post_recvmsg_permission(struct sock *sk,
> -+						     struct sk_buff *skb,
> -+						     int flags)
> -+{
> -+	int (*func) (struct sock *, struct sk_buff *, int)
> -+		= ccsecurity_ops.socket_post_recvmsg_permission;
> -+	return func ? func(sk, skb, flags) : 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_socket_post_recvmsg_permission(struct sock *sk,
> -+						     struct sk_buff *skb,
> -+						     int flags)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_PORTRESERVE
> -+
> -+static inline _Bool ccs_lport_reserved(const u16 port)
> -+{
> -+	_Bool (*func) (const u16) = ccsecurity_ops.lport_reserved;
> -+	return func ? func(port) : 0;
> -+}
> -+
> -+#else
> -+
> -+static inline _Bool ccs_lport_reserved(const u16 port)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+
> -+static inline _Bool ccs_capable(const u8 operation)
> -+{
> -+	_Bool (*func) (const u8) = ccsecurity_ops.capable;
> -+	return func ? func(operation) : 1;
> -+}
> -+
> -+static inline int ccs_socket_create_permission(int family, int type,
> -+					       int protocol)
> -+{
> -+	int (*func) (int, int, int) = ccsecurity_ops.socket_create_permission;
> -+	return func ? func(family, type, protocol) : 0;
> -+}
> -+
> -+static inline int ccs_ptrace_permission(long request, long pid)
> -+{
> -+	int (*func) (long, long) = ccsecurity_ops.ptrace_permission;
> -+	return func ? func(request, pid) : 0;
> -+}
> -+
> -+#else
> -+
> -+static inline _Bool ccs_capable(const u8 operation)
> -+{
> -+	return 1;
> -+}
> -+
> -+static inline int ccs_socket_create_permission(int family, int type,
> -+					       int protocol)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_ptrace_permission(long request, long pid)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+
> -+static inline int ccs_kill_permission(pid_t pid, int sig)
> -+{
> -+	int (*func) (pid_t, int) = ccsecurity_ops.kill_permission;
> -+	return func ? func(pid, sig) : 0;
> -+}
> -+
> -+static inline int ccs_tgkill_permission(pid_t tgid, pid_t pid, int sig)
> -+{
> -+	int (*func) (pid_t, pid_t, int) = ccsecurity_ops.tgkill_permission;
> -+	return func ? func(tgid, pid, sig) : 0;
> -+}
> -+
> -+static inline int ccs_tkill_permission(pid_t pid, int sig)
> -+{
> -+	int (*func) (pid_t, int) = ccsecurity_ops.tkill_permission;
> -+	return func ? func(pid, sig) : 0;
> -+}
> -+
> -+static inline int ccs_sigqueue_permission(pid_t pid, int sig)
> -+{
> -+	int (*func) (pid_t, int) = ccsecurity_ops.sigqueue_permission;
> -+	return func ? func(pid, sig) : 0;
> -+}
> -+
> -+static inline int ccs_tgsigqueue_permission(pid_t tgid, pid_t pid, int sig)
> -+{
> -+	int (*func) (pid_t, pid_t, int) = ccsecurity_ops.tgsigqueue_permission;
> -+	return func ? func(tgid, pid, sig) : 0;
> -+}
> -+
> -+#else
> -+
> -+static inline int ccs_kill_permission(pid_t pid, int sig)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_tgkill_permission(pid_t tgid, pid_t pid, int sig)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_tkill_permission(pid_t pid, int sig)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_sigqueue_permission(pid_t pid, int sig)
> -+{
> -+	return 0;
> -+}
> -+
> -+static inline int ccs_tgsigqueue_permission(pid_t tgid, pid_t pid, int sig)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif
> -+
> -+/* Index numbers for Capability Controls. */
> -+enum ccs_capability_acl_index {
> -+	/* socket(PF_ROUTE, *, *)                                      */
> -+	CCS_USE_ROUTE_SOCKET,
> -+	/* socket(PF_PACKET, *, *)                                     */
> -+	CCS_USE_PACKET_SOCKET,
> -+	/* sys_reboot()                                                */
> -+	CCS_SYS_REBOOT,
> -+	/* sys_vhangup()                                               */
> -+	CCS_SYS_VHANGUP,
> -+	/* do_settimeofday(), sys_adjtimex()                           */
> -+	CCS_SYS_SETTIME,
> -+	/* sys_nice(), sys_setpriority()                               */
> -+	CCS_SYS_NICE,
> -+	/* sys_sethostname(), sys_setdomainname()                      */
> -+	CCS_SYS_SETHOSTNAME,
> -+	/* sys_create_module(), sys_init_module(), sys_delete_module() */
> -+	CCS_USE_KERNEL_MODULE,
> -+	/* sys_kexec_load()                                            */
> -+	CCS_SYS_KEXEC_LOAD,
> -+	/* sys_ptrace()                                                */
> -+	CCS_SYS_PTRACE,
> -+	CCS_MAX_CAPABILITY_INDEX
> -+};
> -+
> -+#endif
> -diff --git a/include/linux/lsm2ccsecurity.h b/include/linux/lsm2ccsecurity.h
> -new file mode 100644
> -index 0000000..ab4ea5c
> ---- /dev/null
> -+++ b/include/linux/lsm2ccsecurity.h
> -@@ -0,0 +1,181 @@
> -+/*
> -+ * include/linux/lsm2ccsecurity.h
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/07/11
> -+ */
> -+
> -+#ifndef _LINUX_LSM2CCSECURITY_H
> -+#define _LINUX_LSM2CCSECURITY_H
> -+
> -+#include <linux/version.h>
> -+#include <linux/uidgid.h>
> -+
> -+#ifdef CONFIG_CCSECURITY
> -+
> -+int ccs_settime(const struct timespec *ts, const struct timezone *tz);
> -+int ccs_sb_mount(const char *dev_name, struct path *path, const char *type,
> -+		 unsigned long flags, void *data);
> -+int ccs_sb_umount(struct vfsmount *mnt, int flags);
> -+int ccs_sb_pivotroot(struct path *old_path, struct path *new_path);
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
> -+int ccs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
> -+#else
> -+int ccs_inode_getattr(const struct path *path);
> -+#endif
> -+int ccs_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
> -+int ccs_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg);
> -+int ccs_file_open(struct file *file, const struct cred *cred);
> -+int ccs_socket_create(int family, int type, int protocol, int kern);
> -+int ccs_socket_bind(struct socket *sock, struct sockaddr *address,
> -+		    int addrlen);
> -+int ccs_socket_connect(struct socket *sock, struct sockaddr *address,
> -+		       int addrlen);
> -+int ccs_socket_listen(struct socket *sock, int backlog);
> -+int ccs_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size);
> -+int ccs_path_unlink(struct path *dir, struct dentry *dentry);
> -+int ccs_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode);
> -+int ccs_path_rmdir(struct path *dir, struct dentry *dentry);
> -+int ccs_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
> -+		   unsigned int dev);
> -+int ccs_path_truncate(struct path *path);
> -+int ccs_path_symlink(struct path *dir, struct dentry *dentry,
> -+		     const char *old_name);
> -+int ccs_path_link(struct dentry *old_dentry, struct path *new_dir,
> -+		  struct dentry *new_dentry);
> -+int ccs_path_rename(struct path *old_dir, struct dentry *old_dentry,
> -+		    struct path *new_dir, struct dentry *new_dentry);
> -+int ccs_path_chmod(struct path *path, umode_t mode);
> -+int ccs_path_chown(struct path *path, kuid_t uid, kgid_t gid);
> -+int ccs_path_chroot(struct path *path);
> -+
> -+#else
> -+
> -+static inline int ccs_settime(const struct timespec *ts,
> -+			      const struct timezone *tz)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_sb_mount(const char *dev_name, struct path *path,
> -+			       const char *type, unsigned long flags,
> -+			       void *data)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_sb_umount(struct vfsmount *mnt, int flags)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_sb_pivotroot(struct path *old_path,
> -+				   struct path *new_path)
> -+{
> -+	return 0;
> -+}
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
> -+static inline int ccs_inode_getattr(struct vfsmount *mnt,
> -+				    struct dentry *dentry)
> -+{
> -+	return 0;
> -+}
> -+#else
> -+static inline int ccs_inode_getattr(const struct path *path)
> -+{
> -+	return 0;
> -+}
> -+#endif
> -+static inline int ccs_file_ioctl(struct file *file, unsigned int cmd,
> -+				 unsigned long arg)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_file_fcntl(struct file *file, unsigned int cmd,
> -+				 unsigned long arg)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_file_open(struct file *file, const struct cred *cred)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_socket_create(int family, int type, int protocol,
> -+				    int kern)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_socket_bind(struct socket *sock,
> -+				  struct sockaddr *address, int addrlen)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_socket_connect(struct socket *sock,
> -+				     struct sockaddr *address, int addrlen)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_socket_listen(struct socket *sock, int backlog)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_socket_sendmsg(struct socket *sock, struct msghdr *msg,
> -+				     int size)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_unlink(struct path *dir, struct dentry *dentry)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_mkdir(struct path *dir, struct dentry *dentry,
> -+				 umode_t mode)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_rmdir(struct path *dir, struct dentry *dentry)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_mknod(struct path *dir, struct dentry *dentry,
> -+				 umode_t mode, unsigned int dev)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_truncate(struct path *path)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_symlink(struct path *dir, struct dentry *dentry,
> -+				   const char *old_name)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_link(struct dentry *old_dentry,
> -+				struct path *new_dir,
> -+				struct dentry *new_dentry)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_rename(struct path *old_dir,
> -+				  struct dentry *old_dentry,
> -+				  struct path *new_dir,
> -+				  struct dentry *new_dentry)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_chmod(struct path *path, umode_t mode)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_chown(struct path *path, kuid_t uid, kgid_t gid)
> -+{
> -+	return 0;
> -+}
> -+static inline int ccs_path_chroot(struct path *path)
> -+{
> -+	return 0;
> -+}
> -+
> -+#endif /* defined(CONFIG_CCSECURITY) */
> -+
> -+#endif /* !defined(_LINUX_LSM2CCSECURITY_H) */
> -diff --git a/security/ccsecurity/Config.in b/security/ccsecurity/Config.in
> -new file mode 100644
> -index 0000000..da39bad6
> ---- /dev/null
> -+++ b/security/ccsecurity/Config.in
> -@@ -0,0 +1,83 @@
> -+#
> -+# Mandatory Access Control configuration
> -+#
> -+mainmenu_option next_comment
> -+comment 'Security options'
> -+
> -+[ -z "$CONFIG_CCSECURITY" ] && define_bool CONFIG_CCSECURITY y
> -+bool 'CCSecurity support' CONFIG_CCSECURITY
> -+
> -+if [ "$CONFIG_CCSECURITY" = "y" ]; then
> -+
> -+  [ -z "$CONFIG_CCSECURITY_LKM" ] && define_bool CONFIG_CCSECURITY_LKM n
> -+  bool 'Compile as loadable kernel module' CONFIG_CCSECURITY_LKM
> -+
> -+  [ -z "$CONFIG_CCSECURITY_DISABLE_BY_DEFAULT" ] && define_bool CONFIG_CCSECURITY_DISABLE_BY_DEFAULT n
> -+  bool 'Disable by default' CONFIG_CCSECURITY_DISABLE_BY_DEFAULT
> -+
> -+  [ -z "$CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY" ] && define_int CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY 2048
> -+  [ $CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY -lt 0 ] && define_int CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY 0
> -+  int  'Default maximal count for learning mode' CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY
> -+
> -+  [ -z "$CONFIG_CCSECURITY_MAX_AUDIT_LOG" ] && define_int CONFIG_CCSECURITY_MAX_AUDIT_LOG 1024
> -+  [ $CONFIG_CCSECURITY_MAX_AUDIT_LOG -lt 0 ] && define_int CONFIG_CCSECURITY_MAX_AUDIT_LOG 0
> -+  int  'Default maximal count for audit log' CONFIG_CCSECURITY_MAX_AUDIT_LOG
> -+
> -+  [ -z "$CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER" ] && define_bool CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER n
> -+  bool 'Activate without calling userspace policy loader.' CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
> -+
> -+  if [ "$CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER" = "n" ]; then
> -+
> -+    define_string CONFIG_CCSECURITY_POLICY_LOADER "/sbin/ccs-init"
> -+    string 'Location of userspace policy loader' CONFIG_CCSECURITY_POLICY_LOADER "/sbin/ccs-init"
> -+
> -+    define_string CONFIG_CCSECURITY_ACTIVATION_TRIGGER "/sbin/init"
> -+    string 'Trigger for calling userspace policy loader' CONFIG_CCSECURITY_ACTIVATION_TRIGGER "/sbin/init"
> -+
> -+  fi
> -+
> -+  [ -z "$CONFIG_CCSECURITY_FILE_READDIR" ] && define_bool CONFIG_CCSECURITY_FILE_READDIR y
> -+  bool "Enable readdir operation restriction." CONFIG_CCSECURITY_FILE_READDIR
> -+
> -+  [ -z "$CONFIG_CCSECURITY_FILE_GETATTR" ] && define_bool CONFIG_CCSECURITY_FILE_GETATTR y
> -+  bool "Enable getattr operation restriction." CONFIG_CCSECURITY_FILE_GETATTR
> -+
> -+  if [ "$CONFIG_NET" = "y" ]; then
> -+
> -+     [ -z "$CONFIG_CCSECURITY_NETWORK" ] && define_bool CONFIG_CCSECURITY_NETWORK y
> -+     bool "Enable socket operation restriction." CONFIG_CCSECURITY_NETWORK
> -+
> -+     if [ "$CONFIG_CCSECURITY_NETWORK" = "y" ]; then
> -+
> -+	#[ -z "$CONFIG_CCSECURITY_NETWORK_RECVMSG" ] &&
> -+	define_bool CONFIG_CCSECURITY_NETWORK_RECVMSG y
> -+
> -+     fi
> -+
> -+  fi
> -+
> -+  [ -z "$CONFIG_CCSECURITY_CAPABILITY" ] && define_bool CONFIG_CCSECURITY_CAPABILITY y
> -+  bool "Enable non-POSIX capability operation restriction." CONFIG_CCSECURITY_CAPABILITY
> -+
> -+  [ -z "$CONFIG_CCSECURITY_IPC" ] && define_bool CONFIG_CCSECURITY_IPC y
> -+  bool "Enable IPC operation restriction." CONFIG_CCSECURITY_IPC
> -+
> -+  [ -z "$CONFIG_CCSECURITY_MISC" ] && define_bool CONFIG_CCSECURITY_MISC y
> -+  bool "Enable environment variable names restriction." CONFIG_CCSECURITY_MISC
> -+
> -+  [ -z "$CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER" ] && define_bool CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER y
> -+  bool "Enable execute handler functionality." CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+
> -+  [ -z "$CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION" ] && define_bool CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION y
> -+  bool "Enable domain transition without program execution request." CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+
> -+  if [ "$CONFIG_NET" = "y" ]; then
> -+
> -+     [ -z "$CONFIG_CCSECURITY_PORTRESERVE" ] && define_bool CONFIG_CCSECURITY_PORTRESERVE y
> -+     bool "Enable local port reserver." CONFIG_CCSECURITY_PORTRESERVE
> -+
> -+  fi
> -+
> -+fi
> -+
> -+endmenu
> -diff --git a/security/ccsecurity/Kconfig b/security/ccsecurity/Kconfig
> -new file mode 100644
> -index 0000000..8d7b200
> ---- /dev/null
> -+++ b/security/ccsecurity/Kconfig
> -@@ -0,0 +1,190 @@
> -+config CCSECURITY
> -+	bool "CCSecurity support"
> -+	default y
> -+	help
> -+	  Say Y here to support non-LSM version of TOMOYO Linux.
> -+	  http://tomoyo.osdn.jp/
> -+
> -+config CCSECURITY_LKM
> -+	bool "Compile as loadable kernel module"
> -+	default n
> -+	depends on CCSECURITY && MODULES
> -+	help
> -+	  This version of TOMOYO depends on patching the kernel source in order
> -+	  to insert some hooks which LSM does not provide. Therefore,
> -+	  recompiling the kernel is inevitable. But if you want to keep
> -+	  vmlinux's size as small as possible, you can compile most part of
> -+	  TOMOYO as a loadable kernel module by saying Y here.
> -+
> -+config CCSECURITY_DISABLE_BY_DEFAULT
> -+	bool "Disable by default"
> -+	default n
> -+	depends on CCSECURITY
> -+	help
> -+	  Say Y here if you want TOMOYO disabled by default.
> -+	  To enable TOMOYO, pass ccsecurity=on to kernel command line.
> -+	  To disable TOMOYO, pass ccsecurity=off to kernel command line.
> -+
> -+config CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+	bool "Do not modify 'struct task_struct' in order to keep KABI"
> -+	default n
> -+	depends on CCSECURITY
> -+	help
> -+	  Say Y here if you want to keep KABI for prebuilt kernel modules
> -+	  unchanged. TOMOYO needs "struct ccs_domain_info *" and "u32" for each
> -+	  "struct task_struct". But embedding these variables into
> -+	  "struct task_struct" breaks KABI for prebuilt kernel modules (which
> -+	  means that you will need to rebuild prebuilt kernel modules).
> -+	  If you say Y here, these variables are managed outside
> -+	  "struct task_struct" rather than embedding into "struct task_struct",
> -+	  but accessing these variables becomes slower because lookup operation
> -+	  is performed every time the current thread needs to access them.
> -+
> -+config CCSECURITY_MAX_ACCEPT_ENTRY
> -+	int "Default maximal count for learning mode"
> -+	default 2048
> -+	range 0 2147483647
> -+	depends on CCSECURITY
> -+	help
> -+	  This is the default value for maximal ACL entries
> -+	  that are automatically appended into policy at "learning mode".
> -+	  Some programs access thousands of objects, so running
> -+	  such programs in "learning mode" dulls the system response
> -+	  and consumes much memory.
> -+	  This is the safeguard for such programs.
> -+
> -+config CCSECURITY_MAX_AUDIT_LOG
> -+	int "Default maximal count for audit log"
> -+	default 1024
> -+	range 0 2147483647
> -+	depends on CCSECURITY
> -+	help
> -+	  This is the default value for maximal entries for
> -+	  audit logs that the kernel can hold on memory.
> -+	  You can read the log via /proc/ccs/audit.
> -+	  If you don't need audit logs, you may set this value to 0.
> -+
> -+config CCSECURITY_OMIT_USERSPACE_LOADER
> -+	bool "Activate without calling userspace policy loader."
> -+	default n
> -+	depends on CCSECURITY
> -+	---help---
> -+	  Say Y here if you want to activate access control as soon as built-in
> -+	  policy was loaded. This option will be useful for systems where
> -+	  operations which can lead to the hijacking of the boot sequence are
> -+	  needed before loading the policy. For example, you can activate
> -+	  immediately after loading the fixed part of policy which will allow
> -+	  only operations needed for mounting a partition which contains the
> -+	  variant part of policy and verifying (e.g. running GPG check) and
> -+	  loading the variant part of policy. Since you can start using
> -+	  enforcing mode from the beginning, you can reduce the possibility of
> -+	  hijacking the boot sequence.
> -+
> -+	  If you say Y to both "Compile as loadable kernel module" option and
> -+	  "Activate without calling userspace policy loader." option, be sure
> -+	  to excplicitly load the kernel module from the userspace, for
> -+	  the kernel will not call /sbin/ccs-init when /sbin/init starts.
> -+
> -+config CCSECURITY_POLICY_LOADER
> -+	string "Location of userspace policy loader"
> -+	default "/sbin/ccs-init"
> -+	depends on CCSECURITY
> -+	depends on !CCSECURITY_OMIT_USERSPACE_LOADER
> -+	---help---
> -+	  This is the default pathname of policy loader which is called before
> -+	  activation. You can override this setting via CCS_loader= kernel
> -+	  command line option.
> -+
> -+config CCSECURITY_ACTIVATION_TRIGGER
> -+	string "Trigger for calling userspace policy loader"
> -+	default "/sbin/init"
> -+	depends on CCSECURITY
> -+	depends on !CCSECURITY_OMIT_USERSPACE_LOADER
> -+	---help---
> -+	  This is the default pathname of activation trigger.
> -+	  You can override this setting via CCS_trigger= kernel command line
> -+	  option. For example, if you pass init=/bin/systemd option, you may
> -+	  want to also pass CCS_trigger=/bin/systemd option.
> -+
> -+	  Say Y here if you want to enable only specific functionality in order
> -+	  to reduce object file size.
> -+
> -+config CCSECURITY_FILE_READDIR
> -+	bool "Enable readdir operation restriction."
> -+	default y
> -+	depends on CCSECURITY
> -+	---help---
> -+	  Say Y here if you want to enable analysis/restriction of opening
> -+	  directories for reading. Reading directory entries is a commonly
> -+	  requested operation and damage caused by not restricting it as MAC
> -+	  might be acceptable for you.
> -+
> -+config CCSECURITY_FILE_GETATTR
> -+	bool "Enable getattr operation restriction."
> -+	default y
> -+	depends on CCSECURITY
> -+	---help---
> -+	  Say Y here if you want to enable analysis/restriction of getting
> -+	  information of files. Getting file's information is a commonly
> -+	  requested operation and damage caused by not restricting it as MAC
> -+	  might be acceptable for you.
> -+
> -+config CCSECURITY_NETWORK
> -+	bool "Enable socket operation restriction."
> -+	default y
> -+	depends on NET
> -+	depends on CCSECURITY
> -+	---help---
> -+	  Say Y here if you want to enable analysis/restriction of INET and
> -+	  UNIX domain socket's operations.
> -+
> -+config CCSECURITY_CAPABILITY
> -+	bool "Enable non-POSIX capability operation restriction."
> -+	default y
> -+	depends on CCSECURITY
> -+	---help---
> -+	  Say Y here if you want to enable analysis/restriction of non-POSIX
> -+	  capabilities.
> -+
> -+config CCSECURITY_IPC
> -+	bool "Enable IPC operation restriction."
> -+	default y
> -+	depends on CCSECURITY
> -+	---help---
> -+	  Say Y here if you want to enable analysis/restriction of sending
> -+	  signals.
> -+
> -+config CCSECURITY_MISC
> -+	bool "Enable environment variable names restriction."
> -+	default y
> -+	depends on CCSECURITY
> -+	---help---
> -+	  Say Y here if you want to enable analysis/restriction of environment
> -+	  variable names passed upon program execution request.
> -+
> -+config CCSECURITY_TASK_EXECUTE_HANDLER
> -+	bool "Enable execute handler functionality."
> -+	default y
> -+	depends on CCSECURITY
> -+	---help---
> -+	  Say Y here if you want to enable execute handler functionality.
> -+
> -+config CCSECURITY_TASK_DOMAIN_TRANSITION
> -+	bool "Enable domain transition without program execution request."
> -+	default y
> -+	depends on CCSECURITY
> -+	---help---
> -+	  Say Y here if you want to enable domain transition without involving
> -+	  program execution request.
> -+
> -+config CCSECURITY_PORTRESERVE
> -+       bool "Enable local port reserver."
> -+       default y
> -+       depends on NET
> -+       depends on CCSECURITY
> -+       ---help---
> -+	 Say Y here if you want to implement
> -+	 /proc/sys/net/ipv4/ip_local_reserved_ports as a MAC policy.
> -+
> -+config CCSECURITY_NETWORK_RECVMSG
> -+	def_bool CCSECURITY_NETWORK
> -diff --git a/security/ccsecurity/Makefile b/security/ccsecurity/Makefile
> -new file mode 100644
> -index 0000000..79c3632
> ---- /dev/null
> -+++ b/security/ccsecurity/Makefile
> -@@ -0,0 +1,122 @@
> -+ccsecurity-objs := permission.o gc.o memory.o policy_io.o realpath.o
> -+
> -+ifeq ($(VERSION)$(PATCHLEVEL),24)
> -+
> -+ifdef CONFIG_CCSECURITY
> -+O_TARGET := ccsecurity.o
> -+ifdef CONFIG_CCSECURITY_LKM
> -+all_targets: load_policy.o
> -+obj-m := ccsecurity.o
> -+obj-y := $(ccsecurity-objs)
> -+else
> -+all_targets: ccsecurity.o
> -+obj-y := load_policy.o $(ccsecurity-objs)
> -+endif
> -+export-objs := load_policy.o
> -+endif
> -+include $(TOPDIR)/Rules.make
> -+
> -+policy/profile.conf:
> -+	@mkdir -p policy/
> -+	@echo Creating an empty policy/profile.conf
> -+	@touch $@
> -+
> -+policy/exception_policy.conf:
> -+	@mkdir -p policy/
> -+	@echo Creating a default policy/exception_policy.conf
> -+	@echo initialize_domain /sbin/modprobe from any >> $@
> -+	@echo initialize_domain /sbin/hotplug from any >> $@
> -+
> -+policy/domain_policy.conf:
> -+	@mkdir -p policy/
> -+	@echo Creating an empty policy/domain_policy.conf
> -+	@touch $@
> -+
> -+policy/manager.conf:
> -+	@mkdir -p policy/
> -+	@echo Creating an empty policy/manager.conf
> -+	@touch $@
> -+
> -+policy/stat.conf:
> -+	@mkdir -p policy/
> -+	@echo Creating an empty policy/stat.conf
> -+	@touch $@
> -+
> -+builtin-policy.h: policy/profile.conf policy/exception_policy.conf policy/domain_policy.conf policy/manager.conf policy/stat.conf
> -+	@echo Generating built-in policy for TOMOYO 1.8.x.
> -+	@echo "static char ccs_builtin_profile[] __initdata =" > $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/profile.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@echo "static char ccs_builtin_exception_policy[] __initdata =" >> $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/exception_policy.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@echo "static char ccs_builtin_domain_policy[] __initdata =" >> $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/domain_policy.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@echo "static char ccs_builtin_manager[] __initdata =" >> $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/manager.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@echo "static char ccs_builtin_stat[] __initdata =" >> $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < policy/stat.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@mv $@.tmp $@
> -+
> -+policy_io.o: builtin-policy.h
> -+
> -+else
> -+
> -+obj-y += load_policy.o
> -+ifdef CONFIG_CCSECURITY_LKM
> -+obj-m += ccsecurity.o
> -+else
> -+obj-y += ccsecurity.o
> -+endif
> -+
> -+$(obj)/policy/profile.conf:
> -+	@mkdir -p $(obj)/policy/
> -+	@echo Creating an empty policy/profile.conf
> -+	@touch $@
> -+
> -+$(obj)/policy/exception_policy.conf:
> -+	@mkdir -p $(obj)/policy/
> -+	@echo Creating a default policy/exception_policy.conf
> -+	@echo initialize_domain /sbin/modprobe from any >> $@
> -+	@echo initialize_domain /sbin/hotplug from any >> $@
> -+
> -+$(obj)/policy/domain_policy.conf:
> -+	@mkdir -p $(obj)/policy/
> -+	@echo Creating an empty policy/domain_policy.conf
> -+	@touch $@
> -+
> -+$(obj)/policy/manager.conf:
> -+	@mkdir -p $(obj)/policy/
> -+	@echo Creating an empty policy/manager.conf
> -+	@touch $@
> -+
> -+$(obj)/policy/stat.conf:
> -+	@mkdir -p $(obj)/policy/
> -+	@echo Creating an empty policy/stat.conf
> -+	@touch $@
> -+
> -+$(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
> -+	@echo Generating built-in policy for TOMOYO 1.8.x.
> -+	@echo "static char ccs_builtin_profile[] __initdata =" > $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@echo "static char ccs_builtin_exception_policy[] __initdata =" >> $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/exception_policy.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@echo "static char ccs_builtin_domain_policy[] __initdata =" >> $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/domain_policy.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@echo "static char ccs_builtin_manager[] __initdata =" >> $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/manager.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@echo "static char ccs_builtin_stat[] __initdata =" >> $@.tmp
> -+	@sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/stat.conf >> $@.tmp
> -+	@echo "\"\";" >> $@.tmp
> -+	@mv $@.tmp $@
> -+
> -+$(obj)/policy_io.o: $(obj)/builtin-policy.h
> -+
> -+endif
> -diff --git a/security/ccsecurity/gc.c b/security/ccsecurity/gc.c
> -new file mode 100644
> -index 0000000..0a578ab
> ---- /dev/null
> -+++ b/security/ccsecurity/gc.c
> -@@ -0,0 +1,1036 @@
> -+/*
> -+ * security/ccsecurity/gc.c
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/05/05
> -+ */
> -+
> -+#include "internal.h"
> -+
> -+/***** SECTION1: Constants definition *****/
> -+
> -+/* For compatibility with older kernels. */
> -+#ifndef for_each_process
> -+#define for_each_process for_each_task
> -+#endif
> -+
> -+/* The list for "struct ccs_io_buffer". */
> -+static LIST_HEAD(ccs_io_buffer_list);
> -+/* Lock for protecting ccs_io_buffer_list. */
> -+static DEFINE_SPINLOCK(ccs_io_buffer_list_lock);
> -+
> -+/***** SECTION2: Structure definition *****/
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
> -+
> -+/*
> -+ * Lock for syscall users.
> -+ *
> -+ * This lock is used for protecting single SRCU section for 2.6.18 and
> -+ * earlier kernels because they don't have SRCU support.
> -+ */
> -+struct ccs_lock_struct {
> -+	int counter_idx; /* Currently active index (0 or 1). */
> -+	int counter[2];  /* Current users. Protected by ccs_counter_lock. */
> -+};
> -+
> -+#endif
> -+
> -+/***** SECTION3: Prototype definition section *****/
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
> -+int ccs_lock(void);
> -+#endif
> -+void ccs_del_acl(struct list_head *element);
> -+void ccs_del_condition(struct list_head *element);
> -+void ccs_notify_gc(struct ccs_io_buffer *head, const bool is_register);
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
> -+void ccs_unlock(const int idx);
> -+#endif
> -+
> -+static bool ccs_domain_used_by_task(struct ccs_domain_info *domain);
> -+static bool ccs_name_used_by_io_buffer(const char *string, const size_t size);
> -+static bool ccs_struct_used_by_io_buffer(const struct list_head *element);
> -+static int ccs_gc_thread(void *unused);
> -+static void ccs_collect_acl(struct list_head *list);
> -+static void ccs_collect_entry(void);
> -+static void ccs_collect_member(const enum ccs_policy_id id,
> -+			       struct list_head *member_list);
> -+static void ccs_memory_free(const void *ptr, const enum ccs_policy_id type);
> -+static void ccs_put_name_union(struct ccs_name_union *ptr);
> -+static void ccs_put_number_union(struct ccs_number_union *ptr);
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
> -+static void ccs_synchronize_counter(void);
> -+#endif
> -+static void ccs_try_to_gc(const enum ccs_policy_id type,
> -+			  struct list_head *element);
> -+
> -+/***** SECTION4: Standalone functions section *****/
> -+
> -+/***** SECTION5: Variables definition section *****/
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
> -+
> -+/*
> -+ * Lock for syscall users.
> -+ *
> -+ * This lock is held for only protecting single SRCU section.
> -+ */
> -+struct srcu_struct ccs_ss;
> -+
> -+#else
> -+
> -+static struct ccs_lock_struct ccs_counter;
> -+/* Lock for protecting ccs_counter. */
> -+static DEFINE_SPINLOCK(ccs_counter_lock);
> -+
> -+#endif
> -+
> -+/***** SECTION6: Dependent functions section *****/
> -+
> -+/**
> -+ * ccs_memory_free - Free memory for elements.
> -+ *
> -+ * @ptr:  Pointer to allocated memory.
> -+ * @type: One of values in "enum ccs_policy_id".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Caller holds ccs_policy_lock mutex.
> -+ */
> -+static void ccs_memory_free(const void *ptr, const enum ccs_policy_id type)
> -+{
> -+	/* Size of an element. */
> -+	static const u8 e[CCS_MAX_POLICY] = {
> -+#ifdef CONFIG_CCSECURITY_PORTRESERVE
> -+		[CCS_ID_RESERVEDPORT] = sizeof(struct ccs_reserved),
> -+#endif
> -+		[CCS_ID_GROUP] = sizeof(struct ccs_group),
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+		[CCS_ID_ADDRESS_GROUP] = sizeof(struct ccs_address_group),
> -+#endif
> -+		[CCS_ID_PATH_GROUP] = sizeof(struct ccs_path_group),
> -+		[CCS_ID_NUMBER_GROUP] = sizeof(struct ccs_number_group),
> -+		[CCS_ID_AGGREGATOR] = sizeof(struct ccs_aggregator),
> -+		[CCS_ID_TRANSITION_CONTROL]
> -+		= sizeof(struct ccs_transition_control),
> -+		[CCS_ID_MANAGER] = sizeof(struct ccs_manager),
> -+		/* [CCS_ID_CONDITION] = "struct ccs_condition"->size, */
> -+		/* [CCS_ID_NAME] = "struct ccs_name"->size, */
> -+		/* [CCS_ID_ACL] = a["struct ccs_acl_info"->type], */
> -+		[CCS_ID_DOMAIN] = sizeof(struct ccs_domain_info),
> -+	};
> -+	/* Size of a domain ACL element. */
> -+	static const u8 a[] = {
> -+		[CCS_TYPE_PATH_ACL] = sizeof(struct ccs_path_acl),
> -+		[CCS_TYPE_PATH2_ACL] = sizeof(struct ccs_path2_acl),
> -+		[CCS_TYPE_PATH_NUMBER_ACL]
> -+		= sizeof(struct ccs_path_number_acl),
> -+		[CCS_TYPE_MKDEV_ACL] = sizeof(struct ccs_mkdev_acl),
> -+		[CCS_TYPE_MOUNT_ACL] = sizeof(struct ccs_mount_acl),
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+		[CCS_TYPE_INET_ACL] = sizeof(struct ccs_inet_acl),
> -+		[CCS_TYPE_UNIX_ACL] = sizeof(struct ccs_unix_acl),
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+		[CCS_TYPE_ENV_ACL] = sizeof(struct ccs_env_acl),
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+		[CCS_TYPE_CAPABILITY_ACL] = sizeof(struct ccs_capability_acl),
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+		[CCS_TYPE_SIGNAL_ACL] = sizeof(struct ccs_signal_acl),
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+		[CCS_TYPE_AUTO_EXECUTE_HANDLER]
> -+		= sizeof(struct ccs_handler_acl),
> -+		[CCS_TYPE_DENIED_EXECUTE_HANDLER]
> -+		= sizeof(struct ccs_handler_acl),
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+		[CCS_TYPE_AUTO_TASK_ACL] = sizeof(struct ccs_task_acl),
> -+		[CCS_TYPE_MANUAL_TASK_ACL] = sizeof(struct ccs_task_acl),
> -+#endif
> -+	};
> -+	size_t size;
> -+	if (type == CCS_ID_ACL)
> -+		size = a[container_of(ptr, typeof(struct ccs_acl_info),
> -+				      list)->type];
> -+	else if (type == CCS_ID_NAME)
> -+		size = container_of(ptr, typeof(struct ccs_name),
> -+				    head.list)->size;
> -+	else if (type == CCS_ID_CONDITION)
> -+		size = container_of(ptr, typeof(struct ccs_condition),
> -+				    head.list)->size;
> -+	else
> -+		size = e[type];
> -+	ccs_memory_used[CCS_MEMORY_POLICY] -= ccs_round2(size);
> -+	kfree(ptr);
> -+}
> -+
> -+/**
> -+ * ccs_put_name_union - Drop reference on "struct ccs_name_union".
> -+ *
> -+ * @ptr: Pointer to "struct ccs_name_union".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_put_name_union(struct ccs_name_union *ptr)
> -+{
> -+	ccs_put_group(ptr->group);
> -+	ccs_put_name(ptr->filename);
> -+}
> -+
> -+/**
> -+ * ccs_put_number_union - Drop reference on "struct ccs_number_union".
> -+ *
> -+ * @ptr: Pointer to "struct ccs_number_union".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_put_number_union(struct ccs_number_union *ptr)
> -+{
> -+	ccs_put_group(ptr->group);
> -+}
> -+
> -+/**
> -+ * ccs_struct_used_by_io_buffer - Check whether the list element is used by /proc/ccs/ users or not.
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns true if @element is used by /proc/ccs/ users, false otherwise.
> -+ */
> -+static bool ccs_struct_used_by_io_buffer(const struct list_head *element)
> -+{
> -+	struct ccs_io_buffer *head;
> -+	bool in_use = false;
> -+	spin_lock(&ccs_io_buffer_list_lock);
> -+	list_for_each_entry(head, &ccs_io_buffer_list, list) {
> -+		head->users++;
> -+		spin_unlock(&ccs_io_buffer_list_lock);
> -+		mutex_lock(&head->io_sem);
> -+		if (head->r.domain == element || head->r.group == element ||
> -+		    head->r.acl == element || &head->w.domain->list == element)
> -+			in_use = true;
> -+		mutex_unlock(&head->io_sem);
> -+		spin_lock(&ccs_io_buffer_list_lock);
> -+		head->users--;
> -+		if (in_use)
> -+			break;
> -+	}
> -+	spin_unlock(&ccs_io_buffer_list_lock);
> -+	return in_use;
> -+}
> -+
> -+/**
> -+ * ccs_name_used_by_io_buffer - Check whether the string is used by /proc/ccs/ users or not.
> -+ *
> -+ * @string: String to check.
> -+ * @size:   Memory allocated for @string .
> -+ *
> -+ * Returns true if @string is used by /proc/ccs/ users, false otherwise.
> -+ */
> -+static bool ccs_name_used_by_io_buffer(const char *string, const size_t size)
> -+{
> -+	struct ccs_io_buffer *head;
> -+	bool in_use = false;
> -+	spin_lock(&ccs_io_buffer_list_lock);
> -+	list_for_each_entry(head, &ccs_io_buffer_list, list) {
> -+		int i;
> -+		head->users++;
> -+		spin_unlock(&ccs_io_buffer_list_lock);
> -+		mutex_lock(&head->io_sem);
> -+		for (i = 0; i < CCS_MAX_IO_READ_QUEUE; i++) {
> -+			const char *w = head->r.w[i];
> -+			if (w < string || w > string + size)
> -+				continue;
> -+			in_use = true;
> -+			break;
> -+		}
> -+		mutex_unlock(&head->io_sem);
> -+		spin_lock(&ccs_io_buffer_list_lock);
> -+		head->users--;
> -+		if (in_use)
> -+			break;
> -+	}
> -+	spin_unlock(&ccs_io_buffer_list_lock);
> -+	return in_use;
> -+}
> -+
> -+/**
> -+ * ccs_del_transition_control - Delete members in "struct ccs_transition_control".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_del_transition_control(struct list_head *element)
> -+{
> -+	struct ccs_transition_control *ptr =
> -+		container_of(element, typeof(*ptr), head.list);
> -+	ccs_put_name(ptr->domainname);
> -+	ccs_put_name(ptr->program);
> -+}
> -+
> -+/**
> -+ * ccs_del_aggregator - Delete members in "struct ccs_aggregator".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_del_aggregator(struct list_head *element)
> -+{
> -+	struct ccs_aggregator *ptr =
> -+		container_of(element, typeof(*ptr), head.list);
> -+	ccs_put_name(ptr->original_name);
> -+	ccs_put_name(ptr->aggregated_name);
> -+}
> -+
> -+/**
> -+ * ccs_del_manager - Delete members in "struct ccs_manager".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_del_manager(struct list_head *element)
> -+{
> -+	struct ccs_manager *ptr =
> -+		container_of(element, typeof(*ptr), head.list);
> -+	ccs_put_name(ptr->manager);
> -+}
> -+
> -+/**
> -+ * ccs_domain_used_by_task - Check whether the given pointer is referenced by a task.
> -+ *
> -+ * @domain: Pointer to "struct ccs_domain_info".
> -+ *
> -+ * Returns true if @domain is in use, false otherwise.
> -+ */
> -+static bool ccs_domain_used_by_task(struct ccs_domain_info *domain)
> -+{
> -+	bool in_use = false;
> -+	/*
> -+	 * Don't delete this domain if somebody is doing execve().
> -+	 *
> -+	 * Since ccs_finish_execve() first reverts ccs_domain_info and then
> -+	 * updates ccs_flags, we need smp_rmb() to make sure that GC first
> -+	 * checks ccs_flags and then checks ccs_domain_info.
> -+	 */
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+	int idx;
> -+	rcu_read_lock();
> -+	for (idx = 0; idx < CCS_MAX_TASK_SECURITY_HASH; idx++) {
> -+		struct ccs_security *ptr;
> -+		struct list_head *list = &ccs_task_security_list[idx];
> -+		list_for_each_entry_rcu(ptr, list, list) {
> -+			if (!(ptr->ccs_flags & CCS_TASK_IS_IN_EXECVE)) {
> -+				smp_rmb(); /* Avoid out of order execution. */
> -+				if (ptr->ccs_domain_info != domain)
> -+					continue;
> -+			}
> -+			in_use = true;
> -+			goto out;
> -+		}
> -+	}
> -+out:
> -+	rcu_read_unlock();
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
> -+	struct task_struct *g;
> -+	struct task_struct *t;
> -+	ccs_tasklist_lock();
> -+	do_each_thread(g, t) {
> -+		if (!(t->ccs_flags & CCS_TASK_IS_IN_EXECVE)) {
> -+			smp_rmb(); /* Avoid out of order execution. */
> -+			if (t->ccs_domain_info != domain)
> -+				continue;
> -+		}
> -+		in_use = true;
> -+		goto out;
> -+	} while_each_thread(g, t);
> -+out:
> -+	ccs_tasklist_unlock();
> -+#else
> -+	struct task_struct *p;
> -+	ccs_tasklist_lock();
> -+	for_each_process(p) {
> -+		if (!(p->ccs_flags & CCS_TASK_IS_IN_EXECVE)) {
> -+			smp_rmb(); /* Avoid out of order execution. */
> -+			if (p->ccs_domain_info != domain)
> -+				continue;
> -+		}
> -+		in_use = true;
> -+		break;
> -+	}
> -+	ccs_tasklist_unlock();
> -+#endif
> -+	return in_use;
> -+}
> -+
> -+/**
> -+ * ccs_del_acl - Delete members in "struct ccs_acl_info".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+void ccs_del_acl(struct list_head *element)
> -+{
> -+	struct ccs_acl_info *acl = container_of(element, typeof(*acl), list);
> -+	ccs_put_condition(acl->cond);
> -+	switch (acl->type) {
> -+	case CCS_TYPE_PATH_ACL:
> -+		{
> -+			struct ccs_path_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_name_union(&entry->name);
> -+		}
> -+		break;
> -+	case CCS_TYPE_PATH2_ACL:
> -+		{
> -+			struct ccs_path2_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_name_union(&entry->name1);
> -+			ccs_put_name_union(&entry->name2);
> -+		}
> -+		break;
> -+	case CCS_TYPE_PATH_NUMBER_ACL:
> -+		{
> -+			struct ccs_path_number_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_name_union(&entry->name);
> -+			ccs_put_number_union(&entry->number);
> -+		}
> -+		break;
> -+	case CCS_TYPE_MKDEV_ACL:
> -+		{
> -+			struct ccs_mkdev_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_name_union(&entry->name);
> -+			ccs_put_number_union(&entry->mode);
> -+			ccs_put_number_union(&entry->major);
> -+			ccs_put_number_union(&entry->minor);
> -+		}
> -+		break;
> -+	case CCS_TYPE_MOUNT_ACL:
> -+		{
> -+			struct ccs_mount_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_name_union(&entry->dev_name);
> -+			ccs_put_name_union(&entry->dir_name);
> -+			ccs_put_name_union(&entry->fs_type);
> -+			ccs_put_number_union(&entry->flags);
> -+		}
> -+		break;
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	case CCS_TYPE_INET_ACL:
> -+		{
> -+			struct ccs_inet_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_group(entry->address.group);
> -+			ccs_put_number_union(&entry->port);
> -+		}
> -+		break;
> -+	case CCS_TYPE_UNIX_ACL:
> -+		{
> -+			struct ccs_unix_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_name_union(&entry->name);
> -+		}
> -+		break;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	case CCS_TYPE_ENV_ACL:
> -+		{
> -+			struct ccs_env_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_name(entry->env);
> -+		}
> -+		break;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	case CCS_TYPE_CAPABILITY_ACL:
> -+		{
> -+			/* Nothing to do. */
> -+		}
> -+		break;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	case CCS_TYPE_SIGNAL_ACL:
> -+		{
> -+			struct ccs_signal_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_number_union(&entry->sig);
> -+			ccs_put_name(entry->domainname);
> -+		}
> -+		break;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	case CCS_TYPE_AUTO_EXECUTE_HANDLER:
> -+	case CCS_TYPE_DENIED_EXECUTE_HANDLER:
> -+		{
> -+			struct ccs_handler_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_name(entry->handler);
> -+		}
> -+		break;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+	case CCS_TYPE_AUTO_TASK_ACL:
> -+	case CCS_TYPE_MANUAL_TASK_ACL:
> -+		{
> -+			struct ccs_task_acl *entry =
> -+				container_of(acl, typeof(*entry), head);
> -+			ccs_put_name(entry->domainname);
> -+		}
> -+		break;
> -+#endif
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_del_domain - Delete members in "struct ccs_domain_info".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Caller holds ccs_policy_lock mutex.
> -+ */
> -+static inline void ccs_del_domain(struct list_head *element)
> -+{
> -+	struct ccs_domain_info *domain =
> -+		container_of(element, typeof(*domain), list);
> -+	struct ccs_acl_info *acl;
> -+	struct ccs_acl_info *tmp;
> -+	/*
> -+	 * Since this domain is referenced from neither "struct ccs_io_buffer"
> -+	 * nor "struct task_struct", we can delete elements without checking
> -+	 * for is_deleted flag.
> -+	 */
> -+	list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
> -+		ccs_del_acl(&acl->list);
> -+		ccs_memory_free(acl, CCS_ID_ACL);
> -+	}
> -+	ccs_put_name(domain->domainname);
> -+}
> -+
> -+/**
> -+ * ccs_del_path_group - Delete members in "struct ccs_path_group".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_del_path_group(struct list_head *element)
> -+{
> -+	struct ccs_path_group *member =
> -+		container_of(element, typeof(*member), head.list);
> -+	ccs_put_name(member->member_name);
> -+}
> -+
> -+/**
> -+ * ccs_del_group - Delete "struct ccs_group".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_del_group(struct list_head *element)
> -+{
> -+	struct ccs_group *group =
> -+		container_of(element, typeof(*group), head.list);
> -+	ccs_put_name(group->group_name);
> -+}
> -+
> -+/**
> -+ * ccs_del_address_group - Delete members in "struct ccs_address_group".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_del_address_group(struct list_head *element)
> -+{
> -+	/* Nothing to do. */
> -+}
> -+
> -+/**
> -+ * ccs_del_number_group - Delete members in "struct ccs_number_group".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_del_number_group(struct list_head *element)
> -+{
> -+	/* Nothing to do. */
> -+}
> -+
> -+/**
> -+ * ccs_del_reservedport - Delete members in "struct ccs_reserved".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_del_reservedport(struct list_head *element)
> -+{
> -+	/* Nothing to do. */
> -+}
> -+
> -+/**
> -+ * ccs_del_condition - Delete members in "struct ccs_condition".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+void ccs_del_condition(struct list_head *element)
> -+{
> -+	struct ccs_condition *cond = container_of(element, typeof(*cond),
> -+						  head.list);
> -+	const u16 condc = cond->condc;
> -+	const u16 numbers_count = cond->numbers_count;
> -+	const u16 names_count = cond->names_count;
> -+	const u16 argc = cond->argc;
> -+	const u16 envc = cond->envc;
> -+	unsigned int i;
> -+	const struct ccs_condition_element *condp
> -+		= (const struct ccs_condition_element *) (cond + 1);
> -+	struct ccs_number_union *numbers_p
> -+		= (struct ccs_number_union *) (condp + condc);
> -+	struct ccs_name_union *names_p
> -+		= (struct ccs_name_union *) (numbers_p + numbers_count);
> -+	const struct ccs_argv *argv
> -+		= (const struct ccs_argv *) (names_p + names_count);
> -+	const struct ccs_envp *envp
> -+		= (const struct ccs_envp *) (argv + argc);
> -+	for (i = 0; i < numbers_count; i++)
> -+		ccs_put_number_union(numbers_p++);
> -+	for (i = 0; i < names_count; i++)
> -+		ccs_put_name_union(names_p++);
> -+	for (i = 0; i < argc; argv++, i++)
> -+		ccs_put_name(argv->value);
> -+	for (i = 0; i < envc; envp++, i++) {
> -+		ccs_put_name(envp->name);
> -+		ccs_put_name(envp->value);
> -+	}
> -+	ccs_put_name(cond->transit);
> -+}
> -+
> -+/**
> -+ * ccs_del_name - Delete members in "struct ccs_name".
> -+ *
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_del_name(struct list_head *element)
> -+{
> -+	/* Nothing to do. */
> -+}
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
> -+
> -+/**
> -+ * ccs_lock - Alternative for srcu_read_lock().
> -+ *
> -+ * Returns index number which has to be passed to ccs_unlock().
> -+ */
> -+int ccs_lock(void)
> -+{
> -+	int idx;
> -+	spin_lock(&ccs_counter_lock);
> -+	idx = ccs_counter.counter_idx;
> -+	ccs_counter.counter[idx]++;
> -+	spin_unlock(&ccs_counter_lock);
> -+	return idx;
> -+}
> -+
> -+/**
> -+ * ccs_unlock - Alternative for srcu_read_unlock().
> -+ *
> -+ * @idx: Index number returned by ccs_lock().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+void ccs_unlock(const int idx)
> -+{
> -+	spin_lock(&ccs_counter_lock);
> -+	ccs_counter.counter[idx]--;
> -+	spin_unlock(&ccs_counter_lock);
> -+}
> -+
> -+/**
> -+ * ccs_synchronize_counter - Alternative for synchronize_srcu().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_synchronize_counter(void)
> -+{
> -+	int idx;
> -+	int v;
> -+	/*
> -+	 * Change currently active counter's index. Make it visible to other
> -+	 * threads by doing it with ccs_counter_lock held.
> -+	 * This function is called by garbage collector thread, and the garbage
> -+	 * collector thread is exclusive. Therefore, it is guaranteed that
> -+	 * SRCU grace period has expired when returning from this function.
> -+	 */
> -+	spin_lock(&ccs_counter_lock);
> -+	idx = ccs_counter.counter_idx;
> -+	ccs_counter.counter_idx ^= 1;
> -+	v = ccs_counter.counter[idx];
> -+	spin_unlock(&ccs_counter_lock);
> -+	/* Wait for previously active counter to become 0. */
> -+	while (v) {
> -+		ssleep(1);
> -+		spin_lock(&ccs_counter_lock);
> -+		v = ccs_counter.counter[idx];
> -+		spin_unlock(&ccs_counter_lock);
> -+	}
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_try_to_gc - Try to kfree() an entry.
> -+ *
> -+ * @type:    One of values in "enum ccs_policy_id".
> -+ * @element: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Caller holds ccs_policy_lock mutex.
> -+ */
> -+static void ccs_try_to_gc(const enum ccs_policy_id type,
> -+			  struct list_head *element)
> -+{
> -+	/*
> -+	 * __list_del_entry() guarantees that the list element became no longer
> -+	 * reachable from the list which the element was originally on (e.g.
> -+	 * ccs_domain_list). Also, synchronize_srcu() guarantees that the list
> -+	 * element became no longer referenced by syscall users.
> -+	 */
> -+	__list_del_entry(element);
> -+	mutex_unlock(&ccs_policy_lock);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
> -+	synchronize_srcu(&ccs_ss);
> -+#else
> -+	ccs_synchronize_counter();
> -+#endif
> -+	/*
> -+	 * However, there are two users which may still be using the list
> -+	 * element. We need to defer until both users forget this element.
> -+	 *
> -+	 * Don't kfree() until "struct ccs_io_buffer"->r.{domain,group,acl} and
> -+	 * "struct ccs_io_buffer"->w.domain forget this element.
> -+	 */
> -+	if (ccs_struct_used_by_io_buffer(element))
> -+		goto reinject;
> -+	switch (type) {
> -+	case CCS_ID_TRANSITION_CONTROL:
> -+		ccs_del_transition_control(element);
> -+		break;
> -+	case CCS_ID_MANAGER:
> -+		ccs_del_manager(element);
> -+		break;
> -+	case CCS_ID_AGGREGATOR:
> -+		ccs_del_aggregator(element);
> -+		break;
> -+	case CCS_ID_GROUP:
> -+		ccs_del_group(element);
> -+		break;
> -+	case CCS_ID_PATH_GROUP:
> -+		ccs_del_path_group(element);
> -+		break;
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	case CCS_ID_ADDRESS_GROUP:
> -+		ccs_del_address_group(element);
> -+		break;
> -+#endif
> -+	case CCS_ID_NUMBER_GROUP:
> -+		ccs_del_number_group(element);
> -+		break;
> -+#ifdef CONFIG_CCSECURITY_PORTRESERVE
> -+	case CCS_ID_RESERVEDPORT:
> -+		ccs_del_reservedport(element);
> -+		break;
> -+#endif
> -+	case CCS_ID_CONDITION:
> -+		ccs_del_condition(element);
> -+		break;
> -+	case CCS_ID_NAME:
> -+		/*
> -+		 * Don't kfree() until all "struct ccs_io_buffer"->r.w[] forget
> -+		 * this element.
> -+		 */
> -+		if (ccs_name_used_by_io_buffer
> -+		    (container_of(element, typeof(struct ccs_name),
> -+				  head.list)->entry.name,
> -+		     container_of(element, typeof(struct ccs_name),
> -+				  head.list)->size))
> -+			goto reinject;
> -+		ccs_del_name(element);
> -+		break;
> -+	case CCS_ID_ACL:
> -+		ccs_del_acl(element);
> -+		break;
> -+	case CCS_ID_DOMAIN:
> -+		/*
> -+		 * Don't kfree() until all "struct task_struct" forget this
> -+		 * element.
> -+		 */
> -+		if (ccs_domain_used_by_task
> -+		    (container_of(element, typeof(struct ccs_domain_info),
> -+				  list)))
> -+			goto reinject;
> -+		break;
> -+	case CCS_MAX_POLICY:
> -+		break;
> -+	}
> -+	mutex_lock(&ccs_policy_lock);
> -+	if (type == CCS_ID_DOMAIN)
> -+		ccs_del_domain(element);
> -+	ccs_memory_free(element, type);
> -+	return;
> -+reinject:
> -+	/*
> -+	 * We can safely reinject this element here bacause
> -+	 * (1) Appending list elements and removing list elements are protected
> -+	 *     by ccs_policy_lock mutex.
> -+	 * (2) Only this function removes list elements and this function is
> -+	 *     exclusively executed by ccs_gc_mutex mutex.
> -+	 * are true.
> -+	 */
> -+	mutex_lock(&ccs_policy_lock);
> -+	list_add_rcu(element, element->prev);
> -+}
> -+
> -+/**
> -+ * ccs_collect_member - Delete elements with "struct ccs_acl_head".
> -+ *
> -+ * @id:          One of values in "enum ccs_policy_id".
> -+ * @member_list: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Caller holds ccs_policy_lock mutex.
> -+ */
> -+static void ccs_collect_member(const enum ccs_policy_id id,
> -+			       struct list_head *member_list)
> -+{
> -+	struct ccs_acl_head *member;
> -+	struct ccs_acl_head *tmp;
> -+	list_for_each_entry_safe(member, tmp, member_list, list) {
> -+		if (!member->is_deleted)
> -+			continue;
> -+		member->is_deleted = CCS_GC_IN_PROGRESS;
> -+		ccs_try_to_gc(id, &member->list);
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_collect_acl - Delete elements in "struct ccs_domain_info".
> -+ *
> -+ * @list: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Caller holds ccs_policy_lock mutex.
> -+ */
> -+static void ccs_collect_acl(struct list_head *list)
> -+{
> -+	struct ccs_acl_info *acl;
> -+	struct ccs_acl_info *tmp;
> -+	list_for_each_entry_safe(acl, tmp, list, list) {
> -+		if (!acl->is_deleted)
> -+			continue;
> -+		acl->is_deleted = CCS_GC_IN_PROGRESS;
> -+		ccs_try_to_gc(CCS_ID_ACL, &acl->list);
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_collect_entry - Try to kfree() deleted elements.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_collect_entry(void)
> -+{
> -+	int i;
> -+	enum ccs_policy_id id;
> -+	struct ccs_policy_namespace *ns;
> -+	mutex_lock(&ccs_policy_lock);
> -+	{
> -+		struct ccs_domain_info *domain;
> -+		struct ccs_domain_info *tmp;
> -+		list_for_each_entry_safe(domain, tmp, &ccs_domain_list, list) {
> -+			ccs_collect_acl(&domain->acl_info_list);
> -+			if (!domain->is_deleted ||
> -+			    ccs_domain_used_by_task(domain))
> -+				continue;
> -+			ccs_try_to_gc(CCS_ID_DOMAIN, &domain->list);
> -+		}
> -+	}
> -+	list_for_each_entry(ns, &ccs_namespace_list, namespace_list) {
> -+		for (id = 0; id < CCS_MAX_POLICY; id++)
> -+			ccs_collect_member(id, &ns->policy_list[id]);
> -+		for (i = 0; i < CCS_MAX_ACL_GROUPS; i++)
> -+			ccs_collect_acl(&ns->acl_group[i]);
> -+	}
> -+	{
> -+		struct ccs_shared_acl_head *ptr;
> -+		struct ccs_shared_acl_head *tmp;
> -+		list_for_each_entry_safe(ptr, tmp, &ccs_condition_list, list) {
> -+			if (atomic_read(&ptr->users) > 0)
> -+				continue;
> -+			atomic_set(&ptr->users, CCS_GC_IN_PROGRESS);
> -+			ccs_try_to_gc(CCS_ID_CONDITION, &ptr->list);
> -+		}
> -+	}
> -+	list_for_each_entry(ns, &ccs_namespace_list, namespace_list) {
> -+		for (i = 0; i < CCS_MAX_GROUP; i++) {
> -+			struct list_head *list = &ns->group_list[i];
> -+			struct ccs_group *group;
> -+			struct ccs_group *tmp;
> -+			switch (i) {
> -+			case 0:
> -+				id = CCS_ID_PATH_GROUP;
> -+				break;
> -+			case 1:
> -+				id = CCS_ID_NUMBER_GROUP;
> -+				break;
> -+			default:
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+				id = CCS_ID_ADDRESS_GROUP;
> -+#else
> -+				continue;
> -+#endif
> -+				break;
> -+			}
> -+			list_for_each_entry_safe(group, tmp, list, head.list) {
> -+				ccs_collect_member(id, &group->member_list);
> -+				if (!list_empty(&group->member_list) ||
> -+				    atomic_read(&group->head.users) > 0)
> -+					continue;
> -+				atomic_set(&group->head.users,
> -+					   CCS_GC_IN_PROGRESS);
> -+				ccs_try_to_gc(CCS_ID_GROUP, &group->head.list);
> -+			}
> -+		}
> -+	}
> -+	for (i = 0; i < CCS_MAX_HASH; i++) {
> -+		struct list_head *list = &ccs_name_list[i];
> -+		struct ccs_shared_acl_head *ptr;
> -+		struct ccs_shared_acl_head *tmp;
> -+		list_for_each_entry_safe(ptr, tmp, list, list) {
> -+			if (atomic_read(&ptr->users) > 0)
> -+				continue;
> -+			atomic_set(&ptr->users, CCS_GC_IN_PROGRESS);
> -+			ccs_try_to_gc(CCS_ID_NAME, &ptr->list);
> -+		}
> -+	}
> -+	mutex_unlock(&ccs_policy_lock);
> -+}
> -+
> -+/**
> -+ * ccs_gc_thread - Garbage collector thread function.
> -+ *
> -+ * @unused: Unused.
> -+ *
> -+ * Returns 0.
> -+ */
> -+static int ccs_gc_thread(void *unused)
> -+{
> -+	/* Garbage collector thread is exclusive. */
> -+	static DEFINE_MUTEX(ccs_gc_mutex);
> -+	if (!mutex_trylock(&ccs_gc_mutex))
> -+		goto out;
> -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 6)
> -+	/* daemonize() not needed. */
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+	daemonize("GC for CCS");
> -+#else
> -+	daemonize();
> -+	reparent_to_init();
> -+#if defined(TASK_DEAD)
> -+	{
> -+		struct task_struct *task = current;
> -+		spin_lock_irq(&task->sighand->siglock);
> -+		siginitsetinv(&task->blocked, 0);
> -+		recalc_sigpending();
> -+		spin_unlock_irq(&task->sighand->siglock);
> -+	}
> -+#else
> -+	{
> -+		struct task_struct *task = current;
> -+		spin_lock_irq(&task->sigmask_lock);
> -+		siginitsetinv(&task->blocked, 0);
> -+		recalc_sigpending(task);
> -+		spin_unlock_irq(&task->sigmask_lock);
> -+	}
> -+#endif
> -+	snprintf(current->comm, sizeof(current->comm) - 1, "GC for CCS");
> -+#endif
> -+	ccs_collect_entry();
> -+	{
> -+		struct ccs_io_buffer *head;
> -+		struct ccs_io_buffer *tmp;
> -+		spin_lock(&ccs_io_buffer_list_lock);
> -+		list_for_each_entry_safe(head, tmp, &ccs_io_buffer_list,
> -+					 list) {
> -+			if (head->users)
> -+				continue;
> -+			list_del(&head->list);
> -+			kfree(head->read_buf);
> -+			kfree(head->write_buf);
> -+			kfree(head);
> -+		}
> -+		spin_unlock(&ccs_io_buffer_list_lock);
> -+	}
> -+	mutex_unlock(&ccs_gc_mutex);
> -+out:
> -+	/* This acts as do_exit(0). */
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_notify_gc - Register/unregister /proc/ccs/ users.
> -+ *
> -+ * @head:        Pointer to "struct ccs_io_buffer".
> -+ * @is_register: True if register, false if unregister.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+void ccs_notify_gc(struct ccs_io_buffer *head, const bool is_register)
> -+{
> -+	bool is_write = false;
> -+	spin_lock(&ccs_io_buffer_list_lock);
> -+	if (is_register) {
> -+		head->users = 1;
> -+		list_add(&head->list, &ccs_io_buffer_list);
> -+	} else {
> -+		is_write = head->write_buf != NULL;
> -+		if (!--head->users) {
> -+			list_del(&head->list);
> -+			kfree(head->read_buf);
> -+			kfree(head->write_buf);
> -+			kfree(head);
> -+		}
> -+	}
> -+	spin_unlock(&ccs_io_buffer_list_lock);
> -+	if (is_write) {
> -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 6)
> -+		struct task_struct *task = kthread_create(ccs_gc_thread, NULL,
> -+							  "GC for CCS");
> -+		if (!IS_ERR(task))
> -+			wake_up_process(task);
> -+#else
> -+		kernel_thread(ccs_gc_thread, NULL, 0);
> -+#endif
> -+	}
> -+}
> -diff --git a/security/ccsecurity/internal.h b/security/ccsecurity/internal.h
> -new file mode 100644
> -index 0000000..3f703f2
> ---- /dev/null
> -+++ b/security/ccsecurity/internal.h
> -@@ -0,0 +1,2090 @@
> -+/*
> -+ * security/ccsecurity/internal.h
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/05/05
> -+ */
> -+
> -+#ifndef _SECURITY_CCSECURITY_INTERNAL_H
> -+#define _SECURITY_CCSECURITY_INTERNAL_H
> -+
> -+#include <linux/version.h>
> -+#include <linux/types.h>
> -+#include <linux/kernel.h>
> -+#include <linux/string.h>
> -+#include <linux/mm.h>
> -+#include <linux/utime.h>
> -+#include <linux/file.h>
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 38)
> -+#include <linux/smp_lock.h>
> -+#endif
> -+#include <linux/module.h>
> -+#include <linux/init.h>
> -+#include <linux/slab.h>
> -+#include <linux/highmem.h>
> -+#include <linux/poll.h>
> -+#include <linux/binfmts.h>
> -+#include <linux/delay.h>
> -+#include <linux/sched.h>
> -+#include <linux/dcache.h>
> -+#include <linux/mount.h>
> -+#include <linux/net.h>
> -+#include <linux/inet.h>
> -+#include <linux/in.h>
> -+#include <linux/in6.h>
> -+#include <linux/un.h>
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+#include <linux/fs.h>
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+#include <linux/namei.h>
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
> -+#include <linux/fs_struct.h>
> -+#endif
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> -+#include <linux/namespace.h>
> -+#endif
> -+#include <linux/proc_fs.h>
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(RHEL_MAJOR)
> -+#include <linux/hash.h>
> -+#endif
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
> -+#include <linux/sysctl.h>
> -+#endif
> -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 6)
> -+#include <linux/kthread.h>
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
> -+#include <linux/magic.h>
> -+#endif
> -+#include <stdarg.h>
> -+#include <asm/uaccess.h>
> -+#include <net/sock.h>
> -+#include <net/af_unix.h>
> -+#include <net/ip.h>
> -+#include <net/ipv6.h>
> -+#include <net/udp.h>
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+#define sk_family family
> -+#define sk_protocol protocol
> -+#define sk_type type
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> -+
> -+/* Structure for holding "struct vfsmount *" and "struct dentry *". */
> -+struct path {
> -+	struct vfsmount *mnt;
> -+	struct dentry *dentry;
> -+};
> -+
> -+#endif
> -+
> -+#ifndef __printf
> -+#define __printf(a,b) __attribute__((format(printf,a,b)))
> -+#endif
> -+#ifndef __packed
> -+#define __packed __attribute__((__packed__))
> -+#endif
> -+#ifndef bool
> -+#define bool _Bool
> -+#endif
> -+#ifndef false
> -+#define false 0
> -+#endif
> -+#ifndef true
> -+#define true 1
> -+#endif
> -+
> -+#ifndef __user
> -+#define __user
> -+#endif
> -+
> -+#ifndef current_uid
> -+#define current_uid()   (current->uid)
> -+#endif
> -+#ifndef current_gid
> -+#define current_gid()   (current->gid)
> -+#endif
> -+#ifndef current_euid
> -+#define current_euid()  (current->euid)
> -+#endif
> -+#ifndef current_egid
> -+#define current_egid()  (current->egid)
> -+#endif
> -+#ifndef current_suid
> -+#define current_suid()  (current->suid)
> -+#endif
> -+#ifndef current_sgid
> -+#define current_sgid()  (current->sgid)
> -+#endif
> -+#ifndef current_fsuid
> -+#define current_fsuid() (current->fsuid)
> -+#endif
> -+#ifndef current_fsgid
> -+#define current_fsgid() (current->fsgid)
> -+#endif
> -+
> -+#ifndef DEFINE_SPINLOCK
> -+#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
> -+#define mutex semaphore
> -+#define mutex_init(mutex) init_MUTEX(mutex)
> -+#define mutex_unlock(mutex) up(mutex)
> -+#define mutex_lock(mutex) down(mutex)
> -+#define mutex_lock_interruptible(mutex) down_interruptible(mutex)
> -+#define mutex_trylock(mutex) (!down_trylock(mutex))
> -+#define DEFINE_MUTEX(mutexname) DECLARE_MUTEX(mutexname)
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15)
> -+#define MS_UNBINDABLE	(1<<17)	/* change to unbindable */
> -+#define MS_PRIVATE	(1<<18)	/* change to private */
> -+#define MS_SLAVE	(1<<19)	/* change to slave */
> -+#define MS_SHARED	(1<<20)	/* change to shared */
> -+#endif
> -+
> -+#ifndef container_of
> -+#define container_of(ptr, type, member) ({				\
> -+			const typeof(((type *)0)->member) *__mptr = (ptr); \
> -+			(type *)((char *)__mptr - offsetof(type, member)); })
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
> -+#define smp_read_barrier_depends smp_rmb
> -+#endif
> -+
> -+#ifndef ACCESS_ONCE
> -+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
> -+#endif
> -+
> -+#ifndef rcu_dereference
> -+#define rcu_dereference(p)     ({					\
> -+			typeof(p) _________p1 = ACCESS_ONCE(p);		\
> -+			smp_read_barrier_depends(); /* see RCU */	\
> -+			(_________p1);					\
> -+		})
> -+#endif
> -+
> -+#ifndef rcu_assign_pointer
> -+#define rcu_assign_pointer(p, v)			\
> -+	({						\
> -+		if (!__builtin_constant_p(v) ||		\
> -+		    ((v) != NULL))			\
> -+			smp_wmb(); /* see RCU */	\
> -+		(p) = (v);				\
> -+	})
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
> -+#define f_vfsmnt f_path.mnt
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
> -+
> -+/**
> -+ * kzalloc() - Allocate memory. The memory is set to zero.
> -+ *
> -+ * @size:  Size to allocate.
> -+ * @flags: GFP flags.
> -+ *
> -+ * Returns pointer to allocated memory on success, NULL otherwise.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ *
> -+ * Since several distributions backported kzalloc(), I define it as a macro
> -+ * rather than an inlined function in order to avoid multiple definition error.
> -+ */
> -+#define kzalloc(size, flags) ({					\
> -+			void *ret = kmalloc((size), (flags));	\
> -+			if (ret)				\
> -+				memset(ret, 0, (size));		\
> -+			ret; })
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
> -+
> -+/**
> -+ * path_put - Drop reference on "struct path".
> -+ *
> -+ * @path: Pointer to "struct path".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline void path_put(struct path *path)
> -+{
> -+	dput(path->dentry);
> -+	mntput(path->mnt);
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+
> -+/**
> -+ * __list_add_rcu - Insert a new entry between two known consecutive entries.
> -+ *
> -+ * @new:  Pointer to "struct list_head".
> -+ * @prev: Pointer to "struct list_head".
> -+ * @next: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline void __list_add_rcu(struct list_head *new,
> -+				  struct list_head *prev,
> -+				  struct list_head *next)
> -+{
> -+	new->next = next;
> -+	new->prev = prev;
> -+	rcu_assign_pointer(prev->next, new);
> -+	next->prev = new;
> -+}
> -+
> -+/**
> -+ * list_add_tail_rcu - Add a new entry to rcu-protected list.
> -+ *
> -+ * @new:  Pointer to "struct list_head".
> -+ * @head: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline void list_add_tail_rcu(struct list_head *new,
> -+				     struct list_head *head)
> -+{
> -+	__list_add_rcu(new, head->prev, head);
> -+}
> -+
> -+/**
> -+ * list_add_rcu - Add a new entry to rcu-protected list.
> -+ *
> -+ * @new:  Pointer to "struct list_head".
> -+ * @head: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline void list_add_rcu(struct list_head *new, struct list_head *head)
> -+{
> -+	__list_add_rcu(new, head, head->next);
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
> -+
> -+/**
> -+ * __list_del_entry - Deletes entry from list without re-initialization.
> -+ *
> -+ * @entry: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline void __list_del_entry(struct list_head *entry)
> -+{
> -+	__list_del(entry->prev, entry->next);
> -+}
> -+
> -+#endif
> -+
> -+#ifndef list_for_each_entry_safe
> -+
> -+/**
> -+ * list_for_each_entry_safe - Iterate over list of given type safe against removal of list entry.
> -+ *
> -+ * @pos:    The "type *" to use as a loop cursor.
> -+ * @n:      Another "type *" to use as temporary storage.
> -+ * @head:   Pointer to "struct list_head".
> -+ * @member: The name of the list_struct within the struct.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+#define list_for_each_entry_safe(pos, n, head, member)                  \
> -+	for (pos = list_entry((head)->next, typeof(*pos), member),      \
> -+		     n = list_entry(pos->member.next, typeof(*pos), member); \
> -+	     &pos->member != (head);					\
> -+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
> -+
> -+#endif
> -+
> -+#ifndef srcu_dereference
> -+
> -+/**
> -+ * srcu_dereference - Fetch SRCU-protected pointer with checking.
> -+ *
> -+ * @p:  The pointer to read, prior to dereferencing.
> -+ * @ss: Pointer to "struct srcu_struct".
> -+ *
> -+ * Returns @p.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+#define srcu_dereference(p, ss) rcu_dereference(p)
> -+
> -+#endif
> -+
> -+#ifndef list_for_each_entry_srcu
> -+
> -+/**
> -+ * list_for_each_entry_srcu - Iterate over rcu list of given type.
> -+ *
> -+ * @pos:    The type * to use as a loop cursor.
> -+ * @head:   The head for your list.
> -+ * @member: The name of the list_struct within the struct.
> -+ * @ss:     Pointer to "struct srcu_struct".
> -+ *
> -+ * As of 2.6.36, this macro is not provided because only TOMOYO wants it.
> -+ */
> -+#define list_for_each_entry_srcu(pos, head, member, ss)		      \
> -+	for (pos = list_entry(srcu_dereference((head)->next, ss),     \
> -+			      typeof(*pos), member);		      \
> -+	     prefetch(pos->member.next), &pos->member != (head);      \
> -+	     pos = list_entry(srcu_dereference(pos->member.next, ss), \
> -+			      typeof(*pos), member))
> -+
> -+#endif
> -+
> -+#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))
> -+
> -+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 4, 21)
> -+#undef ssleep
> -+#endif
> -+
> -+#ifndef ssleep
> -+
> -+/**
> -+ * ssleep - Sleep for specified seconds.
> -+ *
> -+ * @secs: Seconds to sleep.
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ *
> -+ * Since several distributions backported ssleep(), I define it as a macro
> -+ * rather than an inlined function in order to avoid multiple definition error.
> -+ */
> -+#define ssleep(secs) {						\
> -+		set_current_state(TASK_UNINTERRUPTIBLE);	\
> -+		schedule_timeout((HZ * secs) + 1);		\
> -+	}
> -+
> -+#endif
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 5, 0)
> -+
> -+/**
> -+ * from_kuid - Convert kuid_t to uid_t.
> -+ *
> -+ * @ns:  Unused.
> -+ * @uid: kuid_t value.
> -+ *
> -+ * Returns uid seen from init's user namespace.
> -+ */
> -+#define from_kuid(ns, uid) (uid)
> -+
> -+/**
> -+ * from_kgid - Convert kgid_t to gid_t.
> -+ *
> -+ * @ns:  Unused.
> -+ * @gid: kgid_t value.
> -+ *
> -+ * Returns gid seen from init's user namespace.
> -+ */
> -+#define from_kgid(ns, gid) (gid)
> -+
> -+/**
> -+ * uid_eq - Check whether the uids are equals or not.
> -+ *
> -+ * @left: Uid seen from current user namespace.
> -+ * @right: Uid seen from current user namespace.
> -+ *
> -+ * Returns true if uid is root in init's user namespace, false otherwise.
> -+ */
> -+#define uid_eq(left, right) ((left) == (right))
> -+#define GLOBAL_ROOT_UID 0
> -+
> -+#endif
> -+
> -+/*
> -+ * TOMOYO specific part start.
> -+ */
> -+
> -+#include <linux/ccsecurity.h>
> -+
> -+/* Enumeration definition for internal use. */
> -+
> -+/* Index numbers for Access Controls. */
> -+enum ccs_acl_entry_type_index {
> -+	CCS_TYPE_PATH_ACL,
> -+	CCS_TYPE_PATH2_ACL,
> -+	CCS_TYPE_PATH_NUMBER_ACL,
> -+	CCS_TYPE_MKDEV_ACL,
> -+	CCS_TYPE_MOUNT_ACL,
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	CCS_TYPE_ENV_ACL,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	CCS_TYPE_CAPABILITY_ACL,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	CCS_TYPE_INET_ACL,
> -+	CCS_TYPE_UNIX_ACL,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	CCS_TYPE_SIGNAL_ACL,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	CCS_TYPE_AUTO_EXECUTE_HANDLER,
> -+	CCS_TYPE_DENIED_EXECUTE_HANDLER,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+	CCS_TYPE_AUTO_TASK_ACL,
> -+	CCS_TYPE_MANUAL_TASK_ACL,
> -+#endif
> -+};
> -+
> -+/* Index numbers for "struct ccs_condition". */
> -+enum ccs_conditions_index {
> -+	CCS_TASK_UID,             /* current_uid()   */
> -+	CCS_TASK_EUID,            /* current_euid()  */
> -+	CCS_TASK_SUID,            /* current_suid()  */
> -+	CCS_TASK_FSUID,           /* current_fsuid() */
> -+	CCS_TASK_GID,             /* current_gid()   */
> -+	CCS_TASK_EGID,            /* current_egid()  */
> -+	CCS_TASK_SGID,            /* current_sgid()  */
> -+	CCS_TASK_FSGID,           /* current_fsgid() */
> -+	CCS_TASK_PID,             /* sys_getpid()   */
> -+	CCS_TASK_PPID,            /* sys_getppid()  */
> -+	CCS_EXEC_ARGC,            /* "struct linux_binprm *"->argc */
> -+	CCS_EXEC_ENVC,            /* "struct linux_binprm *"->envc */
> -+	CCS_TYPE_IS_SOCKET,       /* S_IFSOCK */
> -+	CCS_TYPE_IS_SYMLINK,      /* S_IFLNK */
> -+	CCS_TYPE_IS_FILE,         /* S_IFREG */
> -+	CCS_TYPE_IS_BLOCK_DEV,    /* S_IFBLK */
> -+	CCS_TYPE_IS_DIRECTORY,    /* S_IFDIR */
> -+	CCS_TYPE_IS_CHAR_DEV,     /* S_IFCHR */
> -+	CCS_TYPE_IS_FIFO,         /* S_IFIFO */
> -+	CCS_MODE_SETUID,          /* S_ISUID */
> -+	CCS_MODE_SETGID,          /* S_ISGID */
> -+	CCS_MODE_STICKY,          /* S_ISVTX */
> -+	CCS_MODE_OWNER_READ,      /* S_IRUSR */
> -+	CCS_MODE_OWNER_WRITE,     /* S_IWUSR */
> -+	CCS_MODE_OWNER_EXECUTE,   /* S_IXUSR */
> -+	CCS_MODE_GROUP_READ,      /* S_IRGRP */
> -+	CCS_MODE_GROUP_WRITE,     /* S_IWGRP */
> -+	CCS_MODE_GROUP_EXECUTE,   /* S_IXGRP */
> -+	CCS_MODE_OTHERS_READ,     /* S_IROTH */
> -+	CCS_MODE_OTHERS_WRITE,    /* S_IWOTH */
> -+	CCS_MODE_OTHERS_EXECUTE,  /* S_IXOTH */
> -+	CCS_TASK_TYPE,            /* ((u8) task->ccs_flags) &
> -+				     CCS_TASK_IS_EXECUTE_HANDLER */
> -+	CCS_TASK_EXECUTE_HANDLER, /* CCS_TASK_IS_EXECUTE_HANDLER */
> -+	CCS_EXEC_REALPATH,
> -+	CCS_SYMLINK_TARGET,
> -+	CCS_PATH1_UID,
> -+	CCS_PATH1_GID,
> -+	CCS_PATH1_INO,
> -+	CCS_PATH1_MAJOR,
> -+	CCS_PATH1_MINOR,
> -+	CCS_PATH1_PERM,
> -+	CCS_PATH1_TYPE,
> -+	CCS_PATH1_DEV_MAJOR,
> -+	CCS_PATH1_DEV_MINOR,
> -+	CCS_PATH2_UID,
> -+	CCS_PATH2_GID,
> -+	CCS_PATH2_INO,
> -+	CCS_PATH2_MAJOR,
> -+	CCS_PATH2_MINOR,
> -+	CCS_PATH2_PERM,
> -+	CCS_PATH2_TYPE,
> -+	CCS_PATH2_DEV_MAJOR,
> -+	CCS_PATH2_DEV_MINOR,
> -+	CCS_PATH1_PARENT_UID,
> -+	CCS_PATH1_PARENT_GID,
> -+	CCS_PATH1_PARENT_INO,
> -+	CCS_PATH1_PARENT_PERM,
> -+	CCS_PATH2_PARENT_UID,
> -+	CCS_PATH2_PARENT_GID,
> -+	CCS_PATH2_PARENT_INO,
> -+	CCS_PATH2_PARENT_PERM,
> -+	CCS_MAX_CONDITION_KEYWORD,
> -+	CCS_NUMBER_UNION,
> -+	CCS_NAME_UNION,
> -+	CCS_ARGV_ENTRY,
> -+	CCS_ENVP_ENTRY,
> -+};
> -+
> -+/* Index numbers for domain's attributes. */
> -+enum ccs_domain_info_flags_index {
> -+	/* Quota warnning flag.   */
> -+	CCS_DIF_QUOTA_WARNED,
> -+	/*
> -+	 * This domain was unable to create a new domain at
> -+	 * ccs_find_next_domain() because the name of the domain to be created
> -+	 * was too long or it could not allocate memory.
> -+	 * More than one process continued execve() without domain transition.
> -+	 */
> -+	CCS_DIF_TRANSITION_FAILED,
> -+	CCS_MAX_DOMAIN_INFO_FLAGS
> -+};
> -+
> -+/* Index numbers for audit type. */
> -+enum ccs_grant_log {
> -+	/* Follow profile's configuration. */
> -+	CCS_GRANTLOG_AUTO,
> -+	/* Do not generate grant log. */
> -+	CCS_GRANTLOG_NO,
> -+	/* Generate grant_log. */
> -+	CCS_GRANTLOG_YES,
> -+};
> -+
> -+/* Index numbers for group entries. */
> -+enum ccs_group_id {
> -+	CCS_PATH_GROUP,
> -+	CCS_NUMBER_GROUP,
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	CCS_ADDRESS_GROUP,
> -+#endif
> -+	CCS_MAX_GROUP
> -+};
> -+
> -+/* Index numbers for category of functionality. */
> -+enum ccs_mac_category_index {
> -+	CCS_MAC_CATEGORY_FILE,
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	CCS_MAC_CATEGORY_NETWORK,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	CCS_MAC_CATEGORY_MISC,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	CCS_MAC_CATEGORY_IPC,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	CCS_MAC_CATEGORY_CAPABILITY,
> -+#endif
> -+	CCS_MAX_MAC_CATEGORY_INDEX
> -+};
> -+
> -+/* Index numbers for functionality. */
> -+enum ccs_mac_index {
> -+	CCS_MAC_FILE_EXECUTE,
> -+	CCS_MAC_FILE_OPEN,
> -+	CCS_MAC_FILE_CREATE,
> -+	CCS_MAC_FILE_UNLINK,
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+	CCS_MAC_FILE_GETATTR,
> -+#endif
> -+	CCS_MAC_FILE_MKDIR,
> -+	CCS_MAC_FILE_RMDIR,
> -+	CCS_MAC_FILE_MKFIFO,
> -+	CCS_MAC_FILE_MKSOCK,
> -+	CCS_MAC_FILE_TRUNCATE,
> -+	CCS_MAC_FILE_SYMLINK,
> -+	CCS_MAC_FILE_MKBLOCK,
> -+	CCS_MAC_FILE_MKCHAR,
> -+	CCS_MAC_FILE_LINK,
> -+	CCS_MAC_FILE_RENAME,
> -+	CCS_MAC_FILE_CHMOD,
> -+	CCS_MAC_FILE_CHOWN,
> -+	CCS_MAC_FILE_CHGRP,
> -+	CCS_MAC_FILE_IOCTL,
> -+	CCS_MAC_FILE_CHROOT,
> -+	CCS_MAC_FILE_MOUNT,
> -+	CCS_MAC_FILE_UMOUNT,
> -+	CCS_MAC_FILE_PIVOT_ROOT,
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	CCS_MAC_NETWORK_INET_STREAM_BIND,
> -+	CCS_MAC_NETWORK_INET_STREAM_LISTEN,
> -+	CCS_MAC_NETWORK_INET_STREAM_CONNECT,
> -+	CCS_MAC_NETWORK_INET_STREAM_ACCEPT,
> -+	CCS_MAC_NETWORK_INET_DGRAM_BIND,
> -+	CCS_MAC_NETWORK_INET_DGRAM_SEND,
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	CCS_MAC_NETWORK_INET_DGRAM_RECV,
> -+#endif
> -+	CCS_MAC_NETWORK_INET_RAW_BIND,
> -+	CCS_MAC_NETWORK_INET_RAW_SEND,
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	CCS_MAC_NETWORK_INET_RAW_RECV,
> -+#endif
> -+	CCS_MAC_NETWORK_UNIX_STREAM_BIND,
> -+	CCS_MAC_NETWORK_UNIX_STREAM_LISTEN,
> -+	CCS_MAC_NETWORK_UNIX_STREAM_CONNECT,
> -+	CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT,
> -+	CCS_MAC_NETWORK_UNIX_DGRAM_BIND,
> -+	CCS_MAC_NETWORK_UNIX_DGRAM_SEND,
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	CCS_MAC_NETWORK_UNIX_DGRAM_RECV,
> -+#endif
> -+	CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND,
> -+	CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
> -+	CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
> -+	CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	CCS_MAC_ENVIRON,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	CCS_MAC_SIGNAL,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET,
> -+	CCS_MAC_CAPABILITY_USE_PACKET_SOCKET,
> -+	CCS_MAC_CAPABILITY_SYS_REBOOT,
> -+	CCS_MAC_CAPABILITY_SYS_VHANGUP,
> -+	CCS_MAC_CAPABILITY_SYS_SETTIME,
> -+	CCS_MAC_CAPABILITY_SYS_NICE,
> -+	CCS_MAC_CAPABILITY_SYS_SETHOSTNAME,
> -+	CCS_MAC_CAPABILITY_USE_KERNEL_MODULE,
> -+	CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD,
> -+	CCS_MAC_CAPABILITY_SYS_PTRACE,
> -+#endif
> -+	CCS_MAX_MAC_INDEX
> -+};
> -+
> -+/* Index numbers for /proc/ccs/stat interface. */
> -+enum ccs_memory_stat_type {
> -+	CCS_MEMORY_POLICY,
> -+	CCS_MEMORY_AUDIT,
> -+	CCS_MEMORY_QUERY,
> -+	CCS_MAX_MEMORY_STAT
> -+};
> -+
> -+/* Index numbers for access controls with one pathname and three numbers. */
> -+enum ccs_mkdev_acl_index {
> -+	CCS_TYPE_MKBLOCK,
> -+	CCS_TYPE_MKCHAR,
> -+	CCS_MAX_MKDEV_OPERATION
> -+};
> -+
> -+/* Index numbers for operation mode. */
> -+enum ccs_mode_value {
> -+	CCS_CONFIG_DISABLED,
> -+	CCS_CONFIG_LEARNING,
> -+	CCS_CONFIG_PERMISSIVE,
> -+	CCS_CONFIG_ENFORCING,
> -+	CCS_CONFIG_MAX_MODE,
> -+	CCS_CONFIG_WANT_REJECT_LOG =  64,
> -+	CCS_CONFIG_WANT_GRANT_LOG  = 128,
> -+	CCS_CONFIG_USE_DEFAULT     = 255,
> -+};
> -+
> -+/* Index numbers for socket operations. */
> -+enum ccs_network_acl_index {
> -+	CCS_NETWORK_BIND,    /* bind() operation. */
> -+	CCS_NETWORK_LISTEN,  /* listen() operation. */
> -+	CCS_NETWORK_CONNECT, /* connect() operation. */
> -+	CCS_NETWORK_ACCEPT,  /* accept() operation. */
> -+	CCS_NETWORK_SEND,    /* send() operation. */
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	CCS_NETWORK_RECV,    /* recv() operation. */
> -+#endif
> -+	CCS_MAX_NETWORK_OPERATION
> -+};
> -+
> -+/* Index numbers for access controls with two pathnames. */
> -+enum ccs_path2_acl_index {
> -+	CCS_TYPE_LINK,
> -+	CCS_TYPE_RENAME,
> -+	CCS_TYPE_PIVOT_ROOT,
> -+	CCS_MAX_PATH2_OPERATION
> -+};
> -+
> -+/* Index numbers for access controls with one pathname. */
> -+enum ccs_path_acl_index {
> -+	CCS_TYPE_EXECUTE,
> -+	CCS_TYPE_READ,
> -+	CCS_TYPE_WRITE,
> -+	CCS_TYPE_APPEND,
> -+	CCS_TYPE_UNLINK,
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+	CCS_TYPE_GETATTR,
> -+#endif
> -+	CCS_TYPE_RMDIR,
> -+	CCS_TYPE_TRUNCATE,
> -+	CCS_TYPE_SYMLINK,
> -+	CCS_TYPE_CHROOT,
> -+	CCS_TYPE_UMOUNT,
> -+	CCS_MAX_PATH_OPERATION
> -+};
> -+
> -+/* Index numbers for access controls with one pathname and one number. */
> -+enum ccs_path_number_acl_index {
> -+	CCS_TYPE_CREATE,
> -+	CCS_TYPE_MKDIR,
> -+	CCS_TYPE_MKFIFO,
> -+	CCS_TYPE_MKSOCK,
> -+	CCS_TYPE_IOCTL,
> -+	CCS_TYPE_CHMOD,
> -+	CCS_TYPE_CHOWN,
> -+	CCS_TYPE_CHGRP,
> -+	CCS_MAX_PATH_NUMBER_OPERATION
> -+};
> -+
> -+/* Index numbers for stat(). */
> -+enum ccs_path_stat_index {
> -+	/* Do not change this order. */
> -+	CCS_PATH1,
> -+	CCS_PATH1_PARENT,
> -+	CCS_PATH2,
> -+	CCS_PATH2_PARENT,
> -+	CCS_MAX_PATH_STAT
> -+};
> -+
> -+/* Index numbers for entry type. */
> -+enum ccs_policy_id {
> -+#ifdef CONFIG_CCSECURITY_PORTRESERVE
> -+	CCS_ID_RESERVEDPORT,
> -+#endif
> -+	CCS_ID_GROUP,
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	CCS_ID_ADDRESS_GROUP,
> -+#endif
> -+	CCS_ID_PATH_GROUP,
> -+	CCS_ID_NUMBER_GROUP,
> -+	CCS_ID_AGGREGATOR,
> -+	CCS_ID_TRANSITION_CONTROL,
> -+	CCS_ID_MANAGER,
> -+	CCS_ID_CONDITION,
> -+	CCS_ID_NAME,
> -+	CCS_ID_ACL,
> -+	CCS_ID_DOMAIN,
> -+	CCS_MAX_POLICY
> -+};
> -+
> -+/* Index numbers for /proc/ccs/stat interface. */
> -+enum ccs_policy_stat_type {
> -+	/* Do not change this order. */
> -+	CCS_STAT_POLICY_UPDATES,
> -+	CCS_STAT_POLICY_LEARNING,   /* == CCS_CONFIG_LEARNING */
> -+	CCS_STAT_POLICY_PERMISSIVE, /* == CCS_CONFIG_PERMISSIVE */
> -+	CCS_STAT_POLICY_ENFORCING,  /* == CCS_CONFIG_ENFORCING */
> -+	CCS_MAX_POLICY_STAT
> -+};
> -+
> -+/* Index numbers for profile's PREFERENCE values. */
> -+enum ccs_pref_index {
> -+	CCS_PREF_MAX_AUDIT_LOG,
> -+	CCS_PREF_MAX_LEARNING_ENTRY,
> -+	CCS_PREF_ENFORCING_PENALTY,
> -+	CCS_MAX_PREF
> -+};
> -+
> -+/* Index numbers for /proc/ccs/ interfaces. */
> -+enum ccs_proc_interface_index {
> -+	CCS_DOMAIN_POLICY,
> -+	CCS_EXCEPTION_POLICY,
> -+	CCS_PROCESS_STATUS,
> -+	CCS_STAT,
> -+	CCS_AUDIT,
> -+	CCS_VERSION,
> -+	CCS_PROFILE,
> -+	CCS_QUERY,
> -+	CCS_MANAGER,
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	CCS_EXECUTE_HANDLER,
> -+#endif
> -+};
> -+
> -+/* Index numbers for special mount operations. */
> -+enum ccs_special_mount {
> -+	CCS_MOUNT_BIND,            /* mount --bind /source /dest   */
> -+	CCS_MOUNT_MOVE,            /* mount --move /old /new       */
> -+	CCS_MOUNT_REMOUNT,         /* mount -o remount /dir        */
> -+	CCS_MOUNT_MAKE_UNBINDABLE, /* mount --make-unbindable /dir */
> -+	CCS_MOUNT_MAKE_PRIVATE,    /* mount --make-private /dir    */
> -+	CCS_MOUNT_MAKE_SLAVE,      /* mount --make-slave /dir      */
> -+	CCS_MOUNT_MAKE_SHARED,     /* mount --make-shared /dir     */
> -+	CCS_MAX_SPECIAL_MOUNT
> -+};
> -+
> -+/* Index numbers for domain transition control keywords. */
> -+enum ccs_transition_type {
> -+	/* Do not change this order, */
> -+	CCS_TRANSITION_CONTROL_NO_RESET,
> -+	CCS_TRANSITION_CONTROL_RESET,
> -+	CCS_TRANSITION_CONTROL_NO_INITIALIZE,
> -+	CCS_TRANSITION_CONTROL_INITIALIZE,
> -+	CCS_TRANSITION_CONTROL_NO_KEEP,
> -+	CCS_TRANSITION_CONTROL_KEEP,
> -+	CCS_MAX_TRANSITION_TYPE
> -+};
> -+
> -+/* Index numbers for type of numeric values. */
> -+enum ccs_value_type {
> -+	CCS_VALUE_TYPE_INVALID,
> -+	CCS_VALUE_TYPE_DECIMAL,
> -+	CCS_VALUE_TYPE_OCTAL,
> -+	CCS_VALUE_TYPE_HEXADECIMAL,
> -+};
> -+
> -+/* Constants definition for internal use. */
> -+
> -+/*
> -+ * TOMOYO uses this hash only when appending a string into the string table.
> -+ * Frequency of appending strings is very low. So we don't need large (e.g.
> -+ * 64k) hash size. 256 will be sufficient.
> -+ */
> -+#define CCS_HASH_BITS 8
> -+#define CCS_MAX_HASH (1u << CCS_HASH_BITS)
> -+
> -+/*
> -+ * TOMOYO checks only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET.
> -+ * Therefore, we don't need SOCK_MAX.
> -+ */
> -+#define CCS_SOCK_MAX 6
> -+
> -+/* Size of temporary buffer for execve() operation. */
> -+#define CCS_EXEC_TMPSIZE     4096
> -+
> -+/* Garbage collector is trying to kfree() this element. */
> -+#define CCS_GC_IN_PROGRESS -1
> -+
> -+/* Profile number is an integer between 0 and 255. */
> -+#define CCS_MAX_PROFILES 256
> -+
> -+/* Group number is an integer between 0 and 255. */
> -+#define CCS_MAX_ACL_GROUPS 256
> -+
> -+/* Current thread is doing open(O_RDONLY | O_TRUNC) ? */
> -+#define CCS_OPEN_FOR_READ_TRUNCATE        1
> -+/* Current thread is doing open(3) ? */
> -+#define CCS_OPEN_FOR_IOCTL_ONLY           2
> -+/* Current thread is doing do_execve() ? */
> -+#define CCS_TASK_IS_IN_EXECVE             4
> -+/* Current thread is running as an execute handler program? */
> -+#define CCS_TASK_IS_EXECUTE_HANDLER       8
> -+/* Current thread is allowed to modify policy via /proc/ccs/ interface? */
> -+#define CCS_TASK_IS_MANAGER              16
> -+
> -+/*
> -+ * Retry this request. Returned by ccs_supervisor() if policy violation has
> -+ * occurred in enforcing mode and the userspace daemon decided to retry.
> -+ *
> -+ * We must choose a positive value in order to distinguish "granted" (which is
> -+ * 0) and "rejected" (which is a negative value) and "retry".
> -+ */
> -+#define CCS_RETRY_REQUEST 1
> -+
> -+/* Ignore gfp flags which are not supported. */
> -+#ifndef __GFP_HIGHIO
> -+#define __GFP_HIGHIO 0
> -+#endif
> -+#ifndef __GFP_NOWARN
> -+#define __GFP_NOWARN 0
> -+#endif
> -+#ifndef __GFP_NORETRY
> -+#define __GFP_NORETRY 0
> -+#endif
> -+#ifndef __GFP_NOMEMALLOC
> -+#define __GFP_NOMEMALLOC 0
> -+#endif
> -+
> -+/* The gfp flags used by TOMOYO. */
> -+#define CCS_GFP_FLAGS (__GFP_WAIT | __GFP_IO | __GFP_HIGHIO | __GFP_NOWARN | \
> -+		       __GFP_NORETRY | __GFP_NOMEMALLOC)
> -+
> -+/* Size of read buffer for /proc/ccs/ interface. */
> -+#define CCS_MAX_IO_READ_QUEUE 64
> -+
> -+/* Structure definition for internal use. */
> -+
> -+/* Common header for holding ACL entries. */
> -+struct ccs_acl_head {
> -+	struct list_head list;
> -+	s8 is_deleted; /* true or false or CCS_GC_IN_PROGRESS */
> -+} __packed;
> -+
> -+/* Common header for shared entries. */
> -+struct ccs_shared_acl_head {
> -+	struct list_head list;
> -+	atomic_t users;
> -+} __packed;
> -+
> -+/* Common header for individual entries. */
> -+struct ccs_acl_info {
> -+	struct list_head list;
> -+	struct ccs_condition *cond; /* Maybe NULL. */
> -+	s8 is_deleted; /* true or false or CCS_GC_IN_PROGRESS */
> -+	u8 type; /* One of values in "enum ccs_acl_entry_type_index". */
> -+	u16 perm;
> -+} __packed;
> -+
> -+/* Structure for holding a word. */
> -+struct ccs_name_union {
> -+	/* Either @filename or @group is NULL. */
> -+	const struct ccs_path_info *filename;
> -+	struct ccs_group *group;
> -+};
> -+
> -+/* Structure for holding a number. */
> -+struct ccs_number_union {
> -+	unsigned long values[2];
> -+	struct ccs_group *group; /* Maybe NULL. */
> -+	/* One of values in "enum ccs_value_type". */
> -+	u8 value_type[2];
> -+};
> -+
> -+/* Structure for holding an IP address. */
> -+struct ccs_ipaddr_union {
> -+	struct in6_addr ip[2]; /* Big endian. */
> -+	struct ccs_group *group; /* Pointer to address group. */
> -+	bool is_ipv6; /* Valid only if @group == NULL. */
> -+};
> -+
> -+/* Structure for "path_group"/"number_group"/"address_group" directive. */
> -+struct ccs_group {
> -+	struct ccs_shared_acl_head head;
> -+	/* Name of group (without leading '@'). */
> -+	const struct ccs_path_info *group_name;
> -+	/*
> -+	 * List of "struct ccs_path_group" or "struct ccs_number_group" or
> -+	 * "struct ccs_address_group".
> -+	 */
> -+	struct list_head member_list;
> -+};
> -+
> -+/* Structure for "path_group" directive. */
> -+struct ccs_path_group {
> -+	struct ccs_acl_head head;
> -+	const struct ccs_path_info *member_name;
> -+};
> -+
> -+/* Structure for "number_group" directive. */
> -+struct ccs_number_group {
> -+	struct ccs_acl_head head;
> -+	struct ccs_number_union number;
> -+};
> -+
> -+/* Structure for "address_group" directive. */
> -+struct ccs_address_group {
> -+	struct ccs_acl_head head;
> -+	/* Structure for holding an IP address. */
> -+	struct ccs_ipaddr_union address;
> -+};
> -+
> -+/* Subset of "struct stat". Used by conditional ACL and audit logs. */
> -+struct ccs_mini_stat {
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
> -+	kuid_t uid;
> -+	kgid_t gid;
> -+#else
> -+	uid_t uid;
> -+	gid_t gid;
> -+#endif
> -+	ino_t ino;
> -+	umode_t mode;
> -+	dev_t dev;
> -+	dev_t rdev;
> -+};
> -+
> -+/* Structure for dumping argv[] and envp[] of "struct linux_binprm". */
> -+struct ccs_page_dump {
> -+	struct page *page;    /* Previously dumped page. */
> -+	char *data;           /* Contents of "page". Size is PAGE_SIZE. */
> -+};
> -+
> -+/* Structure for attribute checks in addition to pathname checks. */
> -+struct ccs_obj_info {
> -+	/* True if ccs_get_attributes() was already called, false otherwise. */
> -+	bool validate_done;
> -+	/* True if @stat[] is valid. */
> -+	bool stat_valid[CCS_MAX_PATH_STAT];
> -+	/* First pathname. Initialized with { NULL, NULL } if no path. */
> -+	struct path path1;
> -+	/* Second pathname. Initialized with { NULL, NULL } if no path. */
> -+	struct path path2;
> -+	/*
> -+	 * Information on @path1, @path1's parent directory, @path2, @path2's
> -+	 * parent directory.
> -+	 */
> -+	struct ccs_mini_stat stat[CCS_MAX_PATH_STAT];
> -+	/*
> -+	 * Content of symbolic link to be created. NULL for operations other
> -+	 * than symlink().
> -+	 */
> -+	struct ccs_path_info *symlink_target;
> -+};
> -+
> -+/* Structure for entries which follows "struct ccs_condition". */
> -+struct ccs_condition_element {
> -+	/*
> -+	 * Left hand operand. A "struct ccs_argv" for CCS_ARGV_ENTRY, a
> -+	 * "struct ccs_envp" for CCS_ENVP_ENTRY is attached to the tail
> -+	 * of the array of this struct.
> -+	 */
> -+	u8 left;
> -+	/*
> -+	 * Right hand operand. A "struct ccs_number_union" for
> -+	 * CCS_NUMBER_UNION, a "struct ccs_name_union" for CCS_NAME_UNION is
> -+	 * attached to the tail of the array of this struct.
> -+	 */
> -+	u8 right;
> -+	/* Equation operator. True if equals or overlaps, false otherwise. */
> -+	bool equals;
> -+};
> -+
> -+/* Structure for optional arguments. */
> -+struct ccs_condition {
> -+	struct ccs_shared_acl_head head;
> -+	u32 size; /* Memory size allocated for this entry. */
> -+	u16 condc; /* Number of conditions in this struct. */
> -+	u16 numbers_count; /* Number of "struct ccs_number_union values". */
> -+	u16 names_count; /* Number of "struct ccs_name_union names". */
> -+	u16 argc; /* Number of "struct ccs_argv". */
> -+	u16 envc; /* Number of "struct ccs_envp". */
> -+	u8 grant_log; /* One of values in "enum ccs_grant_log". */
> -+	bool exec_transit; /* True if transit is for "file execute". */
> -+	const struct ccs_path_info *transit; /* Maybe NULL. */
> -+	/*
> -+	 * struct ccs_condition_element condition[condc];
> -+	 * struct ccs_number_union values[numbers_count];
> -+	 * struct ccs_name_union names[names_count];
> -+	 * struct ccs_argv argv[argc];
> -+	 * struct ccs_envp envp[envc];
> -+	 */
> -+};
> -+
> -+struct ccs_execve;
> -+struct ccs_policy_namespace;
> -+
> -+/* Structure for request info. */
> -+struct ccs_request_info {
> -+	/*
> -+	 * For holding parameters specific to operations which deal files.
> -+	 * NULL if not dealing files.
> -+	 */
> -+	struct ccs_obj_info *obj;
> -+	/*
> -+	 * For holding parameters specific to execve() request.
> -+	 * NULL if not dealing do_execve().
> -+	 */
> -+	struct ccs_execve *ee;
> -+	/*
> -+	 * For holding parameters.
> -+	 * Pointers in this union are not NULL except path->matched_path.
> -+	 */
> -+	union {
> -+		struct {
> -+			const struct ccs_path_info *filename;
> -+			/*
> -+			 * For using wildcards at ccs_find_next_domain().
> -+			 *
> -+			 * The matched_acl cannot be used because it may refer
> -+			 * a "struct ccs_path_acl" with ->is_group == true.
> -+			 * We want to use exact "struct ccs_path_info" rather
> -+			 * than "struct ccs_path_acl".
> -+			 */
> -+			const struct ccs_path_info *matched_path;
> -+			/* One of values in "enum ccs_path_acl_index". */
> -+			u8 operation;
> -+		} path;
> -+		struct {
> -+			const struct ccs_path_info *filename1;
> -+			const struct ccs_path_info *filename2;
> -+			/* One of values in "enum ccs_path2_acl_index". */
> -+			u8 operation;
> -+		} path2;
> -+		struct {
> -+			const struct ccs_path_info *filename;
> -+			unsigned int mode;
> -+			unsigned int major;
> -+			unsigned int minor;
> -+			/* One of values in "enum ccs_mkdev_acl_index". */
> -+			u8 operation;
> -+		} mkdev;
> -+		struct {
> -+			const struct ccs_path_info *filename;
> -+			unsigned long number;
> -+			/*
> -+			 * One of values in "enum ccs_path_number_acl_index".
> -+			 */
> -+			u8 operation;
> -+		} path_number;
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+		struct {
> -+			const u32 *address; /* Big endian. */
> -+			u16 port; /* Host endian. */
> -+			/* One of values smaller than CCS_SOCK_MAX. */
> -+			u8 protocol;
> -+			/* One of values in "enum ccs_network_acl_index". */
> -+			u8 operation;
> -+			bool is_ipv6;
> -+		} inet_network;
> -+		struct {
> -+			const struct ccs_path_info *address;
> -+			/* One of values smaller than CCS_SOCK_MAX. */
> -+			u8 protocol;
> -+			/* One of values in "enum ccs_network_acl_index". */
> -+			u8 operation;
> -+		} unix_network;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+		struct {
> -+			const struct ccs_path_info *name;
> -+		} environ;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+		struct {
> -+			/* One of values in "enum ccs_capability_acl_index". */
> -+			u8 operation;
> -+		} capability;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+		struct {
> -+			const char *dest_pattern;
> -+			int sig;
> -+		} signal;
> -+#endif
> -+		struct {
> -+			const struct ccs_path_info *type;
> -+			const struct ccs_path_info *dir;
> -+			const struct ccs_path_info *dev;
> -+			unsigned long flags;
> -+			int need_dev;
> -+		} mount;
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+		struct {
> -+			const struct ccs_path_info *domainname;
> -+		} task;
> -+#endif
> -+	} param;
> -+	/*
> -+	 * For updating current->ccs_domain_info at ccs_update_task_domain().
> -+	 * Initialized to NULL at ccs_init_request_info().
> -+	 * Matching "struct ccs_acl_info" is copied if access request was
> -+	 * granted. Re-initialized to NULL at ccs_update_task_domain().
> -+	 */
> -+	struct ccs_acl_info *matched_acl;
> -+	u8 param_type; /* One of values in "enum ccs_acl_entry_type_index". */
> -+	bool granted; /* True if granted, false otherwise. */
> -+	/* True if current thread should not be carried sleep penalty. */
> -+	bool dont_sleep_on_enforce_error;
> -+	/*
> -+	 * For counting number of retries made for this request.
> -+	 * This counter is incremented whenever ccs_supervisor() returned
> -+	 * CCS_RETRY_REQUEST.
> -+	 */
> -+	u8 retry;
> -+	/*
> -+	 * For holding profile number used for this request.
> -+	 * One of values between 0 and CCS_MAX_PROFILES - 1.
> -+	 */
> -+	u8 profile;
> -+	/*
> -+	 * For holding operation mode used for this request.
> -+	 * One of CCS_CONFIG_DISABLED, CCS_CONFIG_LEARNING,
> -+	 * CCS_CONFIG_PERMISSIVE, CCS_CONFIG_ENFORCING.
> -+	 */
> -+	u8 mode;
> -+	/*
> -+	 * For holding operation index used for this request.
> -+	 * Used by ccs_init_request_info() / ccs_get_mode() /
> -+	 * ccs_write_log(). One of values in "enum ccs_mac_index".
> -+	 */
> -+	u8 type;
> -+};
> -+
> -+/* Structure for holding a token. */
> -+struct ccs_path_info {
> -+	const char *name;
> -+	u32 hash;          /* = full_name_hash(name, strlen(name)) */
> -+	u16 total_len;     /* = strlen(name)                       */
> -+	u16 const_len;     /* = ccs_const_part_length(name)        */
> -+	bool is_dir;       /* = ccs_strendswith(name, "/")         */
> -+	bool is_patterned; /* = const_len < total_len              */
> -+};
> -+
> -+/* Structure for execve() operation. */
> -+struct ccs_execve {
> -+	struct ccs_request_info r;
> -+	struct ccs_obj_info obj;
> -+	struct linux_binprm *bprm;
> -+	struct ccs_domain_info *previous_domain;
> -+	const struct ccs_path_info *transition;
> -+	/* For execute_handler */
> -+	const struct ccs_path_info *handler;
> -+	char *handler_path; /* = kstrdup(handler->name, CCS_GFP_FLAGS) */
> -+	/* For dumping argv[] and envp[]. */
> -+	struct ccs_page_dump dump;
> -+	/* For temporary use. */
> -+	char *tmp; /* Size is CCS_EXEC_TMPSIZE bytes */
> -+};
> -+
> -+/* Structure for domain information. */
> -+struct ccs_domain_info {
> -+	struct list_head list;
> -+	struct list_head acl_info_list;
> -+	/* Name of this domain. Never NULL.          */
> -+	const struct ccs_path_info *domainname;
> -+	/* Namespace for this domain. Never NULL. */
> -+	struct ccs_policy_namespace *ns;
> -+	/* Group numbers to use. */
> -+	unsigned long group[CCS_MAX_ACL_GROUPS / BITS_PER_LONG];
> -+	u8 profile;        /* Profile number to use. */
> -+	bool is_deleted;   /* Delete flag.           */
> -+	bool flags[CCS_MAX_DOMAIN_INFO_FLAGS];
> -+};
> -+
> -+/*
> -+ * Structure for "reset_domain"/"no_reset_domain"/"initialize_domain"/
> -+ * "no_initialize_domain"/"keep_domain"/"no_keep_domain" keyword.
> -+ */
> -+struct ccs_transition_control {
> -+	struct ccs_acl_head head;
> -+	u8 type; /* One of values in "enum ccs_transition_type" */
> -+	bool is_last_name; /* True if the domainname is ccs_last_word(). */
> -+	const struct ccs_path_info *domainname; /* Maybe NULL */
> -+	const struct ccs_path_info *program;    /* Maybe NULL */
> -+};
> -+
> -+/* Structure for "aggregator" keyword. */
> -+struct ccs_aggregator {
> -+	struct ccs_acl_head head;
> -+	const struct ccs_path_info *original_name;
> -+	const struct ccs_path_info *aggregated_name;
> -+};
> -+
> -+/* Structure for "deny_autobind" keyword. */
> -+struct ccs_reserved {
> -+	struct ccs_acl_head head;
> -+	struct ccs_number_union port;
> -+};
> -+
> -+/* Structure for policy manager. */
> -+struct ccs_manager {
> -+	struct ccs_acl_head head;
> -+	/* A path to program or a domainname. */
> -+	const struct ccs_path_info *manager;
> -+};
> -+
> -+/* Structure for argv[]. */
> -+struct ccs_argv {
> -+	unsigned long index;
> -+	const struct ccs_path_info *value;
> -+	bool is_not;
> -+};
> -+
> -+/* Structure for envp[]. */
> -+struct ccs_envp {
> -+	const struct ccs_path_info *name;
> -+	const struct ccs_path_info *value;
> -+	bool is_not;
> -+};
> -+
> -+/*
> -+ * Structure for "task auto_execute_handler" and "task denied_execute_handler"
> -+ * directive.
> -+ *
> -+ * If "task auto_execute_handler" directive exists and the current process is
> -+ * not an execute handler, all execve() requests are replaced by execve()
> -+ * requests of a program specified by "task auto_execute_handler" directive.
> -+ * If the current process is an execute handler, "task auto_execute_handler"
> -+ * and "task denied_execute_handler" directives are ignored.
> -+ * The program specified by "task execute_handler" validates execve()
> -+ * parameters and executes the original execve() requests if appropriate.
> -+ *
> -+ * "task denied_execute_handler" directive is used only when execve() request
> -+ * was rejected in enforcing mode (i.e. CONFIG::file::execute={ mode=enforcing
> -+ * }). The program specified by "task denied_execute_handler" does whatever it
> -+ * wants to do (e.g. silently terminate, change firewall settings, redirect the
> -+ * user to honey pot etc.).
> -+ */
> -+struct ccs_handler_acl {
> -+	struct ccs_acl_info head;       /* type = CCS_TYPE_*_EXECUTE_HANDLER */
> -+	const struct ccs_path_info *handler; /* Pointer to single pathname.  */
> -+};
> -+
> -+/*
> -+ * Structure for "task auto_domain_transition" and
> -+ * "task manual_domain_transition" directive.
> -+ */
> -+struct ccs_task_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_*_TASK_ACL */
> -+	/* Pointer to domainname. */
> -+	const struct ccs_path_info *domainname;
> -+};
> -+
> -+/*
> -+ * Structure for "file execute", "file read", "file write", "file append",
> -+ * "file unlink", "file getattr", "file rmdir", "file truncate",
> -+ * "file symlink", "file chroot" and "file unmount" directive.
> -+ */
> -+struct ccs_path_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_PATH_ACL */
> -+	struct ccs_name_union name;
> -+};
> -+
> -+/*
> -+ * Structure for "file rename", "file link" and "file pivot_root" directive.
> -+ */
> -+struct ccs_path2_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_PATH2_ACL */
> -+	struct ccs_name_union name1;
> -+	struct ccs_name_union name2;
> -+};
> -+
> -+/*
> -+ * Structure for "file create", "file mkdir", "file mkfifo", "file mksock",
> -+ * "file ioctl", "file chmod", "file chown" and "file chgrp" directive.
> -+ */
> -+struct ccs_path_number_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_PATH_NUMBER_ACL */
> -+	struct ccs_name_union name;
> -+	struct ccs_number_union number;
> -+};
> -+
> -+/* Structure for "file mkblock" and "file mkchar" directive. */
> -+struct ccs_mkdev_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_MKDEV_ACL */
> -+	struct ccs_name_union name;
> -+	struct ccs_number_union mode;
> -+	struct ccs_number_union major;
> -+	struct ccs_number_union minor;
> -+};
> -+
> -+/* Structure for "file mount" directive. */
> -+struct ccs_mount_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_MOUNT_ACL */
> -+	struct ccs_name_union dev_name;
> -+	struct ccs_name_union dir_name;
> -+	struct ccs_name_union fs_type;
> -+	struct ccs_number_union flags;
> -+};
> -+
> -+/* Structure for "misc env" directive in domain policy. */
> -+struct ccs_env_acl {
> -+	struct ccs_acl_info head;        /* type = CCS_TYPE_ENV_ACL  */
> -+	const struct ccs_path_info *env; /* environment variable */
> -+};
> -+
> -+/* Structure for "capability" directive. */
> -+struct ccs_capability_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_CAPABILITY_ACL */
> -+	u8 operation; /* One of values in "enum ccs_capability_acl_index". */
> -+};
> -+
> -+/* Structure for "ipc signal" directive. */
> -+struct ccs_signal_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_SIGNAL_ACL */
> -+	struct ccs_number_union sig;
> -+	/* Pointer to destination pattern. */
> -+	const struct ccs_path_info *domainname;
> -+};
> -+
> -+/* Structure for "network inet" directive. */
> -+struct ccs_inet_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_INET_ACL */
> -+	u8 protocol;
> -+	struct ccs_ipaddr_union address;
> -+	struct ccs_number_union port;
> -+};
> -+
> -+/* Structure for "network unix" directive. */
> -+struct ccs_unix_acl {
> -+	struct ccs_acl_info head; /* type = CCS_TYPE_UNIX_ACL */
> -+	u8 protocol;
> -+	struct ccs_name_union name;
> -+};
> -+
> -+/* Structure for holding string data. */
> -+struct ccs_name {
> -+	struct ccs_shared_acl_head head;
> -+	int size; /* Memory size allocated for this entry. */
> -+	struct ccs_path_info entry;
> -+};
> -+
> -+/* Structure for holding a line from /proc/ccs/ interface. */
> -+struct ccs_acl_param {
> -+	char *data; /* Unprocessed data. */
> -+	struct list_head *list; /* List to add or remove. */
> -+	struct ccs_policy_namespace *ns; /* Namespace to use. */
> -+	bool is_delete; /* True if it is a delete request. */
> -+	union ccs_acl_union {
> -+		struct ccs_acl_info acl_info;
> -+		struct ccs_handler_acl handler_acl;
> -+		struct ccs_task_acl task_acl;
> -+		struct ccs_path_acl path_acl;
> -+		struct ccs_path2_acl path2_acl;
> -+		struct ccs_path_number_acl path_number_acl;
> -+		struct ccs_mkdev_acl mkdev_acl;
> -+		struct ccs_mount_acl mount_acl;
> -+		struct ccs_env_acl env_acl;
> -+		struct ccs_capability_acl capability_acl;
> -+		struct ccs_signal_acl signal_acl;
> -+		struct ccs_inet_acl inet_acl;
> -+		struct ccs_unix_acl unix_acl;
> -+		/**/
> -+		struct ccs_acl_head acl_head;
> -+		struct ccs_transition_control transition_control;
> -+		struct ccs_aggregator aggregator;
> -+		struct ccs_reserved reserved;
> -+		struct ccs_manager manager;
> -+		struct ccs_path_group path_group;
> -+		struct ccs_number_group number_group;
> -+		struct ccs_address_group address_group;
> -+	} e;
> -+};
> -+
> -+/* Structure for reading/writing policy via /proc/ccs/ interfaces. */
> -+struct ccs_io_buffer {
> -+	/* Exclusive lock for this structure.   */
> -+	struct mutex io_sem;
> -+	char __user *read_user_buf;
> -+	size_t read_user_buf_avail;
> -+	struct {
> -+		struct list_head *ns;
> -+		struct list_head *domain;
> -+		struct list_head *group;
> -+		struct list_head *acl;
> -+		size_t avail;
> -+		unsigned int step;
> -+		unsigned int query_index;
> -+		u16 index;
> -+		u16 cond_index;
> -+		u8 acl_group_index;
> -+		u8 cond_step;
> -+		u8 bit;
> -+		u8 w_pos;
> -+		bool eof;
> -+		bool print_this_domain_only;
> -+		bool print_transition_related_only;
> -+		bool print_cond_part;
> -+		const char *w[CCS_MAX_IO_READ_QUEUE];
> -+	} r;
> -+	struct {
> -+		struct ccs_policy_namespace *ns;
> -+		struct ccs_domain_info *domain;
> -+		size_t avail;
> -+		bool is_delete;
> -+	} w;
> -+	/* Buffer for reading.                  */
> -+	char *read_buf;
> -+	/* Size of read buffer.                 */
> -+	size_t readbuf_size;
> -+	/* Buffer for writing.                  */
> -+	char *write_buf;
> -+	/* Size of write buffer.                */
> -+	size_t writebuf_size;
> -+	/* Type of interface. */
> -+	enum ccs_proc_interface_index type;
> -+	/* Users counter protected by ccs_io_buffer_list_lock. */
> -+	u8 users;
> -+	/* List for telling GC not to kfree() elements. */
> -+	struct list_head list;
> -+};
> -+
> -+/* Structure for /proc/ccs/profile interface. */
> -+struct ccs_profile {
> -+	const struct ccs_path_info *comment;
> -+	u8 default_config;
> -+	u8 config[CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX];
> -+	unsigned int pref[CCS_MAX_PREF];
> -+};
> -+
> -+/* Structure for representing YYYY/MM/DD hh/mm/ss. */
> -+struct ccs_time {
> -+	u16 year;
> -+	u8 month;
> -+	u8 day;
> -+	u8 hour;
> -+	u8 min;
> -+	u8 sec;
> -+};
> -+
> -+/* Structure for policy namespace. */
> -+struct ccs_policy_namespace {
> -+	/* Profile table. Memory is allocated as needed. */
> -+	struct ccs_profile *profile_ptr[CCS_MAX_PROFILES];
> -+	/* List of "struct ccs_group". */
> -+	struct list_head group_list[CCS_MAX_GROUP];
> -+	/* List of policy. */
> -+	struct list_head policy_list[CCS_MAX_POLICY];
> -+	/* The global ACL referred by "use_group" keyword. */
> -+	struct list_head acl_group[CCS_MAX_ACL_GROUPS];
> -+	/* List for connecting to ccs_namespace_list list. */
> -+	struct list_head namespace_list;
> -+	/* Profile version. Currently only 20150505 is supported. */
> -+	unsigned int profile_version;
> -+	/* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */
> -+	const char *name;
> -+};
> -+
> -+/* Prototype definition for "struct ccsecurity_operations". */
> -+
> -+void __init ccs_permission_init(void);
> -+void __init ccs_mm_init(void);
> -+
> -+/* Prototype definition for internal use. */
> -+
> -+bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
> -+		   struct ccs_page_dump *dump);
> -+bool ccs_memory_ok(const void *ptr, const unsigned int size);
> -+char *ccs_encode(const char *str);
> -+char *ccs_encode2(const char *str, int str_len);
> -+char *ccs_realpath(const struct path *path);
> -+const char *ccs_get_exe(void);
> -+const struct ccs_path_info *ccs_get_name(const char *name);
> -+int ccs_audit_log(struct ccs_request_info *r);
> -+int ccs_check_acl(struct ccs_request_info *r);
> -+int ccs_init_request_info(struct ccs_request_info *r, const u8 index);
> -+struct ccs_domain_info *ccs_assign_domain(const char *domainname,
> -+					  const bool transit);
> -+u8 ccs_get_config(const u8 profile, const u8 index);
> -+void *ccs_commit_ok(void *data, const unsigned int size);
> -+void ccs_del_acl(struct list_head *element);
> -+void ccs_del_condition(struct list_head *element);
> -+void ccs_fill_path_info(struct ccs_path_info *ptr);
> -+void ccs_get_attributes(struct ccs_obj_info *obj);
> -+void ccs_notify_gc(struct ccs_io_buffer *head, const bool is_register);
> -+void ccs_transition_failed(const char *domainname);
> -+void ccs_warn_oom(const char *function);
> -+void ccs_write_log(struct ccs_request_info *r, const char *fmt, ...)
> -+	__printf(2, 3);
> -+
> -+/* Variable definition for internal use. */
> -+
> -+extern bool ccs_policy_loaded;
> -+extern const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS];
> -+extern const u8 ccs_c2mac[CCS_MAX_CAPABILITY_INDEX];
> -+extern const u8 ccs_pn2mac[CCS_MAX_PATH_NUMBER_OPERATION];
> -+extern const u8 ccs_pnnn2mac[CCS_MAX_MKDEV_OPERATION];
> -+extern const u8 ccs_pp2mac[CCS_MAX_PATH2_OPERATION];
> -+extern struct ccs_domain_info ccs_kernel_domain;
> -+extern struct list_head ccs_condition_list;
> -+extern struct list_head ccs_domain_list;
> -+extern struct list_head ccs_name_list[CCS_MAX_HASH];
> -+extern struct list_head ccs_namespace_list;
> -+extern struct mutex ccs_policy_lock;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
> -+extern struct srcu_struct ccs_ss;
> -+#endif
> -+extern unsigned int ccs_memory_quota[CCS_MAX_MEMORY_STAT];
> -+extern unsigned int ccs_memory_used[CCS_MAX_MEMORY_STAT];
> -+
> -+/* Inlined functions for internal use. */
> -+
> -+/**
> -+ * ccs_pathcmp - strcmp() for "struct ccs_path_info" structure.
> -+ *
> -+ * @a: Pointer to "struct ccs_path_info".
> -+ * @b: Pointer to "struct ccs_path_info".
> -+ *
> -+ * Returns true if @a != @b, false otherwise.
> -+ */
> -+static inline bool ccs_pathcmp(const struct ccs_path_info *a,
> -+			       const struct ccs_path_info *b)
> -+{
> -+	return a->hash != b->hash || strcmp(a->name, b->name);
> -+}
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
> -+
> -+/**
> -+ * ccs_read_lock - Take lock for protecting policy.
> -+ *
> -+ * Returns index number for ccs_read_unlock().
> -+ */
> -+static inline int ccs_read_lock(void)
> -+{
> -+	return srcu_read_lock(&ccs_ss);
> -+}
> -+
> -+/**
> -+ * ccs_read_unlock - Release lock for protecting policy.
> -+ *
> -+ * @idx: Index number returned by ccs_read_lock().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_read_unlock(const int idx)
> -+{
> -+	srcu_read_unlock(&ccs_ss, idx);
> -+}
> -+
> -+#else
> -+
> -+int ccs_lock(void);
> -+void ccs_unlock(const int idx);
> -+
> -+/**
> -+ * ccs_read_lock - Take lock for protecting policy.
> -+ *
> -+ * Returns index number for ccs_read_unlock().
> -+ */
> -+static inline int ccs_read_lock(void)
> -+{
> -+	return ccs_lock();
> -+}
> -+
> -+/**
> -+ * ccs_read_unlock - Release lock for protecting policy.
> -+ *
> -+ * @idx: Index number returned by ccs_read_lock().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_read_unlock(const int idx)
> -+{
> -+	ccs_unlock(idx);
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
> -+
> -+/**
> -+ * ccs_tasklist_lock - Take lock for reading list of "struct task_struct".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_tasklist_lock(void)
> -+{
> -+	rcu_read_lock();
> -+}
> -+
> -+/**
> -+ * ccs_tasklist_unlock - Release lock for reading list of "struct task_struct".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_tasklist_unlock(void)
> -+{
> -+	rcu_read_unlock();
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * ccs_tasklist_lock - Take lock for reading list of "struct task_struct".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_tasklist_lock(void)
> -+{
> -+	read_lock(&tasklist_lock);
> -+}
> -+
> -+/**
> -+ * ccs_tasklist_unlock - Release lock for reading list of "struct task_struct".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_tasklist_unlock(void)
> -+{
> -+	read_unlock(&tasklist_lock);
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
> -+
> -+/**
> -+ * ccs_sys_getppid - Copy of getppid().
> -+ *
> -+ * Returns parent process's PID.
> -+ *
> -+ * Alpha does not have getppid() defined. To be able to build this module on
> -+ * Alpha, I have to copy getppid() from kernel/timer.c.
> -+ */
> -+static inline pid_t ccs_sys_getppid(void)
> -+{
> -+	pid_t pid;
> -+	rcu_read_lock();
> -+	pid = task_tgid_vnr(rcu_dereference(current->real_parent));
> -+	rcu_read_unlock();
> -+	return pid;
> -+}
> -+
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+
> -+/**
> -+ * ccs_sys_getppid - Copy of getppid().
> -+ *
> -+ * Returns parent process's PID.
> -+ *
> -+ * This function was rewritten to use RCU in 2.6.16.34. However, distributors
> -+ * which use earlier kernels (e.g. 2.6.8/2.6.9) did not backport the bugfix.
> -+ * Therefore, I'm using code for 2.6.16.34 for earlier kernels.
> -+ */
> -+static inline pid_t ccs_sys_getppid(void)
> -+{
> -+	pid_t pid;
> -+	rcu_read_lock();
> -+#if (defined(RHEL_MAJOR) && RHEL_MAJOR == 5) || (defined(AX_MAJOR) && AX_MAJOR == 3)
> -+	pid = rcu_dereference(current->parent)->tgid;
> -+#elif defined(CONFIG_UTRACE)
> -+	/*
> -+	 * RHEL 5.0 kernel does not have RHEL_MAJOR/RHEL_MINOR defined.
> -+	 * Assume RHEL 5.0 if CONFIG_UTRACE is defined.
> -+	 */
> -+	pid = rcu_dereference(current->parent)->tgid;
> -+#else
> -+	pid = rcu_dereference(current->real_parent)->tgid;
> -+#endif
> -+	rcu_read_unlock();
> -+	return pid;
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * ccs_sys_getppid - Copy of getppid().
> -+ *
> -+ * Returns parent process's PID.
> -+ *
> -+ * I can't use code for 2.6.16.34 for 2.4 kernels because 2.4 kernels does not
> -+ * have RCU. Therefore, I'm using pessimistic lock (i.e. tasklist_lock
> -+ * spinlock).
> -+ */
> -+static inline pid_t ccs_sys_getppid(void)
> -+{
> -+	pid_t pid;
> -+	read_lock(&tasklist_lock);
> -+#ifdef TASK_DEAD
> -+	pid = current->group_leader->real_parent->tgid;
> -+#else
> -+	pid = current->p_opptr->pid;
> -+#endif
> -+	read_unlock(&tasklist_lock);
> -+	return pid;
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
> -+
> -+/**
> -+ * ccs_sys_getpid - Copy of getpid().
> -+ *
> -+ * Returns current thread's PID.
> -+ *
> -+ * Alpha does not have getpid() defined. To be able to build this module on
> -+ * Alpha, I have to copy getpid() from kernel/timer.c.
> -+ */
> -+static inline pid_t ccs_sys_getpid(void)
> -+{
> -+	return task_tgid_vnr(current);
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * ccs_sys_getpid - Copy of getpid().
> -+ *
> -+ * Returns current thread's PID.
> -+ */
> -+static inline pid_t ccs_sys_getpid(void)
> -+{
> -+	return current->tgid;
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_get_mode - Get mode for specified functionality.
> -+ *
> -+ * @profile: Profile number.
> -+ * @index:   Functionality number.
> -+ *
> -+ * Returns mode.
> -+ */
> -+static inline u8 ccs_get_mode(const u8 profile, const u8 index)
> -+{
> -+	return ccs_get_config(profile, index) & (CCS_CONFIG_MAX_MODE - 1);
> -+}
> -+
> -+#if defined(CONFIG_SLOB)
> -+
> -+/**
> -+ * ccs_round2 - Round up to power of 2 for calculating memory usage.
> -+ *
> -+ * @size: Size to be rounded up.
> -+ *
> -+ * Returns @size.
> -+ *
> -+ * Since SLOB does not round up, this function simply returns @size.
> -+ */
> -+static inline int ccs_round2(size_t size)
> -+{
> -+	return size;
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * ccs_round2 - Round up to power of 2 for calculating memory usage.
> -+ *
> -+ * @size: Size to be rounded up.
> -+ *
> -+ * Returns rounded size.
> -+ *
> -+ * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of
> -+ * (e.g.) 128 bytes.
> -+ */
> -+static inline int ccs_round2(size_t size)
> -+{
> -+#if PAGE_SIZE == 4096
> -+	size_t bsize = 32;
> -+#else
> -+	size_t bsize = 64;
> -+#endif
> -+	if (!size)
> -+		return 0;
> -+	while (size > bsize)
> -+		bsize <<= 1;
> -+	return bsize;
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_put_condition - Drop reference on "struct ccs_condition".
> -+ *
> -+ * @cond: Pointer to "struct ccs_condition". Maybe NULL.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_put_condition(struct ccs_condition *cond)
> -+{
> -+	if (cond)
> -+		atomic_dec(&cond->head.users);
> -+}
> -+
> -+/**
> -+ * ccs_put_group - Drop reference on "struct ccs_group".
> -+ *
> -+ * @group: Pointer to "struct ccs_group". Maybe NULL.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_put_group(struct ccs_group *group)
> -+{
> -+	if (group)
> -+		atomic_dec(&group->head.users);
> -+}
> -+
> -+/**
> -+ * ccs_put_name - Drop reference on "struct ccs_name".
> -+ *
> -+ * @name: Pointer to "struct ccs_path_info". Maybe NULL.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_put_name(const struct ccs_path_info *name)
> -+{
> -+	if (name)
> -+		atomic_dec(&container_of(name, struct ccs_name, entry)->
> -+			   head.users);
> -+}
> -+
> -+/* For importing variables and functions. */
> -+extern const struct ccsecurity_exports ccsecurity_exports;
> -+
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+
> -+/*
> -+ * Structure for holding "struct ccs_domain_info *" and "struct ccs_execve *"
> -+ * and "u32 ccs_flags" for each "struct task_struct".
> -+ *
> -+ * "struct ccs_domain_info *" and "u32 ccs_flags" for each "struct task_struct"
> -+ * are maintained outside that "struct task_struct". Therefore, ccs_security
> -+ * != task_struct . This keeps KABI for distributor's prebuilt kernels but
> -+ * entails slow access.
> -+ *
> -+ * Memory for this structure is allocated when current thread tries to access
> -+ * it. Therefore, if memory allocation failed, current thread will be killed by
> -+ * SIGKILL. Note that if current->pid == 1, sending SIGKILL won't work.
> -+ */
> -+struct ccs_security {
> -+	struct list_head list;
> -+	const struct task_struct *task;
> -+	struct ccs_domain_info *ccs_domain_info;
> -+	u32 ccs_flags;
> -+	struct rcu_head rcu;
> -+};
> -+
> -+#define CCS_TASK_SECURITY_HASH_BITS 12
> -+#define CCS_MAX_TASK_SECURITY_HASH (1u << CCS_TASK_SECURITY_HASH_BITS)
> -+extern struct list_head ccs_task_security_list[CCS_MAX_TASK_SECURITY_HASH];
> -+
> -+struct ccs_security *ccs_find_task_security(const struct task_struct *task);
> -+
> -+/**
> -+ * ccs_current_security - Get "struct ccs_security" for current thread.
> -+ *
> -+ * Returns pointer to "struct ccs_security" for current thread.
> -+ */
> -+static inline struct ccs_security *ccs_current_security(void)
> -+{
> -+	return ccs_find_task_security(current);
> -+}
> -+
> -+/**
> -+ * ccs_task_domain - Get "struct ccs_domain_info" for specified thread.
> -+ *
> -+ * @task: Pointer to "struct task_struct".
> -+ *
> -+ * Returns pointer to "struct ccs_security" for specified thread.
> -+ */
> -+static inline struct ccs_domain_info *ccs_task_domain(struct task_struct *task)
> -+{
> -+	struct ccs_domain_info *domain;
> -+	rcu_read_lock();
> -+	domain = ccs_find_task_security(task)->ccs_domain_info;
> -+	rcu_read_unlock();
> -+	return domain;
> -+}
> -+
> -+/**
> -+ * ccs_current_domain - Get "struct ccs_domain_info" for current thread.
> -+ *
> -+ * Returns pointer to "struct ccs_domain_info" for current thread.
> -+ */
> -+static inline struct ccs_domain_info *ccs_current_domain(void)
> -+{
> -+	return ccs_find_task_security(current)->ccs_domain_info;
> -+}
> -+
> -+/**
> -+ * ccs_task_flags - Get flags for specified thread.
> -+ *
> -+ * @task: Pointer to "struct task_struct".
> -+ *
> -+ * Returns flags for specified thread.
> -+ */
> -+static inline u32 ccs_task_flags(struct task_struct *task)
> -+{
> -+	u32 ccs_flags;
> -+	rcu_read_lock();
> -+	ccs_flags = ccs_find_task_security(task)->ccs_flags;
> -+	rcu_read_unlock();
> -+	return ccs_flags;
> -+}
> -+
> -+/**
> -+ * ccs_current_flags - Get flags for current thread.
> -+ *
> -+ * Returns flags for current thread.
> -+ */
> -+static inline u32 ccs_current_flags(void)
> -+{
> -+	return ccs_find_task_security(current)->ccs_flags;
> -+}
> -+
> -+#else
> -+
> -+/*
> -+ * "struct ccs_domain_info *" and "u32 ccs_flags" for each "struct task_struct"
> -+ * are maintained inside that "struct task_struct". Therefore, ccs_security ==
> -+ * task_struct . This allows fast access but breaks KABI checks for
> -+ * distributor's prebuilt kernels due to changes in "struct task_struct".
> -+ */
> -+#define ccs_security task_struct
> -+
> -+/**
> -+ * ccs_find_task_security - Find "struct ccs_security" for given task.
> -+ *
> -+ * @task: Pointer to "struct task_struct".
> -+ *
> -+ * Returns pointer to "struct ccs_security".
> -+ */
> -+static inline struct ccs_security *ccs_find_task_security(struct task_struct *
> -+							  task)
> -+{
> -+	return task;
> -+}
> -+
> -+/**
> -+ * ccs_current_security - Get "struct ccs_security" for current thread.
> -+ *
> -+ * Returns pointer to "struct ccs_security" for current thread.
> -+ */
> -+static inline struct ccs_security *ccs_current_security(void)
> -+{
> -+	return ccs_find_task_security(current);
> -+}
> -+
> -+/**
> -+ * ccs_task_domain - Get "struct ccs_domain_info" for specified thread.
> -+ *
> -+ * @task: Pointer to "struct task_struct".
> -+ *
> -+ * Returns pointer to "struct ccs_security" for specified thread.
> -+ */
> -+static inline struct ccs_domain_info *ccs_task_domain(struct task_struct *task)
> -+{
> -+	struct ccs_domain_info *domain = task->ccs_domain_info;
> -+	return domain ? domain : &ccs_kernel_domain;
> -+}
> -+
> -+/**
> -+ * ccs_current_domain - Get "struct ccs_domain_info" for current thread.
> -+ *
> -+ * Returns pointer to "struct ccs_domain_info" for current thread.
> -+ *
> -+ * If current thread does not belong to a domain (which is true for initial
> -+ * init_task in order to hide ccs_kernel_domain from this module),
> -+ * current thread enters into ccs_kernel_domain.
> -+ */
> -+static inline struct ccs_domain_info *ccs_current_domain(void)
> -+{
> -+	struct task_struct *task = current;
> -+	if (!task->ccs_domain_info)
> -+		task->ccs_domain_info = &ccs_kernel_domain;
> -+	return task->ccs_domain_info;
> -+}
> -+
> -+/**
> -+ * ccs_task_flags - Get flags for specified thread.
> -+ *
> -+ * @task: Pointer to "struct task_struct".
> -+ *
> -+ * Returns flags for specified thread.
> -+ */
> -+static inline u32 ccs_task_flags(struct task_struct *task)
> -+{
> -+	return ccs_find_task_security(task)->ccs_flags;
> -+}
> -+
> -+/**
> -+ * ccs_current_flags - Get flags for current thread.
> -+ *
> -+ * Returns flags for current thread.
> -+ */
> -+static inline u32 ccs_current_flags(void)
> -+{
> -+	return ccs_find_task_security(current)->ccs_flags;
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_current_namespace - Get "struct ccs_policy_namespace" for current thread.
> -+ *
> -+ * Returns pointer to "struct ccs_policy_namespace" for current thread.
> -+ */
> -+static inline struct ccs_policy_namespace *ccs_current_namespace(void)
> -+{
> -+	return ccs_current_domain()->ns;
> -+}
> -+
> -+#endif
> -diff --git a/security/ccsecurity/load_policy.c b/security/ccsecurity/load_policy.c
> -new file mode 100644
> -index 0000000..fc4ae30
> ---- /dev/null
> -+++ b/security/ccsecurity/load_policy.c
> -@@ -0,0 +1,352 @@
> -+/*
> -+ * security/ccsecurity/load_policy.c
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/05/05
> -+ */
> -+
> -+#include <linux/version.h>
> -+#include <linux/module.h>
> -+#include <linux/init.h>
> -+#include <linux/binfmts.h>
> -+#include <linux/sched.h>
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+#include <linux/kmod.h>
> -+/*
> -+ * Regarding 2.4 kernels, we need to define __KERNEL_SYSCALLS__ in order to use
> -+ * waitpid() because call_usermodehelper() does not support UMH_WAIT_PROC.
> -+ */
> -+#define __KERNEL_SYSCALLS__
> -+#include <linux/unistd.h>
> -+#else
> -+#include <linux/fs.h>
> -+#include <linux/namei.h>
> -+#endif
> -+#ifndef LOOKUP_POSITIVE
> -+#define LOOKUP_POSITIVE 0
> -+#endif
> -+
> -+/*
> -+ * TOMOYO specific part start.
> -+ */
> -+
> -+#include <linux/ccsecurity.h>
> -+
> -+/**
> -+ * ccs_setup - Set enable/disable upon boot.
> -+ *
> -+ * @str: "off" to disable, "on" to enable.
> -+ *
> -+ * Returns 0.
> -+ */
> -+static int __init ccs_setup(char *str)
> -+{
> -+	if (!strcmp(str, "off"))
> -+		ccsecurity_ops.disabled = 1;
> -+	else if (!strcmp(str, "on"))
> -+		ccsecurity_ops.disabled = 0;
> -+	return 0;
> -+}
> -+
> -+__setup("ccsecurity=", ccs_setup);
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
> -+#include "lsm2ccsecurity.c"
> -+#endif
> -+
> -+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
> -+
> -+/* Path to the policy loader. (default = CONFIG_CCSECURITY_POLICY_LOADER) */
> -+static const char *ccs_loader;
> -+
> -+/**
> -+ * ccs_loader_setup - Set policy loader.
> -+ *
> -+ * @str: Program to use as a policy loader (e.g. /sbin/ccs-init ).
> -+ *
> -+ * Returns 0.
> -+ */
> -+static int __init ccs_loader_setup(char *str)
> -+{
> -+	ccs_loader = str;
> -+	return 0;
> -+}
> -+
> -+__setup("CCS_loader=", ccs_loader_setup);
> -+
> -+/**
> -+ * ccs_policy_loader_exists - Check whether /sbin/ccs-init exists.
> -+ *
> -+ * Returns true if /sbin/ccs-init exists, false otherwise.
> -+ */
> -+static _Bool ccs_policy_loader_exists(void)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
> -+	struct path path;
> -+	if (!ccs_loader)
> -+		ccs_loader = CONFIG_CCSECURITY_POLICY_LOADER;
> -+	if (kern_path(ccs_loader, LOOKUP_FOLLOW | LOOKUP_POSITIVE,
> -+		      &path) == 0) {
> -+		path_put(&path);
> -+		return 1;
> -+	}
> -+#else
> -+	struct nameidata nd;
> -+	if (!ccs_loader)
> -+		ccs_loader = CONFIG_CCSECURITY_POLICY_LOADER;
> -+	if (path_lookup(ccs_loader, LOOKUP_FOLLOW | LOOKUP_POSITIVE,
> -+			&nd) == 0) {
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+		path_put(&nd.path);
> -+#else
> -+		path_release(&nd);
> -+#endif
> -+		return 1;
> -+	}
> -+#endif
> -+	printk(KERN_INFO "Not activating Mandatory Access Control "
> -+	       "as %s does not exist.\n", ccs_loader);
> -+	return 0;
> -+}
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+
> -+/**
> -+ * ccs_run_loader - Start /sbin/ccs-init.
> -+ *
> -+ * @unused: Not used.
> -+ *
> -+ * Returns PID of /sbin/ccs-init on success, negative value otherwise.
> -+ */
> -+static int ccs_run_loader(void *unused)
> -+{
> -+	char *argv[2];
> -+	char *envp[3];
> -+	printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
> -+	       ccs_loader);
> -+	argv[0] = (char *) ccs_loader;
> -+	argv[1] = NULL;
> -+	envp[0] = "HOME=/";
> -+	envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
> -+	envp[2] = NULL;
> -+	return exec_usermodehelper(argv[0], argv, envp);
> -+}
> -+
> -+#endif
> -+
> -+/* Path to the trigger. (default = CONFIG_CCSECURITY_ACTIVATION_TRIGGER) */
> -+static const char *ccs_trigger;
> -+
> -+/**
> -+ * ccs_trigger_setup - Set trigger for activation.
> -+ *
> -+ * @str: Program to use as an activation trigger (e.g. /sbin/init ).
> -+ *
> -+ * Returns 0.
> -+ */
> -+static int __init ccs_trigger_setup(char *str)
> -+{
> -+	ccs_trigger = str;
> -+	return 0;
> -+}
> -+
> -+__setup("CCS_trigger=", ccs_trigger_setup);
> -+
> -+/**
> -+ * ccs_load_policy - Run external policy loader to load policy.
> -+ *
> -+ * @filename: The program about to start.
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This function checks whether @filename is /sbin/init, and if so
> -+ * invoke /sbin/ccs-init and wait for the termination of /sbin/ccs-init
> -+ * and then continues invocation of /sbin/init.
> -+ * /sbin/ccs-init reads policy files in /etc/ccs/ directory and
> -+ * writes to /proc/ccs/ interfaces.
> -+ */
> -+static void ccs_load_policy(const char *filename)
> -+{
> -+	static _Bool done;
> -+	if (ccsecurity_ops.disabled || done)
> -+		return;
> -+	if (!ccs_trigger)
> -+		ccs_trigger = CONFIG_CCSECURITY_ACTIVATION_TRIGGER;
> -+	if (strcmp(filename, ccs_trigger))
> -+		return;
> -+	if (!ccs_policy_loader_exists())
> -+		return;
> -+	done = 1;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+	{
> -+		char *argv[2];
> -+		char *envp[3];
> -+		printk(KERN_INFO "Calling %s to load policy. Please wait.\n",
> -+		       ccs_loader);
> -+		argv[0] = (char *) ccs_loader;
> -+		argv[1] = NULL;
> -+		envp[0] = "HOME=/";
> -+		envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
> -+		envp[2] = NULL;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) || defined(UMH_WAIT_PROC)
> -+		call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
> -+#else
> -+		call_usermodehelper(argv[0], argv, envp, 1);
> -+#endif
> -+	}
> -+#elif defined(TASK_DEAD)
> -+	{
> -+		/* Copied from kernel/kmod.c */
> -+		struct task_struct *task = current;
> -+		pid_t pid = kernel_thread(ccs_run_loader, NULL, 0);
> -+		sigset_t tmpsig;
> -+		spin_lock_irq(&task->sighand->siglock);
> -+		tmpsig = task->blocked;
> -+		siginitsetinv(&task->blocked,
> -+			      sigmask(SIGKILL) | sigmask(SIGSTOP));
> -+		recalc_sigpending();
> -+		spin_unlock_irq(&task->sighand->siglock);
> -+		if (pid >= 0)
> -+			waitpid(pid, NULL, __WCLONE);
> -+		spin_lock_irq(&task->sighand->siglock);
> -+		task->blocked = tmpsig;
> -+		recalc_sigpending();
> -+		spin_unlock_irq(&task->sighand->siglock);
> -+	}
> -+#else
> -+	{
> -+		/* Copied from kernel/kmod.c */
> -+		struct task_struct *task = current;
> -+		pid_t pid = kernel_thread(ccs_run_loader, NULL, 0);
> -+		sigset_t tmpsig;
> -+		spin_lock_irq(&task->sigmask_lock);
> -+		tmpsig = task->blocked;
> -+		siginitsetinv(&task->blocked,
> -+			      sigmask(SIGKILL) | sigmask(SIGSTOP));
> -+		recalc_sigpending(task);
> -+		spin_unlock_irq(&task->sigmask_lock);
> -+		if (pid >= 0)
> -+			waitpid(pid, NULL, __WCLONE);
> -+		spin_lock_irq(&task->sigmask_lock);
> -+		task->blocked = tmpsig;
> -+		recalc_sigpending(task);
> -+		spin_unlock_irq(&task->sigmask_lock);
> -+	}
> -+#endif
> -+	if (ccsecurity_ops.check_profile)
> -+		ccsecurity_ops.check_profile();
> -+	else
> -+		panic("Failed to load policy.");
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
> -+
> -+/**
> -+ * __ccs_search_binary_handler - Load policy before calling search_binary_handler().
> -+ *
> -+ * @bprm: Pointer to "struct linux_binprm".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_search_binary_handler(struct linux_binprm *bprm)
> -+{
> -+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
> -+	ccs_load_policy(bprm->filename);
> -+#endif
> -+	/*
> -+	 * ccs_load_policy() executes /sbin/ccs-init if bprm->filename is
> -+	 * /sbin/init. /sbin/ccs-init executes /etc/ccs/ccs-load-module to
> -+	 * load loadable kernel module. The loadable kernel module modifies
> -+	 * "struct ccsecurity_ops". Thus, we need to transfer control to
> -+	 * __ccs_search_binary_handler() in security/ccsecurity/permission.c
> -+	 * if "struct ccsecurity_ops" was modified.
> -+	 */
> -+	if (ccsecurity_ops.search_binary_handler
> -+	    != __ccs_search_binary_handler)
> -+		return ccsecurity_ops.search_binary_handler(bprm);
> -+	return search_binary_handler(bprm);
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * __ccs_search_binary_handler - Load policy before calling search_binary_handler().
> -+ *
> -+ * @bprm: Pointer to "struct linux_binprm".
> -+ * @regs: Pointer to "struct pt_regs".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_search_binary_handler(struct linux_binprm *bprm,
> -+				       struct pt_regs *regs)
> -+{
> -+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
> -+	ccs_load_policy(bprm->filename);
> -+#endif
> -+	/*
> -+	 * ccs_load_policy() executes /sbin/ccs-init if bprm->filename is
> -+	 * /sbin/init. /sbin/ccs-init executes /etc/ccs/ccs-load-module to
> -+	 * load loadable kernel module. The loadable kernel module modifies
> -+	 * "struct ccsecurity_ops". Thus, we need to transfer control to
> -+	 * __ccs_search_binary_handler() in security/ccsecurity/permission.c
> -+	 * if "struct ccsecurity_ops" was modified.
> -+	 */
> -+	if (ccsecurity_ops.search_binary_handler
> -+	    != __ccs_search_binary_handler)
> -+		return ccsecurity_ops.search_binary_handler(bprm, regs);
> -+	return search_binary_handler(bprm, regs);
> -+}
> -+
> -+#endif
> -+
> -+/*
> -+ * Some exports for loadable kernel module part.
> -+ *
> -+ * Although scripts/checkpatch.pl complains about use of "extern" in C file,
> -+ * we don't put these into security/ccsecurity/internal.h because we want to
> -+ * split built-in part and loadable kernel module part.
> -+ */
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
> -+extern spinlock_t vfsmount_lock;
> -+#endif
> -+
> -+/* For exporting variables and functions. */
> -+const struct ccsecurity_exports ccsecurity_exports = {
> -+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
> -+	.load_policy = ccs_load_policy,
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY)
> -+	.add_hooks = ccs_add_hooks,
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
> -+	.d_absolute_path = d_absolute_path,
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
> -+	.__d_path = __d_path,
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+	.vfsmount_lock = &vfsmount_lock,
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
> -+	.find_task_by_vpid = find_task_by_vpid,
> -+	.find_task_by_pid_ns = find_task_by_pid_ns,
> -+#endif
> -+};
> -+#ifdef CONFIG_CCSECURITY_LKM
> -+/* Only ccsecurity module need to access this struct. */
> -+EXPORT_SYMBOL_GPL(ccsecurity_exports);
> -+#endif
> -+
> -+/* Members are updated by loadable kernel module. */
> -+struct ccsecurity_operations ccsecurity_ops = {
> -+	.search_binary_handler = __ccs_search_binary_handler,
> -+#ifdef CONFIG_CCSECURITY_DISABLE_BY_DEFAULT
> -+	.disabled = 1,
> -+#endif
> -+};
> -+/*
> -+ * Non-GPL modules might need to access this struct via inlined functions
> -+ * embedded into include/linux/security.h and include/net/ip.h
> -+ */
> -+EXPORT_SYMBOL(ccsecurity_ops);
> -diff --git a/security/ccsecurity/lsm2ccsecurity.c b/security/ccsecurity/lsm2ccsecurity.c
> -new file mode 100644
> -index 0000000..b81d8ed
> ---- /dev/null
> -+++ b/security/ccsecurity/lsm2ccsecurity.c
> -@@ -0,0 +1,192 @@
> -+/*
> -+ * security/ccsecurity/lsm2ccsecurity.c
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/07/11
> -+ */
> -+
> -+#include <linux/path.h>
> -+#include <linux/security.h>
> -+#include <linux/ccsecurity.h>
> -+
> -+int ccs_settime(const struct timespec *ts, const struct timezone *tz)
> -+{
> -+        return ccs_capable(CCS_SYS_SETTIME) ? 0 : -EPERM;
> -+}
> -+
> -+int ccs_sb_mount(const char *dev_name, struct path *path, const char *type,
> -+		 unsigned long flags, void *data)
> -+{
> -+        return ccs_mount_permission(dev_name, path, type, flags, data);
> -+}
> -+
> -+int ccs_sb_umount(struct vfsmount *mnt, int flags)
> -+{
> -+        return ccs_umount_permission(mnt, flags);
> -+}
> -+
> -+int ccs_sb_pivotroot(struct path *old_path, struct path *new_path)
> -+{
> -+        return ccs_pivot_root_permission(old_path, new_path);
> -+}
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
> -+int ccs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
> -+{
> -+        return ccs_getattr_permission(mnt, dentry);
> -+}
> -+#else
> -+int ccs_inode_getattr(const struct path *path)
> -+{
> -+        return ccs_getattr_permission(path->mnt, path->dentry);
> -+}
> -+#endif
> -+
> -+int ccs_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> -+{
> -+        return ccs_ioctl_permission(file, cmd, arg);
> -+}
> -+
> -+int ccs_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
> -+{
> -+        return ccs_fcntl_permission(file, cmd, arg);
> -+}
> -+
> -+int ccs_file_open(struct file *file, const struct cred *cred)
> -+{
> -+        return ccs_open_permission(file);
> -+}
> -+
> -+int ccs_socket_create(int family, int type, int protocol, int kern)
> -+{
> -+        return ccs_socket_create_permission(family, type, protocol);
> -+}
> -+
> -+int ccs_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
> -+{
> -+        return ccs_socket_bind_permission(sock, address, addrlen);
> -+}
> -+
> -+int ccs_socket_connect(struct socket *sock, struct sockaddr *address,
> -+		       int addrlen)
> -+{
> -+        return ccs_socket_connect_permission(sock, address, addrlen);
> -+}
> -+
> -+int ccs_socket_listen(struct socket *sock, int backlog)
> -+{
> -+        return ccs_socket_listen_permission(sock);
> -+}
> -+
> -+int ccs_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
> -+{
> -+        return ccs_socket_sendmsg_permission(sock, msg, size);
> -+}
> -+
> -+int ccs_path_unlink(struct path *dir, struct dentry *dentry)
> -+{
> -+        return ccs_unlink_permission(dentry, dir->mnt);
> -+}
> -+
> -+int ccs_path_mkdir(struct path *dir, struct dentry *dentry, umode_t mode)
> -+{
> -+        return ccs_mkdir_permission(dentry, dir->mnt, mode);
> -+}
> -+
> -+int ccs_path_rmdir(struct path *dir, struct dentry *dentry)
> -+{
> -+        return ccs_rmdir_permission(dentry, dir->mnt);
> -+}
> -+
> -+int ccs_path_mknod(struct path *dir, struct dentry *dentry, umode_t mode,
> -+		   unsigned int dev)
> -+{
> -+        return ccs_mknod_permission(dentry, dir->mnt, mode, dev);
> -+}
> -+
> -+int ccs_path_truncate(struct path *path)
> -+{
> -+        return ccs_truncate_permission(path->dentry, path->mnt);
> -+}
> -+
> -+int ccs_path_symlink(struct path *dir, struct dentry *dentry,
> -+		     const char *old_name)
> -+{
> -+        return ccs_symlink_permission(dentry, dir->mnt, old_name);
> -+}
> -+
> -+int ccs_path_link(struct dentry *old_dentry, struct path *new_dir,
> -+		  struct dentry *new_dentry)
> -+{
> -+        return ccs_link_permission(old_dentry, new_dentry, new_dir->mnt);
> -+}
> -+
> -+int ccs_path_rename(struct path *old_dir, struct dentry *old_dentry,
> -+		    struct path *new_dir, struct dentry *new_dentry)
> -+{
> -+        return ccs_rename_permission(old_dentry, new_dentry, new_dir->mnt);
> -+}
> -+
> -+int ccs_path_chmod(struct path *path, umode_t mode)
> -+{
> -+        return ccs_chmod_permission(path->dentry, path->mnt, mode);
> -+}
> -+
> -+int ccs_path_chown(struct path *path, kuid_t uid, kgid_t gid)
> -+{
> -+        return ccs_chown_permission(path->dentry, path->mnt, uid, gid);
> -+}
> -+
> -+int ccs_path_chroot(struct path *path)
> -+{
> -+        return ccs_chroot_permission(path);
> -+}
> -+
> -+#if !defined(CONFIG_SECURITY_PATH)
> -+EXPORT_SYMBOL(ccs_path_mkdir);
> -+EXPORT_SYMBOL(ccs_path_mknod);
> -+EXPORT_SYMBOL(ccs_path_unlink);
> -+EXPORT_SYMBOL(ccs_path_rename);
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY)
> -+
> -+#include <linux/lsm_hooks.h>
> -+
> -+static struct security_hook_list ccsecurity_hooks[] = {
> -+	LSM_HOOK_INIT(settime, ccs_settime),
> -+	LSM_HOOK_INIT(sb_mount, ccs_sb_mount),
> -+	LSM_HOOK_INIT(sb_umount, ccs_sb_umount),
> -+	LSM_HOOK_INIT(sb_pivotroot, ccs_sb_pivotroot),
> -+	LSM_HOOK_INIT(inode_getattr, ccs_inode_getattr),
> -+	LSM_HOOK_INIT(file_ioctl, ccs_file_ioctl),
> -+	LSM_HOOK_INIT(file_fcntl, ccs_file_fcntl),
> -+	LSM_HOOK_INIT(file_open, ccs_file_open),
> -+#if defined(CONFIG_SECURITY_NETWORK)
> -+	LSM_HOOK_INIT(socket_create, ccs_socket_create),
> -+	LSM_HOOK_INIT(socket_bind, ccs_socket_bind),
> -+	LSM_HOOK_INIT(socket_connect, ccs_socket_connect),
> -+	LSM_HOOK_INIT(socket_listen, ccs_socket_listen),
> -+	LSM_HOOK_INIT(socket_sendmsg, ccs_socket_sendmsg),
> -+#endif
> -+#if defined(CONFIG_SECURITY_PATH)
> -+	LSM_HOOK_INIT(path_unlink, ccs_path_unlink),
> -+	LSM_HOOK_INIT(path_mkdir, ccs_path_mkdir),
> -+	LSM_HOOK_INIT(path_rmdir, ccs_path_rmdir),
> -+	LSM_HOOK_INIT(path_mknod, ccs_path_mknod),
> -+	LSM_HOOK_INIT(path_truncate, ccs_path_truncate),
> -+	LSM_HOOK_INIT(path_symlink, ccs_path_symlink),
> -+	LSM_HOOK_INIT(path_link, ccs_path_link),
> -+	LSM_HOOK_INIT(path_rename, ccs_path_rename),
> -+	LSM_HOOK_INIT(path_chmod, ccs_path_chmod),
> -+	LSM_HOOK_INIT(path_chown, ccs_path_chown),
> -+	LSM_HOOK_INIT(path_chroot, ccs_path_chroot),
> -+#endif
> -+};
> -+
> -+static void ccs_add_hooks(void)
> -+{
> -+	security_add_hooks(ccsecurity_hooks, ARRAY_SIZE(ccsecurity_hooks));
> -+}
> -+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY) */
> -diff --git a/security/ccsecurity/memory.c b/security/ccsecurity/memory.c
> -new file mode 100644
> -index 0000000..6514a26
> ---- /dev/null
> -+++ b/security/ccsecurity/memory.c
> -@@ -0,0 +1,356 @@
> -+/*
> -+ * security/ccsecurity/memory.c
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/05/05
> -+ */
> -+
> -+#include "internal.h"
> -+
> -+/***** SECTION1: Constants definition *****/
> -+
> -+/***** SECTION2: Structure definition *****/
> -+
> -+/***** SECTION3: Prototype definition section *****/
> -+
> -+bool ccs_memory_ok(const void *ptr, const unsigned int size);
> -+const struct ccs_path_info *ccs_get_name(const char *name);
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+struct ccs_security *ccs_find_task_security(const struct task_struct *task);
> -+#endif
> -+void *ccs_commit_ok(void *data, const unsigned int size);
> -+void __init ccs_mm_init(void);
> -+void ccs_warn_oom(const char *function);
> -+
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+static int __ccs_alloc_task_security(const struct task_struct *task);
> -+static void __ccs_free_task_security(const struct task_struct *task);
> -+static void ccs_add_task_security(struct ccs_security *ptr,
> -+				  struct list_head *list);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
> -+static void ccs_rcu_free(struct rcu_head *rcu);
> -+#else
> -+static void ccs_rcu_free(void *arg);
> -+#endif
> -+#endif
> -+
> -+/***** SECTION4: Standalone functions section *****/
> -+
> -+/***** SECTION5: Variables definition section *****/
> -+
> -+/* Memoy currently used by policy/audit log/query. */
> -+unsigned int ccs_memory_used[CCS_MAX_MEMORY_STAT];
> -+
> -+/* Memory quota for "policy"/"audit log"/"query". */
> -+unsigned int ccs_memory_quota[CCS_MAX_MEMORY_STAT];
> -+
> -+/* The list for "struct ccs_name". */
> -+struct list_head ccs_name_list[CCS_MAX_HASH];
> -+
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+
> -+/* Dummy security context for avoiding NULL pointer dereference. */
> -+static struct ccs_security ccs_oom_security = {
> -+	.ccs_domain_info = &ccs_kernel_domain
> -+};
> -+
> -+/* Dummy security context for avoiding NULL pointer dereference. */
> -+static struct ccs_security ccs_default_security = {
> -+	.ccs_domain_info = &ccs_kernel_domain
> -+};
> -+
> -+/* List of "struct ccs_security". */
> -+struct list_head ccs_task_security_list[CCS_MAX_TASK_SECURITY_HASH];
> -+/* Lock for protecting ccs_task_security_list[]. */
> -+static DEFINE_SPINLOCK(ccs_task_security_list_lock);
> -+
> -+#endif
> -+
> -+/***** SECTION6: Dependent functions section *****/
> -+
> -+/**
> -+ * ccs_warn_oom - Print out of memory warning message.
> -+ *
> -+ * @function: Function's name.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+void ccs_warn_oom(const char *function)
> -+{
> -+	/* Reduce error messages. */
> -+	static pid_t ccs_last_pid;
> -+	const pid_t pid = current->pid;
> -+	if (ccs_last_pid != pid) {
> -+		printk(KERN_WARNING "ERROR: Out of memory at %s.\n",
> -+		       function);
> -+		ccs_last_pid = pid;
> -+	}
> -+	if (!ccs_policy_loaded)
> -+		panic("MAC Initialization failed.\n");
> -+}
> -+
> -+/**
> -+ * ccs_memory_ok - Check memory quota.
> -+ *
> -+ * @ptr:  Pointer to allocated memory. Maybe NULL.
> -+ * @size: Size in byte. Not used if @ptr is NULL.
> -+ *
> -+ * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
> -+ *
> -+ * Caller holds ccs_policy_lock mutex.
> -+ */
> -+bool ccs_memory_ok(const void *ptr, const unsigned int size)
> -+{
> -+	if (ptr) {
> -+		const size_t s = ccs_round2(size);
> -+		ccs_memory_used[CCS_MEMORY_POLICY] += s;
> -+		if (!ccs_memory_quota[CCS_MEMORY_POLICY] ||
> -+		    ccs_memory_used[CCS_MEMORY_POLICY] <=
> -+		    ccs_memory_quota[CCS_MEMORY_POLICY])
> -+			return true;
> -+		ccs_memory_used[CCS_MEMORY_POLICY] -= s;
> -+	}
> -+	ccs_warn_oom(__func__);
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_commit_ok - Allocate memory and check memory quota.
> -+ *
> -+ * @data: Data to copy from.
> -+ * @size: Size in byte.
> -+ *
> -+ * Returns pointer to allocated memory on success, NULL otherwise.
> -+ * @data is zero-cleared on success.
> -+ *
> -+ * Caller holds ccs_policy_lock mutex.
> -+ */
> -+void *ccs_commit_ok(void *data, const unsigned int size)
> -+{
> -+	void *ptr = kmalloc(size, CCS_GFP_FLAGS);
> -+	if (ccs_memory_ok(ptr, size)) {
> -+		memmove(ptr, data, size);
> -+		memset(data, 0, size);
> -+		return ptr;
> -+	}
> -+	kfree(ptr);
> -+	return NULL;
> -+}
> -+
> -+/**
> -+ * ccs_get_name - Allocate memory for string data.
> -+ *
> -+ * @name: The string to store into the permernent memory.
> -+ *
> -+ * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
> -+ */
> -+const struct ccs_path_info *ccs_get_name(const char *name)
> -+{
> -+	struct ccs_name *ptr;
> -+	unsigned int hash;
> -+	int len;
> -+	int allocated_len;
> -+	struct list_head *head;
> -+
> -+	if (!name)
> -+		return NULL;
> -+	len = strlen(name) + 1;
> -+	hash = full_name_hash((const unsigned char *) name, len - 1);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) || defined(RHEL_MAJOR)
> -+	head = &ccs_name_list[hash_long(hash, CCS_HASH_BITS)];
> -+#else
> -+	head = &ccs_name_list[hash % CCS_MAX_HASH];
> -+#endif
> -+	if (mutex_lock_interruptible(&ccs_policy_lock))
> -+		return NULL;
> -+	list_for_each_entry(ptr, head, head.list) {
> -+		if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name) ||
> -+		    atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS)
> -+			continue;
> -+		atomic_inc(&ptr->head.users);
> -+		goto out;
> -+	}
> -+	allocated_len = sizeof(*ptr) + len;
> -+	ptr = kzalloc(allocated_len, CCS_GFP_FLAGS);
> -+	if (ccs_memory_ok(ptr, allocated_len)) {
> -+		ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
> -+		memmove((char *) ptr->entry.name, name, len);
> -+		atomic_set(&ptr->head.users, 1);
> -+		ccs_fill_path_info(&ptr->entry);
> -+		ptr->size = allocated_len;
> -+		list_add_tail(&ptr->head.list, head);
> -+	} else {
> -+		kfree(ptr);
> -+		ptr = NULL;
> -+	}
> -+out:
> -+	mutex_unlock(&ccs_policy_lock);
> -+	return ptr ? &ptr->entry : NULL;
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+
> -+/**
> -+ * ccs_add_task_security - Add "struct ccs_security" to list.
> -+ *
> -+ * @ptr:  Pointer to "struct ccs_security".
> -+ * @list: Pointer to "struct list_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_add_task_security(struct ccs_security *ptr,
> -+				  struct list_head *list)
> -+{
> -+	unsigned long flags;
> -+	spin_lock_irqsave(&ccs_task_security_list_lock, flags);
> -+	list_add_rcu(&ptr->list, list);
> -+	spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
> -+}
> -+
> -+/**
> -+ * __ccs_alloc_task_security - Allocate memory for new tasks.
> -+ *
> -+ * @task: Pointer to "struct task_struct".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_alloc_task_security(const struct task_struct *task)
> -+{
> -+	struct ccs_security *old_security = ccs_current_security();
> -+	struct ccs_security *new_security = kzalloc(sizeof(*new_security),
> -+						    GFP_KERNEL);
> -+	struct list_head *list = &ccs_task_security_list
> -+		[hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
> -+	if (!new_security)
> -+		return -ENOMEM;
> -+	new_security->task = task;
> -+	new_security->ccs_domain_info = old_security->ccs_domain_info;
> -+	new_security->ccs_flags = old_security->ccs_flags;
> -+	ccs_add_task_security(new_security, list);
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_find_task_security - Find "struct ccs_security" for given task.
> -+ *
> -+ * @task: Pointer to "struct task_struct".
> -+ *
> -+ * Returns pointer to "struct ccs_security" on success, &ccs_oom_security on
> -+ * out of memory, &ccs_default_security otherwise.
> -+ *
> -+ * If @task is current thread and "struct ccs_security" for current thread was
> -+ * not found, I try to allocate it. But if allocation failed, current thread
> -+ * will be killed by SIGKILL. Note that if current->pid == 1, sending SIGKILL
> -+ * won't work.
> -+ */
> -+struct ccs_security *ccs_find_task_security(const struct task_struct *task)
> -+{
> -+	struct ccs_security *ptr;
> -+	struct list_head *list = &ccs_task_security_list
> -+		[hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
> -+	/* Make sure INIT_LIST_HEAD() in ccs_mm_init() takes effect. */
> -+	while (!list->next);
> -+	rcu_read_lock();
> -+	list_for_each_entry_rcu(ptr, list, list) {
> -+		if (ptr->task != task)
> -+			continue;
> -+		rcu_read_unlock();
> -+		return ptr;
> -+	}
> -+	rcu_read_unlock();
> -+	if (task != current)
> -+		return &ccs_default_security;
> -+	/* Use GFP_ATOMIC because caller may have called rcu_read_lock(). */
> -+	ptr = kzalloc(sizeof(*ptr), GFP_ATOMIC);
> -+	if (!ptr) {
> -+		printk(KERN_WARNING "Unable to allocate memory for pid=%u\n",
> -+		       task->pid);
> -+		send_sig(SIGKILL, current, 0);
> -+		return &ccs_oom_security;
> -+	}
> -+	*ptr = ccs_default_security;
> -+	ptr->task = task;
> -+	ccs_add_task_security(ptr, list);
> -+	return ptr;
> -+}
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
> -+
> -+/**
> -+ * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
> -+ *
> -+ * @rcu: Pointer to "struct rcu_head".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_rcu_free(struct rcu_head *rcu)
> -+{
> -+	struct ccs_security *ptr = container_of(rcu, typeof(*ptr), rcu);
> -+	kfree(ptr);
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
> -+ *
> -+ * @arg: Pointer to "void".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_rcu_free(void *arg)
> -+{
> -+	struct ccs_security *ptr = arg;
> -+	kfree(ptr);
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * __ccs_free_task_security - Release memory associated with "struct task_struct".
> -+ *
> -+ * @task: Pointer to "struct task_struct".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void __ccs_free_task_security(const struct task_struct *task)
> -+{
> -+	unsigned long flags;
> -+	struct ccs_security *ptr = ccs_find_task_security(task);
> -+	if (ptr == &ccs_default_security || ptr == &ccs_oom_security)
> -+		return;
> -+	spin_lock_irqsave(&ccs_task_security_list_lock, flags);
> -+	list_del_rcu(&ptr->list);
> -+	spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
> -+	call_rcu(&ptr->rcu, ccs_rcu_free);
> -+#else
> -+	call_rcu(&ptr->rcu, ccs_rcu_free, ptr);
> -+#endif
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_mm_init - Initialize mm related code.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+void __init ccs_mm_init(void)
> -+{
> -+	int idx;
> -+	for (idx = 0; idx < CCS_MAX_HASH; idx++)
> -+		INIT_LIST_HEAD(&ccs_name_list[idx]);
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+	for (idx = 0; idx < CCS_MAX_TASK_SECURITY_HASH; idx++)
> -+		INIT_LIST_HEAD(&ccs_task_security_list[idx]);
> -+#endif
> -+	smp_wmb(); /* Avoid out of order execution. */
> -+#ifdef CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY
> -+	ccsecurity_ops.alloc_task_security = __ccs_alloc_task_security;
> -+	ccsecurity_ops.free_task_security = __ccs_free_task_security;
> -+#endif
> -+	ccs_kernel_domain.domainname = ccs_get_name("<kernel>");
> -+	list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
> -+}
> -diff --git a/security/ccsecurity/permission.c b/security/ccsecurity/permission.c
> -new file mode 100644
> -index 0000000..d73c237
> ---- /dev/null
> -+++ b/security/ccsecurity/permission.c
> -@@ -0,0 +1,5025 @@
> -+/*
> -+ * security/ccsecurity/permission.c
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/05/05
> -+ */
> -+
> -+#include "internal.h"
> -+
> -+/***** SECTION1: Constants definition *****/
> -+
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
> -+
> -+/*
> -+ * may_open() receives open flags modified by open_to_namei_flags() until
> -+ * 2.6.32. We stop here in case some distributions backported ACC_MODE changes,
> -+ * for we can't determine whether may_open() receives open flags modified by
> -+ * open_to_namei_flags() or not.
> -+ */
> -+#ifdef ACC_MODE
> -+#error ACC_MODE already defined.
> -+#endif
> -+#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
> -+
> -+#if defined(RHEL_MAJOR) && RHEL_MAJOR == 6
> -+/* RHEL6 passes unmodified flags since 2.6.32-71.14.1.el6 . */
> -+#undef ACC_MODE
> -+#define ACC_MODE(x) ("\004\002\006"[(x)&O_ACCMODE])
> -+#endif
> -+
> -+#endif
> -+
> -+/* String table for special mount operations. */
> -+static const char * const ccs_mounts[CCS_MAX_SPECIAL_MOUNT] = {
> -+	[CCS_MOUNT_BIND]            = "--bind",
> -+	[CCS_MOUNT_MOVE]            = "--move",
> -+	[CCS_MOUNT_REMOUNT]         = "--remount",
> -+	[CCS_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable",
> -+	[CCS_MOUNT_MAKE_PRIVATE]    = "--make-private",
> -+	[CCS_MOUNT_MAKE_SLAVE]      = "--make-slave",
> -+	[CCS_MOUNT_MAKE_SHARED]     = "--make-shared",
> -+};
> -+
> -+/* Mapping table from "enum ccs_path_acl_index" to "enum ccs_mac_index". */
> -+static const u8 ccs_p2mac[CCS_MAX_PATH_OPERATION] = {
> -+	[CCS_TYPE_EXECUTE]    = CCS_MAC_FILE_EXECUTE,
> -+	[CCS_TYPE_READ]       = CCS_MAC_FILE_OPEN,
> -+	[CCS_TYPE_WRITE]      = CCS_MAC_FILE_OPEN,
> -+	[CCS_TYPE_APPEND]     = CCS_MAC_FILE_OPEN,
> -+	[CCS_TYPE_UNLINK]     = CCS_MAC_FILE_UNLINK,
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+	[CCS_TYPE_GETATTR]    = CCS_MAC_FILE_GETATTR,
> -+#endif
> -+	[CCS_TYPE_RMDIR]      = CCS_MAC_FILE_RMDIR,
> -+	[CCS_TYPE_TRUNCATE]   = CCS_MAC_FILE_TRUNCATE,
> -+	[CCS_TYPE_SYMLINK]    = CCS_MAC_FILE_SYMLINK,
> -+	[CCS_TYPE_CHROOT]     = CCS_MAC_FILE_CHROOT,
> -+	[CCS_TYPE_UMOUNT]     = CCS_MAC_FILE_UMOUNT,
> -+};
> -+
> -+/* Mapping table from "enum ccs_mkdev_acl_index" to "enum ccs_mac_index". */
> -+const u8 ccs_pnnn2mac[CCS_MAX_MKDEV_OPERATION] = {
> -+	[CCS_TYPE_MKBLOCK] = CCS_MAC_FILE_MKBLOCK,
> -+	[CCS_TYPE_MKCHAR]  = CCS_MAC_FILE_MKCHAR,
> -+};
> -+
> -+/* Mapping table from "enum ccs_path2_acl_index" to "enum ccs_mac_index". */
> -+const u8 ccs_pp2mac[CCS_MAX_PATH2_OPERATION] = {
> -+	[CCS_TYPE_LINK]       = CCS_MAC_FILE_LINK,
> -+	[CCS_TYPE_RENAME]     = CCS_MAC_FILE_RENAME,
> -+	[CCS_TYPE_PIVOT_ROOT] = CCS_MAC_FILE_PIVOT_ROOT,
> -+};
> -+
> -+/*
> -+ * Mapping table from "enum ccs_path_number_acl_index" to "enum ccs_mac_index".
> -+ */
> -+const u8 ccs_pn2mac[CCS_MAX_PATH_NUMBER_OPERATION] = {
> -+	[CCS_TYPE_CREATE] = CCS_MAC_FILE_CREATE,
> -+	[CCS_TYPE_MKDIR]  = CCS_MAC_FILE_MKDIR,
> -+	[CCS_TYPE_MKFIFO] = CCS_MAC_FILE_MKFIFO,
> -+	[CCS_TYPE_MKSOCK] = CCS_MAC_FILE_MKSOCK,
> -+	[CCS_TYPE_IOCTL]  = CCS_MAC_FILE_IOCTL,
> -+	[CCS_TYPE_CHMOD]  = CCS_MAC_FILE_CHMOD,
> -+	[CCS_TYPE_CHOWN]  = CCS_MAC_FILE_CHOWN,
> -+	[CCS_TYPE_CHGRP]  = CCS_MAC_FILE_CHGRP,
> -+};
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+
> -+/*
> -+ * Mapping table from "enum ccs_network_acl_index" to "enum ccs_mac_index" for
> -+ * inet domain socket.
> -+ */
> -+static const u8 ccs_inet2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
> -+	[SOCK_STREAM] = {
> -+		[CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_INET_STREAM_BIND,
> -+		[CCS_NETWORK_LISTEN]  = CCS_MAC_NETWORK_INET_STREAM_LISTEN,
> -+		[CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_INET_STREAM_CONNECT,
> -+		[CCS_NETWORK_ACCEPT]  = CCS_MAC_NETWORK_INET_STREAM_ACCEPT,
> -+	},
> -+	[SOCK_DGRAM] = {
> -+		[CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_INET_DGRAM_BIND,
> -+		[CCS_NETWORK_SEND]    = CCS_MAC_NETWORK_INET_DGRAM_SEND,
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+		[CCS_NETWORK_RECV]    = CCS_MAC_NETWORK_INET_DGRAM_RECV,
> -+#endif
> -+	},
> -+	[SOCK_RAW]    = {
> -+		[CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_INET_RAW_BIND,
> -+		[CCS_NETWORK_SEND]    = CCS_MAC_NETWORK_INET_RAW_SEND,
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+		[CCS_NETWORK_RECV]    = CCS_MAC_NETWORK_INET_RAW_RECV,
> -+#endif
> -+	},
> -+};
> -+
> -+/*
> -+ * Mapping table from "enum ccs_network_acl_index" to "enum ccs_mac_index" for
> -+ * unix domain socket.
> -+ */
> -+static const u8 ccs_unix2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
> -+	[SOCK_STREAM] = {
> -+		[CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_UNIX_STREAM_BIND,
> -+		[CCS_NETWORK_LISTEN]  = CCS_MAC_NETWORK_UNIX_STREAM_LISTEN,
> -+		[CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_STREAM_CONNECT,
> -+		[CCS_NETWORK_ACCEPT]  = CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT,
> -+	},
> -+	[SOCK_DGRAM] = {
> -+		[CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_UNIX_DGRAM_BIND,
> -+		[CCS_NETWORK_SEND]    = CCS_MAC_NETWORK_UNIX_DGRAM_SEND,
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+		[CCS_NETWORK_RECV]    = CCS_MAC_NETWORK_UNIX_DGRAM_RECV,
> -+#endif
> -+	},
> -+	[SOCK_SEQPACKET] = {
> -+		[CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND,
> -+		[CCS_NETWORK_LISTEN]  = CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
> -+		[CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
> -+		[CCS_NETWORK_ACCEPT]  = CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT,
> -+	},
> -+};
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+
> -+/*
> -+ * Mapping table from "enum ccs_capability_acl_index" to "enum ccs_mac_index".
> -+ */
> -+const u8 ccs_c2mac[CCS_MAX_CAPABILITY_INDEX] = {
> -+	[CCS_USE_ROUTE_SOCKET]  = CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET,
> -+	[CCS_USE_PACKET_SOCKET] = CCS_MAC_CAPABILITY_USE_PACKET_SOCKET,
> -+	[CCS_SYS_REBOOT]        = CCS_MAC_CAPABILITY_SYS_REBOOT,
> -+	[CCS_SYS_VHANGUP]       = CCS_MAC_CAPABILITY_SYS_VHANGUP,
> -+	[CCS_SYS_SETTIME]       = CCS_MAC_CAPABILITY_SYS_SETTIME,
> -+	[CCS_SYS_NICE]          = CCS_MAC_CAPABILITY_SYS_NICE,
> -+	[CCS_SYS_SETHOSTNAME]   = CCS_MAC_CAPABILITY_SYS_SETHOSTNAME,
> -+	[CCS_USE_KERNEL_MODULE] = CCS_MAC_CAPABILITY_USE_KERNEL_MODULE,
> -+	[CCS_SYS_KEXEC_LOAD]    = CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD,
> -+	[CCS_SYS_PTRACE]        = CCS_MAC_CAPABILITY_SYS_PTRACE,
> -+};
> -+
> -+#endif
> -+
> -+/***** SECTION2: Structure definition *****/
> -+
> -+/* Structure for holding inet domain socket's address. */
> -+struct ccs_inet_addr_info {
> -+	u16 port;           /* In network byte order. */
> -+	const u32 *address; /* In network byte order. */
> -+	bool is_ipv6;
> -+};
> -+
> -+/* Structure for holding unix domain socket's address. */
> -+struct ccs_unix_addr_info {
> -+	u8 *addr; /* This may not be '\0' terminated string. */
> -+	unsigned int addr_len;
> -+};
> -+
> -+/* Structure for holding socket address. */
> -+struct ccs_addr_info {
> -+	u8 protocol;
> -+	u8 operation;
> -+	struct ccs_inet_addr_info inet;
> -+	struct ccs_unix_addr_info unix0;
> -+};
> -+
> -+/***** SECTION3: Prototype definition section *****/
> -+
> -+bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
> -+		   struct ccs_page_dump *dump);
> -+void ccs_get_attributes(struct ccs_obj_info *obj);
> -+
> -+static bool ccs_alphabet_char(const char c);
> -+static bool ccs_argv(const unsigned int index, const char *arg_ptr,
> -+		     const int argc, const struct ccs_argv *argv, u8 *checked);
> -+static bool ccs_byte_range(const char *str);
> -+static bool ccs_check_entry(struct ccs_request_info *r,
> -+			    struct ccs_acl_info *ptr);
> -+static bool ccs_check_mkdev_acl(struct ccs_request_info *r,
> -+				const struct ccs_acl_info *ptr);
> -+static bool ccs_check_mount_acl(struct ccs_request_info *r,
> -+				const struct ccs_acl_info *ptr);
> -+static bool ccs_check_path2_acl(struct ccs_request_info *r,
> -+				const struct ccs_acl_info *ptr);
> -+static bool ccs_check_path_acl(struct ccs_request_info *r,
> -+			       const struct ccs_acl_info *ptr);
> -+static bool ccs_check_path_number_acl(struct ccs_request_info *r,
> -+				      const struct ccs_acl_info *ptr);
> -+static bool ccs_compare_number_union(const unsigned long value,
> -+				     const struct ccs_number_union *ptr);
> -+static bool ccs_condition(struct ccs_request_info *r,
> -+			  const struct ccs_condition *cond);
> -+static bool ccs_decimal(const char c);
> -+static bool ccs_envp(const char *env_name, const char *env_value,
> -+		     const int envc, const struct ccs_envp *envp, u8 *checked);
> -+static bool ccs_file_matches_pattern(const char *filename,
> -+				     const char *filename_end,
> -+				     const char *pattern,
> -+				     const char *pattern_end);
> -+static bool ccs_file_matches_pattern2(const char *filename,
> -+				      const char *filename_end,
> -+				      const char *pattern,
> -+				      const char *pattern_end);
> -+static bool ccs_get_realpath(struct ccs_path_info *buf, struct path *path);
> -+static bool ccs_hexadecimal(const char c);
> -+static bool ccs_number_matches_group(const unsigned long min,
> -+				     const unsigned long max,
> -+				     const struct ccs_group *group);
> -+static bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
> -+				     const struct ccs_path_info *pattern);
> -+static bool ccs_path_matches_pattern2(const char *f, const char *p);
> -+static bool ccs_scan_bprm(struct ccs_execve *ee, const u16 argc,
> -+			  const struct ccs_argv *argv, const u16 envc,
> -+			  const struct ccs_envp *envp);
> -+static bool ccs_scan_exec_realpath(struct file *file,
> -+				   const struct ccs_name_union *ptr,
> -+				   const bool match);
> -+static bool ccs_scan_transition(const struct list_head *list,
> -+				const struct ccs_path_info *domainname,
> -+				const struct ccs_path_info *program,
> -+				const char *last_name,
> -+				const enum ccs_transition_type type);
> -+static const char *ccs_last_word(const char *name);
> -+static const struct ccs_path_info *ccs_compare_name_union
> -+(const struct ccs_path_info *name, const struct ccs_name_union *ptr);
> -+static const struct ccs_path_info *ccs_path_matches_group
> -+(const struct ccs_path_info *pathname, const struct ccs_group *group);
> -+static enum ccs_transition_type ccs_transition_type
> -+(const struct ccs_policy_namespace *ns, const struct ccs_path_info *domainname,
> -+ const struct ccs_path_info *program);
> -+static int __ccs_chmod_permission(struct dentry *dentry,
> -+				  struct vfsmount *vfsmnt, mode_t mode);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
> -+static int __ccs_chown_permission(struct dentry *dentry,
> -+				  struct vfsmount *vfsmnt, kuid_t user,
> -+				  kgid_t group);
> -+#else
> -+static int __ccs_chown_permission(struct dentry *dentry,
> -+				  struct vfsmount *vfsmnt, uid_t user,
> -+				  gid_t group);
> -+#endif
> -+static int __ccs_chroot_permission(struct path *path);
> -+static int __ccs_fcntl_permission(struct file *file, unsigned int cmd,
> -+				  unsigned long arg);
> -+static int __ccs_ioctl_permission(struct file *filp, unsigned int cmd,
> -+				  unsigned long arg);
> -+static int __ccs_link_permission(struct dentry *old_dentry,
> -+				 struct dentry *new_dentry,
> -+				 struct vfsmount *mnt);
> -+static int __ccs_mkdir_permission(struct dentry *dentry, struct vfsmount *mnt,
> -+				  unsigned int mode);
> -+static int __ccs_mknod_permission(struct dentry *dentry, struct vfsmount *mnt,
> -+				  const unsigned int mode, unsigned int dev);
> -+static int __ccs_mount_permission(const char *dev_name, struct path *path,
> -+				  const char *type, unsigned long flags,
> -+				  void *data_page);
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
> -+static int __ccs_open_exec_permission(struct dentry *dentry,
> -+				      struct vfsmount *mnt);
> -+#endif
> -+static int __ccs_open_permission(struct dentry *dentry, struct vfsmount *mnt,
> -+				 const int flag);
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
> -+static int __ccs_parse_table(int __user *name, int nlen, void __user *oldval,
> -+			     void __user *newval, struct ctl_table *table);
> -+#endif
> -+static int __ccs_pivot_root_permission(struct path *old_path,
> -+				       struct path *new_path);
> -+static int __ccs_rename_permission(struct dentry *old_dentry,
> -+				   struct dentry *new_dentry,
> -+				   struct vfsmount *mnt);
> -+static int __ccs_rmdir_permission(struct dentry *dentry, struct vfsmount *mnt);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
> -+static int __ccs_search_binary_handler(struct linux_binprm *bprm);
> -+#else
> -+static int __ccs_search_binary_handler(struct linux_binprm *bprm,
> -+				       struct pt_regs *regs);
> -+#endif
> -+static int __ccs_symlink_permission(struct dentry *dentry,
> -+				    struct vfsmount *mnt, const char *from);
> -+static int __ccs_truncate_permission(struct dentry *dentry,
> -+				     struct vfsmount *mnt);
> -+static int __ccs_umount_permission(struct vfsmount *mnt, int flags);
> -+static int __ccs_unlink_permission(struct dentry *dentry,
> -+				   struct vfsmount *mnt);
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
> -+static int __ccs_uselib_permission(struct dentry *dentry,
> -+				   struct vfsmount *mnt);
> -+#endif
> -+static int ccs_execute_permission(struct ccs_request_info *r,
> -+				  const struct ccs_path_info *filename);
> -+static int ccs_find_next_domain(struct ccs_execve *ee);
> -+static int ccs_get_path(const char *pathname, struct path *path);
> -+static int ccs_kern_path(const char *pathname, int flags, struct path *path);
> -+static int ccs_mkdev_perm(const u8 operation, struct dentry *dentry,
> -+			  struct vfsmount *mnt, const unsigned int mode,
> -+			  unsigned int dev);
> -+static int ccs_mount_acl(struct ccs_request_info *r, const char *dev_name,
> -+			 struct path *dir, const char *type,
> -+			 unsigned long flags);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
> -+static int ccs_new_open_permission(struct file *filp);
> -+#endif
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
> -+static int ccs_old_chroot_permission(struct nameidata *nd);
> -+static int ccs_old_mount_permission(const char *dev_name, struct nameidata *nd,
> -+				    const char *type, unsigned long flags,
> -+				    void *data_page);
> -+static int ccs_old_pivot_root_permission(struct nameidata *old_nd,
> -+					 struct nameidata *new_nd);
> -+#endif
> -+static int ccs_path2_perm(const u8 operation, struct dentry *dentry1,
> -+			  struct vfsmount *mnt1, struct dentry *dentry2,
> -+			  struct vfsmount *mnt2);
> -+static int ccs_path_number_perm(const u8 type, struct dentry *dentry,
> -+				struct vfsmount *vfsmnt, unsigned long number);
> -+static int ccs_path_perm(const u8 operation, struct dentry *dentry,
> -+			 struct vfsmount *mnt, const char *target);
> -+static int ccs_path_permission(struct ccs_request_info *r, u8 operation,
> -+			       const struct ccs_path_info *filename);
> -+static int ccs_start_execve(struct linux_binprm *bprm,
> -+			    struct ccs_execve **eep);
> -+static int ccs_symlink_path(const char *pathname, struct ccs_path_info *name);
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
> -+static void __ccs_clear_open_mode(void);
> -+static void __ccs_save_open_mode(int mode);
> -+#endif
> -+static void ccs_add_slash(struct ccs_path_info *buf);
> -+static void ccs_finish_execve(int retval, struct ccs_execve *ee);
> -+
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+static bool ccs_check_env_acl(struct ccs_request_info *r,
> -+			      const struct ccs_acl_info *ptr);
> -+static int ccs_env_perm(struct ccs_request_info *r, const char *env);
> -+static int ccs_environ(struct ccs_execve *ee);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+static bool __ccs_capable(const u8 operation);
> -+static bool ccs_check_capability_acl(struct ccs_request_info *r,
> -+				     const struct ccs_acl_info *ptr);
> -+static bool ccs_kernel_service(void);
> -+static int __ccs_ptrace_permission(long request, long pid);
> -+static int __ccs_socket_create_permission(int family, int type, int protocol);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
> -+				      const struct ccs_group *group);
> -+static bool ccs_check_inet_acl(struct ccs_request_info *r,
> -+			       const struct ccs_acl_info *ptr);
> -+static bool ccs_check_unix_acl(struct ccs_request_info *r,
> -+			       const struct ccs_acl_info *ptr);
> -+static bool ccs_kernel_service(void);
> -+static int __ccs_socket_bind_permission(struct socket *sock,
> -+					struct sockaddr *addr, int addr_len);
> -+static int __ccs_socket_connect_permission(struct socket *sock,
> -+					   struct sockaddr *addr,
> -+					   int addr_len);
> -+static int __ccs_socket_listen_permission(struct socket *sock);
> -+static int __ccs_socket_post_accept_permission(struct socket *sock,
> -+					       struct socket *newsock);
> -+static int __ccs_socket_sendmsg_permission(struct socket *sock,
> -+					   struct msghdr *msg, int size);
> -+static int ccs_check_inet_address(const struct sockaddr *addr,
> -+				  const unsigned int addr_len, const u16 port,
> -+				  struct ccs_addr_info *address);
> -+static int ccs_check_unix_address(struct sockaddr *addr,
> -+				  const unsigned int addr_len,
> -+				  struct ccs_addr_info *address);
> -+static int ccs_inet_entry(const struct ccs_addr_info *address);
> -+static int ccs_unix_entry(const struct ccs_addr_info *address);
> -+static u8 ccs_sock_family(struct sock *sk);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+static int __ccs_socket_post_recvmsg_permission(struct sock *sk,
> -+						struct sk_buff *skb,
> -+						int flags);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+static bool ccs_check_signal_acl(struct ccs_request_info *r,
> -+				 const struct ccs_acl_info *ptr);
> -+static int ccs_signal_acl(const int pid, const int sig);
> -+static int ccs_signal_acl0(pid_t tgid, pid_t pid, int sig);
> -+static int ccs_signal_acl2(const int sig, const int pid);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+static int __ccs_getattr_permission(struct vfsmount *mnt,
> -+				    struct dentry *dentry);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+static bool ccs_find_execute_handler(struct ccs_execve *ee, const u8 type);
> -+static int ccs_try_alt_exec(struct ccs_execve *ee);
> -+static void ccs_unescape(unsigned char *dest);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+static bool ccs_check_task_acl(struct ccs_request_info *r,
> -+			       const struct ccs_acl_info *ptr);
> -+#endif
> -+
> -+/***** SECTION4: Standalone functions section *****/
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
> -+
> -+/**
> -+ * ccs_copy_argv - Wrapper for copy_strings_kernel().
> -+ *
> -+ * @arg:  String to copy.
> -+ * @bprm: Pointer to "struct linux_binprm".
> -+ *
> -+ * Returns return value of copy_strings_kernel().
> -+ */
> -+static inline int ccs_copy_argv(const char *arg, struct linux_binprm *bprm)
> -+{
> -+	const int ret = copy_strings_kernel(1, &arg, bprm);
> -+	if (ret >= 0)
> -+		bprm->argc++;
> -+	return ret;
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * ccs_copy_argv - Wrapper for copy_strings_kernel().
> -+ *
> -+ * @arg:  String to copy.
> -+ * @bprm: Pointer to "struct linux_binprm".
> -+ *
> -+ * Returns return value of copy_strings_kernel().
> -+ */
> -+static inline int ccs_copy_argv(char *arg, struct linux_binprm *bprm)
> -+{
> -+	const int ret = copy_strings_kernel(1, &arg, bprm);
> -+	if (ret >= 0)
> -+		bprm->argc++;
> -+	return ret;
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
> -+
> -+/**
> -+ * get_fs_root - Get reference on root directory.
> -+ *
> -+ * @fs:   Pointer to "struct fs_struct".
> -+ * @root: Pointer to "struct path".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline void get_fs_root(struct fs_struct *fs, struct path *root)
> -+{
> -+	read_lock(&fs->lock);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+	*root = fs->root;
> -+	path_get(root);
> -+#else
> -+	root->dentry = dget(fs->root);
> -+	root->mnt = mntget(fs->rootmnt);
> -+#endif
> -+	read_unlock(&fs->lock);
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+
> -+/**
> -+ * module_put - Put a reference on module.
> -+ *
> -+ * @module: Pointer to "struct module". Maybe NULL.
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline void module_put(struct module *module)
> -+{
> -+	if (module)
> -+		__MOD_DEC_USE_COUNT(module);
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_put_filesystem - Wrapper for put_filesystem().
> -+ *
> -+ * @fstype: Pointer to "struct file_system_type".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Since put_filesystem() is not exported, I embed put_filesystem() here.
> -+ */
> -+static inline void ccs_put_filesystem(struct file_system_type *fstype)
> -+{
> -+	module_put(fstype->owner);
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
> -+#if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
> -+#if !defined(AX_MAJOR) || AX_MAJOR != 3
> -+
> -+/**
> -+ * ip_hdr - Get "struct iphdr".
> -+ *
> -+ * @skb: Pointer to "struct sk_buff".
> -+ *
> -+ * Returns pointer to "struct iphdr".
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
> -+{
> -+	return skb->nh.iph;
> -+}
> -+
> -+/**
> -+ * udp_hdr - Get "struct udphdr".
> -+ *
> -+ * @skb: Pointer to "struct sk_buff".
> -+ *
> -+ * Returns pointer to "struct udphdr".
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
> -+{
> -+	return skb->h.uh;
> -+}
> -+
> -+/**
> -+ * ipv6_hdr - Get "struct ipv6hdr".
> -+ *
> -+ * @skb: Pointer to "struct sk_buff".
> -+ *
> -+ * Returns pointer to "struct ipv6hdr".
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
> -+{
> -+	return skb->nh.ipv6h;
> -+}
> -+
> -+#endif
> -+#endif
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+
> -+/**
> -+ * skb_kill_datagram - Kill a datagram forcibly.
> -+ *
> -+ * @sk:    Pointer to "struct sock".
> -+ * @skb:   Pointer to "struct sk_buff".
> -+ * @flags: Flags passed to skb_recv_datagram().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
> -+				     int flags)
> -+{
> -+	/* Clear queue. */
> -+	if (flags & MSG_PEEK) {
> -+		int clear = 0;
> -+		spin_lock_irq(&sk->receive_queue.lock);
> -+		if (skb == skb_peek(&sk->receive_queue)) {
> -+			__skb_unlink(skb, &sk->receive_queue);
> -+			clear = 1;
> -+		}
> -+		spin_unlock_irq(&sk->receive_queue.lock);
> -+		if (clear)
> -+			kfree_skb(skb);
> -+	}
> -+	skb_free_datagram(sk, skb);
> -+}
> -+
> -+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
> -+
> -+/**
> -+ * skb_kill_datagram - Kill a datagram forcibly.
> -+ *
> -+ * @sk:    Pointer to "struct sock".
> -+ * @skb:   Pointer to "struct sk_buff".
> -+ * @flags: Flags passed to skb_recv_datagram().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
> -+				     int flags)
> -+{
> -+	/* Clear queue. */
> -+	if (flags & MSG_PEEK) {
> -+		int clear = 0;
> -+		spin_lock_bh(&sk->sk_receive_queue.lock);
> -+		if (skb == skb_peek(&sk->sk_receive_queue)) {
> -+			__skb_unlink(skb, &sk->sk_receive_queue);
> -+			clear = 1;
> -+		}
> -+		spin_unlock_bh(&sk->sk_receive_queue.lock);
> -+		if (clear)
> -+			kfree_skb(skb);
> -+	}
> -+	skb_free_datagram(sk, skb);
> -+}
> -+
> -+#endif
> -+
> -+#endif
> -+
> -+/***** SECTION5: Variables definition section *****/
> -+
> -+/* The initial domain. */
> -+struct ccs_domain_info ccs_kernel_domain;
> -+
> -+/* The list for "struct ccs_domain_info". */
> -+LIST_HEAD(ccs_domain_list);
> -+
> -+/***** SECTION6: Dependent functions section *****/
> -+
> -+/**
> -+ * ccs_path_matches_group - Check whether the given pathname matches members of the given pathname group.
> -+ *
> -+ * @pathname: The name of pathname.
> -+ * @group:    Pointer to "struct ccs_path_group".
> -+ *
> -+ * Returns matched member's pathname if @pathname matches pathnames in @group,
> -+ * NULL otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static const struct ccs_path_info *ccs_path_matches_group
> -+(const struct ccs_path_info *pathname, const struct ccs_group *group)
> -+{
> -+	struct ccs_path_group *member;
> -+	list_for_each_entry_srcu(member, &group->member_list, head.list,
> -+				 &ccs_ss) {
> -+		if (member->head.is_deleted)
> -+			continue;
> -+		if (!ccs_path_matches_pattern(pathname, member->member_name))
> -+			continue;
> -+		return member->member_name;
> -+	}
> -+	return NULL;
> -+}
> -+
> -+/**
> -+ * ccs_number_matches_group - Check whether the given number matches members of the given number group.
> -+ *
> -+ * @min:   Min number.
> -+ * @max:   Max number.
> -+ * @group: Pointer to "struct ccs_number_group".
> -+ *
> -+ * Returns true if @min and @max partially overlaps @group, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_number_matches_group(const unsigned long min,
> -+				     const unsigned long max,
> -+				     const struct ccs_group *group)
> -+{
> -+	struct ccs_number_group *member;
> -+	bool matched = false;
> -+	list_for_each_entry_srcu(member, &group->member_list, head.list,
> -+				 &ccs_ss) {
> -+		if (member->head.is_deleted)
> -+			continue;
> -+		if (min > member->number.values[1] ||
> -+		    max < member->number.values[0])
> -+			continue;
> -+		matched = true;
> -+		break;
> -+	}
> -+	return matched;
> -+}
> -+
> -+/**
> -+ * ccs_check_entry - Do permission check.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true on match, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_check_entry(struct ccs_request_info *r,
> -+			    struct ccs_acl_info *ptr)
> -+{
> -+	if (ptr->is_deleted || ptr->type != r->param_type)
> -+		return false;
> -+	switch (r->param_type) {
> -+	case CCS_TYPE_PATH_ACL:
> -+		return ccs_check_path_acl(r, ptr);
> -+	case CCS_TYPE_PATH2_ACL:
> -+		return ccs_check_path2_acl(r, ptr);
> -+	case CCS_TYPE_PATH_NUMBER_ACL:
> -+		return ccs_check_path_number_acl(r, ptr);
> -+	case CCS_TYPE_MKDEV_ACL:
> -+		return ccs_check_mkdev_acl(r, ptr);
> -+	case CCS_TYPE_MOUNT_ACL:
> -+		return ccs_check_mount_acl(r, ptr);
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	case CCS_TYPE_ENV_ACL:
> -+		return ccs_check_env_acl(r, ptr);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	case CCS_TYPE_CAPABILITY_ACL:
> -+		return ccs_check_capability_acl(r, ptr);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	case CCS_TYPE_INET_ACL:
> -+		return ccs_check_inet_acl(r, ptr);
> -+	case CCS_TYPE_UNIX_ACL:
> -+		return ccs_check_unix_acl(r, ptr);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	case CCS_TYPE_SIGNAL_ACL:
> -+		return ccs_check_signal_acl(r, ptr);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+	case CCS_TYPE_MANUAL_TASK_ACL:
> -+		return ccs_check_task_acl(r, ptr);
> -+#endif
> -+	}
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_check_acl - Do permission check.
> -+ *
> -+ * @r: Pointer to "struct ccs_request_info".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+int ccs_check_acl(struct ccs_request_info *r)
> -+{
> -+	const struct ccs_domain_info *domain = ccs_current_domain();
> -+	int error;
> -+	do {
> -+		struct ccs_acl_info *ptr;
> -+		const struct list_head *list = &domain->acl_info_list;
> -+		u16 i = 0;
> -+retry:
> -+		list_for_each_entry_srcu(ptr, list, list, &ccs_ss) {
> -+			if (!ccs_check_entry(r, ptr))
> -+				continue;
> -+			if (!ccs_condition(r, ptr->cond))
> -+				continue;
> -+			r->matched_acl = ptr;
> -+			r->granted = true;
> -+			ccs_audit_log(r);
> -+			return 0;
> -+		}
> -+		for (; i < CCS_MAX_ACL_GROUPS; i++) {
> -+			if (!test_bit(i, domain->group))
> -+				continue;
> -+			list = &domain->ns->acl_group[i++];
> -+			goto retry;
> -+		}
> -+		r->granted = false;
> -+		error = ccs_audit_log(r);
> -+	} while (error == CCS_RETRY_REQUEST &&
> -+		 r->type != CCS_MAC_FILE_EXECUTE);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_last_word - Get last component of a domainname.
> -+ *
> -+ * @name: Domainname to check.
> -+ *
> -+ * Returns the last word of @name.
> -+ */
> -+static const char *ccs_last_word(const char *name)
> -+{
> -+	const char *cp = strrchr(name, ' ');
> -+	if (cp)
> -+		return cp + 1;
> -+	return name;
> -+}
> -+
> -+/**
> -+ * ccs_scan_transition - Try to find specific domain transition type.
> -+ *
> -+ * @list:       Pointer to "struct list_head".
> -+ * @domainname: The name of current domain.
> -+ * @program:    The name of requested program.
> -+ * @last_name:  The last component of @domainname.
> -+ * @type:       One of values in "enum ccs_transition_type".
> -+ *
> -+ * Returns true if found one, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_scan_transition(const struct list_head *list,
> -+				const struct ccs_path_info *domainname,
> -+				const struct ccs_path_info *program,
> -+				const char *last_name,
> -+				const enum ccs_transition_type type)
> -+{
> -+	const struct ccs_transition_control *ptr;
> -+	list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
> -+		if (ptr->head.is_deleted || ptr->type != type)
> -+			continue;
> -+		if (ptr->domainname) {
> -+			if (!ptr->is_last_name) {
> -+				if (ptr->domainname != domainname)
> -+					continue;
> -+			} else {
> -+				/*
> -+				 * Use direct strcmp() since this is
> -+				 * unlikely used.
> -+				 */
> -+				if (strcmp(ptr->domainname->name, last_name))
> -+					continue;
> -+			}
> -+		}
> -+		if (ptr->program && ccs_pathcmp(ptr->program, program))
> -+			continue;
> -+		return true;
> -+	}
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_transition_type - Get domain transition type.
> -+ *
> -+ * @ns:         Pointer to "struct ccs_policy_namespace".
> -+ * @domainname: The name of current domain.
> -+ * @program:    The name of requested program.
> -+ *
> -+ * Returns CCS_TRANSITION_CONTROL_TRANSIT if executing @program causes domain
> -+ * transition across namespaces, CCS_TRANSITION_CONTROL_INITIALIZE if executing
> -+ * @program reinitializes domain transition within that namespace,
> -+ * CCS_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname ,
> -+ * others otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static enum ccs_transition_type ccs_transition_type
> -+(const struct ccs_policy_namespace *ns, const struct ccs_path_info *domainname,
> -+ const struct ccs_path_info *program)
> -+{
> -+	const char *last_name = ccs_last_word(domainname->name);
> -+	enum ccs_transition_type type = CCS_TRANSITION_CONTROL_NO_RESET;
> -+	while (type < CCS_MAX_TRANSITION_TYPE) {
> -+		const struct list_head * const list =
> -+			&ns->policy_list[CCS_ID_TRANSITION_CONTROL];
> -+		if (!ccs_scan_transition(list, domainname, program, last_name,
> -+					 type)) {
> -+			type++;
> -+			continue;
> -+		}
> -+		if (type != CCS_TRANSITION_CONTROL_NO_RESET &&
> -+		    type != CCS_TRANSITION_CONTROL_NO_INITIALIZE)
> -+			break;
> -+		/*
> -+		 * Do not check for reset_domain if no_reset_domain matched.
> -+		 * Do not check for initialize_domain if no_initialize_domain
> -+		 * matched.
> -+		 */
> -+		type++;
> -+		type++;
> -+	}
> -+	return type;
> -+}
> -+
> -+/**
> -+ * ccs_find_next_domain - Find a domain.
> -+ *
> -+ * @ee: Pointer to "struct ccs_execve".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_find_next_domain(struct ccs_execve *ee)
> -+{
> -+	struct ccs_request_info *r = &ee->r;
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	const struct ccs_path_info *handler = ee->handler;
> -+#endif
> -+	struct ccs_domain_info *domain = NULL;
> -+	struct ccs_domain_info * const old_domain = ccs_current_domain();
> -+	struct linux_binprm *bprm = ee->bprm;
> -+	struct ccs_security *task = ccs_current_security();
> -+	const struct ccs_path_info *candidate;
> -+	struct ccs_path_info exename;
> -+	int retval;
> -+	bool reject_on_transition_failure = false;
> -+
> -+	/* Get symlink's pathname of program. */
> -+	retval = ccs_symlink_path(bprm->filename, &exename);
> -+	if (retval < 0)
> -+		return retval;
> -+
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	if (handler) {
> -+		/* No permission check for execute handler. */
> -+		candidate = &exename;
> -+		if (ccs_pathcmp(candidate, handler)) {
> -+			/* Failed to verify execute handler. */
> -+			static u8 counter = 20;
> -+			if (counter) {
> -+				counter--;
> -+				printk(KERN_WARNING "Failed to verify: %s\n",
> -+				       handler->name);
> -+			}
> -+			goto out;
> -+		}
> -+	} else
> -+#endif
> -+	{
> -+		struct ccs_aggregator *ptr;
> -+		struct list_head *list;
> -+retry:
> -+		/* Check 'aggregator' directive. */
> -+		candidate = &exename;
> -+		list = &old_domain->ns->policy_list[CCS_ID_AGGREGATOR];
> -+		list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
> -+			if (ptr->head.is_deleted ||
> -+			    !ccs_path_matches_pattern(candidate,
> -+						      ptr->original_name))
> -+				continue;
> -+			candidate = ptr->aggregated_name;
> -+			break;
> -+		}
> -+
> -+		/* Check execute permission. */
> -+		retval = ccs_execute_permission(r, candidate);
> -+		if (retval == CCS_RETRY_REQUEST)
> -+			goto retry;
> -+		if (retval < 0)
> -+			goto out;
> -+		/*
> -+		 * To be able to specify domainnames with wildcards, use the
> -+		 * pathname specified in the policy (which may contain
> -+		 * wildcard) rather than the pathname passed to execve()
> -+		 * (which never contains wildcard).
> -+		 */
> -+		if (r->param.path.matched_path)
> -+			candidate = r->param.path.matched_path;
> -+	}
> -+	/*
> -+	 * Check for domain transition preference if "file execute" matched.
> -+	 * If preference is given, make do_execve() fail if domain transition
> -+	 * has failed, for domain transition preference should be used with
> -+	 * destination domain defined.
> -+	 */
> -+	if (r->ee->transition) {
> -+		const char *domainname = r->ee->transition->name;
> -+		reject_on_transition_failure = true;
> -+		if (!strcmp(domainname, "keep"))
> -+			goto force_keep_domain;
> -+		if (!strcmp(domainname, "child"))
> -+			goto force_child_domain;
> -+		if (!strcmp(domainname, "reset"))
> -+			goto force_reset_domain;
> -+		if (!strcmp(domainname, "initialize"))
> -+			goto force_initialize_domain;
> -+		if (!strcmp(domainname, "parent")) {
> -+			char *cp;
> -+			strncpy(ee->tmp, old_domain->domainname->name,
> -+				CCS_EXEC_TMPSIZE - 1);
> -+			cp = strrchr(ee->tmp, ' ');
> -+			if (cp)
> -+				*cp = '\0';
> -+		} else if (*domainname == '<')
> -+			strncpy(ee->tmp, domainname, CCS_EXEC_TMPSIZE - 1);
> -+		else
> -+			snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
> -+				 old_domain->domainname->name, domainname);
> -+		goto force_jump_domain;
> -+	}
> -+	/*
> -+	 * No domain transition preference specified.
> -+	 * Calculate domain to transit to.
> -+	 */
> -+	switch (ccs_transition_type(old_domain->ns, old_domain->domainname,
> -+				    candidate)) {
> -+	case CCS_TRANSITION_CONTROL_RESET:
> -+force_reset_domain:
> -+		/* Transit to the root of specified namespace. */
> -+		snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "<%s>",
> -+			 candidate->name);
> -+		/*
> -+		 * Make do_execve() fail if domain transition across namespaces
> -+		 * has failed.
> -+		 */
> -+		reject_on_transition_failure = true;
> -+		break;
> -+	case CCS_TRANSITION_CONTROL_INITIALIZE:
> -+force_initialize_domain:
> -+		/* Transit to the child of current namespace's root. */
> -+		snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
> -+			 old_domain->ns->name, candidate->name);
> -+		break;
> -+	case CCS_TRANSITION_CONTROL_KEEP:
> -+force_keep_domain:
> -+		/* Keep current domain. */
> -+		domain = old_domain;
> -+		break;
> -+	default:
> -+		if (old_domain == &ccs_kernel_domain && !ccs_policy_loaded) {
> -+			/*
> -+			 * Needn't to transit from kernel domain before
> -+			 * starting /sbin/init. But transit from kernel domain
> -+			 * if executing initializers because they might start
> -+			 * before /sbin/init.
> -+			 */
> -+			domain = old_domain;
> -+			break;
> -+		}
> -+force_child_domain:
> -+		/* Normal domain transition. */
> -+		snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
> -+			 old_domain->domainname->name, candidate->name);
> -+		break;
> -+	}
> -+force_jump_domain:
> -+	/*
> -+	 * Tell GC that I started execve().
> -+	 * Also, tell open_exec() to check read permission.
> -+	 */
> -+	task->ccs_flags |= CCS_TASK_IS_IN_EXECVE;
> -+	/*
> -+	 * Make task->ccs_flags visible to GC before changing
> -+	 * task->ccs_domain_info.
> -+	 */
> -+	smp_wmb();
> -+	/*
> -+	 * Proceed to the next domain in order to allow reaching via PID.
> -+	 * It will be reverted if execve() failed. Reverting is not good.
> -+	 * But it is better than being unable to reach via PID in interactive
> -+	 * enforcing mode.
> -+	 */
> -+	if (!domain)
> -+		domain = ccs_assign_domain(ee->tmp, true);
> -+	if (domain)
> -+		retval = 0;
> -+	else if (reject_on_transition_failure) {
> -+		printk(KERN_WARNING
> -+		       "ERROR: Domain '%s' not ready.\n", ee->tmp);
> -+		retval = -ENOMEM;
> -+	} else if (r->mode == CCS_CONFIG_ENFORCING)
> -+		retval = -ENOMEM;
> -+	else {
> -+		retval = 0;
> -+		if (!old_domain->flags[CCS_DIF_TRANSITION_FAILED]) {
> -+			old_domain->flags[CCS_DIF_TRANSITION_FAILED] = true;
> -+			r->granted = false;
> -+			ccs_write_log(r, "%s",
> -+				      ccs_dif[CCS_DIF_TRANSITION_FAILED]);
> -+			printk(KERN_WARNING
> -+			       "ERROR: Domain '%s' not defined.\n", ee->tmp);
> -+		}
> -+	}
> -+out:
> -+	kfree(exename.name);
> -+	return retval;
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+
> -+/**
> -+ * ccs_unescape - Unescape escaped string.
> -+ *
> -+ * @dest: String to unescape.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_unescape(unsigned char *dest)
> -+{
> -+	unsigned char *src = dest;
> -+	unsigned char c;
> -+	unsigned char d;
> -+	unsigned char e;
> -+	while (1) {
> -+		c = *src++;
> -+		if (!c)
> -+			break;
> -+		if (c != '\\') {
> -+			*dest++ = c;
> -+			continue;
> -+		}
> -+		c = *src++;
> -+		if (c == '\\') {
> -+			*dest++ = c;
> -+			continue;
> -+		}
> -+		if (c < '0' || c > '3')
> -+			break;
> -+		d = *src++;
> -+		if (d < '0' || d > '7')
> -+			break;
> -+		e = *src++;
> -+		if (e < '0' || e > '7')
> -+			break;
> -+		*dest++ = ((c - '0') << 6) + ((d - '0') << 3) + (e - '0');
> -+	}
> -+	*dest = '\0';
> -+}
> -+
> -+/**
> -+ * ccs_try_alt_exec - Try to start execute handler.
> -+ *
> -+ * @ee: Pointer to "struct ccs_execve".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_try_alt_exec(struct ccs_execve *ee)
> -+{
> -+	/*
> -+	 * Contents of modified bprm.
> -+	 * The envp[] in original bprm is moved to argv[] so that
> -+	 * the alternatively executed program won't be affected by
> -+	 * some dangerous environment variables like LD_PRELOAD.
> -+	 *
> -+	 * modified bprm->argc
> -+	 *    = original bprm->argc + original bprm->envc + 7
> -+	 * modified bprm->envc
> -+	 *    = 0
> -+	 *
> -+	 * modified bprm->argv[0]
> -+	 *    = the program's name specified by *_execute_handler
> -+	 * modified bprm->argv[1]
> -+	 *    = ccs_current_domain()->domainname->name
> -+	 * modified bprm->argv[2]
> -+	 *    = the current process's name
> -+	 * modified bprm->argv[3]
> -+	 *    = the current process's information (e.g. uid/gid).
> -+	 * modified bprm->argv[4]
> -+	 *    = original bprm->filename
> -+	 * modified bprm->argv[5]
> -+	 *    = original bprm->argc in string expression
> -+	 * modified bprm->argv[6]
> -+	 *    = original bprm->envc in string expression
> -+	 * modified bprm->argv[7]
> -+	 *    = original bprm->argv[0]
> -+	 *  ...
> -+	 * modified bprm->argv[bprm->argc + 6]
> -+	 *     = original bprm->argv[bprm->argc - 1]
> -+	 * modified bprm->argv[bprm->argc + 7]
> -+	 *     = original bprm->envp[0]
> -+	 *  ...
> -+	 * modified bprm->argv[bprm->envc + bprm->argc + 6]
> -+	 *     = original bprm->envp[bprm->envc - 1]
> -+	 */
> -+	struct linux_binprm *bprm = ee->bprm;
> -+	struct file *filp;
> -+	int retval;
> -+	const int original_argc = bprm->argc;
> -+	const int original_envc = bprm->envc;
> -+
> -+	/* Close the requested program's dentry. */
> -+	ee->obj.path1.dentry = NULL;
> -+	ee->obj.path1.mnt = NULL;
> -+	ee->obj.stat_valid[CCS_PATH1] = false;
> -+	ee->obj.stat_valid[CCS_PATH1_PARENT] = false;
> -+	ee->obj.validate_done = false;
> -+	allow_write_access(bprm->file);
> -+	fput(bprm->file);
> -+	bprm->file = NULL;
> -+
> -+	/* Invalidate page dump cache. */
> -+	ee->dump.page = NULL;
> -+
> -+	/* Move envp[] to argv[] */
> -+	bprm->argc += bprm->envc;
> -+	bprm->envc = 0;
> -+
> -+	/* Set argv[6] */
> -+	{
> -+		snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_envc);
> -+		retval = ccs_copy_argv(ee->tmp, bprm);
> -+		if (retval < 0)
> -+			goto out;
> -+	}
> -+
> -+	/* Set argv[5] */
> -+	{
> -+		snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_argc);
> -+		retval = ccs_copy_argv(ee->tmp, bprm);
> -+		if (retval < 0)
> -+			goto out;
> -+	}
> -+
> -+	/* Set argv[4] */
> -+	{
> -+		retval = ccs_copy_argv(bprm->filename, bprm);
> -+		if (retval < 0)
> -+			goto out;
> -+	}
> -+
> -+	/* Set argv[3] */
> -+	{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
> -+		/*
> -+		 * Pass uid/gid seen from current user namespace, for these
> -+		 * values are used by programs in current user namespace in
> -+		 * order to decide whether to execve() or not (rather than by
> -+		 * auditing daemon in init's user namespace).
> -+		 */
> -+		snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
> -+			 "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
> -+			 "sgid=%d fsuid=%d fsgid=%d", ccs_sys_getpid(),
> -+			 __kuid_val(current_uid()), __kgid_val(current_gid()),
> -+			 __kuid_val(current_euid()),
> -+			 __kgid_val(current_egid()),
> -+			 __kuid_val(current_suid()),
> -+			 __kgid_val(current_sgid()),
> -+			 __kuid_val(current_fsuid()),
> -+			 __kgid_val(current_fsgid()));
> -+#else
> -+		snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
> -+			 "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
> -+			 "sgid=%d fsuid=%d fsgid=%d", ccs_sys_getpid(),
> -+			 current_uid(), current_gid(), current_euid(),
> -+			 current_egid(), current_suid(), current_sgid(),
> -+			 current_fsuid(), current_fsgid());
> -+#endif
> -+		retval = ccs_copy_argv(ee->tmp, bprm);
> -+		if (retval < 0)
> -+			goto out;
> -+	}
> -+
> -+	/* Set argv[2] */
> -+	{
> -+		char *exe = (char *) ccs_get_exe();
> -+		if (exe) {
> -+			retval = ccs_copy_argv(exe, bprm);
> -+			kfree(exe);
> -+		} else {
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
> -+			retval = ccs_copy_argv("<unknown>", bprm);
> -+#else
> -+			snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "<unknown>");
> -+			retval = ccs_copy_argv(ee->tmp, bprm);
> -+#endif
> -+		}
> -+		if (retval < 0)
> -+			goto out;
> -+	}
> -+
> -+	/* Set argv[1] */
> -+	{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
> -+		retval = ccs_copy_argv(ccs_current_domain()->domainname->name,
> -+				       bprm);
> -+#else
> -+		snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s",
> -+			 ccs_current_domain()->domainname->name);
> -+		retval = ccs_copy_argv(ee->tmp, bprm);
> -+#endif
> -+		if (retval < 0)
> -+			goto out;
> -+	}
> -+
> -+	/* Set argv[0] */
> -+	{
> -+		struct path root;
> -+		char *cp;
> -+		int root_len;
> -+		int handler_len;
> -+		get_fs_root(current->fs, &root);
> -+		cp = ccs_realpath(&root);
> -+		path_put(&root);
> -+		if (!cp) {
> -+			retval = -ENOMEM;
> -+			goto out;
> -+		}
> -+		root_len = strlen(cp);
> -+		retval = strncmp(ee->handler->name, cp, root_len);
> -+		root_len--;
> -+		kfree(cp);
> -+		if (retval) {
> -+			retval = -ENOENT;
> -+			goto out;
> -+		}
> -+		handler_len = ee->handler->total_len + 1;
> -+		cp = kmalloc(handler_len, CCS_GFP_FLAGS);
> -+		if (!cp) {
> -+			retval = -ENOMEM;
> -+			goto out;
> -+		}
> -+		/* ee->handler_path is released by ccs_finish_execve(). */
> -+		ee->handler_path = cp;
> -+		/* Adjust root directory for open_exec(). */
> -+		memmove(cp, ee->handler->name + root_len,
> -+			handler_len - root_len);
> -+		ccs_unescape(cp);
> -+		retval = -ENOENT;
> -+		if (*cp != '/')
> -+			goto out;
> -+		retval = ccs_copy_argv(cp, bprm);
> -+		if (retval < 0)
> -+			goto out;
> -+	}
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
> -+	bprm->argv_len = bprm->exec - bprm->p;
> -+#endif
> -+#endif
> -+
> -+	/*
> -+	 * OK, now restart the process with execute handler program's dentry.
> -+	 */
> -+	filp = open_exec(ee->handler_path);
> -+	if (IS_ERR(filp)) {
> -+		retval = PTR_ERR(filp);
> -+		goto out;
> -+	}
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
> -+	ee->obj.path1 = filp->f_path;
> -+#else
> -+	ee->obj.path1.dentry = filp->f_dentry;
> -+	ee->obj.path1.mnt = filp->f_vfsmnt;
> -+#endif
> -+	bprm->file = filp;
> -+	bprm->filename = ee->handler_path;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+	bprm->interp = bprm->filename;
> -+#endif
> -+	retval = prepare_binprm(bprm);
> -+	if (retval < 0)
> -+		goto out;
> -+	ee->r.dont_sleep_on_enforce_error = true;
> -+	retval = ccs_find_next_domain(ee);
> -+	ee->r.dont_sleep_on_enforce_error = false;
> -+out:
> -+	return retval;
> -+}
> -+
> -+/**
> -+ * ccs_find_execute_handler - Find an execute handler.
> -+ *
> -+ * @ee:   Pointer to "struct ccs_execve".
> -+ * @type: Type of execute handler.
> -+ *
> -+ * Returns true if found, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_find_execute_handler(struct ccs_execve *ee, const u8 type)
> -+{
> -+	struct ccs_request_info *r = &ee->r;
> -+	/*
> -+	 * To avoid infinite execute handler loop, don't use execute handler
> -+	 * if the current process is marked as execute handler.
> -+	 */
> -+	if (ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)
> -+		return false;
> -+	r->param_type = type;
> -+	ccs_check_acl(r);
> -+	if (!r->granted)
> -+		return false;
> -+	ee->handler = container_of(r->matched_acl, struct ccs_handler_acl,
> -+				   head)->handler;
> -+	ee->transition = r->matched_acl && r->matched_acl->cond &&
> -+		r->matched_acl->cond->exec_transit ?
> -+		r->matched_acl->cond->transit : NULL;
> -+	return true;
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_MMU
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
> -+#define CCS_BPRM_MMU
> -+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3
> -+#define CCS_BPRM_MMU
> -+#elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2
> -+#define CCS_BPRM_MMU
> -+#endif
> -+#endif
> -+
> -+/**
> -+ * ccs_dump_page - Dump a page to buffer.
> -+ *
> -+ * @bprm: Pointer to "struct linux_binprm".
> -+ * @pos:  Location to dump.
> -+ * @dump: Poiner to "struct ccs_page_dump".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
> -+		   struct ccs_page_dump *dump)
> -+{
> -+	struct page *page;
> -+	/* dump->data is released by ccs_start_execve(). */
> -+	if (!dump->data) {
> -+		dump->data = kzalloc(PAGE_SIZE, CCS_GFP_FLAGS);
> -+		if (!dump->data)
> -+			return false;
> -+	}
> -+	/* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
> -+#ifdef CCS_BPRM_MMU
> -+	if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
> -+		return false;
> -+#else
> -+	page = bprm->page[pos / PAGE_SIZE];
> -+#endif
> -+	if (page != dump->page) {
> -+		const unsigned int offset = pos % PAGE_SIZE;
> -+		/*
> -+		 * Maybe kmap()/kunmap() should be used here.
> -+		 * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
> -+		 * So do I.
> -+		 */
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
> -+		char *kaddr = kmap_atomic(page);
> -+#else
> -+		char *kaddr = kmap_atomic(page, KM_USER0);
> -+#endif
> -+		dump->page = page;
> -+		memcpy(dump->data + offset, kaddr + offset,
> -+		       PAGE_SIZE - offset);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
> -+		kunmap_atomic(kaddr);
> -+#else
> -+		kunmap_atomic(kaddr, KM_USER0);
> -+#endif
> -+	}
> -+	/* Same with put_arg_page(page) in fs/exec.c */
> -+#ifdef CCS_BPRM_MMU
> -+	put_page(page);
> -+#endif
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_start_execve - Prepare for execve() operation.
> -+ *
> -+ * @bprm: Pointer to "struct linux_binprm".
> -+ * @eep:  Pointer to "struct ccs_execve *".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_start_execve(struct linux_binprm *bprm,
> -+			    struct ccs_execve **eep)
> -+{
> -+	int retval;
> -+	struct ccs_security *task = ccs_current_security();
> -+	struct ccs_execve *ee;
> -+	int idx;
> -+	*eep = NULL;
> -+	ee = kzalloc(sizeof(*ee), CCS_GFP_FLAGS);
> -+	if (!ee)
> -+		return -ENOMEM;
> -+	ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
> -+	if (!ee->tmp) {
> -+		kfree(ee);
> -+		return -ENOMEM;
> -+	}
> -+	idx = ccs_read_lock();
> -+	/* ee->dump->data is allocated by ccs_dump_page(). */
> -+	ee->previous_domain = task->ccs_domain_info;
> -+	/* Clear manager flag. */
> -+	task->ccs_flags &= ~CCS_TASK_IS_MANAGER;
> -+	*eep = ee;
> -+	ccs_init_request_info(&ee->r, CCS_MAC_FILE_EXECUTE);
> -+	ee->r.ee = ee;
> -+	ee->bprm = bprm;
> -+	ee->r.obj = &ee->obj;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
> -+	ee->obj.path1 = bprm->file->f_path;
> -+#else
> -+	ee->obj.path1.dentry = bprm->file->f_dentry;
> -+	ee->obj.path1.mnt = bprm->file->f_vfsmnt;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	/*
> -+	 * No need to call ccs_environ() for execute handler because envp[] is
> -+	 * moved to argv[].
> -+	 */
> -+	if (ccs_find_execute_handler(ee, CCS_TYPE_AUTO_EXECUTE_HANDLER)) {
> -+		retval = ccs_try_alt_exec(ee);
> -+		goto done;
> -+	}
> -+#endif
> -+	retval = ccs_find_next_domain(ee);
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	if (retval == -EPERM &&
> -+	    ccs_find_execute_handler(ee, CCS_TYPE_DENIED_EXECUTE_HANDLER)) {
> -+		retval = ccs_try_alt_exec(ee);
> -+		goto done;
> -+	}
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	if (!retval)
> -+		retval = ccs_environ(ee);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+done:
> -+#endif
> -+	ccs_read_unlock(idx);
> -+	kfree(ee->tmp);
> -+	ee->tmp = NULL;
> -+	kfree(ee->dump.data);
> -+	ee->dump.data = NULL;
> -+	return retval;
> -+}
> -+
> -+/**
> -+ * ccs_finish_execve - Clean up execve() operation.
> -+ *
> -+ * @retval: Return code of an execve() operation.
> -+ * @ee:     Pointer to "struct ccs_execve".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_finish_execve(int retval, struct ccs_execve *ee)
> -+{
> -+	struct ccs_security *task = ccs_current_security();
> -+	if (!ee)
> -+		return;
> -+	if (retval < 0) {
> -+		task->ccs_domain_info = ee->previous_domain;
> -+		/*
> -+		 * Make task->ccs_domain_info visible to GC before changing
> -+		 * task->ccs_flags.
> -+		 */
> -+		smp_wmb();
> -+	} else {
> -+		/* Mark the current process as execute handler. */
> -+		if (ee->handler)
> -+			task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
> -+		/* Mark the current process as normal process. */
> -+		else
> -+			task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
> -+	}
> -+	/* Tell GC that I finished execve(). */
> -+	task->ccs_flags &= ~CCS_TASK_IS_IN_EXECVE;
> -+	kfree(ee->handler_path);
> -+	kfree(ee);
> -+}
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
> -+
> -+/**
> -+ * __ccs_search_binary_handler - Main routine for do_execve().
> -+ *
> -+ * @bprm: Pointer to "struct linux_binprm".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Performs permission checks for do_execve() and domain transition.
> -+ * Domain transition by "struct ccs_domain_transition_control" and
> -+ * "auto_domain_transition=" parameter of "struct ccs_condition" are reverted
> -+ * if do_execve() failed.
> -+ * Garbage collector does not remove "struct ccs_domain_info" from
> -+ * ccs_domain_list nor kfree("struct ccs_domain_info") if the current thread is
> -+ * marked as CCS_TASK_IS_IN_EXECVE.
> -+ */
> -+static int __ccs_search_binary_handler(struct linux_binprm *bprm)
> -+{
> -+	struct ccs_execve *ee;
> -+	int retval;
> -+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
> -+	if (!ccs_policy_loaded)
> -+		ccsecurity_exports.load_policy(bprm->filename);
> -+#endif
> -+	retval = ccs_start_execve(bprm, &ee);
> -+	if (!retval)
> -+		retval = search_binary_handler(bprm);
> -+	ccs_finish_execve(retval, ee);
> -+	return retval;
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * __ccs_search_binary_handler - Main routine for do_execve().
> -+ *
> -+ * @bprm: Pointer to "struct linux_binprm".
> -+ * @regs: Pointer to "struct pt_regs".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Performs permission checks for do_execve() and domain transition.
> -+ * Domain transition by "struct ccs_domain_transition_control" and
> -+ * "auto_domain_transition=" parameter of "struct ccs_condition" are reverted
> -+ * if do_execve() failed.
> -+ * Garbage collector does not remove "struct ccs_domain_info" from
> -+ * ccs_domain_list nor kfree("struct ccs_domain_info") if the current thread is
> -+ * marked as CCS_TASK_IS_IN_EXECVE.
> -+ */
> -+static int __ccs_search_binary_handler(struct linux_binprm *bprm,
> -+				       struct pt_regs *regs)
> -+{
> -+	struct ccs_execve *ee;
> -+	int retval;
> -+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
> -+	if (!ccs_policy_loaded)
> -+		ccsecurity_exports.load_policy(bprm->filename);
> -+#endif
> -+	retval = ccs_start_execve(bprm, &ee);
> -+	if (!retval)
> -+		retval = search_binary_handler(bprm, regs);
> -+	ccs_finish_execve(retval, ee);
> -+	return retval;
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_permission_init - Register permission check hooks.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+void __init ccs_permission_init(void)
> -+{
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
> -+	ccsecurity_ops.save_open_mode = __ccs_save_open_mode;
> -+	ccsecurity_ops.clear_open_mode = __ccs_clear_open_mode;
> -+	ccsecurity_ops.open_permission = __ccs_open_permission;
> -+#else
> -+	ccsecurity_ops.open_permission = ccs_new_open_permission;
> -+#endif
> -+	ccsecurity_ops.fcntl_permission = __ccs_fcntl_permission;
> -+	ccsecurity_ops.ioctl_permission = __ccs_ioctl_permission;
> -+	ccsecurity_ops.chmod_permission = __ccs_chmod_permission;
> -+	ccsecurity_ops.chown_permission = __ccs_chown_permission;
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+	ccsecurity_ops.getattr_permission = __ccs_getattr_permission;
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+	ccsecurity_ops.pivot_root_permission = __ccs_pivot_root_permission;
> -+	ccsecurity_ops.chroot_permission = __ccs_chroot_permission;
> -+#else
> -+	ccsecurity_ops.pivot_root_permission = ccs_old_pivot_root_permission;
> -+	ccsecurity_ops.chroot_permission = ccs_old_chroot_permission;
> -+#endif
> -+	ccsecurity_ops.umount_permission = __ccs_umount_permission;
> -+	ccsecurity_ops.mknod_permission = __ccs_mknod_permission;
> -+	ccsecurity_ops.mkdir_permission = __ccs_mkdir_permission;
> -+	ccsecurity_ops.rmdir_permission = __ccs_rmdir_permission;
> -+	ccsecurity_ops.unlink_permission = __ccs_unlink_permission;
> -+	ccsecurity_ops.symlink_permission = __ccs_symlink_permission;
> -+	ccsecurity_ops.truncate_permission = __ccs_truncate_permission;
> -+	ccsecurity_ops.rename_permission = __ccs_rename_permission;
> -+	ccsecurity_ops.link_permission = __ccs_link_permission;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
> -+	ccsecurity_ops.open_exec_permission = __ccs_open_exec_permission;
> -+	ccsecurity_ops.uselib_permission = __ccs_uselib_permission;
> -+#endif
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
> -+	ccsecurity_ops.parse_table = __ccs_parse_table;
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+	ccsecurity_ops.mount_permission = __ccs_mount_permission;
> -+#else
> -+	ccsecurity_ops.mount_permission = ccs_old_mount_permission;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	ccsecurity_ops.socket_create_permission =
> -+		__ccs_socket_create_permission;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	ccsecurity_ops.socket_listen_permission =
> -+		__ccs_socket_listen_permission;
> -+	ccsecurity_ops.socket_connect_permission =
> -+		__ccs_socket_connect_permission;
> -+	ccsecurity_ops.socket_bind_permission = __ccs_socket_bind_permission;
> -+	ccsecurity_ops.socket_post_accept_permission =
> -+		__ccs_socket_post_accept_permission;
> -+	ccsecurity_ops.socket_sendmsg_permission =
> -+		__ccs_socket_sendmsg_permission;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	ccsecurity_ops.socket_post_recvmsg_permission =
> -+		__ccs_socket_post_recvmsg_permission;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	ccsecurity_ops.kill_permission = ccs_signal_acl;
> -+	ccsecurity_ops.tgkill_permission = ccs_signal_acl0;
> -+	ccsecurity_ops.tkill_permission = ccs_signal_acl;
> -+	ccsecurity_ops.sigqueue_permission = ccs_signal_acl;
> -+	ccsecurity_ops.tgsigqueue_permission = ccs_signal_acl0;
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	ccsecurity_ops.capable = __ccs_capable;
> -+	ccsecurity_ops.ptrace_permission = __ccs_ptrace_permission;
> -+#endif
> -+	ccsecurity_ops.search_binary_handler = __ccs_search_binary_handler;
> -+}
> -+
> -+/**
> -+ * ccs_kern_path - Wrapper for kern_path().
> -+ *
> -+ * @pathname: Pathname to resolve. Maybe NULL.
> -+ * @flags:    Lookup flags.
> -+ * @path:     Pointer to "struct path".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_kern_path(const char *pathname, int flags, struct path *path)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
> -+	if (!pathname || kern_path(pathname, flags, path))
> -+		return -ENOENT;
> -+#else
> -+	struct nameidata nd;
> -+	if (!pathname || path_lookup(pathname, flags, &nd))
> -+		return -ENOENT;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+	*path = nd.path;
> -+#else
> -+	path->dentry = nd.dentry;
> -+	path->mnt = nd.mnt;
> -+#endif
> -+#endif
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_get_path - Get dentry/vfsmmount of a pathname.
> -+ *
> -+ * @pathname: The pathname to solve. Maybe NULL.
> -+ * @path:     Pointer to "struct path".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_get_path(const char *pathname, struct path *path)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+	return ccs_kern_path(pathname, LOOKUP_FOLLOW, path);
> -+#else
> -+	return ccs_kern_path(pathname, LOOKUP_FOLLOW | LOOKUP_POSITIVE, path);
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_symlink_path - Get symlink's pathname.
> -+ *
> -+ * @pathname: The pathname to solve. Maybe NULL.
> -+ * @name:     Pointer to "struct ccs_path_info".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * This function uses kzalloc(), so caller must kfree() if this function
> -+ * didn't return NULL.
> -+ */
> -+static int ccs_symlink_path(const char *pathname, struct ccs_path_info *name)
> -+{
> -+	char *buf;
> -+	struct path path;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+	if (ccs_kern_path(pathname, 0, &path))
> -+		return -ENOENT;
> -+#else
> -+	if (ccs_kern_path(pathname, LOOKUP_POSITIVE, &path))
> -+		return -ENOENT;
> -+#endif
> -+	buf = ccs_realpath(&path);
> -+	path_put(&path);
> -+	if (buf) {
> -+		name->name = buf;
> -+		ccs_fill_path_info(name);
> -+		return 0;
> -+	}
> -+	return -ENOMEM;
> -+}
> -+
> -+/**
> -+ * ccs_check_mount_acl - Check permission for path path path number operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_mount_acl(struct ccs_request_info *r,
> -+				const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_mount_acl *acl =
> -+		container_of(ptr, typeof(*acl), head);
> -+	return ccs_compare_number_union(r->param.mount.flags, &acl->flags) &&
> -+		ccs_compare_name_union(r->param.mount.type, &acl->fs_type) &&
> -+		ccs_compare_name_union(r->param.mount.dir, &acl->dir_name) &&
> -+		(!r->param.mount.need_dev ||
> -+		 ccs_compare_name_union(r->param.mount.dev, &acl->dev_name));
> -+}
> -+
> -+/**
> -+ * ccs_mount_acl - Check permission for mount() operation.
> -+ *
> -+ * @r:        Pointer to "struct ccs_request_info".
> -+ * @dev_name: Name of device file. Maybe NULL.
> -+ * @dir:      Pointer to "struct path".
> -+ * @type:     Name of filesystem type.
> -+ * @flags:    Mount options.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_mount_acl(struct ccs_request_info *r, const char *dev_name,
> -+			 struct path *dir, const char *type,
> -+			 unsigned long flags)
> -+{
> -+	struct ccs_obj_info obj = { };
> -+	struct file_system_type *fstype = NULL;
> -+	const char *requested_type = NULL;
> -+	const char *requested_dir_name = NULL;
> -+	const char *requested_dev_name = NULL;
> -+	struct ccs_path_info rtype;
> -+	struct ccs_path_info rdev;
> -+	struct ccs_path_info rdir;
> -+	int need_dev = 0;
> -+	int error = -ENOMEM;
> -+	r->obj = &obj;
> -+
> -+	/* Get fstype. */
> -+	requested_type = ccs_encode(type);
> -+	if (!requested_type)
> -+		goto out;
> -+	rtype.name = requested_type;
> -+	ccs_fill_path_info(&rtype);
> -+
> -+	/* Get mount point. */
> -+	obj.path2 = *dir;
> -+	requested_dir_name = ccs_realpath(dir);
> -+	if (!requested_dir_name) {
> -+		error = -ENOMEM;
> -+		goto out;
> -+	}
> -+	rdir.name = requested_dir_name;
> -+	ccs_fill_path_info(&rdir);
> -+
> -+	/* Compare fs name. */
> -+	if (type == ccs_mounts[CCS_MOUNT_REMOUNT]) {
> -+		/* dev_name is ignored. */
> -+	} else if (type == ccs_mounts[CCS_MOUNT_MAKE_UNBINDABLE] ||
> -+		   type == ccs_mounts[CCS_MOUNT_MAKE_PRIVATE] ||
> -+		   type == ccs_mounts[CCS_MOUNT_MAKE_SLAVE] ||
> -+		   type == ccs_mounts[CCS_MOUNT_MAKE_SHARED]) {
> -+		/* dev_name is ignored. */
> -+	} else if (type == ccs_mounts[CCS_MOUNT_BIND] ||
> -+		   type == ccs_mounts[CCS_MOUNT_MOVE]) {
> -+		need_dev = -1; /* dev_name is a directory */
> -+	} else {
> -+		fstype = get_fs_type(type);
> -+		if (!fstype) {
> -+			error = -ENODEV;
> -+			goto out;
> -+		}
> -+		if (fstype->fs_flags & FS_REQUIRES_DEV)
> -+			/* dev_name is a block device file. */
> -+			need_dev = 1;
> -+	}
> -+	if (need_dev) {
> -+		/* Get mount point or device file. */
> -+		if (ccs_get_path(dev_name, &obj.path1)) {
> -+			error = -ENOENT;
> -+			goto out;
> -+		}
> -+		requested_dev_name = ccs_realpath(&obj.path1);
> -+		if (!requested_dev_name) {
> -+			error = -ENOENT;
> -+			goto out;
> -+		}
> -+	} else {
> -+		/* Map dev_name to "<NULL>" if no dev_name given. */
> -+		if (!dev_name)
> -+			dev_name = "<NULL>";
> -+		requested_dev_name = ccs_encode(dev_name);
> -+		if (!requested_dev_name) {
> -+			error = -ENOMEM;
> -+			goto out;
> -+		}
> -+	}
> -+	rdev.name = requested_dev_name;
> -+	ccs_fill_path_info(&rdev);
> -+	r->param_type = CCS_TYPE_MOUNT_ACL;
> -+	r->param.mount.need_dev = need_dev;
> -+	r->param.mount.dev = &rdev;
> -+	r->param.mount.dir = &rdir;
> -+	r->param.mount.type = &rtype;
> -+	r->param.mount.flags = flags;
> -+	error = ccs_check_acl(r);
> -+out:
> -+	kfree(requested_dev_name);
> -+	kfree(requested_dir_name);
> -+	if (fstype)
> -+		ccs_put_filesystem(fstype);
> -+	kfree(requested_type);
> -+	/* Drop refcount obtained by ccs_get_path(). */
> -+	if (obj.path1.dentry)
> -+		path_put(&obj.path1);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * __ccs_mount_permission - Check permission for mount() operation.
> -+ *
> -+ * @dev_name:  Name of device file. Maybe NULL.
> -+ * @path:      Pointer to "struct path".
> -+ * @type:      Name of filesystem type. Maybe NULL.
> -+ * @flags:     Mount options.
> -+ * @data_page: Optional data. Maybe NULL.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_mount_permission(const char *dev_name, struct path *path,
> -+				  const char *type, unsigned long flags,
> -+				  void *data_page)
> -+{
> -+	struct ccs_request_info r;
> -+	int error = 0;
> -+	int idx;
> -+	if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
> -+		flags &= ~MS_MGC_MSK;
> -+	if (flags & MS_REMOUNT) {
> -+		type = ccs_mounts[CCS_MOUNT_REMOUNT];
> -+		flags &= ~MS_REMOUNT;
> -+	} else if (flags & MS_BIND) {
> -+		type = ccs_mounts[CCS_MOUNT_BIND];
> -+		flags &= ~MS_BIND;
> -+	} else if (flags & MS_SHARED) {
> -+		if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
> -+			return -EINVAL;
> -+		type = ccs_mounts[CCS_MOUNT_MAKE_SHARED];
> -+		flags &= ~MS_SHARED;
> -+	} else if (flags & MS_PRIVATE) {
> -+		if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
> -+			return -EINVAL;
> -+		type = ccs_mounts[CCS_MOUNT_MAKE_PRIVATE];
> -+		flags &= ~MS_PRIVATE;
> -+	} else if (flags & MS_SLAVE) {
> -+		if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
> -+			return -EINVAL;
> -+		type = ccs_mounts[CCS_MOUNT_MAKE_SLAVE];
> -+		flags &= ~MS_SLAVE;
> -+	} else if (flags & MS_UNBINDABLE) {
> -+		if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
> -+			return -EINVAL;
> -+		type = ccs_mounts[CCS_MOUNT_MAKE_UNBINDABLE];
> -+		flags &= ~MS_UNBINDABLE;
> -+	} else if (flags & MS_MOVE) {
> -+		type = ccs_mounts[CCS_MOUNT_MOVE];
> -+		flags &= ~MS_MOVE;
> -+	}
> -+	if (!type)
> -+		type = "<NULL>";
> -+	idx = ccs_read_lock();
> -+	if (ccs_init_request_info(&r, CCS_MAC_FILE_MOUNT)
> -+	    != CCS_CONFIG_DISABLED)
> -+		error = ccs_mount_acl(&r, dev_name, path, type, flags);
> -+	ccs_read_unlock(idx);
> -+	return error;
> -+}
> -+
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
> -+
> -+/**
> -+ * ccs_old_mount_permission - Check permission for mount() operation.
> -+ *
> -+ * @dev_name:  Name of device file.
> -+ * @nd:        Pointer to "struct nameidata".
> -+ * @type:      Name of filesystem type. Maybe NULL.
> -+ * @flags:     Mount options.
> -+ * @data_page: Optional data. Maybe NULL.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_old_mount_permission(const char *dev_name, struct nameidata *nd,
> -+				    const char *type, unsigned long flags,
> -+				    void *data_page)
> -+{
> -+	struct path path = { nd->mnt, nd->dentry };
> -+	return __ccs_mount_permission(dev_name, &path, type, flags, data_page);
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_compare_number_union - Check whether a value matches "struct ccs_number_union" or not.
> -+ *
> -+ * @value: Number to check.
> -+ * @ptr:   Pointer to "struct ccs_number_union".
> -+ *
> -+ * Returns true if @value matches @ptr, false otherwise.
> -+ */
> -+static bool ccs_compare_number_union(const unsigned long value,
> -+				     const struct ccs_number_union *ptr)
> -+{
> -+	if (ptr->group)
> -+		return ccs_number_matches_group(value, value, ptr->group);
> -+	return value >= ptr->values[0] && value <= ptr->values[1];
> -+}
> -+
> -+/**
> -+ * ccs_compare_name_union - Check whether a name matches "struct ccs_name_union" or not.
> -+ *
> -+ * @name: Pointer to "struct ccs_path_info".
> -+ * @ptr:  Pointer to "struct ccs_name_union".
> -+ *
> -+ * Returns "struct ccs_path_info" if @name matches @ptr, NULL otherwise.
> -+ */
> -+static const struct ccs_path_info *ccs_compare_name_union
> -+(const struct ccs_path_info *name, const struct ccs_name_union *ptr)
> -+{
> -+	if (ptr->group)
> -+		return ccs_path_matches_group(name, ptr->group);
> -+	if (ccs_path_matches_pattern(name, ptr->filename))
> -+		return ptr->filename;
> -+	return NULL;
> -+}
> -+
> -+/**
> -+ * ccs_add_slash - Add trailing '/' if needed.
> -+ *
> -+ * @buf: Pointer to "struct ccs_path_info".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * @buf must be generated by ccs_encode() because this function does not
> -+ * allocate memory for adding '/'.
> -+ */
> -+static void ccs_add_slash(struct ccs_path_info *buf)
> -+{
> -+	if (buf->is_dir)
> -+		return;
> -+	/* This is OK because ccs_encode() reserves space for appending "/". */
> -+	strcat((char *) buf->name, "/");
> -+	ccs_fill_path_info(buf);
> -+}
> -+
> -+/**
> -+ * ccs_get_realpath - Get realpath.
> -+ *
> -+ * @buf:  Pointer to "struct ccs_path_info".
> -+ * @path: Pointer to "struct path". @path->mnt may be NULL.
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_get_realpath(struct ccs_path_info *buf, struct path *path)
> -+{
> -+	buf->name = ccs_realpath(path);
> -+	if (buf->name) {
> -+		ccs_fill_path_info(buf);
> -+		return true;
> -+	}
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_check_path_acl - Check permission for path operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ *
> -+ * To be able to use wildcard for domain transition, this function sets
> -+ * matching entry on success. Since the caller holds ccs_read_lock(),
> -+ * it is safe to set matching entry.
> -+ */
> -+static bool ccs_check_path_acl(struct ccs_request_info *r,
> -+			       const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_path_acl *acl = container_of(ptr, typeof(*acl), head);
> -+	if (ptr->perm & (1 << r->param.path.operation)) {
> -+		r->param.path.matched_path =
> -+			ccs_compare_name_union(r->param.path.filename,
> -+					       &acl->name);
> -+		return r->param.path.matched_path != NULL;
> -+	}
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_check_path_number_acl - Check permission for path number operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_path_number_acl(struct ccs_request_info *r,
> -+				      const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_path_number_acl *acl =
> -+		container_of(ptr, typeof(*acl), head);
> -+	return (ptr->perm & (1 << r->param.path_number.operation)) &&
> -+		ccs_compare_number_union(r->param.path_number.number,
> -+					 &acl->number) &&
> -+		ccs_compare_name_union(r->param.path_number.filename,
> -+				       &acl->name);
> -+}
> -+
> -+/**
> -+ * ccs_check_path2_acl - Check permission for path path operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_path2_acl(struct ccs_request_info *r,
> -+				const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_path2_acl *acl =
> -+		container_of(ptr, typeof(*acl), head);
> -+	return (ptr->perm & (1 << r->param.path2.operation)) &&
> -+		ccs_compare_name_union(r->param.path2.filename1, &acl->name1)
> -+		&& ccs_compare_name_union(r->param.path2.filename2,
> -+					  &acl->name2);
> -+}
> -+
> -+/**
> -+ * ccs_check_mkdev_acl - Check permission for path number number number operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_mkdev_acl(struct ccs_request_info *r,
> -+				const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_mkdev_acl *acl =
> -+		container_of(ptr, typeof(*acl), head);
> -+	return (ptr->perm & (1 << r->param.mkdev.operation)) &&
> -+		ccs_compare_number_union(r->param.mkdev.mode, &acl->mode) &&
> -+		ccs_compare_number_union(r->param.mkdev.major, &acl->major) &&
> -+		ccs_compare_number_union(r->param.mkdev.minor, &acl->minor) &&
> -+		ccs_compare_name_union(r->param.mkdev.filename, &acl->name);
> -+}
> -+
> -+/**
> -+ * ccs_path_permission - Check permission for path operation.
> -+ *
> -+ * @r:         Pointer to "struct ccs_request_info".
> -+ * @operation: Type of operation.
> -+ * @filename:  Filename to check.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_path_permission(struct ccs_request_info *r, u8 operation,
> -+			       const struct ccs_path_info *filename)
> -+{
> -+	r->type = ccs_p2mac[operation];
> -+	r->mode = ccs_get_mode(r->profile, r->type);
> -+	if (r->mode == CCS_CONFIG_DISABLED)
> -+		return 0;
> -+	r->param_type = CCS_TYPE_PATH_ACL;
> -+	r->param.path.filename = filename;
> -+	r->param.path.operation = operation;
> -+	return ccs_check_acl(r);
> -+}
> -+
> -+/**
> -+ * ccs_execute_permission - Check permission for execute operation.
> -+ *
> -+ * @r:         Pointer to "struct ccs_request_info".
> -+ * @filename:  Filename to check.
> -+ *
> -+ * Returns 0 on success, CCS_RETRY_REQUEST on retry, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_execute_permission(struct ccs_request_info *r,
> -+				  const struct ccs_path_info *filename)
> -+{
> -+	int error;
> -+	/*
> -+	 * Unlike other permission checks, this check is done regardless of
> -+	 * profile mode settings in order to check for domain transition
> -+	 * preference.
> -+	 */
> -+	r->type = CCS_MAC_FILE_EXECUTE;
> -+	r->mode = ccs_get_mode(r->profile, r->type);
> -+	r->param_type = CCS_TYPE_PATH_ACL;
> -+	r->param.path.filename = filename;
> -+	r->param.path.operation = CCS_TYPE_EXECUTE;
> -+	error = ccs_check_acl(r);
> -+	r->ee->transition = r->matched_acl && r->matched_acl->cond &&
> -+		r->matched_acl->cond->exec_transit ?
> -+		r->matched_acl->cond->transit : NULL;
> -+	return error;
> -+}
> -+
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
> -+
> -+/**
> -+ * __ccs_save_open_mode - Remember original flags passed to sys_open().
> -+ *
> -+ * @mode: Flags passed to sys_open().
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * TOMOYO does not check "file write" if open(path, O_TRUNC | O_RDONLY) was
> -+ * requested because write() is not permitted. Instead, TOMOYO checks
> -+ * "file truncate" if O_TRUNC is passed.
> -+ *
> -+ * TOMOYO does not check "file read" and "file write" if open(path, 3) was
> -+ * requested because read()/write() are not permitted. Instead, TOMOYO checks
> -+ * "file ioctl" when ioctl() is requested.
> -+ */
> -+static void __ccs_save_open_mode(int mode)
> -+{
> -+	if ((mode & 3) == 3)
> -+		ccs_current_security()->ccs_flags |= CCS_OPEN_FOR_IOCTL_ONLY;
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 14)
> -+	/* O_TRUNC passes MAY_WRITE to ccs_open_permission(). */
> -+	else if (!(mode & 3) && (mode & O_TRUNC))
> -+		ccs_current_security()->ccs_flags |=
> -+			CCS_OPEN_FOR_READ_TRUNCATE;
> -+#endif
> -+}
> -+
> -+/**
> -+ * __ccs_clear_open_mode - Forget original flags passed to sys_open().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void __ccs_clear_open_mode(void)
> -+{
> -+	ccs_current_security()->ccs_flags &= ~(CCS_OPEN_FOR_IOCTL_ONLY |
> -+					       CCS_OPEN_FOR_READ_TRUNCATE);
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * __ccs_open_permission - Check permission for "read" and "write".
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @mnt:    Pointer to "struct vfsmount". Maybe NULL.
> -+ * @flag:   Flags for open().
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_open_permission(struct dentry *dentry, struct vfsmount *mnt,
> -+				 const int flag)
> -+{
> -+	struct ccs_request_info r;
> -+	struct ccs_obj_info obj = {
> -+		.path1.dentry = dentry,
> -+		.path1.mnt = mnt,
> -+	};
> -+	const u32 ccs_flags = ccs_current_flags();
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
> -+	const u8 acc_mode = (flag & 3) == 3 ? 0 : ACC_MODE(flag);
> -+#else
> -+	const u8 acc_mode = (ccs_flags & CCS_OPEN_FOR_IOCTL_ONLY) ? 0 :
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 14)
> -+		(ccs_flags & CCS_OPEN_FOR_READ_TRUNCATE) ? 4 :
> -+#endif
> -+		ACC_MODE(flag);
> -+#endif
> -+	int error = 0;
> -+	struct ccs_path_info buf;
> -+	int idx;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
> -+	if (current->in_execve && !(ccs_flags & CCS_TASK_IS_IN_EXECVE))
> -+		return 0;
> -+#endif
> -+#ifndef CONFIG_CCSECURITY_FILE_READDIR
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
> -+	if (d_is_dir(dentry))
> -+		return 0;
> -+#else
> -+	if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
> -+		return 0;
> -+#endif
> -+#endif
> -+	buf.name = NULL;
> -+	r.mode = CCS_CONFIG_DISABLED;
> -+	idx = ccs_read_lock();
> -+	if (acc_mode && ccs_init_request_info(&r, CCS_MAC_FILE_OPEN)
> -+	    != CCS_CONFIG_DISABLED) {
> -+		if (!ccs_get_realpath(&buf, &obj.path1)) {
> -+			error = -ENOMEM;
> -+			goto out;
> -+		}
> -+		r.obj = &obj;
> -+		if (acc_mode & MAY_READ)
> -+			error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
> -+		if (!error && (acc_mode & MAY_WRITE))
> -+			error = ccs_path_permission(&r, (flag & O_APPEND) ?
> -+						    CCS_TYPE_APPEND :
> -+						    CCS_TYPE_WRITE, &buf);
> -+	}
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
> -+	if (!error && (flag & O_TRUNC) &&
> -+	    ccs_init_request_info(&r, CCS_MAC_FILE_TRUNCATE)
> -+	    != CCS_CONFIG_DISABLED) {
> -+		if (!buf.name && !ccs_get_realpath(&buf, &obj.path1)) {
> -+			error = -ENOMEM;
> -+			goto out;
> -+		}
> -+		r.obj = &obj;
> -+		error = ccs_path_permission(&r, CCS_TYPE_TRUNCATE, &buf);
> -+	}
> -+#endif
> -+out:
> -+	kfree(buf.name);
> -+	ccs_read_unlock(idx);
> -+	if (r.mode != CCS_CONFIG_ENFORCING)
> -+		error = 0;
> -+	return error;
> -+}
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
> -+
> -+/**
> -+ * ccs_new_open_permission - Check permission for "read" and "write".
> -+ *
> -+ * @filp: Pointer to "struct file".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_new_open_permission(struct file *filp)
> -+{
> -+	return __ccs_open_permission(filp->f_path.dentry, filp->f_path.mnt,
> -+				     filp->f_flags);
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "getattr", "chroot" and "unmount".
> -+ *
> -+ * @operation: Type of operation.
> -+ * @dentry:    Pointer to "struct dentry".
> -+ * @mnt:       Pointer to "struct vfsmount". Maybe NULL.
> -+ * @target:    Symlink's target if @operation is CCS_TYPE_SYMLINK,
> -+ *             NULL otherwise.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_path_perm(const u8 operation, struct dentry *dentry,
> -+			 struct vfsmount *mnt, const char *target)
> -+{
> -+	struct ccs_request_info r;
> -+	struct ccs_obj_info obj = {
> -+		.path1.dentry = dentry,
> -+		.path1.mnt = mnt,
> -+	};
> -+	int error = 0;
> -+	struct ccs_path_info buf;
> -+	bool is_enforce = false;
> -+	struct ccs_path_info symlink_target;
> -+	int idx;
> -+	buf.name = NULL;
> -+	symlink_target.name = NULL;
> -+	idx = ccs_read_lock();
> -+	if (ccs_init_request_info(&r, ccs_p2mac[operation])
> -+	    == CCS_CONFIG_DISABLED)
> -+		goto out;
> -+	is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
> -+	error = -ENOMEM;
> -+	if (!ccs_get_realpath(&buf, &obj.path1))
> -+		goto out;
> -+	r.obj = &obj;
> -+	switch (operation) {
> -+	case CCS_TYPE_RMDIR:
> -+	case CCS_TYPE_CHROOT:
> -+		ccs_add_slash(&buf);
> -+		break;
> -+	case CCS_TYPE_SYMLINK:
> -+		symlink_target.name = ccs_encode(target);
> -+		if (!symlink_target.name)
> -+			goto out;
> -+		ccs_fill_path_info(&symlink_target);
> -+		obj.symlink_target = &symlink_target;
> -+		break;
> -+	}
> -+	error = ccs_path_permission(&r, operation, &buf);
> -+	if (operation == CCS_TYPE_SYMLINK)
> -+		kfree(symlink_target.name);
> -+out:
> -+	kfree(buf.name);
> -+	ccs_read_unlock(idx);
> -+	if (!is_enforce)
> -+		error = 0;
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_mkdev_perm - Check permission for "mkblock" and "mkchar".
> -+ *
> -+ * @operation: Type of operation. (CCS_TYPE_MKCHAR or CCS_TYPE_MKBLOCK)
> -+ * @dentry:    Pointer to "struct dentry".
> -+ * @mnt:       Pointer to "struct vfsmount". Maybe NULL.
> -+ * @mode:      Create mode.
> -+ * @dev:       Device number.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_mkdev_perm(const u8 operation, struct dentry *dentry,
> -+			  struct vfsmount *mnt, const unsigned int mode,
> -+			  unsigned int dev)
> -+{
> -+	struct ccs_request_info r;
> -+	struct ccs_obj_info obj = {
> -+		.path1.dentry = dentry,
> -+		.path1.mnt = mnt,
> -+	};
> -+	int error = 0;
> -+	struct ccs_path_info buf;
> -+	bool is_enforce = false;
> -+	int idx;
> -+	idx = ccs_read_lock();
> -+	if (ccs_init_request_info(&r, ccs_pnnn2mac[operation])
> -+	    == CCS_CONFIG_DISABLED)
> -+		goto out;
> -+	is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
> -+	error = -EPERM;
> -+	if (!capable(CAP_MKNOD))
> -+		goto out;
> -+	error = -ENOMEM;
> -+	if (!ccs_get_realpath(&buf, &obj.path1))
> -+		goto out;
> -+	r.obj = &obj;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+	dev = new_decode_dev(dev);
> -+#endif
> -+	r.param_type = CCS_TYPE_MKDEV_ACL;
> -+	r.param.mkdev.filename = &buf;
> -+	r.param.mkdev.operation = operation;
> -+	r.param.mkdev.mode = mode;
> -+	r.param.mkdev.major = MAJOR(dev);
> -+	r.param.mkdev.minor = MINOR(dev);
> -+	error = ccs_check_acl(&r);
> -+	kfree(buf.name);
> -+out:
> -+	ccs_read_unlock(idx);
> -+	if (!is_enforce)
> -+		error = 0;
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_path2_perm - Check permission for "rename", "link" and "pivot_root".
> -+ *
> -+ * @operation: Type of operation.
> -+ * @dentry1:   Pointer to "struct dentry".
> -+ * @mnt1:      Pointer to "struct vfsmount". Maybe NULL.
> -+ * @dentry2:   Pointer to "struct dentry".
> -+ * @mnt2:      Pointer to "struct vfsmount". Maybe NULL.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_path2_perm(const u8 operation, struct dentry *dentry1,
> -+			  struct vfsmount *mnt1, struct dentry *dentry2,
> -+			  struct vfsmount *mnt2)
> -+{
> -+	struct ccs_request_info r;
> -+	int error = 0;
> -+	struct ccs_path_info buf1;
> -+	struct ccs_path_info buf2;
> -+	bool is_enforce = false;
> -+	struct ccs_obj_info obj = {
> -+		.path1.dentry = dentry1,
> -+		.path1.mnt = mnt1,
> -+		.path2.dentry = dentry2,
> -+		.path2.mnt = mnt2,
> -+	};
> -+	int idx;
> -+	buf1.name = NULL;
> -+	buf2.name = NULL;
> -+	idx = ccs_read_lock();
> -+	if (ccs_init_request_info(&r, ccs_pp2mac[operation])
> -+	    == CCS_CONFIG_DISABLED)
> -+		goto out;
> -+	is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
> -+	error = -ENOMEM;
> -+	if (!ccs_get_realpath(&buf1, &obj.path1) ||
> -+	    !ccs_get_realpath(&buf2, &obj.path2))
> -+		goto out;
> -+	switch (operation) {
> -+	case CCS_TYPE_RENAME:
> -+	case CCS_TYPE_LINK:
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
> -+		if (!d_is_dir(dentry1))
> -+			break;
> -+#else
> -+		if (!dentry1->d_inode || !S_ISDIR(dentry1->d_inode->i_mode))
> -+			break;
> -+#endif
> -+		/* fall through */
> -+	case CCS_TYPE_PIVOT_ROOT:
> -+		ccs_add_slash(&buf1);
> -+		ccs_add_slash(&buf2);
> -+		break;
> -+	}
> -+	r.obj = &obj;
> -+	r.param_type = CCS_TYPE_PATH2_ACL;
> -+	r.param.path2.operation = operation;
> -+	r.param.path2.filename1 = &buf1;
> -+	r.param.path2.filename2 = &buf2;
> -+	error = ccs_check_acl(&r);
> -+out:
> -+	kfree(buf1.name);
> -+	kfree(buf2.name);
> -+	ccs_read_unlock(idx);
> -+	if (!is_enforce)
> -+		error = 0;
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
> -+ *
> -+ * @type:   Type of operation.
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
> -+ * @number: Number.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_path_number_perm(const u8 type, struct dentry *dentry,
> -+				struct vfsmount *vfsmnt, unsigned long number)
> -+{
> -+	struct ccs_request_info r;
> -+	struct ccs_obj_info obj = {
> -+		.path1.dentry = dentry,
> -+		.path1.mnt = vfsmnt,
> -+	};
> -+	int error = 0;
> -+	struct ccs_path_info buf;
> -+	int idx;
> -+	if (!dentry)
> -+		return 0;
> -+	idx = ccs_read_lock();
> -+	if (ccs_init_request_info(&r, ccs_pn2mac[type]) == CCS_CONFIG_DISABLED)
> -+		goto out;
> -+	error = -ENOMEM;
> -+	if (!ccs_get_realpath(&buf, &obj.path1))
> -+		goto out;
> -+	r.obj = &obj;
> -+	if (type == CCS_TYPE_MKDIR)
> -+		ccs_add_slash(&buf);
> -+	r.param_type = CCS_TYPE_PATH_NUMBER_ACL;
> -+	r.param.path_number.operation = type;
> -+	r.param.path_number.filename = &buf;
> -+	r.param.path_number.number = number;
> -+	error = ccs_check_acl(&r);
> -+	kfree(buf.name);
> -+out:
> -+	ccs_read_unlock(idx);
> -+	if (r.mode != CCS_CONFIG_ENFORCING)
> -+		error = 0;
> -+	return error;
> -+}
> -+
> -+/**
> -+ * __ccs_ioctl_permission - Check permission for "ioctl".
> -+ *
> -+ * @filp: Pointer to "struct file".
> -+ * @cmd:  Ioctl command number.
> -+ * @arg:  Param for @cmd.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_ioctl_permission(struct file *filp, unsigned int cmd,
> -+				  unsigned long arg)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
> -+	return ccs_path_number_perm(CCS_TYPE_IOCTL, filp->f_path.dentry,
> -+				    filp->f_path.mnt, cmd);
> -+#else
> -+	return ccs_path_number_perm(CCS_TYPE_IOCTL, filp->f_dentry,
> -+				    filp->f_vfsmnt, cmd);
> -+#endif
> -+}
> -+
> -+/**
> -+ * __ccs_chmod_permission - Check permission for "chmod".
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
> -+ * @mode:   Mode.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_chmod_permission(struct dentry *dentry,
> -+				  struct vfsmount *vfsmnt, mode_t mode)
> -+{
> -+	return ccs_path_number_perm(CCS_TYPE_CHMOD, dentry, vfsmnt,
> -+				    mode & S_IALLUGO);
> -+}
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
> -+
> -+/**
> -+ * __ccs_chown_permission - Check permission for "chown/chgrp".
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
> -+ * @user:   User ID.
> -+ * @group:  Group ID.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_chown_permission(struct dentry *dentry,
> -+				  struct vfsmount *vfsmnt, kuid_t user,
> -+				  kgid_t group)
> -+{
> -+	int error = 0;
> -+	if (uid_valid(user))
> -+		error = ccs_path_number_perm(CCS_TYPE_CHOWN, dentry, vfsmnt,
> -+					     from_kuid(&init_user_ns, user));
> -+	if (!error && gid_valid(group))
> -+		error = ccs_path_number_perm(CCS_TYPE_CHGRP, dentry, vfsmnt,
> -+					     from_kgid(&init_user_ns, group));
> -+	return error;
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * __ccs_chown_permission - Check permission for "chown/chgrp".
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
> -+ * @user:   User ID.
> -+ * @group:  Group ID.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_chown_permission(struct dentry *dentry,
> -+				  struct vfsmount *vfsmnt, uid_t user,
> -+				  gid_t group)
> -+{
> -+	int error = 0;
> -+	if (user == (uid_t) -1 && group == (gid_t) -1)
> -+		return 0;
> -+	if (user != (uid_t) -1)
> -+		error = ccs_path_number_perm(CCS_TYPE_CHOWN, dentry, vfsmnt,
> -+					     user);
> -+	if (!error && group != (gid_t) -1)
> -+		error = ccs_path_number_perm(CCS_TYPE_CHGRP, dentry, vfsmnt,
> -+					     group);
> -+	return error;
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * __ccs_fcntl_permission - Check permission for changing O_APPEND flag.
> -+ *
> -+ * @file: Pointer to "struct file".
> -+ * @cmd:  Command number.
> -+ * @arg:  Value for @cmd.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_fcntl_permission(struct file *file, unsigned int cmd,
> -+				  unsigned long arg)
> -+{
> -+	if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)))
> -+		return 0;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
> -+	return __ccs_open_permission(file->f_path.dentry, file->f_path.mnt,
> -+				     O_WRONLY | (arg & O_APPEND));
> -+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 6
> -+	return __ccs_open_permission(file->f_dentry, file->f_vfsmnt,
> -+				     O_WRONLY | (arg & O_APPEND));
> -+#else
> -+	return __ccs_open_permission(file->f_dentry, file->f_vfsmnt,
> -+				     (O_WRONLY + 1) | (arg & O_APPEND));
> -+#endif
> -+}
> -+
> -+/**
> -+ * __ccs_pivot_root_permission - Check permission for pivot_root().
> -+ *
> -+ * @old_path: Pointer to "struct path".
> -+ * @new_path: Pointer to "struct path".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_pivot_root_permission(struct path *old_path,
> -+				       struct path *new_path)
> -+{
> -+	return ccs_path2_perm(CCS_TYPE_PIVOT_ROOT, new_path->dentry,
> -+			      new_path->mnt, old_path->dentry, old_path->mnt);
> -+}
> -+
> -+/**
> -+ * __ccs_chroot_permission - Check permission for chroot().
> -+ *
> -+ * @path: Pointer to "struct path".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_chroot_permission(struct path *path)
> -+{
> -+	return ccs_path_perm(CCS_TYPE_CHROOT, path->dentry, path->mnt, NULL);
> -+}
> -+
> -+/**
> -+ * __ccs_umount_permission - Check permission for unmount.
> -+ *
> -+ * @mnt:   Pointer to "struct vfsmount".
> -+ * @flags: Unused.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_umount_permission(struct vfsmount *mnt, int flags)
> -+{
> -+	return ccs_path_perm(CCS_TYPE_UMOUNT, mnt->mnt_root, mnt, NULL);
> -+}
> -+
> -+/**
> -+ * __ccs_mknod_permission - Check permission for vfs_mknod().
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @mnt:    Pointer to "struct vfsmount". Maybe NULL.
> -+ * @mode:   Device type and permission.
> -+ * @dev:    Device number for block or character device.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_mknod_permission(struct dentry *dentry, struct vfsmount *mnt,
> -+				  const unsigned int mode, unsigned int dev)
> -+{
> -+	int error = 0;
> -+	const unsigned int perm = mode & S_IALLUGO;
> -+	switch (mode & S_IFMT) {
> -+	case S_IFCHR:
> -+		error = ccs_mkdev_perm(CCS_TYPE_MKCHAR, dentry, mnt, perm,
> -+				       dev);
> -+		break;
> -+	case S_IFBLK:
> -+		error = ccs_mkdev_perm(CCS_TYPE_MKBLOCK, dentry, mnt, perm,
> -+				       dev);
> -+		break;
> -+	case S_IFIFO:
> -+		error = ccs_path_number_perm(CCS_TYPE_MKFIFO, dentry, mnt,
> -+					     perm);
> -+		break;
> -+	case S_IFSOCK:
> -+		error = ccs_path_number_perm(CCS_TYPE_MKSOCK, dentry, mnt,
> -+					     perm);
> -+		break;
> -+	case 0:
> -+	case S_IFREG:
> -+		error = ccs_path_number_perm(CCS_TYPE_CREATE, dentry, mnt,
> -+					     perm);
> -+		break;
> -+	}
> -+	return error;
> -+}
> -+
> -+/**
> -+ * __ccs_mkdir_permission - Check permission for vfs_mkdir().
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @mnt:    Pointer to "struct vfsmount". Maybe NULL.
> -+ * @mode:   Create mode.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_mkdir_permission(struct dentry *dentry, struct vfsmount *mnt,
> -+				  unsigned int mode)
> -+{
> -+	return ccs_path_number_perm(CCS_TYPE_MKDIR, dentry, mnt, mode);
> -+}
> -+
> -+/**
> -+ * __ccs_rmdir_permission - Check permission for vfs_rmdir().
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @mnt:    Pointer to "struct vfsmount". Maybe NULL.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_rmdir_permission(struct dentry *dentry, struct vfsmount *mnt)
> -+{
> -+	return ccs_path_perm(CCS_TYPE_RMDIR, dentry, mnt, NULL);
> -+}
> -+
> -+/**
> -+ * __ccs_unlink_permission - Check permission for vfs_unlink().
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @mnt:    Pointer to "struct vfsmount". Maybe NULL.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_unlink_permission(struct dentry *dentry, struct vfsmount *mnt)
> -+{
> -+	return ccs_path_perm(CCS_TYPE_UNLINK, dentry, mnt, NULL);
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+
> -+/**
> -+ * __ccs_getattr_permission - Check permission for vfs_getattr().
> -+ *
> -+ * @mnt:    Pointer to "struct vfsmount". Maybe NULL.
> -+ * @dentry: Pointer to "struct dentry".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_getattr_permission(struct vfsmount *mnt,
> -+				    struct dentry *dentry)
> -+{
> -+	return ccs_path_perm(CCS_TYPE_GETATTR, dentry, mnt, NULL);
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * __ccs_symlink_permission - Check permission for vfs_symlink().
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @mnt:    Pointer to "struct vfsmount". Maybe NULL.
> -+ * @from:   Content of symlink.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_symlink_permission(struct dentry *dentry,
> -+				    struct vfsmount *mnt, const char *from)
> -+{
> -+	return ccs_path_perm(CCS_TYPE_SYMLINK, dentry, mnt, from);
> -+}
> -+
> -+/**
> -+ * __ccs_truncate_permission - Check permission for notify_change().
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @mnt:    Pointer to "struct vfsmount". Maybe NULL.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_truncate_permission(struct dentry *dentry,
> -+				     struct vfsmount *mnt)
> -+{
> -+	return ccs_path_perm(CCS_TYPE_TRUNCATE, dentry, mnt, NULL);
> -+}
> -+
> -+/**
> -+ * __ccs_rename_permission - Check permission for vfs_rename().
> -+ *
> -+ * @old_dentry: Pointer to "struct dentry".
> -+ * @new_dentry: Pointer to "struct dentry".
> -+ * @mnt:        Pointer to "struct vfsmount". Maybe NULL.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_rename_permission(struct dentry *old_dentry,
> -+				   struct dentry *new_dentry,
> -+				   struct vfsmount *mnt)
> -+{
> -+	return ccs_path2_perm(CCS_TYPE_RENAME, old_dentry, mnt, new_dentry,
> -+			      mnt);
> -+}
> -+
> -+/**
> -+ * __ccs_link_permission - Check permission for vfs_link().
> -+ *
> -+ * @old_dentry: Pointer to "struct dentry".
> -+ * @new_dentry: Pointer to "struct dentry".
> -+ * @mnt:        Pointer to "struct vfsmount". Maybe NULL.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_link_permission(struct dentry *old_dentry,
> -+				 struct dentry *new_dentry,
> -+				 struct vfsmount *mnt)
> -+{
> -+	return ccs_path2_perm(CCS_TYPE_LINK, old_dentry, mnt, new_dentry, mnt);
> -+}
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
> -+
> -+/**
> -+ * __ccs_open_exec_permission - Check permission for open_exec().
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @mnt:    Pointer to "struct vfsmount".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_open_exec_permission(struct dentry *dentry,
> -+				      struct vfsmount *mnt)
> -+{
> -+	return (ccs_current_flags() & CCS_TASK_IS_IN_EXECVE) ?
> -+		__ccs_open_permission(dentry, mnt, O_RDONLY + 1) : 0;
> -+}
> -+
> -+/**
> -+ * __ccs_uselib_permission - Check permission for sys_uselib().
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @mnt:    Pointer to "struct vfsmount".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_uselib_permission(struct dentry *dentry, struct vfsmount *mnt)
> -+{
> -+	return __ccs_open_permission(dentry, mnt, O_RDONLY + 1);
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
> -+
> -+/**
> -+ * __ccs_parse_table - Check permission for parse_table().
> -+ *
> -+ * @name:   Pointer to "int __user".
> -+ * @nlen:   Number of elements in @name.
> -+ * @oldval: Pointer to "void __user".
> -+ * @newval: Pointer to "void __user".
> -+ * @table:  Pointer to "struct ctl_table".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Note that this function is racy because this function checks values in
> -+ * userspace memory which could be changed after permission check.
> -+ */
> -+static int __ccs_parse_table(int __user *name, int nlen, void __user *oldval,
> -+			     void __user *newval, struct ctl_table *table)
> -+{
> -+	int n;
> -+	int error = -ENOMEM;
> -+	int op = 0;
> -+	struct ccs_path_info buf;
> -+	char *buffer = NULL;
> -+	struct ccs_request_info r;
> -+	int idx;
> -+	if (oldval)
> -+		op |= 004;
> -+	if (newval)
> -+		op |= 002;
> -+	if (!op) /* Neither read nor write */
> -+		return 0;
> -+	idx = ccs_read_lock();
> -+	if (ccs_init_request_info(&r, CCS_MAC_FILE_OPEN)
> -+	    == CCS_CONFIG_DISABLED) {
> -+		error = 0;
> -+		goto out;
> -+	}
> -+	buffer = kmalloc(PAGE_SIZE, CCS_GFP_FLAGS);
> -+	if (!buffer)
> -+		goto out;
> -+	snprintf(buffer, PAGE_SIZE - 1, "proc:/sys");
> -+repeat:
> -+	if (!nlen) {
> -+		error = -ENOTDIR;
> -+		goto out;
> -+	}
> -+	if (get_user(n, name)) {
> -+		error = -EFAULT;
> -+		goto out;
> -+	}
> -+	for ( ; table->ctl_name
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)
> -+		      || table->procname
> -+#endif
> -+		      ; table++) {
> -+		int pos;
> -+		const char *cp;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21)
> -+		if (n != table->ctl_name && table->ctl_name != CTL_ANY)
> -+			continue;
> -+#else
> -+		if (!n || n != table->ctl_name)
> -+			continue;
> -+#endif
> -+		pos = strlen(buffer);
> -+		cp = table->procname;
> -+		error = -ENOMEM;
> -+		if (cp) {
> -+			int len = strlen(cp);
> -+			if (len + 2 > PAGE_SIZE - 1)
> -+				goto out;
> -+			buffer[pos++] = '/';
> -+			memmove(buffer + pos, cp, len + 1);
> -+		} else {
> -+			/* Assume nobody assigns "=\$=" for procname. */
> -+			snprintf(buffer + pos, PAGE_SIZE - pos - 1,
> -+				 "/=%d=", table->ctl_name);
> -+			if (!memchr(buffer, '\0', PAGE_SIZE - 2))
> -+				goto out;
> -+		}
> -+		if (!table->child)
> -+			goto no_child;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21)
> -+		if (!table->strategy)
> -+			goto no_strategy;
> -+		/* printk("sysctl='%s'\n", buffer); */
> -+		buf.name = ccs_encode(buffer);
> -+		if (!buf.name)
> -+			goto out;
> -+		ccs_fill_path_info(&buf);
> -+		if (op & MAY_READ)
> -+			error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
> -+		else
> -+			error = 0;
> -+		if (!error && (op & MAY_WRITE))
> -+			error = ccs_path_permission(&r, CCS_TYPE_WRITE, &buf);
> -+		kfree(buf.name);
> -+		if (error)
> -+			goto out;
> -+no_strategy:
> -+#endif
> -+		name++;
> -+		nlen--;
> -+		table = table->child;
> -+		goto repeat;
> -+no_child:
> -+		/* printk("sysctl='%s'\n", buffer); */
> -+		buf.name = ccs_encode(buffer);
> -+		if (!buf.name)
> -+			goto out;
> -+		ccs_fill_path_info(&buf);
> -+		if (op & MAY_READ)
> -+			error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
> -+		else
> -+			error = 0;
> -+		if (!error && (op & MAY_WRITE))
> -+			error = ccs_path_permission(&r, CCS_TYPE_WRITE, &buf);
> -+		kfree(buf.name);
> -+		goto out;
> -+	}
> -+	error = -ENOTDIR;
> -+out:
> -+	ccs_read_unlock(idx);
> -+	kfree(buffer);
> -+	return error;
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
> -+
> -+/**
> -+ * ccs_old_pivot_root_permission - Check permission for pivot_root().
> -+ *
> -+ * @old_nd: Pointer to "struct nameidata".
> -+ * @new_nd: Pointer to "struct nameidata".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_old_pivot_root_permission(struct nameidata *old_nd,
> -+					 struct nameidata *new_nd)
> -+{
> -+	struct path old_path = { old_nd->mnt, old_nd->dentry };
> -+	struct path new_path = { new_nd->mnt, new_nd->dentry };
> -+	return __ccs_pivot_root_permission(&old_path, &new_path);
> -+}
> -+
> -+/**
> -+ * ccs_old_chroot_permission - Check permission for chroot().
> -+ *
> -+ * @nd: Pointer to "struct nameidata".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_old_chroot_permission(struct nameidata *nd)
> -+{
> -+	struct path path = { nd->mnt, nd->dentry };
> -+	return __ccs_chroot_permission(&path);
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+
> -+/**
> -+ * ccs_address_matches_group - Check whether the given address matches members of the given address group.
> -+ *
> -+ * @is_ipv6: True if @address is an IPv6 address.
> -+ * @address: An IPv4 or IPv6 address.
> -+ * @group:   Pointer to "struct ccs_address_group".
> -+ *
> -+ * Returns true if @address matches addresses in @group group, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
> -+				      const struct ccs_group *group)
> -+{
> -+	struct ccs_address_group *member;
> -+	bool matched = false;
> -+	const u8 size = is_ipv6 ? 16 : 4;
> -+	list_for_each_entry_srcu(member, &group->member_list, head.list,
> -+				 &ccs_ss) {
> -+		if (member->head.is_deleted)
> -+			continue;
> -+		if (member->address.is_ipv6 != is_ipv6)
> -+			continue;
> -+		if (memcmp(&member->address.ip[0], address, size) > 0 ||
> -+		    memcmp(address, &member->address.ip[1], size) > 0)
> -+			continue;
> -+		matched = true;
> -+		break;
> -+	}
> -+	return matched;
> -+}
> -+
> -+/**
> -+ * ccs_check_inet_acl - Check permission for inet domain socket operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_inet_acl(struct ccs_request_info *r,
> -+			       const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_inet_acl *acl = container_of(ptr, typeof(*acl), head);
> -+	const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4;
> -+	if (!(ptr->perm & (1 << r->param.inet_network.operation)) ||
> -+	    !ccs_compare_number_union(r->param.inet_network.port, &acl->port))
> -+		return false;
> -+	if (acl->address.group)
> -+		return ccs_address_matches_group(r->param.inet_network.is_ipv6,
> -+						 r->param.inet_network.address,
> -+						 acl->address.group);
> -+	return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 &&
> -+		memcmp(&acl->address.ip[0],
> -+		       r->param.inet_network.address, size) <= 0 &&
> -+		memcmp(r->param.inet_network.address,
> -+		       &acl->address.ip[1], size) <= 0;
> -+}
> -+
> -+/**
> -+ * ccs_check_unix_acl - Check permission for unix domain socket operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_unix_acl(struct ccs_request_info *r,
> -+			       const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_unix_acl *acl = container_of(ptr, typeof(*acl), head);
> -+	return (ptr->perm & (1 << r->param.unix_network.operation)) &&
> -+		ccs_compare_name_union(r->param.unix_network.address,
> -+				       &acl->name);
> -+}
> -+
> -+/**
> -+ * ccs_inet_entry - Check permission for INET network operation.
> -+ *
> -+ * @address: Pointer to "struct ccs_addr_info".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_inet_entry(const struct ccs_addr_info *address)
> -+{
> -+	const int idx = ccs_read_lock();
> -+	struct ccs_request_info r;
> -+	int error = 0;
> -+	const u8 type = ccs_inet2mac[address->protocol][address->operation];
> -+	if (type && ccs_init_request_info(&r, type) != CCS_CONFIG_DISABLED) {
> -+		r.param_type = CCS_TYPE_INET_ACL;
> -+		r.param.inet_network.protocol = address->protocol;
> -+		r.param.inet_network.operation = address->operation;
> -+		r.param.inet_network.is_ipv6 = address->inet.is_ipv6;
> -+		r.param.inet_network.address = address->inet.address;
> -+		r.param.inet_network.port = ntohs(address->inet.port);
> -+		r.dont_sleep_on_enforce_error =
> -+			address->operation == CCS_NETWORK_ACCEPT
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+			|| address->operation == CCS_NETWORK_RECV
> -+#endif
> -+			;
> -+		error = ccs_check_acl(&r);
> -+	}
> -+	ccs_read_unlock(idx);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_check_inet_address - Check permission for inet domain socket's operation.
> -+ *
> -+ * @addr:     Pointer to "struct sockaddr".
> -+ * @addr_len: Size of @addr.
> -+ * @port:     Port number.
> -+ * @address:  Pointer to "struct ccs_addr_info".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_check_inet_address(const struct sockaddr *addr,
> -+				  const unsigned int addr_len, const u16 port,
> -+				  struct ccs_addr_info *address)
> -+{
> -+	struct ccs_inet_addr_info *i = &address->inet;
> -+	switch (addr->sa_family) {
> -+	case AF_INET6:
> -+		if (addr_len < SIN6_LEN_RFC2133)
> -+			goto skip;
> -+		i->is_ipv6 = true;
> -+		i->address = (u32 *)
> -+			((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
> -+		i->port = ((struct sockaddr_in6 *) addr)->sin6_port;
> -+		break;
> -+	case AF_INET:
> -+		if (addr_len < sizeof(struct sockaddr_in))
> -+			goto skip;
> -+		i->is_ipv6 = false;
> -+		i->address = (u32 *) &((struct sockaddr_in *) addr)->sin_addr;
> -+		i->port = ((struct sockaddr_in *) addr)->sin_port;
> -+		break;
> -+	default:
> -+		goto skip;
> -+	}
> -+	if (address->protocol == SOCK_RAW)
> -+		i->port = htons(port);
> -+	return ccs_inet_entry(address);
> -+skip:
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_unix_entry - Check permission for UNIX network operation.
> -+ *
> -+ * @address: Pointer to "struct ccs_addr_info".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_unix_entry(const struct ccs_addr_info *address)
> -+{
> -+	const int idx = ccs_read_lock();
> -+	struct ccs_request_info r;
> -+	int error = 0;
> -+	const u8 type = ccs_unix2mac[address->protocol][address->operation];
> -+	if (type && ccs_init_request_info(&r, type) != CCS_CONFIG_DISABLED) {
> -+		char *buf = address->unix0.addr;
> -+		int len = address->unix0.addr_len - sizeof(sa_family_t);
> -+		if (len <= 0) {
> -+			buf = "anonymous";
> -+			len = 9;
> -+		} else if (buf[0]) {
> -+			len = strnlen(buf, len);
> -+		}
> -+		buf = ccs_encode2(buf, len);
> -+		if (buf) {
> -+			struct ccs_path_info addr;
> -+			addr.name = buf;
> -+			ccs_fill_path_info(&addr);
> -+			r.param_type = CCS_TYPE_UNIX_ACL;
> -+			r.param.unix_network.protocol = address->protocol;
> -+			r.param.unix_network.operation = address->operation;
> -+			r.param.unix_network.address = &addr;
> -+			r.dont_sleep_on_enforce_error =
> -+				address->operation == CCS_NETWORK_ACCEPT
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+				|| address->operation == CCS_NETWORK_RECV
> -+#endif
> -+				;
> -+			error = ccs_check_acl(&r);
> -+			kfree(buf);
> -+		} else
> -+			error = -ENOMEM;
> -+	}
> -+	ccs_read_unlock(idx);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_check_unix_address - Check permission for unix domain socket's operation.
> -+ *
> -+ * @addr:     Pointer to "struct sockaddr".
> -+ * @addr_len: Size of @addr.
> -+ * @address:  Pointer to "struct ccs_addr_info".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_check_unix_address(struct sockaddr *addr,
> -+				  const unsigned int addr_len,
> -+				  struct ccs_addr_info *address)
> -+{
> -+	struct ccs_unix_addr_info *u = &address->unix0;
> -+	if (addr->sa_family != AF_UNIX)
> -+		return 0;
> -+	u->addr = ((struct sockaddr_un *) addr)->sun_path;
> -+	u->addr_len = addr_len;
> -+	return ccs_unix_entry(address);
> -+}
> -+
> -+/**
> -+ * ccs_sock_family - Get socket's family.
> -+ *
> -+ * @sk: Pointer to "struct sock".
> -+ *
> -+ * Returns one of PF_INET, PF_INET6, PF_UNIX or 0.
> -+ */
> -+static u8 ccs_sock_family(struct sock *sk)
> -+{
> -+	u8 family;
> -+	if (ccs_kernel_service())
> -+		return 0;
> -+	family = sk->sk_family;
> -+	switch (family) {
> -+	case PF_INET:
> -+	case PF_INET6:
> -+	case PF_UNIX:
> -+		return family;
> -+	default:
> -+		return 0;
> -+	}
> -+}
> -+
> -+/**
> -+ * __ccs_socket_listen_permission - Check permission for listening a socket.
> -+ *
> -+ * @sock: Pointer to "struct socket".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_socket_listen_permission(struct socket *sock)
> -+{
> -+	struct ccs_addr_info address;
> -+	const u8 family = ccs_sock_family(sock->sk);
> -+	const unsigned int type = sock->type;
> -+	struct sockaddr_storage addr;
> -+	int addr_len;
> -+	if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
> -+		return 0;
> -+	{
> -+		const int error = sock->ops->getname(sock, (struct sockaddr *)
> -+						     &addr, &addr_len, 0);
> -+		if (error)
> -+			return error;
> -+	}
> -+	address.protocol = type;
> -+	address.operation = CCS_NETWORK_LISTEN;
> -+	if (family == PF_UNIX)
> -+		return ccs_check_unix_address((struct sockaddr *) &addr,
> -+					      addr_len, &address);
> -+	return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
> -+				      &address);
> -+}
> -+
> -+/**
> -+ * __ccs_socket_connect_permission - Check permission for setting the remote address of a socket.
> -+ *
> -+ * @sock:     Pointer to "struct socket".
> -+ * @addr:     Pointer to "struct sockaddr".
> -+ * @addr_len: Size of @addr.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_socket_connect_permission(struct socket *sock,
> -+					   struct sockaddr *addr, int addr_len)
> -+{
> -+	struct ccs_addr_info address;
> -+	const u8 family = ccs_sock_family(sock->sk);
> -+	const unsigned int type = sock->type;
> -+	if (!family)
> -+		return 0;
> -+	address.protocol = type;
> -+	switch (type) {
> -+	case SOCK_DGRAM:
> -+	case SOCK_RAW:
> -+		address.operation = CCS_NETWORK_SEND;
> -+		break;
> -+	case SOCK_STREAM:
> -+	case SOCK_SEQPACKET:
> -+		address.operation = CCS_NETWORK_CONNECT;
> -+		break;
> -+	default:
> -+		return 0;
> -+	}
> -+	if (family == PF_UNIX)
> -+		return ccs_check_unix_address(addr, addr_len, &address);
> -+	return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
> -+				      &address);
> -+}
> -+
> -+/**
> -+ * __ccs_socket_bind_permission - Check permission for setting the local address of a socket.
> -+ *
> -+ * @sock:     Pointer to "struct socket".
> -+ * @addr:     Pointer to "struct sockaddr".
> -+ * @addr_len: Size of @addr.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_socket_bind_permission(struct socket *sock,
> -+					struct sockaddr *addr, int addr_len)
> -+{
> -+	struct ccs_addr_info address;
> -+	const u8 family = ccs_sock_family(sock->sk);
> -+	const unsigned int type = sock->type;
> -+	if (!family)
> -+		return 0;
> -+	switch (type) {
> -+	case SOCK_STREAM:
> -+	case SOCK_DGRAM:
> -+	case SOCK_RAW:
> -+	case SOCK_SEQPACKET:
> -+		address.protocol = type;
> -+		address.operation = CCS_NETWORK_BIND;
> -+		break;
> -+	default:
> -+		return 0;
> -+	}
> -+	if (family == PF_UNIX)
> -+		return ccs_check_unix_address(addr, addr_len, &address);
> -+	return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
> -+				      &address);
> -+}
> -+
> -+/**
> -+ * __ccs_socket_sendmsg_permission - Check permission for sending a datagram.
> -+ *
> -+ * @sock: Pointer to "struct socket".
> -+ * @msg:  Pointer to "struct msghdr".
> -+ * @size: Unused.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_socket_sendmsg_permission(struct socket *sock,
> -+					   struct msghdr *msg, int size)
> -+{
> -+	struct ccs_addr_info address;
> -+	const u8 family = ccs_sock_family(sock->sk);
> -+	const unsigned int type = sock->type;
> -+	if (!msg->msg_name || !family ||
> -+	    (type != SOCK_DGRAM && type != SOCK_RAW))
> -+		return 0;
> -+	address.protocol = type;
> -+	address.operation = CCS_NETWORK_SEND;
> -+	if (family == PF_UNIX)
> -+		return ccs_check_unix_address((struct sockaddr *)
> -+					      msg->msg_name, msg->msg_namelen,
> -+					      &address);
> -+	return ccs_check_inet_address((struct sockaddr *) msg->msg_name,
> -+				      msg->msg_namelen, sock->sk->sk_protocol,
> -+				      &address);
> -+}
> -+
> -+/**
> -+ * __ccs_socket_post_accept_permission - Check permission for accepting a socket.
> -+ *
> -+ * @sock:    Pointer to "struct socket".
> -+ * @newsock: Pointer to "struct socket".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_socket_post_accept_permission(struct socket *sock,
> -+					       struct socket *newsock)
> -+{
> -+	struct ccs_addr_info address;
> -+	const u8 family = ccs_sock_family(sock->sk);
> -+	const unsigned int type = sock->type;
> -+	struct sockaddr_storage addr;
> -+	int addr_len;
> -+	if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
> -+		return 0;
> -+	{
> -+		const int error = newsock->ops->getname(newsock,
> -+							(struct sockaddr *)
> -+							&addr, &addr_len, 2);
> -+		if (error)
> -+			return error;
> -+	}
> -+	address.protocol = type;
> -+	address.operation = CCS_NETWORK_ACCEPT;
> -+	if (family == PF_UNIX)
> -+		return ccs_check_unix_address((struct sockaddr *) &addr,
> -+					      addr_len, &address);
> -+	return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
> -+				      &address);
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+
> -+/**
> -+ * __ccs_socket_post_recvmsg_permission - Check permission for receiving a datagram.
> -+ *
> -+ * @sk:    Pointer to "struct sock".
> -+ * @skb:   Pointer to "struct sk_buff".
> -+ * @flags: Flags passed to skb_recv_datagram().
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_socket_post_recvmsg_permission(struct sock *sk,
> -+						struct sk_buff *skb, int flags)
> -+{
> -+	struct ccs_addr_info address;
> -+	const u8 family = ccs_sock_family(sk);
> -+	const unsigned int type = sk->sk_type;
> -+	struct sockaddr_storage addr;
> -+	if (!family)
> -+		return 0;
> -+	switch (type) {
> -+	case SOCK_DGRAM:
> -+	case SOCK_RAW:
> -+		address.protocol = type;
> -+		break;
> -+	default:
> -+		return 0;
> -+	}
> -+	address.operation = CCS_NETWORK_RECV;
> -+	switch (family) {
> -+	case PF_INET6:
> -+		{
> -+			struct in6_addr *sin6 = (struct in6_addr *) &addr;
> -+			address.inet.is_ipv6 = true;
> -+			if (type == SOCK_DGRAM &&
> -+			    skb->protocol == htons(ETH_P_IP))
> -+				ipv6_addr_set(sin6, 0, 0, htonl(0xffff),
> -+					      ip_hdr(skb)->saddr);
> -+			else
> -+				*sin6 = ipv6_hdr(skb)->saddr;
> -+			break;
> -+		}
> -+	case PF_INET:
> -+		{
> -+			struct in_addr *sin4 = (struct in_addr *) &addr;
> -+			address.inet.is_ipv6 = false;
> -+			sin4->s_addr = ip_hdr(skb)->saddr;
> -+			break;
> -+		}
> -+	default: /* == PF_UNIX */
> -+		{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+			struct unix_address *u = unix_sk(skb->sk)->addr;
> -+#else
> -+			struct unix_address *u =
> -+				skb->sk->protinfo.af_unix.addr;
> -+#endif
> -+			unsigned int addr_len;
> -+			if (u && u->len <= sizeof(addr)) {
> -+				addr_len = u->len;
> -+				memcpy(&addr, u->name, addr_len);
> -+			} else {
> -+				addr_len = 0;
> -+				addr.ss_family = AF_UNIX;
> -+			}
> -+			if (ccs_check_unix_address((struct sockaddr *) &addr,
> -+						   addr_len, &address))
> -+				goto out;
> -+			return 0;
> -+		}
> -+	}
> -+	address.inet.address = (u32 *) &addr;
> -+	if (type == SOCK_DGRAM)
> -+		address.inet.port = udp_hdr(skb)->source;
> -+	else
> -+		address.inet.port = htons(sk->sk_protocol);
> -+	if (ccs_inet_entry(&address))
> -+		goto out;
> -+	return 0;
> -+out:
> -+	/*
> -+	 * Remove from queue if MSG_PEEK is used so that
> -+	 * the head message from unwanted source in receive queue will not
> -+	 * prevent the caller from picking up next message from wanted source
> -+	 * when the caller is using MSG_PEEK flag for picking up.
> -+	 */
> -+	{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
> -+		bool slow = false;
> -+		if (type == SOCK_DGRAM && family != PF_UNIX)
> -+			slow = lock_sock_fast(sk);
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+		if (type == SOCK_DGRAM && family != PF_UNIX)
> -+			lock_sock(sk);
> -+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 2
> -+		if (type == SOCK_DGRAM && family != PF_UNIX)
> -+			lock_sock(sk);
> -+#endif
> -+		skb_kill_datagram(sk, skb, flags);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
> -+		if (type == SOCK_DGRAM && family != PF_UNIX)
> -+			unlock_sock_fast(sk, slow);
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+		if (type == SOCK_DGRAM && family != PF_UNIX)
> -+			release_sock(sk);
> -+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 2
> -+		if (type == SOCK_DGRAM && family != PF_UNIX)
> -+			release_sock(sk);
> -+#endif
> -+	}
> -+	return -EPERM;
> -+}
> -+
> -+#endif
> -+
> -+#endif
> -+
> -+#if defined(CONFIG_CCSECURITY_CAPABILITY) || defined(CONFIG_CCSECURITY_NETWORK)
> -+
> -+/**
> -+ * ccs_kernel_service - Check whether I'm kernel service or not.
> -+ *
> -+ * Returns true if I'm kernel service, false otherwise.
> -+ */
> -+static bool ccs_kernel_service(void)
> -+{
> -+	/* Nothing to do if I am a kernel service. */
> -+	return segment_eq(get_fs(), KERNEL_DS);
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+
> -+/**
> -+ * ccs_check_capability_acl - Check permission for capability operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_capability_acl(struct ccs_request_info *r,
> -+				     const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_capability_acl *acl =
> -+		container_of(ptr, typeof(*acl), head);
> -+	return acl->operation == r->param.capability.operation;
> -+}
> -+
> -+/**
> -+ * ccs_capable - Check permission for capability.
> -+ *
> -+ * @operation: Type of operation.
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool __ccs_capable(const u8 operation)
> -+{
> -+	struct ccs_request_info r;
> -+	int error = 0;
> -+	const int idx = ccs_read_lock();
> -+	if (ccs_init_request_info(&r, ccs_c2mac[operation])
> -+	    != CCS_CONFIG_DISABLED) {
> -+		r.param_type = CCS_TYPE_CAPABILITY_ACL;
> -+		r.param.capability.operation = operation;
> -+		error = ccs_check_acl(&r);
> -+	}
> -+	ccs_read_unlock(idx);
> -+	return !error;
> -+}
> -+
> -+/**
> -+ * __ccs_socket_create_permission - Check permission for creating a socket.
> -+ *
> -+ * @family:   Protocol family.
> -+ * @type:     Unused.
> -+ * @protocol: Unused.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __ccs_socket_create_permission(int family, int type, int protocol)
> -+{
> -+	if (ccs_kernel_service())
> -+		return 0;
> -+	if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
> -+		return -EPERM;
> -+	if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
> -+		return -EPERM;
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * __ccs_ptrace_permission - Check permission for ptrace().
> -+ *
> -+ * @request: Unused.
> -+ * @pid:     Unused.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Since this function is called from location where it is permitted to sleep,
> -+ * it is racy to check target process's domainname anyway. Therefore, we don't
> -+ * use target process's domainname.
> -+ */
> -+static int __ccs_ptrace_permission(long request, long pid)
> -+{
> -+	return __ccs_capable(CCS_SYS_PTRACE) ? 0 : -EPERM;
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+
> -+/**
> -+ * ccs_check_signal_acl - Check permission for signal operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_signal_acl(struct ccs_request_info *r,
> -+				 const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_signal_acl *acl =
> -+		container_of(ptr, typeof(*acl), head);
> -+	if (ccs_compare_number_union(r->param.signal.sig, &acl->sig)) {
> -+		const int len = acl->domainname->total_len;
> -+		if (!strncmp(acl->domainname->name,
> -+			     r->param.signal.dest_pattern, len)) {
> -+			switch (r->param.signal.dest_pattern[len]) {
> -+			case ' ':
> -+			case '\0':
> -+				return true;
> -+			}
> -+		}
> -+	}
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_signal_acl2 - Check permission for signal.
> -+ *
> -+ * @sig: Signal number.
> -+ * @pid: Target's PID.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_signal_acl2(const int sig, const int pid)
> -+{
> -+	struct ccs_request_info r;
> -+	struct ccs_domain_info *dest = NULL;
> -+	const struct ccs_domain_info * const domain = ccs_current_domain();
> -+	if (ccs_init_request_info(&r, CCS_MAC_SIGNAL) == CCS_CONFIG_DISABLED)
> -+		return 0;
> -+	if (!sig)
> -+		return 0;                /* No check for NULL signal. */
> -+	r.param_type = CCS_TYPE_SIGNAL_ACL;
> -+	r.param.signal.sig = sig;
> -+	r.param.signal.dest_pattern = domain->domainname->name;
> -+	r.granted = true;
> -+	if (ccs_sys_getpid() == pid) {
> -+		ccs_audit_log(&r);
> -+		return 0;                /* No check for self process. */
> -+	}
> -+	{ /* Simplified checking. */
> -+		struct task_struct *p = NULL;
> -+		ccs_tasklist_lock();
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
> -+		if (pid > 0)
> -+			p = ccsecurity_exports.find_task_by_vpid((pid_t) pid);
> -+		else if (pid == 0)
> -+			p = current;
> -+		else if (pid == -1)
> -+			dest = &ccs_kernel_domain;
> -+		else
> -+			p = ccsecurity_exports.find_task_by_vpid((pid_t) -pid);
> -+#else
> -+		if (pid > 0)
> -+			p = find_task_by_pid((pid_t) pid);
> -+		else if (pid == 0)
> -+			p = current;
> -+		else if (pid == -1)
> -+			dest = &ccs_kernel_domain;
> -+		else
> -+			p = find_task_by_pid((pid_t) -pid);
> -+#endif
> -+		if (p)
> -+			dest = ccs_task_domain(p);
> -+		ccs_tasklist_unlock();
> -+	}
> -+	if (!dest)
> -+		return 0; /* I can't find destinatioin. */
> -+	if (domain == dest) {
> -+		ccs_audit_log(&r);
> -+		return 0;                /* No check for self domain. */
> -+	}
> -+	r.param.signal.dest_pattern = dest->domainname->name;
> -+	return ccs_check_acl(&r);
> -+}
> -+
> -+/**
> -+ * ccs_signal_acl - Check permission for signal.
> -+ *
> -+ * @pid: Target's PID.
> -+ * @sig: Signal number.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_signal_acl(const int pid, const int sig)
> -+{
> -+	int error;
> -+	if (!sig)
> -+		error = 0;
> -+	else {
> -+		const int idx = ccs_read_lock();
> -+		error = ccs_signal_acl2(sig, pid);
> -+		ccs_read_unlock(idx);
> -+	}
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_signal_acl0 - Permission check for signal().
> -+ *
> -+ * @tgid: Unused.
> -+ * @pid:  Target's PID.
> -+ * @sig:  Signal number.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_signal_acl0(pid_t tgid, pid_t pid, int sig)
> -+{
> -+	return ccs_signal_acl(pid, sig);
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+
> -+/**
> -+ * ccs_check_env_acl - Check permission for environment variable's name.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_env_acl(struct ccs_request_info *r,
> -+			      const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_env_acl *acl = container_of(ptr, typeof(*acl), head);
> -+	return ccs_path_matches_pattern(r->param.environ.name, acl->env);
> -+}
> -+
> -+/**
> -+ * ccs_env_perm - Check permission for environment variable's name.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @env: The name of environment variable.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_env_perm(struct ccs_request_info *r, const char *env)
> -+{
> -+	struct ccs_path_info environ;
> -+	if (!env || !*env)
> -+		return 0;
> -+	environ.name = env;
> -+	ccs_fill_path_info(&environ);
> -+	r->param_type = CCS_TYPE_ENV_ACL;
> -+	r->param.environ.name = &environ;
> -+	return ccs_check_acl(r);
> -+}
> -+
> -+/**
> -+ * ccs_environ - Check permission for environment variable names.
> -+ *
> -+ * @ee: Pointer to "struct ccs_execve".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_environ(struct ccs_execve *ee)
> -+{
> -+	struct ccs_request_info *r = &ee->r;
> -+	struct linux_binprm *bprm = ee->bprm;
> -+	/* env_page.data is allocated by ccs_dump_page(). */
> -+	struct ccs_page_dump env_page = { };
> -+	char *arg_ptr; /* Size is CCS_EXEC_TMPSIZE bytes */
> -+	int arg_len = 0;
> -+	unsigned long pos = bprm->p;
> -+	int offset = pos % PAGE_SIZE;
> -+	int argv_count = bprm->argc;
> -+	int envp_count = bprm->envc;
> -+	/* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
> -+	int error = -ENOMEM;
> -+	ee->r.type = CCS_MAC_ENVIRON;
> -+	ee->r.profile = ccs_current_domain()->profile;
> -+	ee->r.mode = ccs_get_mode(ee->r.profile, CCS_MAC_ENVIRON);
> -+	if (!r->mode || !envp_count)
> -+		return 0;
> -+	arg_ptr = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
> -+	if (!arg_ptr)
> -+		goto out;
> -+	while (error == -ENOMEM) {
> -+		if (!ccs_dump_page(bprm, pos, &env_page))
> -+			goto out;
> -+		pos += PAGE_SIZE - offset;
> -+		/* Read. */
> -+		while (argv_count && offset < PAGE_SIZE) {
> -+			if (!env_page.data[offset++])
> -+				argv_count--;
> -+		}
> -+		if (argv_count) {
> -+			offset = 0;
> -+			continue;
> -+		}
> -+		while (offset < PAGE_SIZE) {
> -+			const unsigned char c = env_page.data[offset++];
> -+			if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
> -+				if (c == '=') {
> -+					arg_ptr[arg_len++] = '\0';
> -+				} else if (c == '\\') {
> -+					arg_ptr[arg_len++] = '\\';
> -+					arg_ptr[arg_len++] = '\\';
> -+				} else if (c > ' ' && c < 127) {
> -+					arg_ptr[arg_len++] = c;
> -+				} else {
> -+					arg_ptr[arg_len++] = '\\';
> -+					arg_ptr[arg_len++] = (c >> 6) + '0';
> -+					arg_ptr[arg_len++]
> -+						= ((c >> 3) & 7) + '0';
> -+					arg_ptr[arg_len++] = (c & 7) + '0';
> -+				}
> -+			} else {
> -+				arg_ptr[arg_len] = '\0';
> -+			}
> -+			if (c)
> -+				continue;
> -+			if (ccs_env_perm(r, arg_ptr)) {
> -+				error = -EPERM;
> -+				break;
> -+			}
> -+			if (!--envp_count) {
> -+				error = 0;
> -+				break;
> -+			}
> -+			arg_len = 0;
> -+		}
> -+		offset = 0;
> -+	}
> -+out:
> -+	if (r->mode != CCS_CONFIG_ENFORCING)
> -+		error = 0;
> -+	kfree(env_page.data);
> -+	kfree(arg_ptr);
> -+	return error;
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_argv - Check argv[] in "struct linux_binbrm".
> -+ *
> -+ * @index:   Index number of @arg_ptr.
> -+ * @arg_ptr: Contents of argv[@index].
> -+ * @argc:    Length of @argv.
> -+ * @argv:    Pointer to "struct ccs_argv".
> -+ * @checked: Set to true if @argv[@index] was found.
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_argv(const unsigned int index, const char *arg_ptr,
> -+		     const int argc, const struct ccs_argv *argv,
> -+		     u8 *checked)
> -+{
> -+	int i;
> -+	struct ccs_path_info arg;
> -+	arg.name = arg_ptr;
> -+	for (i = 0; i < argc; argv++, checked++, i++) {
> -+		bool result;
> -+		if (index != argv->index)
> -+			continue;
> -+		*checked = 1;
> -+		ccs_fill_path_info(&arg);
> -+		result = ccs_path_matches_pattern(&arg, argv->value);
> -+		if (argv->is_not)
> -+			result = !result;
> -+		if (!result)
> -+			return false;
> -+	}
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_envp - Check envp[] in "struct linux_binbrm".
> -+ *
> -+ * @env_name:  The name of environment variable.
> -+ * @env_value: The value of environment variable.
> -+ * @envc:      Length of @envp.
> -+ * @envp:      Pointer to "struct ccs_envp".
> -+ * @checked:   Set to true if @envp[@env_name] was found.
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_envp(const char *env_name, const char *env_value,
> -+		     const int envc, const struct ccs_envp *envp,
> -+		     u8 *checked)
> -+{
> -+	int i;
> -+	struct ccs_path_info name;
> -+	struct ccs_path_info value;
> -+	name.name = env_name;
> -+	ccs_fill_path_info(&name);
> -+	value.name = env_value;
> -+	ccs_fill_path_info(&value);
> -+	for (i = 0; i < envc; envp++, checked++, i++) {
> -+		bool result;
> -+		if (!ccs_path_matches_pattern(&name, envp->name))
> -+			continue;
> -+		*checked = 1;
> -+		if (envp->value) {
> -+			result = ccs_path_matches_pattern(&value, envp->value);
> -+			if (envp->is_not)
> -+				result = !result;
> -+		} else {
> -+			result = true;
> -+			if (!envp->is_not)
> -+				result = !result;
> -+		}
> -+		if (!result)
> -+			return false;
> -+	}
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_scan_bprm - Scan "struct linux_binprm".
> -+ *
> -+ * @ee:   Pointer to "struct ccs_execve".
> -+ * @argc: Length of @argc.
> -+ * @argv: Pointer to "struct ccs_argv".
> -+ * @envc: Length of @envp.
> -+ * @envp: Poiner to "struct ccs_envp".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_scan_bprm(struct ccs_execve *ee,
> -+			  const u16 argc, const struct ccs_argv *argv,
> -+			  const u16 envc, const struct ccs_envp *envp)
> -+{
> -+	struct linux_binprm *bprm = ee->bprm;
> -+	struct ccs_page_dump *dump = &ee->dump;
> -+	char *arg_ptr = ee->tmp;
> -+	int arg_len = 0;
> -+	unsigned long pos = bprm->p;
> -+	int offset = pos % PAGE_SIZE;
> -+	int argv_count = bprm->argc;
> -+	int envp_count = bprm->envc;
> -+	bool result = true;
> -+	u8 local_checked[32];
> -+	u8 *checked;
> -+	if (argc + envc <= sizeof(local_checked)) {
> -+		checked = local_checked;
> -+		memset(local_checked, 0, sizeof(local_checked));
> -+	} else {
> -+		checked = kzalloc(argc + envc, CCS_GFP_FLAGS);
> -+		if (!checked)
> -+			return false;
> -+	}
> -+	while (argv_count || envp_count) {
> -+		if (!ccs_dump_page(bprm, pos, dump)) {
> -+			result = false;
> -+			goto out;
> -+		}
> -+		pos += PAGE_SIZE - offset;
> -+		while (offset < PAGE_SIZE) {
> -+			/* Read. */
> -+			const char *kaddr = dump->data;
> -+			const unsigned char c = kaddr[offset++];
> -+			if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
> -+				if (c == '\\') {
> -+					arg_ptr[arg_len++] = '\\';
> -+					arg_ptr[arg_len++] = '\\';
> -+				} else if (c > ' ' && c < 127) {
> -+					arg_ptr[arg_len++] = c;
> -+				} else {
> -+					arg_ptr[arg_len++] = '\\';
> -+					arg_ptr[arg_len++] = (c >> 6) + '0';
> -+					arg_ptr[arg_len++] =
> -+						((c >> 3) & 7) + '0';
> -+					arg_ptr[arg_len++] = (c & 7) + '0';
> -+				}
> -+			} else {
> -+				arg_ptr[arg_len] = '\0';
> -+			}
> -+			if (c)
> -+				continue;
> -+			/* Check. */
> -+			if (argv_count) {
> -+				if (!ccs_argv(bprm->argc - argv_count,
> -+					      arg_ptr, argc, argv,
> -+					      checked)) {
> -+					result = false;
> -+					break;
> -+				}
> -+				argv_count--;
> -+			} else if (envp_count) {
> -+				char *cp = strchr(arg_ptr, '=');
> -+				if (cp) {
> -+					*cp = '\0';
> -+					if (!ccs_envp(arg_ptr, cp + 1,
> -+						      envc, envp,
> -+						      checked + argc)) {
> -+						result = false;
> -+						break;
> -+					}
> -+				}
> -+				envp_count--;
> -+			} else {
> -+				break;
> -+			}
> -+			arg_len = 0;
> -+		}
> -+		offset = 0;
> -+		if (!result)
> -+			break;
> -+	}
> -+out:
> -+	if (result) {
> -+		int i;
> -+		/* Check not-yet-checked entries. */
> -+		for (i = 0; i < argc; i++) {
> -+			if (checked[i])
> -+				continue;
> -+			/*
> -+			 * Return true only if all unchecked indexes in
> -+			 * bprm->argv[] are not matched.
> -+			 */
> -+			if (argv[i].is_not)
> -+				continue;
> -+			result = false;
> -+			break;
> -+		}
> -+		for (i = 0; i < envc; envp++, i++) {
> -+			if (checked[argc + i])
> -+				continue;
> -+			/*
> -+			 * Return true only if all unchecked environ variables
> -+			 * in bprm->envp[] are either undefined or not matched.
> -+			 */
> -+			if ((!envp->value && !envp->is_not) ||
> -+			    (envp->value && envp->is_not))
> -+				continue;
> -+			result = false;
> -+			break;
> -+		}
> -+	}
> -+	if (checked != local_checked)
> -+		kfree(checked);
> -+	return result;
> -+}
> -+
> -+/**
> -+ * ccs_scan_exec_realpath - Check "exec.realpath" parameter of "struct ccs_condition".
> -+ *
> -+ * @file:  Pointer to "struct file".
> -+ * @ptr:   Pointer to "struct ccs_name_union".
> -+ * @match: True if "exec.realpath=", false if "exec.realpath!=".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_scan_exec_realpath(struct file *file,
> -+				   const struct ccs_name_union *ptr,
> -+				   const bool match)
> -+{
> -+	bool result;
> -+	struct ccs_path_info exe;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> -+	struct path path;
> -+#endif
> -+	if (!file)
> -+		return false;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
> -+	exe.name = ccs_realpath(&file->f_path);
> -+#else
> -+	path.mnt = file->f_vfsmnt;
> -+	path.dentry = file->f_dentry;
> -+	exe.name = ccs_realpath(&path);
> -+#endif
> -+	if (!exe.name)
> -+		return false;
> -+	ccs_fill_path_info(&exe);
> -+	result = ccs_compare_name_union(&exe, ptr);
> -+	kfree(exe.name);
> -+	return result == match;
> -+}
> -+
> -+/**
> -+ * ccs_get_attributes - Revalidate "struct inode".
> -+ *
> -+ * @obj: Pointer to "struct ccs_obj_info".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+void ccs_get_attributes(struct ccs_obj_info *obj)
> -+{
> -+	u8 i;
> -+	struct dentry *dentry = NULL;
> -+
> -+	for (i = 0; i < CCS_MAX_PATH_STAT; i++) {
> -+		struct inode *inode;
> -+		switch (i) {
> -+		case CCS_PATH1:
> -+			dentry = obj->path1.dentry;
> -+			if (!dentry)
> -+				continue;
> -+			break;
> -+		case CCS_PATH2:
> -+			dentry = obj->path2.dentry;
> -+			if (!dentry)
> -+				continue;
> -+			break;
> -+		default:
> -+			if (!dentry)
> -+				continue;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+			spin_lock(&dcache_lock);
> -+			dentry = dget(dentry->d_parent);
> -+			spin_unlock(&dcache_lock);
> -+#else
> -+			dentry = dget_parent(dentry);
> -+#endif
> -+			break;
> -+		}
> -+		inode = dentry->d_inode;
> -+		if (inode) {
> -+			struct ccs_mini_stat *stat = &obj->stat[i];
> -+			stat->uid  = inode->i_uid;
> -+			stat->gid  = inode->i_gid;
> -+			stat->ino  = inode->i_ino;
> -+			stat->mode = inode->i_mode;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+			stat->dev  = inode->i_dev;
> -+#else
> -+			stat->dev  = inode->i_sb->s_dev;
> -+#endif
> -+			stat->rdev = inode->i_rdev;
> -+			obj->stat_valid[i] = true;
> -+		}
> -+		if (i & 1) /* i == CCS_PATH1_PARENT || i == CCS_PATH2_PARENT */
> -+			dput(dentry);
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_condition - Check condition part.
> -+ *
> -+ * @r:    Pointer to "struct ccs_request_info".
> -+ * @cond: Pointer to "struct ccs_condition". Maybe NULL.
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_condition(struct ccs_request_info *r,
> -+			  const struct ccs_condition *cond)
> -+{
> -+	const u32 ccs_flags = ccs_current_flags();
> -+	u32 i;
> -+	unsigned long min_v[2] = { 0, 0 };
> -+	unsigned long max_v[2] = { 0, 0 };
> -+	const struct ccs_condition_element *condp;
> -+	const struct ccs_number_union *numbers_p;
> -+	const struct ccs_name_union *names_p;
> -+	const struct ccs_argv *argv;
> -+	const struct ccs_envp *envp;
> -+	struct ccs_obj_info *obj;
> -+	u16 condc;
> -+	u16 argc;
> -+	u16 envc;
> -+	struct linux_binprm *bprm = NULL;
> -+	if (!cond)
> -+		return true;
> -+	condc = cond->condc;
> -+	argc = cond->argc;
> -+	envc = cond->envc;
> -+	obj = r->obj;
> -+	if (r->ee)
> -+		bprm = r->ee->bprm;
> -+	if (!bprm && (argc || envc))
> -+		return false;
> -+	condp = (struct ccs_condition_element *) (cond + 1);
> -+	numbers_p = (const struct ccs_number_union *) (condp + condc);
> -+	names_p = (const struct ccs_name_union *)
> -+		(numbers_p + cond->numbers_count);
> -+	argv = (const struct ccs_argv *) (names_p + cond->names_count);
> -+	envp = (const struct ccs_envp *) (argv + argc);
> -+	for (i = 0; i < condc; i++) {
> -+		const bool match = condp->equals;
> -+		const u8 left = condp->left;
> -+		const u8 right = condp->right;
> -+		bool is_bitop[2] = { false, false };
> -+		u8 j;
> -+		condp++;
> -+		/* Check argv[] and envp[] later. */
> -+		if (left == CCS_ARGV_ENTRY || left == CCS_ENVP_ENTRY)
> -+			continue;
> -+		/* Check string expressions. */
> -+		if (right == CCS_NAME_UNION) {
> -+			const struct ccs_name_union *ptr = names_p++;
> -+			switch (left) {
> -+				struct ccs_path_info *symlink;
> -+				struct ccs_execve *ee;
> -+				struct file *file;
> -+			case CCS_SYMLINK_TARGET:
> -+				symlink = obj ? obj->symlink_target : NULL;
> -+				if (!symlink ||
> -+				    !ccs_compare_name_union(symlink, ptr)
> -+				    == match)
> -+					goto out;
> -+				break;
> -+			case CCS_EXEC_REALPATH:
> -+				ee = r->ee;
> -+				file = ee ? ee->bprm->file : NULL;
> -+				if (!ccs_scan_exec_realpath(file, ptr, match))
> -+					goto out;
> -+				break;
> -+			}
> -+			continue;
> -+		}
> -+		/* Check numeric or bit-op expressions. */
> -+		for (j = 0; j < 2; j++) {
> -+			const u8 index = j ? right : left;
> -+			unsigned long value = 0;
> -+			switch (index) {
> -+			case CCS_TASK_UID:
> -+				value = from_kuid(&init_user_ns,
> -+						  current_uid());
> -+				break;
> -+			case CCS_TASK_EUID:
> -+				value = from_kuid(&init_user_ns,
> -+						  current_euid());
> -+				break;
> -+			case CCS_TASK_SUID:
> -+				value = from_kuid(&init_user_ns,
> -+						  current_suid());
> -+				break;
> -+			case CCS_TASK_FSUID:
> -+				value = from_kuid(&init_user_ns,
> -+						  current_fsuid());
> -+				break;
> -+			case CCS_TASK_GID:
> -+				value = from_kgid(&init_user_ns,
> -+						  current_gid());
> -+				break;
> -+			case CCS_TASK_EGID:
> -+				value = from_kgid(&init_user_ns,
> -+						  current_egid());
> -+				break;
> -+			case CCS_TASK_SGID:
> -+				value = from_kgid(&init_user_ns,
> -+						  current_sgid());
> -+				break;
> -+			case CCS_TASK_FSGID:
> -+				value = from_kgid(&init_user_ns,
> -+						  current_fsgid());
> -+				break;
> -+			case CCS_TASK_PID:
> -+				value = ccs_sys_getpid();
> -+				break;
> -+			case CCS_TASK_PPID:
> -+				value = ccs_sys_getppid();
> -+				break;
> -+			case CCS_TYPE_IS_SOCKET:
> -+				value = S_IFSOCK;
> -+				break;
> -+			case CCS_TYPE_IS_SYMLINK:
> -+				value = S_IFLNK;
> -+				break;
> -+			case CCS_TYPE_IS_FILE:
> -+				value = S_IFREG;
> -+				break;
> -+			case CCS_TYPE_IS_BLOCK_DEV:
> -+				value = S_IFBLK;
> -+				break;
> -+			case CCS_TYPE_IS_DIRECTORY:
> -+				value = S_IFDIR;
> -+				break;
> -+			case CCS_TYPE_IS_CHAR_DEV:
> -+				value = S_IFCHR;
> -+				break;
> -+			case CCS_TYPE_IS_FIFO:
> -+				value = S_IFIFO;
> -+				break;
> -+			case CCS_MODE_SETUID:
> -+				value = S_ISUID;
> -+				break;
> -+			case CCS_MODE_SETGID:
> -+				value = S_ISGID;
> -+				break;
> -+			case CCS_MODE_STICKY:
> -+				value = S_ISVTX;
> -+				break;
> -+			case CCS_MODE_OWNER_READ:
> -+				value = S_IRUSR;
> -+				break;
> -+			case CCS_MODE_OWNER_WRITE:
> -+				value = S_IWUSR;
> -+				break;
> -+			case CCS_MODE_OWNER_EXECUTE:
> -+				value = S_IXUSR;
> -+				break;
> -+			case CCS_MODE_GROUP_READ:
> -+				value = S_IRGRP;
> -+				break;
> -+			case CCS_MODE_GROUP_WRITE:
> -+				value = S_IWGRP;
> -+				break;
> -+			case CCS_MODE_GROUP_EXECUTE:
> -+				value = S_IXGRP;
> -+				break;
> -+			case CCS_MODE_OTHERS_READ:
> -+				value = S_IROTH;
> -+				break;
> -+			case CCS_MODE_OTHERS_WRITE:
> -+				value = S_IWOTH;
> -+				break;
> -+			case CCS_MODE_OTHERS_EXECUTE:
> -+				value = S_IXOTH;
> -+				break;
> -+			case CCS_EXEC_ARGC:
> -+				if (!bprm)
> -+					goto out;
> -+				value = bprm->argc;
> -+				break;
> -+			case CCS_EXEC_ENVC:
> -+				if (!bprm)
> -+					goto out;
> -+				value = bprm->envc;
> -+				break;
> -+			case CCS_TASK_TYPE:
> -+				value = ((u8) ccs_flags)
> -+					& CCS_TASK_IS_EXECUTE_HANDLER;
> -+				break;
> -+			case CCS_TASK_EXECUTE_HANDLER:
> -+				value = CCS_TASK_IS_EXECUTE_HANDLER;
> -+				break;
> -+			case CCS_NUMBER_UNION:
> -+				/* Fetch values later. */
> -+				break;
> -+			default:
> -+				if (!obj)
> -+					goto out;
> -+				if (!obj->validate_done) {
> -+					ccs_get_attributes(obj);
> -+					obj->validate_done = true;
> -+				}
> -+				{
> -+					u8 stat_index;
> -+					struct ccs_mini_stat *stat;
> -+					switch (index) {
> -+					case CCS_PATH1_UID:
> -+					case CCS_PATH1_GID:
> -+					case CCS_PATH1_INO:
> -+					case CCS_PATH1_MAJOR:
> -+					case CCS_PATH1_MINOR:
> -+					case CCS_PATH1_TYPE:
> -+					case CCS_PATH1_DEV_MAJOR:
> -+					case CCS_PATH1_DEV_MINOR:
> -+					case CCS_PATH1_PERM:
> -+						stat_index = CCS_PATH1;
> -+						break;
> -+					case CCS_PATH2_UID:
> -+					case CCS_PATH2_GID:
> -+					case CCS_PATH2_INO:
> -+					case CCS_PATH2_MAJOR:
> -+					case CCS_PATH2_MINOR:
> -+					case CCS_PATH2_TYPE:
> -+					case CCS_PATH2_DEV_MAJOR:
> -+					case CCS_PATH2_DEV_MINOR:
> -+					case CCS_PATH2_PERM:
> -+						stat_index = CCS_PATH2;
> -+						break;
> -+					case CCS_PATH1_PARENT_UID:
> -+					case CCS_PATH1_PARENT_GID:
> -+					case CCS_PATH1_PARENT_INO:
> -+					case CCS_PATH1_PARENT_PERM:
> -+						stat_index = CCS_PATH1_PARENT;
> -+						break;
> -+					case CCS_PATH2_PARENT_UID:
> -+					case CCS_PATH2_PARENT_GID:
> -+					case CCS_PATH2_PARENT_INO:
> -+					case CCS_PATH2_PARENT_PERM:
> -+						stat_index = CCS_PATH2_PARENT;
> -+						break;
> -+					default:
> -+						goto out;
> -+					}
> -+					if (!obj->stat_valid[stat_index])
> -+						goto out;
> -+					stat = &obj->stat[stat_index];
> -+					switch (index) {
> -+					case CCS_PATH1_UID:
> -+					case CCS_PATH2_UID:
> -+					case CCS_PATH1_PARENT_UID:
> -+					case CCS_PATH2_PARENT_UID:
> -+						value = from_kuid
> -+							(&init_user_ns,
> -+							 stat->uid);
> -+						break;
> -+					case CCS_PATH1_GID:
> -+					case CCS_PATH2_GID:
> -+					case CCS_PATH1_PARENT_GID:
> -+					case CCS_PATH2_PARENT_GID:
> -+						value = from_kgid
> -+							(&init_user_ns,
> -+							 stat->gid);
> -+						break;
> -+					case CCS_PATH1_INO:
> -+					case CCS_PATH2_INO:
> -+					case CCS_PATH1_PARENT_INO:
> -+					case CCS_PATH2_PARENT_INO:
> -+						value = stat->ino;
> -+						break;
> -+					case CCS_PATH1_MAJOR:
> -+					case CCS_PATH2_MAJOR:
> -+						value = MAJOR(stat->dev);
> -+						break;
> -+					case CCS_PATH1_MINOR:
> -+					case CCS_PATH2_MINOR:
> -+						value = MINOR(stat->dev);
> -+						break;
> -+					case CCS_PATH1_TYPE:
> -+					case CCS_PATH2_TYPE:
> -+						value = stat->mode & S_IFMT;
> -+						break;
> -+					case CCS_PATH1_DEV_MAJOR:
> -+					case CCS_PATH2_DEV_MAJOR:
> -+						value = MAJOR(stat->rdev);
> -+						break;
> -+					case CCS_PATH1_DEV_MINOR:
> -+					case CCS_PATH2_DEV_MINOR:
> -+						value = MINOR(stat->rdev);
> -+						break;
> -+					case CCS_PATH1_PERM:
> -+					case CCS_PATH2_PERM:
> -+					case CCS_PATH1_PARENT_PERM:
> -+					case CCS_PATH2_PARENT_PERM:
> -+						value = stat->mode & S_IALLUGO;
> -+						break;
> -+					}
> -+				}
> -+				break;
> -+			}
> -+			max_v[j] = value;
> -+			min_v[j] = value;
> -+			switch (index) {
> -+			case CCS_MODE_SETUID:
> -+			case CCS_MODE_SETGID:
> -+			case CCS_MODE_STICKY:
> -+			case CCS_MODE_OWNER_READ:
> -+			case CCS_MODE_OWNER_WRITE:
> -+			case CCS_MODE_OWNER_EXECUTE:
> -+			case CCS_MODE_GROUP_READ:
> -+			case CCS_MODE_GROUP_WRITE:
> -+			case CCS_MODE_GROUP_EXECUTE:
> -+			case CCS_MODE_OTHERS_READ:
> -+			case CCS_MODE_OTHERS_WRITE:
> -+			case CCS_MODE_OTHERS_EXECUTE:
> -+				is_bitop[j] = true;
> -+			}
> -+		}
> -+		if (left == CCS_NUMBER_UNION) {
> -+			/* Fetch values now. */
> -+			const struct ccs_number_union *ptr = numbers_p++;
> -+			min_v[0] = ptr->values[0];
> -+			max_v[0] = ptr->values[1];
> -+		}
> -+		if (right == CCS_NUMBER_UNION) {
> -+			/* Fetch values now. */
> -+			const struct ccs_number_union *ptr = numbers_p++;
> -+			if (ptr->group) {
> -+				if (ccs_number_matches_group(min_v[0],
> -+							     max_v[0],
> -+							     ptr->group)
> -+				    == match)
> -+					continue;
> -+			} else {
> -+				if ((min_v[0] <= ptr->values[1] &&
> -+				     max_v[0] >= ptr->values[0]) == match)
> -+					continue;
> -+			}
> -+			goto out;
> -+		}
> -+		/*
> -+		 * Bit operation is valid only when counterpart value
> -+		 * represents permission.
> -+		 */
> -+		if (is_bitop[0] && is_bitop[1]) {
> -+			goto out;
> -+		} else if (is_bitop[0]) {
> -+			switch (right) {
> -+			case CCS_PATH1_PERM:
> -+			case CCS_PATH1_PARENT_PERM:
> -+			case CCS_PATH2_PERM:
> -+			case CCS_PATH2_PARENT_PERM:
> -+				if (!(max_v[0] & max_v[1]) == !match)
> -+					continue;
> -+			}
> -+			goto out;
> -+		} else if (is_bitop[1]) {
> -+			switch (left) {
> -+			case CCS_PATH1_PERM:
> -+			case CCS_PATH1_PARENT_PERM:
> -+			case CCS_PATH2_PERM:
> -+			case CCS_PATH2_PARENT_PERM:
> -+				if (!(max_v[0] & max_v[1]) == !match)
> -+					continue;
> -+			}
> -+			goto out;
> -+		}
> -+		/* Normal value range comparison. */
> -+		if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
> -+			continue;
> -+out:
> -+		return false;
> -+	}
> -+	/* Check argv[] and envp[] now. */
> -+	if (r->ee && (argc || envc))
> -+		return ccs_scan_bprm(r->ee, argc, argv, envc, envp);
> -+	return true;
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+
> -+/**
> -+ * ccs_check_task_acl - Check permission for task operation.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @ptr: Pointer to "struct ccs_acl_info".
> -+ *
> -+ * Returns true if granted, false otherwise.
> -+ */
> -+static bool ccs_check_task_acl(struct ccs_request_info *r,
> -+			       const struct ccs_acl_info *ptr)
> -+{
> -+	const struct ccs_task_acl *acl = container_of(ptr, typeof(*acl), head);
> -+	return !ccs_pathcmp(r->param.task.domainname, acl->domainname);
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_init_request_info - Initialize "struct ccs_request_info" members.
> -+ *
> -+ * @r:     Pointer to "struct ccs_request_info" to initialize.
> -+ * @index: Index number of functionality.
> -+ *
> -+ * Returns mode.
> -+ *
> -+ * "task auto_domain_transition" keyword is evaluated before returning mode for
> -+ * @index. If "task auto_domain_transition" keyword was specified and
> -+ * transition to that domain failed, the current thread will be killed by
> -+ * SIGKILL. Note that if current->pid == 1, sending SIGKILL won't work.
> -+ */
> -+int ccs_init_request_info(struct ccs_request_info *r, const u8 index)
> -+{
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+	u8 i;
> -+	const char *buf;
> -+	for (i = 0; i < 255; i++) {
> -+		const u8 profile = ccs_current_domain()->profile;
> -+		memset(r, 0, sizeof(*r));
> -+		r->profile = profile;
> -+		r->type = index;
> -+		r->mode = ccs_get_mode(profile, index);
> -+		r->param_type = CCS_TYPE_AUTO_TASK_ACL;
> -+		ccs_check_acl(r);
> -+		if (!r->granted)
> -+			return r->mode;
> -+		buf = container_of(r->matched_acl, typeof(struct ccs_task_acl),
> -+				   head)->domainname->name;
> -+		if (!ccs_assign_domain(buf, true))
> -+			break;
> -+	}
> -+	ccs_transition_failed(buf);
> -+	return CCS_CONFIG_DISABLED;
> -+#else
> -+	const u8 profile = ccs_current_domain()->profile;
> -+	memset(r, 0, sizeof(*r));
> -+	r->profile = profile;
> -+	r->type = index;
> -+	r->mode = ccs_get_mode(profile, index);
> -+	return r->mode;
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_byte_range - Check whether the string is a \ooo style octal value.
> -+ *
> -+ * @str: Pointer to the string.
> -+ *
> -+ * Returns true if @str is a \ooo style octal value, false otherwise.
> -+ */
> -+static bool ccs_byte_range(const char *str)
> -+{
> -+	return *str >= '0' && *str++ <= '3' &&
> -+		*str >= '0' && *str++ <= '7' &&
> -+		*str >= '0' && *str <= '7';
> -+}
> -+
> -+/**
> -+ * ccs_decimal - Check whether the character is a decimal character.
> -+ *
> -+ * @c: The character to check.
> -+ *
> -+ * Returns true if @c is a decimal character, false otherwise.
> -+ */
> -+static bool ccs_decimal(const char c)
> -+{
> -+	return c >= '0' && c <= '9';
> -+}
> -+
> -+/**
> -+ * ccs_hexadecimal - Check whether the character is a hexadecimal character.
> -+ *
> -+ * @c: The character to check.
> -+ *
> -+ * Returns true if @c is a hexadecimal character, false otherwise.
> -+ */
> -+static bool ccs_hexadecimal(const char c)
> -+{
> -+	return (c >= '0' && c <= '9') ||
> -+		(c >= 'A' && c <= 'F') ||
> -+		(c >= 'a' && c <= 'f');
> -+}
> -+
> -+/**
> -+ * ccs_alphabet_char - Check whether the character is an alphabet.
> -+ *
> -+ * @c: The character to check.
> -+ *
> -+ * Returns true if @c is an alphabet character, false otherwise.
> -+ */
> -+static bool ccs_alphabet_char(const char c)
> -+{
> -+	return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
> -+}
> -+
> -+/**
> -+ * ccs_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
> -+ *
> -+ * @filename:     The start of string to check.
> -+ * @filename_end: The end of string to check.
> -+ * @pattern:      The start of pattern to compare.
> -+ * @pattern_end:  The end of pattern to compare.
> -+ *
> -+ * Returns true if @filename matches @pattern, false otherwise.
> -+ */
> -+static bool ccs_file_matches_pattern2(const char *filename,
> -+				      const char *filename_end,
> -+				      const char *pattern,
> -+				      const char *pattern_end)
> -+{
> -+	while (filename < filename_end && pattern < pattern_end) {
> -+		char c;
> -+		if (*pattern != '\\') {
> -+			if (*filename++ != *pattern++)
> -+				return false;
> -+			continue;
> -+		}
> -+		c = *filename;
> -+		pattern++;
> -+		switch (*pattern) {
> -+			int i;
> -+			int j;
> -+		case '?':
> -+			if (c == '/') {
> -+				return false;
> -+			} else if (c == '\\') {
> -+				if (filename[1] == '\\')
> -+					filename++;
> -+				else if (ccs_byte_range(filename + 1))
> -+					filename += 3;
> -+				else
> -+					return false;
> -+			}
> -+			break;
> -+		case '\\':
> -+			if (c != '\\')
> -+				return false;
> -+			if (*++filename != '\\')
> -+				return false;
> -+			break;
> -+		case '+':
> -+			if (!ccs_decimal(c))
> -+				return false;
> -+			break;
> -+		case 'x':
> -+			if (!ccs_hexadecimal(c))
> -+				return false;
> -+			break;
> -+		case 'a':
> -+			if (!ccs_alphabet_char(c))
> -+				return false;
> -+			break;
> -+		case '0':
> -+		case '1':
> -+		case '2':
> -+		case '3':
> -+			if (c == '\\' && ccs_byte_range(filename + 1)
> -+			    && !strncmp(filename + 1, pattern, 3)) {
> -+				filename += 3;
> -+				pattern += 2;
> -+				break;
> -+			}
> -+			return false; /* Not matched. */
> -+		case '*':
> -+		case '@':
> -+			for (i = 0; i <= filename_end - filename; i++) {
> -+				if (ccs_file_matches_pattern2(filename + i,
> -+							      filename_end,
> -+							      pattern + 1,
> -+							      pattern_end))
> -+					return true;
> -+				c = filename[i];
> -+				if (c == '.' && *pattern == '@')
> -+					break;
> -+				if (c != '\\')
> -+					continue;
> -+				if (filename[i + 1] == '\\')
> -+					i++;
> -+				else if (ccs_byte_range(filename + i + 1))
> -+					i += 3;
> -+				else
> -+					break; /* Bad pattern. */
> -+			}
> -+			return false; /* Not matched. */
> -+		default:
> -+			j = 0;
> -+			c = *pattern;
> -+			if (c == '$') {
> -+				while (ccs_decimal(filename[j]))
> -+					j++;
> -+			} else if (c == 'X') {
> -+				while (ccs_hexadecimal(filename[j]))
> -+					j++;
> -+			} else if (c == 'A') {
> -+				while (ccs_alphabet_char(filename[j]))
> -+					j++;
> -+			}
> -+			for (i = 1; i <= j; i++) {
> -+				if (ccs_file_matches_pattern2(filename + i,
> -+							      filename_end,
> -+							      pattern + 1,
> -+							      pattern_end))
> -+					return true;
> -+			}
> -+			return false; /* Not matched or bad pattern. */
> -+		}
> -+		filename++;
> -+		pattern++;
> -+	}
> -+	while (*pattern == '\\' &&
> -+	       (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
> -+		pattern += 2;
> -+	return filename == filename_end && pattern == pattern_end;
> -+}
> -+
> -+/**
> -+ * ccs_file_matches_pattern - Pattern matching without '/' character.
> -+ *
> -+ * @filename:     The start of string to check.
> -+ * @filename_end: The end of string to check.
> -+ * @pattern:      The start of pattern to compare.
> -+ * @pattern_end:  The end of pattern to compare.
> -+ *
> -+ * Returns true if @filename matches @pattern, false otherwise.
> -+ */
> -+static bool ccs_file_matches_pattern(const char *filename,
> -+				     const char *filename_end,
> -+				     const char *pattern,
> -+				     const char *pattern_end)
> -+{
> -+	const char *pattern_start = pattern;
> -+	bool first = true;
> -+	bool result;
> -+	while (pattern < pattern_end - 1) {
> -+		/* Split at "\-" pattern. */
> -+		if (*pattern++ != '\\' || *pattern++ != '-')
> -+			continue;
> -+		result = ccs_file_matches_pattern2(filename, filename_end,
> -+						   pattern_start, pattern - 2);
> -+		if (first)
> -+			result = !result;
> -+		if (result)
> -+			return false;
> -+		first = false;
> -+		pattern_start = pattern;
> -+	}
> -+	result = ccs_file_matches_pattern2(filename, filename_end,
> -+					   pattern_start, pattern_end);
> -+	return first ? result : !result;
> -+}
> -+
> -+/**
> -+ * ccs_path_matches_pattern2 - Do pathname pattern matching.
> -+ *
> -+ * @f: The start of string to check.
> -+ * @p: The start of pattern to compare.
> -+ *
> -+ * Returns true if @f matches @p, false otherwise.
> -+ */
> -+static bool ccs_path_matches_pattern2(const char *f, const char *p)
> -+{
> -+	const char *f_delimiter;
> -+	const char *p_delimiter;
> -+	while (*f && *p) {
> -+		f_delimiter = strchr(f, '/');
> -+		if (!f_delimiter)
> -+			f_delimiter = f + strlen(f);
> -+		p_delimiter = strchr(p, '/');
> -+		if (!p_delimiter)
> -+			p_delimiter = p + strlen(p);
> -+		if (*p == '\\' && *(p + 1) == '{')
> -+			goto recursive;
> -+		if (!ccs_file_matches_pattern(f, f_delimiter, p, p_delimiter))
> -+			return false;
> -+		f = f_delimiter;
> -+		if (*f)
> -+			f++;
> -+		p = p_delimiter;
> -+		if (*p)
> -+			p++;
> -+	}
> -+	/* Ignore trailing "\*" and "\@" in @pattern. */
> -+	while (*p == '\\' &&
> -+	       (*(p + 1) == '*' || *(p + 1) == '@'))
> -+		p += 2;
> -+	return !*f && !*p;
> -+recursive:
> -+	/*
> -+	 * The "\{" pattern is permitted only after '/' character.
> -+	 * This guarantees that below "*(p - 1)" is safe.
> -+	 * Also, the "\}" pattern is permitted only before '/' character
> -+	 * so that "\{" + "\}" pair will not break the "\-" operator.
> -+	 */
> -+	if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
> -+	    *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
> -+		return false; /* Bad pattern. */
> -+	do {
> -+		/* Compare current component with pattern. */
> -+		if (!ccs_file_matches_pattern(f, f_delimiter, p + 2,
> -+					      p_delimiter - 2))
> -+			break;
> -+		/* Proceed to next component. */
> -+		f = f_delimiter;
> -+		if (!*f)
> -+			break;
> -+		f++;
> -+		/* Continue comparison. */
> -+		if (ccs_path_matches_pattern2(f, p_delimiter + 1))
> -+			return true;
> -+		f_delimiter = strchr(f, '/');
> -+	} while (f_delimiter);
> -+	return false; /* Not matched. */
> -+}
> -+
> -+/**
> -+ * ccs_path_matches_pattern - Check whether the given filename matches the given pattern.
> -+ *
> -+ * @filename: The filename to check.
> -+ * @pattern:  The pattern to compare.
> -+ *
> -+ * Returns true if matches, false otherwise.
> -+ *
> -+ * The following patterns are available.
> -+ *   \\     \ itself.
> -+ *   \ooo   Octal representation of a byte.
> -+ *   \*     Zero or more repetitions of characters other than '/'.
> -+ *   \@     Zero or more repetitions of characters other than '/' or '.'.
> -+ *   \?     1 byte character other than '/'.
> -+ *   \$     One or more repetitions of decimal digits.
> -+ *   \+     1 decimal digit.
> -+ *   \X     One or more repetitions of hexadecimal digits.
> -+ *   \x     1 hexadecimal digit.
> -+ *   \A     One or more repetitions of alphabet characters.
> -+ *   \a     1 alphabet character.
> -+ *
> -+ *   \-     Subtraction operator.
> -+ *
> -+ *   /\{dir\}/   '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
> -+ *               /dir/dir/dir/ ).
> -+ */
> -+static bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
> -+				     const struct ccs_path_info *pattern)
> -+{
> -+	const char *f = filename->name;
> -+	const char *p = pattern->name;
> -+	const int len = pattern->const_len;
> -+	/* If @pattern doesn't contain pattern, I can use strcmp(). */
> -+	if (!pattern->is_patterned)
> -+		return !ccs_pathcmp(filename, pattern);
> -+	/* Don't compare directory and non-directory. */
> -+	if (filename->is_dir != pattern->is_dir)
> -+		return false;
> -+	/* Compare the initial length without patterns. */
> -+	if (strncmp(f, p, len))
> -+		return false;
> -+	f += len;
> -+	p += len;
> -+	return ccs_path_matches_pattern2(f, p);
> -+}
> -diff --git a/security/ccsecurity/policy_io.c b/security/ccsecurity/policy_io.c
> -new file mode 100644
> -index 0000000..67adb50
> ---- /dev/null
> -+++ b/security/ccsecurity/policy_io.c
> -@@ -0,0 +1,6484 @@
> -+/*
> -+ * security/ccsecurity/policy_io.c
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/05/05
> -+ */
> -+
> -+#include "internal.h"
> -+
> -+/***** SECTION1: Constants definition *****/
> -+
> -+/* Define this to enable debug mode. */
> -+/* #define DEBUG_CONDITION */
> -+
> -+#ifdef DEBUG_CONDITION
> -+#define dprintk printk
> -+#else
> -+#define dprintk(...) do { } while (0)
> -+#endif
> -+
> -+/* Mapping table from "enum ccs_mac_index" to "enum ccs_mac_category_index". */
> -+static const u8 ccs_index2category[CCS_MAX_MAC_INDEX] = {
> -+	/* CONFIG::file group */
> -+	[CCS_MAC_FILE_EXECUTE]    = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_OPEN]       = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_CREATE]     = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_UNLINK]     = CCS_MAC_CATEGORY_FILE,
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+	[CCS_MAC_FILE_GETATTR]    = CCS_MAC_CATEGORY_FILE,
> -+#endif
> -+	[CCS_MAC_FILE_MKDIR]      = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_RMDIR]      = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_MKFIFO]     = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_MKSOCK]     = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_TRUNCATE]   = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_SYMLINK]    = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_MKBLOCK]    = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_MKCHAR]     = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_LINK]       = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_RENAME]     = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_CHMOD]      = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_CHOWN]      = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_CHGRP]      = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_IOCTL]      = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_CHROOT]     = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_MOUNT]      = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_UMOUNT]     = CCS_MAC_CATEGORY_FILE,
> -+	[CCS_MAC_FILE_PIVOT_ROOT] = CCS_MAC_CATEGORY_FILE,
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	/* CONFIG::misc group */
> -+	[CCS_MAC_ENVIRON]         = CCS_MAC_CATEGORY_MISC,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	/* CONFIG::network group */
> -+	[CCS_MAC_NETWORK_INET_STREAM_BIND]       = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_INET_STREAM_LISTEN]     = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_INET_STREAM_CONNECT]    = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_INET_STREAM_ACCEPT]     = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_INET_DGRAM_BIND]        = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_INET_DGRAM_SEND]        = CCS_MAC_CATEGORY_NETWORK,
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	[CCS_MAC_NETWORK_INET_DGRAM_RECV]        = CCS_MAC_CATEGORY_NETWORK,
> -+#endif
> -+	[CCS_MAC_NETWORK_INET_RAW_BIND]          = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_INET_RAW_SEND]          = CCS_MAC_CATEGORY_NETWORK,
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	[CCS_MAC_NETWORK_INET_RAW_RECV]          = CCS_MAC_CATEGORY_NETWORK,
> -+#endif
> -+	[CCS_MAC_NETWORK_UNIX_STREAM_BIND]       = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_UNIX_STREAM_LISTEN]     = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_UNIX_STREAM_CONNECT]    = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT]     = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_UNIX_DGRAM_BIND]        = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_UNIX_DGRAM_SEND]        = CCS_MAC_CATEGORY_NETWORK,
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	[CCS_MAC_NETWORK_UNIX_DGRAM_RECV]        = CCS_MAC_CATEGORY_NETWORK,
> -+#endif
> -+	[CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND]    = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN]  = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = CCS_MAC_CATEGORY_NETWORK,
> -+	[CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT]  = CCS_MAC_CATEGORY_NETWORK,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	/* CONFIG::ipc group */
> -+	[CCS_MAC_SIGNAL]          = CCS_MAC_CATEGORY_IPC,
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	/* CONFIG::capability group */
> -+	[CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET]  = CCS_MAC_CATEGORY_CAPABILITY,
> -+	[CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = CCS_MAC_CATEGORY_CAPABILITY,
> -+	[CCS_MAC_CAPABILITY_SYS_REBOOT]        = CCS_MAC_CATEGORY_CAPABILITY,
> -+	[CCS_MAC_CAPABILITY_SYS_VHANGUP]       = CCS_MAC_CATEGORY_CAPABILITY,
> -+	[CCS_MAC_CAPABILITY_SYS_SETTIME]       = CCS_MAC_CATEGORY_CAPABILITY,
> -+	[CCS_MAC_CAPABILITY_SYS_NICE]          = CCS_MAC_CATEGORY_CAPABILITY,
> -+	[CCS_MAC_CAPABILITY_SYS_SETHOSTNAME]   = CCS_MAC_CATEGORY_CAPABILITY,
> -+	[CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = CCS_MAC_CATEGORY_CAPABILITY,
> -+	[CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD]    = CCS_MAC_CATEGORY_CAPABILITY,
> -+	[CCS_MAC_CAPABILITY_SYS_PTRACE]        = CCS_MAC_CATEGORY_CAPABILITY,
> -+#endif
> -+};
> -+
> -+/* String table for operation mode. */
> -+static const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {
> -+	[CCS_CONFIG_DISABLED]   = "disabled",
> -+	[CCS_CONFIG_LEARNING]   = "learning",
> -+	[CCS_CONFIG_PERMISSIVE] = "permissive",
> -+	[CCS_CONFIG_ENFORCING]  = "enforcing"
> -+};
> -+
> -+/* String table for /proc/ccs/profile interface. */
> -+static const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX
> -+					   + CCS_MAX_MAC_CATEGORY_INDEX] = {
> -+	/* CONFIG::file group */
> -+	[CCS_MAC_FILE_EXECUTE]    = "execute",
> -+	[CCS_MAC_FILE_OPEN]       = "open",
> -+	[CCS_MAC_FILE_CREATE]     = "create",
> -+	[CCS_MAC_FILE_UNLINK]     = "unlink",
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+	[CCS_MAC_FILE_GETATTR]    = "getattr",
> -+#endif
> -+	[CCS_MAC_FILE_MKDIR]      = "mkdir",
> -+	[CCS_MAC_FILE_RMDIR]      = "rmdir",
> -+	[CCS_MAC_FILE_MKFIFO]     = "mkfifo",
> -+	[CCS_MAC_FILE_MKSOCK]     = "mksock",
> -+	[CCS_MAC_FILE_TRUNCATE]   = "truncate",
> -+	[CCS_MAC_FILE_SYMLINK]    = "symlink",
> -+	[CCS_MAC_FILE_MKBLOCK]    = "mkblock",
> -+	[CCS_MAC_FILE_MKCHAR]     = "mkchar",
> -+	[CCS_MAC_FILE_LINK]       = "link",
> -+	[CCS_MAC_FILE_RENAME]     = "rename",
> -+	[CCS_MAC_FILE_CHMOD]      = "chmod",
> -+	[CCS_MAC_FILE_CHOWN]      = "chown",
> -+	[CCS_MAC_FILE_CHGRP]      = "chgrp",
> -+	[CCS_MAC_FILE_IOCTL]      = "ioctl",
> -+	[CCS_MAC_FILE_CHROOT]     = "chroot",
> -+	[CCS_MAC_FILE_MOUNT]      = "mount",
> -+	[CCS_MAC_FILE_UMOUNT]     = "unmount",
> -+	[CCS_MAC_FILE_PIVOT_ROOT] = "pivot_root",
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	/* CONFIG::misc group */
> -+	[CCS_MAC_ENVIRON] = "env",
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	/* CONFIG::network group */
> -+	[CCS_MAC_NETWORK_INET_STREAM_BIND]       = "inet_stream_bind",
> -+	[CCS_MAC_NETWORK_INET_STREAM_LISTEN]     = "inet_stream_listen",
> -+	[CCS_MAC_NETWORK_INET_STREAM_CONNECT]    = "inet_stream_connect",
> -+	[CCS_MAC_NETWORK_INET_STREAM_ACCEPT]     = "inet_stream_accept",
> -+	[CCS_MAC_NETWORK_INET_DGRAM_BIND]        = "inet_dgram_bind",
> -+	[CCS_MAC_NETWORK_INET_DGRAM_SEND]        = "inet_dgram_send",
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	[CCS_MAC_NETWORK_INET_DGRAM_RECV]        = "inet_dgram_recv",
> -+#endif
> -+	[CCS_MAC_NETWORK_INET_RAW_BIND]          = "inet_raw_bind",
> -+	[CCS_MAC_NETWORK_INET_RAW_SEND]          = "inet_raw_send",
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	[CCS_MAC_NETWORK_INET_RAW_RECV]          = "inet_raw_recv",
> -+#endif
> -+	[CCS_MAC_NETWORK_UNIX_STREAM_BIND]       = "unix_stream_bind",
> -+	[CCS_MAC_NETWORK_UNIX_STREAM_LISTEN]     = "unix_stream_listen",
> -+	[CCS_MAC_NETWORK_UNIX_STREAM_CONNECT]    = "unix_stream_connect",
> -+	[CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT]     = "unix_stream_accept",
> -+	[CCS_MAC_NETWORK_UNIX_DGRAM_BIND]        = "unix_dgram_bind",
> -+	[CCS_MAC_NETWORK_UNIX_DGRAM_SEND]        = "unix_dgram_send",
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	[CCS_MAC_NETWORK_UNIX_DGRAM_RECV]        = "unix_dgram_recv",
> -+#endif
> -+	[CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND]    = "unix_seqpacket_bind",
> -+	[CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN]  = "unix_seqpacket_listen",
> -+	[CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect",
> -+	[CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT]  = "unix_seqpacket_accept",
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	/* CONFIG::ipc group */
> -+	[CCS_MAC_SIGNAL] = "signal",
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	/* CONFIG::capability group */
> -+	[CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET]  = "use_route",
> -+	[CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = "use_packet",
> -+	[CCS_MAC_CAPABILITY_SYS_REBOOT]        = "SYS_REBOOT",
> -+	[CCS_MAC_CAPABILITY_SYS_VHANGUP]       = "SYS_VHANGUP",
> -+	[CCS_MAC_CAPABILITY_SYS_SETTIME]       = "SYS_TIME",
> -+	[CCS_MAC_CAPABILITY_SYS_NICE]          = "SYS_NICE",
> -+	[CCS_MAC_CAPABILITY_SYS_SETHOSTNAME]   = "SYS_SETHOSTNAME",
> -+	[CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = "use_kernel_module",
> -+	[CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD]    = "SYS_KEXEC_LOAD",
> -+	[CCS_MAC_CAPABILITY_SYS_PTRACE]        = "SYS_PTRACE",
> -+#endif
> -+	/* CONFIG group */
> -+	[CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_FILE]       = "file",
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	[CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_NETWORK]    = "network",
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	[CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_MISC]       = "misc",
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	[CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_IPC]        = "ipc",
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	[CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
> -+#endif
> -+};
> -+
> -+/* String table for path operation. */
> -+static const char * const ccs_path_keyword[CCS_MAX_PATH_OPERATION] = {
> -+	[CCS_TYPE_EXECUTE]    = "execute",
> -+	[CCS_TYPE_READ]       = "read",
> -+	[CCS_TYPE_WRITE]      = "write",
> -+	[CCS_TYPE_APPEND]     = "append",
> -+	[CCS_TYPE_UNLINK]     = "unlink",
> -+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
> -+	[CCS_TYPE_GETATTR]    = "getattr",
> -+#endif
> -+	[CCS_TYPE_RMDIR]      = "rmdir",
> -+	[CCS_TYPE_TRUNCATE]   = "truncate",
> -+	[CCS_TYPE_SYMLINK]    = "symlink",
> -+	[CCS_TYPE_CHROOT]     = "chroot",
> -+	[CCS_TYPE_UMOUNT]     = "unmount",
> -+};
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+
> -+/* String table for socket's operation. */
> -+static const char * const ccs_socket_keyword[CCS_MAX_NETWORK_OPERATION] = {
> -+	[CCS_NETWORK_BIND]    = "bind",
> -+	[CCS_NETWORK_LISTEN]  = "listen",
> -+	[CCS_NETWORK_CONNECT] = "connect",
> -+	[CCS_NETWORK_ACCEPT]  = "accept",
> -+	[CCS_NETWORK_SEND]    = "send",
> -+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
> -+	[CCS_NETWORK_RECV]    = "recv",
> -+#endif
> -+};
> -+
> -+/* String table for socket's protocols. */
> -+static const char * const ccs_proto_keyword[CCS_SOCK_MAX] = {
> -+	[SOCK_STREAM]    = "stream",
> -+	[SOCK_DGRAM]     = "dgram",
> -+	[SOCK_RAW]       = "raw",
> -+	[SOCK_SEQPACKET] = "seqpacket",
> -+	[0] = " ", /* Dummy for avoiding NULL pointer dereference. */
> -+	[4] = " ", /* Dummy for avoiding NULL pointer dereference. */
> -+};
> -+
> -+#endif
> -+
> -+/* String table for categories. */
> -+static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {
> -+	[CCS_MAC_CATEGORY_FILE]       = "file",
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	[CCS_MAC_CATEGORY_NETWORK]    = "network",
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	[CCS_MAC_CATEGORY_MISC]       = "misc",
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	[CCS_MAC_CATEGORY_IPC]        = "ipc",
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	[CCS_MAC_CATEGORY_CAPABILITY] = "capability",
> -+#endif
> -+};
> -+
> -+/* String table for conditions. */
> -+static const char * const ccs_condition_keyword[CCS_MAX_CONDITION_KEYWORD] = {
> -+	[CCS_TASK_UID]             = "task.uid",
> -+	[CCS_TASK_EUID]            = "task.euid",
> -+	[CCS_TASK_SUID]            = "task.suid",
> -+	[CCS_TASK_FSUID]           = "task.fsuid",
> -+	[CCS_TASK_GID]             = "task.gid",
> -+	[CCS_TASK_EGID]            = "task.egid",
> -+	[CCS_TASK_SGID]            = "task.sgid",
> -+	[CCS_TASK_FSGID]           = "task.fsgid",
> -+	[CCS_TASK_PID]             = "task.pid",
> -+	[CCS_TASK_PPID]            = "task.ppid",
> -+	[CCS_EXEC_ARGC]            = "exec.argc",
> -+	[CCS_EXEC_ENVC]            = "exec.envc",
> -+	[CCS_TYPE_IS_SOCKET]       = "socket",
> -+	[CCS_TYPE_IS_SYMLINK]      = "symlink",
> -+	[CCS_TYPE_IS_FILE]         = "file",
> -+	[CCS_TYPE_IS_BLOCK_DEV]    = "block",
> -+	[CCS_TYPE_IS_DIRECTORY]    = "directory",
> -+	[CCS_TYPE_IS_CHAR_DEV]     = "char",
> -+	[CCS_TYPE_IS_FIFO]         = "fifo",
> -+	[CCS_MODE_SETUID]          = "setuid",
> -+	[CCS_MODE_SETGID]          = "setgid",
> -+	[CCS_MODE_STICKY]          = "sticky",
> -+	[CCS_MODE_OWNER_READ]      = "owner_read",
> -+	[CCS_MODE_OWNER_WRITE]     = "owner_write",
> -+	[CCS_MODE_OWNER_EXECUTE]   = "owner_execute",
> -+	[CCS_MODE_GROUP_READ]      = "group_read",
> -+	[CCS_MODE_GROUP_WRITE]     = "group_write",
> -+	[CCS_MODE_GROUP_EXECUTE]   = "group_execute",
> -+	[CCS_MODE_OTHERS_READ]     = "others_read",
> -+	[CCS_MODE_OTHERS_WRITE]    = "others_write",
> -+	[CCS_MODE_OTHERS_EXECUTE]  = "others_execute",
> -+	[CCS_TASK_TYPE]            = "task.type",
> -+	[CCS_TASK_EXECUTE_HANDLER] = "execute_handler",
> -+	[CCS_EXEC_REALPATH]        = "exec.realpath",
> -+	[CCS_SYMLINK_TARGET]       = "symlink.target",
> -+	[CCS_PATH1_UID]            = "path1.uid",
> -+	[CCS_PATH1_GID]            = "path1.gid",
> -+	[CCS_PATH1_INO]            = "path1.ino",
> -+	[CCS_PATH1_MAJOR]          = "path1.major",
> -+	[CCS_PATH1_MINOR]          = "path1.minor",
> -+	[CCS_PATH1_PERM]           = "path1.perm",
> -+	[CCS_PATH1_TYPE]           = "path1.type",
> -+	[CCS_PATH1_DEV_MAJOR]      = "path1.dev_major",
> -+	[CCS_PATH1_DEV_MINOR]      = "path1.dev_minor",
> -+	[CCS_PATH2_UID]            = "path2.uid",
> -+	[CCS_PATH2_GID]            = "path2.gid",
> -+	[CCS_PATH2_INO]            = "path2.ino",
> -+	[CCS_PATH2_MAJOR]          = "path2.major",
> -+	[CCS_PATH2_MINOR]          = "path2.minor",
> -+	[CCS_PATH2_PERM]           = "path2.perm",
> -+	[CCS_PATH2_TYPE]           = "path2.type",
> -+	[CCS_PATH2_DEV_MAJOR]      = "path2.dev_major",
> -+	[CCS_PATH2_DEV_MINOR]      = "path2.dev_minor",
> -+	[CCS_PATH1_PARENT_UID]     = "path1.parent.uid",
> -+	[CCS_PATH1_PARENT_GID]     = "path1.parent.gid",
> -+	[CCS_PATH1_PARENT_INO]     = "path1.parent.ino",
> -+	[CCS_PATH1_PARENT_PERM]    = "path1.parent.perm",
> -+	[CCS_PATH2_PARENT_UID]     = "path2.parent.uid",
> -+	[CCS_PATH2_PARENT_GID]     = "path2.parent.gid",
> -+	[CCS_PATH2_PARENT_INO]     = "path2.parent.ino",
> -+	[CCS_PATH2_PARENT_PERM]    = "path2.parent.perm",
> -+};
> -+
> -+/* String table for PREFERENCE keyword. */
> -+static const char * const ccs_pref_keywords[CCS_MAX_PREF] = {
> -+	[CCS_PREF_MAX_AUDIT_LOG]      = "max_audit_log",
> -+	[CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
> -+	[CCS_PREF_ENFORCING_PENALTY]  = "enforcing_penalty",
> -+};
> -+
> -+/* String table for domain flags. */
> -+const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
> -+	[CCS_DIF_QUOTA_WARNED]      = "quota_exceeded\n",
> -+	[CCS_DIF_TRANSITION_FAILED] = "transition_failed\n",
> -+};
> -+
> -+/* String table for domain transition control keywords. */
> -+static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
> -+	[CCS_TRANSITION_CONTROL_NO_RESET]      = "no_reset_domain ",
> -+	[CCS_TRANSITION_CONTROL_RESET]         = "reset_domain ",
> -+	[CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
> -+	[CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
> -+	[CCS_TRANSITION_CONTROL_NO_KEEP]       = "no_keep_domain ",
> -+	[CCS_TRANSITION_CONTROL_KEEP]          = "keep_domain ",
> -+};
> -+
> -+/* String table for grouping keywords. */
> -+static const char * const ccs_group_name[CCS_MAX_GROUP] = {
> -+	[CCS_PATH_GROUP]    = "path_group ",
> -+	[CCS_NUMBER_GROUP]  = "number_group ",
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	[CCS_ADDRESS_GROUP] = "address_group ",
> -+#endif
> -+};
> -+
> -+/* String table for /proc/ccs/stat interface. */
> -+static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {
> -+	[CCS_STAT_POLICY_UPDATES]    = "update:",
> -+	[CCS_STAT_POLICY_LEARNING]   = "violation in learning mode:",
> -+	[CCS_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:",
> -+	[CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",
> -+};
> -+
> -+/* String table for /proc/ccs/stat interface. */
> -+static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
> -+	[CCS_MEMORY_POLICY]     = "policy:",
> -+	[CCS_MEMORY_AUDIT]      = "audit log:",
> -+	[CCS_MEMORY_QUERY]      = "query message:",
> -+};
> -+
> -+/***** SECTION2: Structure definition *****/
> -+
> -+struct iattr;
> -+
> -+/* Structure for query. */
> -+struct ccs_query {
> -+	struct list_head list;
> -+	struct ccs_domain_info *domain;
> -+	char *query;
> -+	size_t query_len;
> -+	unsigned int serial;
> -+	u8 timer;
> -+	u8 answer;
> -+	u8 retry;
> -+};
> -+
> -+/* Structure for audit log. */
> -+struct ccs_log {
> -+	struct list_head list;
> -+	char *log;
> -+	int size;
> -+};
> -+
> -+/***** SECTION3: Prototype definition section *****/
> -+
> -+int ccs_audit_log(struct ccs_request_info *r);
> -+struct ccs_domain_info *ccs_assign_domain(const char *domainname,
> -+					  const bool transit);
> -+u8 ccs_get_config(const u8 profile, const u8 index);
> -+void ccs_transition_failed(const char *domainname);
> -+void ccs_write_log(struct ccs_request_info *r, const char *fmt, ...);
> -+
> -+static bool ccs_correct_domain(const unsigned char *domainname);
> -+static bool ccs_correct_path(const char *filename);
> -+static bool ccs_correct_word(const char *string);
> -+static bool ccs_correct_word2(const char *string, size_t len);
> -+static bool ccs_domain_def(const unsigned char *buffer);
> -+static bool ccs_domain_quota_ok(struct ccs_request_info *r);
> -+static bool ccs_flush(struct ccs_io_buffer *head);
> -+static bool ccs_get_audit(const struct ccs_request_info *r);
> -+static bool ccs_has_more_namespace(struct ccs_io_buffer *head);
> -+static bool ccs_manager(void);
> -+static bool ccs_namespace_jump(const char *domainname);
> -+static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv);
> -+static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp);
> -+static bool ccs_parse_name_union(struct ccs_acl_param *param,
> -+				 struct ccs_name_union *ptr);
> -+static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param,
> -+					struct ccs_name_union *ptr);
> -+static bool ccs_parse_number_union(struct ccs_acl_param *param,
> -+				   struct ccs_number_union *ptr);
> -+static bool ccs_permstr(const char *string, const char *keyword);
> -+static bool ccs_print_condition(struct ccs_io_buffer *head,
> -+				const struct ccs_condition *cond);
> -+static bool ccs_print_entry(struct ccs_io_buffer *head,
> -+			    const struct ccs_acl_info *acl);
> -+static bool ccs_print_group(struct ccs_io_buffer *head,
> -+			    const struct ccs_group *group);
> -+static bool ccs_read_acl(struct ccs_io_buffer *head, struct list_head *list);
> -+static bool ccs_read_group(struct ccs_io_buffer *head, const int idx);
> -+static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx);
> -+static bool ccs_same_condition(const struct ccs_condition *a,
> -+			       const struct ccs_condition *b);
> -+static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data);
> -+static bool ccs_set_lf(struct ccs_io_buffer *head);
> -+static bool ccs_str_starts(char **src, const char *find);
> -+static char *ccs_get_transit_preference(struct ccs_acl_param *param,
> -+					struct ccs_condition *e);
> -+static char *ccs_init_log(struct ccs_request_info *r, int len, const char *fmt,
> -+			  va_list args);
> -+static char *ccs_print_bprm(struct linux_binprm *bprm,
> -+			    struct ccs_page_dump *dump);
> -+static char *ccs_print_header(struct ccs_request_info *r);
> -+static char *ccs_read_token(struct ccs_acl_param *param);
> -+static const char *ccs_yesno(const unsigned int value);
> -+static const struct ccs_path_info *ccs_get_domainname
> -+(struct ccs_acl_param *param);
> -+static const struct ccs_path_info *ccs_get_dqword(char *start);
> -+static int __init ccs_init_module(void);
> -+static int ccs_delete_domain(char *domainname);
> -+static int ccs_open(struct inode *inode, struct file *file);
> -+static int ccs_parse_policy(struct ccs_io_buffer *head, char *line);
> -+static int ccs_release(struct inode *inode, struct file *file);
> -+static int ccs_set_mode(char *name, const char *value,
> -+			struct ccs_profile *profile);
> -+static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
> -+	__printf(2, 3);
> -+static int ccs_truncate(char *str);
> -+static int ccs_update_acl(const int size, struct ccs_acl_param *param);
> -+static int ccs_update_manager_entry(const char *manager, const bool is_delete);
> -+static int ccs_update_policy(const int size, struct ccs_acl_param *param);
> -+static int ccs_write_acl(struct ccs_policy_namespace *ns,
> -+			 struct list_head *list, char *data,
> -+			 const bool is_delete);
> -+static int ccs_write_aggregator(struct ccs_acl_param *param);
> -+static int ccs_write_answer(struct ccs_io_buffer *head);
> -+static int ccs_write_domain(struct ccs_io_buffer *head);
> -+static int ccs_write_exception(struct ccs_io_buffer *head);
> -+static int ccs_write_file(struct ccs_acl_param *param);
> -+static int ccs_write_group(struct ccs_acl_param *param, const u8 type);
> -+static int ccs_write_manager(struct ccs_io_buffer *head);
> -+static int ccs_write_pid(struct ccs_io_buffer *head);
> -+static int ccs_write_profile(struct ccs_io_buffer *head);
> -+static int ccs_write_stat(struct ccs_io_buffer *head);
> -+static int ccs_write_task(struct ccs_acl_param *param);
> -+static int ccs_write_transition_control(struct ccs_acl_param *param,
> -+					const u8 type);
> -+static s8 ccs_find_yesno(const char *string, const char *find);
> -+static ssize_t ccs_read(struct file *file, char __user *buf, size_t count,
> -+			loff_t *ppos);
> -+static ssize_t ccs_read_self(struct file *file, char __user *buf, size_t count,
> -+			     loff_t *ppos);
> -+static ssize_t ccs_write(struct file *file, const char __user *buf,
> -+			 size_t count, loff_t *ppos);
> -+static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry);
> -+static struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param);
> -+static struct ccs_domain_info *ccs_find_domain(const char *domainname);
> -+static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial);
> -+static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
> -+				       const u8 idx);
> -+static struct ccs_policy_namespace *ccs_assign_namespace
> -+(const char *domainname);
> -+static struct ccs_policy_namespace *ccs_find_namespace(const char *name,
> -+						       const unsigned int len);
> -+static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
> -+					      const unsigned int profile);
> -+static struct ccs_profile *ccs_profile(const u8 profile);
> -+static u8 ccs_condition_type(const char *word);
> -+static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3);
> -+static u8 ccs_parse_ulong(unsigned long *result, char **str);
> -+static unsigned int ccs_poll(struct file *file, poll_table *wait);
> -+static void __init ccs_create_entry(const char *name, const umode_t mode,
> -+				    struct proc_dir_entry *parent,
> -+				    const u8 key);
> -+static void __init ccs_load_builtin_policy(void);
> -+static void __init ccs_policy_io_init(void);
> -+static void __init ccs_proc_init(void);
> -+static void ccs_add_entry(char *header);
> -+static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
> -+	__printf(3, 4);
> -+static void ccs_addprintf(char *buffer, int len, const char *fmt, ...);
> -+static void ccs_check_profile(void);
> -+static void ccs_convert_time(time_t time, struct ccs_time *stamp);
> -+static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns);
> -+static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
> -+	__printf(2, 3);
> -+static void ccs_normalize_line(unsigned char *buffer);
> -+static void ccs_print_config(struct ccs_io_buffer *head, const u8 config);
> -+static void ccs_print_name_union(struct ccs_io_buffer *head,
> -+				 const struct ccs_name_union *ptr);
> -+static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
> -+					const struct ccs_name_union *ptr);
> -+static void ccs_print_namespace(struct ccs_io_buffer *head);
> -+static void ccs_print_number_union(struct ccs_io_buffer *head,
> -+				   const struct ccs_number_union *ptr);
> -+static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
> -+					   const struct ccs_number_union *ptr);
> -+static void ccs_read_domain(struct ccs_io_buffer *head);
> -+static void ccs_read_exception(struct ccs_io_buffer *head);
> -+static void ccs_read_log(struct ccs_io_buffer *head);
> -+static void ccs_read_manager(struct ccs_io_buffer *head);
> -+static void ccs_read_pid(struct ccs_io_buffer *head);
> -+static void ccs_read_profile(struct ccs_io_buffer *head);
> -+static void ccs_read_query(struct ccs_io_buffer *head);
> -+static void ccs_read_stat(struct ccs_io_buffer *head);
> -+static void ccs_read_version(struct ccs_io_buffer *head);
> -+static void ccs_set_group(struct ccs_io_buffer *head, const char *category);
> -+static void ccs_set_namespace_cursor(struct ccs_io_buffer *head);
> -+static void ccs_set_slash(struct ccs_io_buffer *head);
> -+static void ccs_set_space(struct ccs_io_buffer *head);
> -+static void ccs_set_string(struct ccs_io_buffer *head, const char *string);
> -+static void ccs_set_uint(unsigned int *i, const char *string,
> -+			 const char *find);
> -+static void ccs_update_stat(const u8 index);
> -+static void ccs_update_task_domain(struct ccs_request_info *r);
> -+static void ccs_write_log2(struct ccs_request_info *r, int len,
> -+			   const char *fmt, va_list args);
> -+
> -+#ifdef CONFIG_CCSECURITY_PORTRESERVE
> -+static bool __ccs_lport_reserved(const u16 port);
> -+static int ccs_write_reserved_port(struct ccs_acl_param *param);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
> -+				   struct ccs_ipaddr_union *ptr);
> -+static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
> -+			  const u32 *ip);
> -+static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
> -+			  const struct in6_addr *ip);
> -+static int ccs_write_inet_network(struct ccs_acl_param *param);
> -+static int ccs_write_unix_network(struct ccs_acl_param *param);
> -+static void ccs_print_ip(char *buf, const unsigned int size,
> -+			 const struct ccs_ipaddr_union *ptr);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+static int ccs_write_capability(struct ccs_acl_param *param);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+static int ccs_write_misc(struct ccs_acl_param *param);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+static int ccs_write_ipc(struct ccs_acl_param *param);
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+static ssize_t ccs_write_self(struct file *file, const char __user *buf,
> -+			      size_t count, loff_t *ppos);
> -+#endif
> -+
> -+/***** SECTION4: Standalone functions section *****/
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
> -+
> -+/**
> -+ * fatal_signal_pending - Check whether SIGKILL is pending or not.
> -+ *
> -+ * @p: Pointer to "struct task_struct".
> -+ *
> -+ * Returns true if SIGKILL is pending on @p, false otherwise.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+#define fatal_signal_pending(p) (signal_pending(p) &&			\
> -+				 sigismember(&p->pending.signal, SIGKILL))
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+
> -+/**
> -+ * __wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
> -+ *
> -+ * @wq:        The waitqueue to wait on.
> -+ * @condition: A C expression for the event to wait for.
> -+ * @ret:       Timeout, in jiffies.
> -+ *
> -+ * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
> -+ * signal, and the remaining jiffies otherwise if the condition evaluated to
> -+ * true before the timeout elapsed.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+#define __wait_event_interruptible_timeout(wq, condition, ret)		\
> -+do {									\
> -+	wait_queue_t __wait;						\
> -+	init_waitqueue_entry(&__wait, current);				\
> -+									\
> -+	add_wait_queue(&wq, &__wait);					\
> -+	for (;;) {							\
> -+		set_current_state(TASK_INTERRUPTIBLE);			\
> -+		if (condition)						\
> -+			break;						\
> -+		if (!signal_pending(current)) {				\
> -+			ret = schedule_timeout(ret);			\
> -+			if (!ret)					\
> -+				break;					\
> -+			continue;					\
> -+		}							\
> -+		ret = -ERESTARTSYS;					\
> -+		break;							\
> -+	}								\
> -+	current->state = TASK_RUNNING;					\
> -+	remove_wait_queue(&wq, &__wait);				\
> -+} while (0)
> -+
> -+/**
> -+ * wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
> -+ *
> -+ * @wq:        The waitqueue to wait on.
> -+ * @condition: A C expression for the event to wait for.
> -+ * @timeout:   Timeout, in jiffies.
> -+ *
> -+ * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
> -+ * signal, and the remaining jiffies otherwise if the condition evaluated to
> -+ * true before the timeout elapsed.
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+#define wait_event_interruptible_timeout(wq, condition, timeout)	\
> -+({									\
> -+	long __ret = timeout;						\
> -+	if (!(condition))						\
> -+		__wait_event_interruptible_timeout(wq, condition, __ret); \
> -+	__ret;								\
> -+})
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
> -+ *
> -+ * @time:  Seconds since 1970/01/01 00:00:00.
> -+ * @stamp: Pointer to "struct ccs_time".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * This function does not handle Y2038 problem.
> -+ */
> -+static void ccs_convert_time(time_t time, struct ccs_time *stamp)
> -+{
> -+	static const u16 ccs_eom[2][12] = {
> -+		{ 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
> -+		{ 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
> -+	};
> -+	u16 y;
> -+	u8 m;
> -+	bool r;
> -+	stamp->sec = time % 60;
> -+	time /= 60;
> -+	stamp->min = time % 60;
> -+	time /= 60;
> -+	stamp->hour = time % 24;
> -+	time /= 24;
> -+	for (y = 1970; ; y++) {
> -+		const unsigned short days = (y & 3) ? 365 : 366;
> -+		if (time < days)
> -+			break;
> -+		time -= days;
> -+	}
> -+	r = (y & 3) == 0;
> -+	for (m = 0; m < 11 && time >= ccs_eom[r][m]; m++);
> -+	if (m)
> -+		time -= ccs_eom[r][m - 1];
> -+	stamp->year = y;
> -+	stamp->month = ++m;
> -+	stamp->day = ++time;
> -+}
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 23)
> -+#if !defined(RHEL_VERSION) || RHEL_VERSION != 3
> -+
> -+/**
> -+ * PDE - Get "struct proc_dir_entry".
> -+ *
> -+ * @inode: Pointer to "struct inode".
> -+ *
> -+ * Returns pointer to "struct proc_dir_entry".
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline struct proc_dir_entry *PDE(const struct inode *inode)
> -+{
> -+	return (struct proc_dir_entry *) inode->u.generic_ip;
> -+}
> -+
> -+#endif
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+
> -+/**
> -+ * proc_notify_change - Update inode's attributes and reflect to the dentry.
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @iattr:  Pointer to "struct iattr".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * The 2.4 kernels don't allow chmod()/chown() for files in /proc,
> -+ * while the 2.6 kernels allow.
> -+ * To permit management of /proc/ccs/ interface by non-root user,
> -+ * I modified to allow chmod()/chown() of /proc/ccs/ interface like 2.6 kernels
> -+ * by adding "struct inode_operations"->setattr hook.
> -+ */
> -+static int proc_notify_change(struct dentry *dentry, struct iattr *iattr)
> -+{
> -+	struct inode *inode = dentry->d_inode;
> -+	struct proc_dir_entry *de = PDE(inode);
> -+	int error;
> -+
> -+	error = inode_change_ok(inode, iattr);
> -+	if (error)
> -+		goto out;
> -+
> -+	error = inode_setattr(inode, iattr);
> -+	if (error)
> -+		goto out;
> -+
> -+	de->uid = inode->i_uid;
> -+	de->gid = inode->i_gid;
> -+	de->mode = inode->i_mode;
> -+out:
> -+	return error;
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && defined(CONFIG_NET)
> -+#define ccs_in4_pton in4_pton
> -+#define ccs_in6_pton in6_pton
> -+#else
> -+/*
> -+ * Routines for parsing IPv4 or IPv6 address.
> -+ * These are copied from lib/hexdump.c net/core/utils.c .
> -+ */
> -+#include <linux/ctype.h>
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
> -+static int hex_to_bin(char ch)
> -+{
> -+	if ((ch >= '0') && (ch <= '9'))
> -+		return ch - '0';
> -+	ch = tolower(ch);
> -+	if ((ch >= 'a') && (ch <= 'f'))
> -+		return ch - 'a' + 10;
> -+	return -1;
> -+}
> -+#endif
> -+
> -+#define IN6PTON_XDIGIT		0x00010000
> -+#define IN6PTON_DIGIT		0x00020000
> -+#define IN6PTON_COLON_MASK	0x00700000
> -+#define IN6PTON_COLON_1		0x00100000	/* single : requested */
> -+#define IN6PTON_COLON_2		0x00200000	/* second : requested */
> -+#define IN6PTON_COLON_1_2	0x00400000	/* :: requested */
> -+#define IN6PTON_DOT		0x00800000	/* . */
> -+#define IN6PTON_DELIM		0x10000000
> -+#define IN6PTON_NULL		0x20000000	/* first/tail */
> -+#define IN6PTON_UNKNOWN		0x40000000
> -+
> -+static inline int xdigit2bin(char c, int delim)
> -+{
> -+	int val;
> -+
> -+	if (c == delim || c == '\0')
> -+		return IN6PTON_DELIM;
> -+	if (c == ':')
> -+		return IN6PTON_COLON_MASK;
> -+	if (c == '.')
> -+		return IN6PTON_DOT;
> -+
> -+	val = hex_to_bin(c);
> -+	if (val >= 0)
> -+		return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0);
> -+
> -+	if (delim == -1)
> -+		return IN6PTON_DELIM;
> -+	return IN6PTON_UNKNOWN;
> -+}
> -+
> -+static int ccs_in4_pton(const char *src, int srclen, u8 *dst, int delim,
> -+			const char **end)
> -+{
> -+	const char *s;
> -+	u8 *d;
> -+	u8 dbuf[4];
> -+	int ret = 0;
> -+	int i;
> -+	int w = 0;
> -+
> -+	if (srclen < 0)
> -+		srclen = strlen(src);
> -+	s = src;
> -+	d = dbuf;
> -+	i = 0;
> -+	while (1) {
> -+		int c;
> -+		c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
> -+		if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM |
> -+			   IN6PTON_COLON_MASK)))
> -+			goto out;
> -+		if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
> -+			if (w == 0)
> -+				goto out;
> -+			*d++ = w & 0xff;
> -+			w = 0;
> -+			i++;
> -+			if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
> -+				if (i != 4)
> -+					goto out;
> -+				break;
> -+			}
> -+			goto cont;
> -+		}
> -+		w = (w * 10) + c;
> -+		if ((w & 0xffff) > 255)
> -+			goto out;
> -+cont:
> -+		if (i >= 4)
> -+			goto out;
> -+		s++;
> -+		srclen--;
> -+	}
> -+	ret = 1;
> -+	memcpy(dst, dbuf, sizeof(dbuf));
> -+out:
> -+	if (end)
> -+		*end = s;
> -+	return ret;
> -+}
> -+
> -+static int ccs_in6_pton(const char *src, int srclen, u8 *dst, int delim,
> -+			const char **end)
> -+{
> -+	const char *s, *tok = NULL;
> -+	u8 *d, *dc = NULL;
> -+	u8 dbuf[16];
> -+	int ret = 0;
> -+	int i;
> -+	int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL;
> -+	int w = 0;
> -+
> -+	memset(dbuf, 0, sizeof(dbuf));
> -+
> -+	s = src;
> -+	d = dbuf;
> -+	if (srclen < 0)
> -+		srclen = strlen(src);
> -+
> -+	while (1) {
> -+		int c;
> -+
> -+		c = xdigit2bin(srclen > 0 ? *s : '\0', delim);
> -+		if (!(c & state))
> -+			goto out;
> -+		if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) {
> -+			/* process one 16-bit word */
> -+			if (!(state & IN6PTON_NULL)) {
> -+				*d++ = (w >> 8) & 0xff;
> -+				*d++ = w & 0xff;
> -+			}
> -+			w = 0;
> -+			if (c & IN6PTON_DELIM) {
> -+				/* We've processed last word */
> -+				break;
> -+			}
> -+			/*
> -+			 * COLON_1 => XDIGIT
> -+			 * COLON_2 => XDIGIT|DELIM
> -+			 * COLON_1_2 => COLON_2
> -+			 */
> -+			switch (state & IN6PTON_COLON_MASK) {
> -+			case IN6PTON_COLON_2:
> -+				dc = d;
> -+				state = IN6PTON_XDIGIT | IN6PTON_DELIM;
> -+				if (dc - dbuf >= sizeof(dbuf))
> -+					state |= IN6PTON_NULL;
> -+				break;
> -+			case IN6PTON_COLON_1|IN6PTON_COLON_1_2:
> -+				state = IN6PTON_XDIGIT | IN6PTON_COLON_2;
> -+				break;
> -+			case IN6PTON_COLON_1:
> -+				state = IN6PTON_XDIGIT;
> -+				break;
> -+			case IN6PTON_COLON_1_2:
> -+				state = IN6PTON_COLON_2;
> -+				break;
> -+			default:
> -+				state = 0;
> -+			}
> -+			tok = s + 1;
> -+			goto cont;
> -+		}
> -+
> -+		if (c & IN6PTON_DOT) {
> -+			ret = ccs_in4_pton(tok ? tok : s, srclen +
> -+					   (int)(s - tok), d, delim, &s);
> -+			if (ret > 0) {
> -+				d += 4;
> -+				break;
> -+			}
> -+			goto out;
> -+		}
> -+
> -+		w = (w << 4) | (0xff & c);
> -+		state = IN6PTON_COLON_1 | IN6PTON_DELIM;
> -+		if (!(w & 0xf000))
> -+			state |= IN6PTON_XDIGIT;
> -+		if (!dc && d + 2 < dbuf + sizeof(dbuf)) {
> -+			state |= IN6PTON_COLON_1_2;
> -+			state &= ~IN6PTON_DELIM;
> -+		}
> -+		if (d + 2 >= dbuf + sizeof(dbuf))
> -+			state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2);
> -+cont:
> -+		if ((dc && d + 4 < dbuf + sizeof(dbuf)) ||
> -+		    d + 4 == dbuf + sizeof(dbuf))
> -+			state |= IN6PTON_DOT;
> -+		if (d >= dbuf + sizeof(dbuf))
> -+			state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK);
> -+		s++;
> -+		srclen--;
> -+	}
> -+
> -+	i = 15; d--;
> -+
> -+	if (dc) {
> -+		while (d >= dc)
> -+			dst[i--] = *d--;
> -+		while (i >= dc - dbuf)
> -+			dst[i--] = 0;
> -+		while (i >= 0)
> -+			dst[i--] = *d--;
> -+	} else
> -+		memcpy(dst, dbuf, sizeof(dbuf));
> -+
> -+	ret = 1;
> -+out:
> -+	if (end)
> -+		*end = s;
> -+	return ret;
> -+}
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
> -+
> -+/*
> -+ * Routines for printing IPv4 or IPv6 address.
> -+ * These are copied from include/linux/kernel.h include/net/ipv6.h
> -+ * include/net/addrconf.h lib/hexdump.c lib/vsprintf.c and simplified.
> -+ */
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
> -+#if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5 || !defined(RHEL_MINOR) || RHEL_MINOR < 9
> -+static const char hex_asc[] = "0123456789abcdef";
> -+#define hex_asc_lo(x)   hex_asc[((x) & 0x0f)]
> -+#define hex_asc_hi(x)   hex_asc[((x) & 0xf0) >> 4]
> -+
> -+static inline char *pack_hex_byte(char *buf, u8 byte)
> -+{
> -+	*buf++ = hex_asc_hi(byte);
> -+	*buf++ = hex_asc_lo(byte);
> -+	return buf;
> -+}
> -+#endif
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
> -+static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
> -+{
> -+	return (a->s6_addr32[0] | a->s6_addr32[1] |
> -+		(a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0;
> -+}
> -+#endif
> -+
> -+static inline int ipv6_addr_is_isatap(const struct in6_addr *addr)
> -+{
> -+	return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
> -+}
> -+
> -+static char *ip4_string(char *p, const u8 *addr)
> -+{
> -+	/*
> -+	 * Since this function is called outside vsnprintf(), I can use
> -+	 * sprintf() here.
> -+	 */
> -+	return p +
> -+		sprintf(p, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
> -+}
> -+
> -+static char *ip6_compressed_string(char *p, const char *addr)
> -+{
> -+	int i, j, range;
> -+	unsigned char zerolength[8];
> -+	int longest = 1;
> -+	int colonpos = -1;
> -+	u16 word;
> -+	u8 hi, lo;
> -+	bool needcolon = false;
> -+	bool useIPv4;
> -+	struct in6_addr in6;
> -+
> -+	memcpy(&in6, addr, sizeof(struct in6_addr));
> -+
> -+	useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
> -+
> -+	memset(zerolength, 0, sizeof(zerolength));
> -+
> -+	if (useIPv4)
> -+		range = 6;
> -+	else
> -+		range = 8;
> -+
> -+	/* find position of longest 0 run */
> -+	for (i = 0; i < range; i++) {
> -+		for (j = i; j < range; j++) {
> -+			if (in6.s6_addr16[j] != 0)
> -+				break;
> -+			zerolength[i]++;
> -+		}
> -+	}
> -+	for (i = 0; i < range; i++) {
> -+		if (zerolength[i] > longest) {
> -+			longest = zerolength[i];
> -+			colonpos = i;
> -+		}
> -+	}
> -+	if (longest == 1)		/* don't compress a single 0 */
> -+		colonpos = -1;
> -+
> -+	/* emit address */
> -+	for (i = 0; i < range; i++) {
> -+		if (i == colonpos) {
> -+			if (needcolon || i == 0)
> -+				*p++ = ':';
> -+			*p++ = ':';
> -+			needcolon = false;
> -+			i += longest - 1;
> -+			continue;
> -+		}
> -+		if (needcolon) {
> -+			*p++ = ':';
> -+			needcolon = false;
> -+		}
> -+		/* hex u16 without leading 0s */
> -+		word = ntohs(in6.s6_addr16[i]);
> -+		hi = word >> 8;
> -+		lo = word & 0xff;
> -+		if (hi) {
> -+			if (hi > 0x0f)
> -+				p = pack_hex_byte(p, hi);
> -+			else
> -+				*p++ = hex_asc_lo(hi);
> -+			p = pack_hex_byte(p, lo);
> -+		} else if (lo > 0x0f)
> -+			p = pack_hex_byte(p, lo);
> -+		else
> -+			*p++ = hex_asc_lo(lo);
> -+		needcolon = true;
> -+	}
> -+
> -+	if (useIPv4) {
> -+		if (needcolon)
> -+			*p++ = ':';
> -+		p = ip4_string(p, &in6.s6_addr[12]);
> -+	}
> -+	*p = '\0';
> -+
> -+	return p;
> -+}
> -+#endif
> -+
> -+/**
> -+ * ccs_print_ipv4 - Print an IPv4 address.
> -+ *
> -+ * @buffer:     Buffer to write to.
> -+ * @buffer_len: Size of @buffer.
> -+ * @ip:         Pointer to "u32 in network byte order".
> -+ *
> -+ * Returns written length.
> -+ */
> -+static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len,
> -+			  const u32 *ip)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
> -+	return snprintf(buffer, buffer_len, "%pI4", ip);
> -+#else
> -+	char addr[sizeof("255.255.255.255")];
> -+	ip4_string(addr, (const u8 *) ip);
> -+	return snprintf(buffer, buffer_len, "%s", addr);
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_print_ipv6 - Print an IPv6 address.
> -+ *
> -+ * @buffer:     Buffer to write to.
> -+ * @buffer_len: Size of @buffer.
> -+ * @ip:         Pointer to "struct in6_addr".
> -+ *
> -+ * Returns written length.
> -+ */
> -+static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len,
> -+			  const struct in6_addr *ip)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
> -+	return snprintf(buffer, buffer_len, "%pI6c", ip);
> -+#else
> -+	char addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
> -+	ip6_compressed_string(addr, (const u8 *) ip);
> -+	return snprintf(buffer, buffer_len, "%s", addr);
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_print_ip - Print an IP address.
> -+ *
> -+ * @buf:  Buffer to write to.
> -+ * @size: Size of @buf.
> -+ * @ptr:  Pointer to "struct ipaddr_union".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_print_ip(char *buf, const unsigned int size,
> -+			 const struct ccs_ipaddr_union *ptr)
> -+{
> -+	int len;
> -+	if (ptr->is_ipv6)
> -+		len = ccs_print_ipv6(buf, size, &ptr->ip[0]);
> -+	else
> -+		len = ccs_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0]);
> -+	if (!memcmp(&ptr->ip[0], &ptr->ip[1], 16) || len >= size / 2)
> -+		return;
> -+	buf[len++] = '-';
> -+	if (ptr->is_ipv6)
> -+		ccs_print_ipv6(buf + len, size - len, &ptr->ip[1]);
> -+	else
> -+		ccs_print_ipv4(buf + len, size - len,
> -+			       &ptr->ip[1].s6_addr32[0]);
> -+}
> -+
> -+#endif
> -+
> -+/***** SECTION5: Variables definition section *****/
> -+
> -+/* Permit policy management by non-root user? */
> -+static bool ccs_manage_by_non_root;
> -+
> -+/* Lock for protecting policy. */
> -+DEFINE_MUTEX(ccs_policy_lock);
> -+
> -+/* Has /sbin/init started? */
> -+bool ccs_policy_loaded;
> -+
> -+/* List of namespaces. */
> -+LIST_HEAD(ccs_namespace_list);
> -+/* True if namespace other than ccs_kernel_namespace is defined. */
> -+static bool ccs_namespace_enabled;
> -+
> -+/* Initial namespace.*/
> -+static struct ccs_policy_namespace ccs_kernel_namespace;
> -+
> -+/* List of "struct ccs_condition". */
> -+LIST_HEAD(ccs_condition_list);
> -+
> -+#ifdef CONFIG_CCSECURITY_PORTRESERVE
> -+/* Bitmap for reserved local port numbers.*/
> -+static u8 ccs_reserved_port_map[8192];
> -+#endif
> -+
> -+/* Wait queue for kernel -> userspace notification. */
> -+static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
> -+/* Wait queue for userspace -> kernel notification. */
> -+static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);
> -+
> -+/* The list for "struct ccs_query". */
> -+static LIST_HEAD(ccs_query_list);
> -+
> -+/* Lock for manipulating ccs_query_list. */
> -+static DEFINE_SPINLOCK(ccs_query_list_lock);
> -+
> -+/* Number of "struct file" referring /proc/ccs/query interface. */
> -+static atomic_t ccs_query_observers = ATOMIC_INIT(0);
> -+
> -+/* Wait queue for /proc/ccs/audit. */
> -+static DECLARE_WAIT_QUEUE_HEAD(ccs_log_wait);
> -+
> -+/* The list for "struct ccs_log". */
> -+static LIST_HEAD(ccs_log);
> -+
> -+/* Lock for "struct list_head ccs_log". */
> -+static DEFINE_SPINLOCK(ccs_log_lock);
> -+
> -+/* Length of "stuct list_head ccs_log". */
> -+static unsigned int ccs_log_count;
> -+
> -+/* Timestamp counter for last updated. */
> -+static unsigned int ccs_stat_updated[CCS_MAX_POLICY_STAT];
> -+
> -+/* Counter for number of updates. */
> -+static unsigned int ccs_stat_modified[CCS_MAX_POLICY_STAT];
> -+
> -+/* Operations for /proc/ccs/self_domain interface. */
> -+static
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
> -+const
> -+#endif
> -+struct file_operations ccs_self_operations = {
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+	.write = ccs_write_self,
> -+#endif
> -+	.read  = ccs_read_self,
> -+};
> -+
> -+/* Operations for /proc/ccs/ interface. */
> -+static
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
> -+const
> -+#endif
> -+struct file_operations ccs_operations = {
> -+	.open    = ccs_open,
> -+	.release = ccs_release,
> -+	.poll    = ccs_poll,
> -+	.read    = ccs_read,
> -+	.write   = ccs_write,
> -+};
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+
> -+/* The inode operations for /proc/ccs/ directory. */
> -+static struct inode_operations ccs_dir_inode_operations;
> -+
> -+/* The inode operations for files under /proc/ccs/ directory. */
> -+static struct inode_operations ccs_file_inode_operations;
> -+
> -+#endif
> -+
> -+/***** SECTION6: Dependent functions section *****/
> -+
> -+/**
> -+ * list_for_each_cookie - iterate over a list with cookie.
> -+ *
> -+ * @pos:  Pointer to "struct list_head".
> -+ * @head: Pointer to "struct list_head".
> -+ */
> -+#define list_for_each_cookie(pos, head)					\
> -+	for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \
> -+	     pos != (head); pos = srcu_dereference(pos->next, &ccs_ss))
> -+
> -+/**
> -+ * ccs_read_token - Read a word from a line.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns a word on success, "" otherwise.
> -+ *
> -+ * To allow the caller to skip NULL check, this function returns "" rather than
> -+ * NULL if there is no more words to read.
> -+ */
> -+static char *ccs_read_token(struct ccs_acl_param *param)
> -+{
> -+	char *pos = param->data;
> -+	char *del = strchr(pos, ' ');
> -+	if (del)
> -+		*del++ = '\0';
> -+	else
> -+		del = pos + strlen(pos);
> -+	param->data = del;
> -+	return pos;
> -+}
> -+
> -+/**
> -+ * ccs_make_byte - Make byte value from three octal characters.
> -+ *
> -+ * @c1: The first character.
> -+ * @c2: The second character.
> -+ * @c3: The third character.
> -+ *
> -+ * Returns byte value.
> -+ */
> -+static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3)
> -+{
> -+	return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
> -+}
> -+
> -+/**
> -+ * ccs_correct_word2 - Check whether the given string follows the naming rules.
> -+ *
> -+ * @string: The byte sequence to check. Not '\0'-terminated.
> -+ * @len:    Length of @string.
> -+ *
> -+ * Returns true if @string follows the naming rules, false otherwise.
> -+ */
> -+static bool ccs_correct_word2(const char *string, size_t len)
> -+{
> -+	const char *const start = string;
> -+	bool in_repetition = false;
> -+	unsigned char c;
> -+	unsigned char d;
> -+	unsigned char e;
> -+	if (!len)
> -+		goto out;
> -+	while (len--) {
> -+		c = *string++;
> -+		if (c == '\\') {
> -+			if (!len--)
> -+				goto out;
> -+			c = *string++;
> -+			switch (c) {
> -+			case '\\':  /* "\\" */
> -+				continue;
> -+			case '$':   /* "\$" */
> -+			case '+':   /* "\+" */
> -+			case '?':   /* "\?" */
> -+			case '*':   /* "\*" */
> -+			case '@':   /* "\@" */
> -+			case 'x':   /* "\x" */
> -+			case 'X':   /* "\X" */
> -+			case 'a':   /* "\a" */
> -+			case 'A':   /* "\A" */
> -+			case '-':   /* "\-" */
> -+				continue;
> -+			case '{':   /* "/\{" */
> -+				if (string - 3 < start || *(string - 3) != '/')
> -+					break;
> -+				in_repetition = true;
> -+				continue;
> -+			case '}':   /* "\}/" */
> -+				if (*string != '/')
> -+					break;
> -+				if (!in_repetition)
> -+					break;
> -+				in_repetition = false;
> -+				continue;
> -+			case '0':   /* "\ooo" */
> -+			case '1':
> -+			case '2':
> -+			case '3':
> -+				if (!len-- || !len--)
> -+					break;
> -+				d = *string++;
> -+				e = *string++;
> -+				if (d < '0' || d > '7' || e < '0' || e > '7')
> -+					break;
> -+				c = ccs_make_byte(c, d, e);
> -+				if (c <= ' ' || c >= 127)
> -+					continue;
> -+			}
> -+			goto out;
> -+		} else if (in_repetition && c == '/') {
> -+			goto out;
> -+		} else if (c <= ' ' || c >= 127) {
> -+			goto out;
> -+		}
> -+	}
> -+	if (in_repetition)
> -+		goto out;
> -+	return true;
> -+out:
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_correct_word - Check whether the given string follows the naming rules.
> -+ *
> -+ * @string: The string to check.
> -+ *
> -+ * Returns true if @string follows the naming rules, false otherwise.
> -+ */
> -+static bool ccs_correct_word(const char *string)
> -+{
> -+	return ccs_correct_word2(string, strlen(string));
> -+}
> -+
> -+/**
> -+ * ccs_get_group - Allocate memory for "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group".
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ * @idx:   Index number.
> -+ *
> -+ * Returns pointer to "struct ccs_group" on success, NULL otherwise.
> -+ */
> -+static struct ccs_group *ccs_get_group(struct ccs_acl_param *param,
> -+				       const u8 idx)
> -+{
> -+	struct ccs_group e = { };
> -+	struct ccs_group *group = NULL;
> -+	struct list_head *list;
> -+	const char *group_name = ccs_read_token(param);
> -+	bool found = false;
> -+	if (!ccs_correct_word(group_name) || idx >= CCS_MAX_GROUP)
> -+		return NULL;
> -+	e.group_name = ccs_get_name(group_name);
> -+	if (!e.group_name)
> -+		return NULL;
> -+	if (mutex_lock_interruptible(&ccs_policy_lock))
> -+		goto out;
> -+	list = &param->ns->group_list[idx];
> -+	list_for_each_entry(group, list, head.list) {
> -+		if (e.group_name != group->group_name ||
> -+		    atomic_read(&group->head.users) == CCS_GC_IN_PROGRESS)
> -+			continue;
> -+		atomic_inc(&group->head.users);
> -+		found = true;
> -+		break;
> -+	}
> -+	if (!found) {
> -+		struct ccs_group *entry = ccs_commit_ok(&e, sizeof(e));
> -+		if (entry) {
> -+			INIT_LIST_HEAD(&entry->member_list);
> -+			atomic_set(&entry->head.users, 1);
> -+			list_add_tail_rcu(&entry->head.list, list);
> -+			group = entry;
> -+			found = true;
> -+		}
> -+	}
> -+	mutex_unlock(&ccs_policy_lock);
> -+out:
> -+	ccs_put_name(e.group_name);
> -+	return found ? group : NULL;
> -+}
> -+
> -+/**
> -+ * ccs_parse_name_union - Parse a ccs_name_union.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ * @ptr:   Pointer to "struct ccs_name_union".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_parse_name_union(struct ccs_acl_param *param,
> -+				 struct ccs_name_union *ptr)
> -+{
> -+	char *filename;
> -+	if (param->data[0] == '@') {
> -+		param->data++;
> -+		ptr->group = ccs_get_group(param, CCS_PATH_GROUP);
> -+		return ptr->group != NULL;
> -+	}
> -+	filename = ccs_read_token(param);
> -+	if (!ccs_correct_word(filename))
> -+		return false;
> -+	ptr->filename = ccs_get_name(filename);
> -+	return ptr->filename != NULL;
> -+}
> -+
> -+/**
> -+ * ccs_parse_ulong - Parse an "unsigned long" value.
> -+ *
> -+ * @result: Pointer to "unsigned long".
> -+ * @str:    Pointer to string to parse.
> -+ *
> -+ * Returns one of values in "enum ccs_value_type".
> -+ *
> -+ * The @src is updated to point the first character after the value
> -+ * on success.
> -+ */
> -+static u8 ccs_parse_ulong(unsigned long *result, char **str)
> -+{
> -+	const char *cp = *str;
> -+	char *ep;
> -+	int base = 10;
> -+	if (*cp == '0') {
> -+		char c = *(cp + 1);
> -+		if (c == 'x' || c == 'X') {
> -+			base = 16;
> -+			cp += 2;
> -+		} else if (c >= '0' && c <= '7') {
> -+			base = 8;
> -+			cp++;
> -+		}
> -+	}
> -+	*result = simple_strtoul(cp, &ep, base);
> -+	if (cp == ep)
> -+		return CCS_VALUE_TYPE_INVALID;
> -+	*str = ep;
> -+	switch (base) {
> -+	case 16:
> -+		return CCS_VALUE_TYPE_HEXADECIMAL;
> -+	case 8:
> -+		return CCS_VALUE_TYPE_OCTAL;
> -+	default:
> -+		return CCS_VALUE_TYPE_DECIMAL;
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_parse_number_union - Parse a ccs_number_union.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ * @ptr:   Pointer to "struct ccs_number_union".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_parse_number_union(struct ccs_acl_param *param,
> -+				   struct ccs_number_union *ptr)
> -+{
> -+	char *data;
> -+	u8 type;
> -+	unsigned long v;
> -+	memset(ptr, 0, sizeof(*ptr));
> -+	if (param->data[0] == '@') {
> -+		param->data++;
> -+		ptr->group = ccs_get_group(param, CCS_NUMBER_GROUP);
> -+		return ptr->group != NULL;
> -+	}
> -+	data = ccs_read_token(param);
> -+	type = ccs_parse_ulong(&v, &data);
> -+	if (type == CCS_VALUE_TYPE_INVALID)
> -+		return false;
> -+	ptr->values[0] = v;
> -+	ptr->value_type[0] = type;
> -+	if (!*data) {
> -+		ptr->values[1] = v;
> -+		ptr->value_type[1] = type;
> -+		return true;
> -+	}
> -+	if (*data++ != '-')
> -+		return false;
> -+	type = ccs_parse_ulong(&v, &data);
> -+	if (type == CCS_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
> -+		return false;
> -+	ptr->values[1] = v;
> -+	ptr->value_type[1] = type;
> -+	return true;
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+
> -+/**
> -+ * ccs_parse_ipaddr_union - Parse an IP address.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ * @ptr:   Pointer to "struct ccs_ipaddr_union".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param,
> -+				   struct ccs_ipaddr_union *ptr)
> -+{
> -+	u8 * const min = ptr->ip[0].in6_u.u6_addr8;
> -+	u8 * const max = ptr->ip[1].in6_u.u6_addr8;
> -+	char *address = ccs_read_token(param);
> -+	const char *end;
> -+	if (!strchr(address, ':') &&
> -+	    ccs_in4_pton(address, -1, min, '-', &end) > 0) {
> -+		ptr->is_ipv6 = false;
> -+		if (!*end)
> -+			ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
> -+		else if (*end++ != '-' ||
> -+			 ccs_in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
> -+			return false;
> -+		return true;
> -+	}
> -+	if (ccs_in6_pton(address, -1, min, '-', &end) > 0) {
> -+		ptr->is_ipv6 = true;
> -+		if (!*end)
> -+			memmove(max, min, sizeof(u16) * 8);
> -+		else if (*end++ != '-' ||
> -+			 ccs_in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
> -+			return false;
> -+		return true;
> -+	}
> -+	return false;
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_get_dqword - ccs_get_name() for a quoted string.
> -+ *
> -+ * @start: String to save.
> -+ *
> -+ * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
> -+ */
> -+static const struct ccs_path_info *ccs_get_dqword(char *start)
> -+{
> -+	char *cp = start + strlen(start) - 1;
> -+	if (cp == start || *start++ != '"' || *cp != '"')
> -+		return NULL;
> -+	*cp = '\0';
> -+	if (*start && !ccs_correct_word(start))
> -+		return NULL;
> -+	return ccs_get_name(start);
> -+}
> -+
> -+/**
> -+ * ccs_parse_name_union_quoted - Parse a quoted word.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ * @ptr:   Pointer to "struct ccs_name_union".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param,
> -+					struct ccs_name_union *ptr)
> -+{
> -+	char *filename = param->data;
> -+	if (*filename == '@')
> -+		return ccs_parse_name_union(param, ptr);
> -+	ptr->filename = ccs_get_dqword(filename);
> -+	return ptr->filename != NULL;
> -+}
> -+
> -+/**
> -+ * ccs_parse_argv - Parse an argv[] condition part.
> -+ *
> -+ * @left:  Lefthand value.
> -+ * @right: Righthand value.
> -+ * @argv:  Pointer to "struct ccs_argv".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv)
> -+{
> -+	if (ccs_parse_ulong(&argv->index, &left) != CCS_VALUE_TYPE_DECIMAL ||
> -+	    *left++ != ']' || *left)
> -+		return false;
> -+	argv->value = ccs_get_dqword(right);
> -+	return argv->value != NULL;
> -+}
> -+
> -+/**
> -+ * ccs_parse_envp - Parse an envp[] condition part.
> -+ *
> -+ * @left:  Lefthand value.
> -+ * @right: Righthand value.
> -+ * @envp:  Pointer to "struct ccs_envp".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp)
> -+{
> -+	const struct ccs_path_info *name;
> -+	const struct ccs_path_info *value;
> -+	char *cp = left + strlen(left) - 1;
> -+	if (*cp-- != ']' || *cp != '"')
> -+		goto out;
> -+	*cp = '\0';
> -+	if (!ccs_correct_word(left))
> -+		goto out;
> -+	name = ccs_get_name(left);
> -+	if (!name)
> -+		goto out;
> -+	if (!strcmp(right, "NULL")) {
> -+		value = NULL;
> -+	} else {
> -+		value = ccs_get_dqword(right);
> -+		if (!value) {
> -+			ccs_put_name(name);
> -+			goto out;
> -+		}
> -+	}
> -+	envp->name = name;
> -+	envp->value = value;
> -+	return true;
> -+out:
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_same_condition - Check for duplicated "struct ccs_condition" entry.
> -+ *
> -+ * @a: Pointer to "struct ccs_condition".
> -+ * @b: Pointer to "struct ccs_condition".
> -+ *
> -+ * Returns true if @a == @b, false otherwise.
> -+ */
> -+static bool ccs_same_condition(const struct ccs_condition *a,
> -+			       const struct ccs_condition *b)
> -+{
> -+	return a->size == b->size && a->condc == b->condc &&
> -+		a->numbers_count == b->numbers_count &&
> -+		a->names_count == b->names_count &&
> -+		a->argc == b->argc && a->envc == b->envc &&
> -+		a->grant_log == b->grant_log &&
> -+		a->exec_transit == b->exec_transit && a->transit == b->transit
> -+		&& !memcmp(a + 1, b + 1, a->size - sizeof(*a));
> -+}
> -+
> -+/**
> -+ * ccs_condition_type - Get condition type.
> -+ *
> -+ * @word: Keyword string.
> -+ *
> -+ * Returns one of values in "enum ccs_conditions_index" on success,
> -+ * CCS_MAX_CONDITION_KEYWORD otherwise.
> -+ */
> -+static u8 ccs_condition_type(const char *word)
> -+{
> -+	u8 i;
> -+	for (i = 0; i < CCS_MAX_CONDITION_KEYWORD; i++) {
> -+		if (!strcmp(word, ccs_condition_keyword[i]))
> -+			break;
> -+	}
> -+	return i;
> -+}
> -+
> -+/**
> -+ * ccs_commit_condition - Commit "struct ccs_condition".
> -+ *
> -+ * @entry: Pointer to "struct ccs_condition".
> -+ *
> -+ * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
> -+ *
> -+ * This function merges duplicated entries. This function returns NULL if
> -+ * @entry is not duplicated but memory quota for policy has exceeded.
> -+ */
> -+static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry)
> -+{
> -+	struct ccs_condition *ptr;
> -+	bool found = false;
> -+	if (mutex_lock_interruptible(&ccs_policy_lock)) {
> -+		dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
> -+		ptr = NULL;
> -+		found = true;
> -+		goto out;
> -+	}
> -+	list_for_each_entry(ptr, &ccs_condition_list, head.list) {
> -+		if (!ccs_same_condition(ptr, entry) ||
> -+		    atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS)
> -+			continue;
> -+		/* Same entry found. Share this entry. */
> -+		atomic_inc(&ptr->head.users);
> -+		found = true;
> -+		break;
> -+	}
> -+	if (!found) {
> -+		if (ccs_memory_ok(entry, entry->size)) {
> -+			atomic_set(&entry->head.users, 1);
> -+			list_add(&entry->head.list, &ccs_condition_list);
> -+		} else {
> -+			found = true;
> -+			ptr = NULL;
> -+		}
> -+	}
> -+	mutex_unlock(&ccs_policy_lock);
> -+out:
> -+	if (found) {
> -+		ccs_del_condition(&entry->head.list);
> -+		kfree(entry);
> -+		entry = ptr;
> -+	}
> -+	return entry;
> -+}
> -+
> -+/**
> -+ * ccs_correct_path - Check whether the given pathname follows the naming rules.
> -+ *
> -+ * @filename: The pathname to check.
> -+ *
> -+ * Returns true if @filename follows the naming rules, false otherwise.
> -+ */
> -+static bool ccs_correct_path(const char *filename)
> -+{
> -+	return *filename == '/' && ccs_correct_word(filename);
> -+}
> -+
> -+/**
> -+ * ccs_domain_def - Check whether the given token can be a domainname.
> -+ *
> -+ * @buffer: The token to check.
> -+ *
> -+ * Returns true if @buffer possibly be a domainname, false otherwise.
> -+ */
> -+static bool ccs_domain_def(const unsigned char *buffer)
> -+{
> -+	const unsigned char *cp;
> -+	int len;
> -+	if (*buffer != '<')
> -+		return false;
> -+	cp = strchr(buffer, ' ');
> -+	if (!cp)
> -+		len = strlen(buffer);
> -+	else
> -+		len = cp - buffer;
> -+	if (buffer[len - 1] != '>' || !ccs_correct_word2(buffer + 1, len - 2))
> -+		return false;
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_correct_domain - Check whether the given domainname follows the naming rules.
> -+ *
> -+ * @domainname: The domainname to check.
> -+ *
> -+ * Returns true if @domainname follows the naming rules, false otherwise.
> -+ */
> -+static bool ccs_correct_domain(const unsigned char *domainname)
> -+{
> -+	if (!domainname || !ccs_domain_def(domainname))
> -+		return false;
> -+	domainname = strchr(domainname, ' ');
> -+	if (!domainname++)
> -+		return true;
> -+	while (1) {
> -+		const unsigned char *cp = strchr(domainname, ' ');
> -+		if (!cp)
> -+			break;
> -+		if (*domainname != '/' ||
> -+		    !ccs_correct_word2(domainname, cp - domainname))
> -+			return false;
> -+		domainname = cp + 1;
> -+	}
> -+	return ccs_correct_path(domainname);
> -+}
> -+
> -+/**
> -+ * ccs_normalize_line - Format string.
> -+ *
> -+ * @buffer: The line to normalize.
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Leading and trailing whitespaces are removed.
> -+ * Multiple whitespaces are packed into single space.
> -+ */
> -+static void ccs_normalize_line(unsigned char *buffer)
> -+{
> -+	unsigned char *sp = buffer;
> -+	unsigned char *dp = buffer;
> -+	bool first = true;
> -+	while (*sp && (*sp <= ' ' || *sp >= 127))
> -+		sp++;
> -+	while (*sp) {
> -+		if (!first)
> -+			*dp++ = ' ';
> -+		first = false;
> -+		while (*sp > ' ' && *sp < 127)
> -+			*dp++ = *sp++;
> -+		while (*sp && (*sp <= ' ' || *sp >= 127))
> -+			sp++;
> -+	}
> -+	*dp = '\0';
> -+}
> -+
> -+/**
> -+ * ccs_get_domainname - Read a domainname from a line.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns a domainname on success, NULL otherwise.
> -+ */
> -+static const struct ccs_path_info *ccs_get_domainname
> -+(struct ccs_acl_param *param)
> -+{
> -+	char *start = param->data;
> -+	char *pos = start;
> -+	while (*pos) {
> -+		if (*pos++ != ' ' || *pos++ == '/')
> -+			continue;
> -+		pos -= 2;
> -+		*pos++ = '\0';
> -+		break;
> -+	}
> -+	param->data = pos;
> -+	if (ccs_correct_domain(start))
> -+		return ccs_get_name(start);
> -+	return NULL;
> -+}
> -+
> -+/**
> -+ * ccs_get_transit_preference - Parse domain transition preference for execve().
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ * @e:     Pointer to "struct ccs_condition".
> -+ *
> -+ * Returns the condition string part.
> -+ */
> -+static char *ccs_get_transit_preference(struct ccs_acl_param *param,
> -+					struct ccs_condition *e)
> -+{
> -+	char * const pos = param->data;
> -+	bool flag;
> -+	if (*pos == '<') {
> -+		e->transit = ccs_get_domainname(param);
> -+		goto done;
> -+	}
> -+	{
> -+		char *cp = strchr(pos, ' ');
> -+		if (cp)
> -+			*cp = '\0';
> -+		flag = ccs_correct_path(pos) || !strcmp(pos, "keep") ||
> -+			!strcmp(pos, "initialize") || !strcmp(pos, "reset") ||
> -+			!strcmp(pos, "child") || !strcmp(pos, "parent");
> -+		if (cp)
> -+			*cp = ' ';
> -+	}
> -+	if (!flag)
> -+		return pos;
> -+	e->transit = ccs_get_name(ccs_read_token(param));
> -+done:
> -+	if (e->transit) {
> -+		e->exec_transit = true;
> -+		return param->data;
> -+	}
> -+	/*
> -+	 * Return a bad read-only condition string that will let
> -+	 * ccs_get_condition() return NULL.
> -+	 */
> -+	return "/";
> -+}
> -+
> -+/**
> -+ * ccs_get_condition - Parse condition part.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
> -+ */
> -+struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param)
> -+{
> -+	struct ccs_condition *entry = NULL;
> -+	struct ccs_condition_element *condp = NULL;
> -+	struct ccs_number_union *numbers_p = NULL;
> -+	struct ccs_name_union *names_p = NULL;
> -+	struct ccs_argv *argv = NULL;
> -+	struct ccs_envp *envp = NULL;
> -+	struct ccs_condition e = { };
> -+	char * const start_of_string = ccs_get_transit_preference(param, &e);
> -+	char * const end_of_string = start_of_string + strlen(start_of_string);
> -+	char *pos;
> -+rerun:
> -+	pos = start_of_string;
> -+	while (1) {
> -+		u8 left = -1;
> -+		u8 right = -1;
> -+		char *left_word = pos;
> -+		char *cp;
> -+		char *right_word;
> -+		bool is_not;
> -+		if (!*left_word)
> -+			break;
> -+		/*
> -+		 * Since left-hand condition does not allow use of "path_group"
> -+		 * or "number_group" and environment variable's names do not
> -+		 * accept '=', it is guaranteed that the original line consists
> -+		 * of one or more repetition of $left$operator$right blocks
> -+		 * where "$left is free from '=' and ' '" and "$operator is
> -+		 * either '=' or '!='" and "$right is free from ' '".
> -+		 * Therefore, we can reconstruct the original line at the end
> -+		 * of dry run even if we overwrite $operator with '\0'.
> -+		 */
> -+		cp = strchr(pos, ' ');
> -+		if (cp) {
> -+			*cp = '\0'; /* Will restore later. */
> -+			pos = cp + 1;
> -+		} else {
> -+			pos = "";
> -+		}
> -+		right_word = strchr(left_word, '=');
> -+		if (!right_word || right_word == left_word)
> -+			goto out;
> -+		is_not = *(right_word - 1) == '!';
> -+		if (is_not)
> -+			*(right_word++ - 1) = '\0'; /* Will restore later. */
> -+		else if (*(right_word + 1) != '=')
> -+			*right_word++ = '\0'; /* Will restore later. */
> -+		else
> -+			goto out;
> -+		dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word,
> -+			is_not ? "!" : "", right_word);
> -+		if (!strcmp(left_word, "grant_log")) {
> -+			if (entry) {
> -+				if (is_not ||
> -+				    entry->grant_log != CCS_GRANTLOG_AUTO)
> -+					goto out;
> -+				else if (!strcmp(right_word, "yes"))
> -+					entry->grant_log = CCS_GRANTLOG_YES;
> -+				else if (!strcmp(right_word, "no"))
> -+					entry->grant_log = CCS_GRANTLOG_NO;
> -+				else
> -+					goto out;
> -+			}
> -+			continue;
> -+		}
> -+		if (!strcmp(left_word, "auto_domain_transition")) {
> -+			if (entry) {
> -+				if (is_not || entry->transit)
> -+					goto out;
> -+				entry->transit = ccs_get_dqword(right_word);
> -+				if (!entry->transit ||
> -+				    (entry->transit->name[0] != '/' &&
> -+				     !ccs_domain_def(entry->transit->name)))
> -+					goto out;
> -+			}
> -+			continue;
> -+		}
> -+		if (!strncmp(left_word, "exec.argv[", 10)) {
> -+			if (!argv) {
> -+				e.argc++;
> -+				e.condc++;
> -+			} else {
> -+				e.argc--;
> -+				e.condc--;
> -+				left = CCS_ARGV_ENTRY;
> -+				argv->is_not = is_not;
> -+				if (!ccs_parse_argv(left_word + 10,
> -+						    right_word, argv++))
> -+					goto out;
> -+			}
> -+			goto store_value;
> -+		}
> -+		if (!strncmp(left_word, "exec.envp[\"", 11)) {
> -+			if (!envp) {
> -+				e.envc++;
> -+				e.condc++;
> -+			} else {
> -+				e.envc--;
> -+				e.condc--;
> -+				left = CCS_ENVP_ENTRY;
> -+				envp->is_not = is_not;
> -+				if (!ccs_parse_envp(left_word + 11,
> -+						    right_word, envp++))
> -+					goto out;
> -+			}
> -+			goto store_value;
> -+		}
> -+		left = ccs_condition_type(left_word);
> -+		dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word,
> -+			left);
> -+		if (left == CCS_MAX_CONDITION_KEYWORD) {
> -+			if (!numbers_p) {
> -+				e.numbers_count++;
> -+			} else {
> -+				e.numbers_count--;
> -+				left = CCS_NUMBER_UNION;
> -+				param->data = left_word;
> -+				if (*left_word == '@' ||
> -+				    !ccs_parse_number_union(param,
> -+							    numbers_p++))
> -+					goto out;
> -+			}
> -+		}
> -+		if (!condp)
> -+			e.condc++;
> -+		else
> -+			e.condc--;
> -+		if (left == CCS_EXEC_REALPATH || left == CCS_SYMLINK_TARGET) {
> -+			if (!names_p) {
> -+				e.names_count++;
> -+			} else {
> -+				e.names_count--;
> -+				right = CCS_NAME_UNION;
> -+				param->data = right_word;
> -+				if (!ccs_parse_name_union_quoted(param,
> -+								 names_p++))
> -+					goto out;
> -+			}
> -+			goto store_value;
> -+		}
> -+		right = ccs_condition_type(right_word);
> -+		if (right == CCS_MAX_CONDITION_KEYWORD) {
> -+			if (!numbers_p) {
> -+				e.numbers_count++;
> -+			} else {
> -+				e.numbers_count--;
> -+				right = CCS_NUMBER_UNION;
> -+				param->data = right_word;
> -+				if (!ccs_parse_number_union(param,
> -+							    numbers_p++))
> -+					goto out;
> -+			}
> -+		}
> -+store_value:
> -+		if (!condp) {
> -+			dprintk(KERN_WARNING "%u: dry_run left=%u right=%u "
> -+				"match=%u\n", __LINE__, left, right, !is_not);
> -+			continue;
> -+		}
> -+		condp->left = left;
> -+		condp->right = right;
> -+		condp->equals = !is_not;
> -+		dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n",
> -+			__LINE__, condp->left, condp->right,
> -+			condp->equals);
> -+		condp++;
> -+	}
> -+	dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n",
> -+		__LINE__, e.condc, e.numbers_count, e.names_count, e.argc,
> -+		e.envc);
> -+	if (entry) {
> -+		BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc |
> -+		       e.condc);
> -+		return ccs_commit_condition(entry);
> -+	}
> -+	e.size = sizeof(*entry)
> -+		+ e.condc * sizeof(struct ccs_condition_element)
> -+		+ e.numbers_count * sizeof(struct ccs_number_union)
> -+		+ e.names_count * sizeof(struct ccs_name_union)
> -+		+ e.argc * sizeof(struct ccs_argv)
> -+		+ e.envc * sizeof(struct ccs_envp);
> -+	entry = kzalloc(e.size, CCS_GFP_FLAGS);
> -+	if (!entry)
> -+		goto out2;
> -+	*entry = e;
> -+	e.transit = NULL;
> -+	condp = (struct ccs_condition_element *) (entry + 1);
> -+	numbers_p = (struct ccs_number_union *) (condp + e.condc);
> -+	names_p = (struct ccs_name_union *) (numbers_p + e.numbers_count);
> -+	argv = (struct ccs_argv *) (names_p + e.names_count);
> -+	envp = (struct ccs_envp *) (argv + e.argc);
> -+	{
> -+		bool flag = false;
> -+		for (pos = start_of_string; pos < end_of_string; pos++) {
> -+			if (*pos)
> -+				continue;
> -+			if (flag) /* Restore " ". */
> -+				*pos = ' ';
> -+			else if (*(pos + 1) == '=') /* Restore "!=". */
> -+				*pos = '!';
> -+			else /* Restore "=". */
> -+				*pos = '=';
> -+			flag = !flag;
> -+		}
> -+	}
> -+	goto rerun;
> -+out:
> -+	dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__);
> -+	if (entry) {
> -+		ccs_del_condition(&entry->head.list);
> -+		kfree(entry);
> -+	}
> -+out2:
> -+	ccs_put_name(e.transit);
> -+	return NULL;
> -+}
> -+
> -+/**
> -+ * ccs_yesno - Return "yes" or "no".
> -+ *
> -+ * @value: Bool value.
> -+ *
> -+ * Returns "yes" if @value is not 0, "no" otherwise.
> -+ */
> -+static const char *ccs_yesno(const unsigned int value)
> -+{
> -+	return value ? "yes" : "no";
> -+}
> -+
> -+/**
> -+ * ccs_addprintf - strncat()-like-snprintf().
> -+ *
> -+ * @buffer: Buffer to write to. Must be '\0'-terminated.
> -+ * @len:    Size of @buffer.
> -+ * @fmt:    The printf()'s format string, followed by parameters.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
> -+{
> -+	va_list args;
> -+	const int pos = strlen(buffer);
> -+	va_start(args, fmt);
> -+	vsnprintf(buffer + pos, len - pos - 1, fmt, args);
> -+	va_end(args);
> -+}
> -+
> -+/**
> -+ * ccs_flush - Flush queued string to userspace's buffer.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns true if all data was flushed, false otherwise.
> -+ */
> -+static bool ccs_flush(struct ccs_io_buffer *head)
> -+{
> -+	while (head->r.w_pos) {
> -+		const char *w = head->r.w[0];
> -+		size_t len = strlen(w);
> -+		if (len) {
> -+			if (len > head->read_user_buf_avail)
> -+				len = head->read_user_buf_avail;
> -+			if (!len)
> -+				return false;
> -+			if (copy_to_user(head->read_user_buf, w, len))
> -+				return false;
> -+			head->read_user_buf_avail -= len;
> -+			head->read_user_buf += len;
> -+			w += len;
> -+		}
> -+		head->r.w[0] = w;
> -+		if (*w)
> -+			return false;
> -+		/* Add '\0' for audit logs and query. */
> -+		if (head->type == CCS_AUDIT || head->type == CCS_QUERY) {
> -+			if (!head->read_user_buf_avail ||
> -+			    copy_to_user(head->read_user_buf, "", 1))
> -+				return false;
> -+			head->read_user_buf_avail--;
> -+			head->read_user_buf++;
> -+		}
> -+		head->r.w_pos--;
> -+		for (len = 0; len < head->r.w_pos; len++)
> -+			head->r.w[len] = head->r.w[len + 1];
> -+	}
> -+	head->r.avail = 0;
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_set_string - Queue string to "struct ccs_io_buffer" structure.
> -+ *
> -+ * @head:   Pointer to "struct ccs_io_buffer".
> -+ * @string: String to print.
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Note that @string has to be kept valid until @head is kfree()d.
> -+ * This means that char[] allocated on stack memory cannot be passed to
> -+ * this function. Use ccs_io_printf() for char[] allocated on stack memory.
> -+ */
> -+static void ccs_set_string(struct ccs_io_buffer *head, const char *string)
> -+{
> -+	if (head->r.w_pos < CCS_MAX_IO_READ_QUEUE) {
> -+		head->r.w[head->r.w_pos++] = string;
> -+		ccs_flush(head);
> -+	} else
> -+		printk(KERN_WARNING "Too many words in a line.\n");
> -+}
> -+
> -+/**
> -+ * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @fmt:  The printf()'s format string, followed by parameters.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
> -+{
> -+	va_list args;
> -+	size_t len;
> -+	size_t pos = head->r.avail;
> -+	int size = head->readbuf_size - pos;
> -+	if (size <= 0)
> -+		return;
> -+	va_start(args, fmt);
> -+	len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1;
> -+	va_end(args);
> -+	if (pos + len >= head->readbuf_size) {
> -+		printk(KERN_WARNING "Too many words in a line.\n");
> -+		return;
> -+	}
> -+	head->r.avail += len;
> -+	ccs_set_string(head, head->read_buf + pos);
> -+}
> -+
> -+/**
> -+ * ccs_set_space - Put a space to "struct ccs_io_buffer" structure.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_set_space(struct ccs_io_buffer *head)
> -+{
> -+	ccs_set_string(head, " ");
> -+}
> -+
> -+/**
> -+ * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns true if all data was flushed, false otherwise.
> -+ */
> -+static bool ccs_set_lf(struct ccs_io_buffer *head)
> -+{
> -+	ccs_set_string(head, "\n");
> -+	return !head->r.w_pos;
> -+}
> -+
> -+/**
> -+ * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_set_slash(struct ccs_io_buffer *head)
> -+{
> -+	ccs_set_string(head, "/");
> -+}
> -+
> -+/**
> -+ * ccs_init_policy_namespace - Initialize namespace.
> -+ *
> -+ * @ns: Pointer to "struct ccs_policy_namespace".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns)
> -+{
> -+	unsigned int idx;
> -+	for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++)
> -+		INIT_LIST_HEAD(&ns->acl_group[idx]);
> -+	for (idx = 0; idx < CCS_MAX_GROUP; idx++)
> -+		INIT_LIST_HEAD(&ns->group_list[idx]);
> -+	for (idx = 0; idx < CCS_MAX_POLICY; idx++)
> -+		INIT_LIST_HEAD(&ns->policy_list[idx]);
> -+	ns->profile_version = 20150505;
> -+	ccs_namespace_enabled = !list_empty(&ccs_namespace_list);
> -+	list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list);
> -+}
> -+
> -+/**
> -+ * ccs_print_namespace - Print namespace header.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_print_namespace(struct ccs_io_buffer *head)
> -+{
> -+	if (!ccs_namespace_enabled)
> -+		return;
> -+	ccs_set_string(head,
> -+		       container_of(head->r.ns, struct ccs_policy_namespace,
> -+				    namespace_list)->name);
> -+	ccs_set_space(head);
> -+}
> -+
> -+/**
> -+ * ccs_assign_profile - Create a new profile.
> -+ *
> -+ * @ns:      Pointer to "struct ccs_policy_namespace".
> -+ * @profile: Profile number to create.
> -+ *
> -+ * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
> -+ */
> -+static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
> -+					      const unsigned int profile)
> -+{
> -+	struct ccs_profile *ptr;
> -+	struct ccs_profile *entry;
> -+	if (profile >= CCS_MAX_PROFILES)
> -+		return NULL;
> -+	ptr = ns->profile_ptr[profile];
> -+	if (ptr)
> -+		return ptr;
> -+	entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
> -+	if (mutex_lock_interruptible(&ccs_policy_lock))
> -+		goto out;
> -+	ptr = ns->profile_ptr[profile];
> -+	if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
> -+		ptr = entry;
> -+		ptr->default_config = CCS_CONFIG_DISABLED |
> -+			CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
> -+		memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
> -+		       sizeof(ptr->config));
> -+		ptr->pref[CCS_PREF_MAX_AUDIT_LOG] =
> -+			CONFIG_CCSECURITY_MAX_AUDIT_LOG;
> -+		ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
> -+			CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
> -+		mb(); /* Avoid out-of-order execution. */
> -+		ns->profile_ptr[profile] = ptr;
> -+		entry = NULL;
> -+	}
> -+	mutex_unlock(&ccs_policy_lock);
> -+out:
> -+	kfree(entry);
> -+	return ptr;
> -+}
> -+
> -+/**
> -+ * ccs_check_profile - Check all profiles currently assigned to domains are defined.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_check_profile(void)
> -+{
> -+	struct ccs_domain_info *domain;
> -+	const int idx = ccs_read_lock();
> -+	ccs_policy_loaded = true;
> -+	printk(KERN_INFO "CCSecurity: 1.8.4   2015/05/05\n");
> -+	list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
> -+		const u8 profile = domain->profile;
> -+		struct ccs_policy_namespace *ns = domain->ns;
> -+		if (ns->profile_version == 20100903) {
> -+			static bool done;
> -+			if (!done)
> -+				printk(KERN_INFO "Converting profile version "
> -+				       "from %u to %u.\n", 20100903, 20150505);
> -+			done = true;
> -+			ns->profile_version = 20150505;
> -+		}
> -+		if (ns->profile_version != 20150505)
> -+			printk(KERN_ERR
> -+			       "Profile version %u is not supported.\n",
> -+			       ns->profile_version);
> -+		else if (!ns->profile_ptr[profile])
> -+			printk(KERN_ERR
> -+			       "Profile %u (used by '%s') is not defined.\n",
> -+			       profile, domain->domainname->name);
> -+		else
> -+			continue;
> -+		printk(KERN_ERR
> -+		       "Userland tools for TOMOYO 1.8 must be installed and "
> -+		       "policy must be initialized.\n");
> -+		printk(KERN_ERR "Please see http://tomoyo.osdn.jp/1.8/ "
> -+		       "for more information.\n");
> -+		panic("STOP!");
> -+	}
> -+	ccs_read_unlock(idx);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && defined(CONFIG_SECURITY)
> -+	ccsecurity_exports.add_hooks();
> -+#endif
> -+	printk(KERN_INFO "Mandatory Access Control activated.\n");
> -+}
> -+
> -+/**
> -+ * ccs_profile - Find a profile.
> -+ *
> -+ * @profile: Profile number to find.
> -+ *
> -+ * Returns pointer to "struct ccs_profile".
> -+ */
> -+static struct ccs_profile *ccs_profile(const u8 profile)
> -+{
> -+	static struct ccs_profile ccs_null_profile;
> -+	struct ccs_profile *ptr = ccs_current_namespace()->
> -+		profile_ptr[profile];
> -+	if (!ptr)
> -+		ptr = &ccs_null_profile;
> -+	return ptr;
> -+}
> -+
> -+/**
> -+ * ccs_get_config - Get config for specified profile's specified functionality.
> -+ *
> -+ * @profile: Profile number.
> -+ * @index:   Index number of functionality.
> -+ *
> -+ * Returns config.
> -+ *
> -+ * First, check for CONFIG::category::functionality.
> -+ * If CONFIG::category::functionality is set to use default, then check
> -+ * CONFIG::category. If CONFIG::category is set to use default, then use
> -+ * CONFIG. CONFIG cannot be set to use default.
> -+ */
> -+u8 ccs_get_config(const u8 profile, const u8 index)
> -+{
> -+	u8 config;
> -+	const struct ccs_profile *p;
> -+	if (!ccs_policy_loaded)
> -+		return CCS_CONFIG_DISABLED;
> -+	p = ccs_profile(profile);
> -+	config = p->config[index];
> -+	if (config == CCS_CONFIG_USE_DEFAULT)
> -+		config = p->config[ccs_index2category[index]
> -+				   + CCS_MAX_MAC_INDEX];
> -+	if (config == CCS_CONFIG_USE_DEFAULT)
> -+		config = p->default_config;
> -+	return config;
> -+}
> -+
> -+/**
> -+ * ccs_find_yesno - Find values for specified keyword.
> -+ *
> -+ * @string: String to check.
> -+ * @find:   Name of keyword.
> -+ *
> -+ * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
> -+ */
> -+static s8 ccs_find_yesno(const char *string, const char *find)
> -+{
> -+	const char *cp = strstr(string, find);
> -+	if (cp) {
> -+		cp += strlen(find);
> -+		if (!strncmp(cp, "=yes", 4))
> -+			return 1;
> -+		else if (!strncmp(cp, "=no", 3))
> -+			return 0;
> -+	}
> -+	return -1;
> -+}
> -+
> -+/**
> -+ * ccs_set_uint - Set value for specified preference.
> -+ *
> -+ * @i:      Pointer to "unsigned int".
> -+ * @string: String to check.
> -+ * @find:   Name of keyword.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
> -+{
> -+	const char *cp = strstr(string, find);
> -+	if (cp)
> -+		sscanf(cp + strlen(find), "=%u", i);
> -+}
> -+
> -+/**
> -+ * ccs_str_starts - Check whether the given string starts with the given keyword.
> -+ *
> -+ * @src:  Pointer to pointer to the string.
> -+ * @find: Pointer to the keyword.
> -+ *
> -+ * Returns true if @src starts with @find, false otherwise.
> -+ *
> -+ * The @src is updated to point the first character after the @find
> -+ * if @src starts with @find.
> -+ */
> -+static bool ccs_str_starts(char **src, const char *find)
> -+{
> -+	const int len = strlen(find);
> -+	char *tmp = *src;
> -+	if (strncmp(tmp, find, len))
> -+		return false;
> -+	tmp += len;
> -+	*src = tmp;
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_print_group - Print group's name.
> -+ *
> -+ * @head:  Pointer to "struct ccs_io_buffer".
> -+ * @group: Pointer to "struct ccsgroup". Maybe NULL.
> -+ *
> -+ * Returns true if @group is not NULL. false otherwise.
> -+ */
> -+static bool ccs_print_group(struct ccs_io_buffer *head,
> -+			    const struct ccs_group *group)
> -+{
> -+	if (group) {
> -+		ccs_set_string(head, "@");
> -+		ccs_set_string(head, group->group_name->name);
> -+		return true;
> -+	}
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_set_mode - Set mode for specified profile.
> -+ *
> -+ * @name:    Name of functionality.
> -+ * @value:   Mode for @name.
> -+ * @profile: Pointer to "struct ccs_profile".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_set_mode(char *name, const char *value,
> -+			struct ccs_profile *profile)
> -+{
> -+	u8 i;
> -+	u8 config;
> -+	if (!strcmp(name, "CONFIG")) {
> -+		i = CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
> -+		config = profile->default_config;
> -+	} else if (ccs_str_starts(&name, "CONFIG::")) {
> -+		config = 0;
> -+		for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
> -+		     i++) {
> -+			int len = 0;
> -+			if (i < CCS_MAX_MAC_INDEX) {
> -+				const u8 c = ccs_index2category[i];
> -+				const char *category =
> -+					ccs_category_keywords[c];
> -+				len = strlen(category);
> -+				if (strncmp(name, category, len) ||
> -+				    name[len++] != ':' || name[len++] != ':')
> -+					continue;
> -+			}
> -+			if (strcmp(name + len, ccs_mac_keywords[i]))
> -+				continue;
> -+			config = profile->config[i];
> -+			break;
> -+		}
> -+		if (i == CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
> -+			return -EINVAL;
> -+	} else {
> -+		return -EINVAL;
> -+	}
> -+	if (strstr(value, "use_default")) {
> -+		config = CCS_CONFIG_USE_DEFAULT;
> -+	} else {
> -+		u8 mode;
> -+		for (mode = 0; mode < CCS_CONFIG_MAX_MODE; mode++)
> -+			if (strstr(value, ccs_mode[mode]))
> -+				/*
> -+				 * Update lower 3 bits in order to distinguish
> -+				 * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
> -+				 */
> -+				config = (config & ~7) | mode;
> -+		if (config != CCS_CONFIG_USE_DEFAULT) {
> -+			switch (ccs_find_yesno(value, "grant_log")) {
> -+			case 1:
> -+				config |= CCS_CONFIG_WANT_GRANT_LOG;
> -+				break;
> -+			case 0:
> -+				config &= ~CCS_CONFIG_WANT_GRANT_LOG;
> -+				break;
> -+			}
> -+			switch (ccs_find_yesno(value, "reject_log")) {
> -+			case 1:
> -+				config |= CCS_CONFIG_WANT_REJECT_LOG;
> -+				break;
> -+			case 0:
> -+				config &= ~CCS_CONFIG_WANT_REJECT_LOG;
> -+				break;
> -+			}
> -+		}
> -+	}
> -+	if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
> -+		profile->config[i] = config;
> -+	else if (config != CCS_CONFIG_USE_DEFAULT)
> -+		profile->default_config = config;
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_write_profile - Write profile table.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_write_profile(struct ccs_io_buffer *head)
> -+{
> -+	char *data = head->write_buf;
> -+	unsigned int i;
> -+	char *cp;
> -+	struct ccs_profile *profile;
> -+	if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
> -+	    == 1)
> -+		return 0;
> -+	i = simple_strtoul(data, &cp, 10);
> -+	if (*cp != '-')
> -+		return -EINVAL;
> -+	data = cp + 1;
> -+	profile = ccs_assign_profile(head->w.ns, i);
> -+	if (!profile)
> -+		return -EINVAL;
> -+	cp = strchr(data, '=');
> -+	if (!cp)
> -+		return -EINVAL;
> -+	*cp++ = '\0';
> -+	if (!strcmp(data, "COMMENT")) {
> -+		static DEFINE_SPINLOCK(lock);
> -+		const struct ccs_path_info *new_comment = ccs_get_name(cp);
> -+		const struct ccs_path_info *old_comment;
> -+		if (!new_comment)
> -+			return -ENOMEM;
> -+		spin_lock(&lock);
> -+		old_comment = profile->comment;
> -+		profile->comment = new_comment;
> -+		spin_unlock(&lock);
> -+		ccs_put_name(old_comment);
> -+		return 0;
> -+	}
> -+	if (!strcmp(data, "PREFERENCE")) {
> -+		for (i = 0; i < CCS_MAX_PREF; i++)
> -+			ccs_set_uint(&profile->pref[i], cp,
> -+				     ccs_pref_keywords[i]);
> -+		return 0;
> -+	}
> -+	return ccs_set_mode(data, cp, profile);
> -+}
> -+
> -+/**
> -+ * ccs_print_config - Print mode for specified functionality.
> -+ *
> -+ * @head:   Pointer to "struct ccs_io_buffer".
> -+ * @config: Mode for that functionality.
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Caller prints functionality's name.
> -+ */
> -+static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)
> -+{
> -+	ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
> -+		      ccs_mode[config & 3],
> -+		      ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),
> -+		      ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));
> -+}
> -+
> -+/**
> -+ * ccs_read_profile - Read profile table.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_read_profile(struct ccs_io_buffer *head)
> -+{
> -+	u8 index;
> -+	struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
> -+						       namespace_list);
> -+	const struct ccs_profile *profile;
> -+	if (head->r.eof)
> -+		return;
> -+next:
> -+	index = head->r.index;
> -+	profile = ns->profile_ptr[index];
> -+	switch (head->r.step) {
> -+	case 0:
> -+		ccs_print_namespace(head);
> -+		ccs_io_printf(head, "PROFILE_VERSION=%u\n",
> -+			      ns->profile_version);
> -+		head->r.step++;
> -+		break;
> -+	case 1:
> -+		for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++)
> -+			if (ns->profile_ptr[head->r.index])
> -+				break;
> -+		if (head->r.index == CCS_MAX_PROFILES) {
> -+			head->r.eof = true;
> -+			return;
> -+		}
> -+		head->r.step++;
> -+		break;
> -+	case 2:
> -+		{
> -+			u8 i;
> -+			const struct ccs_path_info *comment = profile->comment;
> -+			ccs_print_namespace(head);
> -+			ccs_io_printf(head, "%u-COMMENT=", index);
> -+			ccs_set_string(head, comment ? comment->name : "");
> -+			ccs_set_lf(head);
> -+			ccs_print_namespace(head);
> -+			ccs_io_printf(head, "%u-PREFERENCE={ ", index);
> -+			for (i = 0; i < CCS_MAX_PREF; i++)
> -+				ccs_io_printf(head, "%s=%u ",
> -+					      ccs_pref_keywords[i],
> -+					      profile->pref[i]);
> -+			ccs_set_string(head, "}\n");
> -+			head->r.step++;
> -+		}
> -+		break;
> -+	case 3:
> -+		{
> -+			ccs_print_namespace(head);
> -+			ccs_io_printf(head, "%u-%s", index, "CONFIG");
> -+			ccs_print_config(head, profile->default_config);
> -+			head->r.bit = 0;
> -+			head->r.step++;
> -+		}
> -+		break;
> -+	case 4:
> -+		for ( ; head->r.bit < CCS_MAX_MAC_INDEX
> -+			      + CCS_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {
> -+			const u8 i = head->r.bit;
> -+			const u8 config = profile->config[i];
> -+			if (config == CCS_CONFIG_USE_DEFAULT)
> -+				continue;
> -+			ccs_print_namespace(head);
> -+			if (i < CCS_MAX_MAC_INDEX)
> -+				ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
> -+					      ccs_category_keywords
> -+					      [ccs_index2category[i]],
> -+					      ccs_mac_keywords[i]);
> -+			else
> -+				ccs_io_printf(head, "%u-CONFIG::%s", index,
> -+					      ccs_mac_keywords[i]);
> -+			ccs_print_config(head, config);
> -+			head->r.bit++;
> -+			break;
> -+		}
> -+		if (head->r.bit == CCS_MAX_MAC_INDEX
> -+		    + CCS_MAX_MAC_CATEGORY_INDEX) {
> -+			head->r.index++;
> -+			head->r.step = 1;
> -+		}
> -+		break;
> -+	}
> -+	if (ccs_flush(head))
> -+		goto next;
> -+}
> -+
> -+/**
> -+ * ccs_update_policy - Update an entry for exception policy.
> -+ *
> -+ * @size:  Size of new entry in bytes.
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_update_policy(const int size, struct ccs_acl_param *param)
> -+{
> -+	struct ccs_acl_head *new_entry = &param->e.acl_head;
> -+	int error = param->is_delete ? -ENOENT : -ENOMEM;
> -+	struct ccs_acl_head *entry;
> -+	struct list_head *list = param->list;
> -+	BUG_ON(size < sizeof(*entry));
> -+	if (mutex_lock_interruptible(&ccs_policy_lock))
> -+		return -ENOMEM;
> -+	list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
> -+		if (entry->is_deleted == CCS_GC_IN_PROGRESS)
> -+			continue;
> -+		if (memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
> -+			continue;
> -+		entry->is_deleted = param->is_delete;
> -+		error = 0;
> -+		break;
> -+	}
> -+	if (error && !param->is_delete) {
> -+		entry = ccs_commit_ok(new_entry, size);
> -+		if (entry) {
> -+			list_add_tail_rcu(&entry->list, list);
> -+			error = 0;
> -+		}
> -+	}
> -+	mutex_unlock(&ccs_policy_lock);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_update_manager_entry - Add a manager entry.
> -+ *
> -+ * @manager:   The path to manager or the domainnamme.
> -+ * @is_delete: True if it is a delete request.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_update_manager_entry(const char *manager,
> -+				    const bool is_delete)
> -+{
> -+	struct ccs_acl_param param = {
> -+		/* .ns = &ccs_kernel_namespace, */
> -+		.is_delete = is_delete,
> -+		.list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER],
> -+	};
> -+	struct ccs_manager *e = &param.e.manager;
> -+	int error = is_delete ? -ENOENT : -ENOMEM;
> -+	/* Forced zero clear for using memcmp() at ccs_update_policy(). */
> -+	memset(&param.e, 0, sizeof(param.e));
> -+	if (!ccs_correct_domain(manager) && !ccs_correct_word(manager))
> -+		return -EINVAL;
> -+	e->manager = ccs_get_name(manager);
> -+	if (e->manager) {
> -+		error = ccs_update_policy(sizeof(*e), &param);
> -+		ccs_put_name(e->manager);
> -+	}
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_write_manager - Write manager policy.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_write_manager(struct ccs_io_buffer *head)
> -+{
> -+	const char *data = head->write_buf;
> -+	if (!strcmp(data, "manage_by_non_root")) {
> -+		ccs_manage_by_non_root = !head->w.is_delete;
> -+		return 0;
> -+	}
> -+	return ccs_update_manager_entry(data, head->w.is_delete);
> -+}
> -+
> -+/**
> -+ * ccs_read_manager - Read manager policy.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static void ccs_read_manager(struct ccs_io_buffer *head)
> -+{
> -+	if (head->r.eof)
> -+		return;
> -+	list_for_each_cookie(head->r.acl, &ccs_kernel_namespace.
> -+			     policy_list[CCS_ID_MANAGER]) {
> -+		struct ccs_manager *ptr =
> -+			list_entry(head->r.acl, typeof(*ptr), head.list);
> -+		if (ptr->head.is_deleted)
> -+			continue;
> -+		if (!ccs_flush(head))
> -+			return;
> -+		ccs_set_string(head, ptr->manager->name);
> -+		ccs_set_lf(head);
> -+	}
> -+	head->r.eof = true;
> -+}
> -+
> -+/**
> -+ * ccs_manager - Check whether the current process is a policy manager.
> -+ *
> -+ * Returns true if the current process is permitted to modify policy
> -+ * via /proc/ccs/ interface.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_manager(void)
> -+{
> -+	struct ccs_manager *ptr;
> -+	struct ccs_path_info exe;
> -+	struct ccs_security *task = ccs_current_security();
> -+	const struct ccs_path_info *domainname
> -+		= ccs_current_domain()->domainname;
> -+	bool found = false;
> -+	if (!ccs_policy_loaded)
> -+		return true;
> -+	if (task->ccs_flags & CCS_TASK_IS_MANAGER)
> -+		return true;
> -+	if (!ccs_manage_by_non_root &&
> -+	    (!uid_eq(current_uid(), GLOBAL_ROOT_UID) ||
> -+	     !uid_eq(current_euid(), GLOBAL_ROOT_UID)))
> -+		return false;
> -+	exe.name = ccs_get_exe();
> -+	if (!exe.name)
> -+		return false;
> -+	ccs_fill_path_info(&exe);
> -+	list_for_each_entry_srcu(ptr, &ccs_kernel_namespace.
> -+				 policy_list[CCS_ID_MANAGER], head.list,
> -+				 &ccs_ss) {
> -+		if (ptr->head.is_deleted)
> -+			continue;
> -+		if (ccs_pathcmp(domainname, ptr->manager) &&
> -+		    ccs_pathcmp(&exe, ptr->manager))
> -+			continue;
> -+		/* Set manager flag. */
> -+		task->ccs_flags |= CCS_TASK_IS_MANAGER;
> -+		found = true;
> -+		break;
> -+	}
> -+	if (!found) { /* Reduce error messages. */
> -+		static pid_t ccs_last_pid;
> -+		const pid_t pid = current->pid;
> -+		if (ccs_last_pid != pid) {
> -+			printk(KERN_WARNING "%s ( %s ) is not permitted to "
> -+			       "update policies.\n", domainname->name,
> -+			       exe.name);
> -+			ccs_last_pid = pid;
> -+		}
> -+	}
> -+	kfree(exe.name);
> -+	return found;
> -+}
> -+
> -+/**
> -+ * ccs_find_domain - Find a domain by the given name.
> -+ *
> -+ * @domainname: The domainname to find.
> -+ *
> -+ * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static struct ccs_domain_info *ccs_find_domain(const char *domainname)
> -+{
> -+	struct ccs_domain_info *domain;
> -+	struct ccs_path_info name;
> -+	name.name = domainname;
> -+	ccs_fill_path_info(&name);
> -+	list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
> -+		if (!domain->is_deleted &&
> -+		    !ccs_pathcmp(&name, domain->domainname))
> -+			return domain;
> -+	}
> -+	return NULL;
> -+}
> -+
> -+/**
> -+ * ccs_select_domain - Parse select command.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @data: String to parse.
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data)
> -+{
> -+	unsigned int pid;
> -+	struct ccs_domain_info *domain = NULL;
> -+	bool global_pid = false;
> -+	if (strncmp(data, "select ", 7))
> -+		return false;
> -+	data += 7;
> -+	if (sscanf(data, "pid=%u", &pid) == 1 ||
> -+	    (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
> -+		struct task_struct *p;
> -+		ccs_tasklist_lock();
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
> -+		if (global_pid)
> -+			p = ccsecurity_exports.find_task_by_pid_ns(pid,
> -+							       &init_pid_ns);
> -+		else
> -+			p = ccsecurity_exports.find_task_by_vpid(pid);
> -+#else
> -+		p = find_task_by_pid(pid);
> -+#endif
> -+		if (p)
> -+			domain = ccs_task_domain(p);
> -+		ccs_tasklist_unlock();
> -+	} else if (!strncmp(data, "domain=", 7)) {
> -+		if (*(data + 7) == '<')
> -+			domain = ccs_find_domain(data + 7);
> -+	} else if (sscanf(data, "Q=%u", &pid) == 1) {
> -+		domain = ccs_find_domain_by_qid(pid);
> -+	} else
> -+		return false;
> -+	head->w.domain = domain;
> -+	/* Accessing read_buf is safe because head->io_sem is held. */
> -+	if (!head->read_buf)
> -+		return true; /* Do nothing if open(O_WRONLY). */
> -+	memset(&head->r, 0, sizeof(head->r));
> -+	head->r.print_this_domain_only = true;
> -+	if (domain)
> -+		head->r.domain = &domain->list;
> -+	else
> -+		head->r.eof = true;
> -+	ccs_io_printf(head, "# select %s\n", data);
> -+	if (domain && domain->is_deleted)
> -+		ccs_set_string(head, "# This is a deleted domain.\n");
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_update_acl - Update "struct ccs_acl_info" entry.
> -+ *
> -+ * @size:  Size of new entry in bytes.
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_update_acl(const int size, struct ccs_acl_param *param)
> -+{
> -+	struct ccs_acl_info *new_entry = &param->e.acl_info;
> -+	const bool is_delete = param->is_delete;
> -+	int error = is_delete ? -ENOENT : -ENOMEM;
> -+	struct ccs_acl_info *entry;
> -+	struct list_head * const list = param->list;
> -+	BUG_ON(size < sizeof(*entry));
> -+	if (param->data[0]) {
> -+		new_entry->cond = ccs_get_condition(param);
> -+		if (!new_entry->cond)
> -+			return -EINVAL;
> -+		/*
> -+		 * Domain transition preference is allowed for only
> -+		 * "file execute"/"task auto_execute_handler"/
> -+		 * "task denied_auto_execute_handler" entries.
> -+		 */
> -+		if (new_entry->cond->exec_transit &&
> -+		    !(new_entry->type == CCS_TYPE_PATH_ACL &&
> -+		      new_entry->perm == 1 << CCS_TYPE_EXECUTE)
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+		    && new_entry->type != CCS_TYPE_AUTO_EXECUTE_HANDLER &&
> -+		    new_entry->type != CCS_TYPE_DENIED_EXECUTE_HANDLER
> -+#endif
> -+		    )
> -+			return -EINVAL;
> -+	}
> -+	if (mutex_lock_interruptible(&ccs_policy_lock))
> -+		return -ENOMEM;
> -+	list_for_each_entry_srcu(entry, list, list, &ccs_ss) {
> -+		if (entry->is_deleted == CCS_GC_IN_PROGRESS)
> -+			continue;
> -+		if (entry->type != new_entry->type ||
> -+		    entry->cond != new_entry->cond ||
> -+		    memcmp(entry + 1, new_entry + 1, size - sizeof(*entry)))
> -+			continue;
> -+		if (is_delete)
> -+			entry->perm &= ~new_entry->perm;
> -+		else
> -+			entry->perm |= new_entry->perm;
> -+		entry->is_deleted = !entry->perm;
> -+		error = 0;
> -+		break;
> -+	}
> -+	if (error && !is_delete) {
> -+		entry = ccs_commit_ok(new_entry, size);
> -+		if (entry) {
> -+			list_add_tail_rcu(&entry->list, list);
> -+			error = 0;
> -+		}
> -+	}
> -+	mutex_unlock(&ccs_policy_lock);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_permstr - Find permission keywords.
> -+ *
> -+ * @string: String representation for permissions in foo/bar/buz format.
> -+ * @keyword: Keyword to find from @string/
> -+ *
> -+ * Returns ture if @keyword was found in @string, false otherwise.
> -+ *
> -+ * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
> -+ */
> -+static bool ccs_permstr(const char *string, const char *keyword)
> -+{
> -+	const char *cp = strstr(string, keyword);
> -+	if (cp)
> -+		return cp == string || *(cp - 1) == '/';
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_write_task - Update task related list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_write_task(struct ccs_acl_param *param)
> -+{
> -+	int error;
> -+	const bool is_auto = ccs_str_starts(&param->data,
> -+					    "auto_domain_transition ");
> -+	if (!is_auto && !ccs_str_starts(&param->data,
> -+					"manual_domain_transition ")) {
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+		struct ccs_handler_acl *e = &param->e.handler_acl;
> -+		char *handler;
> -+		if (ccs_str_starts(&param->data, "auto_execute_handler "))
> -+			e->head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER;
> -+		else if (ccs_str_starts(&param->data,
> -+					"denied_execute_handler "))
> -+			e->head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER;
> -+		else
> -+			return -EINVAL;
> -+		handler = ccs_read_token(param);
> -+		if (!ccs_correct_path(handler))
> -+			return -EINVAL;
> -+		e->handler = ccs_get_name(handler);
> -+		if (!e->handler)
> -+			return -ENOMEM;
> -+		if (e->handler->is_patterned)
> -+			return -EINVAL; /* No patterns allowed. */
> -+		return ccs_update_acl(sizeof(*e), param);
> -+#else
> -+		error = -EINVAL;
> -+#endif
> -+	} else {
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+		struct ccs_task_acl *e = &param->e.task_acl;
> -+		e->head.type = is_auto ?
> -+			CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL;
> -+		e->domainname = ccs_get_domainname(param);
> -+		if (!e->domainname)
> -+			return -EINVAL;
> -+		return ccs_update_acl(sizeof(*e), param);
> -+#else
> -+		error = -EINVAL;
> -+#endif
> -+	}
> -+	return error;
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+
> -+/**
> -+ * ccs_write_inet_network - Write "struct ccs_inet_acl" list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_write_inet_network(struct ccs_acl_param *param)
> -+{
> -+	struct ccs_inet_acl *e = &param->e.inet_acl;
> -+	u8 type;
> -+	const char *protocol = ccs_read_token(param);
> -+	const char *operation = ccs_read_token(param);
> -+	e->head.type = CCS_TYPE_INET_ACL;
> -+	for (type = 0; type < CCS_SOCK_MAX; type++)
> -+		if (!strcmp(protocol, ccs_proto_keyword[type]))
> -+			break;
> -+	if (type == CCS_SOCK_MAX)
> -+		return -EINVAL;
> -+	e->protocol = type;
> -+	e->head.perm = 0;
> -+	for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
> -+		if (ccs_permstr(operation, ccs_socket_keyword[type]))
> -+			e->head.perm |= 1 << type;
> -+	if (!e->head.perm)
> -+		return -EINVAL;
> -+	if (param->data[0] == '@') {
> -+		param->data++;
> -+		e->address.group = ccs_get_group(param, CCS_ADDRESS_GROUP);
> -+		if (!e->address.group)
> -+			return -ENOMEM;
> -+	} else {
> -+		if (!ccs_parse_ipaddr_union(param, &e->address))
> -+			return -EINVAL;
> -+	}
> -+	if (!ccs_parse_number_union(param, &e->port) ||
> -+	    e->port.values[1] > 65535)
> -+		return -EINVAL;
> -+	return ccs_update_acl(sizeof(*e), param);
> -+}
> -+
> -+/**
> -+ * ccs_write_unix_network - Write "struct ccs_unix_acl" list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_write_unix_network(struct ccs_acl_param *param)
> -+{
> -+	struct ccs_unix_acl *e = &param->e.unix_acl;
> -+	u8 type;
> -+	const char *protocol = ccs_read_token(param);
> -+	const char *operation = ccs_read_token(param);
> -+	e->head.type = CCS_TYPE_UNIX_ACL;
> -+	for (type = 0; type < CCS_SOCK_MAX; type++)
> -+		if (!strcmp(protocol, ccs_proto_keyword[type]))
> -+			break;
> -+	if (type == CCS_SOCK_MAX)
> -+		return -EINVAL;
> -+	e->protocol = type;
> -+	e->head.perm = 0;
> -+	for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
> -+		if (ccs_permstr(operation, ccs_socket_keyword[type]))
> -+			e->head.perm |= 1 << type;
> -+	if (!e->head.perm)
> -+		return -EINVAL;
> -+	if (!ccs_parse_name_union(param, &e->name))
> -+		return -EINVAL;
> -+	return ccs_update_acl(sizeof(*e), param);
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_write_file - Update file related list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_write_file(struct ccs_acl_param *param)
> -+{
> -+	u16 perm = 0;
> -+	u8 type;
> -+	const char *operation = ccs_read_token(param);
> -+	for (type = 0; type < CCS_MAX_PATH_OPERATION; type++)
> -+		if (ccs_permstr(operation, ccs_path_keyword[type]))
> -+			perm |= 1 << type;
> -+	if (perm) {
> -+		struct ccs_path_acl *e = &param->e.path_acl;
> -+		e->head.type = CCS_TYPE_PATH_ACL;
> -+		e->head.perm = perm;
> -+		if (!ccs_parse_name_union(param, &e->name))
> -+			return -EINVAL;
> -+		return ccs_update_acl(sizeof(*e), param);
> -+	}
> -+	for (type = 0; type < CCS_MAX_PATH2_OPERATION; type++)
> -+		if (ccs_permstr(operation, ccs_mac_keywords[ccs_pp2mac[type]]))
> -+			perm |= 1 << type;
> -+	if (perm) {
> -+		struct ccs_path2_acl *e = &param->e.path2_acl;
> -+		e->head.type = CCS_TYPE_PATH2_ACL;
> -+		e->head.perm = perm;
> -+		if (!ccs_parse_name_union(param, &e->name1) ||
> -+		    !ccs_parse_name_union(param, &e->name2))
> -+			return -EINVAL;
> -+		return ccs_update_acl(sizeof(*e), param);
> -+	}
> -+	for (type = 0; type < CCS_MAX_PATH_NUMBER_OPERATION; type++)
> -+		if (ccs_permstr(operation, ccs_mac_keywords[ccs_pn2mac[type]]))
> -+			perm |= 1 << type;
> -+	if (perm) {
> -+		struct ccs_path_number_acl *e = &param->e.path_number_acl;
> -+		e->head.type = CCS_TYPE_PATH_NUMBER_ACL;
> -+		e->head.perm = perm;
> -+		if (!ccs_parse_name_union(param, &e->name) ||
> -+		    !ccs_parse_number_union(param, &e->number))
> -+			return -EINVAL;
> -+		return ccs_update_acl(sizeof(*e), param);
> -+	}
> -+	for (type = 0; type < CCS_MAX_MKDEV_OPERATION; type++)
> -+		if (ccs_permstr(operation,
> -+				ccs_mac_keywords[ccs_pnnn2mac[type]]))
> -+			perm |= 1 << type;
> -+	if (perm) {
> -+		struct ccs_mkdev_acl *e = &param->e.mkdev_acl;
> -+		e->head.type = CCS_TYPE_MKDEV_ACL;
> -+		e->head.perm = perm;
> -+		if (!ccs_parse_name_union(param, &e->name) ||
> -+		    !ccs_parse_number_union(param, &e->mode) ||
> -+		    !ccs_parse_number_union(param, &e->major) ||
> -+		    !ccs_parse_number_union(param, &e->minor))
> -+			return -EINVAL;
> -+		return ccs_update_acl(sizeof(*e), param);
> -+	}
> -+	if (ccs_permstr(operation, ccs_mac_keywords[CCS_MAC_FILE_MOUNT])) {
> -+		struct ccs_mount_acl *e = &param->e.mount_acl;
> -+		e->head.type = CCS_TYPE_MOUNT_ACL;
> -+		if (!ccs_parse_name_union(param, &e->dev_name) ||
> -+		    !ccs_parse_name_union(param, &e->dir_name) ||
> -+		    !ccs_parse_name_union(param, &e->fs_type) ||
> -+		    !ccs_parse_number_union(param, &e->flags))
> -+			return -EINVAL;
> -+		return ccs_update_acl(sizeof(*e), param);
> -+	}
> -+	return -EINVAL;
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+
> -+/**
> -+ * ccs_write_misc - Update environment variable list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_write_misc(struct ccs_acl_param *param)
> -+{
> -+	if (ccs_str_starts(&param->data, "env ")) {
> -+		struct ccs_env_acl *e = &param->e.env_acl;
> -+		const char *data = ccs_read_token(param);
> -+		e->head.type = CCS_TYPE_ENV_ACL;
> -+		if (!ccs_correct_word(data) || strchr(data, '='))
> -+			return -EINVAL;
> -+		e->env = ccs_get_name(data);
> -+		if (!e->env)
> -+			return -ENOMEM;
> -+		return ccs_update_acl(sizeof(*e), param);
> -+	}
> -+	return -EINVAL;
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+
> -+/**
> -+ * ccs_write_ipc - Update "struct ccs_signal_acl" list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_write_ipc(struct ccs_acl_param *param)
> -+{
> -+	struct ccs_signal_acl *e = &param->e.signal_acl;
> -+	e->head.type = CCS_TYPE_SIGNAL_ACL;
> -+	if (!ccs_parse_number_union(param, &e->sig))
> -+		return -EINVAL;
> -+	e->domainname = ccs_get_domainname(param);
> -+	if (!e->domainname)
> -+		return -EINVAL;
> -+	return ccs_update_acl(sizeof(*e), param);
> -+}
> -+
> -+#endif
> -+
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+
> -+/**
> -+ * ccs_write_capability - Write "struct ccs_capability_acl" list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_write_capability(struct ccs_acl_param *param)
> -+{
> -+	struct ccs_capability_acl *e = &param->e.capability_acl;
> -+	const char *operation = ccs_read_token(param);
> -+	u8 type;
> -+	e->head.type = CCS_TYPE_CAPABILITY_ACL;
> -+	for (type = 0; type < CCS_MAX_CAPABILITY_INDEX; type++) {
> -+		if (strcmp(operation, ccs_mac_keywords[ccs_c2mac[type]]))
> -+			continue;
> -+		e->operation = type;
> -+		return ccs_update_acl(sizeof(*e), param);
> -+	}
> -+	return -EINVAL;
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_write_acl - Write "struct ccs_acl_info" list.
> -+ *
> -+ * @ns:        Pointer to "struct ccs_policy_namespace".
> -+ * @list:      Pointer to "struct list_head".
> -+ * @data:      Policy to be interpreted.
> -+ * @is_delete: True if it is a delete request.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_write_acl(struct ccs_policy_namespace *ns,
> -+			 struct list_head *list, char *data,
> -+			 const bool is_delete)
> -+{
> -+	struct ccs_acl_param param = {
> -+		.ns = ns,
> -+		.list = list,
> -+		.data = data,
> -+		.is_delete = is_delete,
> -+	};
> -+	static const struct {
> -+		const char *keyword;
> -+		int (*write) (struct ccs_acl_param *);
> -+	} ccs_callback[] = {
> -+		{ "file ", ccs_write_file },
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+		{ "network inet ", ccs_write_inet_network },
> -+		{ "network unix ", ccs_write_unix_network },
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+		{ "misc ", ccs_write_misc },
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+		{ "capability ", ccs_write_capability },
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+		{ "ipc signal ", ccs_write_ipc },
> -+#endif
> -+		{ "task ", ccs_write_task },
> -+	};
> -+	u8 i;
> -+	/* Forced zero clear for using memcmp() at ccs_update_acl(). */
> -+	memset(&param.e, 0, sizeof(param.e));
> -+	param.e.acl_info.perm = 1;
> -+	for (i = 0; i < ARRAY_SIZE(ccs_callback); i++) {
> -+		int error;
> -+		if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))
> -+			continue;
> -+		error = ccs_callback[i].write(&param);
> -+		ccs_del_acl(&param.e.acl_info.list);
> -+		return error;
> -+	}
> -+	return -EINVAL;
> -+}
> -+
> -+/**
> -+ * ccs_delete_domain - Delete a domain.
> -+ *
> -+ * @domainname: The name of domain.
> -+ *
> -+ * Returns 0.
> -+ */
> -+static int ccs_delete_domain(char *domainname)
> -+{
> -+	struct ccs_domain_info *domain;
> -+	struct ccs_path_info name;
> -+	name.name = domainname;
> -+	ccs_fill_path_info(&name);
> -+	if (mutex_lock_interruptible(&ccs_policy_lock))
> -+		return 0;
> -+	/* Is there an active domain? */
> -+	list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
> -+		/* Never delete ccs_kernel_domain. */
> -+		if (domain == &ccs_kernel_domain)
> -+			continue;
> -+		if (domain->is_deleted ||
> -+		    ccs_pathcmp(domain->domainname, &name))
> -+			continue;
> -+		domain->is_deleted = true;
> -+		break;
> -+	}
> -+	mutex_unlock(&ccs_policy_lock);
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_write_domain - Write domain policy.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_write_domain(struct ccs_io_buffer *head)
> -+{
> -+	char *data = head->write_buf;
> -+	struct ccs_policy_namespace *ns;
> -+	struct ccs_domain_info *domain = head->w.domain;
> -+	const bool is_delete = head->w.is_delete;
> -+	const bool is_select = !is_delete && ccs_str_starts(&data, "select ");
> -+	unsigned int idx;
> -+	if (*data == '<') {
> -+		domain = NULL;
> -+		if (is_delete)
> -+			ccs_delete_domain(data);
> -+		else if (is_select)
> -+			domain = ccs_find_domain(data);
> -+		else
> -+			domain = ccs_assign_domain(data, false);
> -+		head->w.domain = domain;
> -+		return 0;
> -+	}
> -+	if (!domain)
> -+		return -EINVAL;
> -+	ns = domain->ns;
> -+	if (sscanf(data, "use_profile %u\n", &idx) == 1 &&
> -+	    idx < CCS_MAX_PROFILES) {
> -+		if (!ccs_policy_loaded || ns->profile_ptr[(u8) idx])
> -+			if (!is_delete)
> -+				domain->profile = (u8) idx;
> -+		return 0;
> -+	}
> -+	if (sscanf(data, "use_group %u\n", &idx) == 1 &&
> -+	    idx < CCS_MAX_ACL_GROUPS) {
> -+		if (!is_delete)
> -+			set_bit(idx, domain->group);
> -+		else
> -+			clear_bit(idx, domain->group);
> -+		return 0;
> -+	}
> -+	for (idx = 0; idx < CCS_MAX_DOMAIN_INFO_FLAGS; idx++) {
> -+		const char *cp = ccs_dif[idx];
> -+		if (strncmp(data, cp, strlen(cp) - 1))
> -+			continue;
> -+		domain->flags[idx] = !is_delete;
> -+		return 0;
> -+	}
> -+	return ccs_write_acl(ns, &domain->acl_info_list, data, is_delete);
> -+}
> -+
> -+/**
> -+ * ccs_print_name_union - Print a ccs_name_union.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @ptr:  Pointer to "struct ccs_name_union".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_print_name_union(struct ccs_io_buffer *head,
> -+				 const struct ccs_name_union *ptr)
> -+{
> -+	ccs_set_space(head);
> -+	if (!ccs_print_group(head, ptr->group))
> -+		ccs_set_string(head, ptr->filename->name);
> -+}
> -+
> -+/**
> -+ * ccs_print_name_union_quoted - Print a ccs_name_union with a quote.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @ptr:  Pointer to "struct ccs_name_union".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
> -+					const struct ccs_name_union *ptr)
> -+{
> -+	if (!ccs_print_group(head, ptr->group)) {
> -+		ccs_set_string(head, "\"");
> -+		ccs_set_string(head, ptr->filename->name);
> -+		ccs_set_string(head, "\"");
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_print_number_union_nospace - Print a ccs_number_union without a space.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @ptr:  Pointer to "struct ccs_number_union".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
> -+					   const struct ccs_number_union *ptr)
> -+{
> -+	if (!ccs_print_group(head, ptr->group)) {
> -+		int i;
> -+		unsigned long min = ptr->values[0];
> -+		const unsigned long max = ptr->values[1];
> -+		u8 min_type = ptr->value_type[0];
> -+		const u8 max_type = ptr->value_type[1];
> -+		char buffer[128];
> -+		buffer[0] = '\0';
> -+		for (i = 0; i < 2; i++) {
> -+			switch (min_type) {
> -+			case CCS_VALUE_TYPE_HEXADECIMAL:
> -+				ccs_addprintf(buffer, sizeof(buffer), "0x%lX",
> -+					      min);
> -+				break;
> -+			case CCS_VALUE_TYPE_OCTAL:
> -+				ccs_addprintf(buffer, sizeof(buffer), "0%lo",
> -+					      min);
> -+				break;
> -+			default:
> -+				ccs_addprintf(buffer, sizeof(buffer), "%lu",
> -+					      min);
> -+				break;
> -+			}
> -+			if (min == max && min_type == max_type)
> -+				break;
> -+			ccs_addprintf(buffer, sizeof(buffer), "-");
> -+			min_type = max_type;
> -+			min = max;
> -+		}
> -+		ccs_io_printf(head, "%s", buffer);
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_print_number_union - Print a ccs_number_union.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @ptr:  Pointer to "struct ccs_number_union".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_print_number_union(struct ccs_io_buffer *head,
> -+				   const struct ccs_number_union *ptr)
> -+{
> -+	ccs_set_space(head);
> -+	ccs_print_number_union_nospace(head, ptr);
> -+}
> -+
> -+/**
> -+ * ccs_print_condition - Print condition part.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @cond: Pointer to "struct ccs_condition".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_print_condition(struct ccs_io_buffer *head,
> -+				const struct ccs_condition *cond)
> -+{
> -+	switch (head->r.cond_step) {
> -+	case 0:
> -+		head->r.cond_index = 0;
> -+		head->r.cond_step++;
> -+		if (cond->transit && cond->exec_transit) {
> -+			ccs_set_space(head);
> -+			ccs_set_string(head, cond->transit->name);
> -+		}
> -+		/* fall through */
> -+	case 1:
> -+		{
> -+			const u16 condc = cond->condc;
> -+			const struct ccs_condition_element *condp =
> -+				(typeof(condp)) (cond + 1);
> -+			const struct ccs_number_union *numbers_p =
> -+				(typeof(numbers_p)) (condp + condc);
> -+			const struct ccs_name_union *names_p =
> -+				(typeof(names_p))
> -+				(numbers_p + cond->numbers_count);
> -+			const struct ccs_argv *argv =
> -+				(typeof(argv)) (names_p + cond->names_count);
> -+			const struct ccs_envp *envp =
> -+				(typeof(envp)) (argv + cond->argc);
> -+			u16 skip;
> -+			for (skip = 0; skip < head->r.cond_index; skip++) {
> -+				const u8 left = condp->left;
> -+				const u8 right = condp->right;
> -+				condp++;
> -+				switch (left) {
> -+				case CCS_ARGV_ENTRY:
> -+					argv++;
> -+					continue;
> -+				case CCS_ENVP_ENTRY:
> -+					envp++;
> -+					continue;
> -+				case CCS_NUMBER_UNION:
> -+					numbers_p++;
> -+					break;
> -+				}
> -+				switch (right) {
> -+				case CCS_NAME_UNION:
> -+					names_p++;
> -+					break;
> -+				case CCS_NUMBER_UNION:
> -+					numbers_p++;
> -+					break;
> -+				}
> -+			}
> -+			while (head->r.cond_index < condc) {
> -+				const u8 match = condp->equals;
> -+				const u8 left = condp->left;
> -+				const u8 right = condp->right;
> -+				if (!ccs_flush(head))
> -+					return false;
> -+				condp++;
> -+				head->r.cond_index++;
> -+				ccs_set_space(head);
> -+				switch (left) {
> -+				case CCS_ARGV_ENTRY:
> -+					ccs_io_printf(head,
> -+						      "exec.argv[%lu]%s=\"",
> -+						      argv->index,
> -+						      argv->is_not ? "!" : "");
> -+					ccs_set_string(head,
> -+						       argv->value->name);
> -+					ccs_set_string(head, "\"");
> -+					argv++;
> -+					continue;
> -+				case CCS_ENVP_ENTRY:
> -+					ccs_set_string(head, "exec.envp[\"");
> -+					ccs_set_string(head, envp->name->name);
> -+					ccs_io_printf(head, "\"]%s=",
> -+						      envp->is_not ? "!" : "");
> -+					if (envp->value) {
> -+						ccs_set_string(head, "\"");
> -+						ccs_set_string(head, envp->
> -+							       value->name);
> -+						ccs_set_string(head, "\"");
> -+					} else {
> -+						ccs_set_string(head, "NULL");
> -+					}
> -+					envp++;
> -+					continue;
> -+				case CCS_NUMBER_UNION:
> -+					ccs_print_number_union_nospace
> -+						(head, numbers_p++);
> -+					break;
> -+				default:
> -+					ccs_set_string(head,
> -+					       ccs_condition_keyword[left]);
> -+					break;
> -+				}
> -+				ccs_set_string(head, match ? "=" : "!=");
> -+				switch (right) {
> -+				case CCS_NAME_UNION:
> -+					ccs_print_name_union_quoted
> -+						(head, names_p++);
> -+					break;
> -+				case CCS_NUMBER_UNION:
> -+					ccs_print_number_union_nospace
> -+						(head, numbers_p++);
> -+					break;
> -+				default:
> -+					ccs_set_string(head,
> -+					       ccs_condition_keyword[right]);
> -+					break;
> -+				}
> -+			}
> -+		}
> -+		head->r.cond_step++;
> -+		/* fall through */
> -+	case 2:
> -+		if (!ccs_flush(head))
> -+			break;
> -+		head->r.cond_step++;
> -+		/* fall through */
> -+	case 3:
> -+		if (cond->grant_log != CCS_GRANTLOG_AUTO)
> -+			ccs_io_printf(head, " grant_log=%s",
> -+				      ccs_yesno(cond->grant_log ==
> -+						CCS_GRANTLOG_YES));
> -+		if (cond->transit && !cond->exec_transit) {
> -+			const char *name = cond->transit->name;
> -+			ccs_set_string(head, " auto_domain_transition=\"");
> -+			ccs_set_string(head, name);
> -+			ccs_set_string(head, "\"");
> -+		}
> -+		ccs_set_lf(head);
> -+		return true;
> -+	}
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_set_group - Print "acl_group " header keyword and category name.
> -+ *
> -+ * @head:     Pointer to "struct ccs_io_buffer".
> -+ * @category: Category name.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_set_group(struct ccs_io_buffer *head, const char *category)
> -+{
> -+	if (head->type == CCS_EXCEPTION_POLICY) {
> -+		ccs_print_namespace(head);
> -+		ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
> -+	}
> -+	ccs_set_string(head, category);
> -+}
> -+
> -+/**
> -+ * ccs_print_entry - Print an ACL entry.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @acl:  Pointer to an ACL entry.
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ */
> -+static bool ccs_print_entry(struct ccs_io_buffer *head,
> -+			    const struct ccs_acl_info *acl)
> -+{
> -+	const u8 acl_type = acl->type;
> -+	const bool may_trigger_transition = acl->cond && acl->cond->transit;
> -+	bool first = true;
> -+	u8 bit;
> -+	if (head->r.print_cond_part)
> -+		goto print_cond_part;
> -+	if (acl->is_deleted)
> -+		return true;
> -+	if (!ccs_flush(head))
> -+		return false;
> -+	else if (acl_type == CCS_TYPE_PATH_ACL) {
> -+		struct ccs_path_acl *ptr
> -+			= container_of(acl, typeof(*ptr), head);
> -+		for (bit = 0; bit < CCS_MAX_PATH_OPERATION; bit++) {
> -+			if (!(acl->perm & (1 << bit)))
> -+				continue;
> -+			if (head->r.print_transition_related_only &&
> -+			    bit != CCS_TYPE_EXECUTE && !may_trigger_transition)
> -+				continue;
> -+			if (first) {
> -+				ccs_set_group(head, "file ");
> -+				first = false;
> -+			} else {
> -+				ccs_set_slash(head);
> -+			}
> -+			ccs_set_string(head, ccs_path_keyword[bit]);
> -+		}
> -+		if (first)
> -+			return true;
> -+		ccs_print_name_union(head, &ptr->name);
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	} else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||
> -+		   acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
> -+		struct ccs_handler_acl *ptr
> -+			= container_of(acl, typeof(*ptr), head);
> -+		ccs_set_group(head, "task ");
> -+		ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER
> -+			       ? "auto_execute_handler " :
> -+			       "denied_execute_handler ");
> -+		ccs_set_string(head, ptr->handler->name);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+	} else if (acl_type == CCS_TYPE_AUTO_TASK_ACL ||
> -+		   acl_type == CCS_TYPE_MANUAL_TASK_ACL) {
> -+		struct ccs_task_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		ccs_set_group(head, "task ");
> -+		ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?
> -+			       "auto_domain_transition " :
> -+			       "manual_domain_transition ");
> -+		ccs_set_string(head, ptr->domainname->name);
> -+#endif
> -+	} else if (head->r.print_transition_related_only &&
> -+		   !may_trigger_transition) {
> -+		return true;
> -+	} else if (acl_type == CCS_TYPE_MKDEV_ACL) {
> -+		struct ccs_mkdev_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		for (bit = 0; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
> -+			if (!(acl->perm & (1 << bit)))
> -+				continue;
> -+			if (first) {
> -+				ccs_set_group(head, "file ");
> -+				first = false;
> -+			} else {
> -+				ccs_set_slash(head);
> -+			}
> -+			ccs_set_string(head, ccs_mac_keywords
> -+				       [ccs_pnnn2mac[bit]]);
> -+		}
> -+		if (first)
> -+			return true;
> -+		ccs_print_name_union(head, &ptr->name);
> -+		ccs_print_number_union(head, &ptr->mode);
> -+		ccs_print_number_union(head, &ptr->major);
> -+		ccs_print_number_union(head, &ptr->minor);
> -+	} else if (acl_type == CCS_TYPE_PATH2_ACL) {
> -+		struct ccs_path2_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		for (bit = 0; bit < CCS_MAX_PATH2_OPERATION; bit++) {
> -+			if (!(acl->perm & (1 << bit)))
> -+				continue;
> -+			if (first) {
> -+				ccs_set_group(head, "file ");
> -+				first = false;
> -+			} else {
> -+				ccs_set_slash(head);
> -+			}
> -+			ccs_set_string(head, ccs_mac_keywords
> -+				       [ccs_pp2mac[bit]]);
> -+		}
> -+		if (first)
> -+			return true;
> -+		ccs_print_name_union(head, &ptr->name1);
> -+		ccs_print_name_union(head, &ptr->name2);
> -+	} else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
> -+		struct ccs_path_number_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		for (bit = 0; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
> -+			if (!(acl->perm & (1 << bit)))
> -+				continue;
> -+			if (first) {
> -+				ccs_set_group(head, "file ");
> -+				first = false;
> -+			} else {
> -+				ccs_set_slash(head);
> -+			}
> -+			ccs_set_string(head, ccs_mac_keywords
> -+				       [ccs_pn2mac[bit]]);
> -+		}
> -+		if (first)
> -+			return true;
> -+		ccs_print_name_union(head, &ptr->name);
> -+		ccs_print_number_union(head, &ptr->number);
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	} else if (acl_type == CCS_TYPE_ENV_ACL) {
> -+		struct ccs_env_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		ccs_set_group(head, "misc env ");
> -+		ccs_set_string(head, ptr->env->name);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	} else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
> -+		struct ccs_capability_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		ccs_set_group(head, "capability ");
> -+		ccs_set_string(head, ccs_mac_keywords
> -+			       [ccs_c2mac[ptr->operation]]);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	} else if (acl_type == CCS_TYPE_INET_ACL) {
> -+		struct ccs_inet_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
> -+			if (!(acl->perm & (1 << bit)))
> -+				continue;
> -+			if (first) {
> -+				ccs_set_group(head, "network inet ");
> -+				ccs_set_string(head, ccs_proto_keyword
> -+					       [ptr->protocol]);
> -+				ccs_set_space(head);
> -+				first = false;
> -+			} else {
> -+				ccs_set_slash(head);
> -+			}
> -+			ccs_set_string(head, ccs_socket_keyword[bit]);
> -+		}
> -+		if (first)
> -+			return true;
> -+		ccs_set_space(head);
> -+		if (!ccs_print_group(head, ptr->address.group)) {
> -+			char buf[128];
> -+			ccs_print_ip(buf, sizeof(buf), &ptr->address);
> -+			ccs_io_printf(head, "%s", buf);
> -+		}
> -+		ccs_print_number_union(head, &ptr->port);
> -+	} else if (acl_type == CCS_TYPE_UNIX_ACL) {
> -+		struct ccs_unix_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
> -+			if (!(acl->perm & (1 << bit)))
> -+				continue;
> -+			if (first) {
> -+				ccs_set_group(head, "network unix ");
> -+				ccs_set_string(head, ccs_proto_keyword
> -+					       [ptr->protocol]);
> -+				ccs_set_space(head);
> -+				first = false;
> -+			} else {
> -+				ccs_set_slash(head);
> -+			}
> -+			ccs_set_string(head, ccs_socket_keyword[bit]);
> -+		}
> -+		if (first)
> -+			return true;
> -+		ccs_print_name_union(head, &ptr->name);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	} else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
> -+		struct ccs_signal_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		ccs_set_group(head, "ipc signal ");
> -+		ccs_print_number_union_nospace(head, &ptr->sig);
> -+		ccs_set_space(head);
> -+		ccs_set_string(head, ptr->domainname->name);
> -+#endif
> -+	} else if (acl_type == CCS_TYPE_MOUNT_ACL) {
> -+		struct ccs_mount_acl *ptr =
> -+			container_of(acl, typeof(*ptr), head);
> -+		ccs_set_group(head, "file mount");
> -+		ccs_print_name_union(head, &ptr->dev_name);
> -+		ccs_print_name_union(head, &ptr->dir_name);
> -+		ccs_print_name_union(head, &ptr->fs_type);
> -+		ccs_print_number_union(head, &ptr->flags);
> -+	}
> -+	if (acl->cond) {
> -+		head->r.print_cond_part = true;
> -+		head->r.cond_step = 0;
> -+		if (!ccs_flush(head))
> -+			return false;
> -+print_cond_part:
> -+		if (!ccs_print_condition(head, acl->cond))
> -+			return false;
> -+		head->r.print_cond_part = false;
> -+	} else {
> -+		ccs_set_lf(head);
> -+	}
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_read_acl - Read "struct ccs_acl_info" list.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @list: Pointer to "struct list_head".
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_read_acl(struct ccs_io_buffer *head, struct list_head *list)
> -+{
> -+	list_for_each_cookie(head->r.acl, list) {
> -+		struct ccs_acl_info *ptr =
> -+			list_entry(head->r.acl, typeof(*ptr), list);
> -+		if (!ccs_print_entry(head, ptr))
> -+			return false;
> -+	}
> -+	head->r.acl = NULL;
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_read_domain - Read domain policy.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static void ccs_read_domain(struct ccs_io_buffer *head)
> -+{
> -+	if (head->r.eof)
> -+		return;
> -+	list_for_each_cookie(head->r.domain, &ccs_domain_list) {
> -+		struct ccs_domain_info *domain =
> -+			list_entry(head->r.domain, typeof(*domain), list);
> -+		switch (head->r.step) {
> -+			u8 i;
> -+		case 0:
> -+			if (domain->is_deleted &&
> -+			    !head->r.print_this_domain_only)
> -+				continue;
> -+			/* Print domainname and flags. */
> -+			ccs_set_string(head, domain->domainname->name);
> -+			ccs_set_lf(head);
> -+			ccs_io_printf(head, "use_profile %u\n",
> -+				      domain->profile);
> -+			for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)
> -+				if (domain->flags[i])
> -+					ccs_set_string(head, ccs_dif[i]);
> -+			head->r.index = 0;
> -+			head->r.step++;
> -+			/* fall through */
> -+		case 1:
> -+			while (head->r.index < CCS_MAX_ACL_GROUPS) {
> -+				i = head->r.index++;
> -+				if (!test_bit(i, domain->group))
> -+					continue;
> -+				ccs_io_printf(head, "use_group %u\n", i);
> -+				if (!ccs_flush(head))
> -+					return;
> -+			}
> -+			head->r.index = 0;
> -+			head->r.step++;
> -+			ccs_set_lf(head);
> -+			/* fall through */
> -+		case 2:
> -+			if (!ccs_read_acl(head, &domain->acl_info_list))
> -+				return;
> -+			head->r.step++;
> -+			if (!ccs_set_lf(head))
> -+				return;
> -+			/* fall through */
> -+		case 3:
> -+			head->r.step = 0;
> -+			if (head->r.print_this_domain_only)
> -+				goto done;
> -+		}
> -+	}
> -+done:
> -+	head->r.eof = true;
> -+}
> -+
> -+/**
> -+ * ccs_write_pid - Specify PID to obtain domainname.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns 0.
> -+ */
> -+static int ccs_write_pid(struct ccs_io_buffer *head)
> -+{
> -+	head->r.eof = false;
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_read_pid - Read information of a process.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns the domainname which the specified PID is in or
> -+ * process information of the specified PID on success,
> -+ * empty string otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static void ccs_read_pid(struct ccs_io_buffer *head)
> -+{
> -+	char *buf = head->write_buf;
> -+	bool task_info = false;
> -+	bool global_pid = false;
> -+	unsigned int pid;
> -+	struct task_struct *p;
> -+	struct ccs_domain_info *domain = NULL;
> -+	u32 ccs_flags = 0;
> -+	/* Accessing write_buf is safe because head->io_sem is held. */
> -+	if (!buf) {
> -+		head->r.eof = true;
> -+		return; /* Do nothing if open(O_RDONLY). */
> -+	}
> -+	if (head->r.w_pos || head->r.eof)
> -+		return;
> -+	head->r.eof = true;
> -+	if (ccs_str_starts(&buf, "info "))
> -+		task_info = true;
> -+	if (ccs_str_starts(&buf, "global-pid "))
> -+		global_pid = true;
> -+	pid = (unsigned int) simple_strtoul(buf, NULL, 10);
> -+	ccs_tasklist_lock();
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
> -+	if (global_pid)
> -+		p = ccsecurity_exports.find_task_by_pid_ns(pid, &init_pid_ns);
> -+	else
> -+		p = ccsecurity_exports.find_task_by_vpid(pid);
> -+#else
> -+	p = find_task_by_pid(pid);
> -+#endif
> -+	if (p) {
> -+		domain = ccs_task_domain(p);
> -+		ccs_flags = ccs_task_flags(p);
> -+	}
> -+	ccs_tasklist_unlock();
> -+	if (!domain)
> -+		return;
> -+	if (!task_info) {
> -+		ccs_io_printf(head, "%u %u ", pid, domain->profile);
> -+		ccs_set_string(head, domain->domainname->name);
> -+	} else {
> -+		ccs_io_printf(head, "%u manager=%s execute_handler=%s ", pid,
> -+			      ccs_yesno(ccs_flags &
> -+					CCS_TASK_IS_MANAGER),
> -+			      ccs_yesno(ccs_flags &
> -+					CCS_TASK_IS_EXECUTE_HANDLER));
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_write_group - Write "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ * @type:  Type of this group.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_write_group(struct ccs_acl_param *param, const u8 type)
> -+{
> -+	struct ccs_group *group = ccs_get_group(param, type);
> -+	int error = -EINVAL;
> -+	if (!group)
> -+		return -ENOMEM;
> -+	param->list = &group->member_list;
> -+	if (type == CCS_PATH_GROUP) {
> -+		struct ccs_path_group *e = &param->e.path_group;
> -+		e->member_name = ccs_get_name(ccs_read_token(param));
> -+		if (!e->member_name) {
> -+			error = -ENOMEM;
> -+			goto out;
> -+		}
> -+		error = ccs_update_policy(sizeof(*e), param);
> -+		ccs_put_name(e->member_name);
> -+	} else if (type == CCS_NUMBER_GROUP) {
> -+		struct ccs_number_group *e = &param->e.number_group;
> -+		if (param->data[0] == '@' ||
> -+		    !ccs_parse_number_union(param, &e->number))
> -+			goto out;
> -+		error = ccs_update_policy(sizeof(*e), param);
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	} else {
> -+		struct ccs_address_group *e = &param->e.address_group;
> -+		if (param->data[0] == '@' ||
> -+		    !ccs_parse_ipaddr_union(param, &e->address))
> -+			goto out;
> -+		error = ccs_update_policy(sizeof(*e), param);
> -+#endif
> -+	}
> -+out:
> -+	ccs_put_group(group);
> -+	return error;
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_PORTRESERVE
> -+/**
> -+ * ccs_lport_reserved - Check whether local port is reserved or not.
> -+ *
> -+ * @port: Port number.
> -+ *
> -+ * Returns true if local port is reserved, false otherwise.
> -+ */
> -+static bool __ccs_lport_reserved(const u16 port)
> -+{
> -+	return ccs_reserved_port_map[port >> 3] & (1 << (port & 7))
> -+		? true : false;
> -+}
> -+
> -+/**
> -+ * ccs_write_reserved_port - Update "struct ccs_reserved" list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_write_reserved_port(struct ccs_acl_param *param)
> -+{
> -+	struct ccs_reserved *e = &param->e.reserved;
> -+	struct ccs_policy_namespace *ns = param->ns;
> -+	int error;
> -+	u8 *tmp;
> -+	if (param->data[0] == '@' ||
> -+	    !ccs_parse_number_union(param, &e->port) ||
> -+	    e->port.values[1] > 65535 || param->data[0])
> -+		return -EINVAL;
> -+	param->list = &ns->policy_list[CCS_ID_RESERVEDPORT];
> -+	error = ccs_update_policy(sizeof(*e), param);
> -+	if (error)
> -+		return error;
> -+	tmp = kzalloc(sizeof(ccs_reserved_port_map), CCS_GFP_FLAGS);
> -+	if (!tmp)
> -+		return -ENOMEM;
> -+	list_for_each_entry_srcu(ns, &ccs_namespace_list, namespace_list,
> -+				 &ccs_ss) {
> -+		struct ccs_reserved *ptr;
> -+		struct list_head *list = &ns->policy_list[CCS_ID_RESERVEDPORT];
> -+		list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
> -+			unsigned int port;
> -+			if (ptr->head.is_deleted)
> -+				continue;
> -+			for (port = ptr->port.values[0];
> -+			     port <= ptr->port.values[1]; port++)
> -+				tmp[port >> 3] |= 1 << (port & 7);
> -+		}
> -+	}
> -+	memmove(ccs_reserved_port_map, tmp, sizeof(ccs_reserved_port_map));
> -+	kfree(tmp);
> -+	/*
> -+	 * Since this feature is no-op by default, we don't need to register
> -+	 * this callback hook unless the first entry is added.
> -+	 */
> -+	ccsecurity_ops.lport_reserved = __ccs_lport_reserved;
> -+	return 0;
> -+}
> -+#endif
> -+
> -+/**
> -+ * ccs_write_aggregator - Write "struct ccs_aggregator" list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_write_aggregator(struct ccs_acl_param *param)
> -+{
> -+	struct ccs_aggregator *e = &param->e.aggregator;
> -+	int error = param->is_delete ? -ENOENT : -ENOMEM;
> -+	const char *original_name = ccs_read_token(param);
> -+	const char *aggregated_name = ccs_read_token(param);
> -+	if (!ccs_correct_word(original_name) ||
> -+	    !ccs_correct_path(aggregated_name))
> -+		return -EINVAL;
> -+	e->original_name = ccs_get_name(original_name);
> -+	e->aggregated_name = ccs_get_name(aggregated_name);
> -+	if (!e->original_name || !e->aggregated_name ||
> -+	    e->aggregated_name->is_patterned) /* No patterns allowed. */
> -+		goto out;
> -+	param->list = &param->ns->policy_list[CCS_ID_AGGREGATOR];
> -+	error = ccs_update_policy(sizeof(*e), param);
> -+out:
> -+	ccs_put_name(e->original_name);
> -+	ccs_put_name(e->aggregated_name);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_write_transition_control - Write "struct ccs_transition_control" list.
> -+ *
> -+ * @param: Pointer to "struct ccs_acl_param".
> -+ * @type:  Type of this entry.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_write_transition_control(struct ccs_acl_param *param,
> -+					const u8 type)
> -+{
> -+	struct ccs_transition_control *e = &param->e.transition_control;
> -+	int error = param->is_delete ? -ENOENT : -ENOMEM;
> -+	char *program = param->data;
> -+	char *domainname = strstr(program, " from ");
> -+	e->type = type;
> -+	if (domainname) {
> -+		*domainname = '\0';
> -+		domainname += 6;
> -+	} else if (type == CCS_TRANSITION_CONTROL_NO_KEEP ||
> -+		   type == CCS_TRANSITION_CONTROL_KEEP) {
> -+		domainname = program;
> -+		program = NULL;
> -+	}
> -+	if (program && strcmp(program, "any")) {
> -+		if (!ccs_correct_path(program))
> -+			return -EINVAL;
> -+		e->program = ccs_get_name(program);
> -+		if (!e->program)
> -+			goto out;
> -+	}
> -+	if (domainname && strcmp(domainname, "any")) {
> -+		if (!ccs_correct_domain(domainname)) {
> -+			if (!ccs_correct_path(domainname))
> -+				goto out;
> -+			e->is_last_name = true;
> -+		}
> -+		e->domainname = ccs_get_name(domainname);
> -+		if (!e->domainname)
> -+			goto out;
> -+	}
> -+	param->list = &param->ns->policy_list[CCS_ID_TRANSITION_CONTROL];
> -+	error = ccs_update_policy(sizeof(*e), param);
> -+out:
> -+	ccs_put_name(e->domainname);
> -+	ccs_put_name(e->program);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_write_exception - Write exception policy.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_write_exception(struct ccs_io_buffer *head)
> -+{
> -+	const bool is_delete = head->w.is_delete;
> -+	struct ccs_acl_param param = {
> -+		.ns = head->w.ns,
> -+		.is_delete = is_delete,
> -+		.data = head->write_buf,
> -+	};
> -+	u8 i;
> -+	/* Forced zero clear for using memcmp() at ccs_update_policy(). */
> -+	memset(&param.e, 0, sizeof(param.e));
> -+	if (ccs_str_starts(&param.data, "aggregator "))
> -+		return ccs_write_aggregator(&param);
> -+#ifdef CONFIG_CCSECURITY_PORTRESERVE
> -+	if (ccs_str_starts(&param.data, "deny_autobind "))
> -+		return ccs_write_reserved_port(&param);
> -+#endif
> -+	for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
> -+		if (ccs_str_starts(&param.data, ccs_transition_type[i]))
> -+			return ccs_write_transition_control(&param, i);
> -+	for (i = 0; i < CCS_MAX_GROUP; i++)
> -+		if (ccs_str_starts(&param.data, ccs_group_name[i]))
> -+			return ccs_write_group(&param, i);
> -+	if (ccs_str_starts(&param.data, "acl_group ")) {
> -+		unsigned int group;
> -+		char *data;
> -+		group = simple_strtoul(param.data, &data, 10);
> -+		if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
> -+			return ccs_write_acl(head->w.ns,
> -+					     &head->w.ns->acl_group[group],
> -+					     data, is_delete);
> -+	}
> -+	return -EINVAL;
> -+}
> -+
> -+/**
> -+ * ccs_read_group - Read "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @idx:  Index number.
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)
> -+{
> -+	struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
> -+						       namespace_list);
> -+	struct list_head *list = &ns->group_list[idx];
> -+	list_for_each_cookie(head->r.group, list) {
> -+		struct ccs_group *group =
> -+			list_entry(head->r.group, typeof(*group), head.list);
> -+		list_for_each_cookie(head->r.acl, &group->member_list) {
> -+			struct ccs_acl_head *ptr =
> -+				list_entry(head->r.acl, typeof(*ptr), list);
> -+			if (ptr->is_deleted)
> -+				continue;
> -+			if (!ccs_flush(head))
> -+				return false;
> -+			ccs_print_namespace(head);
> -+			ccs_set_string(head, ccs_group_name[idx]);
> -+			ccs_set_string(head, group->group_name->name);
> -+			if (idx == CCS_PATH_GROUP) {
> -+				ccs_set_space(head);
> -+				ccs_set_string(head, container_of
> -+					       (ptr, struct ccs_path_group,
> -+						head)->member_name->name);
> -+			} else if (idx == CCS_NUMBER_GROUP) {
> -+				ccs_print_number_union(head, &container_of
> -+					       (ptr, struct ccs_number_group,
> -+						head)->number);
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+			} else if (idx == CCS_ADDRESS_GROUP) {
> -+				char buffer[128];
> -+				struct ccs_address_group *member =
> -+					container_of(ptr, typeof(*member),
> -+						     head);
> -+				ccs_print_ip(buffer, sizeof(buffer),
> -+					     &member->address);
> -+				ccs_io_printf(head, " %s", buffer);
> -+#endif
> -+			}
> -+			ccs_set_lf(head);
> -+		}
> -+		head->r.acl = NULL;
> -+	}
> -+	head->r.group = NULL;
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_read_policy - Read "struct ccs_..._entry" list.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ * @idx:  Index number.
> -+ *
> -+ * Returns true on success, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)
> -+{
> -+	struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
> -+						       namespace_list);
> -+	struct list_head *list = &ns->policy_list[idx];
> -+	list_for_each_cookie(head->r.acl, list) {
> -+		struct ccs_acl_head *acl =
> -+			container_of(head->r.acl, typeof(*acl), list);
> -+		if (acl->is_deleted)
> -+			continue;
> -+		if (head->r.print_transition_related_only &&
> -+		    idx != CCS_ID_TRANSITION_CONTROL)
> -+			continue;
> -+		if (!ccs_flush(head))
> -+			return false;
> -+		switch (idx) {
> -+		case CCS_ID_TRANSITION_CONTROL:
> -+			{
> -+				struct ccs_transition_control *ptr =
> -+					container_of(acl, typeof(*ptr), head);
> -+				ccs_print_namespace(head);
> -+				ccs_set_string(head,
> -+					       ccs_transition_type[ptr->type]);
> -+				ccs_set_string(head, ptr->program ?
> -+					       ptr->program->name : "any");
> -+				ccs_set_string(head, " from ");
> -+				ccs_set_string(head, ptr->domainname ?
> -+					       ptr->domainname->name : "any");
> -+			}
> -+			break;
> -+		case CCS_ID_AGGREGATOR:
> -+			{
> -+				struct ccs_aggregator *ptr =
> -+					container_of(acl, typeof(*ptr), head);
> -+				ccs_print_namespace(head);
> -+				ccs_set_string(head, "aggregator ");
> -+				ccs_set_string(head, ptr->original_name->name);
> -+				ccs_set_space(head);
> -+				ccs_set_string(head,
> -+					       ptr->aggregated_name->name);
> -+			}
> -+			break;
> -+#ifdef CONFIG_CCSECURITY_PORTRESERVE
> -+		case CCS_ID_RESERVEDPORT:
> -+			{
> -+				struct ccs_reserved *ptr =
> -+					container_of(acl, typeof(*ptr), head);
> -+				ccs_print_namespace(head);
> -+				ccs_set_string(head, "deny_autobind ");
> -+				ccs_print_number_union_nospace(head,
> -+							       &ptr->port);
> -+			}
> -+			break;
> -+#endif
> -+		default:
> -+			continue;
> -+		}
> -+		ccs_set_lf(head);
> -+	}
> -+	head->r.acl = NULL;
> -+	return true;
> -+}
> -+
> -+/**
> -+ * ccs_read_exception - Read exception policy.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static void ccs_read_exception(struct ccs_io_buffer *head)
> -+{
> -+	struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
> -+						       namespace_list);
> -+	if (head->r.eof)
> -+		return;
> -+	while (head->r.step < CCS_MAX_POLICY &&
> -+	       ccs_read_policy(head, head->r.step))
> -+		head->r.step++;
> -+	if (head->r.step < CCS_MAX_POLICY)
> -+		return;
> -+	while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP &&
> -+	       ccs_read_group(head, head->r.step - CCS_MAX_POLICY))
> -+		head->r.step++;
> -+	if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)
> -+		return;
> -+	while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
> -+	       + CCS_MAX_ACL_GROUPS) {
> -+		head->r.acl_group_index =
> -+			head->r.step - CCS_MAX_POLICY - CCS_MAX_GROUP;
> -+		if (!ccs_read_acl(head, &ns->acl_group
> -+				  [head->r.acl_group_index]))
> -+			return;
> -+		head->r.step++;
> -+	}
> -+	head->r.eof = true;
> -+}
> -+
> -+/**
> -+ * ccs_truncate - Truncate a line.
> -+ *
> -+ * @str: String to truncate.
> -+ *
> -+ * Returns length of truncated @str.
> -+ */
> -+static int ccs_truncate(char *str)
> -+{
> -+	char *start = str;
> -+	while (*(unsigned char *) str > (unsigned char) ' ')
> -+		str++;
> -+	*str = '\0';
> -+	return strlen(start) + 1;
> -+}
> -+
> -+/**
> -+ * ccs_add_entry - Add an ACL to current thread's domain. Used by learning mode.
> -+ *
> -+ * @header: Lines containing ACL.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_add_entry(char *header)
> -+{
> -+	char *buffer;
> -+	char *realpath = NULL;
> -+	char *argv0 = NULL;
> -+	char *symlink = NULL;
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	char *handler;
> -+#endif
> -+	char *cp = strchr(header, '\n');
> -+	int len;
> -+	if (!cp)
> -+		return;
> -+	cp = strchr(cp + 1, '\n');
> -+	if (!cp)
> -+		return;
> -+	*cp++ = '\0';
> -+	len = strlen(cp) + 1;
> -+	/* strstr() will return NULL if ordering is wrong. */
> -+	if (*cp == 'f') {
> -+		argv0 = strstr(header, " argv[]={ \"");
> -+		if (argv0) {
> -+			argv0 += 10;
> -+			len += ccs_truncate(argv0) + 14;
> -+		}
> -+		realpath = strstr(header, " exec={ realpath=\"");
> -+		if (realpath) {
> -+			realpath += 8;
> -+			len += ccs_truncate(realpath) + 6;
> -+		}
> -+		symlink = strstr(header, " symlink.target=\"");
> -+		if (symlink)
> -+			len += ccs_truncate(symlink + 1) + 1;
> -+	}
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	handler = strstr(header, "type=execute_handler");
> -+	if (handler)
> -+		len += ccs_truncate(handler) + 6;
> -+#endif
> -+	buffer = kmalloc(len, CCS_GFP_FLAGS);
> -+	if (!buffer)
> -+		return;
> -+	snprintf(buffer, len - 1, "%s", cp);
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	if (handler)
> -+		ccs_addprintf(buffer, len, " task.%s", handler);
> -+#endif
> -+	if (realpath)
> -+		ccs_addprintf(buffer, len, " exec.%s", realpath);
> -+	if (argv0)
> -+		ccs_addprintf(buffer, len, " exec.argv[0]=%s", argv0);
> -+	if (symlink)
> -+		ccs_addprintf(buffer, len, "%s", symlink);
> -+	ccs_normalize_line(buffer);
> -+	{
> -+		struct ccs_domain_info *domain = ccs_current_domain();
> -+		if (!ccs_write_acl(domain->ns, &domain->acl_info_list,
> -+				   buffer, false))
> -+			ccs_update_stat(CCS_STAT_POLICY_UPDATES);
> -+	}
> -+	kfree(buffer);
> -+}
> -+
> -+/**
> -+ * ccs_domain_quota_ok - Check for domain's quota.
> -+ *
> -+ * @r: Pointer to "struct ccs_request_info".
> -+ *
> -+ * Returns true if the domain is not exceeded quota, false otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static bool ccs_domain_quota_ok(struct ccs_request_info *r)
> -+{
> -+	unsigned int count = 0;
> -+	struct ccs_domain_info * const domain = ccs_current_domain();
> -+	struct ccs_acl_info *ptr;
> -+	if (r->mode != CCS_CONFIG_LEARNING)
> -+		return false;
> -+	if (!domain)
> -+		return true;
> -+	list_for_each_entry_srcu(ptr, &domain->acl_info_list, list, &ccs_ss) {
> -+		u16 perm;
> -+		u8 i;
> -+		if (ptr->is_deleted)
> -+			continue;
> -+		switch (ptr->type) {
> -+		case CCS_TYPE_PATH_ACL:
> -+		case CCS_TYPE_PATH2_ACL:
> -+		case CCS_TYPE_PATH_NUMBER_ACL:
> -+		case CCS_TYPE_MKDEV_ACL:
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+		case CCS_TYPE_INET_ACL:
> -+		case CCS_TYPE_UNIX_ACL:
> -+#endif
> -+			perm = ptr->perm;
> -+			break;
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+		case CCS_TYPE_AUTO_EXECUTE_HANDLER:
> -+		case CCS_TYPE_DENIED_EXECUTE_HANDLER:
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+		case CCS_TYPE_AUTO_TASK_ACL:
> -+		case CCS_TYPE_MANUAL_TASK_ACL:
> -+#endif
> -+			perm = 0;
> -+			break;
> -+		default:
> -+			perm = 1;
> -+		}
> -+		for (i = 0; i < 16; i++)
> -+			if (perm & (1 << i))
> -+				count++;
> -+	}
> -+	if (count < ccs_profile(r->profile)->pref[CCS_PREF_MAX_LEARNING_ENTRY])
> -+		return true;
> -+	if (!domain->flags[CCS_DIF_QUOTA_WARNED]) {
> -+		domain->flags[CCS_DIF_QUOTA_WARNED] = true;
> -+		/* r->granted = false; */
> -+		ccs_write_log(r, "%s", ccs_dif[CCS_DIF_QUOTA_WARNED]);
> -+		printk(KERN_WARNING "WARNING: "
> -+		       "Domain '%s' has too many ACLs to hold. "
> -+		       "Stopped learning mode.\n", domain->domainname->name);
> -+	}
> -+	return false;
> -+}
> -+
> -+/**
> -+ * ccs_supervisor - Ask for the supervisor's decision.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @fmt: The printf()'s format string, followed by parameters.
> -+ *
> -+ * Returns 0 if the supervisor decided to permit the access request which
> -+ * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor
> -+ * decided to retry the access request which violated the policy in enforcing
> -+ * mode, 0 if it is not in enforcing mode, -EPERM otherwise.
> -+ */
> -+static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
> -+{
> -+	va_list args;
> -+	int error;
> -+	int len;
> -+	static unsigned int ccs_serial;
> -+	struct ccs_query entry = { };
> -+	bool quota_exceeded = false;
> -+	va_start(args, fmt);
> -+	len = vsnprintf((char *) &len, 1, fmt, args) + 1;
> -+	va_end(args);
> -+	/* Write /proc/ccs/audit. */
> -+	va_start(args, fmt);
> -+	ccs_write_log2(r, len, fmt, args);
> -+	va_end(args);
> -+	/* Nothing more to do if granted. */
> -+	if (r->granted)
> -+		return 0;
> -+	if (r->mode)
> -+		ccs_update_stat(r->mode);
> -+	switch (r->mode) {
> -+		int i;
> -+		struct ccs_profile *p;
> -+	case CCS_CONFIG_ENFORCING:
> -+		error = -EPERM;
> -+		if (atomic_read(&ccs_query_observers))
> -+			break;
> -+		if (r->dont_sleep_on_enforce_error)
> -+			goto out;
> -+		p = ccs_profile(r->profile);
> -+		/* Check enforcing_penalty parameter. */
> -+		for (i = 0; i < p->pref[CCS_PREF_ENFORCING_PENALTY]; i++) {
> -+			set_current_state(TASK_INTERRUPTIBLE);
> -+			schedule_timeout(HZ / 10);
> -+		}
> -+		goto out;
> -+	case CCS_CONFIG_LEARNING:
> -+		error = 0;
> -+		/* Check max_learning_entry parameter. */
> -+		if (ccs_domain_quota_ok(r))
> -+			break;
> -+		/* fall through */
> -+	default:
> -+		return 0;
> -+	}
> -+	/* Get message. */
> -+	va_start(args, fmt);
> -+	entry.query = ccs_init_log(r, len, fmt, args);
> -+	va_end(args);
> -+	if (!entry.query)
> -+		goto out;
> -+	entry.query_len = strlen(entry.query) + 1;
> -+	if (!error) {
> -+		ccs_add_entry(entry.query);
> -+		goto out;
> -+	}
> -+	len = ccs_round2(entry.query_len);
> -+	entry.domain = ccs_current_domain();
> -+	spin_lock(&ccs_query_list_lock);
> -+	if (ccs_memory_quota[CCS_MEMORY_QUERY] &&
> -+	    ccs_memory_used[CCS_MEMORY_QUERY] + len
> -+	    >= ccs_memory_quota[CCS_MEMORY_QUERY]) {
> -+		quota_exceeded = true;
> -+	} else {
> -+		entry.serial = ccs_serial++;
> -+		entry.retry = r->retry;
> -+		ccs_memory_used[CCS_MEMORY_QUERY] += len;
> -+		list_add_tail(&entry.list, &ccs_query_list);
> -+	}
> -+	spin_unlock(&ccs_query_list_lock);
> -+	if (quota_exceeded)
> -+		goto out;
> -+	/* Give 10 seconds for supervisor's opinion. */
> -+	while (entry.timer < 10) {
> -+		wake_up_all(&ccs_query_wait);
> -+		if (wait_event_interruptible_timeout
> -+		    (ccs_answer_wait, entry.answer ||
> -+		     !atomic_read(&ccs_query_observers), HZ))
> -+			break;
> -+		else
> -+			entry.timer++;
> -+	}
> -+	spin_lock(&ccs_query_list_lock);
> -+	list_del(&entry.list);
> -+	ccs_memory_used[CCS_MEMORY_QUERY] -= len;
> -+	spin_unlock(&ccs_query_list_lock);
> -+	switch (entry.answer) {
> -+	case 3: /* Asked to retry by administrator. */
> -+		error = CCS_RETRY_REQUEST;
> -+		r->retry++;
> -+		break;
> -+	case 1:
> -+		/* Granted by administrator. */
> -+		error = 0;
> -+		break;
> -+	default:
> -+		/* Timed out or rejected by administrator. */
> -+		break;
> -+	}
> -+out:
> -+	kfree(entry.query);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_audit_log - Audit permission check log.
> -+ *
> -+ * @r: Pointer to "struct ccs_request_info".
> -+ *
> -+ * Returns return value of ccs_supervisor().
> -+ */
> -+int ccs_audit_log(struct ccs_request_info *r)
> -+{
> -+	switch (r->param_type) {
> -+		u8 type;
> -+		char buf[48];
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+		const u32 *address;
> -+#endif
> -+	case CCS_TYPE_PATH_ACL:
> -+		return ccs_supervisor(r, "file %s %s\n", ccs_path_keyword
> -+				      [r->param.path.operation],
> -+				      r->param.path.filename->name);
> -+	case CCS_TYPE_PATH2_ACL:
> -+		return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords
> -+				      [ccs_pp2mac[r->param.path2.operation]],
> -+				      r->param.path2.filename1->name,
> -+				      r->param.path2.filename2->name);
> -+	case CCS_TYPE_PATH_NUMBER_ACL:
> -+		type = r->param.path_number.operation;
> -+		switch (type) {
> -+		case CCS_TYPE_CREATE:
> -+		case CCS_TYPE_MKDIR:
> -+		case CCS_TYPE_MKFIFO:
> -+		case CCS_TYPE_MKSOCK:
> -+		case CCS_TYPE_CHMOD:
> -+			snprintf(buf, sizeof(buf), "0%lo",
> -+				 r->param.path_number.number);
> -+			break;
> -+		case CCS_TYPE_IOCTL:
> -+			snprintf(buf, sizeof(buf), "0x%lX",
> -+				 r->param.path_number.number);
> -+			break;
> -+		default:
> -+			snprintf(buf, sizeof(buf), "%lu",
> -+				 r->param.path_number.number);
> -+			break;
> -+		}
> -+		return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords
> -+				      [ccs_pn2mac[type]],
> -+				      r->param.path_number.filename->name,
> -+				      buf);
> -+	case CCS_TYPE_MKDEV_ACL:
> -+		return ccs_supervisor(r, "file %s %s 0%o %u %u\n",
> -+				      ccs_mac_keywords
> -+				      [ccs_pnnn2mac[r->param.mkdev.operation]],
> -+				      r->param.mkdev.filename->name,
> -+				      r->param.mkdev.mode,
> -+				      r->param.mkdev.major,
> -+				      r->param.mkdev.minor);
> -+	case CCS_TYPE_MOUNT_ACL:
> -+		return ccs_supervisor(r, "file mount %s %s %s 0x%lX\n",
> -+				      r->param.mount.dev->name,
> -+				      r->param.mount.dir->name,
> -+				      r->param.mount.type->name,
> -+				      r->param.mount.flags);
> -+#ifdef CONFIG_CCSECURITY_MISC
> -+	case CCS_TYPE_ENV_ACL:
> -+		return ccs_supervisor(r, "misc env %s\n",
> -+				      r->param.environ.name->name);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_CAPABILITY
> -+	case CCS_TYPE_CAPABILITY_ACL:
> -+		return ccs_supervisor(r, "capability %s\n", ccs_mac_keywords
> -+				      [ccs_c2mac[r->param.capability.
> -+						 operation]]);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_NETWORK
> -+	case CCS_TYPE_INET_ACL:
> -+		address = r->param.inet_network.address;
> -+		if (r->param.inet_network.is_ipv6)
> -+			ccs_print_ipv6(buf, sizeof(buf),
> -+				       (const struct in6_addr *) address);
> -+		else
> -+			ccs_print_ipv4(buf, sizeof(buf), address);
> -+		return ccs_supervisor(r, "network inet %s %s %s %u\n",
> -+				      ccs_proto_keyword[r->param.inet_network.
> -+							protocol],
> -+				      ccs_socket_keyword[r->param.inet_network.
> -+							 operation],
> -+				      buf, r->param.inet_network.port);
> -+	case CCS_TYPE_UNIX_ACL:
> -+		return ccs_supervisor(r, "network unix %s %s %s\n",
> -+				      ccs_proto_keyword[r->param.
> -+							unix_network.protocol],
> -+				      ccs_socket_keyword[r->param.unix_network.
> -+							 operation],
> -+				      r->param.unix_network.address->name);
> -+#endif
> -+#ifdef CONFIG_CCSECURITY_IPC
> -+	case CCS_TYPE_SIGNAL_ACL:
> -+		return ccs_supervisor(r, "ipc signal %d %s\n",
> -+				      r->param.signal.sig,
> -+				      r->param.signal.dest_pattern);
> -+#endif
> -+	}
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_find_domain_by_qid - Get domain by query id.
> -+ *
> -+ * @serial: Query ID assigned by ccs_supervisor().
> -+ *
> -+ * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
> -+ */
> -+static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial)
> -+{
> -+	struct ccs_query *ptr;
> -+	struct ccs_domain_info *domain = NULL;
> -+	spin_lock(&ccs_query_list_lock);
> -+	list_for_each_entry(ptr, &ccs_query_list, list) {
> -+		if (ptr->serial != serial)
> -+			continue;
> -+		domain = ptr->domain;
> -+		break;
> -+	}
> -+	spin_unlock(&ccs_query_list_lock);
> -+	return domain;
> -+}
> -+
> -+/**
> -+ * ccs_read_query - Read access requests which violated policy in enforcing mode.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_read_query(struct ccs_io_buffer *head)
> -+{
> -+	struct list_head *tmp;
> -+	unsigned int pos = 0;
> -+	size_t len = 0;
> -+	char *buf;
> -+	if (head->r.w_pos)
> -+		return;
> -+	kfree(head->read_buf);
> -+	head->read_buf = NULL;
> -+	spin_lock(&ccs_query_list_lock);
> -+	list_for_each(tmp, &ccs_query_list) {
> -+		struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
> -+		if (pos++ != head->r.query_index)
> -+			continue;
> -+		len = ptr->query_len;
> -+		break;
> -+	}
> -+	spin_unlock(&ccs_query_list_lock);
> -+	if (!len) {
> -+		head->r.query_index = 0;
> -+		return;
> -+	}
> -+	buf = kzalloc(len + 32, CCS_GFP_FLAGS);
> -+	if (!buf)
> -+		return;
> -+	pos = 0;
> -+	spin_lock(&ccs_query_list_lock);
> -+	list_for_each(tmp, &ccs_query_list) {
> -+		struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
> -+		if (pos++ != head->r.query_index)
> -+			continue;
> -+		/*
> -+		 * Some query can be skipped because ccs_query_list
> -+		 * can change, but I don't care.
> -+		 */
> -+		if (len == ptr->query_len)
> -+			snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
> -+				 ptr->retry, ptr->query);
> -+		break;
> -+	}
> -+	spin_unlock(&ccs_query_list_lock);
> -+	if (buf[0]) {
> -+		head->read_buf = buf;
> -+		head->r.w[head->r.w_pos++] = buf;
> -+		head->r.query_index++;
> -+	} else {
> -+		kfree(buf);
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_write_answer - Write the supervisor's decision.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns 0 on success, -EINVAL otherwise.
> -+ */
> -+static int ccs_write_answer(struct ccs_io_buffer *head)
> -+{
> -+	char *data = head->write_buf;
> -+	struct list_head *tmp;
> -+	unsigned int serial;
> -+	unsigned int answer;
> -+	spin_lock(&ccs_query_list_lock);
> -+	list_for_each(tmp, &ccs_query_list) {
> -+		struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
> -+		ptr->timer = 0;
> -+	}
> -+	spin_unlock(&ccs_query_list_lock);
> -+	if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
> -+		return -EINVAL;
> -+	spin_lock(&ccs_query_list_lock);
> -+	list_for_each(tmp, &ccs_query_list) {
> -+		struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
> -+		if (ptr->serial != serial)
> -+			continue;
> -+		ptr->answer = (u8) answer;
> -+		/* Remove from ccs_query_list. */
> -+		if (ptr->answer) {
> -+			list_del(&ptr->list);
> -+			INIT_LIST_HEAD(&ptr->list);
> -+		}
> -+		break;
> -+	}
> -+	spin_unlock(&ccs_query_list_lock);
> -+	wake_up_all(&ccs_answer_wait);
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_read_version - Get version.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_read_version(struct ccs_io_buffer *head)
> -+{
> -+	if (head->r.eof)
> -+		return;
> -+	ccs_set_string(head, "1.8.4");
> -+	head->r.eof = true;
> -+}
> -+
> -+/**
> -+ * ccs_update_stat - Update statistic counters.
> -+ *
> -+ * @index: Index for policy type.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_update_stat(const u8 index)
> -+{
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
> -+	struct timeval tv;
> -+	do_gettimeofday(&tv);
> -+	/*
> -+	 * I don't use atomic operations because race condition is not fatal.
> -+	 */
> -+	ccs_stat_updated[index]++;
> -+	ccs_stat_modified[index] = tv.tv_sec;
> -+#else
> -+	/*
> -+	 * I don't use atomic operations because race condition is not fatal.
> -+	 */
> -+	ccs_stat_updated[index]++;
> -+	ccs_stat_modified[index] = get_seconds();
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_read_stat - Read statistic data.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_read_stat(struct ccs_io_buffer *head)
> -+{
> -+	u8 i;
> -+	unsigned int total = 0;
> -+	if (head->r.eof)
> -+		return;
> -+	for (i = 0; i < CCS_MAX_POLICY_STAT; i++) {
> -+		ccs_io_printf(head, "Policy %-30s %10u", ccs_policy_headers[i],
> -+			      ccs_stat_updated[i]);
> -+		if (ccs_stat_modified[i]) {
> -+			struct ccs_time stamp;
> -+			ccs_convert_time(ccs_stat_modified[i], &stamp);
> -+			ccs_io_printf(head, " (Last: %04u/%02u/%02u "
> -+				      "%02u:%02u:%02u)",
> -+				      stamp.year, stamp.month, stamp.day,
> -+				      stamp.hour, stamp.min, stamp.sec);
> -+		}
> -+		ccs_set_lf(head);
> -+	}
> -+	for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) {
> -+		unsigned int used = ccs_memory_used[i];
> -+		total += used;
> -+		ccs_io_printf(head, "Memory used by %-22s %10u",
> -+			      ccs_memory_headers[i], used);
> -+		used = ccs_memory_quota[i];
> -+		if (used)
> -+			ccs_io_printf(head, " (Quota: %10u)", used);
> -+		ccs_set_lf(head);
> -+	}
> -+	ccs_io_printf(head, "Total memory used:                    %10u\n",
> -+		      total);
> -+	head->r.eof = true;
> -+}
> -+
> -+/**
> -+ * ccs_write_stat - Set memory quota.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns 0.
> -+ */
> -+static int ccs_write_stat(struct ccs_io_buffer *head)
> -+{
> -+	char *data = head->write_buf;
> -+	u8 i;
> -+	if (ccs_str_starts(&data, "Memory used by "))
> -+		for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
> -+			if (ccs_str_starts(&data, ccs_memory_headers[i])) {
> -+				if (*data == ' ')
> -+					data++;
> -+				ccs_memory_quota[i] =
> -+					simple_strtoul(data, NULL, 10);
> -+			}
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_print_bprm - Print "struct linux_binprm" for auditing.
> -+ *
> -+ * @bprm: Pointer to "struct linux_binprm".
> -+ * @dump: Pointer to "struct ccs_page_dump".
> -+ *
> -+ * Returns the contents of @bprm on success, NULL otherwise.
> -+ *
> -+ * This function uses kzalloc(), so caller must kfree() if this function
> -+ * didn't return NULL.
> -+ */
> -+static char *ccs_print_bprm(struct linux_binprm *bprm,
> -+			    struct ccs_page_dump *dump)
> -+{
> -+	static const int ccs_buffer_len = 4096 * 2;
> -+	char *buffer = kzalloc(ccs_buffer_len, CCS_GFP_FLAGS);
> -+	char *cp;
> -+	char *last_start;
> -+	int len;
> -+	unsigned long pos = bprm->p;
> -+	int offset = pos % PAGE_SIZE;
> -+	int argv_count = bprm->argc;
> -+	int envp_count = bprm->envc;
> -+	bool truncated = false;
> -+	if (!buffer)
> -+		return NULL;
> -+	len = snprintf(buffer, ccs_buffer_len - 1, "argv[]={ ");
> -+	cp = buffer + len;
> -+	if (!argv_count) {
> -+		memmove(cp, "} envp[]={ ", 11);
> -+		cp += 11;
> -+	}
> -+	last_start = cp;
> -+	while (argv_count || envp_count) {
> -+		if (!ccs_dump_page(bprm, pos, dump))
> -+			goto out;
> -+		pos += PAGE_SIZE - offset;
> -+		/* Read. */
> -+		while (offset < PAGE_SIZE) {
> -+			const char *kaddr = dump->data;
> -+			const unsigned char c = kaddr[offset++];
> -+			if (cp == last_start)
> -+				*cp++ = '"';
> -+			if (cp >= buffer + ccs_buffer_len - 32) {
> -+				/* Reserve some room for "..." string. */
> -+				truncated = true;
> -+			} else if (c == '\\') {
> -+				*cp++ = '\\';
> -+				*cp++ = '\\';
> -+			} else if (c > ' ' && c < 127) {
> -+				*cp++ = c;
> -+			} else if (!c) {
> -+				*cp++ = '"';
> -+				*cp++ = ' ';
> -+				last_start = cp;
> -+			} else {
> -+				*cp++ = '\\';
> -+				*cp++ = (c >> 6) + '0';
> -+				*cp++ = ((c >> 3) & 7) + '0';
> -+				*cp++ = (c & 7) + '0';
> -+			}
> -+			if (c)
> -+				continue;
> -+			if (argv_count) {
> -+				if (--argv_count == 0) {
> -+					if (truncated) {
> -+						cp = last_start;
> -+						memmove(cp, "... ", 4);
> -+						cp += 4;
> -+					}
> -+					memmove(cp, "} envp[]={ ", 11);
> -+					cp += 11;
> -+					last_start = cp;
> -+					truncated = false;
> -+				}
> -+			} else if (envp_count) {
> -+				if (--envp_count == 0) {
> -+					if (truncated) {
> -+						cp = last_start;
> -+						memmove(cp, "... ", 4);
> -+						cp += 4;
> -+					}
> -+				}
> -+			}
> -+			if (!argv_count && !envp_count)
> -+				break;
> -+		}
> -+		offset = 0;
> -+	}
> -+	*cp++ = '}';
> -+	*cp = '\0';
> -+	return buffer;
> -+out:
> -+	snprintf(buffer, ccs_buffer_len - 1, "argv[]={ ... } envp[]= { ... }");
> -+	return buffer;
> -+}
> -+
> -+/**
> -+ * ccs_filetype - Get string representation of file type.
> -+ *
> -+ * @mode: Mode value for stat().
> -+ *
> -+ * Returns file type string.
> -+ */
> -+static inline const char *ccs_filetype(const umode_t mode)
> -+{
> -+	switch (mode & S_IFMT) {
> -+	case S_IFREG:
> -+	case 0:
> -+		return ccs_condition_keyword[CCS_TYPE_IS_FILE];
> -+	case S_IFDIR:
> -+		return ccs_condition_keyword[CCS_TYPE_IS_DIRECTORY];
> -+	case S_IFLNK:
> -+		return ccs_condition_keyword[CCS_TYPE_IS_SYMLINK];
> -+	case S_IFIFO:
> -+		return ccs_condition_keyword[CCS_TYPE_IS_FIFO];
> -+	case S_IFSOCK:
> -+		return ccs_condition_keyword[CCS_TYPE_IS_SOCKET];
> -+	case S_IFBLK:
> -+		return ccs_condition_keyword[CCS_TYPE_IS_BLOCK_DEV];
> -+	case S_IFCHR:
> -+		return ccs_condition_keyword[CCS_TYPE_IS_CHAR_DEV];
> -+	}
> -+	return "unknown"; /* This should not happen. */
> -+}
> -+
> -+/**
> -+ * ccs_print_header - Get header line of audit log.
> -+ *
> -+ * @r: Pointer to "struct ccs_request_info".
> -+ *
> -+ * Returns string representation.
> -+ *
> -+ * This function uses kmalloc(), so caller must kfree() if this function
> -+ * didn't return NULL.
> -+ */
> -+static char *ccs_print_header(struct ccs_request_info *r)
> -+{
> -+	struct ccs_time stamp;
> -+	struct ccs_obj_info *obj = r->obj;
> -+	const u32 ccs_flags = ccs_current_flags();
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
> -+	const pid_t gpid = ccs_sys_getpid();
> -+#else
> -+	const pid_t gpid = task_pid_nr(current);
> -+#endif
> -+	static const int ccs_buffer_len = 4096;
> -+	char *buffer = kmalloc(ccs_buffer_len, CCS_GFP_FLAGS);
> -+	int pos;
> -+	u8 i;
> -+	if (!buffer)
> -+		return NULL;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
> -+	{
> -+		struct timeval tv;
> -+		do_gettimeofday(&tv);
> -+		ccs_convert_time(tv.tv_sec, &stamp);
> -+	}
> -+#else
> -+	ccs_convert_time(get_seconds(), &stamp);
> -+#endif
> -+	pos = snprintf(buffer, ccs_buffer_len - 1,
> -+		       "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
> -+		       "granted=%s (global-pid=%u) task={ pid=%u ppid=%u "
> -+		       "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
> -+		       "fsuid=%u fsgid=%u type%s=execute_handler }",
> -+		       stamp.year, stamp.month, stamp.day, stamp.hour,
> -+		       stamp.min, stamp.sec, r->profile, ccs_mode[r->mode],
> -+		       ccs_yesno(r->granted), gpid, ccs_sys_getpid(),
> -+		       ccs_sys_getppid(),
> -+		       from_kuid(&init_user_ns, current_uid()),
> -+		       from_kgid(&init_user_ns, current_gid()),
> -+		       from_kuid(&init_user_ns, current_euid()),
> -+		       from_kgid(&init_user_ns, current_egid()),
> -+		       from_kuid(&init_user_ns, current_suid()),
> -+		       from_kgid(&init_user_ns, current_sgid()),
> -+		       from_kuid(&init_user_ns, current_fsuid()),
> -+		       from_kgid(&init_user_ns, current_fsgid()),
> -+		       ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER ? "" : "!");
> -+	if (!obj)
> -+		goto no_obj_info;
> -+	if (!obj->validate_done) {
> -+		ccs_get_attributes(obj);
> -+		obj->validate_done = true;
> -+	}
> -+	for (i = 0; i < CCS_MAX_PATH_STAT; i++) {
> -+		struct ccs_mini_stat *stat;
> -+		unsigned int dev;
> -+		umode_t mode;
> -+		if (!obj->stat_valid[i])
> -+			continue;
> -+		stat = &obj->stat[i];
> -+		dev = stat->dev;
> -+		mode = stat->mode;
> -+		if (i & 1) {
> -+			pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos,
> -+					" path%u.parent={ uid=%u gid=%u "
> -+					"ino=%lu perm=0%o }", (i >> 1) + 1,
> -+					from_kuid(&init_user_ns, stat->uid),
> -+					from_kgid(&init_user_ns, stat->gid),
> -+					(unsigned long) stat->ino,
> -+					stat->mode & S_IALLUGO);
> -+			continue;
> -+		}
> -+		pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos,
> -+				" path%u={ uid=%u gid=%u ino=%lu major=%u"
> -+				" minor=%u perm=0%o type=%s", (i >> 1) + 1,
> -+				from_kuid(&init_user_ns, stat->uid),
> -+				from_kgid(&init_user_ns, stat->gid),
> -+				(unsigned long) stat->ino, MAJOR(dev),
> -+				MINOR(dev), mode & S_IALLUGO,
> -+				ccs_filetype(mode));
> -+		if (S_ISCHR(mode) || S_ISBLK(mode)) {
> -+			dev = stat->rdev;
> -+			pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos,
> -+					" dev_major=%u dev_minor=%u",
> -+					MAJOR(dev), MINOR(dev));
> -+		}
> -+		pos += snprintf(buffer + pos, ccs_buffer_len - 1 - pos, " }");
> -+	}
> -+no_obj_info:
> -+	if (pos < ccs_buffer_len - 1)
> -+		return buffer;
> -+	kfree(buffer);
> -+	return NULL;
> -+}
> -+
> -+/**
> -+ * ccs_init_log - Allocate buffer for audit logs.
> -+ *
> -+ * @r:    Pointer to "struct ccs_request_info".
> -+ * @len:  Buffer size needed for @fmt and @args.
> -+ * @fmt:  The printf()'s format string.
> -+ * @args: va_list structure for @fmt.
> -+ *
> -+ * Returns pointer to allocated memory.
> -+ *
> -+ * This function uses kzalloc(), so caller must kfree() if this function
> -+ * didn't return NULL.
> -+ */
> -+static char *ccs_init_log(struct ccs_request_info *r, int len, const char *fmt,
> -+			  va_list args)
> -+{
> -+	char *buf = NULL;
> -+	char *bprm_info = NULL;
> -+	char *realpath = NULL;
> -+	const char *symlink = NULL;
> -+	const char *header = NULL;
> -+	int pos;
> -+	const char *domainname = ccs_current_domain()->domainname->name;
> -+	header = ccs_print_header(r);
> -+	if (!header)
> -+		return NULL;
> -+	/* +10 is for '\n' etc. and '\0'. */
> -+	len += strlen(domainname) + strlen(header) + 10;
> -+	if (r->ee) {
> -+		struct file *file = r->ee->bprm->file;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> -+		struct path path = { file->f_vfsmnt, file->f_dentry };
> -+		realpath = ccs_realpath(&path);
> -+#else
> -+		realpath = ccs_realpath(&file->f_path);
> -+#endif
> -+		bprm_info = ccs_print_bprm(r->ee->bprm, &r->ee->dump);
> -+		if (!realpath || !bprm_info)
> -+			goto out;
> -+		/* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */
> -+		len += strlen(realpath) + 80 + strlen(bprm_info);
> -+	} else if (r->obj && r->obj->symlink_target) {
> -+		symlink = r->obj->symlink_target->name;
> -+		/* +18 is for " symlink.target=\"%s\"" */
> -+		len += 18 + strlen(symlink);
> -+	}
> -+	len = ccs_round2(len);
> -+	buf = kzalloc(len, CCS_GFP_FLAGS);
> -+	if (!buf)
> -+		goto out;
> -+	len--;
> -+	pos = snprintf(buf, len, "%s", header);
> -+	if (realpath) {
> -+		struct linux_binprm *bprm = r->ee->bprm;
> -+		pos += snprintf(buf + pos, len - pos,
> -+				" exec={ realpath=\"%s\" argc=%d envc=%d %s }",
> -+				realpath, bprm->argc, bprm->envc, bprm_info);
> -+	} else if (symlink)
> -+		pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"",
> -+				symlink);
> -+	pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname);
> -+	vsnprintf(buf + pos, len - pos, fmt, args);
> -+out:
> -+	kfree(realpath);
> -+	kfree(bprm_info);
> -+	kfree(header);
> -+	return buf;
> -+}
> -+
> -+/**
> -+ * ccs_transition_failed - Print waning message and send signal when domain transition failed.
> -+ *
> -+ * @domainname: Name of domain to transit.
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Note that if current->pid == 1, sending SIGKILL won't work.
> -+ */
> -+void ccs_transition_failed(const char *domainname)
> -+{
> -+	printk(KERN_WARNING
> -+	       "ERROR: Unable to transit to '%s' domain.\n", domainname);
> -+	force_sig(SIGKILL, current);
> -+}
> -+
> -+/**
> -+ * ccs_update_task_domain - Update task's domain.
> -+ *
> -+ * @r: Pointer to "struct ccs_request_info".
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * The task will retry as hard as possible. But if domain transition failed,
> -+ * the task will be killed by SIGKILL.
> -+ */
> -+static void ccs_update_task_domain(struct ccs_request_info *r)
> -+{
> -+	char *buf;
> -+	const char *cp;
> -+	const struct ccs_acl_info *acl = r->matched_acl;
> -+	r->matched_acl = NULL;
> -+	if (!acl || !acl->cond || !acl->cond->transit ||
> -+	    acl->cond->exec_transit)
> -+		return;
> -+	while (1) {
> -+		buf = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
> -+		if (buf)
> -+			break;
> -+		ssleep(1);
> -+		if (fatal_signal_pending(current))
> -+			return;
> -+	}
> -+	cp = acl->cond->transit->name;
> -+	if (*cp == '/')
> -+		snprintf(buf, CCS_EXEC_TMPSIZE - 1, "%s %s",
> -+			 ccs_current_domain()->domainname->name, cp);
> -+	else
> -+		strncpy(buf, cp, CCS_EXEC_TMPSIZE - 1);
> -+	if (!ccs_assign_domain(buf, true))
> -+		ccs_transition_failed(buf);
> -+	kfree(buf);
> -+}
> -+
> -+/**
> -+ * ccs_get_audit - Get audit mode.
> -+ *
> -+ * @r: Pointer to "struct ccs_request_info".
> -+ *
> -+ * Returns true if this request should be audited, false otherwise.
> -+ */
> -+static bool ccs_get_audit(const struct ccs_request_info *r)
> -+{
> -+	const struct ccs_acl_info *matched_acl = r->matched_acl;
> -+	const u8 profile = r->profile;
> -+	const u8 index = r->type;
> -+	const bool is_granted = r->granted;
> -+	u8 mode;
> -+	struct ccs_profile *p;
> -+	if (!ccs_policy_loaded)
> -+		return false;
> -+	p = ccs_profile(profile);
> -+	if (ccs_log_count >= p->pref[CCS_PREF_MAX_AUDIT_LOG])
> -+		return false;
> -+	if (is_granted && matched_acl && matched_acl->cond &&
> -+	    matched_acl->cond->grant_log != CCS_GRANTLOG_AUTO)
> -+		return matched_acl->cond->grant_log == CCS_GRANTLOG_YES;
> -+	mode = p->config[index];
> -+	if (mode == CCS_CONFIG_USE_DEFAULT)
> -+		mode = p->config
> -+			[ccs_index2category[index] + CCS_MAX_MAC_INDEX];
> -+	if (mode == CCS_CONFIG_USE_DEFAULT)
> -+		mode = p->default_config;
> -+	if (is_granted)
> -+		return mode & CCS_CONFIG_WANT_GRANT_LOG;
> -+	return mode & CCS_CONFIG_WANT_REJECT_LOG;
> -+}
> -+
> -+/**
> -+ * ccs_write_log2 - Write an audit log.
> -+ *
> -+ * @r:    Pointer to "struct ccs_request_info".
> -+ * @len:  Buffer size needed for @fmt and @args.
> -+ * @fmt:  The printf()'s format string.
> -+ * @args: va_list structure for @fmt.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_write_log2(struct ccs_request_info *r, int len,
> -+			   const char *fmt, va_list args)
> -+{
> -+	char *buf;
> -+	struct ccs_log *entry;
> -+	bool quota_exceeded = false;
> -+	if (!ccs_get_audit(r))
> -+		goto out;
> -+	buf = ccs_init_log(r, len, fmt, args);
> -+	if (!buf)
> -+		goto out;
> -+	entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
> -+	if (!entry) {
> -+		kfree(buf);
> -+		goto out;
> -+	}
> -+	entry->log = buf;
> -+	len = ccs_round2(strlen(buf) + 1);
> -+	/*
> -+	 * The entry->size is used for memory quota checks.
> -+	 * Don't go beyond strlen(entry->log).
> -+	 */
> -+	entry->size = len + ccs_round2(sizeof(*entry));
> -+	spin_lock(&ccs_log_lock);
> -+	if (ccs_memory_quota[CCS_MEMORY_AUDIT] &&
> -+	    ccs_memory_used[CCS_MEMORY_AUDIT] + entry->size >=
> -+	    ccs_memory_quota[CCS_MEMORY_AUDIT]) {
> -+		quota_exceeded = true;
> -+	} else {
> -+		ccs_memory_used[CCS_MEMORY_AUDIT] += entry->size;
> -+		list_add_tail(&entry->list, &ccs_log);
> -+		ccs_log_count++;
> -+	}
> -+	spin_unlock(&ccs_log_lock);
> -+	if (quota_exceeded) {
> -+		kfree(buf);
> -+		kfree(entry);
> -+		goto out;
> -+	}
> -+	wake_up(&ccs_log_wait);
> -+out:
> -+	ccs_update_task_domain(r);
> -+}
> -+
> -+/**
> -+ * ccs_write_log - Write an audit log.
> -+ *
> -+ * @r:   Pointer to "struct ccs_request_info".
> -+ * @fmt: The printf()'s format string, followed by parameters.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+void ccs_write_log(struct ccs_request_info *r, const char *fmt, ...)
> -+{
> -+	va_list args;
> -+	int len;
> -+	va_start(args, fmt);
> -+	len = vsnprintf((char *) &len, 1, fmt, args) + 1;
> -+	va_end(args);
> -+	va_start(args, fmt);
> -+	ccs_write_log2(r, len, fmt, args);
> -+	va_end(args);
> -+}
> -+
> -+/**
> -+ * ccs_read_log - Read an audit log.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_read_log(struct ccs_io_buffer *head)
> -+{
> -+	struct ccs_log *ptr = NULL;
> -+	if (head->r.w_pos)
> -+		return;
> -+	kfree(head->read_buf);
> -+	head->read_buf = NULL;
> -+	spin_lock(&ccs_log_lock);
> -+	if (!list_empty(&ccs_log)) {
> -+		ptr = list_entry(ccs_log.next, typeof(*ptr), list);
> -+		list_del(&ptr->list);
> -+		ccs_log_count--;
> -+		ccs_memory_used[CCS_MEMORY_AUDIT] -= ptr->size;
> -+	}
> -+	spin_unlock(&ccs_log_lock);
> -+	if (ptr) {
> -+		head->read_buf = ptr->log;
> -+		head->r.w[head->r.w_pos++] = head->read_buf;
> -+		kfree(ptr);
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_set_namespace_cursor - Set namespace to read.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void ccs_set_namespace_cursor(struct ccs_io_buffer *head)
> -+{
> -+	struct list_head *ns;
> -+	if (head->type != CCS_EXCEPTION_POLICY && head->type != CCS_PROFILE)
> -+		return;
> -+	/*
> -+	 * If this is the first read, or reading previous namespace finished
> -+	 * and has more namespaces to read, update the namespace cursor.
> -+	 */
> -+	ns = head->r.ns;
> -+	if (!ns || (head->r.eof && ns->next != &ccs_namespace_list)) {
> -+		/* Clearing is OK because ccs_flush() returned true. */
> -+		memset(&head->r, 0, sizeof(head->r));
> -+		head->r.ns = ns ? ns->next : ccs_namespace_list.next;
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_has_more_namespace - Check for unread namespaces.
> -+ *
> -+ * @head: Pointer to "struct ccs_io_buffer".
> -+ *
> -+ * Returns true if we have more entries to print, false otherwise.
> -+ */
> -+static bool ccs_has_more_namespace(struct ccs_io_buffer *head)
> -+{
> -+	return (head->type == CCS_EXCEPTION_POLICY ||
> -+		head->type == CCS_PROFILE) && head->r.eof &&
> -+		head->r.ns->next != &ccs_namespace_list;
> -+}
> -+
> -+/**
> -+ * ccs_find_namespace - Find specified namespace.
> -+ *
> -+ * @name: Name of namespace to find.
> -+ * @len:  Length of @name.
> -+ *
> -+ * Returns pointer to "struct ccs_policy_namespace" if found, NULL otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static struct ccs_policy_namespace *ccs_find_namespace(const char *name,
> -+						       const unsigned int len)
> -+{
> -+	struct ccs_policy_namespace *ns;
> -+	list_for_each_entry_srcu(ns, &ccs_namespace_list, namespace_list,
> -+				 &ccs_ss) {
> -+		if (strncmp(name, ns->name, len) ||
> -+		    (name[len] && name[len] != ' '))
> -+			continue;
> -+		return ns;
> -+	}
> -+	return NULL;
> -+}
> -+
> -+/**
> -+ * ccs_assign_namespace - Create a new namespace.
> -+ *
> -+ * @domainname: Name of namespace to create.
> -+ *
> -+ * Returns pointer to "struct ccs_policy_namespace" on success, NULL otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static struct ccs_policy_namespace *ccs_assign_namespace
> -+(const char *domainname)
> -+{
> -+	struct ccs_policy_namespace *ptr;
> -+	struct ccs_policy_namespace *entry;
> -+	const char *cp = domainname;
> -+	unsigned int len = 0;
> -+	while (*cp && *cp++ != ' ')
> -+		len++;
> -+	ptr = ccs_find_namespace(domainname, len);
> -+	if (ptr)
> -+		return ptr;
> -+	if (len >= CCS_EXEC_TMPSIZE - 10 || !ccs_domain_def(domainname))
> -+		return NULL;
> -+	entry = kzalloc(sizeof(*entry) + len + 1, CCS_GFP_FLAGS);
> -+	if (!entry)
> -+		return NULL;
> -+	if (mutex_lock_interruptible(&ccs_policy_lock))
> -+		goto out;
> -+	ptr = ccs_find_namespace(domainname, len);
> -+	if (!ptr && ccs_memory_ok(entry, sizeof(*entry) + len + 1)) {
> -+		char *name = (char *) (entry + 1);
> -+		ptr = entry;
> -+		memmove(name, domainname, len);
> -+		name[len] = '\0';
> -+		entry->name = name;
> -+		ccs_init_policy_namespace(entry);
> -+		entry = NULL;
> -+	}
> -+	mutex_unlock(&ccs_policy_lock);
> -+out:
> -+	kfree(entry);
> -+	return ptr;
> -+}
> -+
> -+/**
> -+ * ccs_namespace_jump - Check for namespace jump.
> -+ *
> -+ * @domainname: Name of domain.
> -+ *
> -+ * Returns true if namespace differs, false otherwise.
> -+ */
> -+static bool ccs_namespace_jump(const char *domainname)
> -+{
> -+	const char *namespace = ccs_current_namespace()->name;
> -+	const int len = strlen(namespace);
> -+	return strncmp(domainname, namespace, len) ||
> -+		(domainname[len] && domainname[len] != ' ');
> -+}
> -+
> -+/**
> -+ * ccs_assign_domain - Create a domain or a namespace.
> -+ *
> -+ * @domainname: The name of domain.
> -+ * @transit:    True if transit to domain found or created.
> -+ *
> -+ * Returns pointer to "struct ccs_domain_info" on success, NULL otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+struct ccs_domain_info *ccs_assign_domain(const char *domainname,
> -+					  const bool transit)
> -+{
> -+	struct ccs_security *security = ccs_current_security();
> -+	struct ccs_domain_info e = { };
> -+	struct ccs_domain_info *entry = ccs_find_domain(domainname);
> -+	bool created = false;
> -+	if (entry) {
> -+		if (transit) {
> -+			/*
> -+			 * Since namespace is created at runtime, profiles may
> -+			 * not be created by the moment the process transits to
> -+			 * that domain. Do not perform domain transition if
> -+			 * profile for that domain is not yet created.
> -+			 */
> -+			if (ccs_policy_loaded &&
> -+			    !entry->ns->profile_ptr[entry->profile])
> -+				return NULL;
> -+			security->ccs_domain_info = entry;
> -+		}
> -+		return entry;
> -+	}
> -+	/* Requested domain does not exist. */
> -+	/* Don't create requested domain if domainname is invalid. */
> -+	if (strlen(domainname) >= CCS_EXEC_TMPSIZE - 10 ||
> -+	    !ccs_correct_domain(domainname))
> -+		return NULL;
> -+	/*
> -+	 * Since definition of profiles and acl_groups may differ across
> -+	 * namespaces, do not inherit "use_profile" and "use_group" settings
> -+	 * by automatically creating requested domain upon domain transition.
> -+	 */
> -+	if (transit && ccs_namespace_jump(domainname))
> -+		return NULL;
> -+	e.ns = ccs_assign_namespace(domainname);
> -+	if (!e.ns)
> -+		return NULL;
> -+	/*
> -+	 * "use_profile" and "use_group" settings for automatically created
> -+	 * domains are inherited from current domain. These are 0 for manually
> -+	 * created domains.
> -+	 */
> -+	if (transit) {
> -+		const struct ccs_domain_info *domain =
> -+			security->ccs_domain_info;
> -+		e.profile = domain->profile;
> -+		memcpy(e.group, domain->group, sizeof(e.group));
> -+	}
> -+	e.domainname = ccs_get_name(domainname);
> -+	if (!e.domainname)
> -+		return NULL;
> -+	if (mutex_lock_interruptible(&ccs_policy_lock))
> -+		goto out;
> -+	entry = ccs_find_domain(domainname);
> -+	if (!entry) {
> -+		entry = ccs_commit_ok(&e, sizeof(e));
> -+		if (entry) {
> -+			INIT_LIST_HEAD(&entry->acl_info_list);
> -+			list_add_tail_rcu(&entry->list, &ccs_domain_list);
> -+			created = true;
> -+		}
> -+	}
> -+	mutex_unlock(&ccs_policy_lock);
> -+out:
> -+	ccs_put_name(e.domainname);
> -+	if (entry && transit) {
> -+		security->ccs_domain_info = entry;
> -+		if (created) {
> -+			struct ccs_request_info r;
> -+			int i;
> -+			ccs_init_request_info(&r, CCS_MAC_FILE_EXECUTE);
> -+			r.granted = false;
> -+			ccs_write_log(&r, "use_profile %u\n", entry->profile);
> -+			for (i = 0; i < CCS_MAX_ACL_GROUPS; i++)
> -+				if (test_bit(i, entry->group))
> -+					ccs_write_log(&r, "use_group %u\n", i);
> -+			ccs_update_stat(CCS_STAT_POLICY_UPDATES);
> -+		}
> -+	}
> -+	return entry;
> -+}
> -+
> -+/**
> -+ * ccs_parse_policy - Parse a policy line.
> -+ *
> -+ * @head: Poiter to "struct ccs_io_buffer".
> -+ * @line: Line to parse.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ *
> -+ * Caller holds ccs_read_lock().
> -+ */
> -+static int ccs_parse_policy(struct ccs_io_buffer *head, char *line)
> -+{
> -+	/* Delete request? */
> -+	head->w.is_delete = !strncmp(line, "delete ", 7);
> -+	if (head->w.is_delete)
> -+		memmove(line, line + 7, strlen(line + 7) + 1);
> -+	/* Selecting namespace to update. */
> -+	if (head->type == CCS_EXCEPTION_POLICY || head->type == CCS_PROFILE) {
> -+		if (*line == '<') {
> -+			char *cp = strchr(line, ' ');
> -+			if (cp) {
> -+				*cp++ = '\0';
> -+				head->w.ns = ccs_assign_namespace(line);
> -+				memmove(line, cp, strlen(cp) + 1);
> -+			} else
> -+				head->w.ns = NULL;
> -+		} else
> -+			head->w.ns = &ccs_kernel_namespace;
> -+		/* Don't allow updating if namespace is invalid. */
> -+		if (!head->w.ns)
> -+			return -ENOENT;
> -+	}
> -+	/* Do the update. */
> -+	switch (head->type) {
> -+	case CCS_DOMAIN_POLICY:
> -+		return ccs_write_domain(head);
> -+	case CCS_EXCEPTION_POLICY:
> -+		return ccs_write_exception(head);
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	case CCS_EXECUTE_HANDLER:
> -+#endif
> -+	case CCS_PROCESS_STATUS:
> -+		return ccs_write_pid(head);
> -+	case CCS_STAT:
> -+		return ccs_write_stat(head);
> -+	case CCS_PROFILE:
> -+		return ccs_write_profile(head);
> -+	case CCS_QUERY:
> -+		return ccs_write_answer(head);
> -+	case CCS_MANAGER:
> -+		return ccs_write_manager(head);
> -+	default:
> -+		return -ENOSYS;
> -+	}
> -+}
> -+
> -+/**
> -+ * ccs_policy_io_init - Register hooks for policy I/O.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void __init ccs_policy_io_init(void)
> -+{
> -+	ccsecurity_ops.check_profile = ccs_check_profile;
> -+}
> -+
> -+/**
> -+ * ccs_load_builtin_policy - Load built-in policy.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void __init ccs_load_builtin_policy(void)
> -+{
> -+	/*
> -+	 * This include file is manually created and contains built-in policy
> -+	 * named "ccs_builtin_profile", "ccs_builtin_exception_policy",
> -+	 * "ccs_builtin_domain_policy", "ccs_builtin_manager",
> -+	 * "ccs_builtin_stat" in the form of "static char [] __initdata".
> -+	 */
> -+#include "builtin-policy.h"
> -+	u8 i;
> -+	const int idx = ccs_read_lock();
> -+	for (i = 0; i < 5; i++) {
> -+		struct ccs_io_buffer head = { };
> -+		char *start = "";
> -+		switch (i) {
> -+		case 0:
> -+			start = ccs_builtin_profile;
> -+			head.type = CCS_PROFILE;
> -+			break;
> -+		case 1:
> -+			start = ccs_builtin_exception_policy;
> -+			head.type = CCS_EXCEPTION_POLICY;
> -+			break;
> -+		case 2:
> -+			start = ccs_builtin_domain_policy;
> -+			head.type = CCS_DOMAIN_POLICY;
> -+			break;
> -+		case 3:
> -+			start = ccs_builtin_manager;
> -+			head.type = CCS_MANAGER;
> -+			break;
> -+		case 4:
> -+			start = ccs_builtin_stat;
> -+			head.type = CCS_STAT;
> -+			break;
> -+		}
> -+		while (1) {
> -+			char *end = strchr(start, '\n');
> -+			if (!end)
> -+				break;
> -+			*end = '\0';
> -+			ccs_normalize_line(start);
> -+			head.write_buf = start;
> -+			ccs_parse_policy(&head, start);
> -+			start = end + 1;
> -+		}
> -+	}
> -+	ccs_read_unlock(idx);
> -+#ifdef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
> -+	ccs_check_profile();
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_read_self - read() for /proc/ccs/self_domain interface.
> -+ *
> -+ * @file:  Pointer to "struct file".
> -+ * @buf:   Domainname which current thread belongs to.
> -+ * @count: Size of @buf.
> -+ * @ppos:  Bytes read by now.
> -+ *
> -+ * Returns read size on success, negative value otherwise.
> -+ */
> -+static ssize_t ccs_read_self(struct file *file, char __user *buf, size_t count,
> -+			     loff_t *ppos)
> -+{
> -+	const char *domain = ccs_current_domain()->domainname->name;
> -+	loff_t len = strlen(domain);
> -+	loff_t pos = *ppos;
> -+	if (pos >= len || !count)
> -+		return 0;
> -+	len -= pos;
> -+	if (count < len)
> -+		len = count;
> -+	if (copy_to_user(buf, domain + pos, len))
> -+		return -EFAULT;
> -+	*ppos += len;
> -+	return len;
> -+}
> -+
> -+/**
> -+ * ccs_open - open() for /proc/ccs/ interface.
> -+ *
> -+ * @inode: Pointer to "struct inode".
> -+ * @file:  Pointer to "struct file".
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int ccs_open(struct inode *inode, struct file *file)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
> -+	const u8 type = (unsigned long) PDE_DATA(inode);
> -+#else
> -+	const u8 type = (unsigned long) PDE(inode)->data;
> -+#endif
> -+	struct ccs_io_buffer *head = kzalloc(sizeof(*head), CCS_GFP_FLAGS);
> -+	if (!head)
> -+		return -ENOMEM;
> -+	mutex_init(&head->io_sem);
> -+	head->type = type;
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	if (type == CCS_EXECUTE_HANDLER) {
> -+		/* Allow execute_handler to read process's status. */
> -+		if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {
> -+			kfree(head);
> -+			return -EPERM;
> -+		}
> -+	}
> -+#endif
> -+	if ((file->f_mode & FMODE_READ) && type != CCS_AUDIT &&
> -+	    type != CCS_QUERY) {
> -+		/* Don't allocate read_buf for poll() access. */
> -+		head->readbuf_size = 4096;
> -+		head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);
> -+		if (!head->read_buf) {
> -+			kfree(head);
> -+			return -ENOMEM;
> -+		}
> -+	}
> -+	if (file->f_mode & FMODE_WRITE) {
> -+		head->writebuf_size = 4096;
> -+		head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);
> -+		if (!head->write_buf) {
> -+			kfree(head->read_buf);
> -+			kfree(head);
> -+			return -ENOMEM;
> -+		}
> -+	}
> -+	/*
> -+	 * If the file is /proc/ccs/query, increment the observer counter.
> -+	 * The obserber counter is used by ccs_supervisor() to see if
> -+	 * there is some process monitoring /proc/ccs/query.
> -+	 */
> -+	if (type == CCS_QUERY)
> -+		atomic_inc(&ccs_query_observers);
> -+	file->private_data = head;
> -+	ccs_notify_gc(head, true);
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_release - close() for /proc/ccs/ interface.
> -+ *
> -+ * @inode: Pointer to "struct inode".
> -+ * @file:  Pointer to "struct file".
> -+ *
> -+ * Returns 0.
> -+ */
> -+static int ccs_release(struct inode *inode, struct file *file)
> -+{
> -+	struct ccs_io_buffer *head = file->private_data;
> -+	/*
> -+	 * If the file is /proc/ccs/query, decrement the observer counter.
> -+	 */
> -+	if (head->type == CCS_QUERY &&
> -+	    atomic_dec_and_test(&ccs_query_observers))
> -+		wake_up_all(&ccs_answer_wait);
> -+	ccs_notify_gc(head, false);
> -+	return 0;
> -+}
> -+
> -+/**
> -+ * ccs_poll - poll() for /proc/ccs/ interface.
> -+ *
> -+ * @file: Pointer to "struct file".
> -+ * @wait: Pointer to "poll_table". Maybe NULL.
> -+ *
> -+ * Returns POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM if ready to read/write,
> -+ * POLLOUT | POLLWRNORM otherwise.
> -+ */
> -+static unsigned int ccs_poll(struct file *file, poll_table *wait)
> -+{
> -+	struct ccs_io_buffer *head = file->private_data;
> -+	if (head->type == CCS_AUDIT) {
> -+		if (!ccs_memory_used[CCS_MEMORY_AUDIT]) {
> -+			poll_wait(file, &ccs_log_wait, wait);
> -+			if (!ccs_memory_used[CCS_MEMORY_AUDIT])
> -+				return POLLOUT | POLLWRNORM;
> -+		}
> -+	} else if (head->type == CCS_QUERY) {
> -+		if (list_empty(&ccs_query_list)) {
> -+			poll_wait(file, &ccs_query_wait, wait);
> -+			if (list_empty(&ccs_query_list))
> -+				return POLLOUT | POLLWRNORM;
> -+		}
> -+	}
> -+	return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
> -+}
> -+
> -+/**
> -+ * ccs_read - read() for /proc/ccs/ interface.
> -+ *
> -+ * @file:  Pointer to "struct file".
> -+ * @buf:   Pointer to buffer.
> -+ * @count: Size of @buf.
> -+ * @ppos:  Unused.
> -+ *
> -+ * Returns bytes read on success, negative value otherwise.
> -+ */
> -+static ssize_t ccs_read(struct file *file, char __user *buf, size_t count,
> -+			loff_t *ppos)
> -+{
> -+	struct ccs_io_buffer *head = file->private_data;
> -+	int len;
> -+	int idx;
> -+	if (mutex_lock_interruptible(&head->io_sem))
> -+		return -EINTR;
> -+	head->read_user_buf = buf;
> -+	head->read_user_buf_avail = count;
> -+	idx = ccs_read_lock();
> -+	if (ccs_flush(head))
> -+		/* Call the policy handler. */
> -+		do {
> -+			ccs_set_namespace_cursor(head);
> -+			switch (head->type) {
> -+			case CCS_DOMAIN_POLICY:
> -+				ccs_read_domain(head);
> -+				break;
> -+			case CCS_EXCEPTION_POLICY:
> -+				ccs_read_exception(head);
> -+				break;
> -+			case CCS_AUDIT:
> -+				ccs_read_log(head);
> -+				break;
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+			case CCS_EXECUTE_HANDLER:
> -+#endif
> -+			case CCS_PROCESS_STATUS:
> -+				ccs_read_pid(head);
> -+				break;
> -+			case CCS_VERSION:
> -+				ccs_read_version(head);
> -+				break;
> -+			case CCS_STAT:
> -+				ccs_read_stat(head);
> -+				break;
> -+			case CCS_PROFILE:
> -+				ccs_read_profile(head);
> -+				break;
> -+			case CCS_QUERY:
> -+				ccs_read_query(head);
> -+				break;
> -+			case CCS_MANAGER:
> -+				ccs_read_manager(head);
> -+				break;
> -+			}
> -+		} while (ccs_flush(head) && ccs_has_more_namespace(head));
> -+	ccs_read_unlock(idx);
> -+	len = head->read_user_buf - buf;
> -+	mutex_unlock(&head->io_sem);
> -+	return len;
> -+}
> -+
> -+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
> -+
> -+/**
> -+ * ccs_write_self - write() for /proc/ccs/self_domain interface.
> -+ *
> -+ * @file:  Pointer to "struct file".
> -+ * @buf:   Domainname to transit to.
> -+ * @count: Size of @buf.
> -+ * @ppos:  Unused.
> -+ *
> -+ * Returns @count on success, negative value otherwise.
> -+ *
> -+ * If domain transition was permitted but the domain transition failed, this
> -+ * function returns error rather than terminating current thread with SIGKILL.
> -+ */
> -+static ssize_t ccs_write_self(struct file *file, const char __user *buf,
> -+			      size_t count, loff_t *ppos)
> -+{
> -+	char *data;
> -+	int error;
> -+	if (!count || count >= CCS_EXEC_TMPSIZE - 10)
> -+		return -ENOMEM;
> -+	data = kzalloc(count + 1, CCS_GFP_FLAGS);
> -+	if (!data)
> -+		return -ENOMEM;
> -+	if (copy_from_user(data, buf, count)) {
> -+		error = -EFAULT;
> -+		goto out;
> -+	}
> -+	ccs_normalize_line(data);
> -+	if (ccs_correct_domain(data)) {
> -+		const int idx = ccs_read_lock();
> -+		struct ccs_path_info name;
> -+		struct ccs_request_info r;
> -+		name.name = data;
> -+		ccs_fill_path_info(&name);
> -+		/* Check "task manual_domain_transition" permission. */
> -+		ccs_init_request_info(&r, CCS_MAC_FILE_EXECUTE);
> -+		r.param_type = CCS_TYPE_MANUAL_TASK_ACL;
> -+		r.param.task.domainname = &name;
> -+		ccs_check_acl(&r);
> -+		if (!r.granted)
> -+			error = -EPERM;
> -+		else
> -+			error = ccs_assign_domain(data, true) ? 0 : -ENOENT;
> -+		ccs_read_unlock(idx);
> -+	} else
> -+		error = -EINVAL;
> -+out:
> -+	kfree(data);
> -+	return error ? error : count;
> -+}
> -+
> -+#endif
> -+
> -+/**
> -+ * ccs_write - write() for /proc/ccs/ interface.
> -+ *
> -+ * @file:  Pointer to "struct file".
> -+ * @buf:   Pointer to buffer.
> -+ * @count: Size of @buf.
> -+ * @ppos:  Unused.
> -+ *
> -+ * Returns @count on success, negative value otherwise.
> -+ */
> -+static ssize_t ccs_write(struct file *file, const char __user *buf,
> -+			 size_t count, loff_t *ppos)
> -+{
> -+	struct ccs_io_buffer *head = file->private_data;
> -+	int error = count;
> -+	char *cp0 = head->write_buf;
> -+	int idx;
> -+	if (mutex_lock_interruptible(&head->io_sem))
> -+		return -EINTR;
> -+	head->read_user_buf_avail = 0;
> -+	idx = ccs_read_lock();
> -+	/* Read a line and dispatch it to the policy handler. */
> -+	while (count) {
> -+		char c;
> -+		if (head->w.avail >= head->writebuf_size - 1) {
> -+			const int len = head->writebuf_size * 2;
> -+			char *cp = kzalloc(len, CCS_GFP_FLAGS);
> -+			if (!cp) {
> -+				error = -ENOMEM;
> -+				break;
> -+			}
> -+			memmove(cp, cp0, head->w.avail);
> -+			kfree(cp0);
> -+			head->write_buf = cp;
> -+			cp0 = cp;
> -+			head->writebuf_size = len;
> -+		}
> -+		if (get_user(c, buf)) {
> -+			error = -EFAULT;
> -+			break;
> -+		}
> -+		buf++;
> -+		count--;
> -+		cp0[head->w.avail++] = c;
> -+		if (c != '\n')
> -+			continue;
> -+		cp0[head->w.avail - 1] = '\0';
> -+		head->w.avail = 0;
> -+		ccs_normalize_line(cp0);
> -+		if (!strcmp(cp0, "reset")) {
> -+			head->w.ns = &ccs_kernel_namespace;
> -+			head->w.domain = NULL;
> -+			memset(&head->r, 0, sizeof(head->r));
> -+			continue;
> -+		}
> -+		/* Don't allow updating policies by non manager programs. */
> -+		switch (head->type) {
> -+		case CCS_PROCESS_STATUS:
> -+			/* This does not write anything. */
> -+			break;
> -+		case CCS_DOMAIN_POLICY:
> -+			if (ccs_select_domain(head, cp0))
> -+				continue;
> -+			/* fall through */
> -+		case CCS_EXCEPTION_POLICY:
> -+			if (!strcmp(cp0, "select transition_only")) {
> -+				head->r.print_transition_related_only = true;
> -+				continue;
> -+			}
> -+			/* fall through */
> -+		default:
> -+			if (!ccs_manager()) {
> -+				error = -EPERM;
> -+				goto out;
> -+			}
> -+		}
> -+		switch (ccs_parse_policy(head, cp0)) {
> -+		case -EPERM:
> -+			error = -EPERM;
> -+			goto out;
> -+		case 0:
> -+			/* Update statistics. */
> -+			switch (head->type) {
> -+			case CCS_DOMAIN_POLICY:
> -+			case CCS_EXCEPTION_POLICY:
> -+			case CCS_STAT:
> -+			case CCS_PROFILE:
> -+			case CCS_MANAGER:
> -+				ccs_update_stat(CCS_STAT_POLICY_UPDATES);
> -+				break;
> -+			default:
> -+				break;
> -+			}
> -+			break;
> -+		}
> -+	}
> -+out:
> -+	ccs_read_unlock(idx);
> -+	mutex_unlock(&head->io_sem);
> -+	return error;
> -+}
> -+
> -+/**
> -+ * ccs_create_entry - Create interface files under /proc/ccs/ directory.
> -+ *
> -+ * @name:   The name of the interface file.
> -+ * @mode:   The permission of the interface file.
> -+ * @parent: The parent directory.
> -+ * @key:    Type of interface.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void __init ccs_create_entry(const char *name, const umode_t mode,
> -+				    struct proc_dir_entry *parent,
> -+				    const u8 key)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
> -+	proc_create_data(name, mode, parent, &ccs_operations,
> -+			 ((u8 *) NULL) + key);
> -+#else
> -+	struct proc_dir_entry *entry = create_proc_entry(name, mode, parent);
> -+	if (entry) {
> -+		entry->proc_fops = &ccs_operations;
> -+		entry->data = ((u8 *) NULL) + key;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+		if (entry->proc_iops)
> -+			ccs_file_inode_operations = *entry->proc_iops;
> -+		if (!ccs_file_inode_operations.setattr)
> -+			ccs_file_inode_operations.setattr = proc_notify_change;
> -+		entry->proc_iops = &ccs_file_inode_operations;
> -+#endif
> -+	}
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_proc_init - Initialize /proc/ccs/ interface.
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static void __init ccs_proc_init(void)
> -+{
> -+	struct proc_dir_entry *ccs_dir = proc_mkdir("ccs", NULL);
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+	if (ccs_dir->proc_iops)
> -+		ccs_dir_inode_operations = *ccs_dir->proc_iops;
> -+	if (!ccs_dir_inode_operations.setattr)
> -+		ccs_dir_inode_operations.setattr = proc_notify_change;
> -+	ccs_dir->proc_iops = &ccs_dir_inode_operations;
> -+#endif
> -+	ccs_create_entry("query",            0600, ccs_dir, CCS_QUERY);
> -+	ccs_create_entry("domain_policy",    0600, ccs_dir, CCS_DOMAIN_POLICY);
> -+	ccs_create_entry("exception_policy", 0600, ccs_dir,
> -+			 CCS_EXCEPTION_POLICY);
> -+	ccs_create_entry("audit",            0400, ccs_dir, CCS_AUDIT);
> -+	ccs_create_entry(".process_status",  0600, ccs_dir,
> -+			 CCS_PROCESS_STATUS);
> -+	ccs_create_entry("stat",             0644, ccs_dir, CCS_STAT);
> -+	ccs_create_entry("profile",          0600, ccs_dir, CCS_PROFILE);
> -+	ccs_create_entry("manager",          0600, ccs_dir, CCS_MANAGER);
> -+	ccs_create_entry("version",          0400, ccs_dir, CCS_VERSION);
> -+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
> -+	ccs_create_entry(".execute_handler", 0666, ccs_dir,
> -+			 CCS_EXECUTE_HANDLER);
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
> -+	proc_create("self_domain", 0666, ccs_dir, &ccs_self_operations);
> -+#else
> -+	{
> -+		struct proc_dir_entry *e = create_proc_entry("self_domain",
> -+							     0666, ccs_dir);
> -+		if (e)
> -+			e->proc_fops = &ccs_self_operations;
> -+	}
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_init_module - Initialize this module.
> -+ *
> -+ * Returns 0 on success, negative value otherwise.
> -+ */
> -+static int __init ccs_init_module(void)
> -+{
> -+	if (ccsecurity_ops.disabled)
> -+		return -EINVAL;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
> -+	MOD_INC_USE_COUNT;
> -+#endif
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
> -+	if (init_srcu_struct(&ccs_ss))
> -+		panic("Out of memory.");
> -+#endif
> -+	ccs_kernel_namespace.name = "<kernel>";
> -+	ccs_init_policy_namespace(&ccs_kernel_namespace);
> -+	ccs_kernel_domain.ns = &ccs_kernel_namespace;
> -+	INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
> -+	ccs_mm_init();
> -+	ccs_policy_io_init();
> -+	ccs_permission_init();
> -+	ccs_proc_init();
> -+	ccs_load_builtin_policy();
> -+	return 0;
> -+}
> -+
> -+MODULE_LICENSE("GPL");
> -+module_init(ccs_init_module);
> -diff --git a/security/ccsecurity/realpath.c b/security/ccsecurity/realpath.c
> -new file mode 100644
> -index 0000000..df821ed
> ---- /dev/null
> -+++ b/security/ccsecurity/realpath.c
> -@@ -0,0 +1,767 @@
> -+/*
> -+ * security/ccsecurity/realpath.c
> -+ *
> -+ * Copyright (C) 2005-2012  NTT DATA CORPORATION
> -+ *
> -+ * Version: 1.8.4   2015/05/05
> -+ */
> -+
> -+#include "internal.h"
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
> -+#include <linux/nsproxy.h>
> -+#include <linux/mnt_namespace.h>
> -+#endif
> -+
> -+/***** SECTION1: Constants definition *****/
> -+
> -+#define SOCKFS_MAGIC 0x534F434B
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+#define s_fs_info u.generic_sbp
> -+#endif
> -+
> -+/***** SECTION2: Structure definition *****/
> -+
> -+/***** SECTION3: Prototype definition section *****/
> -+
> -+char *ccs_encode(const char *str);
> -+char *ccs_encode2(const char *str, int str_len);
> -+char *ccs_realpath(const struct path *path);
> -+const char *ccs_get_exe(void);
> -+void ccs_fill_path_info(struct ccs_path_info *ptr);
> -+
> -+static char *ccs_get_absolute_path(const struct path *path,
> -+				   char * const buffer, const int buflen);
> -+static char *ccs_get_dentry_path(struct dentry *dentry, char * const buffer,
> -+				 const int buflen);
> -+static char *ccs_get_local_path(struct dentry *dentry, char * const buffer,
> -+				const int buflen);
> -+static char *ccs_get_socket_name(const struct path *path, char * const buffer,
> -+				 const int buflen);
> -+static int ccs_const_part_length(const char *filename);
> -+
> -+/***** SECTION4: Standalone functions section *****/
> -+
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
> -+
> -+/**
> -+ * SOCKET_I - Get "struct socket".
> -+ *
> -+ * @inode: Pointer to "struct inode".
> -+ *
> -+ * Returns pointer to "struct socket".
> -+ *
> -+ * This is for compatibility with older kernels.
> -+ */
> -+static inline struct socket *SOCKET_I(struct inode *inode)
> -+{
> -+	return inode->i_sock ? &inode->u.socket_i : NULL;
> -+}
> -+
> -+#endif
> -+
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
> -+
> -+/**
> -+ * ccs_realpath_lock - Take locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_realpath_lock(void)
> -+{
> -+	/* dcache_lock is locked by __d_path(). */
> -+	/* vfsmount_lock is locked by __d_path(). */
> -+}
> -+
> -+/**
> -+ * ccs_realpath_unlock - Release locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_realpath_unlock(void)
> -+{
> -+	/* vfsmount_lock is unlocked by __d_path(). */
> -+	/* dcache_lock is unlocked by __d_path(). */
> -+}
> -+
> -+#elif LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 36)
> -+
> -+/**
> -+ * ccs_realpath_lock - Take locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_realpath_lock(void)
> -+{
> -+	spin_lock(&dcache_lock);
> -+	/* vfsmount_lock is locked by __d_path(). */
> -+}
> -+
> -+/**
> -+ * ccs_realpath_unlock - Release locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_realpath_unlock(void)
> -+{
> -+	/* vfsmount_lock is unlocked by __d_path(). */
> -+	spin_unlock(&dcache_lock);
> -+}
> -+
> -+#elif defined(D_PATH_DISCONNECT) && !defined(CONFIG_SUSE_KERNEL)
> -+
> -+/**
> -+ * ccs_realpath_lock - Take locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ *
> -+ * Original unambiguous-__d_path.diff in patches.apparmor.tar.bz2 inversed the
> -+ * order of holding dcache_lock and vfsmount_lock. That patch was applied on
> -+ * (at least) SUSE 11.1 and Ubuntu 8.10 and Ubuntu 9.04 kernels.
> -+ *
> -+ * However, that patch was updated to use original order and the updated patch
> -+ * is applied to (as far as I know) only SUSE kernels.
> -+ *
> -+ * Therefore, I need to use original order for SUSE 11.1 kernels and inversed
> -+ * order for other kernels. I detect it by checking D_PATH_DISCONNECT and
> -+ * CONFIG_SUSE_KERNEL. I don't know whether other distributions are using the
> -+ * updated patch or not. If you got deadlock, check fs/dcache.c for locking
> -+ * order, and add " && 0" to this "#elif " block if fs/dcache.c uses original
> -+ * order.
> -+ */
> -+static inline void ccs_realpath_lock(void)
> -+{
> -+	spin_lock(ccsecurity_exports.vfsmount_lock);
> -+	spin_lock(&dcache_lock);
> -+}
> -+
> -+/**
> -+ * ccs_realpath_unlock - Release locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_realpath_unlock(void)
> -+{
> -+	spin_unlock(&dcache_lock);
> -+	spin_unlock(ccsecurity_exports.vfsmount_lock);
> -+}
> -+
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
> -+
> -+/**
> -+ * ccs_realpath_lock - Take locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_realpath_lock(void)
> -+{
> -+	spin_lock(&dcache_lock);
> -+	spin_lock(ccsecurity_exports.vfsmount_lock);
> -+}
> -+
> -+/**
> -+ * ccs_realpath_unlock - Release locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_realpath_unlock(void)
> -+{
> -+	spin_unlock(ccsecurity_exports.vfsmount_lock);
> -+	spin_unlock(&dcache_lock);
> -+}
> -+
> -+#else
> -+
> -+/**
> -+ * ccs_realpath_lock - Take locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_realpath_lock(void)
> -+{
> -+	spin_lock(&dcache_lock);
> -+}
> -+
> -+/**
> -+ * ccs_realpath_unlock - Release locks for __d_path().
> -+ *
> -+ * Returns nothing.
> -+ */
> -+static inline void ccs_realpath_unlock(void)
> -+{
> -+	spin_unlock(&dcache_lock);
> -+}
> -+
> -+#endif
> -+
> -+/***** SECTION5: Variables definition section *****/
> -+
> -+/***** SECTION6: Dependent functions section *****/
> -+
> -+/**
> -+ * ccs_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
> -+ *
> -+ * @path:   Pointer to "struct path".
> -+ * @buffer: Pointer to buffer to return value in.
> -+ * @buflen: Sizeof @buffer.
> -+ *
> -+ * Returns the buffer on success, an error code otherwise.
> -+ *
> -+ * Caller holds the dcache_lock and vfsmount_lock.
> -+ * Based on __d_path() in fs/dcache.c
> -+ *
> -+ * If dentry is a directory, trailing '/' is appended.
> -+ */
> -+static char *ccs_get_absolute_path(const struct path *path,
> -+				   char * const buffer, const int buflen)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
> -+	char *pos = ERR_PTR(-ENOMEM);
> -+	if (buflen >= 256) {
> -+		pos = ccsecurity_exports.d_absolute_path(path, buffer,
> -+							 buflen - 1);
> -+		if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
> -+			struct inode *inode = path->dentry->d_inode;
> -+			if (inode && S_ISDIR(inode->i_mode)) {
> -+				buffer[buflen - 2] = '/';
> -+				buffer[buflen - 1] = '\0';
> -+			}
> -+		}
> -+	}
> -+	return pos;
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
> -+	/*
> -+	 * __d_path() will start returning NULL by backporting commit 02125a82
> -+	 * "fix apparmor dereferencing potentially freed dentry, sanitize
> -+	 * __d_path() API".
> -+	 *
> -+	 * Unfortunately, __d_path() after applying that commit always returns
> -+	 * NULL when root is empty. d_absolute_path() is provided for TOMOYO
> -+	 * 2.x and AppArmor but TOMOYO 1.x does not use it, for TOMOYO 1.x
> -+	 * might be built as a loadable kernel module and there is no warrantee
> -+	 * that TOMOYO 1.x is recompiled after applying that commit. Also,
> -+	 * I don't want to search /proc/kallsyms for d_absolute_path() because
> -+	 * I want to keep TOMOYO 1.x architecture independent. Thus, supply
> -+	 * non empty root like AppArmor's d_namespace_path() did.
> -+	 */
> -+	char *pos = ERR_PTR(-ENOMEM);
> -+	if (buflen >= 256) {
> -+		static bool ccs_no_empty;
> -+		if (!ccs_no_empty) {
> -+			struct path root = { };
> -+			pos = ccsecurity_exports.__d_path(path, &root, buffer,
> -+							  buflen - 1);
> -+		} else {
> -+			pos = NULL;
> -+		}
> -+		if (!pos) {
> -+			struct task_struct *task = current;
> -+			struct path root;
> -+			struct path tmp;
> -+			spin_lock(&task->fs->lock);
> -+			root.mnt = task->nsproxy->mnt_ns->root;
> -+			root.dentry = root.mnt->mnt_root;
> -+			path_get(&root);
> -+			spin_unlock(&task->fs->lock);
> -+			tmp = root;
> -+			pos = ccsecurity_exports.__d_path(path, &tmp, buffer,
> -+							  buflen - 1);
> -+			path_put(&root);
> -+			if (!pos)
> -+				return ERR_PTR(-EINVAL);
> -+			/* Remember if __d_path() needs non empty root. */
> -+			ccs_no_empty = true;
> -+		}
> -+		if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
> -+			struct inode *inode = path->dentry->d_inode;
> -+			if (inode && S_ISDIR(inode->i_mode)) {
> -+				buffer[buflen - 2] = '/';
> -+				buffer[buflen - 1] = '\0';
> -+			}
> -+		}
> -+	}
> -+	return pos;
> -+#else
> -+	char *pos = buffer + buflen - 1;
> -+	struct dentry *dentry = path->dentry;
> -+	struct vfsmount *vfsmnt = path->mnt;
> -+	const char *name;
> -+	int len;
> -+
> -+	if (buflen < 256)
> -+		goto out;
> -+
> -+	*pos = '\0';
> -+	if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
> -+		*--pos = '/';
> -+	for (;;) {
> -+		struct dentry *parent;
> -+		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
> -+			if (vfsmnt->mnt_parent == vfsmnt)
> -+				break;
> -+			dentry = vfsmnt->mnt_mountpoint;
> -+			vfsmnt = vfsmnt->mnt_parent;
> -+			continue;
> -+		}
> -+		parent = dentry->d_parent;
> -+		name = dentry->d_name.name;
> -+		len = dentry->d_name.len;
> -+		pos -= len;
> -+		if (pos <= buffer)
> -+			goto out;
> -+		memmove(pos, name, len);
> -+		*--pos = '/';
> -+		dentry = parent;
> -+	}
> -+	if (*pos == '/')
> -+		pos++;
> -+	len = dentry->d_name.len;
> -+	pos -= len;
> -+	if (pos < buffer)
> -+		goto out;
> -+	memmove(pos, dentry->d_name.name, len);
> -+	return pos;
> -+out:
> -+	return ERR_PTR(-ENOMEM);
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_get_dentry_path - Get the path of a dentry.
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @buffer: Pointer to buffer to return value in.
> -+ * @buflen: Sizeof @buffer.
> -+ *
> -+ * Returns the buffer on success, an error code otherwise.
> -+ *
> -+ * Based on dentry_path() in fs/dcache.c
> -+ *
> -+ * If dentry is a directory, trailing '/' is appended.
> -+ */
> -+static char *ccs_get_dentry_path(struct dentry *dentry, char * const buffer,
> -+				 const int buflen)
> -+{
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
> -+	char *pos = ERR_PTR(-ENOMEM);
> -+	if (buflen >= 256) {
> -+		pos = dentry_path_raw(dentry, buffer, buflen - 1);
> -+		if (!IS_ERR(pos) && *pos == '/' && pos[1] &&
> -+		    d_is_dir(dentry)) {
> -+			buffer[buflen - 2] = '/';
> -+			buffer[buflen - 1] = '\0';
> -+		}
> -+	}
> -+	return pos;
> -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
> -+	char *pos = ERR_PTR(-ENOMEM);
> -+	if (buflen >= 256) {
> -+		/* rename_lock is locked/unlocked by dentry_path_raw(). */
> -+		pos = dentry_path_raw(dentry, buffer, buflen - 1);
> -+		if (!IS_ERR(pos) && *pos == '/' && pos[1]) {
> -+			struct inode *inode = dentry->d_inode;
> -+			if (inode && S_ISDIR(inode->i_mode)) {
> -+				buffer[buflen - 2] = '/';
> -+				buffer[buflen - 1] = '\0';
> -+			}
> -+		}
> -+	}
> -+	return pos;
> -+#else
> -+	char *pos = buffer + buflen - 1;
> -+	if (buflen < 256)
> -+		return ERR_PTR(-ENOMEM);
> -+	*pos = '\0';
> -+	if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
> -+		*--pos = '/';
> -+	spin_lock(&dcache_lock);
> -+	while (!IS_ROOT(dentry)) {
> -+		struct dentry *parent = dentry->d_parent;
> -+		const char *name = dentry->d_name.name;
> -+		const int len = dentry->d_name.len;
> -+		pos -= len;
> -+		if (pos <= buffer) {
> -+			pos = ERR_PTR(-ENOMEM);
> -+			break;
> -+		}
> -+		memmove(pos, name, len);
> -+		*--pos = '/';
> -+		dentry = parent;
> -+	}
> -+	spin_unlock(&dcache_lock);
> -+	return pos;
> -+#endif
> -+}
> -+
> -+/**
> -+ * ccs_get_local_path - Get the path of a dentry.
> -+ *
> -+ * @dentry: Pointer to "struct dentry".
> -+ * @buffer: Pointer to buffer to return value in.
> -+ * @buflen: Sizeof @buffer.
> -+ *
> -+ * Returns the buffer on success, an error code otherwise.
> -+ */
> -+static char *ccs_get_local_path(struct dentry *dentry, char * const buffer,
> -+				const int buflen)
> -+{
> -+	struct super_block *sb = dentry->d_sb;
> -+	char *pos = ccs_get_dentry_path(dentry, buffer, buflen);
> -+	if (IS_ERR(pos))
> -+		return pos;
> -+	/* Convert from $PID to self if $PID is current thread. */
> -+	if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') {
> -+		char *ep;
> -+		const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
> -+		if (*ep == '/' && pid && pid ==
> -+		    task_tgid_nr_ns(current, sb->s_fs_info)) {
> -+			pos = ep - 5;
> -+			if (pos < buffer)
> -+				goto out;
> -+			memmove(pos, "/self", 5);
> -+		}
> -+#else
> -+		if (*ep == '/' && pid == ccs_sys_getpid()) {
> -+			pos = ep - 5;
> -+			if (pos < buffer)
> -+				goto out;
> -+			memmove(pos, "/self", 5);
> -+		}
> -+#endif
> -+		goto prepend_filesystem_name;
> -+	}
> -+	/* Use filesystem name for unnamed devices. */
> -+	if (!MAJOR(sb->s_dev))
> -+		goto prepend_filesystem_name;
> -+	{
> -+		struct inode *inode = sb->s_root->d_inode;
> -+		/*
> -+		 * Use filesystem name if filesystems does not support rename()
> -+		 * operation.
> -+		 */
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
> -+		if (inode->i_op && !inode->i_op->rename)
> -+			goto prepend_filesystem_name;
> -+#else
> -+		if (!inode->i_op->rename && !inode->i_op->rename2)
> -+			goto prepend_filesystem_name;
> -+#endif
> -+	}
> -+	/* Prepend device name. */
> -+	{
> -+		char name[64];
> -+		int name_len;
> -+		const dev_t dev = sb->s_dev;
> -+		name[sizeof(name) - 1] = '\0';
> -+		snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev),
> -+			 MINOR(dev));
> -+		name_len = strlen(name);
> -+		pos -= name_len;
> -+		if (pos < buffer)
> -+			goto out;
> -+		memmove(pos, name, name_len);
> -+		return pos;
> -+	}
> -+	/* Prepend filesystem name. */
> -+prepend_filesystem_name:
> -+	{
> -+		const char *name = sb->s_type->name;
> -+		const int name_len = strlen(name);
> -+		pos -= name_len + 1;
> -+		if (pos < buffer)
> -+			goto out;
> -+		memmove(pos, name, name_len);
> -+		pos[name_len] = ':';
> -+	}
> -+	return pos;
> -+out:
> -+	return ERR_PTR(-ENOMEM);
> -+}
> -+
> -+/**
> -+ * ccs_get_socket_name - Get the name of a socket.
> -+ *
> -+ * @path:   Pointer to "struct path".
> -+ * @buffer: Pointer to buffer to return value in.
> -+ * @buflen: Sizeof @buffer.
> -+ *
> -+ * Returns the buffer.
> -+ */
> -+static char *ccs_get_socket_name(const struct path *path, char * const buffer,
> -+				 const int buflen)
> -+{
> -+	struct inode *inode = path->dentry->d_inode;
> -+	struct socket *sock = inode ? SOCKET_I(inode) : NULL;
> -+	struct sock *sk = sock ? sock->sk : NULL;
> -+	if (sk) {
> -+		snprintf(buffer, buflen, "socket:[family=%u:type=%u:"
> -+			 "protocol=%u]", sk->sk_family, sk->sk_type,
> -+			 sk->sk_protocol);
> -+	} else {
> -+		snprintf(buffer, buflen, "socket:[unknown]");
> -+	}
> -+	return buffer;
> -+}
> -+
> -+#define SOCKFS_MAGIC 0x534F434B
> -+
> -+/**
> -+ * ccs_realpath - Returns realpath(3) of the given pathname but ignores chroot'ed root.
> -+ *
> -+ * @path: Pointer to "struct path".
> -+ *
> -+ * Returns the realpath of the given @path on success, NULL otherwise.
> -+ *
> -+ * This function uses kzalloc(), so caller must kfree() if this function
> -+ * didn't return NULL.
> -+ */
> -+char *ccs_realpath(const struct path *path)
> -+{
> -+	char *buf = NULL;
> -+	char *name = NULL;
> -+	unsigned int buf_len = PAGE_SIZE / 2;
> -+	struct dentry *dentry = path->dentry;
> -+	struct super_block *sb;
> -+	if (!dentry)
> -+		return NULL;
> -+	sb = dentry->d_sb;
> -+	while (1) {
> -+		char *pos;
> -+		struct inode *inode;
> -+		buf_len <<= 1;
> -+		kfree(buf);
> -+		buf = kmalloc(buf_len, CCS_GFP_FLAGS);
> -+		if (!buf)
> -+			break;
> -+		/* To make sure that pos is '\0' terminated. */
> -+		buf[buf_len - 1] = '\0';
> -+		/* Get better name for socket. */
> -+		if (sb->s_magic == SOCKFS_MAGIC) {
> -+			pos = ccs_get_socket_name(path, buf, buf_len - 1);
> -+			goto encode;
> -+		}
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
> -+		/* For "pipe:[\$]". */
> -+		if (dentry->d_op && dentry->d_op->d_dname) {
> -+			pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
> -+			goto encode;
> -+		}
> -+#endif
> -+		inode = sb->s_root->d_inode;
> -+		/*
> -+		 * Use local name for "filesystems without rename() operation"
> -+		 * or "path without vfsmount" or "absolute name is unavailable"
> -+		 * cases.
> -+		 */
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
> -+		if (!path->mnt || (inode->i_op && !inode->i_op->rename))
> -+			pos = ERR_PTR(-EINVAL);
> -+		else {
> -+			/* Get absolute name for the rest. */
> -+			ccs_realpath_lock();
> -+			pos = ccs_get_absolute_path(path, buf, buf_len - 1);
> -+			ccs_realpath_unlock();
> -+		}
> -+		if (pos == ERR_PTR(-EINVAL))
> -+			pos = ccs_get_local_path(path->dentry, buf,
> -+						 buf_len - 1);
> -+#else
> -+		if (!path->mnt ||
> -+		    (!inode->i_op->rename && !inode->i_op->rename2))
> -+			pos = ccs_get_local_path(path->dentry, buf,
> -+						 buf_len - 1);
> -+		else
> -+			pos = ccs_get_absolute_path(path, buf, buf_len - 1);
> -+#endif
> -+encode:
> -+		if (IS_ERR(pos))
> -+			continue;
> -+		name = ccs_encode(pos);
> -+		break;
> -+	}
> -+	kfree(buf);
> -+	if (!name)
> -+		ccs_warn_oom(__func__);
> -+	return name;
> -+}
> -+
> -+/**
> -+ * ccs_encode2 - Encode binary string to ascii string.
> -+ *
> -+ * @str:     String in binary format.
> -+ * @str_len: Size of @str in byte.
> -+ *
> -+ * Returns pointer to @str in ascii format on success, NULL otherwise.
> -+ *
> -+ * This function uses kzalloc(), so caller must kfree() if this function
> -+ * didn't return NULL.
> -+ */
> -+char *ccs_encode2(const char *str, int str_len)
> -+{
> -+	int i;
> -+	int len = 0;
> -+	const char *p = str;
> -+	char *cp;
> -+	char *cp0;
> -+	if (!p)
> -+		return NULL;
> -+	for (i = 0; i < str_len; i++) {
> -+		const unsigned char c = p[i];
> -+		if (c == '\\')
> -+			len += 2;
> -+		else if (c > ' ' && c < 127)
> -+			len++;
> -+		else
> -+			len += 4;
> -+	}
> -+	len++;
> -+	/* Reserve space for appending "/". */
> -+	cp = kzalloc(len + 10, CCS_GFP_FLAGS);
> -+	if (!cp)
> -+		return NULL;
> -+	cp0 = cp;
> -+	p = str;
> -+	for (i = 0; i < str_len; i++) {
> -+		const unsigned char c = p[i];
> -+		if (c == '\\') {
> -+			*cp++ = '\\';
> -+			*cp++ = '\\';
> -+		} else if (c > ' ' && c < 127) {
> -+			*cp++ = c;
> -+		} else {
> -+			*cp++ = '\\';
> -+			*cp++ = (c >> 6) + '0';
> -+			*cp++ = ((c >> 3) & 7) + '0';
> -+			*cp++ = (c & 7) + '0';
> -+		}
> -+	}
> -+	return cp0;
> -+}
> -+
> -+/**
> -+ * ccs_encode - Encode binary string to ascii string.
> -+ *
> -+ * @str: String in binary format.
> -+ *
> -+ * Returns pointer to @str in ascii format on success, NULL otherwise.
> -+ *
> -+ * This function uses kzalloc(), so caller must kfree() if this function
> -+ * didn't return NULL.
> -+ */
> -+char *ccs_encode(const char *str)
> -+{
> -+	return str ? ccs_encode2(str, strlen(str)) : NULL;
> -+}
> -+
> -+/**
> -+ * ccs_const_part_length - Evaluate the initial length without a pattern in a token.
> -+ *
> -+ * @filename: The string to evaluate.
> -+ *
> -+ * Returns the initial length without a pattern in @filename.
> -+ */
> -+static int ccs_const_part_length(const char *filename)
> -+{
> -+	char c;
> -+	int len = 0;
> -+	if (!filename)
> -+		return 0;
> -+	while (1) {
> -+		c = *filename++;
> -+		if (!c)
> -+			break;
> -+		if (c != '\\') {
> -+			len++;
> -+			continue;
> -+		}
> -+		c = *filename++;
> -+		switch (c) {
> -+		case '\\':  /* "\\" */
> -+			len += 2;
> -+			continue;
> -+		case '0':   /* "\ooo" */
> -+		case '1':
> -+		case '2':
> -+		case '3':
> -+			c = *filename++;
> -+			if (c < '0' || c > '7')
> -+				break;
> -+			c = *filename++;
> -+			if (c < '0' || c > '7')
> -+				break;
> -+			len += 4;
> -+			continue;
> -+		}
> -+		break;
> -+	}
> -+	return len;
> -+}
> -+
> -+/**
> -+ * ccs_fill_path_info - Fill in "struct ccs_path_info" members.
> -+ *
> -+ * @ptr: Pointer to "struct ccs_path_info" to fill in.
> -+ *
> -+ * The caller sets "struct ccs_path_info"->name.
> -+ */
> -+void ccs_fill_path_info(struct ccs_path_info *ptr)
> -+{
> -+	const char *name = ptr->name;
> -+	const int len = strlen(name);
> -+	ptr->total_len = len;
> -+	ptr->const_len = ccs_const_part_length(name);
> -+	ptr->is_dir = len && (name[len - 1] == '/');
> -+	ptr->is_patterned = (ptr->const_len < len);
> -+	ptr->hash = full_name_hash(name, len);
> -+}
> -+
> -+/**
> -+ * ccs_get_exe - Get ccs_realpath() of current process.
> -+ *
> -+ * Returns the ccs_realpath() of current process on success, NULL otherwise.
> -+ *
> -+ * This function uses kzalloc(), so the caller must kfree()
> -+ * if this function didn't return NULL.
> -+ */
> -+const char *ccs_get_exe(void)
> -+{
> -+	struct mm_struct *mm = current->mm;
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
> -+	struct vm_area_struct *vma;
> -+#endif
> -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
> -+	struct path path;
> -+#endif
> -+	struct file *exe_file = NULL;
> -+	const char *cp;
> -+	if (!mm)
> -+		return NULL;
> -+	down_read(&mm->mmap_sem);
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
> -+	/* Not using get_mm_exe_file() as it is not exported. */
> -+	exe_file = mm->exe_file;
> -+#else
> -+	for (vma = mm->mmap; vma; vma = vma->vm_next) {
> -+		if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
> -+			exe_file = vma->vm_file;
> -+			break;
> -+		}
> -+	}
> -+#endif
> -+	if (exe_file)
> -+		get_file(exe_file);
> -+	up_read(&mm->mmap_sem);
> -+	if (!exe_file)
> -+		return NULL;
> -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
> -+	cp = ccs_realpath(&exe_file->f_path);
> -+#else
> -+	path.mnt = exe_file->f_vfsmnt;
> -+	path.dentry = exe_file->f_dentry;
> -+	cp = ccs_realpath(&path);
> -+#endif
> -+	fput(exe_file);
> -+	return cp;
> -+}
> ---
> -1.9.1
> -
> diff --git a/recipes-kernel/linux/linux-yocto-4.1/tomoyo.cfg b/recipes-kernel/linux/linux-yocto-4.1/tomoyo.cfg
> deleted file mode 100644
> index 8f78270..0000000
> --- a/recipes-kernel/linux/linux-yocto-4.1/tomoyo.cfg
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -CONFIG_CCSECURITY=y
> -CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY=y
> -CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY=2048
> -CONFIG_CCSECURITY_MAX_AUDIT_LOG=1024
> -CONFIG_CCSECURITY_POLICY_LOADER="/sbin/ccs-init"
> -CONFIG_CCSECURITY_ACTIVATION_TRIGGER="/sbin/init"
> -CONFIG_CCSECURITY_FILE_READDIR=y
> -CONFIG_CCSECURITY_FILE_GETATTR=y
> -CONFIG_CCSECURITY_NETWORK=y
> -CONFIG_CCSECURITY_NETWORK_RECVMSG=y
> -CONFIG_CCSECURITY_CAPABILITY=y
> -CONFIG_CCSECURITY_IPC=y
> -CONFIG_CCSECURITY_MISC=y
> -CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER=y
> -CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION=y
> -CONFIG_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
> deleted file mode 100644
> index 588864c..0000000
> --- a/recipes-kernel/linux/linux-yocto-4.1/tomoyo.scc
> +++ /dev/null
> @@ -1,4 +0,0 @@
> -define KFEATURE_DESCRIPTION "Tomoyo Kernel Support"
> -define KFEATURE_COMPATIBILITY arch
> -
> -kconf non-hardware tomoyo.cfg
> diff --git a/recipes-kernel/linux/linux-yocto_4.1.bbappend b/recipes-kernel/linux/linux-yocto_4.1.bbappend
> deleted file mode 100644
> index dc90e31..0000000
> --- a/recipes-kernel/linux/linux-yocto_4.1.bbappend
> +++ /dev/null
> @@ -1,9 +0,0 @@
> -FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-4.1:"
> -
> -# Tomoyo kernel support
> -SRC_URI += "\
> -	${@bb.utils.contains('DISTRO_FEATURES', 'tomoyo', ' file://ccs-tools-yocto.4.1.patch', '', d)} \
> -	${@bb.utils.contains('DISTRO_FEATURES', 'tomoyo', ' file://ccs-tools-yocto_security.patch', '', d)} \
> -	${@bb.utils.contains('DISTRO_FEATURES', 'tomoyo', ' file://tomoyo.cfg', '', d)} \
> -	${@bb.utils.contains('DISTRO_FEATURES', 'tomoyo', ' file://tomoyo.scc', '', d)} \
> -	"




More information about the yocto mailing list