This is TOMOYO Linux patch for kernel 5.14.21.

Source code for this patch is https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.14.21.tar.xz
---
 fs/exec.c                 |    2 -
 fs/open.c                 |    2 +
 fs/proc/version.c         |    7 ++++
 include/linux/sched.h     |    5 +++
 include/linux/security.h  |   70 ++++++++++++++++++++++++++++------------------
 include/net/ip.h          |    4 ++
 init/init_task.c          |    4 ++
 kernel/kexec.c            |    4 +-
 kernel/module.c           |    5 +++
 kernel/ptrace.c           |   10 ++++++
 kernel/reboot.c           |    3 +
 kernel/sched/core.c       |    2 +
 kernel/signal.c           |   25 ++++++++++++++++
 kernel/sys.c              |    8 +++++
 kernel/time/timekeeping.c |    8 +++++
 net/ipv4/raw.c            |    4 ++
 net/ipv4/udp.c            |    2 +
 net/ipv6/raw.c            |    4 ++
 net/ipv6/udp.c            |    2 +
 net/socket.c              |    4 ++
 net/unix/af_unix.c        |    5 +++
 security/Kconfig          |    2 +
 security/Makefile         |    3 +
 security/security.c       |    5 ++-
 24 files changed, 160 insertions(+), 30 deletions(-)

--- linux-5.14.21.orig/fs/exec.c
+++ linux-5.14.21/fs/exec.c
@@ -1828,7 +1828,7 @@ static int bprm_execve(struct linux_binp
 	if (retval)
 		goto out;
 
-	retval = exec_binprm(bprm);
+	retval = ccs_exec_binprm(bprm);
 	if (retval < 0)
 		goto out;
 
--- linux-5.14.21.orig/fs/open.c
+++ linux-5.14.21/fs/open.c
@@ -1363,6 +1363,8 @@ SYSCALL_DEFINE3(close_range, unsigned in
  */
 SYSCALL_DEFINE0(vhangup)
 {
+	if (!ccs_capable(CCS_SYS_VHANGUP))
+		return -EPERM;
 	if (capable(CAP_SYS_TTY_CONFIG)) {
 		tty_vhangup_self();
 		return 0;
--- linux-5.14.21.orig/fs/proc/version.c
+++ linux-5.14.21/fs/proc/version.c
@@ -21,3 +21,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: 5.14.21 2021/11/29\n");
+	return 0;
+}
+fs_initcall(ccs_show_version);
--- linux-5.14.21.orig/include/linux/sched.h
+++ linux-5.14.21/include/linux/sched.h
@@ -43,6 +43,7 @@ struct bio_list;
 struct blk_plug;
 struct bpf_local_storage;
 struct capture_control;
+struct ccs_domain_info;
 struct cfs_rq;
 struct fs_struct;
 struct futex_pi_state;
@@ -1380,6 +1381,10 @@ struct task_struct {
 	/* Used by BPF task local storage */
 	struct bpf_local_storage __rcu	*bpf_storage;
 #endif
+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
+	struct ccs_domain_info		*ccs_domain_info;
+	u32				ccs_flags;
+#endif
 
 #ifdef CONFIG_GCC_PLUGIN_STACKLEAK
 	unsigned long			lowest_stack;
--- linux-5.14.21.orig/include/linux/security.h
+++ linux-5.14.21/include/linux/security.h
@@ -59,6 +59,7 @@ struct fs_parameter;
 enum fs_value_type;
 struct watch;
 struct watch_notification;
+#include <linux/ccsecurity.h>
 
 /* Default (no) options for the capable function */
 #define CAP_OPT_NONE 0x0
@@ -587,7 +588,10 @@ static inline int security_syslog(int ty
 static inline int security_settime64(const struct timespec64 *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)
@@ -680,18 +684,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(const struct path *old_path,
 					const 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,
@@ -719,7 +723,7 @@ static inline int security_add_mnt_opt(c
 static inline int security_move_mount(const struct path *from_path,
 				      const struct path *to_path)
 {
-	return 0;
+	return ccs_move_mount_permission(from_path, to_path);
 }
 
 static inline int security_path_notify(const struct path *path, u64 mask,
@@ -860,7 +864,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 user_namespace *mnt_userns,
@@ -958,7 +962,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,
@@ -987,7 +991,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)
@@ -1009,17 +1013,19 @@ static inline int security_file_receive(
 
 static inline int security_file_open(struct file *file)
 {
-	return 0;
+	return ccs_file_open(file);
 }
 
 static inline int security_task_alloc(struct task_struct *task,
 				      unsigned long clone_flags)
 {
-	return 0;
+	return ccs_alloc_task_security(task);
 }
 
 static inline void security_task_free(struct task_struct *task)
-{ }
+{
+	ccs_free_task_security(task);
+}
 
 static inline int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
 {
@@ -1446,7 +1452,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,
@@ -1467,19 +1473,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,
@@ -1491,7 +1497,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,
@@ -1782,42 +1788,42 @@ int security_path_chroot(const struct pa
 #else	/* CONFIG_SECURITY_PATH */
 static inline int security_path_unlink(const struct path *dir, struct dentry *dentry)
 {
-	return 0;
+	return ccs_path_unlink(dir, dentry);
 }
 
 static inline int security_path_mkdir(const struct path *dir, struct dentry *dentry,
 				      umode_t mode)
 {
-	return 0;
+	return ccs_path_mkdir(dir, dentry, mode);
 }
 
 static inline int security_path_rmdir(const struct path *dir, struct dentry *dentry)
 {
-	return 0;
+	return ccs_path_rmdir(dir, dentry);
 }
 
 static inline int security_path_mknod(const 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(const struct path *path)
 {
-	return 0;
+	return ccs_path_truncate(path);
 }
 
 static inline int security_path_symlink(const 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,
 				     const 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(const struct path *old_dir,
@@ -1826,22 +1832,32 @@ static inline int security_path_rename(c
 				       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(const struct path *path, umode_t mode)
 {
-	return 0;
+	return ccs_path_chmod(path, mode);
 }
 
 static inline int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
 {
-	return 0;
+	return ccs_path_chown(path, uid, gid);
 }
 
 static inline int security_path_chroot(const struct path *path)
 {
-	return 0;
+	return ccs_path_chroot(path);
 }
 #endif	/* CONFIG_SECURITY_PATH */
 
--- linux-5.14.21.orig/include/net/ip.h
+++ linux-5.14.21/include/net/ip.h
@@ -339,6 +339,8 @@ void inet_get_local_port_range(struct ne
 #ifdef CONFIG_SYSCTL
 static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port)
 {
+	if (ccs_lport_reserved(port))
+		return true;
 	if (!net->ipv4.sysctl_local_reserved_ports)
 		return false;
 	return test_bit(port, net->ipv4.sysctl_local_reserved_ports);
@@ -357,6 +359,8 @@ static inline bool inet_port_requires_bi
 #else
 static inline bool inet_is_local_reserved_port(struct net *net, unsigned short port)
 {
+	if (ccs_lport_reserved(port))
+		return true;
 	return false;
 }
 
--- linux-5.14.21.orig/init/init_task.c
+++ linux-5.14.21/init/init_task.c
@@ -213,6 +213,10 @@ struct task_struct init_task
 #ifdef CONFIG_SECCOMP_FILTER
 	.seccomp	= { .filter_count = ATOMIC_INIT(0) },
 #endif
+#if defined(CONFIG_CCSECURITY) && !defined(CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY)
+	.ccs_domain_info = NULL,
+	.ccs_flags      = 0,
+#endif
 };
 EXPORT_SYMBOL(init_task);
 
--- linux-5.14.21.orig/kernel/kexec.c
+++ linux-5.14.21/kernel/kexec.c
@@ -16,7 +16,7 @@
 #include <linux/syscalls.h>
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
-
+#include <linux/ccsecurity.h>
 #include "kexec_internal.h"
 
 static int copy_user_segment_list(struct kimage *image,
@@ -203,6 +203,8 @@ static inline int kexec_load_check(unsig
 	/* 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;
 
 	/* Permit LSMs and IMA to fail the kexec */
 	result = security_kernel_load_data(LOADING_KEXEC_IMAGE, false);
--- linux-5.14.21.orig/kernel/module.c
+++ linux-5.14.21/kernel/module.c
@@ -59,6 +59,7 @@
 #include <linux/audit.h>
 #include <uapi/linux/module.h>
 #include "module-internal.h"
+#include <linux/ccsecurity.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
@@ -918,6 +919,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;
@@ -3790,6 +3793,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-5.14.21.orig/kernel/ptrace.c
+++ linux-5.14.21/kernel/ptrace.c
@@ -1279,6 +1279,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();
@@ -1426,6 +1431,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-5.14.21.orig/kernel/reboot.c
+++ linux-5.14.21/kernel/reboot.c
@@ -18,6 +18,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
@@ -326,6 +327,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-5.14.21.orig/kernel/sched/core.c
+++ linux-5.14.21/kernel/sched/core.c
@@ -6685,6 +6685,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-5.14.21.orig/kernel/signal.c
+++ linux-5.14.21/kernel/signal.c
@@ -3691,6 +3691,8 @@ static inline void prepare_kill_siginfo(
 SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
 {
 	struct kernel_siginfo info;
+	if (ccs_kill_permission(pid, sig))
+		return -EPERM;
 
 	prepare_kill_siginfo(sig, &info);
 
@@ -3790,6 +3792,21 @@ SYSCALL_DEFINE4(pidfd_send_signal, int,
 	if (!access_pidfd_pidns(pid))
 		goto err;
 
+	{
+		struct task_struct *task;
+		int id = 0;
+
+		rcu_read_lock();
+		task = pid_task(pid, PIDTYPE_PID);
+		if (task)
+			id = task_pid_vnr(task);
+		rcu_read_unlock();
+		if (task && ccs_kill_permission(id, sig)) {
+			ret = -EPERM;
+			goto err;
+		}
+	}
+
 	if (info) {
 		ret = copy_siginfo_from_user_any(&kinfo, info);
 		if (unlikely(ret))
@@ -3874,6 +3891,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);
 }
@@ -3890,6 +3909,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);
 }
@@ -3902,6 +3923,8 @@ static int do_rt_sigqueueinfo(pid_t pid,
 	if ((info->si_code >= 0 || info->si_code == SI_TKILL) &&
 	    (task_pid_vnr(current) != pid))
 		return -EPERM;
+	if (ccs_sigqueue_permission(pid, sig))
+		return -EPERM;
 
 	/* POSIX.1b doesn't mention process groups.  */
 	return kill_proc_info(sig, info, pid);
@@ -3949,6 +3972,8 @@ static int do_rt_tgsigqueueinfo(pid_t tg
 	if ((info->si_code >= 0 || info->si_code == SI_TKILL) &&
 	    (task_pid_vnr(current) != pid))
 		return -EPERM;
+	if (ccs_tgsigqueue_permission(tgid, pid, sig))
+		return -EPERM;
 
 	return do_send_specific(tgid, pid, sig, info);
 }
--- linux-5.14.21.orig/kernel/sys.c
+++ linux-5.14.21/kernel/sys.c
@@ -211,6 +211,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;
@@ -1346,6 +1350,8 @@ SYSCALL_DEFINE2(sethostname, char __user
 
 	if (len < 0 || len > __NEW_UTS_LEN)
 		return -EINVAL;
+	if (!ccs_capable(CCS_SYS_SETHOSTNAME))
+		return -EPERM;
 	errno = -EFAULT;
 	if (!copy_from_user(tmp, name, len)) {
 		struct new_utsname *u;
@@ -1398,6 +1404,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;
 
 	errno = -EFAULT;
 	if (!copy_from_user(tmp, name, len)) {
--- linux-5.14.21.orig/kernel/time/timekeeping.c
+++ linux-5.14.21/kernel/time/timekeeping.c
@@ -22,6 +22,7 @@
 #include <linux/pvclock_gtod.h>
 #include <linux/compiler.h>
 #include <linux/audit.h>
+#include <linux/ccsecurity.h>
 
 #include "tick-internal.h"
 #include "ntp_internal.h"
@@ -2326,10 +2327,15 @@ static int timekeeping_validate_timex(co
 		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!
@@ -2344,6 +2350,8 @@ static int timekeeping_validate_timex(co
 		/* In order to inject time, you gotta be super-user! */
 		if (!capable(CAP_SYS_TIME))
 			return -EPERM;
+		if (!ccs_capable(CCS_SYS_SETTIME))
+			return -EPERM;
 
 		/*
 		 * Validate if a timespec/timeval used to inject a time
--- linux-5.14.21.orig/net/ipv4/raw.c
+++ linux-5.14.21/net/ipv4/raw.c
@@ -768,6 +768,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-5.14.21.orig/net/ipv4/udp.c
+++ linux-5.14.21/net/ipv4/udp.c
@@ -1851,6 +1851,8 @@ try_again:
 	skb = __skb_recv_udp(sk, flags, noblock, &off, &err);
 	if (!skb)
 		return err;
+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags))
+		return -EAGAIN; /* Hope less harmful than -EPERM. */
 
 	ulen = udp_skb_len(skb);
 	copied = len;
--- linux-5.14.21.orig/net/ipv6/raw.c
+++ linux-5.14.21/net/ipv6/raw.c
@@ -480,6 +480,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-5.14.21.orig/net/ipv6/udp.c
+++ linux-5.14.21/net/ipv6/udp.c
@@ -343,6 +343,8 @@ try_again:
 	skb = __skb_recv_udp(sk, flags, noblock, &off, &err);
 	if (!skb)
 		return err;
+	if (ccs_socket_post_recvmsg_permission(sk, skb, flags))
+		return -EAGAIN; /* Hope less harmful than -EPERM. */
 
 	ulen = udp6_skb_len(skb);
 	copied = len;
--- linux-5.14.21.orig/net/socket.c
+++ linux-5.14.21/net/socket.c
@@ -1782,6 +1782,10 @@ int __sys_accept4_file(struct file *file
 	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) {
 		len = newsock->ops->getname(newsock,
 					(struct sockaddr *)&address, 2);
--- linux-5.14.21.orig/net/unix/af_unix.c
+++ linux-5.14.21/net/unix/af_unix.c
@@ -2202,6 +2202,10 @@ static int unix_dgram_recvmsg(struct soc
 						EPOLLOUT | EPOLLWRNORM |
 						EPOLLWRBAND);
 
+	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);
 
@@ -2252,6 +2256,7 @@ static int unix_dgram_recvmsg(struct soc
 
 out_free:
 	skb_free_datagram(sk, skb);
+out_unlock:
 	mutex_unlock(&u->iolock);
 out:
 	return err;
--- linux-5.14.21.orig/security/Kconfig
+++ linux-5.14.21/security/Kconfig
@@ -295,5 +295,7 @@ config LSM
 
 source "security/Kconfig.hardening"
 
+source "security/ccsecurity/Kconfig"
+
 endmenu
 
--- linux-5.14.21.orig/security/Makefile
+++ linux-5.14.21/security/Makefile
@@ -38,3 +38,6 @@ obj-$(CONFIG_SECURITY_LANDLOCK)		+= land
 # Object integrity file lists
 subdir-$(CONFIG_INTEGRITY)		+= integrity
 obj-$(CONFIG_INTEGRITY)			+= integrity/
+
+subdir-$(CONFIG_CCSECURITY)		+= ccsecurity
+obj-$(CONFIG_CCSECURITY)		+= ccsecurity/
--- linux-5.14.21.orig/security/security.c
+++ linux-5.14.21/security/security.c
@@ -1644,7 +1644,9 @@ int security_task_alloc(struct task_stru
 
 	if (rc)
 		return rc;
-	rc = call_int_hook(task_alloc, 0, task, clone_flags);
+	rc = ccs_alloc_task_security(task);
+	if (likely(!rc))
+		rc = call_int_hook(task_alloc, 0, task, clone_flags);
 	if (unlikely(rc))
 		security_task_free(task);
 	return rc;
@@ -1653,6 +1655,7 @@ int security_task_alloc(struct task_stru
 void security_task_free(struct task_struct *task)
 {
 	call_void_hook(task_free, task);
+	ccs_free_task_security(task);
 
 	kfree(task->security);
 	task->security = NULL;
