• R/O
  • SSH
  • HTTPS

akari: Commit


Commit MetaInfo

Révision695 (tree)
l'heure2023-05-27 15:50:45
Auteurkumaneko

Message de Log

1.0.48

Change Summary

Modification

--- tags/patches/1.0.48/permission.c (nonexistent)
+++ tags/patches/1.0.48/permission.c (revision 695)
@@ -0,0 +1,5154 @@
1+/*
2+ * security/ccsecurity/permission.c
3+ *
4+ * Copyright (C) 2005-2012 NTT DATA CORPORATION
5+ *
6+ * Version: 1.8.9 2021/04/01
7+ */
8+
9+#include "internal.h"
10+
11+/***** SECTION1: Constants definition *****/
12+
13+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
14+
15+/*
16+ * may_open() receives open flags modified by open_to_namei_flags() until
17+ * 2.6.32. We stop here in case some distributions backported ACC_MODE changes,
18+ * for we can't determine whether may_open() receives open flags modified by
19+ * open_to_namei_flags() or not.
20+ */
21+#ifdef ACC_MODE
22+#error ACC_MODE already defined.
23+#endif
24+#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
25+
26+#if defined(RHEL_MAJOR) && RHEL_MAJOR == 6
27+/* RHEL6 passes unmodified flags since 2.6.32-71.14.1.el6 . */
28+#undef ACC_MODE
29+#define ACC_MODE(x) ("\004\002\006"[(x)&O_ACCMODE])
30+#endif
31+
32+#endif
33+
34+/* String table for special mount operations. */
35+static const char * const ccs_mounts[CCS_MAX_SPECIAL_MOUNT] = {
36+ [CCS_MOUNT_BIND] = "--bind",
37+ [CCS_MOUNT_MOVE] = "--move",
38+ [CCS_MOUNT_REMOUNT] = "--remount",
39+ [CCS_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable",
40+ [CCS_MOUNT_MAKE_PRIVATE] = "--make-private",
41+ [CCS_MOUNT_MAKE_SLAVE] = "--make-slave",
42+ [CCS_MOUNT_MAKE_SHARED] = "--make-shared",
43+};
44+
45+/* Mapping table from "enum ccs_path_acl_index" to "enum ccs_mac_index". */
46+static const u8 ccs_p2mac[CCS_MAX_PATH_OPERATION] = {
47+ [CCS_TYPE_EXECUTE] = CCS_MAC_FILE_EXECUTE,
48+ [CCS_TYPE_READ] = CCS_MAC_FILE_OPEN,
49+ [CCS_TYPE_WRITE] = CCS_MAC_FILE_OPEN,
50+ [CCS_TYPE_APPEND] = CCS_MAC_FILE_OPEN,
51+ [CCS_TYPE_UNLINK] = CCS_MAC_FILE_UNLINK,
52+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
53+ [CCS_TYPE_GETATTR] = CCS_MAC_FILE_GETATTR,
54+#endif
55+ [CCS_TYPE_RMDIR] = CCS_MAC_FILE_RMDIR,
56+ [CCS_TYPE_TRUNCATE] = CCS_MAC_FILE_TRUNCATE,
57+ [CCS_TYPE_SYMLINK] = CCS_MAC_FILE_SYMLINK,
58+ [CCS_TYPE_CHROOT] = CCS_MAC_FILE_CHROOT,
59+ [CCS_TYPE_UMOUNT] = CCS_MAC_FILE_UMOUNT,
60+};
61+
62+/* Mapping table from "enum ccs_mkdev_acl_index" to "enum ccs_mac_index". */
63+const u8 ccs_pnnn2mac[CCS_MAX_MKDEV_OPERATION] = {
64+ [CCS_TYPE_MKBLOCK] = CCS_MAC_FILE_MKBLOCK,
65+ [CCS_TYPE_MKCHAR] = CCS_MAC_FILE_MKCHAR,
66+};
67+
68+/* Mapping table from "enum ccs_path2_acl_index" to "enum ccs_mac_index". */
69+const u8 ccs_pp2mac[CCS_MAX_PATH2_OPERATION] = {
70+ [CCS_TYPE_LINK] = CCS_MAC_FILE_LINK,
71+ [CCS_TYPE_RENAME] = CCS_MAC_FILE_RENAME,
72+ [CCS_TYPE_PIVOT_ROOT] = CCS_MAC_FILE_PIVOT_ROOT,
73+};
74+
75+/*
76+ * Mapping table from "enum ccs_path_number_acl_index" to "enum ccs_mac_index".
77+ */
78+const u8 ccs_pn2mac[CCS_MAX_PATH_NUMBER_OPERATION] = {
79+ [CCS_TYPE_CREATE] = CCS_MAC_FILE_CREATE,
80+ [CCS_TYPE_MKDIR] = CCS_MAC_FILE_MKDIR,
81+ [CCS_TYPE_MKFIFO] = CCS_MAC_FILE_MKFIFO,
82+ [CCS_TYPE_MKSOCK] = CCS_MAC_FILE_MKSOCK,
83+ [CCS_TYPE_IOCTL] = CCS_MAC_FILE_IOCTL,
84+ [CCS_TYPE_CHMOD] = CCS_MAC_FILE_CHMOD,
85+ [CCS_TYPE_CHOWN] = CCS_MAC_FILE_CHOWN,
86+ [CCS_TYPE_CHGRP] = CCS_MAC_FILE_CHGRP,
87+};
88+
89+#ifdef CONFIG_CCSECURITY_NETWORK
90+
91+/*
92+ * Mapping table from "enum ccs_network_acl_index" to "enum ccs_mac_index" for
93+ * inet domain socket.
94+ */
95+static const u8 ccs_inet2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
96+ [SOCK_STREAM] = {
97+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_INET_STREAM_BIND,
98+ [CCS_NETWORK_LISTEN] = CCS_MAC_NETWORK_INET_STREAM_LISTEN,
99+ [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_INET_STREAM_CONNECT,
100+ [CCS_NETWORK_ACCEPT] = CCS_MAC_NETWORK_INET_STREAM_ACCEPT,
101+ },
102+ [SOCK_DGRAM] = {
103+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_INET_DGRAM_BIND,
104+ [CCS_NETWORK_SEND] = CCS_MAC_NETWORK_INET_DGRAM_SEND,
105+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
106+ [CCS_NETWORK_RECV] = CCS_MAC_NETWORK_INET_DGRAM_RECV,
107+#endif
108+ },
109+ [SOCK_RAW] = {
110+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_INET_RAW_BIND,
111+ [CCS_NETWORK_SEND] = CCS_MAC_NETWORK_INET_RAW_SEND,
112+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
113+ [CCS_NETWORK_RECV] = CCS_MAC_NETWORK_INET_RAW_RECV,
114+#endif
115+ },
116+};
117+
118+/*
119+ * Mapping table from "enum ccs_network_acl_index" to "enum ccs_mac_index" for
120+ * unix domain socket.
121+ */
122+static const u8 ccs_unix2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
123+ [SOCK_STREAM] = {
124+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_UNIX_STREAM_BIND,
125+ [CCS_NETWORK_LISTEN] = CCS_MAC_NETWORK_UNIX_STREAM_LISTEN,
126+ [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_STREAM_CONNECT,
127+ [CCS_NETWORK_ACCEPT] = CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT,
128+ },
129+ [SOCK_DGRAM] = {
130+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_UNIX_DGRAM_BIND,
131+ [CCS_NETWORK_SEND] = CCS_MAC_NETWORK_UNIX_DGRAM_SEND,
132+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
133+ [CCS_NETWORK_RECV] = CCS_MAC_NETWORK_UNIX_DGRAM_RECV,
134+#endif
135+ },
136+ [SOCK_SEQPACKET] = {
137+ [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND,
138+ [CCS_NETWORK_LISTEN] = CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
139+ [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
140+ [CCS_NETWORK_ACCEPT] = CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT,
141+ },
142+};
143+
144+#endif
145+
146+#ifdef CONFIG_CCSECURITY_CAPABILITY
147+
148+/*
149+ * Mapping table from "enum ccs_capability_acl_index" to "enum ccs_mac_index".
150+ */
151+const u8 ccs_c2mac[CCS_MAX_CAPABILITY_INDEX] = {
152+ [CCS_USE_ROUTE_SOCKET] = CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET,
153+ [CCS_USE_PACKET_SOCKET] = CCS_MAC_CAPABILITY_USE_PACKET_SOCKET,
154+ [CCS_SYS_REBOOT] = CCS_MAC_CAPABILITY_SYS_REBOOT,
155+ [CCS_SYS_VHANGUP] = CCS_MAC_CAPABILITY_SYS_VHANGUP,
156+ [CCS_SYS_SETTIME] = CCS_MAC_CAPABILITY_SYS_SETTIME,
157+ [CCS_SYS_NICE] = CCS_MAC_CAPABILITY_SYS_NICE,
158+ [CCS_SYS_SETHOSTNAME] = CCS_MAC_CAPABILITY_SYS_SETHOSTNAME,
159+ [CCS_USE_KERNEL_MODULE] = CCS_MAC_CAPABILITY_USE_KERNEL_MODULE,
160+ [CCS_SYS_KEXEC_LOAD] = CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD,
161+ [CCS_SYS_PTRACE] = CCS_MAC_CAPABILITY_SYS_PTRACE,
162+};
163+
164+#endif
165+
166+/***** SECTION2: Structure definition *****/
167+
168+/* Structure for holding inet domain socket's address. */
169+struct ccs_inet_addr_info {
170+ u16 port; /* In network byte order. */
171+ const u32 *address; /* In network byte order. */
172+ bool is_ipv6;
173+};
174+
175+/* Structure for holding unix domain socket's address. */
176+struct ccs_unix_addr_info {
177+ u8 *addr; /* This may not be '\0' terminated string. */
178+ unsigned int addr_len;
179+};
180+
181+/* Structure for holding socket address. */
182+struct ccs_addr_info {
183+ u8 protocol;
184+ u8 operation;
185+ struct ccs_inet_addr_info inet;
186+ struct ccs_unix_addr_info unix0;
187+};
188+
189+/***** SECTION3: Prototype definition section *****/
190+
191+bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
192+ struct ccs_page_dump *dump);
193+void ccs_get_attributes(struct ccs_obj_info *obj);
194+
195+static bool ccs_alphabet_char(const char c);
196+static bool ccs_argv(const unsigned int index, const char *arg_ptr,
197+ const int argc, const struct ccs_argv *argv, u8 *checked);
198+static bool ccs_byte_range(const char *str);
199+static bool ccs_check_entry(struct ccs_request_info *r,
200+ struct ccs_acl_info *ptr);
201+static bool ccs_check_mkdev_acl(struct ccs_request_info *r,
202+ const struct ccs_acl_info *ptr);
203+static bool ccs_check_mount_acl(struct ccs_request_info *r,
204+ const struct ccs_acl_info *ptr);
205+static bool ccs_check_path2_acl(struct ccs_request_info *r,
206+ const struct ccs_acl_info *ptr);
207+static bool ccs_check_path_acl(struct ccs_request_info *r,
208+ const struct ccs_acl_info *ptr);
209+static bool ccs_check_path_number_acl(struct ccs_request_info *r,
210+ const struct ccs_acl_info *ptr);
211+static bool ccs_compare_number_union(const unsigned long value,
212+ const struct ccs_number_union *ptr);
213+static bool ccs_condition(struct ccs_request_info *r,
214+ const struct ccs_condition *cond);
215+static bool ccs_decimal(const char c);
216+static bool ccs_envp(const char *env_name, const char *env_value,
217+ const int envc, const struct ccs_envp *envp, u8 *checked);
218+static bool ccs_file_matches_pattern(const char *filename,
219+ const char *filename_end,
220+ const char *pattern,
221+ const char *pattern_end);
222+static bool ccs_file_matches_pattern2(const char *filename,
223+ const char *filename_end,
224+ const char *pattern,
225+ const char *pattern_end);
226+static bool ccs_get_realpath(struct ccs_path_info *buf, struct path *path);
227+static bool ccs_hexadecimal(const char c);
228+static bool ccs_number_matches_group(const unsigned long min,
229+ const unsigned long max,
230+ const struct ccs_group *group);
231+static bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
232+ const struct ccs_path_info *pattern);
233+static bool ccs_path_matches_pattern2(const char *f, const char *p);
234+static bool ccs_scan_bprm(struct ccs_execve *ee, const u16 argc,
235+ const struct ccs_argv *argv, const u16 envc,
236+ const struct ccs_envp *envp);
237+static bool ccs_scan_exec_realpath(struct file *file,
238+ const struct ccs_name_union *ptr,
239+ const bool match);
240+static bool ccs_scan_transition(const struct list_head *list,
241+ const struct ccs_path_info *domainname,
242+ const struct ccs_path_info *program,
243+ const char *last_name,
244+ const enum ccs_transition_type type);
245+static const char *ccs_last_word(const char *name);
246+static const struct ccs_path_info *ccs_compare_name_union
247+(const struct ccs_path_info *name, const struct ccs_name_union *ptr);
248+static const struct ccs_path_info *ccs_path_matches_group
249+(const struct ccs_path_info *pathname, const struct ccs_group *group);
250+static enum ccs_transition_type ccs_transition_type
251+(const struct ccs_policy_namespace *ns, const struct ccs_path_info *domainname,
252+ const struct ccs_path_info *program);
253+static int __ccs_chmod_permission(struct dentry *dentry,
254+ struct vfsmount *vfsmnt, mode_t mode);
255+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
256+static int __ccs_chown_permission(struct dentry *dentry,
257+ struct vfsmount *vfsmnt, kuid_t user,
258+ kgid_t group);
259+#else
260+static int __ccs_chown_permission(struct dentry *dentry,
261+ struct vfsmount *vfsmnt, uid_t user,
262+ gid_t group);
263+#endif
264+static int __ccs_chroot_permission(const struct path *path);
265+static int __ccs_fcntl_permission(struct file *file, unsigned int cmd,
266+ unsigned long arg);
267+static int __ccs_ioctl_permission(struct file *filp, unsigned int cmd,
268+ unsigned long arg);
269+static int __ccs_link_permission(struct dentry *old_dentry,
270+ struct dentry *new_dentry,
271+ struct vfsmount *mnt);
272+static int __ccs_mkdir_permission(struct dentry *dentry, struct vfsmount *mnt,
273+ unsigned int mode);
274+static int __ccs_mknod_permission(struct dentry *dentry, struct vfsmount *mnt,
275+ const unsigned int mode, unsigned int dev);
276+static int __ccs_mount_permission(const char *dev_name,
277+ const struct path *path, const char *type,
278+ unsigned long flags, void *data_page);
279+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
280+static int __ccs_move_mount_permission(const struct path *from_path,
281+ const struct path *to_path);
282+#endif
283+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
284+static int __ccs_open_exec_permission(struct dentry *dentry,
285+ struct vfsmount *mnt);
286+#endif
287+static int __ccs_open_permission(struct dentry *dentry, struct vfsmount *mnt,
288+ const int flag);
289+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
290+static int __ccs_parse_table(int __user *name, int nlen, void __user *oldval,
291+ void __user *newval, struct ctl_table *table);
292+#endif
293+static int __ccs_pivot_root_permission(const struct path *old_path,
294+ const struct path *new_path);
295+static int __ccs_rename_permission(struct dentry *old_dentry,
296+ struct dentry *new_dentry,
297+ struct vfsmount *mnt);
298+static int __ccs_rmdir_permission(struct dentry *dentry, struct vfsmount *mnt);
299+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
300+static int __ccs_search_binary_handler(struct linux_binprm *bprm,
301+ struct pt_regs *regs);
302+#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
303+static int __ccs_search_binary_handler(struct linux_binprm *bprm);
304+#endif
305+static int __ccs_symlink_permission(struct dentry *dentry,
306+ struct vfsmount *mnt, const char *from);
307+static int __ccs_truncate_permission(struct dentry *dentry,
308+ struct vfsmount *mnt);
309+static int __ccs_umount_permission(struct vfsmount *mnt, int flags);
310+static int __ccs_unlink_permission(struct dentry *dentry,
311+ struct vfsmount *mnt);
312+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
313+static int __ccs_uselib_permission(struct dentry *dentry,
314+ struct vfsmount *mnt);
315+#endif
316+static int ccs_execute_permission(struct ccs_request_info *r,
317+ const struct ccs_path_info *filename);
318+static int ccs_find_next_domain(struct ccs_execve *ee);
319+static int ccs_get_path(const char *pathname, struct path *path);
320+static int ccs_kern_path(const char *pathname, int flags, struct path *path);
321+static int ccs_mkdev_perm(const u8 operation, struct dentry *dentry,
322+ struct vfsmount *mnt, const unsigned int mode,
323+ unsigned int dev);
324+static int ccs_mount_acl(struct ccs_request_info *r, const char *dev_name,
325+ const struct path *dir, const char *type,
326+ unsigned long flags);
327+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
328+static int ccs_new_open_permission(struct file *filp);
329+#endif
330+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
331+static int ccs_old_chroot_permission(struct nameidata *nd);
332+static int ccs_old_mount_permission(const char *dev_name, struct nameidata *nd,
333+ const char *type, unsigned long flags,
334+ void *data_page);
335+static int ccs_old_pivot_root_permission(struct nameidata *old_nd,
336+ struct nameidata *new_nd);
337+#endif
338+static int ccs_path2_perm(const u8 operation, struct dentry *dentry1,
339+ struct vfsmount *mnt1, struct dentry *dentry2,
340+ struct vfsmount *mnt2);
341+static int ccs_path_number_perm(const u8 type, struct dentry *dentry,
342+ struct vfsmount *vfsmnt, unsigned long number);
343+static int ccs_path_perm(const u8 operation, struct dentry *dentry,
344+ struct vfsmount *mnt, const char *target);
345+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) || !defined(CONFIG_SYSCTL_SYSCALL)
346+static
347+#endif
348+int ccs_path_permission(struct ccs_request_info *r, u8 operation,
349+ const struct ccs_path_info *filename);
350+static int ccs_symlink_path(const char *pathname, struct ccs_path_info *name);
351+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
352+static void __ccs_clear_open_mode(void);
353+static void __ccs_save_open_mode(int mode);
354+#endif
355+static void ccs_add_slash(struct ccs_path_info *buf);
356+
357+#ifdef CONFIG_CCSECURITY_MISC
358+static bool ccs_check_env_acl(struct ccs_request_info *r,
359+ const struct ccs_acl_info *ptr);
360+static int ccs_env_perm(struct ccs_request_info *r, const char *env);
361+static int ccs_environ(struct ccs_execve *ee);
362+#endif
363+
364+#ifdef CONFIG_CCSECURITY_CAPABILITY
365+static bool __ccs_capable(const u8 operation);
366+static bool ccs_check_capability_acl(struct ccs_request_info *r,
367+ const struct ccs_acl_info *ptr);
368+static bool ccs_kernel_service(void);
369+static int __ccs_ptrace_permission(long request, long pid);
370+static int __ccs_socket_create_permission(int family, int type, int protocol);
371+#endif
372+
373+#ifdef CONFIG_CCSECURITY_NETWORK
374+static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
375+ const struct ccs_group *group);
376+static bool ccs_check_inet_acl(struct ccs_request_info *r,
377+ const struct ccs_acl_info *ptr);
378+static bool ccs_check_unix_acl(struct ccs_request_info *r,
379+ const struct ccs_acl_info *ptr);
380+static bool ccs_kernel_service(void);
381+static int __ccs_socket_bind_permission(struct socket *sock,
382+ struct sockaddr *addr, int addr_len);
383+static int __ccs_socket_connect_permission(struct socket *sock,
384+ struct sockaddr *addr,
385+ int addr_len);
386+static int __ccs_socket_listen_permission(struct socket *sock);
387+static int __ccs_socket_post_accept_permission(struct socket *sock,
388+ struct socket *newsock);
389+static int __ccs_socket_sendmsg_permission(struct socket *sock,
390+ struct msghdr *msg, int size);
391+static int ccs_check_inet_address(const struct sockaddr *addr,
392+ const unsigned int addr_len, const u16 port,
393+ struct ccs_addr_info *address);
394+static int ccs_check_unix_address(struct sockaddr *addr,
395+ const unsigned int addr_len,
396+ struct ccs_addr_info *address);
397+static int ccs_inet_entry(const struct ccs_addr_info *address);
398+static int ccs_unix_entry(const struct ccs_addr_info *address);
399+static u8 ccs_sock_family(struct sock *sk);
400+#endif
401+
402+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
403+static int __ccs_socket_post_recvmsg_permission(struct sock *sk,
404+ struct sk_buff *skb,
405+ int flags);
406+#endif
407+
408+#ifdef CONFIG_CCSECURITY_IPC
409+static bool ccs_check_signal_acl(struct ccs_request_info *r,
410+ const struct ccs_acl_info *ptr);
411+static int ccs_signal_acl(const int pid, const int sig);
412+static int ccs_signal_acl0(pid_t tgid, pid_t pid, int sig);
413+static int ccs_signal_acl2(const int sig, const int pid);
414+#endif
415+
416+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
417+static int __ccs_getattr_permission(struct vfsmount *mnt,
418+ struct dentry *dentry);
419+#endif
420+
421+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
422+static bool ccs_find_execute_handler(struct ccs_execve *ee, const u8 type);
423+static int ccs_try_alt_exec(struct ccs_execve *ee);
424+static void ccs_unescape(unsigned char *dest);
425+#endif
426+
427+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
428+static bool ccs_check_task_acl(struct ccs_request_info *r,
429+ const struct ccs_acl_info *ptr);
430+#endif
431+
432+/***** SECTION4: Standalone functions section *****/
433+
434+#if defined(RHEL_MAJOR) && RHEL_MAJOR == 8 && defined(RHEL_MINOR) && RHEL_MINOR >= 6
435+
436+/**
437+ * prepare_binprm - Read the first BINPRM_BUF_SIZE bytes.
438+ *
439+ * @bprm: Pointer to "struct linux_binprm".
440+ *
441+ * This is not the same with prepare_binprm() in fs/exec.c due to not exported
442+ * bprm_fill_uid()/security_bprm_repopulate_creds(). I guess that RHBZ#1993665
443+ * decided to accept a not-yet-upstreamed "exec: Control flow simplifications"
444+ * feature. But since this path is used by execute_handler, I assume that
445+ * suid/sgid is not set on programs called via this path.
446+ */
447+static int prepare_binprm(struct linux_binprm *bprm)
448+{
449+ loff_t pos = 0;
450+
451+ memset(bprm->buf, 0, BINPRM_BUF_SIZE);
452+ return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos);
453+}
454+
455+#endif
456+
457+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
458+
459+/**
460+ * prepare_binprm - Read the first BINPRM_BUF_SIZE bytes.
461+ *
462+ * @bprm: Pointer to "struct linux_binprm".
463+ *
464+ * Same with prepare_binprm() in fs/exec.c
465+ */
466+static inline int prepare_binprm(struct linux_binprm *bprm)
467+{
468+ loff_t pos = 0;
469+
470+ memset(bprm->buf, 0, BINPRM_BUF_SIZE);
471+ return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos);
472+}
473+
474+/**
475+ * ccs_copy_argv - Wrapper for copy_string_kernel().
476+ *
477+ * @arg: String to copy.
478+ * @bprm: Pointer to "struct linux_binprm".
479+ *
480+ * Returns return value of copy_string_kernel().
481+ */
482+static inline int ccs_copy_argv(const char *arg, struct linux_binprm *bprm)
483+{
484+ const int ret = copy_string_kernel(arg, bprm);
485+ if (ret >= 0)
486+ bprm->argc++;
487+ return ret;
488+}
489+
490+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
491+
492+/**
493+ * ccs_copy_argv - Wrapper for copy_strings_kernel().
494+ *
495+ * @arg: String to copy.
496+ * @bprm: Pointer to "struct linux_binprm".
497+ *
498+ * Returns return value of copy_strings_kernel().
499+ */
500+static inline int ccs_copy_argv(const char *arg, struct linux_binprm *bprm)
501+{
502+ const int ret = copy_strings_kernel(1, &arg, bprm);
503+ if (ret >= 0)
504+ bprm->argc++;
505+ return ret;
506+}
507+
508+#else
509+
510+/**
511+ * ccs_copy_argv - Wrapper for copy_strings_kernel().
512+ *
513+ * @arg: String to copy.
514+ * @bprm: Pointer to "struct linux_binprm".
515+ *
516+ * Returns return value of copy_strings_kernel().
517+ */
518+static inline int ccs_copy_argv(char *arg, struct linux_binprm *bprm)
519+{
520+ const int ret = copy_strings_kernel(1, &arg, bprm);
521+ if (ret >= 0)
522+ bprm->argc++;
523+ return ret;
524+}
525+
526+#endif
527+
528+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)
529+
530+/**
531+ * get_fs_root - Get reference on root directory.
532+ *
533+ * @fs: Pointer to "struct fs_struct".
534+ * @root: Pointer to "struct path".
535+ *
536+ * Returns nothing.
537+ *
538+ * This is for compatibility with older kernels.
539+ */
540+static inline void get_fs_root(struct fs_struct *fs, struct path *root)
541+{
542+ read_lock(&fs->lock);
543+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
544+ *root = fs->root;
545+ path_get(root);
546+#else
547+ root->dentry = dget(fs->root);
548+ root->mnt = mntget(fs->rootmnt);
549+#endif
550+ read_unlock(&fs->lock);
551+}
552+
553+#endif
554+
555+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
556+
557+/**
558+ * module_put - Put a reference on module.
559+ *
560+ * @module: Pointer to "struct module". Maybe NULL.
561+ *
562+ * Returns nothing.
563+ *
564+ * This is for compatibility with older kernels.
565+ */
566+static inline void module_put(struct module *module)
567+{
568+ if (module)
569+ __MOD_DEC_USE_COUNT(module);
570+}
571+
572+#endif
573+
574+/**
575+ * ccs_put_filesystem - Wrapper for put_filesystem().
576+ *
577+ * @fstype: Pointer to "struct file_system_type".
578+ *
579+ * Returns nothing.
580+ *
581+ * Since put_filesystem() is not exported, I embed put_filesystem() here.
582+ */
583+static inline void ccs_put_filesystem(struct file_system_type *fstype)
584+{
585+ module_put(fstype->owner);
586+}
587+
588+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
589+
590+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
591+#if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
592+#if !defined(AX_MAJOR) || AX_MAJOR != 3
593+
594+/**
595+ * ip_hdr - Get "struct iphdr".
596+ *
597+ * @skb: Pointer to "struct sk_buff".
598+ *
599+ * Returns pointer to "struct iphdr".
600+ *
601+ * This is for compatibility with older kernels.
602+ */
603+static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
604+{
605+ return skb->nh.iph;
606+}
607+
608+/**
609+ * udp_hdr - Get "struct udphdr".
610+ *
611+ * @skb: Pointer to "struct sk_buff".
612+ *
613+ * Returns pointer to "struct udphdr".
614+ *
615+ * This is for compatibility with older kernels.
616+ */
617+static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
618+{
619+ return skb->h.uh;
620+}
621+
622+/**
623+ * ipv6_hdr - Get "struct ipv6hdr".
624+ *
625+ * @skb: Pointer to "struct sk_buff".
626+ *
627+ * Returns pointer to "struct ipv6hdr".
628+ *
629+ * This is for compatibility with older kernels.
630+ */
631+static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
632+{
633+ return skb->nh.ipv6h;
634+}
635+
636+#endif
637+#endif
638+#endif
639+
640+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
641+
642+/**
643+ * skb_kill_datagram - Kill a datagram forcibly.
644+ *
645+ * @sk: Pointer to "struct sock".
646+ * @skb: Pointer to "struct sk_buff".
647+ * @flags: Flags passed to skb_recv_datagram().
648+ *
649+ * Returns nothing.
650+ */
651+static inline void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
652+ int flags)
653+{
654+ /* Clear queue. */
655+ if (flags & MSG_PEEK) {
656+ int clear = 0;
657+ spin_lock_irq(&sk->receive_queue.lock);
658+ if (skb == skb_peek(&sk->receive_queue)) {
659+ __skb_unlink(skb, &sk->receive_queue);
660+ clear = 1;
661+ }
662+ spin_unlock_irq(&sk->receive_queue.lock);
663+ if (clear)
664+ kfree_skb(skb);
665+ }
666+ skb_free_datagram(sk, skb);
667+}
668+
669+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
670+
671+/**
672+ * skb_kill_datagram - Kill a datagram forcibly.
673+ *
674+ * @sk: Pointer to "struct sock".
675+ * @skb: Pointer to "struct sk_buff".
676+ * @flags: Flags passed to skb_recv_datagram().
677+ *
678+ * Returns nothing.
679+ */
680+static inline void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
681+ int flags)
682+{
683+ /* Clear queue. */
684+ if (flags & MSG_PEEK) {
685+ int clear = 0;
686+ spin_lock_bh(&sk->sk_receive_queue.lock);
687+ if (skb == skb_peek(&sk->sk_receive_queue)) {
688+ __skb_unlink(skb, &sk->sk_receive_queue);
689+ clear = 1;
690+ }
691+ spin_unlock_bh(&sk->sk_receive_queue.lock);
692+ if (clear)
693+ kfree_skb(skb);
694+ }
695+ skb_free_datagram(sk, skb);
696+}
697+
698+#endif
699+
700+#endif
701+
702+/***** SECTION5: Variables definition section *****/
703+
704+/* The initial domain. */
705+struct ccs_domain_info ccs_kernel_domain;
706+
707+/* The list for "struct ccs_domain_info". */
708+LIST_HEAD(ccs_domain_list);
709+
710+/***** SECTION6: Dependent functions section *****/
711+
712+/**
713+ * ccs_path_matches_group - Check whether the given pathname matches members of the given pathname group.
714+ *
715+ * @pathname: The name of pathname.
716+ * @group: Pointer to "struct ccs_path_group".
717+ *
718+ * Returns matched member's pathname if @pathname matches pathnames in @group,
719+ * NULL otherwise.
720+ *
721+ * Caller holds ccs_read_lock().
722+ */
723+static const struct ccs_path_info *ccs_path_matches_group
724+(const struct ccs_path_info *pathname, const struct ccs_group *group)
725+{
726+ struct ccs_path_group *member;
727+ list_for_each_entry_srcu(member, &group->member_list, head.list,
728+ &ccs_ss) {
729+ if (member->head.is_deleted)
730+ continue;
731+ if (!ccs_path_matches_pattern(pathname, member->member_name))
732+ continue;
733+ return member->member_name;
734+ }
735+ return NULL;
736+}
737+
738+/**
739+ * ccs_number_matches_group - Check whether the given number matches members of the given number group.
740+ *
741+ * @min: Min number.
742+ * @max: Max number.
743+ * @group: Pointer to "struct ccs_number_group".
744+ *
745+ * Returns true if @min and @max partially overlaps @group, false otherwise.
746+ *
747+ * Caller holds ccs_read_lock().
748+ */
749+static bool ccs_number_matches_group(const unsigned long min,
750+ const unsigned long max,
751+ const struct ccs_group *group)
752+{
753+ struct ccs_number_group *member;
754+ bool matched = false;
755+ list_for_each_entry_srcu(member, &group->member_list, head.list,
756+ &ccs_ss) {
757+ if (member->head.is_deleted)
758+ continue;
759+ if (min > member->number.values[1] ||
760+ max < member->number.values[0])
761+ continue;
762+ matched = true;
763+ break;
764+ }
765+ return matched;
766+}
767+
768+/**
769+ * ccs_check_entry - Do permission check.
770+ *
771+ * @r: Pointer to "struct ccs_request_info".
772+ * @ptr: Pointer to "struct ccs_acl_info".
773+ *
774+ * Returns true on match, false otherwise.
775+ *
776+ * Caller holds ccs_read_lock().
777+ */
778+static bool ccs_check_entry(struct ccs_request_info *r,
779+ struct ccs_acl_info *ptr)
780+{
781+ if (ptr->is_deleted || ptr->type != r->param_type)
782+ return false;
783+ switch (r->param_type) {
784+ case CCS_TYPE_PATH_ACL:
785+ return ccs_check_path_acl(r, ptr);
786+ case CCS_TYPE_PATH2_ACL:
787+ return ccs_check_path2_acl(r, ptr);
788+ case CCS_TYPE_PATH_NUMBER_ACL:
789+ return ccs_check_path_number_acl(r, ptr);
790+ case CCS_TYPE_MKDEV_ACL:
791+ return ccs_check_mkdev_acl(r, ptr);
792+ case CCS_TYPE_MOUNT_ACL:
793+ return ccs_check_mount_acl(r, ptr);
794+#ifdef CONFIG_CCSECURITY_MISC
795+ case CCS_TYPE_ENV_ACL:
796+ return ccs_check_env_acl(r, ptr);
797+#endif
798+#ifdef CONFIG_CCSECURITY_CAPABILITY
799+ case CCS_TYPE_CAPABILITY_ACL:
800+ return ccs_check_capability_acl(r, ptr);
801+#endif
802+#ifdef CONFIG_CCSECURITY_NETWORK
803+ case CCS_TYPE_INET_ACL:
804+ return ccs_check_inet_acl(r, ptr);
805+ case CCS_TYPE_UNIX_ACL:
806+ return ccs_check_unix_acl(r, ptr);
807+#endif
808+#ifdef CONFIG_CCSECURITY_IPC
809+ case CCS_TYPE_SIGNAL_ACL:
810+ return ccs_check_signal_acl(r, ptr);
811+#endif
812+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
813+ case CCS_TYPE_MANUAL_TASK_ACL:
814+ return ccs_check_task_acl(r, ptr);
815+#endif
816+ }
817+ return true;
818+}
819+
820+/**
821+ * ccs_check_acl - Do permission check.
822+ *
823+ * @r: Pointer to "struct ccs_request_info".
824+ *
825+ * Returns 0 on success, negative value otherwise.
826+ *
827+ * Caller holds ccs_read_lock().
828+ */
829+int ccs_check_acl(struct ccs_request_info *r)
830+{
831+ const struct ccs_domain_info *domain = ccs_current_domain();
832+ int error;
833+ r->matched_acl = NULL;
834+ do {
835+ struct ccs_acl_info *ptr;
836+ const struct list_head *list = &domain->acl_info_list;
837+ u16 i = 0;
838+retry:
839+ list_for_each_entry_srcu(ptr, list, list, &ccs_ss) {
840+ if (!ccs_check_entry(r, ptr))
841+ continue;
842+ if (!ccs_condition(r, ptr->cond))
843+ continue;
844+ r->matched_acl = ptr;
845+ r->granted = true;
846+ ccs_audit_log(r);
847+ return 0;
848+ }
849+ for (; i < CCS_MAX_ACL_GROUPS; i++) {
850+ if (!test_bit(i, domain->group))
851+ continue;
852+ list = &domain->ns->acl_group[i++];
853+ goto retry;
854+ }
855+ r->granted = false;
856+ error = ccs_audit_log(r);
857+ } while (error == CCS_RETRY_REQUEST &&
858+ r->type != CCS_MAC_FILE_EXECUTE);
859+ return error;
860+}
861+
862+/**
863+ * ccs_last_word - Get last component of a domainname.
864+ *
865+ * @name: Domainname to check.
866+ *
867+ * Returns the last word of @name.
868+ */
869+static const char *ccs_last_word(const char *name)
870+{
871+ const char *cp = strrchr(name, ' ');
872+ if (cp)
873+ return cp + 1;
874+ return name;
875+}
876+
877+/**
878+ * ccs_scan_transition - Try to find specific domain transition type.
879+ *
880+ * @list: Pointer to "struct list_head".
881+ * @domainname: The name of current domain.
882+ * @program: The name of requested program.
883+ * @last_name: The last component of @domainname.
884+ * @type: One of values in "enum ccs_transition_type".
885+ *
886+ * Returns true if found one, false otherwise.
887+ *
888+ * Caller holds ccs_read_lock().
889+ */
890+static bool ccs_scan_transition(const struct list_head *list,
891+ const struct ccs_path_info *domainname,
892+ const struct ccs_path_info *program,
893+ const char *last_name,
894+ const enum ccs_transition_type type)
895+{
896+ const struct ccs_transition_control *ptr;
897+ list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
898+ if (ptr->head.is_deleted || ptr->type != type)
899+ continue;
900+ if (ptr->domainname) {
901+ if (!ptr->is_last_name) {
902+ if (ptr->domainname != domainname)
903+ continue;
904+ } else {
905+ /*
906+ * Use direct strcmp() since this is
907+ * unlikely used.
908+ */
909+ if (strcmp(ptr->domainname->name, last_name))
910+ continue;
911+ }
912+ }
913+ if (ptr->program && ccs_pathcmp(ptr->program, program))
914+ continue;
915+ return true;
916+ }
917+ return false;
918+}
919+
920+/**
921+ * ccs_transition_type - Get domain transition type.
922+ *
923+ * @ns: Pointer to "struct ccs_policy_namespace".
924+ * @domainname: The name of current domain.
925+ * @program: The name of requested program.
926+ *
927+ * Returns CCS_TRANSITION_CONTROL_TRANSIT if executing @program causes domain
928+ * transition across namespaces, CCS_TRANSITION_CONTROL_INITIALIZE if executing
929+ * @program reinitializes domain transition within that namespace,
930+ * CCS_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname ,
931+ * others otherwise.
932+ *
933+ * Caller holds ccs_read_lock().
934+ */
935+static enum ccs_transition_type ccs_transition_type
936+(const struct ccs_policy_namespace *ns, const struct ccs_path_info *domainname,
937+ const struct ccs_path_info *program)
938+{
939+ const char *last_name = ccs_last_word(domainname->name);
940+ enum ccs_transition_type type = CCS_TRANSITION_CONTROL_NO_RESET;
941+ while (type < CCS_MAX_TRANSITION_TYPE) {
942+ const struct list_head * const list =
943+ &ns->policy_list[CCS_ID_TRANSITION_CONTROL];
944+ if (!ccs_scan_transition(list, domainname, program, last_name,
945+ type)) {
946+ type++;
947+ continue;
948+ }
949+ if (type != CCS_TRANSITION_CONTROL_NO_RESET &&
950+ type != CCS_TRANSITION_CONTROL_NO_INITIALIZE)
951+ break;
952+ /*
953+ * Do not check for reset_domain if no_reset_domain matched.
954+ * Do not check for initialize_domain if no_initialize_domain
955+ * matched.
956+ */
957+ type++;
958+ type++;
959+ }
960+ return type;
961+}
962+
963+/**
964+ * ccs_find_next_domain - Find a domain.
965+ *
966+ * @ee: Pointer to "struct ccs_execve".
967+ *
968+ * Returns 0 on success, negative value otherwise.
969+ *
970+ * Caller holds ccs_read_lock().
971+ */
972+static int ccs_find_next_domain(struct ccs_execve *ee)
973+{
974+ struct ccs_request_info *r = &ee->r;
975+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
976+ const struct ccs_path_info *handler = ee->handler;
977+#endif
978+ struct ccs_domain_info *domain = NULL;
979+ struct ccs_domain_info * const old_domain = ccs_current_domain();
980+ struct linux_binprm *bprm = ee->bprm;
981+ struct ccs_security *task = ccs_current_security();
982+ const struct ccs_path_info *candidate;
983+ struct ccs_path_info exename;
984+ int retval;
985+ bool reject_on_transition_failure = false;
986+
987+ /* Get symlink's pathname of program. */
988+ retval = ccs_symlink_path(bprm->filename, &exename);
989+ if (retval < 0)
990+ return retval;
991+
992+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
993+ if (handler) {
994+ /* No permission check for execute handler. */
995+ candidate = &exename;
996+ if (ccs_pathcmp(candidate, handler)) {
997+ /* Failed to verify execute handler. */
998+ static u8 counter = 20;
999+ if (counter) {
1000+ counter--;
1001+ printk(KERN_WARNING "Failed to verify: %s\n",
1002+ handler->name);
1003+ }
1004+ goto out;
1005+ }
1006+ } else
1007+#endif
1008+ {
1009+ struct ccs_aggregator *ptr;
1010+ struct list_head *list;
1011+retry:
1012+ /* Check 'aggregator' directive. */
1013+ candidate = &exename;
1014+ list = &old_domain->ns->policy_list[CCS_ID_AGGREGATOR];
1015+ list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) {
1016+ if (ptr->head.is_deleted ||
1017+ !ccs_path_matches_pattern(candidate,
1018+ ptr->original_name))
1019+ continue;
1020+ candidate = ptr->aggregated_name;
1021+ break;
1022+ }
1023+
1024+ /* Check execute permission. */
1025+ retval = ccs_execute_permission(r, candidate);
1026+ if (retval == CCS_RETRY_REQUEST)
1027+ goto retry;
1028+ if (retval < 0)
1029+ goto out;
1030+ /*
1031+ * To be able to specify domainnames with wildcards, use the
1032+ * pathname specified in the policy (which may contain
1033+ * wildcard) rather than the pathname passed to execve()
1034+ * (which never contains wildcard).
1035+ */
1036+ if (r->param.path.matched_path)
1037+ candidate = r->param.path.matched_path;
1038+ }
1039+ /*
1040+ * Check for domain transition preference if "file execute" matched.
1041+ * If preference is given, make do_execve() fail if domain transition
1042+ * has failed, for domain transition preference should be used with
1043+ * destination domain defined.
1044+ */
1045+ if (r->ee->transition) {
1046+ const char *domainname = r->ee->transition->name;
1047+ reject_on_transition_failure = true;
1048+ if (!strcmp(domainname, "keep"))
1049+ goto force_keep_domain;
1050+ if (!strcmp(domainname, "child"))
1051+ goto force_child_domain;
1052+ if (!strcmp(domainname, "reset"))
1053+ goto force_reset_domain;
1054+ if (!strcmp(domainname, "initialize"))
1055+ goto force_initialize_domain;
1056+ if (!strcmp(domainname, "parent")) {
1057+ char *cp;
1058+ strncpy(ee->tmp, old_domain->domainname->name,
1059+ CCS_EXEC_TMPSIZE - 1);
1060+ cp = strrchr(ee->tmp, ' ');
1061+ if (cp)
1062+ *cp = '\0';
1063+ } else if (*domainname == '<')
1064+ strncpy(ee->tmp, domainname, CCS_EXEC_TMPSIZE - 1);
1065+ else
1066+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
1067+ old_domain->domainname->name, domainname);
1068+ goto force_jump_domain;
1069+ }
1070+ /*
1071+ * No domain transition preference specified.
1072+ * Calculate domain to transit to.
1073+ */
1074+ switch (ccs_transition_type(old_domain->ns, old_domain->domainname,
1075+ candidate)) {
1076+ case CCS_TRANSITION_CONTROL_RESET:
1077+force_reset_domain:
1078+ /* Transit to the root of specified namespace. */
1079+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "<%s>",
1080+ candidate->name);
1081+ /*
1082+ * Make do_execve() fail if domain transition across namespaces
1083+ * has failed.
1084+ */
1085+ reject_on_transition_failure = true;
1086+ break;
1087+ case CCS_TRANSITION_CONTROL_INITIALIZE:
1088+force_initialize_domain:
1089+ /* Transit to the child of current namespace's root. */
1090+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
1091+ old_domain->ns->name, candidate->name);
1092+ break;
1093+ case CCS_TRANSITION_CONTROL_KEEP:
1094+force_keep_domain:
1095+ /* Keep current domain. */
1096+ domain = old_domain;
1097+ break;
1098+ default:
1099+ if (old_domain == &ccs_kernel_domain && !ccs_policy_loaded) {
1100+ /*
1101+ * Needn't to transit from kernel domain before
1102+ * starting /sbin/init. But transit from kernel domain
1103+ * if executing initializers because they might start
1104+ * before /sbin/init.
1105+ */
1106+ domain = old_domain;
1107+ break;
1108+ }
1109+force_child_domain:
1110+ /* Normal domain transition. */
1111+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s %s",
1112+ old_domain->domainname->name, candidate->name);
1113+ break;
1114+ }
1115+force_jump_domain:
1116+ /*
1117+ * Tell GC that I started execve().
1118+ * Also, tell open_exec() to check read permission.
1119+ */
1120+ task->ccs_flags |= CCS_TASK_IS_IN_EXECVE;
1121+ /*
1122+ * Make task->ccs_flags visible to GC before changing
1123+ * task->ccs_domain_info.
1124+ */
1125+ smp_wmb();
1126+ /*
1127+ * Proceed to the next domain in order to allow reaching via PID.
1128+ * It will be reverted if execve() failed. Reverting is not good.
1129+ * But it is better than being unable to reach via PID in interactive
1130+ * enforcing mode.
1131+ */
1132+ if (!domain)
1133+ domain = ccs_assign_domain(ee->tmp, true);
1134+ if (domain)
1135+ retval = 0;
1136+ else if (reject_on_transition_failure) {
1137+ printk(KERN_WARNING
1138+ "ERROR: Domain '%s' not ready.\n", ee->tmp);
1139+ retval = -ENOMEM;
1140+ } else if (r->mode == CCS_CONFIG_ENFORCING)
1141+ retval = -ENOMEM;
1142+ else {
1143+ retval = 0;
1144+ if (!old_domain->flags[CCS_DIF_TRANSITION_FAILED]) {
1145+ old_domain->flags[CCS_DIF_TRANSITION_FAILED] = true;
1146+ r->granted = false;
1147+ ccs_write_log(r, "%s",
1148+ ccs_dif[CCS_DIF_TRANSITION_FAILED]);
1149+ printk(KERN_WARNING
1150+ "ERROR: Domain '%s' not defined.\n", ee->tmp);
1151+ }
1152+ }
1153+out:
1154+ kfree(exename.name);
1155+ return retval;
1156+}
1157+
1158+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
1159+
1160+/**
1161+ * ccs_unescape - Unescape escaped string.
1162+ *
1163+ * @dest: String to unescape.
1164+ *
1165+ * Returns nothing.
1166+ */
1167+static void ccs_unescape(unsigned char *dest)
1168+{
1169+ unsigned char *src = dest;
1170+ unsigned char c;
1171+ unsigned char d;
1172+ unsigned char e;
1173+ while (1) {
1174+ c = *src++;
1175+ if (!c)
1176+ break;
1177+ if (c != '\\') {
1178+ *dest++ = c;
1179+ continue;
1180+ }
1181+ c = *src++;
1182+ if (c == '\\') {
1183+ *dest++ = c;
1184+ continue;
1185+ }
1186+ if (c < '0' || c > '3')
1187+ break;
1188+ d = *src++;
1189+ if (d < '0' || d > '7')
1190+ break;
1191+ e = *src++;
1192+ if (e < '0' || e > '7')
1193+ break;
1194+ *dest++ = ((c - '0') << 6) + ((d - '0') << 3) + (e - '0');
1195+ }
1196+ *dest = '\0';
1197+}
1198+
1199+/**
1200+ * ccs_try_alt_exec - Try to start execute handler.
1201+ *
1202+ * @ee: Pointer to "struct ccs_execve".
1203+ *
1204+ * Returns 0 on success, negative value otherwise.
1205+ */
1206+static int ccs_try_alt_exec(struct ccs_execve *ee)
1207+{
1208+ /*
1209+ * Contents of modified bprm.
1210+ * The envp[] in original bprm is moved to argv[] so that
1211+ * the alternatively executed program won't be affected by
1212+ * some dangerous environment variables like LD_PRELOAD.
1213+ *
1214+ * modified bprm->argc
1215+ * = original bprm->argc + original bprm->envc + 7
1216+ * modified bprm->envc
1217+ * = 0
1218+ *
1219+ * modified bprm->argv[0]
1220+ * = the program's name specified by *_execute_handler
1221+ * modified bprm->argv[1]
1222+ * = ccs_current_domain()->domainname->name
1223+ * modified bprm->argv[2]
1224+ * = the current process's name
1225+ * modified bprm->argv[3]
1226+ * = the current process's information (e.g. uid/gid).
1227+ * modified bprm->argv[4]
1228+ * = original bprm->filename
1229+ * modified bprm->argv[5]
1230+ * = original bprm->argc in string expression
1231+ * modified bprm->argv[6]
1232+ * = original bprm->envc in string expression
1233+ * modified bprm->argv[7]
1234+ * = original bprm->argv[0]
1235+ * ...
1236+ * modified bprm->argv[bprm->argc + 6]
1237+ * = original bprm->argv[bprm->argc - 1]
1238+ * modified bprm->argv[bprm->argc + 7]
1239+ * = original bprm->envp[0]
1240+ * ...
1241+ * modified bprm->argv[bprm->envc + bprm->argc + 6]
1242+ * = original bprm->envp[bprm->envc - 1]
1243+ */
1244+ struct linux_binprm *bprm = ee->bprm;
1245+ struct file *filp;
1246+ int retval;
1247+ const int original_argc = bprm->argc;
1248+ const int original_envc = bprm->envc;
1249+
1250+ /* Close the requested program's dentry. */
1251+ ee->obj.path1.dentry = NULL;
1252+ ee->obj.path1.mnt = NULL;
1253+ ee->obj.stat_valid[CCS_PATH1] = false;
1254+ ee->obj.stat_valid[CCS_PATH1_PARENT] = false;
1255+ ee->obj.validate_done = false;
1256+ allow_write_access(bprm->file);
1257+ fput(bprm->file);
1258+ bprm->file = NULL;
1259+
1260+ /* Invalidate page dump cache. */
1261+ ee->dump.page = NULL;
1262+
1263+ /* Move envp[] to argv[] */
1264+ bprm->argc += bprm->envc;
1265+ bprm->envc = 0;
1266+
1267+ /* Set argv[6] */
1268+ {
1269+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_envc);
1270+ retval = ccs_copy_argv(ee->tmp, bprm);
1271+ if (retval < 0)
1272+ goto out;
1273+ }
1274+
1275+ /* Set argv[5] */
1276+ {
1277+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%d", original_argc);
1278+ retval = ccs_copy_argv(ee->tmp, bprm);
1279+ if (retval < 0)
1280+ goto out;
1281+ }
1282+
1283+ /* Set argv[4] */
1284+ {
1285+ retval = ccs_copy_argv(bprm->filename, bprm);
1286+ if (retval < 0)
1287+ goto out;
1288+ }
1289+
1290+ /* Set argv[3] */
1291+ {
1292+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
1293+ /*
1294+ * Pass uid/gid seen from current user namespace, for these
1295+ * values are used by programs in current user namespace in
1296+ * order to decide whether to execve() or not (rather than by
1297+ * auditing daemon in init's user namespace).
1298+ */
1299+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
1300+ "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
1301+ "sgid=%d fsuid=%d fsgid=%d", ccs_sys_getpid(),
1302+ __kuid_val(current_uid()), __kgid_val(current_gid()),
1303+ __kuid_val(current_euid()),
1304+ __kgid_val(current_egid()),
1305+ __kuid_val(current_suid()),
1306+ __kgid_val(current_sgid()),
1307+ __kuid_val(current_fsuid()),
1308+ __kgid_val(current_fsgid()));
1309+#else
1310+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1,
1311+ "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d "
1312+ "sgid=%d fsuid=%d fsgid=%d", ccs_sys_getpid(),
1313+ current_uid(), current_gid(), current_euid(),
1314+ current_egid(), current_suid(), current_sgid(),
1315+ current_fsuid(), current_fsgid());
1316+#endif
1317+ retval = ccs_copy_argv(ee->tmp, bprm);
1318+ if (retval < 0)
1319+ goto out;
1320+ }
1321+
1322+ /* Set argv[2] */
1323+ {
1324+ char *exe = (char *) ccs_get_exe();
1325+ if (exe) {
1326+ retval = ccs_copy_argv(exe, bprm);
1327+ kfree(exe);
1328+ } else {
1329+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
1330+ retval = ccs_copy_argv("<unknown>", bprm);
1331+#else
1332+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "<unknown>");
1333+ retval = ccs_copy_argv(ee->tmp, bprm);
1334+#endif
1335+ }
1336+ if (retval < 0)
1337+ goto out;
1338+ }
1339+
1340+ /* Set argv[1] */
1341+ {
1342+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
1343+ retval = ccs_copy_argv(ccs_current_domain()->domainname->name,
1344+ bprm);
1345+#else
1346+ snprintf(ee->tmp, CCS_EXEC_TMPSIZE - 1, "%s",
1347+ ccs_current_domain()->domainname->name);
1348+ retval = ccs_copy_argv(ee->tmp, bprm);
1349+#endif
1350+ if (retval < 0)
1351+ goto out;
1352+ }
1353+
1354+ /* Set argv[0] */
1355+ {
1356+ struct path root;
1357+ char *cp;
1358+ int root_len;
1359+ int handler_len;
1360+ get_fs_root(current->fs, &root);
1361+ cp = ccs_realpath(&root);
1362+ path_put(&root);
1363+ if (!cp) {
1364+ retval = -ENOMEM;
1365+ goto out;
1366+ }
1367+ root_len = strlen(cp);
1368+ retval = strncmp(ee->handler->name, cp, root_len);
1369+ root_len--;
1370+ kfree(cp);
1371+ if (retval) {
1372+ retval = -ENOENT;
1373+ goto out;
1374+ }
1375+ handler_len = ee->handler->total_len + 1;
1376+ cp = kmalloc(handler_len, CCS_GFP_FLAGS);
1377+ if (!cp) {
1378+ retval = -ENOMEM;
1379+ goto out;
1380+ }
1381+ /* ee->handler_path is released by ccs_finish_execve(). */
1382+ ee->handler_path = cp;
1383+ /* Adjust root directory for open_exec(). */
1384+ memmove(cp, ee->handler->name + root_len,
1385+ handler_len - root_len);
1386+ ccs_unescape(cp);
1387+ retval = -ENOENT;
1388+ if (*cp != '/')
1389+ goto out;
1390+ retval = ccs_copy_argv(cp, bprm);
1391+ if (retval < 0)
1392+ goto out;
1393+ }
1394+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
1395+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
1396+ bprm->argv_len = bprm->exec - bprm->p;
1397+#endif
1398+#endif
1399+
1400+ /*
1401+ * OK, now restart the process with execute handler program's dentry.
1402+ */
1403+ filp = open_exec(ee->handler_path);
1404+ if (IS_ERR(filp)) {
1405+ retval = PTR_ERR(filp);
1406+ goto out;
1407+ }
1408+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
1409+ ee->obj.path1 = filp->f_path;
1410+#else
1411+ ee->obj.path1.dentry = filp->f_dentry;
1412+ ee->obj.path1.mnt = filp->f_vfsmnt;
1413+#endif
1414+ bprm->file = filp;
1415+ bprm->filename = ee->handler_path;
1416+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1417+ bprm->interp = bprm->filename;
1418+#endif
1419+ retval = prepare_binprm(bprm);
1420+ if (retval < 0)
1421+ goto out;
1422+ ee->r.dont_sleep_on_enforce_error = true;
1423+ retval = ccs_find_next_domain(ee);
1424+ ee->r.dont_sleep_on_enforce_error = false;
1425+out:
1426+ return retval;
1427+}
1428+
1429+/**
1430+ * ccs_find_execute_handler - Find an execute handler.
1431+ *
1432+ * @ee: Pointer to "struct ccs_execve".
1433+ * @type: Type of execute handler.
1434+ *
1435+ * Returns true if found, false otherwise.
1436+ *
1437+ * Caller holds ccs_read_lock().
1438+ */
1439+static bool ccs_find_execute_handler(struct ccs_execve *ee, const u8 type)
1440+{
1441+ struct ccs_request_info *r = &ee->r;
1442+ /*
1443+ * To avoid infinite execute handler loop, don't use execute handler
1444+ * if the current process is marked as execute handler.
1445+ */
1446+ if (ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)
1447+ return false;
1448+ r->param_type = type;
1449+ ccs_check_acl(r);
1450+ if (!r->granted)
1451+ return false;
1452+ ee->handler = container_of(r->matched_acl, struct ccs_handler_acl,
1453+ head)->handler;
1454+ ee->transition = r->matched_acl && r->matched_acl->cond &&
1455+ r->matched_acl->cond->exec_transit ?
1456+ r->matched_acl->cond->transit : NULL;
1457+ return true;
1458+}
1459+
1460+#endif
1461+
1462+#ifdef CONFIG_MMU
1463+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
1464+#define CCS_BPRM_MMU
1465+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3
1466+#define CCS_BPRM_MMU
1467+#elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2
1468+#define CCS_BPRM_MMU
1469+#endif
1470+#endif
1471+
1472+/**
1473+ * ccs_dump_page - Dump a page to buffer.
1474+ *
1475+ * @bprm: Pointer to "struct linux_binprm".
1476+ * @pos: Location to dump.
1477+ * @dump: Pointer to "struct ccs_page_dump".
1478+ *
1479+ * Returns true on success, false otherwise.
1480+ */
1481+bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
1482+ struct ccs_page_dump *dump)
1483+{
1484+ struct page *page;
1485+#if defined(CCS_BPRM_MMU) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
1486+ int ret;
1487+#endif
1488+ /* dump->data is released by ccs_start_execve(). */
1489+ if (!dump->data) {
1490+ dump->data = kzalloc(PAGE_SIZE, CCS_GFP_FLAGS);
1491+ if (!dump->data)
1492+ return false;
1493+ }
1494+ /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
1495+#ifdef CCS_BPRM_MMU
1496+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
1497+ mmap_read_lock(bprm->mm);
1498+ ret = get_user_pages_remote(bprm->mm, pos, 1, FOLL_FORCE, &page, NULL, NULL);
1499+ mmap_read_unlock(bprm->mm);
1500+ if (ret <= 0)
1501+ return false;
1502+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
1503+ if (get_user_pages_remote(bprm->mm, pos, 1, FOLL_FORCE, &page,
1504+ NULL, NULL) <= 0)
1505+ return false;
1506+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
1507+ if (get_user_pages_remote(current, bprm->mm, pos, 1, FOLL_FORCE, &page,
1508+ NULL, NULL) <= 0)
1509+ return false;
1510+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
1511+ if (get_user_pages_remote(current, bprm->mm, pos, 1, FOLL_FORCE, &page,
1512+ NULL) <= 0)
1513+ return false;
1514+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 168) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
1515+ if (get_user_pages(current, bprm->mm, pos, 1, FOLL_FORCE, &page,
1516+ NULL) <= 0)
1517+ return false;
1518+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
1519+ if (get_user_pages_remote(current, bprm->mm, pos, 1, 0, 1, &page,
1520+ NULL) <= 0)
1521+ return false;
1522+#else
1523+ if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1524+ return false;
1525+#endif
1526+#else
1527+ page = bprm->page[pos / PAGE_SIZE];
1528+#endif
1529+ if (page != dump->page) {
1530+ const unsigned int offset = pos % PAGE_SIZE;
1531+ /*
1532+ * Maybe kmap()/kunmap() should be used here.
1533+ * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
1534+ * So do I.
1535+ */
1536+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
1537+ char *kaddr = kmap_atomic(page);
1538+#else
1539+ char *kaddr = kmap_atomic(page, KM_USER0);
1540+#endif
1541+ dump->page = page;
1542+ memcpy(dump->data + offset, kaddr + offset,
1543+ PAGE_SIZE - offset);
1544+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
1545+ kunmap_atomic(kaddr);
1546+#else
1547+ kunmap_atomic(kaddr, KM_USER0);
1548+#endif
1549+ }
1550+ /* Same with put_arg_page(page) in fs/exec.c */
1551+#ifdef CCS_BPRM_MMU
1552+ put_page(page);
1553+#endif
1554+ return true;
1555+}
1556+
1557+/**
1558+ * ccs_start_execve - Prepare for execve() operation.
1559+ *
1560+ * @bprm: Pointer to "struct linux_binprm".
1561+ * @eep: Pointer to "struct ccs_execve *".
1562+ *
1563+ * Returns 0 on success, negative value otherwise.
1564+ */
1565+int ccs_start_execve(struct linux_binprm *bprm, struct ccs_execve **eep)
1566+{
1567+ int retval;
1568+ struct ccs_security *task;
1569+ struct ccs_execve *ee;
1570+ int idx;
1571+ *eep = NULL;
1572+ ee = kzalloc(sizeof(*ee), CCS_GFP_FLAGS);
1573+ if (!ee)
1574+ return -ENOMEM;
1575+ ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
1576+ if (!ee->tmp) {
1577+ kfree(ee);
1578+ return -ENOMEM;
1579+ }
1580+ ccs_audit_alloc_execve(ee);
1581+ task = ccs_current_security();
1582+ idx = ccs_read_lock();
1583+ /* ee->dump->data is allocated by ccs_dump_page(). */
1584+ ee->previous_domain = task->ccs_domain_info;
1585+ /* Clear manager flag. */
1586+ task->ccs_flags &= ~CCS_TASK_IS_MANAGER;
1587+ *eep = ee;
1588+ ccs_init_request_info(&ee->r, CCS_MAC_FILE_EXECUTE);
1589+ ee->r.ee = ee;
1590+ ee->bprm = bprm;
1591+ ee->r.obj = &ee->obj;
1592+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
1593+ ee->obj.path1 = bprm->file->f_path;
1594+#else
1595+ ee->obj.path1.dentry = bprm->file->f_dentry;
1596+ ee->obj.path1.mnt = bprm->file->f_vfsmnt;
1597+#endif
1598+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
1599+ /*
1600+ * No need to call ccs_environ() for execute handler because envp[] is
1601+ * moved to argv[].
1602+ */
1603+ if (ccs_find_execute_handler(ee, CCS_TYPE_AUTO_EXECUTE_HANDLER)) {
1604+ retval = ccs_try_alt_exec(ee);
1605+ goto done;
1606+ }
1607+#endif
1608+ retval = ccs_find_next_domain(ee);
1609+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
1610+ if (retval == -EPERM &&
1611+ ccs_find_execute_handler(ee, CCS_TYPE_DENIED_EXECUTE_HANDLER)) {
1612+ retval = ccs_try_alt_exec(ee);
1613+ goto done;
1614+ }
1615+#endif
1616+#ifdef CONFIG_CCSECURITY_MISC
1617+ if (!retval)
1618+ retval = ccs_environ(ee);
1619+#endif
1620+#ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
1621+done:
1622+#endif
1623+ ccs_read_unlock(idx);
1624+ kfree(ee->tmp);
1625+ ee->tmp = NULL;
1626+ kfree(ee->dump.data);
1627+ ee->dump.data = NULL;
1628+ if (retval) {
1629+ ccs_finish_execve(retval, ee);
1630+ *eep = NULL;
1631+ }
1632+ return retval;
1633+}
1634+
1635+/**
1636+ * ccs_finish_execve - Clean up execve() operation.
1637+ *
1638+ * @retval: Return code of an execve() operation.
1639+ * @ee: Pointer to "struct ccs_execve".
1640+ *
1641+ * Returns nothing.
1642+ */
1643+void ccs_finish_execve(int retval, struct ccs_execve *ee)
1644+{
1645+ struct ccs_security *task = ccs_current_security();
1646+ if (!ee)
1647+ return;
1648+ if (retval < 0) {
1649+ task->ccs_domain_info = ee->previous_domain;
1650+ /*
1651+ * Make task->ccs_domain_info visible to GC before changing
1652+ * task->ccs_flags.
1653+ */
1654+ smp_wmb();
1655+ } else {
1656+ /* Mark the current process as execute handler. */
1657+ if (ee->handler)
1658+ task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
1659+ /* Mark the current process as normal process. */
1660+ else
1661+ task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
1662+ }
1663+ /* Tell GC that I finished execve(). */
1664+ task->ccs_flags &= ~CCS_TASK_IS_IN_EXECVE;
1665+ ccs_audit_free_execve(ee, true);
1666+ kfree(ee->handler_path);
1667+ kfree(ee);
1668+}
1669+
1670+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
1671+
1672+/**
1673+ * __ccs_search_binary_handler - Main routine for do_execve().
1674+ *
1675+ * @bprm: Pointer to "struct linux_binprm".
1676+ * @regs: Pointer to "struct pt_regs".
1677+ *
1678+ * Returns 0 on success, negative value otherwise.
1679+ *
1680+ * Performs permission checks for do_execve() and domain transition.
1681+ * Domain transition by "struct ccs_domain_transition_control" and
1682+ * "auto_domain_transition=" parameter of "struct ccs_condition" are reverted
1683+ * if do_execve() failed.
1684+ * Garbage collector does not remove "struct ccs_domain_info" from
1685+ * ccs_domain_list nor kfree("struct ccs_domain_info") if the current thread is
1686+ * marked as CCS_TASK_IS_IN_EXECVE.
1687+ */
1688+static int __ccs_search_binary_handler(struct linux_binprm *bprm,
1689+ struct pt_regs *regs)
1690+{
1691+ struct ccs_execve *ee;
1692+ int retval = ccs_start_execve(bprm, &ee);
1693+ if (!retval)
1694+ retval = search_binary_handler(bprm, regs);
1695+ ccs_finish_execve(retval, ee);
1696+ return retval;
1697+}
1698+
1699+#elif LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0)
1700+
1701+/**
1702+ * __ccs_search_binary_handler - Main routine for do_execve().
1703+ *
1704+ * @bprm: Pointer to "struct linux_binprm".
1705+ *
1706+ * Returns 0 on success, negative value otherwise.
1707+ *
1708+ * Performs permission checks for do_execve() and domain transition.
1709+ * Domain transition by "struct ccs_domain_transition_control" and
1710+ * "auto_domain_transition=" parameter of "struct ccs_condition" are reverted
1711+ * if do_execve() failed.
1712+ * Garbage collector does not remove "struct ccs_domain_info" from
1713+ * ccs_domain_list nor kfree("struct ccs_domain_info") if the current thread is
1714+ * marked as CCS_TASK_IS_IN_EXECVE.
1715+ */
1716+static int __ccs_search_binary_handler(struct linux_binprm *bprm)
1717+{
1718+ struct ccs_execve *ee;
1719+ int retval = ccs_start_execve(bprm, &ee);
1720+ if (!retval)
1721+ retval = search_binary_handler(bprm);
1722+ ccs_finish_execve(retval, ee);
1723+ return retval;
1724+}
1725+
1726+#endif
1727+
1728+/**
1729+ * ccs_permission_init - Register permission check hooks.
1730+ *
1731+ * Returns nothing.
1732+ */
1733+void __init ccs_permission_init(void)
1734+{
1735+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
1736+ ccsecurity_ops.save_open_mode = __ccs_save_open_mode;
1737+ ccsecurity_ops.clear_open_mode = __ccs_clear_open_mode;
1738+ ccsecurity_ops.open_permission = __ccs_open_permission;
1739+#else
1740+ ccsecurity_ops.open_permission = ccs_new_open_permission;
1741+#endif
1742+ ccsecurity_ops.fcntl_permission = __ccs_fcntl_permission;
1743+ ccsecurity_ops.ioctl_permission = __ccs_ioctl_permission;
1744+ ccsecurity_ops.chmod_permission = __ccs_chmod_permission;
1745+ ccsecurity_ops.chown_permission = __ccs_chown_permission;
1746+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
1747+ ccsecurity_ops.getattr_permission = __ccs_getattr_permission;
1748+#endif
1749+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1750+ ccsecurity_ops.pivot_root_permission = __ccs_pivot_root_permission;
1751+ ccsecurity_ops.chroot_permission = __ccs_chroot_permission;
1752+#else
1753+ ccsecurity_ops.pivot_root_permission = ccs_old_pivot_root_permission;
1754+ ccsecurity_ops.chroot_permission = ccs_old_chroot_permission;
1755+#endif
1756+ ccsecurity_ops.umount_permission = __ccs_umount_permission;
1757+ ccsecurity_ops.mknod_permission = __ccs_mknod_permission;
1758+ ccsecurity_ops.mkdir_permission = __ccs_mkdir_permission;
1759+ ccsecurity_ops.rmdir_permission = __ccs_rmdir_permission;
1760+ ccsecurity_ops.unlink_permission = __ccs_unlink_permission;
1761+ ccsecurity_ops.symlink_permission = __ccs_symlink_permission;
1762+ ccsecurity_ops.truncate_permission = __ccs_truncate_permission;
1763+ ccsecurity_ops.rename_permission = __ccs_rename_permission;
1764+ ccsecurity_ops.link_permission = __ccs_link_permission;
1765+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1766+ ccsecurity_ops.open_exec_permission = __ccs_open_exec_permission;
1767+ ccsecurity_ops.uselib_permission = __ccs_uselib_permission;
1768+#endif
1769+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
1770+ ccsecurity_ops.parse_table = __ccs_parse_table;
1771+#endif
1772+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1773+ ccsecurity_ops.mount_permission = __ccs_mount_permission;
1774+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
1775+ ccsecurity_ops.move_mount_permission = __ccs_move_mount_permission;
1776+#endif
1777+#else
1778+ ccsecurity_ops.mount_permission = ccs_old_mount_permission;
1779+#endif
1780+#ifdef CONFIG_CCSECURITY_CAPABILITY
1781+ ccsecurity_ops.socket_create_permission =
1782+ __ccs_socket_create_permission;
1783+#endif
1784+#ifdef CONFIG_CCSECURITY_NETWORK
1785+ ccsecurity_ops.socket_listen_permission =
1786+ __ccs_socket_listen_permission;
1787+ ccsecurity_ops.socket_connect_permission =
1788+ __ccs_socket_connect_permission;
1789+ ccsecurity_ops.socket_bind_permission = __ccs_socket_bind_permission;
1790+ ccsecurity_ops.socket_post_accept_permission =
1791+ __ccs_socket_post_accept_permission;
1792+ ccsecurity_ops.socket_sendmsg_permission =
1793+ __ccs_socket_sendmsg_permission;
1794+#endif
1795+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
1796+ ccsecurity_ops.socket_post_recvmsg_permission =
1797+ __ccs_socket_post_recvmsg_permission;
1798+#endif
1799+#ifdef CONFIG_CCSECURITY_IPC
1800+ ccsecurity_ops.kill_permission = ccs_signal_acl;
1801+ ccsecurity_ops.tgkill_permission = ccs_signal_acl0;
1802+ ccsecurity_ops.tkill_permission = ccs_signal_acl;
1803+ ccsecurity_ops.sigqueue_permission = ccs_signal_acl;
1804+ ccsecurity_ops.tgsigqueue_permission = ccs_signal_acl0;
1805+#endif
1806+#ifdef CONFIG_CCSECURITY_CAPABILITY
1807+ ccsecurity_ops.capable = __ccs_capable;
1808+ ccsecurity_ops.ptrace_permission = __ccs_ptrace_permission;
1809+#endif
1810+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
1811+ ccsecurity_ops.finish_execve = ccs_finish_execve;
1812+ ccsecurity_ops.start_execve = ccs_start_execve;
1813+#else
1814+ ccsecurity_ops.search_binary_handler = __ccs_search_binary_handler;
1815+#endif
1816+}
1817+
1818+/**
1819+ * ccs_kern_path - Wrapper for kern_path().
1820+ *
1821+ * @pathname: Pathname to resolve. Maybe NULL.
1822+ * @flags: Lookup flags.
1823+ * @path: Pointer to "struct path".
1824+ *
1825+ * Returns 0 on success, negative value otherwise.
1826+ */
1827+static int ccs_kern_path(const char *pathname, int flags, struct path *path)
1828+{
1829+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
1830+ if (!pathname || kern_path(pathname, flags, path))
1831+ return -ENOENT;
1832+#else
1833+ struct nameidata nd;
1834+ if (!pathname || path_lookup(pathname, flags, &nd))
1835+ return -ENOENT;
1836+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1837+ *path = nd.path;
1838+#else
1839+ path->dentry = nd.dentry;
1840+ path->mnt = nd.mnt;
1841+#endif
1842+#endif
1843+ return 0;
1844+}
1845+
1846+/**
1847+ * ccs_get_path - Get dentry/vfsmmount of a pathname.
1848+ *
1849+ * @pathname: The pathname to solve. Maybe NULL.
1850+ * @path: Pointer to "struct path".
1851+ *
1852+ * Returns 0 on success, negative value otherwise.
1853+ */
1854+static int ccs_get_path(const char *pathname, struct path *path)
1855+{
1856+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1857+ return ccs_kern_path(pathname, LOOKUP_FOLLOW, path);
1858+#else
1859+ return ccs_kern_path(pathname, LOOKUP_FOLLOW | LOOKUP_POSITIVE, path);
1860+#endif
1861+}
1862+
1863+/**
1864+ * ccs_symlink_path - Get symlink's pathname.
1865+ *
1866+ * @pathname: The pathname to solve. Maybe NULL.
1867+ * @name: Pointer to "struct ccs_path_info".
1868+ *
1869+ * Returns 0 on success, negative value otherwise.
1870+ *
1871+ * This function uses kzalloc(), so caller must kfree() if this function
1872+ * didn't return NULL.
1873+ */
1874+static int ccs_symlink_path(const char *pathname, struct ccs_path_info *name)
1875+{
1876+ char *buf;
1877+ struct path path;
1878+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1879+ if (ccs_kern_path(pathname, 0, &path))
1880+ return -ENOENT;
1881+#else
1882+ if (ccs_kern_path(pathname, LOOKUP_POSITIVE, &path))
1883+ return -ENOENT;
1884+#endif
1885+ buf = ccs_realpath(&path);
1886+ path_put(&path);
1887+ if (buf) {
1888+ name->name = buf;
1889+ ccs_fill_path_info(name);
1890+ return 0;
1891+ }
1892+ return -ENOMEM;
1893+}
1894+
1895+/**
1896+ * ccs_check_mount_acl - Check permission for path path path number operation.
1897+ *
1898+ * @r: Pointer to "struct ccs_request_info".
1899+ * @ptr: Pointer to "struct ccs_acl_info".
1900+ *
1901+ * Returns true if granted, false otherwise.
1902+ */
1903+static bool ccs_check_mount_acl(struct ccs_request_info *r,
1904+ const struct ccs_acl_info *ptr)
1905+{
1906+ const struct ccs_mount_acl *acl =
1907+ container_of(ptr, typeof(*acl), head);
1908+ return ccs_compare_number_union(r->param.mount.flags, &acl->flags) &&
1909+ ccs_compare_name_union(r->param.mount.type, &acl->fs_type) &&
1910+ ccs_compare_name_union(r->param.mount.dir, &acl->dir_name) &&
1911+ (!r->param.mount.need_dev ||
1912+ ccs_compare_name_union(r->param.mount.dev, &acl->dev_name));
1913+}
1914+
1915+/**
1916+ * ccs_mount_acl - Check permission for mount() operation.
1917+ *
1918+ * @r: Pointer to "struct ccs_request_info".
1919+ * @dev_name: Name of device file. Maybe NULL.
1920+ * @dir: Pointer to "struct path".
1921+ * @type: Name of filesystem type.
1922+ * @flags: Mount options.
1923+ *
1924+ * Returns 0 on success, negative value otherwise.
1925+ *
1926+ * Caller holds ccs_read_lock().
1927+ */
1928+static int ccs_mount_acl(struct ccs_request_info *r, const char *dev_name,
1929+ const struct path *dir, const char *type,
1930+ unsigned long flags)
1931+{
1932+ struct ccs_obj_info obj = { };
1933+ struct file_system_type *fstype = NULL;
1934+ const char *requested_type = NULL;
1935+ const char *requested_dir_name = NULL;
1936+ const char *requested_dev_name = NULL;
1937+ struct ccs_path_info rtype;
1938+ struct ccs_path_info rdev;
1939+ struct ccs_path_info rdir;
1940+ int need_dev = 0;
1941+ int error = -ENOMEM;
1942+ r->obj = &obj;
1943+
1944+ /* Get fstype. */
1945+ requested_type = ccs_encode(type);
1946+ if (!requested_type)
1947+ goto out;
1948+ rtype.name = requested_type;
1949+ ccs_fill_path_info(&rtype);
1950+
1951+ /* Get mount point. */
1952+ obj.path2 = *dir;
1953+ requested_dir_name = ccs_realpath(dir);
1954+ if (!requested_dir_name) {
1955+ error = -ENOMEM;
1956+ goto out;
1957+ }
1958+ rdir.name = requested_dir_name;
1959+ ccs_fill_path_info(&rdir);
1960+
1961+ /* Compare fs name. */
1962+ if (type == ccs_mounts[CCS_MOUNT_REMOUNT]) {
1963+ /* dev_name is ignored. */
1964+ } else if (type == ccs_mounts[CCS_MOUNT_MAKE_UNBINDABLE] ||
1965+ type == ccs_mounts[CCS_MOUNT_MAKE_PRIVATE] ||
1966+ type == ccs_mounts[CCS_MOUNT_MAKE_SLAVE] ||
1967+ type == ccs_mounts[CCS_MOUNT_MAKE_SHARED]) {
1968+ /* dev_name is ignored. */
1969+ } else if (type == ccs_mounts[CCS_MOUNT_BIND] ||
1970+ type == ccs_mounts[CCS_MOUNT_MOVE]) {
1971+ need_dev = -1; /* dev_name is a directory */
1972+ } else {
1973+ fstype = get_fs_type(type);
1974+ if (!fstype) {
1975+ error = -ENODEV;
1976+ goto out;
1977+ }
1978+ if (fstype->fs_flags & FS_REQUIRES_DEV)
1979+ /* dev_name is a block device file. */
1980+ need_dev = 1;
1981+ }
1982+ if (need_dev) {
1983+ /* Get mount point or device file. */
1984+ if (ccs_get_path(dev_name, &obj.path1)) {
1985+ error = -ENOENT;
1986+ goto out;
1987+ }
1988+ requested_dev_name = ccs_realpath(&obj.path1);
1989+ if (!requested_dev_name) {
1990+ error = -ENOENT;
1991+ goto out;
1992+ }
1993+ } else {
1994+ /* Map dev_name to "<NULL>" if no dev_name given. */
1995+ if (!dev_name)
1996+ dev_name = "<NULL>";
1997+ requested_dev_name = ccs_encode(dev_name);
1998+ if (!requested_dev_name) {
1999+ error = -ENOMEM;
2000+ goto out;
2001+ }
2002+ }
2003+ rdev.name = requested_dev_name;
2004+ ccs_fill_path_info(&rdev);
2005+ r->param_type = CCS_TYPE_MOUNT_ACL;
2006+ r->param.mount.need_dev = need_dev;
2007+ r->param.mount.dev = &rdev;
2008+ r->param.mount.dir = &rdir;
2009+ r->param.mount.type = &rtype;
2010+ r->param.mount.flags = flags;
2011+ error = ccs_check_acl(r);
2012+out:
2013+ kfree(requested_dev_name);
2014+ kfree(requested_dir_name);
2015+ if (fstype)
2016+ ccs_put_filesystem(fstype);
2017+ kfree(requested_type);
2018+ /* Drop refcount obtained by ccs_get_path(). */
2019+ if (obj.path1.dentry)
2020+ path_put(&obj.path1);
2021+ return error;
2022+}
2023+
2024+/**
2025+ * __ccs_mount_permission - Check permission for mount() operation.
2026+ *
2027+ * @dev_name: Name of device file. Maybe NULL.
2028+ * @path: Pointer to "struct path".
2029+ * @type: Name of filesystem type. Maybe NULL.
2030+ * @flags: Mount options.
2031+ * @data_page: Optional data. Maybe NULL.
2032+ *
2033+ * Returns 0 on success, negative value otherwise.
2034+ */
2035+static int __ccs_mount_permission(const char *dev_name,
2036+ const struct path *path, const char *type,
2037+ unsigned long flags, void *data_page)
2038+{
2039+ struct ccs_request_info r;
2040+ int error = 0;
2041+ int idx;
2042+ if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
2043+ flags &= ~MS_MGC_MSK;
2044+ if (flags & MS_REMOUNT) {
2045+ type = ccs_mounts[CCS_MOUNT_REMOUNT];
2046+ flags &= ~MS_REMOUNT;
2047+ } else if (flags & MS_BIND) {
2048+ type = ccs_mounts[CCS_MOUNT_BIND];
2049+ flags &= ~MS_BIND;
2050+ } else if (flags & MS_SHARED) {
2051+ if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
2052+ return -EINVAL;
2053+ type = ccs_mounts[CCS_MOUNT_MAKE_SHARED];
2054+ flags &= ~MS_SHARED;
2055+ } else if (flags & MS_PRIVATE) {
2056+ if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
2057+ return -EINVAL;
2058+ type = ccs_mounts[CCS_MOUNT_MAKE_PRIVATE];
2059+ flags &= ~MS_PRIVATE;
2060+ } else if (flags & MS_SLAVE) {
2061+ if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
2062+ return -EINVAL;
2063+ type = ccs_mounts[CCS_MOUNT_MAKE_SLAVE];
2064+ flags &= ~MS_SLAVE;
2065+ } else if (flags & MS_UNBINDABLE) {
2066+ if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
2067+ return -EINVAL;
2068+ type = ccs_mounts[CCS_MOUNT_MAKE_UNBINDABLE];
2069+ flags &= ~MS_UNBINDABLE;
2070+ } else if (flags & MS_MOVE) {
2071+ type = ccs_mounts[CCS_MOUNT_MOVE];
2072+ flags &= ~MS_MOVE;
2073+ }
2074+ if (!type)
2075+ type = "<NULL>";
2076+ idx = ccs_read_lock();
2077+ if (ccs_init_request_info(&r, CCS_MAC_FILE_MOUNT)
2078+ != CCS_CONFIG_DISABLED)
2079+ error = ccs_mount_acl(&r, dev_name, path, type, flags);
2080+ ccs_read_unlock(idx);
2081+ return error;
2082+}
2083+
2084+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
2085+
2086+/**
2087+ * ccs_old_mount_permission - Check permission for mount() operation.
2088+ *
2089+ * @dev_name: Name of device file.
2090+ * @nd: Pointer to "struct nameidata".
2091+ * @type: Name of filesystem type. Maybe NULL.
2092+ * @flags: Mount options.
2093+ * @data_page: Optional data. Maybe NULL.
2094+ *
2095+ * Returns 0 on success, negative value otherwise.
2096+ */
2097+static int ccs_old_mount_permission(const char *dev_name, struct nameidata *nd,
2098+ const char *type, unsigned long flags,
2099+ void *data_page)
2100+{
2101+ struct path path = { nd->mnt, nd->dentry };
2102+ return __ccs_mount_permission(dev_name, &path, type, flags, data_page);
2103+}
2104+
2105+#endif
2106+
2107+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
2108+/**
2109+ * __ccs_move_mount_permission - Check permission for move_mount() operation.
2110+ *
2111+ * @from_path: Pointer to "struct path".
2112+ * @to_path: Pointer to "struct path".
2113+ *
2114+ * Returns 0 on success, negative value otherwise.
2115+ */
2116+static int __ccs_move_mount_permission(const struct path *from_path,
2117+ const struct path *to_path)
2118+{
2119+ return -ENOSYS; /* For now. */
2120+}
2121+#endif
2122+
2123+/**
2124+ * ccs_compare_number_union - Check whether a value matches "struct ccs_number_union" or not.
2125+ *
2126+ * @value: Number to check.
2127+ * @ptr: Pointer to "struct ccs_number_union".
2128+ *
2129+ * Returns true if @value matches @ptr, false otherwise.
2130+ */
2131+static bool ccs_compare_number_union(const unsigned long value,
2132+ const struct ccs_number_union *ptr)
2133+{
2134+ if (ptr->group)
2135+ return ccs_number_matches_group(value, value, ptr->group);
2136+ return value >= ptr->values[0] && value <= ptr->values[1];
2137+}
2138+
2139+/**
2140+ * ccs_compare_name_union - Check whether a name matches "struct ccs_name_union" or not.
2141+ *
2142+ * @name: Pointer to "struct ccs_path_info".
2143+ * @ptr: Pointer to "struct ccs_name_union".
2144+ *
2145+ * Returns "struct ccs_path_info" if @name matches @ptr, NULL otherwise.
2146+ */
2147+static const struct ccs_path_info *ccs_compare_name_union
2148+(const struct ccs_path_info *name, const struct ccs_name_union *ptr)
2149+{
2150+ if (ptr->group)
2151+ return ccs_path_matches_group(name, ptr->group);
2152+ if (ccs_path_matches_pattern(name, ptr->filename))
2153+ return ptr->filename;
2154+ return NULL;
2155+}
2156+
2157+/**
2158+ * ccs_add_slash - Add trailing '/' if needed.
2159+ *
2160+ * @buf: Pointer to "struct ccs_path_info".
2161+ *
2162+ * Returns nothing.
2163+ *
2164+ * @buf must be generated by ccs_encode() because this function does not
2165+ * allocate memory for adding '/'.
2166+ */
2167+static void ccs_add_slash(struct ccs_path_info *buf)
2168+{
2169+ if (buf->is_dir)
2170+ return;
2171+ /* This is OK because ccs_encode() reserves space for appending "/". */
2172+ strcat((char *) buf->name, "/");
2173+ ccs_fill_path_info(buf);
2174+}
2175+
2176+/**
2177+ * ccs_get_realpath - Get realpath.
2178+ *
2179+ * @buf: Pointer to "struct ccs_path_info".
2180+ * @path: Pointer to "struct path". @path->mnt may be NULL.
2181+ *
2182+ * Returns true on success, false otherwise.
2183+ */
2184+static bool ccs_get_realpath(struct ccs_path_info *buf, struct path *path)
2185+{
2186+ buf->name = ccs_realpath(path);
2187+ if (buf->name) {
2188+ ccs_fill_path_info(buf);
2189+ return true;
2190+ }
2191+ return false;
2192+}
2193+
2194+/**
2195+ * ccs_check_path_acl - Check permission for path operation.
2196+ *
2197+ * @r: Pointer to "struct ccs_request_info".
2198+ * @ptr: Pointer to "struct ccs_acl_info".
2199+ *
2200+ * Returns true if granted, false otherwise.
2201+ *
2202+ * To be able to use wildcard for domain transition, this function sets
2203+ * matching entry on success. Since the caller holds ccs_read_lock(),
2204+ * it is safe to set matching entry.
2205+ */
2206+static bool ccs_check_path_acl(struct ccs_request_info *r,
2207+ const struct ccs_acl_info *ptr)
2208+{
2209+ const struct ccs_path_acl *acl = container_of(ptr, typeof(*acl), head);
2210+ if (ptr->perm & (1 << r->param.path.operation)) {
2211+ r->param.path.matched_path =
2212+ ccs_compare_name_union(r->param.path.filename,
2213+ &acl->name);
2214+ return r->param.path.matched_path != NULL;
2215+ }
2216+ return false;
2217+}
2218+
2219+/**
2220+ * ccs_check_path_number_acl - Check permission for path number operation.
2221+ *
2222+ * @r: Pointer to "struct ccs_request_info".
2223+ * @ptr: Pointer to "struct ccs_acl_info".
2224+ *
2225+ * Returns true if granted, false otherwise.
2226+ */
2227+static bool ccs_check_path_number_acl(struct ccs_request_info *r,
2228+ const struct ccs_acl_info *ptr)
2229+{
2230+ const struct ccs_path_number_acl *acl =
2231+ container_of(ptr, typeof(*acl), head);
2232+ return (ptr->perm & (1 << r->param.path_number.operation)) &&
2233+ ccs_compare_number_union(r->param.path_number.number,
2234+ &acl->number) &&
2235+ ccs_compare_name_union(r->param.path_number.filename,
2236+ &acl->name);
2237+}
2238+
2239+/**
2240+ * ccs_check_path2_acl - Check permission for path path operation.
2241+ *
2242+ * @r: Pointer to "struct ccs_request_info".
2243+ * @ptr: Pointer to "struct ccs_acl_info".
2244+ *
2245+ * Returns true if granted, false otherwise.
2246+ */
2247+static bool ccs_check_path2_acl(struct ccs_request_info *r,
2248+ const struct ccs_acl_info *ptr)
2249+{
2250+ const struct ccs_path2_acl *acl =
2251+ container_of(ptr, typeof(*acl), head);
2252+ return (ptr->perm & (1 << r->param.path2.operation)) &&
2253+ ccs_compare_name_union(r->param.path2.filename1, &acl->name1)
2254+ && ccs_compare_name_union(r->param.path2.filename2,
2255+ &acl->name2);
2256+}
2257+
2258+/**
2259+ * ccs_check_mkdev_acl - Check permission for path number number number operation.
2260+ *
2261+ * @r: Pointer to "struct ccs_request_info".
2262+ * @ptr: Pointer to "struct ccs_acl_info".
2263+ *
2264+ * Returns true if granted, false otherwise.
2265+ */
2266+static bool ccs_check_mkdev_acl(struct ccs_request_info *r,
2267+ const struct ccs_acl_info *ptr)
2268+{
2269+ const struct ccs_mkdev_acl *acl =
2270+ container_of(ptr, typeof(*acl), head);
2271+ return (ptr->perm & (1 << r->param.mkdev.operation)) &&
2272+ ccs_compare_number_union(r->param.mkdev.mode, &acl->mode) &&
2273+ ccs_compare_number_union(r->param.mkdev.major, &acl->major) &&
2274+ ccs_compare_number_union(r->param.mkdev.minor, &acl->minor) &&
2275+ ccs_compare_name_union(r->param.mkdev.filename, &acl->name);
2276+}
2277+
2278+/**
2279+ * ccs_path_permission - Check permission for path operation.
2280+ *
2281+ * @r: Pointer to "struct ccs_request_info".
2282+ * @operation: Type of operation.
2283+ * @filename: Filename to check.
2284+ *
2285+ * Returns 0 on success, negative value otherwise.
2286+ *
2287+ * Caller holds ccs_read_lock().
2288+ */
2289+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21) || LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) || !defined(CONFIG_SYSCTL_SYSCALL)
2290+static
2291+#endif
2292+int ccs_path_permission(struct ccs_request_info *r, u8 operation,
2293+ const struct ccs_path_info *filename)
2294+{
2295+ r->type = ccs_p2mac[operation];
2296+ r->mode = ccs_get_mode(r->profile, r->type);
2297+ if (r->mode == CCS_CONFIG_DISABLED)
2298+ return 0;
2299+ r->param_type = CCS_TYPE_PATH_ACL;
2300+ r->param.path.filename = filename;
2301+ r->param.path.operation = operation;
2302+ return ccs_check_acl(r);
2303+}
2304+
2305+/**
2306+ * ccs_execute_permission - Check permission for execute operation.
2307+ *
2308+ * @r: Pointer to "struct ccs_request_info".
2309+ * @filename: Filename to check.
2310+ *
2311+ * Returns 0 on success, CCS_RETRY_REQUEST on retry, negative value otherwise.
2312+ *
2313+ * Caller holds ccs_read_lock().
2314+ */
2315+static int ccs_execute_permission(struct ccs_request_info *r,
2316+ const struct ccs_path_info *filename)
2317+{
2318+ int error;
2319+ /*
2320+ * Unlike other permission checks, this check is done regardless of
2321+ * profile mode settings in order to check for domain transition
2322+ * preference.
2323+ */
2324+ r->type = CCS_MAC_FILE_EXECUTE;
2325+ r->mode = ccs_get_mode(r->profile, r->type);
2326+ r->param_type = CCS_TYPE_PATH_ACL;
2327+ r->param.path.filename = filename;
2328+ r->param.path.operation = CCS_TYPE_EXECUTE;
2329+ error = ccs_check_acl(r);
2330+ r->ee->transition = r->matched_acl && r->matched_acl->cond &&
2331+ r->matched_acl->cond->exec_transit ?
2332+ r->matched_acl->cond->transit : NULL;
2333+ return error;
2334+}
2335+
2336+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
2337+
2338+/**
2339+ * __ccs_save_open_mode - Remember original flags passed to sys_open().
2340+ *
2341+ * @mode: Flags passed to sys_open().
2342+ *
2343+ * Returns nothing.
2344+ *
2345+ * TOMOYO does not check "file write" if open(path, O_TRUNC | O_RDONLY) was
2346+ * requested because write() is not permitted. Instead, TOMOYO checks
2347+ * "file truncate" if O_TRUNC is passed.
2348+ *
2349+ * TOMOYO does not check "file read" and "file write" if open(path, 3) was
2350+ * requested because read()/write() are not permitted. Instead, TOMOYO checks
2351+ * "file ioctl" when ioctl() is requested.
2352+ */
2353+static void __ccs_save_open_mode(int mode)
2354+{
2355+ if ((mode & 3) == 3)
2356+ ccs_current_security()->ccs_flags |= CCS_OPEN_FOR_IOCTL_ONLY;
2357+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 14)
2358+ /* O_TRUNC passes MAY_WRITE to ccs_open_permission(). */
2359+ else if (!(mode & 3) && (mode & O_TRUNC))
2360+ ccs_current_security()->ccs_flags |=
2361+ CCS_OPEN_FOR_READ_TRUNCATE;
2362+#endif
2363+}
2364+
2365+/**
2366+ * __ccs_clear_open_mode - Forget original flags passed to sys_open().
2367+ *
2368+ * Returns nothing.
2369+ */
2370+static void __ccs_clear_open_mode(void)
2371+{
2372+ ccs_current_security()->ccs_flags &= ~(CCS_OPEN_FOR_IOCTL_ONLY |
2373+ CCS_OPEN_FOR_READ_TRUNCATE);
2374+}
2375+
2376+#endif
2377+
2378+/**
2379+ * __ccs_open_permission - Check permission for "read" and "write".
2380+ *
2381+ * @dentry: Pointer to "struct dentry".
2382+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2383+ * @flag: Flags for open().
2384+ *
2385+ * Returns 0 on success, negative value otherwise.
2386+ */
2387+static int __ccs_open_permission(struct dentry *dentry, struct vfsmount *mnt,
2388+ const int flag)
2389+{
2390+ struct ccs_request_info r;
2391+ struct ccs_obj_info obj = {
2392+ .path1.dentry = dentry,
2393+ .path1.mnt = mnt,
2394+ };
2395+ const u32 ccs_flags = ccs_current_flags();
2396+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
2397+ const u8 acc_mode = (flag & 3) == 3 ? 0 : ACC_MODE(flag);
2398+#else
2399+ const u8 acc_mode = (ccs_flags & CCS_OPEN_FOR_IOCTL_ONLY) ? 0 :
2400+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 14)
2401+ (ccs_flags & CCS_OPEN_FOR_READ_TRUNCATE) ? 4 :
2402+#endif
2403+ ACC_MODE(flag);
2404+#endif
2405+ int error = 0;
2406+ struct ccs_path_info buf;
2407+ int idx;
2408+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
2409+ if (current->in_execve && !(ccs_flags & CCS_TASK_IS_IN_EXECVE))
2410+ return 0;
2411+#endif
2412+#ifndef CONFIG_CCSECURITY_FILE_READDIR
2413+ if (d_is_dir(dentry))
2414+ return 0;
2415+#endif
2416+ buf.name = NULL;
2417+ r.mode = CCS_CONFIG_DISABLED;
2418+ idx = ccs_read_lock();
2419+ if (acc_mode && ccs_init_request_info(&r, CCS_MAC_FILE_OPEN)
2420+ != CCS_CONFIG_DISABLED) {
2421+ if (!ccs_get_realpath(&buf, &obj.path1)) {
2422+ error = -ENOMEM;
2423+ goto out;
2424+ }
2425+ r.obj = &obj;
2426+ if (acc_mode & MAY_READ)
2427+ error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
2428+ if (!error && (acc_mode & MAY_WRITE))
2429+ error = ccs_path_permission(&r, (flag & O_APPEND) ?
2430+ CCS_TYPE_APPEND :
2431+ CCS_TYPE_WRITE, &buf);
2432+ }
2433+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
2434+ if (!error && (flag & O_TRUNC) &&
2435+ ccs_init_request_info(&r, CCS_MAC_FILE_TRUNCATE)
2436+ != CCS_CONFIG_DISABLED) {
2437+ if (!buf.name && !ccs_get_realpath(&buf, &obj.path1)) {
2438+ error = -ENOMEM;
2439+ goto out;
2440+ }
2441+ r.obj = &obj;
2442+ error = ccs_path_permission(&r, CCS_TYPE_TRUNCATE, &buf);
2443+ }
2444+#endif
2445+out:
2446+ kfree(buf.name);
2447+ ccs_read_unlock(idx);
2448+ if (r.mode != CCS_CONFIG_ENFORCING)
2449+ error = 0;
2450+ return error;
2451+}
2452+
2453+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
2454+
2455+/**
2456+ * ccs_new_open_permission - Check permission for "read" and "write".
2457+ *
2458+ * @filp: Pointer to "struct file".
2459+ *
2460+ * Returns 0 on success, negative value otherwise.
2461+ */
2462+static int ccs_new_open_permission(struct file *filp)
2463+{
2464+ return __ccs_open_permission(filp->f_path.dentry, filp->f_path.mnt,
2465+ filp->f_flags);
2466+}
2467+
2468+#endif
2469+
2470+/**
2471+ * ccs_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "getattr", "chroot" and "unmount".
2472+ *
2473+ * @operation: Type of operation.
2474+ * @dentry: Pointer to "struct dentry".
2475+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2476+ * @target: Symlink's target if @operation is CCS_TYPE_SYMLINK,
2477+ * NULL otherwise.
2478+ *
2479+ * Returns 0 on success, negative value otherwise.
2480+ */
2481+static int ccs_path_perm(const u8 operation, struct dentry *dentry,
2482+ struct vfsmount *mnt, const char *target)
2483+{
2484+ struct ccs_request_info r;
2485+ struct ccs_obj_info obj = {
2486+ .path1.dentry = dentry,
2487+ .path1.mnt = mnt,
2488+ };
2489+ int error = 0;
2490+ struct ccs_path_info buf;
2491+ bool is_enforce = false;
2492+ struct ccs_path_info symlink_target;
2493+ int idx;
2494+ buf.name = NULL;
2495+ symlink_target.name = NULL;
2496+ idx = ccs_read_lock();
2497+ if (ccs_init_request_info(&r, ccs_p2mac[operation])
2498+ == CCS_CONFIG_DISABLED)
2499+ goto out;
2500+ is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
2501+ error = -ENOMEM;
2502+ if (!ccs_get_realpath(&buf, &obj.path1))
2503+ goto out;
2504+ r.obj = &obj;
2505+ switch (operation) {
2506+ case CCS_TYPE_RMDIR:
2507+ case CCS_TYPE_CHROOT:
2508+ ccs_add_slash(&buf);
2509+ break;
2510+ case CCS_TYPE_SYMLINK:
2511+ symlink_target.name = ccs_encode(target);
2512+ if (!symlink_target.name)
2513+ goto out;
2514+ ccs_fill_path_info(&symlink_target);
2515+ obj.symlink_target = &symlink_target;
2516+ break;
2517+ }
2518+ error = ccs_path_permission(&r, operation, &buf);
2519+ if (operation == CCS_TYPE_SYMLINK)
2520+ kfree(symlink_target.name);
2521+out:
2522+ kfree(buf.name);
2523+ ccs_read_unlock(idx);
2524+ if (!is_enforce)
2525+ error = 0;
2526+ return error;
2527+}
2528+
2529+/**
2530+ * ccs_mkdev_perm - Check permission for "mkblock" and "mkchar".
2531+ *
2532+ * @operation: Type of operation. (CCS_TYPE_MKCHAR or CCS_TYPE_MKBLOCK)
2533+ * @dentry: Pointer to "struct dentry".
2534+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2535+ * @mode: Create mode.
2536+ * @dev: Device number.
2537+ *
2538+ * Returns 0 on success, negative value otherwise.
2539+ */
2540+static int ccs_mkdev_perm(const u8 operation, struct dentry *dentry,
2541+ struct vfsmount *mnt, const unsigned int mode,
2542+ unsigned int dev)
2543+{
2544+ struct ccs_request_info r;
2545+ struct ccs_obj_info obj = {
2546+ .path1.dentry = dentry,
2547+ .path1.mnt = mnt,
2548+ };
2549+ int error = 0;
2550+ struct ccs_path_info buf;
2551+ bool is_enforce = false;
2552+ int idx;
2553+ idx = ccs_read_lock();
2554+ if (ccs_init_request_info(&r, ccs_pnnn2mac[operation])
2555+ == CCS_CONFIG_DISABLED)
2556+ goto out;
2557+ is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
2558+ error = -EPERM;
2559+ if (!capable(CAP_MKNOD))
2560+ goto out;
2561+ error = -ENOMEM;
2562+ if (!ccs_get_realpath(&buf, &obj.path1))
2563+ goto out;
2564+ r.obj = &obj;
2565+#ifdef CONFIG_SECURITY_PATH
2566+ dev = new_decode_dev(dev);
2567+#endif
2568+ r.param_type = CCS_TYPE_MKDEV_ACL;
2569+ r.param.mkdev.filename = &buf;
2570+ r.param.mkdev.operation = operation;
2571+ r.param.mkdev.mode = mode;
2572+ r.param.mkdev.major = MAJOR(dev);
2573+ r.param.mkdev.minor = MINOR(dev);
2574+ error = ccs_check_acl(&r);
2575+ kfree(buf.name);
2576+out:
2577+ ccs_read_unlock(idx);
2578+ if (!is_enforce)
2579+ error = 0;
2580+ return error;
2581+}
2582+
2583+/**
2584+ * ccs_path2_perm - Check permission for "rename", "link" and "pivot_root".
2585+ *
2586+ * @operation: Type of operation.
2587+ * @dentry1: Pointer to "struct dentry".
2588+ * @mnt1: Pointer to "struct vfsmount". Maybe NULL.
2589+ * @dentry2: Pointer to "struct dentry".
2590+ * @mnt2: Pointer to "struct vfsmount". Maybe NULL.
2591+ *
2592+ * Returns 0 on success, negative value otherwise.
2593+ */
2594+static int ccs_path2_perm(const u8 operation, struct dentry *dentry1,
2595+ struct vfsmount *mnt1, struct dentry *dentry2,
2596+ struct vfsmount *mnt2)
2597+{
2598+ struct ccs_request_info r;
2599+ int error = 0;
2600+ struct ccs_path_info buf1;
2601+ struct ccs_path_info buf2;
2602+ bool is_enforce = false;
2603+ struct ccs_obj_info obj = {
2604+ .path1.dentry = dentry1,
2605+ .path1.mnt = mnt1,
2606+ .path2.dentry = dentry2,
2607+ .path2.mnt = mnt2,
2608+ };
2609+ int idx;
2610+ buf1.name = NULL;
2611+ buf2.name = NULL;
2612+ idx = ccs_read_lock();
2613+ if (ccs_init_request_info(&r, ccs_pp2mac[operation])
2614+ == CCS_CONFIG_DISABLED)
2615+ goto out;
2616+ is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
2617+ error = -ENOMEM;
2618+ if (!ccs_get_realpath(&buf1, &obj.path1) ||
2619+ !ccs_get_realpath(&buf2, &obj.path2))
2620+ goto out;
2621+ switch (operation) {
2622+ case CCS_TYPE_RENAME:
2623+ case CCS_TYPE_LINK:
2624+ if (!d_is_dir(dentry1))
2625+ break;
2626+ /* fall through */
2627+ fallthrough;
2628+ case CCS_TYPE_PIVOT_ROOT:
2629+ ccs_add_slash(&buf1);
2630+ ccs_add_slash(&buf2);
2631+ break;
2632+ }
2633+ r.obj = &obj;
2634+ r.param_type = CCS_TYPE_PATH2_ACL;
2635+ r.param.path2.operation = operation;
2636+ r.param.path2.filename1 = &buf1;
2637+ r.param.path2.filename2 = &buf2;
2638+ error = ccs_check_acl(&r);
2639+out:
2640+ kfree(buf1.name);
2641+ kfree(buf2.name);
2642+ ccs_read_unlock(idx);
2643+ if (!is_enforce)
2644+ error = 0;
2645+ return error;
2646+}
2647+
2648+/**
2649+ * ccs_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
2650+ *
2651+ * @type: Type of operation.
2652+ * @dentry: Pointer to "struct dentry".
2653+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
2654+ * @number: Number.
2655+ *
2656+ * Returns 0 on success, negative value otherwise.
2657+ */
2658+static int ccs_path_number_perm(const u8 type, struct dentry *dentry,
2659+ struct vfsmount *vfsmnt, unsigned long number)
2660+{
2661+ struct ccs_request_info r;
2662+ struct ccs_obj_info obj = {
2663+ .path1.dentry = dentry,
2664+ .path1.mnt = vfsmnt,
2665+ };
2666+ int error = 0;
2667+ struct ccs_path_info buf;
2668+ int idx;
2669+ if (!dentry)
2670+ return 0;
2671+ idx = ccs_read_lock();
2672+ if (ccs_init_request_info(&r, ccs_pn2mac[type]) == CCS_CONFIG_DISABLED)
2673+ goto out;
2674+ error = -ENOMEM;
2675+ if (!ccs_get_realpath(&buf, &obj.path1))
2676+ goto out;
2677+ r.obj = &obj;
2678+ if (type == CCS_TYPE_MKDIR)
2679+ ccs_add_slash(&buf);
2680+ r.param_type = CCS_TYPE_PATH_NUMBER_ACL;
2681+ r.param.path_number.operation = type;
2682+ r.param.path_number.filename = &buf;
2683+ r.param.path_number.number = number;
2684+ error = ccs_check_acl(&r);
2685+ kfree(buf.name);
2686+out:
2687+ ccs_read_unlock(idx);
2688+ if (r.mode != CCS_CONFIG_ENFORCING)
2689+ error = 0;
2690+ return error;
2691+}
2692+
2693+/**
2694+ * __ccs_ioctl_permission - Check permission for "ioctl".
2695+ *
2696+ * @filp: Pointer to "struct file".
2697+ * @cmd: Ioctl command number.
2698+ * @arg: Param for @cmd.
2699+ *
2700+ * Returns 0 on success, negative value otherwise.
2701+ */
2702+static int __ccs_ioctl_permission(struct file *filp, unsigned int cmd,
2703+ unsigned long arg)
2704+{
2705+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
2706+ return ccs_path_number_perm(CCS_TYPE_IOCTL, filp->f_path.dentry,
2707+ filp->f_path.mnt, cmd);
2708+#else
2709+ return ccs_path_number_perm(CCS_TYPE_IOCTL, filp->f_dentry,
2710+ filp->f_vfsmnt, cmd);
2711+#endif
2712+}
2713+
2714+/**
2715+ * __ccs_chmod_permission - Check permission for "chmod".
2716+ *
2717+ * @dentry: Pointer to "struct dentry".
2718+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
2719+ * @mode: Mode.
2720+ *
2721+ * Returns 0 on success, negative value otherwise.
2722+ */
2723+static int __ccs_chmod_permission(struct dentry *dentry,
2724+ struct vfsmount *vfsmnt, mode_t mode)
2725+{
2726+ return ccs_path_number_perm(CCS_TYPE_CHMOD, dentry, vfsmnt,
2727+ mode & S_IALLUGO);
2728+}
2729+
2730+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
2731+
2732+/**
2733+ * __ccs_chown_permission - Check permission for "chown/chgrp".
2734+ *
2735+ * @dentry: Pointer to "struct dentry".
2736+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
2737+ * @user: User ID.
2738+ * @group: Group ID.
2739+ *
2740+ * Returns 0 on success, negative value otherwise.
2741+ */
2742+static int __ccs_chown_permission(struct dentry *dentry,
2743+ struct vfsmount *vfsmnt, kuid_t user,
2744+ kgid_t group)
2745+{
2746+ int error = 0;
2747+ if (uid_valid(user))
2748+ error = ccs_path_number_perm(CCS_TYPE_CHOWN, dentry, vfsmnt,
2749+ from_kuid(&init_user_ns, user));
2750+ if (!error && gid_valid(group))
2751+ error = ccs_path_number_perm(CCS_TYPE_CHGRP, dentry, vfsmnt,
2752+ from_kgid(&init_user_ns, group));
2753+ return error;
2754+}
2755+
2756+#else
2757+
2758+/**
2759+ * __ccs_chown_permission - Check permission for "chown/chgrp".
2760+ *
2761+ * @dentry: Pointer to "struct dentry".
2762+ * @vfsmnt: Pointer to "struct vfsmount". Maybe NULL.
2763+ * @user: User ID.
2764+ * @group: Group ID.
2765+ *
2766+ * Returns 0 on success, negative value otherwise.
2767+ */
2768+static int __ccs_chown_permission(struct dentry *dentry,
2769+ struct vfsmount *vfsmnt, uid_t user,
2770+ gid_t group)
2771+{
2772+ int error = 0;
2773+ if (user == (uid_t) -1 && group == (gid_t) -1)
2774+ return 0;
2775+ if (user != (uid_t) -1)
2776+ error = ccs_path_number_perm(CCS_TYPE_CHOWN, dentry, vfsmnt,
2777+ user);
2778+ if (!error && group != (gid_t) -1)
2779+ error = ccs_path_number_perm(CCS_TYPE_CHGRP, dentry, vfsmnt,
2780+ group);
2781+ return error;
2782+}
2783+
2784+#endif
2785+
2786+/**
2787+ * __ccs_fcntl_permission - Check permission for changing O_APPEND flag.
2788+ *
2789+ * @file: Pointer to "struct file".
2790+ * @cmd: Command number.
2791+ * @arg: Value for @cmd.
2792+ *
2793+ * Returns 0 on success, negative value otherwise.
2794+ */
2795+static int __ccs_fcntl_permission(struct file *file, unsigned int cmd,
2796+ unsigned long arg)
2797+{
2798+ if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)))
2799+ return 0;
2800+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
2801+ return __ccs_open_permission(file->f_path.dentry, file->f_path.mnt,
2802+ O_WRONLY | (arg & O_APPEND));
2803+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 6
2804+ return __ccs_open_permission(file->f_dentry, file->f_vfsmnt,
2805+ O_WRONLY | (arg & O_APPEND));
2806+#else
2807+ return __ccs_open_permission(file->f_dentry, file->f_vfsmnt,
2808+ (O_WRONLY + 1) | (arg & O_APPEND));
2809+#endif
2810+}
2811+
2812+/**
2813+ * __ccs_pivot_root_permission - Check permission for pivot_root().
2814+ *
2815+ * @old_path: Pointer to "struct path".
2816+ * @new_path: Pointer to "struct path".
2817+ *
2818+ * Returns 0 on success, negative value otherwise.
2819+ */
2820+static int __ccs_pivot_root_permission(const struct path *old_path,
2821+ const struct path *new_path)
2822+{
2823+ return ccs_path2_perm(CCS_TYPE_PIVOT_ROOT, new_path->dentry,
2824+ new_path->mnt, old_path->dentry, old_path->mnt);
2825+}
2826+
2827+/**
2828+ * __ccs_chroot_permission - Check permission for chroot().
2829+ *
2830+ * @path: Pointer to "struct path".
2831+ *
2832+ * Returns 0 on success, negative value otherwise.
2833+ */
2834+static int __ccs_chroot_permission(const struct path *path)
2835+{
2836+ return ccs_path_perm(CCS_TYPE_CHROOT, path->dentry, path->mnt, NULL);
2837+}
2838+
2839+/**
2840+ * __ccs_umount_permission - Check permission for unmount.
2841+ *
2842+ * @mnt: Pointer to "struct vfsmount".
2843+ * @flags: Unused.
2844+ *
2845+ * Returns 0 on success, negative value otherwise.
2846+ */
2847+static int __ccs_umount_permission(struct vfsmount *mnt, int flags)
2848+{
2849+ return ccs_path_perm(CCS_TYPE_UMOUNT, mnt->mnt_root, mnt, NULL);
2850+}
2851+
2852+/**
2853+ * __ccs_mknod_permission - Check permission for vfs_mknod().
2854+ *
2855+ * @dentry: Pointer to "struct dentry".
2856+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2857+ * @mode: Device type and permission.
2858+ * @dev: Device number for block or character device.
2859+ *
2860+ * Returns 0 on success, negative value otherwise.
2861+ */
2862+static int __ccs_mknod_permission(struct dentry *dentry, struct vfsmount *mnt,
2863+ const unsigned int mode, unsigned int dev)
2864+{
2865+ int error = 0;
2866+ const unsigned int perm = mode & S_IALLUGO;
2867+ switch (mode & S_IFMT) {
2868+ case S_IFCHR:
2869+ error = ccs_mkdev_perm(CCS_TYPE_MKCHAR, dentry, mnt, perm,
2870+ dev);
2871+ break;
2872+ case S_IFBLK:
2873+ error = ccs_mkdev_perm(CCS_TYPE_MKBLOCK, dentry, mnt, perm,
2874+ dev);
2875+ break;
2876+ case S_IFIFO:
2877+ error = ccs_path_number_perm(CCS_TYPE_MKFIFO, dentry, mnt,
2878+ perm);
2879+ break;
2880+ case S_IFSOCK:
2881+ error = ccs_path_number_perm(CCS_TYPE_MKSOCK, dentry, mnt,
2882+ perm);
2883+ break;
2884+ case 0:
2885+ case S_IFREG:
2886+ error = ccs_path_number_perm(CCS_TYPE_CREATE, dentry, mnt,
2887+ perm);
2888+ break;
2889+ }
2890+ return error;
2891+}
2892+
2893+/**
2894+ * __ccs_mkdir_permission - Check permission for vfs_mkdir().
2895+ *
2896+ * @dentry: Pointer to "struct dentry".
2897+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2898+ * @mode: Create mode.
2899+ *
2900+ * Returns 0 on success, negative value otherwise.
2901+ */
2902+static int __ccs_mkdir_permission(struct dentry *dentry, struct vfsmount *mnt,
2903+ unsigned int mode)
2904+{
2905+ return ccs_path_number_perm(CCS_TYPE_MKDIR, dentry, mnt, mode);
2906+}
2907+
2908+/**
2909+ * __ccs_rmdir_permission - Check permission for vfs_rmdir().
2910+ *
2911+ * @dentry: Pointer to "struct dentry".
2912+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2913+ *
2914+ * Returns 0 on success, negative value otherwise.
2915+ */
2916+static int __ccs_rmdir_permission(struct dentry *dentry, struct vfsmount *mnt)
2917+{
2918+ return ccs_path_perm(CCS_TYPE_RMDIR, dentry, mnt, NULL);
2919+}
2920+
2921+/**
2922+ * __ccs_unlink_permission - Check permission for vfs_unlink().
2923+ *
2924+ * @dentry: Pointer to "struct dentry".
2925+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2926+ *
2927+ * Returns 0 on success, negative value otherwise.
2928+ */
2929+static int __ccs_unlink_permission(struct dentry *dentry, struct vfsmount *mnt)
2930+{
2931+ return ccs_path_perm(CCS_TYPE_UNLINK, dentry, mnt, NULL);
2932+}
2933+
2934+#ifdef CONFIG_CCSECURITY_FILE_GETATTR
2935+
2936+/**
2937+ * __ccs_getattr_permission - Check permission for vfs_getattr().
2938+ *
2939+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2940+ * @dentry: Pointer to "struct dentry".
2941+ *
2942+ * Returns 0 on success, negative value otherwise.
2943+ */
2944+static int __ccs_getattr_permission(struct vfsmount *mnt,
2945+ struct dentry *dentry)
2946+{
2947+ return ccs_path_perm(CCS_TYPE_GETATTR, dentry, mnt, NULL);
2948+}
2949+
2950+#endif
2951+
2952+/**
2953+ * __ccs_symlink_permission - Check permission for vfs_symlink().
2954+ *
2955+ * @dentry: Pointer to "struct dentry".
2956+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2957+ * @from: Content of symlink.
2958+ *
2959+ * Returns 0 on success, negative value otherwise.
2960+ */
2961+static int __ccs_symlink_permission(struct dentry *dentry,
2962+ struct vfsmount *mnt, const char *from)
2963+{
2964+ return ccs_path_perm(CCS_TYPE_SYMLINK, dentry, mnt, from);
2965+}
2966+
2967+/**
2968+ * __ccs_truncate_permission - Check permission for notify_change().
2969+ *
2970+ * @dentry: Pointer to "struct dentry".
2971+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2972+ *
2973+ * Returns 0 on success, negative value otherwise.
2974+ */
2975+static int __ccs_truncate_permission(struct dentry *dentry,
2976+ struct vfsmount *mnt)
2977+{
2978+ return ccs_path_perm(CCS_TYPE_TRUNCATE, dentry, mnt, NULL);
2979+}
2980+
2981+/**
2982+ * __ccs_rename_permission - Check permission for vfs_rename().
2983+ *
2984+ * @old_dentry: Pointer to "struct dentry".
2985+ * @new_dentry: Pointer to "struct dentry".
2986+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
2987+ *
2988+ * Returns 0 on success, negative value otherwise.
2989+ */
2990+static int __ccs_rename_permission(struct dentry *old_dentry,
2991+ struct dentry *new_dentry,
2992+ struct vfsmount *mnt)
2993+{
2994+ return ccs_path2_perm(CCS_TYPE_RENAME, old_dentry, mnt, new_dentry,
2995+ mnt);
2996+}
2997+
2998+/**
2999+ * __ccs_link_permission - Check permission for vfs_link().
3000+ *
3001+ * @old_dentry: Pointer to "struct dentry".
3002+ * @new_dentry: Pointer to "struct dentry".
3003+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
3004+ *
3005+ * Returns 0 on success, negative value otherwise.
3006+ */
3007+static int __ccs_link_permission(struct dentry *old_dentry,
3008+ struct dentry *new_dentry,
3009+ struct vfsmount *mnt)
3010+{
3011+ return ccs_path2_perm(CCS_TYPE_LINK, old_dentry, mnt, new_dentry, mnt);
3012+}
3013+
3014+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
3015+
3016+/**
3017+ * __ccs_open_exec_permission - Check permission for open_exec().
3018+ *
3019+ * @dentry: Pointer to "struct dentry".
3020+ * @mnt: Pointer to "struct vfsmount".
3021+ *
3022+ * Returns 0 on success, negative value otherwise.
3023+ */
3024+static int __ccs_open_exec_permission(struct dentry *dentry,
3025+ struct vfsmount *mnt)
3026+{
3027+ return (ccs_current_flags() & CCS_TASK_IS_IN_EXECVE) ?
3028+ __ccs_open_permission(dentry, mnt, O_RDONLY + 1) : 0;
3029+}
3030+
3031+/**
3032+ * __ccs_uselib_permission - Check permission for sys_uselib().
3033+ *
3034+ * @dentry: Pointer to "struct dentry".
3035+ * @mnt: Pointer to "struct vfsmount".
3036+ *
3037+ * Returns 0 on success, negative value otherwise.
3038+ */
3039+static int __ccs_uselib_permission(struct dentry *dentry, struct vfsmount *mnt)
3040+{
3041+ return __ccs_open_permission(dentry, mnt, O_RDONLY + 1);
3042+}
3043+
3044+#endif
3045+
3046+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
3047+
3048+/**
3049+ * __ccs_parse_table - Check permission for parse_table().
3050+ *
3051+ * @name: Pointer to "int __user".
3052+ * @nlen: Number of elements in @name.
3053+ * @oldval: Pointer to "void __user".
3054+ * @newval: Pointer to "void __user".
3055+ * @table: Pointer to "struct ctl_table".
3056+ *
3057+ * Returns 0 on success, negative value otherwise.
3058+ *
3059+ * Note that this function is racy because this function checks values in
3060+ * userspace memory which could be changed after permission check.
3061+ */
3062+static int __ccs_parse_table(int __user *name, int nlen, void __user *oldval,
3063+ void __user *newval, struct ctl_table *table)
3064+{
3065+ int n;
3066+ int error = -ENOMEM;
3067+ int op = 0;
3068+ struct ccs_path_info buf;
3069+ char *buffer = NULL;
3070+ struct ccs_request_info r;
3071+ int idx;
3072+ if (oldval)
3073+ op |= 004;
3074+ if (newval)
3075+ op |= 002;
3076+ if (!op) /* Neither read nor write */
3077+ return 0;
3078+ idx = ccs_read_lock();
3079+ if (ccs_init_request_info(&r, CCS_MAC_FILE_OPEN)
3080+ == CCS_CONFIG_DISABLED) {
3081+ error = 0;
3082+ goto out;
3083+ }
3084+ buffer = kmalloc(PAGE_SIZE, CCS_GFP_FLAGS);
3085+ if (!buffer)
3086+ goto out;
3087+ snprintf(buffer, PAGE_SIZE - 1, "proc:/sys");
3088+repeat:
3089+ if (!nlen) {
3090+ error = -ENOTDIR;
3091+ goto out;
3092+ }
3093+ if (get_user(n, name)) {
3094+ error = -EFAULT;
3095+ goto out;
3096+ }
3097+ for ( ; table->ctl_name
3098+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21)
3099+ || table->procname
3100+#endif
3101+ ; table++) {
3102+ int pos;
3103+ const char *cp;
3104+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21)
3105+ if (n != table->ctl_name && table->ctl_name != CTL_ANY)
3106+ continue;
3107+#else
3108+ if (!n || n != table->ctl_name)
3109+ continue;
3110+#endif
3111+ pos = strlen(buffer);
3112+ cp = table->procname;
3113+ error = -ENOMEM;
3114+ if (cp) {
3115+ int len = strlen(cp);
3116+ if (len + 2 > PAGE_SIZE - 1)
3117+ goto out;
3118+ buffer[pos++] = '/';
3119+ memmove(buffer + pos, cp, len + 1);
3120+ } else {
3121+ /* Assume nobody assigns "=\$=" for procname. */
3122+ snprintf(buffer + pos, PAGE_SIZE - pos - 1,
3123+ "/=%d=", table->ctl_name);
3124+ if (!memchr(buffer, '\0', PAGE_SIZE - 2))
3125+ goto out;
3126+ }
3127+ if (!table->child)
3128+ goto no_child;
3129+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 21)
3130+ if (!table->strategy)
3131+ goto no_strategy;
3132+ /* printk("sysctl='%s'\n", buffer); */
3133+ buf.name = ccs_encode(buffer);
3134+ if (!buf.name)
3135+ goto out;
3136+ ccs_fill_path_info(&buf);
3137+ if (op & MAY_READ)
3138+ error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
3139+ else
3140+ error = 0;
3141+ if (!error && (op & MAY_WRITE))
3142+ error = ccs_path_permission(&r, CCS_TYPE_WRITE, &buf);
3143+ kfree(buf.name);
3144+ if (error)
3145+ goto out;
3146+no_strategy:
3147+#endif
3148+ name++;
3149+ nlen--;
3150+ table = table->child;
3151+ goto repeat;
3152+no_child:
3153+ /* printk("sysctl='%s'\n", buffer); */
3154+ buf.name = ccs_encode(buffer);
3155+ if (!buf.name)
3156+ goto out;
3157+ ccs_fill_path_info(&buf);
3158+ if (op & MAY_READ)
3159+ error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
3160+ else
3161+ error = 0;
3162+ if (!error && (op & MAY_WRITE))
3163+ error = ccs_path_permission(&r, CCS_TYPE_WRITE, &buf);
3164+ kfree(buf.name);
3165+ goto out;
3166+ }
3167+ error = -ENOTDIR;
3168+out:
3169+ ccs_read_unlock(idx);
3170+ kfree(buffer);
3171+ return error;
3172+}
3173+
3174+#endif
3175+
3176+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
3177+
3178+/**
3179+ * ccs_old_pivot_root_permission - Check permission for pivot_root().
3180+ *
3181+ * @old_nd: Pointer to "struct nameidata".
3182+ * @new_nd: Pointer to "struct nameidata".
3183+ *
3184+ * Returns 0 on success, negative value otherwise.
3185+ */
3186+static int ccs_old_pivot_root_permission(struct nameidata *old_nd,
3187+ struct nameidata *new_nd)
3188+{
3189+ struct path old_path = { old_nd->mnt, old_nd->dentry };
3190+ struct path new_path = { new_nd->mnt, new_nd->dentry };
3191+ return __ccs_pivot_root_permission(&old_path, &new_path);
3192+}
3193+
3194+/**
3195+ * ccs_old_chroot_permission - Check permission for chroot().
3196+ *
3197+ * @nd: Pointer to "struct nameidata".
3198+ *
3199+ * Returns 0 on success, negative value otherwise.
3200+ */
3201+static int ccs_old_chroot_permission(struct nameidata *nd)
3202+{
3203+ struct path path = { nd->mnt, nd->dentry };
3204+ return __ccs_chroot_permission(&path);
3205+}
3206+
3207+#endif
3208+
3209+#ifdef CONFIG_CCSECURITY_NETWORK
3210+
3211+/**
3212+ * ccs_address_matches_group - Check whether the given address matches members of the given address group.
3213+ *
3214+ * @is_ipv6: True if @address is an IPv6 address.
3215+ * @address: An IPv4 or IPv6 address.
3216+ * @group: Pointer to "struct ccs_address_group".
3217+ *
3218+ * Returns true if @address matches addresses in @group group, false otherwise.
3219+ *
3220+ * Caller holds ccs_read_lock().
3221+ */
3222+static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
3223+ const struct ccs_group *group)
3224+{
3225+ struct ccs_address_group *member;
3226+ bool matched = false;
3227+ const u8 size = is_ipv6 ? 16 : 4;
3228+ list_for_each_entry_srcu(member, &group->member_list, head.list,
3229+ &ccs_ss) {
3230+ if (member->head.is_deleted)
3231+ continue;
3232+ if (member->address.is_ipv6 != is_ipv6)
3233+ continue;
3234+ if (memcmp(&member->address.ip[0], address, size) > 0 ||
3235+ memcmp(address, &member->address.ip[1], size) > 0)
3236+ continue;
3237+ matched = true;
3238+ break;
3239+ }
3240+ return matched;
3241+}
3242+
3243+/**
3244+ * ccs_check_inet_acl - Check permission for inet domain socket operation.
3245+ *
3246+ * @r: Pointer to "struct ccs_request_info".
3247+ * @ptr: Pointer to "struct ccs_acl_info".
3248+ *
3249+ * Returns true if granted, false otherwise.
3250+ */
3251+static bool ccs_check_inet_acl(struct ccs_request_info *r,
3252+ const struct ccs_acl_info *ptr)
3253+{
3254+ const struct ccs_inet_acl *acl = container_of(ptr, typeof(*acl), head);
3255+ const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4;
3256+ if (!(ptr->perm & (1 << r->param.inet_network.operation)) ||
3257+ !ccs_compare_number_union(r->param.inet_network.port, &acl->port))
3258+ return false;
3259+ if (acl->address.group)
3260+ return ccs_address_matches_group(r->param.inet_network.is_ipv6,
3261+ r->param.inet_network.address,
3262+ acl->address.group);
3263+ return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 &&
3264+ memcmp(&acl->address.ip[0],
3265+ r->param.inet_network.address, size) <= 0 &&
3266+ memcmp(r->param.inet_network.address,
3267+ &acl->address.ip[1], size) <= 0;
3268+}
3269+
3270+/**
3271+ * ccs_check_unix_acl - Check permission for unix domain socket operation.
3272+ *
3273+ * @r: Pointer to "struct ccs_request_info".
3274+ * @ptr: Pointer to "struct ccs_acl_info".
3275+ *
3276+ * Returns true if granted, false otherwise.
3277+ */
3278+static bool ccs_check_unix_acl(struct ccs_request_info *r,
3279+ const struct ccs_acl_info *ptr)
3280+{
3281+ const struct ccs_unix_acl *acl = container_of(ptr, typeof(*acl), head);
3282+ return (ptr->perm & (1 << r->param.unix_network.operation)) &&
3283+ ccs_compare_name_union(r->param.unix_network.address,
3284+ &acl->name);
3285+}
3286+
3287+/**
3288+ * ccs_inet_entry - Check permission for INET network operation.
3289+ *
3290+ * @address: Pointer to "struct ccs_addr_info".
3291+ *
3292+ * Returns 0 on success, negative value otherwise.
3293+ */
3294+static int ccs_inet_entry(const struct ccs_addr_info *address)
3295+{
3296+ const int idx = ccs_read_lock();
3297+ struct ccs_request_info r;
3298+ int error = 0;
3299+ const u8 type = ccs_inet2mac[address->protocol][address->operation];
3300+ if (type && ccs_init_request_info(&r, type) != CCS_CONFIG_DISABLED) {
3301+ r.param_type = CCS_TYPE_INET_ACL;
3302+ r.param.inet_network.protocol = address->protocol;
3303+ r.param.inet_network.operation = address->operation;
3304+ r.param.inet_network.is_ipv6 = address->inet.is_ipv6;
3305+ r.param.inet_network.address = address->inet.address;
3306+ r.param.inet_network.port = ntohs(address->inet.port);
3307+ r.dont_sleep_on_enforce_error =
3308+ address->operation == CCS_NETWORK_ACCEPT
3309+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
3310+ || address->operation == CCS_NETWORK_RECV
3311+#endif
3312+ ;
3313+ error = ccs_check_acl(&r);
3314+ }
3315+ ccs_read_unlock(idx);
3316+ return error;
3317+}
3318+
3319+/**
3320+ * ccs_check_inet_address - Check permission for inet domain socket's operation.
3321+ *
3322+ * @addr: Pointer to "struct sockaddr".
3323+ * @addr_len: Size of @addr.
3324+ * @port: Port number.
3325+ * @address: Pointer to "struct ccs_addr_info".
3326+ *
3327+ * Returns 0 on success, negative value otherwise.
3328+ */
3329+static int ccs_check_inet_address(const struct sockaddr *addr,
3330+ const unsigned int addr_len, const u16 port,
3331+ struct ccs_addr_info *address)
3332+{
3333+ struct ccs_inet_addr_info *i = &address->inet;
3334+ if (addr_len < sizeof(addr->sa_family))
3335+ goto skip;
3336+ switch (addr->sa_family) {
3337+ case AF_INET6:
3338+ if (addr_len < SIN6_LEN_RFC2133)
3339+ goto skip;
3340+ i->is_ipv6 = true;
3341+ i->address = (u32 *)
3342+ ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
3343+ i->port = ((struct sockaddr_in6 *) addr)->sin6_port;
3344+ break;
3345+ case AF_INET:
3346+ if (addr_len < sizeof(struct sockaddr_in))
3347+ goto skip;
3348+ i->is_ipv6 = false;
3349+ i->address = (u32 *) &((struct sockaddr_in *) addr)->sin_addr;
3350+ i->port = ((struct sockaddr_in *) addr)->sin_port;
3351+ break;
3352+ default:
3353+ goto skip;
3354+ }
3355+ if (address->protocol == SOCK_RAW)
3356+ i->port = htons(port);
3357+ return ccs_inet_entry(address);
3358+skip:
3359+ return 0;
3360+}
3361+
3362+/**
3363+ * ccs_unix_entry - Check permission for UNIX network operation.
3364+ *
3365+ * @address: Pointer to "struct ccs_addr_info".
3366+ *
3367+ * Returns 0 on success, negative value otherwise.
3368+ */
3369+static int ccs_unix_entry(const struct ccs_addr_info *address)
3370+{
3371+ const int idx = ccs_read_lock();
3372+ struct ccs_request_info r;
3373+ int error = 0;
3374+ const u8 type = ccs_unix2mac[address->protocol][address->operation];
3375+ if (type && ccs_init_request_info(&r, type) != CCS_CONFIG_DISABLED) {
3376+ char *buf = address->unix0.addr;
3377+ int len = address->unix0.addr_len - sizeof(sa_family_t);
3378+ if (len <= 0) {
3379+ buf = "anonymous";
3380+ len = 9;
3381+ } else if (buf[0]) {
3382+ len = strnlen(buf, len);
3383+ }
3384+ buf = ccs_encode2(buf, len);
3385+ if (buf) {
3386+ struct ccs_path_info addr;
3387+ addr.name = buf;
3388+ ccs_fill_path_info(&addr);
3389+ r.param_type = CCS_TYPE_UNIX_ACL;
3390+ r.param.unix_network.protocol = address->protocol;
3391+ r.param.unix_network.operation = address->operation;
3392+ r.param.unix_network.address = &addr;
3393+ r.dont_sleep_on_enforce_error =
3394+ address->operation == CCS_NETWORK_ACCEPT
3395+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
3396+ || address->operation == CCS_NETWORK_RECV
3397+#endif
3398+ ;
3399+ error = ccs_check_acl(&r);
3400+ kfree(buf);
3401+ } else
3402+ error = -ENOMEM;
3403+ }
3404+ ccs_read_unlock(idx);
3405+ return error;
3406+}
3407+
3408+/**
3409+ * ccs_check_unix_address - Check permission for unix domain socket's operation.
3410+ *
3411+ * @addr: Pointer to "struct sockaddr".
3412+ * @addr_len: Size of @addr.
3413+ * @address: Pointer to "struct ccs_addr_info".
3414+ *
3415+ * Returns 0 on success, negative value otherwise.
3416+ */
3417+static int ccs_check_unix_address(struct sockaddr *addr,
3418+ const unsigned int addr_len,
3419+ struct ccs_addr_info *address)
3420+{
3421+ struct ccs_unix_addr_info *u = &address->unix0;
3422+ if (addr_len < sizeof(addr->sa_family))
3423+ return 0;
3424+ if (addr->sa_family != AF_UNIX)
3425+ return 0;
3426+ u->addr = ((struct sockaddr_un *) addr)->sun_path;
3427+ u->addr_len = addr_len;
3428+ return ccs_unix_entry(address);
3429+}
3430+
3431+/**
3432+ * ccs_sock_family - Get socket's family.
3433+ *
3434+ * @sk: Pointer to "struct sock".
3435+ *
3436+ * Returns one of PF_INET, PF_INET6, PF_UNIX or 0.
3437+ */
3438+static u8 ccs_sock_family(struct sock *sk)
3439+{
3440+ u8 family;
3441+ if (ccs_kernel_service())
3442+ return 0;
3443+ family = sk->sk_family;
3444+ switch (family) {
3445+ case PF_INET:
3446+ case PF_INET6:
3447+ case PF_UNIX:
3448+ return family;
3449+ default:
3450+ return 0;
3451+ }
3452+}
3453+
3454+/**
3455+ * __ccs_socket_listen_permission - Check permission for listening a socket.
3456+ *
3457+ * @sock: Pointer to "struct socket".
3458+ *
3459+ * Returns 0 on success, negative value otherwise.
3460+ */
3461+static int __ccs_socket_listen_permission(struct socket *sock)
3462+{
3463+ struct ccs_addr_info address;
3464+ const u8 family = ccs_sock_family(sock->sk);
3465+ const unsigned int type = sock->type;
3466+ struct sockaddr_storage addr;
3467+ int addr_len;
3468+ if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
3469+ return 0;
3470+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
3471+ {
3472+ const int error = sock->ops->getname(sock, (struct sockaddr *)
3473+ &addr, &addr_len, 0);
3474+ if (error)
3475+ return error;
3476+ }
3477+#else
3478+ addr_len = sock->ops->getname(sock, (struct sockaddr *) &addr, 0);
3479+ if (addr_len < 0)
3480+ return addr_len;
3481+#endif
3482+ address.protocol = type;
3483+ address.operation = CCS_NETWORK_LISTEN;
3484+ if (family == PF_UNIX)
3485+ return ccs_check_unix_address((struct sockaddr *) &addr,
3486+ addr_len, &address);
3487+ return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
3488+ &address);
3489+}
3490+
3491+/**
3492+ * __ccs_socket_connect_permission - Check permission for setting the remote address of a socket.
3493+ *
3494+ * @sock: Pointer to "struct socket".
3495+ * @addr: Pointer to "struct sockaddr".
3496+ * @addr_len: Size of @addr.
3497+ *
3498+ * Returns 0 on success, negative value otherwise.
3499+ */
3500+static int __ccs_socket_connect_permission(struct socket *sock,
3501+ struct sockaddr *addr, int addr_len)
3502+{
3503+ struct ccs_addr_info address;
3504+ const u8 family = ccs_sock_family(sock->sk);
3505+ const unsigned int type = sock->type;
3506+ if (!family)
3507+ return 0;
3508+ address.protocol = type;
3509+ switch (type) {
3510+ case SOCK_DGRAM:
3511+ case SOCK_RAW:
3512+ address.operation = CCS_NETWORK_SEND;
3513+ break;
3514+ case SOCK_STREAM:
3515+ case SOCK_SEQPACKET:
3516+ address.operation = CCS_NETWORK_CONNECT;
3517+ break;
3518+ default:
3519+ return 0;
3520+ }
3521+ if (family == PF_UNIX)
3522+ return ccs_check_unix_address(addr, addr_len, &address);
3523+ return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
3524+ &address);
3525+}
3526+
3527+/**
3528+ * __ccs_socket_bind_permission - Check permission for setting the local address of a socket.
3529+ *
3530+ * @sock: Pointer to "struct socket".
3531+ * @addr: Pointer to "struct sockaddr".
3532+ * @addr_len: Size of @addr.
3533+ *
3534+ * Returns 0 on success, negative value otherwise.
3535+ */
3536+static int __ccs_socket_bind_permission(struct socket *sock,
3537+ struct sockaddr *addr, int addr_len)
3538+{
3539+ struct ccs_addr_info address;
3540+ const u8 family = ccs_sock_family(sock->sk);
3541+ const unsigned int type = sock->type;
3542+ if (!family)
3543+ return 0;
3544+ switch (type) {
3545+ case SOCK_STREAM:
3546+ case SOCK_DGRAM:
3547+ case SOCK_RAW:
3548+ case SOCK_SEQPACKET:
3549+ address.protocol = type;
3550+ address.operation = CCS_NETWORK_BIND;
3551+ break;
3552+ default:
3553+ return 0;
3554+ }
3555+ if (family == PF_UNIX)
3556+ return ccs_check_unix_address(addr, addr_len, &address);
3557+ return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
3558+ &address);
3559+}
3560+
3561+/**
3562+ * __ccs_socket_sendmsg_permission - Check permission for sending a datagram.
3563+ *
3564+ * @sock: Pointer to "struct socket".
3565+ * @msg: Pointer to "struct msghdr".
3566+ * @size: Unused.
3567+ *
3568+ * Returns 0 on success, negative value otherwise.
3569+ */
3570+static int __ccs_socket_sendmsg_permission(struct socket *sock,
3571+ struct msghdr *msg, int size)
3572+{
3573+ struct ccs_addr_info address;
3574+ const u8 family = ccs_sock_family(sock->sk);
3575+ const unsigned int type = sock->type;
3576+ if (!msg->msg_name || !family ||
3577+ (type != SOCK_DGRAM && type != SOCK_RAW))
3578+ return 0;
3579+ address.protocol = type;
3580+ address.operation = CCS_NETWORK_SEND;
3581+ if (family == PF_UNIX)
3582+ return ccs_check_unix_address((struct sockaddr *)
3583+ msg->msg_name, msg->msg_namelen,
3584+ &address);
3585+ return ccs_check_inet_address((struct sockaddr *) msg->msg_name,
3586+ msg->msg_namelen, sock->sk->sk_protocol,
3587+ &address);
3588+}
3589+
3590+/**
3591+ * __ccs_socket_post_accept_permission - Check permission for accepting a socket.
3592+ *
3593+ * @sock: Pointer to "struct socket".
3594+ * @newsock: Pointer to "struct socket".
3595+ *
3596+ * Returns 0 on success, negative value otherwise.
3597+ */
3598+static int __ccs_socket_post_accept_permission(struct socket *sock,
3599+ struct socket *newsock)
3600+{
3601+ struct ccs_addr_info address;
3602+ const u8 family = ccs_sock_family(sock->sk);
3603+ const unsigned int type = sock->type;
3604+ struct sockaddr_storage addr;
3605+ int addr_len;
3606+ if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
3607+ return 0;
3608+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
3609+ {
3610+ const int error = newsock->ops->getname(newsock,
3611+ (struct sockaddr *)
3612+ &addr, &addr_len, 2);
3613+ if (error)
3614+ return error;
3615+ }
3616+#else
3617+ addr_len = newsock->ops->getname(newsock, (struct sockaddr *) &addr,
3618+ 2);
3619+ if (addr_len < 0)
3620+ return addr_len;
3621+#endif
3622+ address.protocol = type;
3623+ address.operation = CCS_NETWORK_ACCEPT;
3624+ if (family == PF_UNIX)
3625+ return ccs_check_unix_address((struct sockaddr *) &addr,
3626+ addr_len, &address);
3627+ return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
3628+ &address);
3629+}
3630+
3631+#ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
3632+
3633+/**
3634+ * __ccs_socket_post_recvmsg_permission - Check permission for receiving a datagram.
3635+ *
3636+ * @sk: Pointer to "struct sock".
3637+ * @skb: Pointer to "struct sk_buff".
3638+ * @flags: Flags passed to skb_recv_datagram().
3639+ *
3640+ * Returns 0 on success, negative value otherwise.
3641+ */
3642+static int __ccs_socket_post_recvmsg_permission(struct sock *sk,
3643+ struct sk_buff *skb, int flags)
3644+{
3645+ struct ccs_addr_info address;
3646+ const u8 family = ccs_sock_family(sk);
3647+ const unsigned int type = sk->sk_type;
3648+ struct sockaddr_storage addr;
3649+ if (!family)
3650+ return 0;
3651+ switch (type) {
3652+ case SOCK_DGRAM:
3653+ case SOCK_RAW:
3654+ address.protocol = type;
3655+ break;
3656+ default:
3657+ return 0;
3658+ }
3659+ address.operation = CCS_NETWORK_RECV;
3660+ switch (family) {
3661+ case PF_INET6:
3662+ {
3663+ struct in6_addr *sin6 = (struct in6_addr *) &addr;
3664+ address.inet.is_ipv6 = true;
3665+ if (type == SOCK_DGRAM &&
3666+ skb->protocol == htons(ETH_P_IP))
3667+ ipv6_addr_set(sin6, 0, 0, htonl(0xffff),
3668+ ip_hdr(skb)->saddr);
3669+ else
3670+ *sin6 = ipv6_hdr(skb)->saddr;
3671+ break;
3672+ }
3673+ case PF_INET:
3674+ {
3675+ struct in_addr *sin4 = (struct in_addr *) &addr;
3676+ address.inet.is_ipv6 = false;
3677+ sin4->s_addr = ip_hdr(skb)->saddr;
3678+ break;
3679+ }
3680+ default: /* == PF_UNIX */
3681+ {
3682+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
3683+ struct unix_address *u = unix_sk(skb->sk)->addr;
3684+#else
3685+ struct unix_address *u =
3686+ skb->sk->protinfo.af_unix.addr;
3687+#endif
3688+ unsigned int addr_len;
3689+ if (u && u->len <= sizeof(addr)) {
3690+ addr_len = u->len;
3691+ memcpy(&addr, u->name, addr_len);
3692+ } else {
3693+ addr_len = sizeof(addr.ss_family);
3694+ addr.ss_family = AF_UNIX;
3695+ }
3696+ if (ccs_check_unix_address((struct sockaddr *) &addr,
3697+ addr_len, &address))
3698+ goto out;
3699+ return 0;
3700+ }
3701+ }
3702+ address.inet.address = (u32 *) &addr;
3703+ if (type == SOCK_DGRAM)
3704+ address.inet.port = udp_hdr(skb)->source;
3705+ else
3706+ address.inet.port = htons(sk->sk_protocol);
3707+ if (ccs_inet_entry(&address))
3708+ goto out;
3709+ return 0;
3710+out:
3711+ /*
3712+ * Remove from queue if MSG_PEEK is used so that
3713+ * the head message from unwanted source in receive queue will not
3714+ * prevent the caller from picking up next message from wanted source
3715+ * when the caller is using MSG_PEEK flag for picking up.
3716+ */
3717+ {
3718+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
3719+ bool slow = false;
3720+ if (type == SOCK_DGRAM && family != PF_UNIX)
3721+ slow = lock_sock_fast(sk);
3722+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
3723+ if (type == SOCK_DGRAM && family != PF_UNIX)
3724+ lock_sock(sk);
3725+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 2
3726+ if (type == SOCK_DGRAM && family != PF_UNIX)
3727+ lock_sock(sk);
3728+#endif
3729+ skb_kill_datagram(sk, skb, flags);
3730+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
3731+ if (type == SOCK_DGRAM && family != PF_UNIX)
3732+ unlock_sock_fast(sk, slow);
3733+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
3734+ if (type == SOCK_DGRAM && family != PF_UNIX)
3735+ release_sock(sk);
3736+#elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 2
3737+ if (type == SOCK_DGRAM && family != PF_UNIX)
3738+ release_sock(sk);
3739+#endif
3740+ }
3741+ return -EPERM;
3742+}
3743+
3744+#endif
3745+
3746+#endif
3747+
3748+#if defined(CONFIG_CCSECURITY_CAPABILITY) || defined(CONFIG_CCSECURITY_NETWORK)
3749+
3750+/**
3751+ * ccs_kernel_service - Check whether I'm kernel service or not.
3752+ *
3753+ * Returns true if I'm kernel service, false otherwise.
3754+ */
3755+static bool ccs_kernel_service(void)
3756+{
3757+ /* Nothing to do if I am a kernel service. */
3758+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0) && LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
3759+ return (current->flags & (PF_KTHREAD | PF_IO_WORKER)) == PF_KTHREAD;
3760+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3761+ return current->flags & PF_KTHREAD;
3762+#else
3763+ return segment_eq(get_fs(), KERNEL_DS);
3764+#endif
3765+}
3766+
3767+#endif
3768+
3769+#ifdef CONFIG_CCSECURITY_CAPABILITY
3770+
3771+/**
3772+ * ccs_check_capability_acl - Check permission for capability operation.
3773+ *
3774+ * @r: Pointer to "struct ccs_request_info".
3775+ * @ptr: Pointer to "struct ccs_acl_info".
3776+ *
3777+ * Returns true if granted, false otherwise.
3778+ */
3779+static bool ccs_check_capability_acl(struct ccs_request_info *r,
3780+ const struct ccs_acl_info *ptr)
3781+{
3782+ const struct ccs_capability_acl *acl =
3783+ container_of(ptr, typeof(*acl), head);
3784+ return acl->operation == r->param.capability.operation;
3785+}
3786+
3787+/**
3788+ * ccs_capable - Check permission for capability.
3789+ *
3790+ * @operation: Type of operation.
3791+ *
3792+ * Returns true on success, false otherwise.
3793+ */
3794+static bool __ccs_capable(const u8 operation)
3795+{
3796+ struct ccs_request_info r;
3797+ int error = 0;
3798+ const int idx = ccs_read_lock();
3799+ if (ccs_init_request_info(&r, ccs_c2mac[operation])
3800+ != CCS_CONFIG_DISABLED) {
3801+ r.param_type = CCS_TYPE_CAPABILITY_ACL;
3802+ r.param.capability.operation = operation;
3803+ error = ccs_check_acl(&r);
3804+ }
3805+ ccs_read_unlock(idx);
3806+ return !error;
3807+}
3808+
3809+/**
3810+ * __ccs_socket_create_permission - Check permission for creating a socket.
3811+ *
3812+ * @family: Protocol family.
3813+ * @type: Unused.
3814+ * @protocol: Unused.
3815+ *
3816+ * Returns 0 on success, negative value otherwise.
3817+ */
3818+static int __ccs_socket_create_permission(int family, int type, int protocol)
3819+{
3820+ if (ccs_kernel_service())
3821+ return 0;
3822+ if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
3823+ return -EPERM;
3824+ if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
3825+ return -EPERM;
3826+ return 0;
3827+}
3828+
3829+/**
3830+ * __ccs_ptrace_permission - Check permission for ptrace().
3831+ *
3832+ * @request: Unused.
3833+ * @pid: Unused.
3834+ *
3835+ * Returns 0 on success, negative value otherwise.
3836+ *
3837+ * Since this function is called from location where it is permitted to sleep,
3838+ * it is racy to check target process's domainname anyway. Therefore, we don't
3839+ * use target process's domainname.
3840+ */
3841+static int __ccs_ptrace_permission(long request, long pid)
3842+{
3843+ return __ccs_capable(CCS_SYS_PTRACE) ? 0 : -EPERM;
3844+}
3845+
3846+#endif
3847+
3848+#ifdef CONFIG_CCSECURITY_IPC
3849+
3850+/**
3851+ * ccs_check_signal_acl - Check permission for signal operation.
3852+ *
3853+ * @r: Pointer to "struct ccs_request_info".
3854+ * @ptr: Pointer to "struct ccs_acl_info".
3855+ *
3856+ * Returns true if granted, false otherwise.
3857+ */
3858+static bool ccs_check_signal_acl(struct ccs_request_info *r,
3859+ const struct ccs_acl_info *ptr)
3860+{
3861+ const struct ccs_signal_acl *acl =
3862+ container_of(ptr, typeof(*acl), head);
3863+ if (ccs_compare_number_union(r->param.signal.sig, &acl->sig)) {
3864+ const int len = acl->domainname->total_len;
3865+ if (!strncmp(acl->domainname->name,
3866+ r->param.signal.dest_pattern, len)) {
3867+ switch (r->param.signal.dest_pattern[len]) {
3868+ case ' ':
3869+ case '\0':
3870+ return true;
3871+ }
3872+ }
3873+ }
3874+ return false;
3875+}
3876+
3877+/**
3878+ * ccs_signal_acl2 - Check permission for signal.
3879+ *
3880+ * @sig: Signal number.
3881+ * @pid: Target's PID.
3882+ *
3883+ * Returns 0 on success, negative value otherwise.
3884+ *
3885+ * Caller holds ccs_read_lock().
3886+ */
3887+static int ccs_signal_acl2(const int sig, const int pid)
3888+{
3889+ struct ccs_request_info r;
3890+ struct ccs_domain_info *dest = NULL;
3891+ const struct ccs_domain_info * const domain = ccs_current_domain();
3892+ if (ccs_init_request_info(&r, CCS_MAC_SIGNAL) == CCS_CONFIG_DISABLED)
3893+ return 0;
3894+ if (!sig)
3895+ return 0; /* No check for NULL signal. */
3896+ r.param_type = CCS_TYPE_SIGNAL_ACL;
3897+ r.param.signal.sig = sig;
3898+ r.param.signal.dest_pattern = domain->domainname->name;
3899+ r.granted = true;
3900+ if (ccs_sys_getpid() == pid) {
3901+ ccs_audit_log(&r);
3902+ return 0; /* No check for self process. */
3903+ }
3904+ { /* Simplified checking. */
3905+ struct task_struct *p = NULL;
3906+ ccs_tasklist_lock();
3907+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
3908+ if (pid > 0)
3909+ p = ccsecurity_exports.find_task_by_vpid((pid_t) pid);
3910+ else if (pid == 0)
3911+ p = current;
3912+ else if (pid == -1)
3913+ dest = &ccs_kernel_domain;
3914+ else
3915+ p = ccsecurity_exports.find_task_by_vpid((pid_t) -pid);
3916+#else
3917+ if (pid > 0)
3918+ p = find_task_by_pid((pid_t) pid);
3919+ else if (pid == 0)
3920+ p = current;
3921+ else if (pid == -1)
3922+ dest = &ccs_kernel_domain;
3923+ else
3924+ p = find_task_by_pid((pid_t) -pid);
3925+#endif
3926+ if (p)
3927+ dest = ccs_task_domain(p);
3928+ ccs_tasklist_unlock();
3929+ }
3930+ if (!dest)
3931+ return 0; /* I can't find destinatioin. */
3932+ if (domain == dest) {
3933+ ccs_audit_log(&r);
3934+ return 0; /* No check for self domain. */
3935+ }
3936+ r.param.signal.dest_pattern = dest->domainname->name;
3937+ return ccs_check_acl(&r);
3938+}
3939+
3940+/**
3941+ * ccs_signal_acl - Check permission for signal.
3942+ *
3943+ * @pid: Target's PID.
3944+ * @sig: Signal number.
3945+ *
3946+ * Returns 0 on success, negative value otherwise.
3947+ */
3948+static int ccs_signal_acl(const int pid, const int sig)
3949+{
3950+ int error;
3951+ if (!sig)
3952+ error = 0;
3953+ else {
3954+ const int idx = ccs_read_lock();
3955+ error = ccs_signal_acl2(sig, pid);
3956+ ccs_read_unlock(idx);
3957+ }
3958+ return error;
3959+}
3960+
3961+/**
3962+ * ccs_signal_acl0 - Permission check for signal().
3963+ *
3964+ * @tgid: Unused.
3965+ * @pid: Target's PID.
3966+ * @sig: Signal number.
3967+ *
3968+ * Returns 0 on success, negative value otherwise.
3969+ */
3970+static int ccs_signal_acl0(pid_t tgid, pid_t pid, int sig)
3971+{
3972+ return ccs_signal_acl(pid, sig);
3973+}
3974+
3975+#endif
3976+
3977+#ifdef CONFIG_CCSECURITY_MISC
3978+
3979+/**
3980+ * ccs_check_env_acl - Check permission for environment variable's name.
3981+ *
3982+ * @r: Pointer to "struct ccs_request_info".
3983+ * @ptr: Pointer to "struct ccs_acl_info".
3984+ *
3985+ * Returns true if granted, false otherwise.
3986+ */
3987+static bool ccs_check_env_acl(struct ccs_request_info *r,
3988+ const struct ccs_acl_info *ptr)
3989+{
3990+ const struct ccs_env_acl *acl = container_of(ptr, typeof(*acl), head);
3991+ return ccs_path_matches_pattern(r->param.environ.name, acl->env);
3992+}
3993+
3994+/**
3995+ * ccs_env_perm - Check permission for environment variable's name.
3996+ *
3997+ * @r: Pointer to "struct ccs_request_info".
3998+ * @env: The name of environment variable.
3999+ *
4000+ * Returns 0 on success, negative value otherwise.
4001+ *
4002+ * Caller holds ccs_read_lock().
4003+ */
4004+static int ccs_env_perm(struct ccs_request_info *r, const char *env)
4005+{
4006+ struct ccs_path_info environ;
4007+ if (!env || !*env)
4008+ return 0;
4009+ environ.name = env;
4010+ ccs_fill_path_info(&environ);
4011+ r->param_type = CCS_TYPE_ENV_ACL;
4012+ r->param.environ.name = &environ;
4013+ return ccs_check_acl(r);
4014+}
4015+
4016+/**
4017+ * ccs_environ - Check permission for environment variable names.
4018+ *
4019+ * @ee: Pointer to "struct ccs_execve".
4020+ *
4021+ * Returns 0 on success, negative value otherwise.
4022+ */
4023+static int ccs_environ(struct ccs_execve *ee)
4024+{
4025+ struct ccs_request_info *r = &ee->r;
4026+ struct linux_binprm *bprm = ee->bprm;
4027+ /* env_page.data is allocated by ccs_dump_page(). */
4028+ struct ccs_page_dump env_page = { };
4029+ char *arg_ptr; /* Size is CCS_EXEC_TMPSIZE bytes */
4030+ int arg_len = 0;
4031+ unsigned long pos = bprm->p;
4032+ int offset = pos % PAGE_SIZE;
4033+ int argv_count = bprm->argc;
4034+ int envp_count = bprm->envc;
4035+ /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
4036+ int error = -ENOMEM;
4037+ ee->r.type = CCS_MAC_ENVIRON;
4038+ ee->r.profile = ccs_current_domain()->profile;
4039+ ee->r.mode = ccs_get_mode(ee->r.profile, CCS_MAC_ENVIRON);
4040+ if (!r->mode || !envp_count)
4041+ return 0;
4042+ arg_ptr = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
4043+ if (!arg_ptr)
4044+ goto out;
4045+ while (error == -ENOMEM) {
4046+ if (!ccs_dump_page(bprm, pos, &env_page))
4047+ goto out;
4048+ pos += PAGE_SIZE - offset;
4049+ /* Read. */
4050+ while (argv_count && offset < PAGE_SIZE) {
4051+ if (!env_page.data[offset++])
4052+ argv_count--;
4053+ }
4054+ if (argv_count) {
4055+ offset = 0;
4056+ continue;
4057+ }
4058+ while (offset < PAGE_SIZE) {
4059+ const unsigned char c = env_page.data[offset++];
4060+ if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
4061+ if (c == '=') {
4062+ arg_ptr[arg_len++] = '\0';
4063+ } else if (c == '\\') {
4064+ arg_ptr[arg_len++] = '\\';
4065+ arg_ptr[arg_len++] = '\\';
4066+ } else if (c > ' ' && c < 127) {
4067+ arg_ptr[arg_len++] = c;
4068+ } else {
4069+ arg_ptr[arg_len++] = '\\';
4070+ arg_ptr[arg_len++] = (c >> 6) + '0';
4071+ arg_ptr[arg_len++]
4072+ = ((c >> 3) & 7) + '0';
4073+ arg_ptr[arg_len++] = (c & 7) + '0';
4074+ }
4075+ } else {
4076+ arg_ptr[arg_len] = '\0';
4077+ }
4078+ if (c)
4079+ continue;
4080+ if (ccs_env_perm(r, arg_ptr)) {
4081+ error = -EPERM;
4082+ break;
4083+ }
4084+ if (!--envp_count) {
4085+ error = 0;
4086+ break;
4087+ }
4088+ arg_len = 0;
4089+ }
4090+ offset = 0;
4091+ }
4092+out:
4093+ if (r->mode != CCS_CONFIG_ENFORCING)
4094+ error = 0;
4095+ kfree(env_page.data);
4096+ kfree(arg_ptr);
4097+ return error;
4098+}
4099+
4100+#endif
4101+
4102+/**
4103+ * ccs_argv - Check argv[] in "struct linux_binbrm".
4104+ *
4105+ * @index: Index number of @arg_ptr.
4106+ * @arg_ptr: Contents of argv[@index].
4107+ * @argc: Length of @argv.
4108+ * @argv: Pointer to "struct ccs_argv".
4109+ * @checked: Set to true if @argv[@index] was found.
4110+ *
4111+ * Returns true on success, false otherwise.
4112+ */
4113+static bool ccs_argv(const unsigned int index, const char *arg_ptr,
4114+ const int argc, const struct ccs_argv *argv,
4115+ u8 *checked)
4116+{
4117+ int i;
4118+ struct ccs_path_info arg;
4119+ arg.name = arg_ptr;
4120+ for (i = 0; i < argc; argv++, checked++, i++) {
4121+ bool result;
4122+ if (index != argv->index)
4123+ continue;
4124+ *checked = 1;
4125+ ccs_fill_path_info(&arg);
4126+ result = ccs_path_matches_pattern(&arg, argv->value);
4127+ if (argv->is_not)
4128+ result = !result;
4129+ if (!result)
4130+ return false;
4131+ }
4132+ return true;
4133+}
4134+
4135+/**
4136+ * ccs_envp - Check envp[] in "struct linux_binbrm".
4137+ *
4138+ * @env_name: The name of environment variable.
4139+ * @env_value: The value of environment variable.
4140+ * @envc: Length of @envp.
4141+ * @envp: Pointer to "struct ccs_envp".
4142+ * @checked: Set to true if @envp[@env_name] was found.
4143+ *
4144+ * Returns true on success, false otherwise.
4145+ */
4146+static bool ccs_envp(const char *env_name, const char *env_value,
4147+ const int envc, const struct ccs_envp *envp,
4148+ u8 *checked)
4149+{
4150+ int i;
4151+ struct ccs_path_info name;
4152+ struct ccs_path_info value;
4153+ name.name = env_name;
4154+ ccs_fill_path_info(&name);
4155+ value.name = env_value;
4156+ ccs_fill_path_info(&value);
4157+ for (i = 0; i < envc; envp++, checked++, i++) {
4158+ bool result;
4159+ if (!ccs_path_matches_pattern(&name, envp->name))
4160+ continue;
4161+ *checked = 1;
4162+ if (envp->value) {
4163+ result = ccs_path_matches_pattern(&value, envp->value);
4164+ if (envp->is_not)
4165+ result = !result;
4166+ } else {
4167+ result = true;
4168+ if (!envp->is_not)
4169+ result = !result;
4170+ }
4171+ if (!result)
4172+ return false;
4173+ }
4174+ return true;
4175+}
4176+
4177+/**
4178+ * ccs_scan_bprm - Scan "struct linux_binprm".
4179+ *
4180+ * @ee: Pointer to "struct ccs_execve".
4181+ * @argc: Length of @argc.
4182+ * @argv: Pointer to "struct ccs_argv".
4183+ * @envc: Length of @envp.
4184+ * @envp: Pointer to "struct ccs_envp".
4185+ *
4186+ * Returns true on success, false otherwise.
4187+ */
4188+static bool ccs_scan_bprm(struct ccs_execve *ee,
4189+ const u16 argc, const struct ccs_argv *argv,
4190+ const u16 envc, const struct ccs_envp *envp)
4191+{
4192+ struct linux_binprm *bprm = ee->bprm;
4193+ struct ccs_page_dump *dump = &ee->dump;
4194+ char *arg_ptr = ee->tmp;
4195+ int arg_len = 0;
4196+ unsigned long pos = bprm->p;
4197+ int offset = pos % PAGE_SIZE;
4198+ int argv_count = bprm->argc;
4199+ int envp_count = bprm->envc;
4200+ bool result = true;
4201+ u8 local_checked[32];
4202+ u8 *checked;
4203+ if (argc + envc <= sizeof(local_checked)) {
4204+ checked = local_checked;
4205+ memset(local_checked, 0, sizeof(local_checked));
4206+ } else {
4207+ checked = kzalloc(argc + envc, CCS_GFP_FLAGS);
4208+ if (!checked)
4209+ return false;
4210+ }
4211+ while (argv_count || envp_count) {
4212+ if (!ccs_dump_page(bprm, pos, dump)) {
4213+ result = false;
4214+ goto out;
4215+ }
4216+ pos += PAGE_SIZE - offset;
4217+ while (offset < PAGE_SIZE) {
4218+ /* Read. */
4219+ const char *kaddr = dump->data;
4220+ const unsigned char c = kaddr[offset++];
4221+ if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
4222+ if (c == '\\') {
4223+ arg_ptr[arg_len++] = '\\';
4224+ arg_ptr[arg_len++] = '\\';
4225+ } else if (c > ' ' && c < 127) {
4226+ arg_ptr[arg_len++] = c;
4227+ } else {
4228+ arg_ptr[arg_len++] = '\\';
4229+ arg_ptr[arg_len++] = (c >> 6) + '0';
4230+ arg_ptr[arg_len++] =
4231+ ((c >> 3) & 7) + '0';
4232+ arg_ptr[arg_len++] = (c & 7) + '0';
4233+ }
4234+ } else {
4235+ arg_ptr[arg_len] = '\0';
4236+ }
4237+ if (c)
4238+ continue;
4239+ /* Check. */
4240+ if (argv_count) {
4241+ if (!ccs_argv(bprm->argc - argv_count,
4242+ arg_ptr, argc, argv,
4243+ checked)) {
4244+ result = false;
4245+ break;
4246+ }
4247+ argv_count--;
4248+ } else if (envp_count) {
4249+ char *cp = strchr(arg_ptr, '=');
4250+ if (cp) {
4251+ *cp = '\0';
4252+ if (!ccs_envp(arg_ptr, cp + 1,
4253+ envc, envp,
4254+ checked + argc)) {
4255+ result = false;
4256+ break;
4257+ }
4258+ }
4259+ envp_count--;
4260+ } else {
4261+ break;
4262+ }
4263+ arg_len = 0;
4264+ }
4265+ offset = 0;
4266+ if (!result)
4267+ break;
4268+ }
4269+out:
4270+ if (result) {
4271+ int i;
4272+ /* Check not-yet-checked entries. */
4273+ for (i = 0; i < argc; i++) {
4274+ if (checked[i])
4275+ continue;
4276+ /*
4277+ * Return true only if all unchecked indexes in
4278+ * bprm->argv[] are not matched.
4279+ */
4280+ if (argv[i].is_not)
4281+ continue;
4282+ result = false;
4283+ break;
4284+ }
4285+ for (i = 0; i < envc; envp++, i++) {
4286+ if (checked[argc + i])
4287+ continue;
4288+ /*
4289+ * Return true only if all unchecked environ variables
4290+ * in bprm->envp[] are either undefined or not matched.
4291+ */
4292+ if ((!envp->value && !envp->is_not) ||
4293+ (envp->value && envp->is_not))
4294+ continue;
4295+ result = false;
4296+ break;
4297+ }
4298+ }
4299+ if (checked != local_checked)
4300+ kfree(checked);
4301+ return result;
4302+}
4303+
4304+/**
4305+ * ccs_scan_exec_realpath - Check "exec.realpath" parameter of "struct ccs_condition".
4306+ *
4307+ * @file: Pointer to "struct file".
4308+ * @ptr: Pointer to "struct ccs_name_union".
4309+ * @match: True if "exec.realpath=", false if "exec.realpath!=".
4310+ *
4311+ * Returns true on success, false otherwise.
4312+ */
4313+static bool ccs_scan_exec_realpath(struct file *file,
4314+ const struct ccs_name_union *ptr,
4315+ const bool match)
4316+{
4317+ bool result;
4318+ struct ccs_path_info exe;
4319+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
4320+ struct path path;
4321+#endif
4322+ if (!file)
4323+ return false;
4324+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
4325+ exe.name = ccs_realpath(&file->f_path);
4326+#else
4327+ path.mnt = file->f_vfsmnt;
4328+ path.dentry = file->f_dentry;
4329+ exe.name = ccs_realpath(&path);
4330+#endif
4331+ if (!exe.name)
4332+ return false;
4333+ ccs_fill_path_info(&exe);
4334+ result = ccs_compare_name_union(&exe, ptr);
4335+ kfree(exe.name);
4336+ return result == match;
4337+}
4338+
4339+/**
4340+ * ccs_get_attributes - Revalidate "struct inode".
4341+ *
4342+ * @obj: Pointer to "struct ccs_obj_info".
4343+ *
4344+ * Returns nothing.
4345+ */
4346+void ccs_get_attributes(struct ccs_obj_info *obj)
4347+{
4348+ u8 i;
4349+ struct dentry *dentry = NULL;
4350+
4351+ for (i = 0; i < CCS_MAX_PATH_STAT; i++) {
4352+ struct inode *inode;
4353+ switch (i) {
4354+ case CCS_PATH1:
4355+ dentry = obj->path1.dentry;
4356+ if (!dentry)
4357+ continue;
4358+ break;
4359+ case CCS_PATH2:
4360+ dentry = obj->path2.dentry;
4361+ if (!dentry)
4362+ continue;
4363+ break;
4364+ default:
4365+ if (!dentry)
4366+ continue;
4367+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
4368+ spin_lock(&dcache_lock);
4369+ dentry = dget(dentry->d_parent);
4370+ spin_unlock(&dcache_lock);
4371+#else
4372+ dentry = dget_parent(dentry);
4373+#endif
4374+ break;
4375+ }
4376+ inode = d_backing_inode(dentry);
4377+ if (inode) {
4378+ struct ccs_mini_stat *stat = &obj->stat[i];
4379+ stat->uid = inode->i_uid;
4380+ stat->gid = inode->i_gid;
4381+ stat->ino = inode->i_ino;
4382+ stat->mode = inode->i_mode;
4383+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
4384+ stat->dev = inode->i_dev;
4385+#else
4386+ stat->dev = inode->i_sb->s_dev;
4387+#endif
4388+ stat->rdev = inode->i_rdev;
4389+ obj->stat_valid[i] = true;
4390+ }
4391+ if (i & 1) /* i == CCS_PATH1_PARENT || i == CCS_PATH2_PARENT */
4392+ dput(dentry);
4393+ }
4394+}
4395+
4396+/**
4397+ * ccs_condition - Check condition part.
4398+ *
4399+ * @r: Pointer to "struct ccs_request_info".
4400+ * @cond: Pointer to "struct ccs_condition". Maybe NULL.
4401+ *
4402+ * Returns true on success, false otherwise.
4403+ *
4404+ * Caller holds ccs_read_lock().
4405+ */
4406+static bool ccs_condition(struct ccs_request_info *r,
4407+ const struct ccs_condition *cond)
4408+{
4409+ const u32 ccs_flags = ccs_current_flags();
4410+ u32 i;
4411+ unsigned long min_v[2] = { 0, 0 };
4412+ unsigned long max_v[2] = { 0, 0 };
4413+ const struct ccs_condition_element *condp;
4414+ const struct ccs_number_union *numbers_p;
4415+ const struct ccs_name_union *names_p;
4416+ const struct ccs_argv *argv;
4417+ const struct ccs_envp *envp;
4418+ struct ccs_obj_info *obj;
4419+ u16 condc;
4420+ u16 argc;
4421+ u16 envc;
4422+ struct linux_binprm *bprm = NULL;
4423+ if (!cond)
4424+ return true;
4425+ condc = cond->condc;
4426+ argc = cond->argc;
4427+ envc = cond->envc;
4428+ obj = r->obj;
4429+ if (r->ee)
4430+ bprm = r->ee->bprm;
4431+ if (!bprm && (argc || envc))
4432+ return false;
4433+ condp = (struct ccs_condition_element *) (cond + 1);
4434+ numbers_p = (const struct ccs_number_union *) (condp + condc);
4435+ names_p = (const struct ccs_name_union *)
4436+ (numbers_p + cond->numbers_count);
4437+ argv = (const struct ccs_argv *) (names_p + cond->names_count);
4438+ envp = (const struct ccs_envp *) (argv + argc);
4439+ for (i = 0; i < condc; i++) {
4440+ const bool match = condp->equals;
4441+ const u8 left = condp->left;
4442+ const u8 right = condp->right;
4443+ bool is_bitop[2] = { false, false };
4444+ u8 j;
4445+ condp++;
4446+ /* Check argv[] and envp[] later. */
4447+ if (left == CCS_ARGV_ENTRY || left == CCS_ENVP_ENTRY)
4448+ continue;
4449+ /* Check string expressions. */
4450+ if (right == CCS_NAME_UNION) {
4451+ const struct ccs_name_union *ptr = names_p++;
4452+ switch (left) {
4453+ struct ccs_path_info *symlink;
4454+ struct ccs_execve *ee;
4455+ struct file *file;
4456+ case CCS_SYMLINK_TARGET:
4457+ symlink = obj ? obj->symlink_target : NULL;
4458+ if (!symlink ||
4459+ !ccs_compare_name_union(symlink, ptr)
4460+ == match)
4461+ goto out;
4462+ break;
4463+ case CCS_EXEC_REALPATH:
4464+ ee = r->ee;
4465+ file = ee ? ee->bprm->file : NULL;
4466+ if (!ccs_scan_exec_realpath(file, ptr, match))
4467+ goto out;
4468+ break;
4469+ }
4470+ continue;
4471+ }
4472+ /* Check numeric or bit-op expressions. */
4473+ for (j = 0; j < 2; j++) {
4474+ const u8 index = j ? right : left;
4475+ unsigned long value = 0;
4476+ switch (index) {
4477+ case CCS_TASK_UID:
4478+ value = from_kuid(&init_user_ns,
4479+ current_uid());
4480+ break;
4481+ case CCS_TASK_EUID:
4482+ value = from_kuid(&init_user_ns,
4483+ current_euid());
4484+ break;
4485+ case CCS_TASK_SUID:
4486+ value = from_kuid(&init_user_ns,
4487+ current_suid());
4488+ break;
4489+ case CCS_TASK_FSUID:
4490+ value = from_kuid(&init_user_ns,
4491+ current_fsuid());
4492+ break;
4493+ case CCS_TASK_GID:
4494+ value = from_kgid(&init_user_ns,
4495+ current_gid());
4496+ break;
4497+ case CCS_TASK_EGID:
4498+ value = from_kgid(&init_user_ns,
4499+ current_egid());
4500+ break;
4501+ case CCS_TASK_SGID:
4502+ value = from_kgid(&init_user_ns,
4503+ current_sgid());
4504+ break;
4505+ case CCS_TASK_FSGID:
4506+ value = from_kgid(&init_user_ns,
4507+ current_fsgid());
4508+ break;
4509+ case CCS_TASK_PID:
4510+ value = ccs_sys_getpid();
4511+ break;
4512+ case CCS_TASK_PPID:
4513+ value = ccs_sys_getppid();
4514+ break;
4515+ case CCS_TYPE_IS_SOCKET:
4516+ value = S_IFSOCK;
4517+ break;
4518+ case CCS_TYPE_IS_SYMLINK:
4519+ value = S_IFLNK;
4520+ break;
4521+ case CCS_TYPE_IS_FILE:
4522+ value = S_IFREG;
4523+ break;
4524+ case CCS_TYPE_IS_BLOCK_DEV:
4525+ value = S_IFBLK;
4526+ break;
4527+ case CCS_TYPE_IS_DIRECTORY:
4528+ value = S_IFDIR;
4529+ break;
4530+ case CCS_TYPE_IS_CHAR_DEV:
4531+ value = S_IFCHR;
4532+ break;
4533+ case CCS_TYPE_IS_FIFO:
4534+ value = S_IFIFO;
4535+ break;
4536+ case CCS_MODE_SETUID:
4537+ value = S_ISUID;
4538+ break;
4539+ case CCS_MODE_SETGID:
4540+ value = S_ISGID;
4541+ break;
4542+ case CCS_MODE_STICKY:
4543+ value = S_ISVTX;
4544+ break;
4545+ case CCS_MODE_OWNER_READ:
4546+ value = S_IRUSR;
4547+ break;
4548+ case CCS_MODE_OWNER_WRITE:
4549+ value = S_IWUSR;
4550+ break;
4551+ case CCS_MODE_OWNER_EXECUTE:
4552+ value = S_IXUSR;
4553+ break;
4554+ case CCS_MODE_GROUP_READ:
4555+ value = S_IRGRP;
4556+ break;
4557+ case CCS_MODE_GROUP_WRITE:
4558+ value = S_IWGRP;
4559+ break;
4560+ case CCS_MODE_GROUP_EXECUTE:
4561+ value = S_IXGRP;
4562+ break;
4563+ case CCS_MODE_OTHERS_READ:
4564+ value = S_IROTH;
4565+ break;
4566+ case CCS_MODE_OTHERS_WRITE:
4567+ value = S_IWOTH;
4568+ break;
4569+ case CCS_MODE_OTHERS_EXECUTE:
4570+ value = S_IXOTH;
4571+ break;
4572+ case CCS_EXEC_ARGC:
4573+ if (!bprm)
4574+ goto out;
4575+ value = bprm->argc;
4576+ break;
4577+ case CCS_EXEC_ENVC:
4578+ if (!bprm)
4579+ goto out;
4580+ value = bprm->envc;
4581+ break;
4582+ case CCS_TASK_TYPE:
4583+ value = ((u8) ccs_flags)
4584+ & CCS_TASK_IS_EXECUTE_HANDLER;
4585+ break;
4586+ case CCS_TASK_EXECUTE_HANDLER:
4587+ value = CCS_TASK_IS_EXECUTE_HANDLER;
4588+ break;
4589+ case CCS_NUMBER_UNION:
4590+ /* Fetch values later. */
4591+ break;
4592+ default:
4593+ if (!obj)
4594+ goto out;
4595+ if (!obj->validate_done) {
4596+ ccs_get_attributes(obj);
4597+ obj->validate_done = true;
4598+ }
4599+ {
4600+ u8 stat_index;
4601+ struct ccs_mini_stat *stat;
4602+ switch (index) {
4603+ case CCS_PATH1_UID:
4604+ case CCS_PATH1_GID:
4605+ case CCS_PATH1_INO:
4606+ case CCS_PATH1_MAJOR:
4607+ case CCS_PATH1_MINOR:
4608+ case CCS_PATH1_TYPE:
4609+ case CCS_PATH1_DEV_MAJOR:
4610+ case CCS_PATH1_DEV_MINOR:
4611+ case CCS_PATH1_PERM:
4612+ stat_index = CCS_PATH1;
4613+ break;
4614+ case CCS_PATH2_UID:
4615+ case CCS_PATH2_GID:
4616+ case CCS_PATH2_INO:
4617+ case CCS_PATH2_MAJOR:
4618+ case CCS_PATH2_MINOR:
4619+ case CCS_PATH2_TYPE:
4620+ case CCS_PATH2_DEV_MAJOR:
4621+ case CCS_PATH2_DEV_MINOR:
4622+ case CCS_PATH2_PERM:
4623+ stat_index = CCS_PATH2;
4624+ break;
4625+ case CCS_PATH1_PARENT_UID:
4626+ case CCS_PATH1_PARENT_GID:
4627+ case CCS_PATH1_PARENT_INO:
4628+ case CCS_PATH1_PARENT_PERM:
4629+ stat_index = CCS_PATH1_PARENT;
4630+ break;
4631+ case CCS_PATH2_PARENT_UID:
4632+ case CCS_PATH2_PARENT_GID:
4633+ case CCS_PATH2_PARENT_INO:
4634+ case CCS_PATH2_PARENT_PERM:
4635+ stat_index = CCS_PATH2_PARENT;
4636+ break;
4637+ default:
4638+ goto out;
4639+ }
4640+ if (!obj->stat_valid[stat_index])
4641+ goto out;
4642+ stat = &obj->stat[stat_index];
4643+ switch (index) {
4644+ case CCS_PATH1_UID:
4645+ case CCS_PATH2_UID:
4646+ case CCS_PATH1_PARENT_UID:
4647+ case CCS_PATH2_PARENT_UID:
4648+ value = from_kuid
4649+ (&init_user_ns,
4650+ stat->uid);
4651+ break;
4652+ case CCS_PATH1_GID:
4653+ case CCS_PATH2_GID:
4654+ case CCS_PATH1_PARENT_GID:
4655+ case CCS_PATH2_PARENT_GID:
4656+ value = from_kgid
4657+ (&init_user_ns,
4658+ stat->gid);
4659+ break;
4660+ case CCS_PATH1_INO:
4661+ case CCS_PATH2_INO:
4662+ case CCS_PATH1_PARENT_INO:
4663+ case CCS_PATH2_PARENT_INO:
4664+ value = stat->ino;
4665+ break;
4666+ case CCS_PATH1_MAJOR:
4667+ case CCS_PATH2_MAJOR:
4668+ value = MAJOR(stat->dev);
4669+ break;
4670+ case CCS_PATH1_MINOR:
4671+ case CCS_PATH2_MINOR:
4672+ value = MINOR(stat->dev);
4673+ break;
4674+ case CCS_PATH1_TYPE:
4675+ case CCS_PATH2_TYPE:
4676+ value = stat->mode & S_IFMT;
4677+ break;
4678+ case CCS_PATH1_DEV_MAJOR:
4679+ case CCS_PATH2_DEV_MAJOR:
4680+ value = MAJOR(stat->rdev);
4681+ break;
4682+ case CCS_PATH1_DEV_MINOR:
4683+ case CCS_PATH2_DEV_MINOR:
4684+ value = MINOR(stat->rdev);
4685+ break;
4686+ case CCS_PATH1_PERM:
4687+ case CCS_PATH2_PERM:
4688+ case CCS_PATH1_PARENT_PERM:
4689+ case CCS_PATH2_PARENT_PERM:
4690+ value = stat->mode & S_IALLUGO;
4691+ break;
4692+ }
4693+ }
4694+ break;
4695+ }
4696+ max_v[j] = value;
4697+ min_v[j] = value;
4698+ switch (index) {
4699+ case CCS_MODE_SETUID:
4700+ case CCS_MODE_SETGID:
4701+ case CCS_MODE_STICKY:
4702+ case CCS_MODE_OWNER_READ:
4703+ case CCS_MODE_OWNER_WRITE:
4704+ case CCS_MODE_OWNER_EXECUTE:
4705+ case CCS_MODE_GROUP_READ:
4706+ case CCS_MODE_GROUP_WRITE:
4707+ case CCS_MODE_GROUP_EXECUTE:
4708+ case CCS_MODE_OTHERS_READ:
4709+ case CCS_MODE_OTHERS_WRITE:
4710+ case CCS_MODE_OTHERS_EXECUTE:
4711+ is_bitop[j] = true;
4712+ }
4713+ }
4714+ if (left == CCS_NUMBER_UNION) {
4715+ /* Fetch values now. */
4716+ const struct ccs_number_union *ptr = numbers_p++;
4717+ min_v[0] = ptr->values[0];
4718+ max_v[0] = ptr->values[1];
4719+ }
4720+ if (right == CCS_NUMBER_UNION) {
4721+ /* Fetch values now. */
4722+ const struct ccs_number_union *ptr = numbers_p++;
4723+ if (ptr->group) {
4724+ if (ccs_number_matches_group(min_v[0],
4725+ max_v[0],
4726+ ptr->group)
4727+ == match)
4728+ continue;
4729+ } else {
4730+ if ((min_v[0] <= ptr->values[1] &&
4731+ max_v[0] >= ptr->values[0]) == match)
4732+ continue;
4733+ }
4734+ goto out;
4735+ }
4736+ /*
4737+ * Bit operation is valid only when counterpart value
4738+ * represents permission.
4739+ */
4740+ if (is_bitop[0] && is_bitop[1]) {
4741+ goto out;
4742+ } else if (is_bitop[0]) {
4743+ switch (right) {
4744+ case CCS_PATH1_PERM:
4745+ case CCS_PATH1_PARENT_PERM:
4746+ case CCS_PATH2_PERM:
4747+ case CCS_PATH2_PARENT_PERM:
4748+ if (!(max_v[0] & max_v[1]) == !match)
4749+ continue;
4750+ }
4751+ goto out;
4752+ } else if (is_bitop[1]) {
4753+ switch (left) {
4754+ case CCS_PATH1_PERM:
4755+ case CCS_PATH1_PARENT_PERM:
4756+ case CCS_PATH2_PERM:
4757+ case CCS_PATH2_PARENT_PERM:
4758+ if (!(max_v[0] & max_v[1]) == !match)
4759+ continue;
4760+ }
4761+ goto out;
4762+ }
4763+ /* Normal value range comparison. */
4764+ if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
4765+ continue;
4766+out:
4767+ return false;
4768+ }
4769+ /* Check argv[] and envp[] now. */
4770+ if (r->ee && (argc || envc))
4771+ return ccs_scan_bprm(r->ee, argc, argv, envc, envp);
4772+ return true;
4773+}
4774+
4775+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
4776+
4777+/**
4778+ * ccs_check_task_acl - Check permission for task operation.
4779+ *
4780+ * @r: Pointer to "struct ccs_request_info".
4781+ * @ptr: Pointer to "struct ccs_acl_info".
4782+ *
4783+ * Returns true if granted, false otherwise.
4784+ */
4785+static bool ccs_check_task_acl(struct ccs_request_info *r,
4786+ const struct ccs_acl_info *ptr)
4787+{
4788+ const struct ccs_task_acl *acl = container_of(ptr, typeof(*acl), head);
4789+ return !ccs_pathcmp(r->param.task.domainname, acl->domainname);
4790+}
4791+
4792+#endif
4793+
4794+/**
4795+ * ccs_init_request_info - Initialize "struct ccs_request_info" members.
4796+ *
4797+ * @r: Pointer to "struct ccs_request_info" to initialize.
4798+ * @index: Index number of functionality.
4799+ *
4800+ * Returns mode.
4801+ *
4802+ * "task auto_domain_transition" keyword is evaluated before returning mode for
4803+ * @index. If "task auto_domain_transition" keyword was specified and
4804+ * transition to that domain failed, the current thread will be killed by
4805+ * SIGKILL. Note that if current->pid == 1, sending SIGKILL won't work.
4806+ */
4807+int ccs_init_request_info(struct ccs_request_info *r, const u8 index)
4808+{
4809+#ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
4810+ u8 i;
4811+ const char *buf;
4812+ for (i = 0; i < 255; i++) {
4813+ const u8 profile = ccs_current_domain()->profile;
4814+ memset(r, 0, sizeof(*r));
4815+ r->profile = profile;
4816+ r->type = index;
4817+ r->mode = ccs_get_mode(profile, index);
4818+ r->param_type = CCS_TYPE_AUTO_TASK_ACL;
4819+ ccs_check_acl(r);
4820+ if (!r->granted)
4821+ return r->mode;
4822+ buf = container_of(r->matched_acl, typeof(struct ccs_task_acl),
4823+ head)->domainname->name;
4824+ if (!ccs_assign_domain(buf, true))
4825+ break;
4826+ }
4827+ ccs_transition_failed(buf);
4828+ return CCS_CONFIG_DISABLED;
4829+#else
4830+ const u8 profile = ccs_current_domain()->profile;
4831+ memset(r, 0, sizeof(*r));
4832+ r->profile = profile;
4833+ r->type = index;
4834+ r->mode = ccs_get_mode(profile, index);
4835+ return r->mode;
4836+#endif
4837+}
4838+
4839+/**
4840+ * ccs_byte_range - Check whether the string is a \ooo style octal value.
4841+ *
4842+ * @str: Pointer to the string.
4843+ *
4844+ * Returns true if @str is a \ooo style octal value, false otherwise.
4845+ */
4846+static bool ccs_byte_range(const char *str)
4847+{
4848+ return *str >= '0' && *str++ <= '3' &&
4849+ *str >= '0' && *str++ <= '7' &&
4850+ *str >= '0' && *str <= '7';
4851+}
4852+
4853+/**
4854+ * ccs_decimal - Check whether the character is a decimal character.
4855+ *
4856+ * @c: The character to check.
4857+ *
4858+ * Returns true if @c is a decimal character, false otherwise.
4859+ */
4860+static bool ccs_decimal(const char c)
4861+{
4862+ return c >= '0' && c <= '9';
4863+}
4864+
4865+/**
4866+ * ccs_hexadecimal - Check whether the character is a hexadecimal character.
4867+ *
4868+ * @c: The character to check.
4869+ *
4870+ * Returns true if @c is a hexadecimal character, false otherwise.
4871+ */
4872+static bool ccs_hexadecimal(const char c)
4873+{
4874+ return (c >= '0' && c <= '9') ||
4875+ (c >= 'A' && c <= 'F') ||
4876+ (c >= 'a' && c <= 'f');
4877+}
4878+
4879+/**
4880+ * ccs_alphabet_char - Check whether the character is an alphabet.
4881+ *
4882+ * @c: The character to check.
4883+ *
4884+ * Returns true if @c is an alphabet character, false otherwise.
4885+ */
4886+static bool ccs_alphabet_char(const char c)
4887+{
4888+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
4889+}
4890+
4891+/**
4892+ * ccs_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
4893+ *
4894+ * @filename: The start of string to check.
4895+ * @filename_end: The end of string to check.
4896+ * @pattern: The start of pattern to compare.
4897+ * @pattern_end: The end of pattern to compare.
4898+ *
4899+ * Returns true if @filename matches @pattern, false otherwise.
4900+ */
4901+static bool ccs_file_matches_pattern2(const char *filename,
4902+ const char *filename_end,
4903+ const char *pattern,
4904+ const char *pattern_end)
4905+{
4906+ while (filename < filename_end && pattern < pattern_end) {
4907+ char c;
4908+ if (*pattern != '\\') {
4909+ if (*filename++ != *pattern++)
4910+ return false;
4911+ continue;
4912+ }
4913+ c = *filename;
4914+ pattern++;
4915+ switch (*pattern) {
4916+ int i;
4917+ int j;
4918+ case '?':
4919+ if (c == '/') {
4920+ return false;
4921+ } else if (c == '\\') {
4922+ if (filename[1] == '\\')
4923+ filename++;
4924+ else if (ccs_byte_range(filename + 1))
4925+ filename += 3;
4926+ else
4927+ return false;
4928+ }
4929+ break;
4930+ case '\\':
4931+ if (c != '\\')
4932+ return false;
4933+ if (*++filename != '\\')
4934+ return false;
4935+ break;
4936+ case '+':
4937+ if (!ccs_decimal(c))
4938+ return false;
4939+ break;
4940+ case 'x':
4941+ if (!ccs_hexadecimal(c))
4942+ return false;
4943+ break;
4944+ case 'a':
4945+ if (!ccs_alphabet_char(c))
4946+ return false;
4947+ break;
4948+ case '0':
4949+ case '1':
4950+ case '2':
4951+ case '3':
4952+ if (c == '\\' && ccs_byte_range(filename + 1)
4953+ && !strncmp(filename + 1, pattern, 3)) {
4954+ filename += 3;
4955+ pattern += 2;
4956+ break;
4957+ }
4958+ return false; /* Not matched. */
4959+ case '*':
4960+ case '@':
4961+ for (i = 0; i <= filename_end - filename; i++) {
4962+ if (ccs_file_matches_pattern2(filename + i,
4963+ filename_end,
4964+ pattern + 1,
4965+ pattern_end))
4966+ return true;
4967+ c = filename[i];
4968+ if (c == '.' && *pattern == '@')
4969+ break;
4970+ if (c != '\\')
4971+ continue;
4972+ if (filename[i + 1] == '\\')
4973+ i++;
4974+ else if (ccs_byte_range(filename + i + 1))
4975+ i += 3;
4976+ else
4977+ break; /* Bad pattern. */
4978+ }
4979+ return false; /* Not matched. */
4980+ default:
4981+ j = 0;
4982+ c = *pattern;
4983+ if (c == '$') {
4984+ while (ccs_decimal(filename[j]))
4985+ j++;
4986+ } else if (c == 'X') {
4987+ while (ccs_hexadecimal(filename[j]))
4988+ j++;
4989+ } else if (c == 'A') {
4990+ while (ccs_alphabet_char(filename[j]))
4991+ j++;
4992+ }
4993+ for (i = 1; i <= j; i++) {
4994+ if (ccs_file_matches_pattern2(filename + i,
4995+ filename_end,
4996+ pattern + 1,
4997+ pattern_end))
4998+ return true;
4999+ }
5000+ return false; /* Not matched or bad pattern. */
5001+ }
5002+ filename++;
5003+ pattern++;
5004+ }
5005+ while (*pattern == '\\' &&
5006+ (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
5007+ pattern += 2;
5008+ return filename == filename_end && pattern == pattern_end;
5009+}
5010+
5011+/**
5012+ * ccs_file_matches_pattern - Pattern matching without '/' character.
5013+ *
5014+ * @filename: The start of string to check.
5015+ * @filename_end: The end of string to check.
5016+ * @pattern: The start of pattern to compare.
5017+ * @pattern_end: The end of pattern to compare.
5018+ *
5019+ * Returns true if @filename matches @pattern, false otherwise.
5020+ */
5021+static bool ccs_file_matches_pattern(const char *filename,
5022+ const char *filename_end,
5023+ const char *pattern,
5024+ const char *pattern_end)
5025+{
5026+ const char *pattern_start = pattern;
5027+ bool first = true;
5028+ bool result;
5029+ while (pattern < pattern_end - 1) {
5030+ /* Split at "\-" pattern. */
5031+ if (*pattern++ != '\\' || *pattern++ != '-')
5032+ continue;
5033+ result = ccs_file_matches_pattern2(filename, filename_end,
5034+ pattern_start, pattern - 2);
5035+ if (first)
5036+ result = !result;
5037+ if (result)
5038+ return false;
5039+ first = false;
5040+ pattern_start = pattern;
5041+ }
5042+ result = ccs_file_matches_pattern2(filename, filename_end,
5043+ pattern_start, pattern_end);
5044+ return first ? result : !result;
5045+}
5046+
5047+/**
5048+ * ccs_path_matches_pattern2 - Do pathname pattern matching.
5049+ *
5050+ * @f: The start of string to check.
5051+ * @p: The start of pattern to compare.
5052+ *
5053+ * Returns true if @f matches @p, false otherwise.
5054+ */
5055+static bool ccs_path_matches_pattern2(const char *f, const char *p)
5056+{
5057+ const char *f_delimiter;
5058+ const char *p_delimiter;
5059+ while (*f && *p) {
5060+ f_delimiter = strchr(f, '/');
5061+ if (!f_delimiter)
5062+ f_delimiter = f + strlen(f);
5063+ p_delimiter = strchr(p, '/');
5064+ if (!p_delimiter)
5065+ p_delimiter = p + strlen(p);
5066+ if (*p == '\\' && *(p + 1) == '{')
5067+ goto recursive;
5068+ if (!ccs_file_matches_pattern(f, f_delimiter, p, p_delimiter))
5069+ return false;
5070+ f = f_delimiter;
5071+ if (*f)
5072+ f++;
5073+ p = p_delimiter;
5074+ if (*p)
5075+ p++;
5076+ }
5077+ /* Ignore trailing "\*" and "\@" in @pattern. */
5078+ while (*p == '\\' &&
5079+ (*(p + 1) == '*' || *(p + 1) == '@'))
5080+ p += 2;
5081+ return !*f && !*p;
5082+recursive:
5083+ /*
5084+ * The "\{" pattern is permitted only after '/' character.
5085+ * This guarantees that below "*(p - 1)" is safe.
5086+ * Also, the "\}" pattern is permitted only before '/' character
5087+ * so that "\{" + "\}" pair will not break the "\-" operator.
5088+ */
5089+ if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
5090+ *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
5091+ return false; /* Bad pattern. */
5092+ do {
5093+ /* Compare current component with pattern. */
5094+ if (!ccs_file_matches_pattern(f, f_delimiter, p + 2,
5095+ p_delimiter - 2))
5096+ break;
5097+ /* Proceed to next component. */
5098+ f = f_delimiter;
5099+ if (!*f)
5100+ break;
5101+ f++;
5102+ /* Continue comparison. */
5103+ if (ccs_path_matches_pattern2(f, p_delimiter + 1))
5104+ return true;
5105+ f_delimiter = strchr(f, '/');
5106+ } while (f_delimiter);
5107+ return false; /* Not matched. */
5108+}
5109+
5110+/**
5111+ * ccs_path_matches_pattern - Check whether the given filename matches the given pattern.
5112+ *
5113+ * @filename: The filename to check.
5114+ * @pattern: The pattern to compare.
5115+ *
5116+ * Returns true if matches, false otherwise.
5117+ *
5118+ * The following patterns are available.
5119+ * \\ \ itself.
5120+ * \ooo Octal representation of a byte.
5121+ * \* Zero or more repetitions of characters other than '/'.
5122+ * \@ Zero or more repetitions of characters other than '/' or '.'.
5123+ * \? 1 byte character other than '/'.
5124+ * \$ One or more repetitions of decimal digits.
5125+ * \+ 1 decimal digit.
5126+ * \X One or more repetitions of hexadecimal digits.
5127+ * \x 1 hexadecimal digit.
5128+ * \A One or more repetitions of alphabet characters.
5129+ * \a 1 alphabet character.
5130+ *
5131+ * \- Subtraction operator.
5132+ *
5133+ * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
5134+ * /dir/dir/dir/ ).
5135+ */
5136+static bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
5137+ const struct ccs_path_info *pattern)
5138+{
5139+ const char *f = filename->name;
5140+ const char *p = pattern->name;
5141+ const int len = pattern->const_len;
5142+ /* If @pattern doesn't contain pattern, I can use strcmp(). */
5143+ if (!pattern->is_patterned)
5144+ return !ccs_pathcmp(filename, pattern);
5145+ /* Don't compare directory and non-directory. */
5146+ if (filename->is_dir != pattern->is_dir)
5147+ return false;
5148+ /* Compare the initial length without patterns. */
5149+ if (strncmp(f, p, len))
5150+ return false;
5151+ f += len;
5152+ p += len;
5153+ return ccs_path_matches_pattern2(f, p);
5154+}
--- tags/patches/1.0.48/README (nonexistent)
+++ tags/patches/1.0.48/README (revision 695)
@@ -0,0 +1,390 @@
1+Notes for AKARI project
2+
3+AKARI is Access Keeping And Regulating Instrument for Linux 2.6 and later
4+kernels.
5+
6+You can use AKARI for analyzing your system's behavior (i.e. reports which
7+application accesses which resources like strace command does) and optionally
8+restricting your system's behavior (i.e. controls which application can
9+access which resources like TOMOYO/AppArmor does).
10+
11+AKARI is forked from TOMOYO 1.8 and made as a LKM (loadable kernel module)
12+so that you don't need to replace your kernels installed in your system.
13+
14+This patch is released under the GPLv2.
15+
16+Project URL: https://akari.osdn.jp/
17+
18+ChangeLog:
19+
20+Version 1.0 2010/10/10 First release.
21+
22+Version 1.0.1 2010/10/18 Minor update release.
23+
24+ Synchronize with TOMOYO revision 4069.
25+
26+ Fix off-by-two in ccs_check_unix_address().
27+
28+ Implement post accept() LSM hook.
29+
30+Version 1.0.2 2010/10/25 Minor update release.
31+
32+ Synchronize with TOMOYO revision 4090.
33+
34+ Add getattr() and readdir() checks.
35+
36+ Use "YYYY/MM/DD hh:mm:ss" format for /proc/ccs/ interface.
37+
38+ Do not automatically add / for umount().
39+
40+Version 1.0.3 2010/11/01 Minor update release.
41+
42+ Synchronize with TOMOYO revision 4104.
43+
44+ Fix pathname handling in ccs_unix_entry().
45+
46+Version 1.0.4 2010/11/11 Minor update release.
47+
48+ Synchronize with TOMOYO 1.8.0 release.
49+
50+ Add sysctl() check for 2.6.21 to 2.6.32 kernels.
51+
52+ Fix double new_decode_dev() bug for mknod().
53+
54+ Fix keyword typo.
55+
56+ Fix build failure on some kernels.
57+
58+ Changed pathname prefix priority.
59+
60+ Use hash table for faster scan.
61+
62+ Updated function comments.
63+
64+Version 1.0.5 2010/11/22 Minor update release.
65+
66+ Make ccs_domain_info/ccs_flags inheritable for 2.6.29 and later kernels.
67+
68+Version 1.0.6 2010/12/31 Minor update release.
69+
70+ Synchronize with TOMOYO revision 4280.
71+
72+ Use same interface for audit logs.
73+
74+ Split ccs_null_security into ccs_default_security and ccs_oom_security.
75+
76+Version 1.0.7 2011/01/21 Minor update release.
77+
78+ Synchronize with TOMOYO revision 4400.
79+
80+ Use filesystem name for unnamed devices when vfsmount is missing.
81+
82+Version 1.0.8 2011/02/07 Minor update release.
83+
84+ Synchronize with TOMOYO revision 4545.
85+
86+ Fix infinite loop bug when reading /proc/ccs/audit or /proc/ccs/query .
87+
88+Version 1.0.9 2011/02/14 Minor update release.
89+
90+ Fix missing permission check for interpreters in 2.6.30 and later kernels.
91+
92+Version 1.0.10 2011/02/15 Minor update release.
93+
94+ Fix missing permission check for interpreters in 2.6.23 and earlier kernels.
95+
96+ Fix wrong execute permission check and domain transition in 2.6.28 and earlier kernels.
97+
98+Version 1.0.11 2010/04/01 Minor update release.
99+
100+ Synchronize with TOMOYO 1.8.1 release.
101+
102+ Run garbage collector without waiting for /proc/ccs/ users.
103+
104+ Support built-in policy configuration.
105+
106+ Remove /proc/ccs/meminfo interface.
107+
108+ Pack policy when printing via /proc/ccs/ interface.
109+
110+ Fix conditional policy parsing.
111+
112+ Serialize updating profile's comment line.
113+
114+Version 1.0.12 2011/04/11 Minor update release.
115+
116+ Synchronize with TOMOYO revision 4874.
117+
118+ Fix fcntl(F_SETFL, O_APPEND) handling.
119+
120+Version 1.0.13 2011/05/05 Minor update release.
121+
122+ Synchronize with TOMOYO revision 4963.
123+
124+ Fix wrong profile number in audit logs for "misc env" permission.
125+
126+Version 1.0.14 2011/05/11 Minor update release.
127+
128+ Synchronize with TOMOYO revision 4978.
129+
130+ Fix wrong domainname validation.
131+
132+Version 1.0.15 2011/06/20 Minor update release.
133+
134+ Synchronize with TOMOYO 1.8.2 release.
135+
136+ Add policy namespace support.
137+
138+Version 1.0.16 2011/07/07 Minor update release.
139+
140+ Synchronize with TOMOYO revision 5235.
141+
142+ Remove /proc/ccs/.domain_status interface.
143+
144+Version 1.0.17 2011/07/13 Minor update release.
145+
146+ Synchronize with TOMOYO revision 5266.
147+
148+ Fix /proc/ccs/stat parser.
149+
150+ Accept "::" notation for IPv6 address.
151+
152+Version 1.0.18 2011/09/03 Minor update release.
153+
154+ Synchronize with TOMOYO revision 5401.
155+
156+ Avoid race when retrying "file execute" permission check.
157+
158+ Remove unneeded daemonize().
159+
160+ Fix load failure with !CONFIG_SMP && !CONFIG_DEBUG_SPINLOCK kernels.
161+
162+Version 1.0.19 2011/09/15 Minor update release.
163+
164+ Use akari/config.h for choosing build options.
165+
166+ Fix build error on CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER=y case.
167+
168+ Use lookup_mnt() rather than __put_namespace(). (2.6.0 to 2.6.2 kernels)
169+
170+ Fix unbalanced spin_lock()/spin_unlock() pair in lsm_pin().
171+ (2.6.15 to 2.6.35 kernels)
172+
173+ Fix "struct task_struct" leaks of tasks created before loading akari.ko .
174+ (2.6.28 and earlier kernels)
175+
176+ Use "struct task_struct"->pids[PIDTYPE_PID].pid instead of
177+ "struct task_struct" for associating with per "struct task_struct" variables
178+ (i.e. "struct ccs_security") in order to reduce amount of dead memory
179+ waiting for garbage collection. (2.6.29 and later kernels)
180+
181+ Add akari_test.ko for checking whether akari.ko seems to work or not.
182+
183+ Add SH and ARM architectures support. (Needs more testing.)
184+
185+Version 1.0.20 2011/09/29 Minor update release.
186+
187+ Synchronize with TOMOYO 1.8.3 release.
188+
189+ Allow specifying domain transition preference.
190+
191+ Simplify garbage collector.
192+
193+Version 1.0.21 2011/10/25 Minor update release.
194+
195+ Synchronize with TOMOYO revision 5569.
196+
197+ Fix incomplete read after seek.
198+
199+ Use query id for reaching target process's domain policy.
200+
201+ Fix quota counting.
202+
203+Version 1.0.22 2011/11/11 Minor update release.
204+
205+ Synchronize with TOMOYO revision 5625.
206+
207+ Optimize for object's size.
208+
209+Version 1.0.23 2011/11/18 Minor update release.
210+
211+ Synchronize with TOMOYO revision 5646.
212+
213+ Fix kernel config mapping error.
214+
215+Version 1.0.24 2011/12/13 Minor update release.
216+
217+ Synchronize with TOMOYO revision 5711.
218+
219+ Follow __d_path() behavior change. (Only 2.6.36 and later)
220+
221+Version 1.0.25 2012/02/29 Minor update release.
222+
223+ Synchronize with TOMOYO revision 5893.
224+
225+ Follow UMH_WAIT_PROC constant renumbering.
226+
227+ Fix mount flags checking order.
228+
229+Version 1.0.26 2012/04/01 Minor update release.
230+
231+ Synchronize with TOMOYO revision 5973.
232+
233+ Return appropriate value to poll().
234+
235+Version 1.0.27 2012/05/05 Minor update release.
236+
237+ Synchronize with TOMOYO revision 6035.
238+
239+ Readd RHEL_MINOR/AX_MINOR checks.
240+
241+ Accept manager programs which do not start with / .
242+
243+Version 1.0.28 2012/10/20 Security update release.
244+
245+ Fix kernel panic caused by double kfree() bug when "struct ccs_execve"
246+ pointer was by error duplicated at __ccs_alloc_task_security().
247+ This bug affects only 2.6.28 and earlier kernels.
248+
249+Version 1.0.29 2012/11/04 Minor update release.
250+
251+ Use dummy pointer as needed in order to make sure that security_bprm_free()
252+ (which is used for making the caller of do_execve() return to previous
253+ domain when do_execve() failed after domain transition) is always called.
254+ Without this fix, domain transition history on 2.6.28 and earlier kernels
255+ becomes inaccurate.
256+
257+Version 1.0.30 2013/02/14 Minor update release.
258+
259+ Commit a2a8474c "exec: do not sleep in TASK_TRACED under ->cred_guard_mutex"
260+ moved "current->in_execve = 1;" from before prepare_bprm_creds() to after
261+ prepare_bprm_creds(). It turned out that, as an unexpected bonus, we can use
262+ security_prepare_creds() as a hook for emulating security_bprm_free() hook.
263+
264+ I updated the logic for security_bprm_free() emulation, and now AKARI should
265+ be able to coexist with other AKARI-like LKM-based LSM implementations (e.g.
266+ CaitSith) on all kernel versions other than 2.6.29 and 2.6.30.
267+
268+Version 1.0.31 2015/01/12 Minor update release.
269+
270+ Synchronize with TOMOYO revision 6373.
271+
272+ Fix missing chmod(-1) check in Linux 3.1 and later kernels.
273+
274+ Fix potentially using bogus attributes when stat() fails.
275+
276+Version 1.0.32 2015/04/08 Minor update release.
277+
278+ Synchronize with TOMOYO revision 6388.
279+
280+ Fix incorrect readdir() permission check.
281+
282+Version 1.0.33 2015/04/21 Minor update release.
283+
284+ Synchronize with TOMOYO revision 6407.
285+
286+ Fix incorrect retry request check.
287+
288+Version 1.0.34 2015/05/05 Minor update release.
289+
290+ Synchronize with TOMOYO 1.8.4 release.
291+
292+ Support multiple use_group entries.
293+
294+Version 1.0.35 2015/11/11 Minor update release.
295+
296+ Synchronize with TOMOYO 1.8.5 release.
297+
298+ Use memory allocation flags used by TOMOYO 2.x.
299+
300+ Limit wildcard recursion depth.
301+
302+Version 1.0.36 2017/02/20 Minor update release.
303+
304+ Synchronize with TOMOYO revision 6553.
305+
306+ The bug fixed in TOMOYO's GC does not affect AKARI because
307+ AKARI always uses CONFIG_CCSECURITY_USE_EXTERNAL_TASK_SECURITY.
308+
309+Version 1.0.37 2017/09/17 Minor update release.
310+
311+ Use smp_rmb() when waiting for hook readiness.
312+
313+Version 1.0.38 2018/04/01 Minor update release.
314+
315+ Synchronize with TOMOYO revision 6638.
316+
317+ Due to incorrect probe_kernel_write() usage, previously registered LSM
318+ hook (if any) was by error overwritten by this hook. This bug affects
319+ only 4.12 and later kernels.
320+
321+Version 1.0.39 2019/08/20 Minor update release.
322+
323+ Synchronize with TOMOYO 1.8.6 release.
324+
325+ Change pathname calculation for read-only filesystems.
326+
327+ Reject move_mount() system call for now.
328+
329+ Don't check open/getattr permission on sockets.
330+
331+Version 1.0.40 2019/12/25 Minor update release.
332+
333+ Synchronize with TOMOYO revision 6758.
334+
335+ Don't use nifty names on sockets.
336+
337+Version 1.0.41 2020/04/13 Minor update release.
338+
339+ Synchronize with TOMOYO revision 6785.
340+
341+ Fix wrong put_page() usage in ccs_dump_page().
342+
343+Version 1.0.42 2020/05/05 Minor update release.
344+
345+ Synchronize with TOMOYO 1.8.7 release.
346+
347+ Loosen domainname validation and pathname validation.
348+
349+Version 1.0.43 2020/08/08 Minor update release.
350+
351+ Synchronize with TOMOYO revision 6816.
352+
353+ Fix domain transition preference.
354+
355+Version 1.0.44 2020/08/20 Minor update release.
356+
357+ Synchronize with TOMOYO revision 6821.
358+
359+ Fix ccs_realpath() fallback.
360+
361+ Fix wrong ccs_search_binary_handler() mapping.
362+
363+Version 1.0.45 2020/11/11 Minor update release.
364+
365+ Synchronize with TOMOYO 1.8.8 release.
366+
367+ Fix LSM hook detection on ARM64.
368+
369+Version 1.0.46 2020/11/12 Minor update release.
370+
371+ Since ccsecurity_exports.load_policy is initialized to NULL in AKARI,
372+ calling ccsecurity_exports.load_policy() before ccs_permission_init() is
373+ called (changed in revision 654) caused kernel panic as soon as loading
374+ akari.ko module. Since AKARI directly calls ccs_load_policy(), there is
375+ no need to use ccsecurity_exports.load_policy().
376+
377+Version 1.0.47 2021/04/01 Minor update release.
378+
379+ Synchronize with TOMOYO 1.8.9 release.
380+
381+ Skip permission checks for fileless execution requests.
382+
383+ Fix ccs_kernel_service().
384+
385+Version 1.0.48 2023/05/27 Security update release.
386+
387+ When ccs_start_execve() failed before CCS_TASK_IS_IN_EXECVE is set,
388+ ccs_clear_execve(-1, ptr) was not called. As a result, retried execve()
389+ request did not check execute permission. This bug affects only 2.6.29
390+ and later kernels.
--- tags/patches/1.0.48/lsm-2.6.0-vfs.c (nonexistent)
+++ tags/patches/1.0.48/lsm-2.6.0-vfs.c (revision 695)
@@ -0,0 +1,1588 @@
1+/*
2+ * lsm.c
3+ *
4+ * Copyright (C) 2010-2015 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5+ *
6+ * Version: 1.0.48 2023/05/27
7+ */
8+
9+#include "internal.h"
10+#include "probe.h"
11+
12+/* Prototype definition. */
13+
14+static int __ccs_alloc_task_security(const struct task_struct *task);
15+static void __ccs_free_task_security(const struct task_struct *task);
16+
17+/* Dummy security context for avoiding NULL pointer dereference. */
18+static struct ccs_security ccs_oom_security = {
19+ .ccs_domain_info = &ccs_kernel_domain
20+};
21+
22+/* Dummy security context for avoiding NULL pointer dereference. */
23+static struct ccs_security ccs_default_security = {
24+ .ccs_domain_info = &ccs_kernel_domain
25+};
26+
27+/* List of "struct ccs_security". */
28+struct list_head ccs_task_security_list[CCS_MAX_TASK_SECURITY_HASH];
29+/* Lock for protecting ccs_task_security_list[]. */
30+static DEFINE_SPINLOCK(ccs_task_security_list_lock);
31+
32+/* Dummy marker for calling security_bprm_free(). */
33+static const unsigned long ccs_bprm_security;
34+
35+/* For exporting variables and functions. */
36+struct ccsecurity_exports ccsecurity_exports;
37+/* Members are updated by loadable kernel module. */
38+struct ccsecurity_operations ccsecurity_ops;
39+
40+/* Function pointers originally registered by register_security(). */
41+static struct security_operations original_security_ops /* = *security_ops; */;
42+
43+#ifdef CONFIG_AKARI_TRACE_EXECVE_COUNT
44+
45+/**
46+ * ccs_update_ee_counter - Update "struct ccs_execve" counter.
47+ *
48+ * @count: Count to increment or decrement.
49+ *
50+ * Returns updated counter.
51+ */
52+static unsigned int ccs_update_ee_counter(int count)
53+{
54+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) || defined(atomic_add_return)
55+ /* Debug counter for detecting "struct ccs_execve" memory leak. */
56+ static atomic_t ccs_ee_counter = ATOMIC_INIT(0);
57+ return atomic_add_return(count, &ccs_ee_counter);
58+#else
59+ static DEFINE_SPINLOCK(ccs_ee_lock);
60+ static unsigned int ccs_ee_counter;
61+ unsigned long flags;
62+ spin_lock_irqsave(&ccs_ee_lock, flags);
63+ ccs_ee_counter += count;
64+ count = ccs_ee_counter;
65+ spin_unlock_irqrestore(&ccs_ee_lock, flags);
66+ return count;
67+#endif
68+}
69+
70+/**
71+ * ccs_audit_alloc_execve - Audit allocation of "struct ccs_execve".
72+ *
73+ * @ee: Pointer to "struct ccs_execve".
74+ *
75+ * Returns nothing.
76+ */
77+void ccs_audit_alloc_execve(const struct ccs_execve * const ee)
78+{
79+ printk(KERN_INFO "AKARI: Allocated %p by pid=%u (count=%u)\n", ee,
80+ current->pid, ccs_update_ee_counter(1) - 1);
81+}
82+
83+/**
84+ * ccs_audit_free_execve - Audit release of "struct ccs_execve".
85+ *
86+ * @ee: Pointer to "struct ccs_execve".
87+ * @task: True if released by current task, false otherwise.
88+ *
89+ * Returns nothing.
90+ */
91+void ccs_audit_free_execve(const struct ccs_execve * const ee,
92+ const bool is_current)
93+{
94+ const unsigned int tmp = ccs_update_ee_counter(-1);
95+ if (is_current)
96+ printk(KERN_INFO "AKARI: Releasing %p by pid=%u (count=%u)\n",
97+ ee, current->pid, tmp);
98+ else
99+ printk(KERN_INFO "AKARI: Releasing %p by kernel (count=%u)\n",
100+ ee, tmp);
101+}
102+
103+#endif
104+
105+#if !defined(CONFIG_AKARI_DEBUG)
106+#define ccs_debug_trace(pos) do { } while (0)
107+#else
108+#define ccs_debug_trace(pos) \
109+ do { \
110+ static bool done; \
111+ if (!done) { \
112+ printk(KERN_INFO \
113+ "AKARI: Debug trace: " pos " of 4\n"); \
114+ done = true; \
115+ } \
116+ } while (0)
117+#endif
118+
119+/**
120+ * ccs_clear_execve - Release memory used by do_execve().
121+ *
122+ * @ret: 0 if do_execve() succeeded, negative value otherwise.
123+ * @security: Pointer to "struct ccs_security".
124+ *
125+ * Returns nothing.
126+ */
127+static void ccs_clear_execve(int ret, struct ccs_security *security)
128+{
129+ struct ccs_execve *ee;
130+ if (security == &ccs_default_security || security == &ccs_oom_security)
131+ return;
132+ ee = security->ee;
133+ security->ee = NULL;
134+ if (!ee)
135+ return;
136+ ccs_finish_execve(ret, ee);
137+}
138+
139+/**
140+ * ccs_task_alloc_security - Allocate memory for new tasks.
141+ *
142+ * @p: Pointer to "struct task_struct".
143+ *
144+ * Returns 0 on success, negative value otherwise.
145+ */
146+static int ccs_task_alloc_security(struct task_struct *p)
147+{
148+ int rc = __ccs_alloc_task_security(p);
149+ if (rc)
150+ return rc;
151+ while (!original_security_ops.task_alloc_security)
152+ smp_rmb();
153+ rc = original_security_ops.task_alloc_security(p);
154+ if (rc)
155+ __ccs_free_task_security(p);
156+ return rc;
157+}
158+
159+/**
160+ * ccs_task_free_security - Release memory for "struct task_struct".
161+ *
162+ * @p: Pointer to "struct task_struct".
163+ *
164+ * Returns nothing.
165+ */
166+static void ccs_task_free_security(struct task_struct *p)
167+{
168+ while (!original_security_ops.task_free_security)
169+ smp_rmb();
170+ original_security_ops.task_free_security(p);
171+ __ccs_free_task_security(p);
172+}
173+
174+/**
175+ * ccs_bprm_alloc_security - Allocate memory for "struct linux_binprm".
176+ *
177+ * @bprm: Pointer to "struct linux_binprm".
178+ *
179+ * Returns 0 on success, negative value otherwise.
180+ */
181+static int ccs_bprm_alloc_security(struct linux_binprm *bprm)
182+{
183+ int rc;
184+ while (!original_security_ops.bprm_alloc_security)
185+ smp_rmb();
186+ rc = original_security_ops.bprm_alloc_security(bprm);
187+ if (bprm->security || rc)
188+ return rc;
189+ /*
190+ * Update bprm->security to &ccs_bprm_security so that
191+ * security_bprm_free() is called even if do_execve() failed at
192+ * search_binary_handler() without allocating memory at
193+ * security_bprm_alloc(). This trick assumes that active LSM module
194+ * does not access bprm->security if that module did not allocate
195+ * memory at security_bprm_alloc().
196+ */
197+ bprm->security = (void *) &ccs_bprm_security;
198+ return 0;
199+}
200+
201+/**
202+ * ccs_bprm_free_security - Release memory for "struct linux_binprm".
203+ *
204+ * @bprm: Pointer to "struct linux_binprm".
205+ *
206+ * Returns nothing.
207+ */
208+static void ccs_bprm_free_security(struct linux_binprm *bprm)
209+{
210+ /*
211+ * If do_execve() succeeded, bprm->security will be updated to NULL at
212+ * security_bprm_compute_creds()/security_bprm_apply_creds() if
213+ * bprm->security was set to &ccs_bprm_security at
214+ * security_bprm_alloc().
215+ *
216+ * If do_execve() failed, bprm->security remains at &ccs_bprm_security
217+ * if bprm->security was set to &ccs_bprm_security at
218+ * security_bprm_alloc().
219+ *
220+ * And do_execve() does not call security_bprm_free() if do_execve()
221+ * failed and bprm->security == NULL. Therefore, do not call
222+ * original_security_ops.bprm_free_security() if bprm->security remains
223+ * at &ccs_bprm_security .
224+ */
225+ if (bprm->security != &ccs_bprm_security) {
226+ while (!original_security_ops.bprm_free_security)
227+ smp_rmb();
228+ original_security_ops.bprm_free_security(bprm);
229+ }
230+ /*
231+ * If do_execve() succeeded,
232+ * ccs_clear_execve(0, ccs_current_security());
233+ * is called before calling below one.
234+ * Thus, below call becomes no-op if do_execve() succeeded.
235+ */
236+ ccs_clear_execve(-1, ccs_current_security());
237+}
238+
239+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 6)
240+
241+/**
242+ * ccs_bprm_compute_creds - A hook which is called when do_execve() succeeded.
243+ *
244+ * @bprm: Pointer to "struct linux_binprm".
245+ *
246+ * Returns nothing.
247+ */
248+static void ccs_bprm_compute_creds(struct linux_binprm *bprm)
249+{
250+ if (bprm->security == &ccs_bprm_security)
251+ bprm->security = NULL;
252+ while (!original_security_ops.bprm_compute_creds)
253+ smp_rmb();
254+ original_security_ops.bprm_compute_creds(bprm);
255+ ccs_clear_execve(0, ccs_current_security());
256+}
257+
258+#else
259+
260+/**
261+ * ccs_bprm_apply_creds - A hook which is called when do_execve() succeeded.
262+ *
263+ * @bprm: Pointer to "struct linux_binprm".
264+ * @unsafe: Unsafe flag.
265+ *
266+ * Returns nothing.
267+ */
268+static void ccs_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
269+{
270+ if (bprm->security == &ccs_bprm_security)
271+ bprm->security = NULL;
272+ while (!original_security_ops.bprm_apply_creds)
273+ smp_rmb();
274+ original_security_ops.bprm_apply_creds(bprm, unsafe);
275+ ccs_clear_execve(0, ccs_current_security());
276+}
277+
278+#endif
279+
280+/**
281+ * ccs_bprm_check_security - Check permission for execve().
282+ *
283+ * @bprm: Pointer to "struct linux_binprm".
284+ *
285+ * Returns 0 on success, negative value otherwise.
286+ */
287+static int ccs_bprm_check_security(struct linux_binprm *bprm)
288+{
289+ struct ccs_security *security = ccs_current_security();
290+ if (security == &ccs_default_security || security == &ccs_oom_security)
291+ return -ENOMEM;
292+ if (!security->ee) {
293+ int rc;
294+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
295+ if (!ccs_policy_loaded)
296+ ccs_load_policy(bprm->filename);
297+#endif
298+ rc = ccs_start_execve(bprm, &security->ee);
299+ if (rc)
300+ return rc;
301+ }
302+ while (!original_security_ops.bprm_check_security)
303+ smp_rmb();
304+ return original_security_ops.bprm_check_security(bprm);
305+}
306+
307+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
308+
309+/**
310+ * ccs_open - Check permission for open().
311+ *
312+ * @f: Pointer to "struct file".
313+ *
314+ * Returns 0 on success, negative value otherwise.
315+ */
316+static int ccs_open(struct file *f)
317+{
318+ return ccs_open_permission(f->f_path.dentry, f->f_path.mnt,
319+ f->f_flags + 1);
320+}
321+
322+#endif
323+
324+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
325+
326+/**
327+ * ccs_dentry_open - Check permission for open().
328+ *
329+ * @f: Pointer to "struct file".
330+ *
331+ * Returns 0 on success, negative value otherwise.
332+ */
333+static int ccs_dentry_open(struct file *f)
334+{
335+ int rc = ccs_open(f);
336+ if (rc)
337+ return rc;
338+ while (!original_security_ops.dentry_open)
339+ smp_rmb();
340+ return original_security_ops.dentry_open(f);
341+}
342+
343+#else
344+
345+/**
346+ * ccs_open - Check permission for open().
347+ *
348+ * @inode: Pointer to "struct inode".
349+ * @mask: Open mode.
350+ * @nd: Pointer to "struct nameidata".
351+ *
352+ * Returns 0 on success, negative value otherwise.
353+ */
354+static int ccs_open(struct inode *inode, int mask, struct nameidata *nd)
355+{
356+ int flags;
357+ if (!nd || !nd->dentry)
358+ return 0;
359+ /* open_exec() passes MAY_EXEC . */
360+ if (mask == MAY_EXEC && inode && S_ISREG(inode->i_mode) &&
361+ (ccs_current_flags() & CCS_TASK_IS_IN_EXECVE))
362+ mask = MAY_READ;
363+ /*
364+ * This flags value is passed to ACC_MODE().
365+ * ccs_open_permission() for older versions uses old ACC_MODE().
366+ */
367+ switch (mask & (MAY_READ | MAY_WRITE)) {
368+ case MAY_READ:
369+ flags = 01;
370+ break;
371+ case MAY_WRITE:
372+ flags = 02;
373+ break;
374+ case MAY_READ | MAY_WRITE:
375+ flags = 03;
376+ break;
377+ default:
378+ return 0;
379+ }
380+ return ccs_open_permission(nd->dentry, nd->mnt, flags);
381+}
382+
383+/**
384+ * ccs_inode_permission - Check permission for open().
385+ *
386+ * @inode: Pointer to "struct inode".
387+ * @mask: Open mode.
388+ * @nd: Pointer to "struct nameidata".
389+ *
390+ * Returns 0 on success, negative value otherwise.
391+ *
392+ * Note that this hook is called from permission(), and may not be called for
393+ * open(). Maybe it is better to use security_file_permission().
394+ */
395+static int ccs_inode_permission(struct inode *inode, int mask,
396+ struct nameidata *nd)
397+{
398+ int rc = ccs_open(inode, mask, nd);
399+ if (rc)
400+ return rc;
401+ while (!original_security_ops.inode_permission)
402+ smp_rmb();
403+ return original_security_ops.inode_permission(inode, mask, nd);
404+}
405+
406+#endif
407+
408+/**
409+ * ccs_inode_setattr - Check permission for chown()/chgrp()/chmod()/truncate().
410+ *
411+ * @dentry: Pointer to "struct dentry".
412+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
413+ * @attr: Pointer to "struct iattr".
414+ *
415+ * Returns 0 on success, negative value otherwise.
416+ */
417+static int ccs_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
418+ struct iattr *attr)
419+{
420+ int rc = 0;
421+ if (attr->ia_valid & ATTR_UID)
422+ rc = ccs_chown_permission(dentry, mnt, attr->ia_uid, -1);
423+ if (!rc && (attr->ia_valid & ATTR_GID))
424+ rc = ccs_chown_permission(dentry, mnt, -1, attr->ia_gid);
425+ if (!rc && (attr->ia_valid & ATTR_MODE))
426+ rc = ccs_chmod_permission(dentry, mnt, attr->ia_mode);
427+ if (!rc && (attr->ia_valid & ATTR_SIZE))
428+ rc = ccs_truncate_permission(dentry, mnt);
429+ if (rc)
430+ return rc;
431+ while (!original_security_ops.inode_setattr)
432+ smp_rmb();
433+ return original_security_ops.inode_setattr(dentry, mnt, attr);
434+}
435+
436+/**
437+ * ccs_inode_getattr - Check permission for stat().
438+ *
439+ * @mnt: Pointer to "struct vfsmount".
440+ * @dentry: Pointer to "struct dentry".
441+ *
442+ * Returns 0 on success, negative value otherwise.
443+ */
444+static int ccs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
445+{
446+ int rc = ccs_getattr_permission(mnt, dentry);
447+ if (rc)
448+ return rc;
449+ while (!original_security_ops.inode_getattr)
450+ smp_rmb();
451+ return original_security_ops.inode_getattr(mnt, dentry);
452+}
453+
454+/**
455+ * ccs_inode_mknod - Check permission for mknod().
456+ *
457+ * @dir: Pointer to "struct inode".
458+ * @dentry: Pointer to "struct dentry".
459+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
460+ * @mode: Create mode.
461+ * @dev: Device major/minor number.
462+ *
463+ * Returns 0 on success, negative value otherwise.
464+ */
465+static int ccs_inode_mknod(struct inode *dir, struct dentry *dentry,
466+ struct vfsmount *mnt, int mode, dev_t dev)
467+{
468+ int rc = ccs_mknod_permission(dentry, mnt, mode, dev);
469+ if (rc)
470+ return rc;
471+ while (!original_security_ops.inode_mknod)
472+ smp_rmb();
473+ return original_security_ops.inode_mknod(dir, dentry, mnt, mode, dev);
474+}
475+
476+/**
477+ * ccs_inode_mkdir - Check permission for mkdir().
478+ *
479+ * @dir: Pointer to "struct inode".
480+ * @dentry: Pointer to "struct dentry".
481+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
482+ * @mode: Create mode.
483+ *
484+ * Returns 0 on success, negative value otherwise.
485+ */
486+static int ccs_inode_mkdir(struct inode *dir, struct dentry *dentry,
487+ struct vfsmount *mnt, int mode)
488+{
489+ int rc = ccs_mkdir_permission(dentry, mnt, mode);
490+ if (rc)
491+ return rc;
492+ while (!original_security_ops.inode_mkdir)
493+ smp_rmb();
494+ return original_security_ops.inode_mkdir(dir, dentry, mnt, mode);
495+}
496+
497+/**
498+ * ccs_inode_rmdir - Check permission for rmdir().
499+ *
500+ * @dir: Pointer to "struct inode".
501+ * @dentry: Pointer to "struct dentry".
502+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
503+ *
504+ * Returns 0 on success, negative value otherwise.
505+ */
506+static int ccs_inode_rmdir(struct inode *dir, struct dentry *dentry,
507+ struct vfsmount *mnt)
508+{
509+ int rc = ccs_rmdir_permission(dentry, mnt);
510+ if (rc)
511+ return rc;
512+ while (!original_security_ops.inode_rmdir)
513+ smp_rmb();
514+ return original_security_ops.inode_rmdir(dir, dentry, mnt);
515+}
516+
517+/**
518+ * ccs_inode_unlink - Check permission for unlink().
519+ *
520+ * @dir: Pointer to "struct inode".
521+ * @dentry: Pointer to "struct dentry".
522+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
523+ *
524+ * Returns 0 on success, negative value otherwise.
525+ */
526+static int ccs_inode_unlink(struct inode *dir, struct dentry *dentry,
527+ struct vfsmount *mnt)
528+{
529+ int rc = ccs_unlink_permission(dentry, mnt);
530+ if (rc)
531+ return rc;
532+ while (!original_security_ops.inode_unlink)
533+ smp_rmb();
534+ return original_security_ops.inode_unlink(dir, dentry, mnt);
535+}
536+
537+/**
538+ * ccs_inode_symlink - Check permission for symlink().
539+ *
540+ * @dir: Pointer to "struct inode".
541+ * @dentry: Pointer to "struct dentry".
542+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
543+ * @old_name: Content of symbolic link.
544+ *
545+ * Returns 0 on success, negative value otherwise.
546+ */
547+static int ccs_inode_symlink(struct inode *dir, struct dentry *dentry,
548+ struct vfsmount *mnt, const char *old_name)
549+{
550+ int rc = ccs_symlink_permission(dentry, mnt, old_name);
551+ if (rc)
552+ return rc;
553+ while (!original_security_ops.inode_symlink)
554+ smp_rmb();
555+ return original_security_ops.inode_symlink(dir, dentry, mnt, old_name);
556+}
557+
558+/**
559+ * ccs_inode_rename - Check permission for rename().
560+ *
561+ * @old_dir: Pointer to "struct inode".
562+ * @old_dentry: Pointer to "struct dentry".
563+ * @old_mnt: Pointer to "struct vfsmount". Maybe NULL.
564+ * @new_dir: Pointer to "struct inode".
565+ * @new_dentry: Pointer to "struct dentry".
566+ * @new_mnt: Pointer to "struct vfsmount". Maybe NULL.
567+ *
568+ * Returns 0 on success, negative value otherwise.
569+ */
570+static int ccs_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
571+ struct vfsmount *old_mnt, struct inode *new_dir,
572+ struct dentry *new_dentry,
573+ struct vfsmount *new_mnt)
574+{
575+ int rc = ccs_rename_permission(old_dentry, new_dentry, new_mnt);
576+ if (rc)
577+ return rc;
578+ while (!original_security_ops.inode_rename)
579+ smp_rmb();
580+ return original_security_ops.inode_rename(old_dir, old_dentry, old_mnt,
581+ new_dir, new_dentry,
582+ new_mnt);
583+}
584+
585+/**
586+ * ccs_inode_link - Check permission for link().
587+ *
588+ * @old_dentry: Pointer to "struct dentry".
589+ * @old_mnt: Pointer to "struct vfsmount". Maybe NULL.
590+ * @dir: Pointer to "struct inode".
591+ * @new_dentry: Pointer to "struct dentry".
592+ * @new_mnt: Pointer to "struct vfsmount". Maybe NULL.
593+ *
594+ * Returns 0 on success, negative value otherwise.
595+ */
596+static int ccs_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
597+ struct inode *dir, struct dentry *new_dentry,
598+ struct vfsmount *new_mnt)
599+{
600+ int rc = ccs_link_permission(old_dentry, new_dentry, new_mnt);
601+ if (rc)
602+ return rc;
603+ while (!original_security_ops.inode_link)
604+ smp_rmb();
605+ return original_security_ops.inode_link(old_dentry, old_mnt, dir,
606+ new_dentry, new_mnt);
607+}
608+
609+/**
610+ * ccs_inode_create - Check permission for creat().
611+ *
612+ * @dir: Pointer to "struct inode".
613+ * @dentry: Pointer to "struct dentry".
614+ * @mnt: Pointer to "struct vfsmount". Maybe NULL.
615+ * @mode: Create mode.
616+ *
617+ * Returns 0 on success, negative value otherwise.
618+ */
619+static int ccs_inode_create(struct inode *dir, struct dentry *dentry,
620+ struct vfsmount *mnt, int mode)
621+{
622+ int rc = ccs_mknod_permission(dentry, mnt, mode, 0);
623+ if (rc)
624+ return rc;
625+ while (!original_security_ops.inode_create)
626+ smp_rmb();
627+ return original_security_ops.inode_create(dir, dentry, mnt, mode);
628+}
629+
630+#ifdef CONFIG_SECURITY_NETWORK
631+
632+#include <net/sock.h>
633+
634+/* Structure for remembering an accept()ed socket's status. */
635+struct ccs_socket_tag {
636+ struct list_head list;
637+ struct inode *inode;
638+ int status;
639+ struct rcu_head rcu;
640+};
641+
642+/*
643+ * List for managing accept()ed sockets.
644+ * Since we don't need to keep an accept()ed socket into this list after
645+ * once the permission was granted, the number of entries in this list is
646+ * likely small. Therefore, we don't use hash tables.
647+ */
648+static LIST_HEAD(ccs_accepted_socket_list);
649+/* Lock for protecting ccs_accepted_socket_list . */
650+static DEFINE_SPINLOCK(ccs_accepted_socket_list_lock);
651+
652+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
653+
654+/**
655+ * ccs_socket_rcu_free - RCU callback for releasing "struct ccs_socket_tag".
656+ *
657+ * @rcu: Pointer to "struct rcu_head".
658+ *
659+ * Returns nothing.
660+ */
661+static void ccs_socket_rcu_free(struct rcu_head *rcu)
662+{
663+ struct ccs_socket_tag *ptr = container_of(rcu, typeof(*ptr), rcu);
664+ kfree(ptr);
665+}
666+
667+#else
668+
669+/**
670+ * ccs_socket_rcu_free - RCU callback for releasing "struct ccs_socket_tag".
671+ *
672+ * @arg: Pointer to "void".
673+ *
674+ * Returns nothing.
675+ */
676+static void ccs_socket_rcu_free(void *arg)
677+{
678+ struct ccs_socket_tag *ptr = arg;
679+ kfree(ptr);
680+}
681+
682+#endif
683+
684+/**
685+ * ccs_update_socket_tag - Update tag associated with accept()ed sockets.
686+ *
687+ * @inode: Pointer to "struct inode".
688+ * @status: New status.
689+ *
690+ * Returns nothing.
691+ *
692+ * If @status == 0, memory for that socket will be released after RCU grace
693+ * period.
694+ */
695+static void ccs_update_socket_tag(struct inode *inode, int status)
696+{
697+ struct ccs_socket_tag *ptr;
698+ /*
699+ * Protect whole section because multiple threads may call this
700+ * function with same "sock" via ccs_validate_socket().
701+ */
702+ spin_lock(&ccs_accepted_socket_list_lock);
703+ rcu_read_lock();
704+ list_for_each_entry_rcu(ptr, &ccs_accepted_socket_list, list) {
705+ if (ptr->inode != inode)
706+ continue;
707+ ptr->status = status;
708+ if (status)
709+ break;
710+ list_del_rcu(&ptr->list);
711+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
712+ call_rcu(&ptr->rcu, ccs_socket_rcu_free);
713+#else
714+ call_rcu(&ptr->rcu, ccs_socket_rcu_free, ptr);
715+#endif
716+ break;
717+ }
718+ rcu_read_unlock();
719+ spin_unlock(&ccs_accepted_socket_list_lock);
720+}
721+
722+/**
723+ * ccs_validate_socket - Check post accept() permission if needed.
724+ *
725+ * @sock: Pointer to "struct socket".
726+ *
727+ * Returns 0 on success, negative value otherwise.
728+ */
729+static int ccs_validate_socket(struct socket *sock)
730+{
731+ struct inode *inode = SOCK_INODE(sock);
732+ struct ccs_socket_tag *ptr;
733+ int ret = 0;
734+ rcu_read_lock();
735+ list_for_each_entry_rcu(ptr, &ccs_accepted_socket_list, list) {
736+ if (ptr->inode != inode)
737+ continue;
738+ ret = ptr->status;
739+ break;
740+ }
741+ rcu_read_unlock();
742+ if (ret <= 0)
743+ /*
744+ * This socket is not an accept()ed socket or this socket is
745+ * an accept()ed socket and post accept() permission is done.
746+ */
747+ return ret;
748+ /*
749+ * Check post accept() permission now.
750+ *
751+ * Strictly speaking, we need to pass both listen()ing socket and
752+ * accept()ed socket to __ccs_socket_post_accept_permission().
753+ * But since socket's family and type are same for both sockets,
754+ * passing the accept()ed socket in place for the listen()ing socket
755+ * will work.
756+ */
757+ ret = ccs_socket_post_accept_permission(sock, sock);
758+ /*
759+ * If permission was granted, we forget that this is an accept()ed
760+ * socket. Otherwise, we remember that this socket needs to return
761+ * error for subsequent socketcalls.
762+ */
763+ ccs_update_socket_tag(inode, ret);
764+ return ret;
765+}
766+
767+/**
768+ * ccs_socket_accept - Check permission for accept().
769+ *
770+ * @sock: Pointer to "struct socket".
771+ * @newsock: Pointer to "struct socket".
772+ *
773+ * Returns 0 on success, negative value otherwise.
774+ *
775+ * This hook is used for setting up environment for doing post accept()
776+ * permission check. If dereferencing sock->ops->something() were ordered by
777+ * rcu_dereference(), we could replace sock->ops with "a copy of original
778+ * sock->ops with modified sock->ops->accept()" using rcu_assign_pointer()
779+ * in order to do post accept() permission check before returning to userspace.
780+ * If we make the copy in security_socket_post_create(), it would be possible
781+ * to safely replace sock->ops here, but we don't do so because we don't want
782+ * to allocate memory for sockets which do not call sock->ops->accept().
783+ * Therefore, we do post accept() permission check upon next socket syscalls
784+ * rather than between sock->ops->accept() and returning to userspace.
785+ * This means that if a socket was close()d before calling some socket
786+ * syscalls, post accept() permission check will not be done.
787+ */
788+static int ccs_socket_accept(struct socket *sock, struct socket *newsock)
789+{
790+ struct ccs_socket_tag *ptr;
791+ int rc = ccs_validate_socket(sock);
792+ if (rc < 0)
793+ return rc;
794+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
795+ if (!ptr)
796+ return -ENOMEM;
797+ while (!original_security_ops.socket_accept)
798+ smp_rmb();
799+ rc = original_security_ops.socket_accept(sock, newsock);
800+ if (rc) {
801+ kfree(ptr);
802+ return rc;
803+ }
804+ /*
805+ * Subsequent LSM hooks will receive "newsock". Therefore, I mark
806+ * "newsock" as "an accept()ed socket but post accept() permission
807+ * check is not done yet" by allocating memory using inode of the
808+ * "newsock" as a search key.
809+ */
810+ ptr->inode = SOCK_INODE(newsock);
811+ ptr->status = 1; /* Check post accept() permission later. */
812+ spin_lock(&ccs_accepted_socket_list_lock);
813+ list_add_tail_rcu(&ptr->list, &ccs_accepted_socket_list);
814+ spin_unlock(&ccs_accepted_socket_list_lock);
815+ return 0;
816+}
817+
818+/**
819+ * ccs_socket_listen - Check permission for listen().
820+ *
821+ * @sock: Pointer to "struct socket".
822+ * @backlog: Backlog parameter.
823+ *
824+ * Returns 0 on success, negative value otherwise.
825+ */
826+static int ccs_socket_listen(struct socket *sock, int backlog)
827+{
828+ int rc = ccs_validate_socket(sock);
829+ if (rc < 0)
830+ return rc;
831+ rc = ccs_socket_listen_permission(sock);
832+ if (rc)
833+ return rc;
834+ while (!original_security_ops.socket_listen)
835+ smp_rmb();
836+ return original_security_ops.socket_listen(sock, backlog);
837+}
838+
839+/**
840+ * ccs_socket_connect - Check permission for connect().
841+ *
842+ * @sock: Pointer to "struct socket".
843+ * @addr: Pointer to "struct sockaddr".
844+ * @addr_len: Size of @addr.
845+ *
846+ * Returns 0 on success, negative value otherwise.
847+ */
848+static int ccs_socket_connect(struct socket *sock, struct sockaddr *addr,
849+ int addr_len)
850+{
851+ int rc = ccs_validate_socket(sock);
852+ if (rc < 0)
853+ return rc;
854+ rc = ccs_socket_connect_permission(sock, addr, addr_len);
855+ if (rc)
856+ return rc;
857+ while (!original_security_ops.socket_connect)
858+ smp_rmb();
859+ return original_security_ops.socket_connect(sock, addr, addr_len);
860+}
861+
862+/**
863+ * ccs_socket_bind - Check permission for bind().
864+ *
865+ * @sock: Pointer to "struct socket".
866+ * @addr: Pointer to "struct sockaddr".
867+ * @addr_len: Size of @addr.
868+ *
869+ * Returns 0 on success, negative value otherwise.
870+ */
871+static int ccs_socket_bind(struct socket *sock, struct sockaddr *addr,
872+ int addr_len)
873+{
874+ int rc = ccs_validate_socket(sock);
875+ if (rc < 0)
876+ return rc;
877+ rc = ccs_socket_bind_permission(sock, addr, addr_len);
878+ if (rc)
879+ return rc;
880+ while (!original_security_ops.socket_bind)
881+ smp_rmb();
882+ return original_security_ops.socket_bind(sock, addr, addr_len);
883+}
884+
885+/**
886+ * ccs_socket_sendmsg - Check permission for sendmsg().
887+ *
888+ * @sock: Pointer to "struct socket".
889+ * @msg: Pointer to "struct msghdr".
890+ * @size: Size of message.
891+ *
892+ * Returns 0 on success, negative value otherwise.
893+ */
894+static int ccs_socket_sendmsg(struct socket *sock, struct msghdr *msg,
895+ int size)
896+{
897+ int rc = ccs_validate_socket(sock);
898+ if (rc < 0)
899+ return rc;
900+ rc = ccs_socket_sendmsg_permission(sock, msg, size);
901+ if (rc)
902+ return rc;
903+ while (!original_security_ops.socket_sendmsg)
904+ smp_rmb();
905+ return original_security_ops.socket_sendmsg(sock, msg, size);
906+}
907+
908+/**
909+ * ccs_socket_recvmsg - Check permission for recvmsg().
910+ *
911+ * @sock: Pointer to "struct socket".
912+ * @msg: Pointer to "struct msghdr".
913+ * @size: Size of message.
914+ * @flags: Flags.
915+ *
916+ * Returns 0 on success, negative value otherwise.
917+ */
918+static int ccs_socket_recvmsg(struct socket *sock, struct msghdr *msg,
919+ int size, int flags)
920+{
921+ int rc = ccs_validate_socket(sock);
922+ if (rc < 0)
923+ return rc;
924+ while (!original_security_ops.socket_recvmsg)
925+ smp_rmb();
926+ return original_security_ops.socket_recvmsg(sock, msg, size, flags);
927+}
928+
929+/**
930+ * ccs_socket_getsockname - Check permission for getsockname().
931+ *
932+ * @sock: Pointer to "struct socket".
933+ *
934+ * Returns 0 on success, negative value otherwise.
935+ */
936+static int ccs_socket_getsockname(struct socket *sock)
937+{
938+ int rc = ccs_validate_socket(sock);
939+ if (rc < 0)
940+ return rc;
941+ while (!original_security_ops.socket_getsockname)
942+ smp_rmb();
943+ return original_security_ops.socket_getsockname(sock);
944+}
945+
946+/**
947+ * ccs_socket_getpeername - Check permission for getpeername().
948+ *
949+ * @sock: Pointer to "struct socket".
950+ *
951+ * Returns 0 on success, negative value otherwise.
952+ */
953+static int ccs_socket_getpeername(struct socket *sock)
954+{
955+ int rc = ccs_validate_socket(sock);
956+ if (rc < 0)
957+ return rc;
958+ while (!original_security_ops.socket_getpeername)
959+ smp_rmb();
960+ return original_security_ops.socket_getpeername(sock);
961+}
962+
963+/**
964+ * ccs_socket_getsockopt - Check permission for getsockopt().
965+ *
966+ * @sock: Pointer to "struct socket".
967+ * @level: Level.
968+ * @optname: Option's name,
969+ *
970+ * Returns 0 on success, negative value otherwise.
971+ */
972+static int ccs_socket_getsockopt(struct socket *sock, int level, int optname)
973+{
974+ int rc = ccs_validate_socket(sock);
975+ if (rc < 0)
976+ return rc;
977+ while (!original_security_ops.socket_getsockopt)
978+ smp_rmb();
979+ return original_security_ops.socket_getsockopt(sock, level, optname);
980+}
981+
982+/**
983+ * ccs_socket_setsockopt - Check permission for setsockopt().
984+ *
985+ * @sock: Pointer to "struct socket".
986+ * @level: Level.
987+ * @optname: Option's name,
988+ *
989+ * Returns 0 on success, negative value otherwise.
990+ */
991+static int ccs_socket_setsockopt(struct socket *sock, int level, int optname)
992+{
993+ int rc = ccs_validate_socket(sock);
994+ if (rc < 0)
995+ return rc;
996+ while (!original_security_ops.socket_setsockopt)
997+ smp_rmb();
998+ return original_security_ops.socket_setsockopt(sock, level, optname);
999+}
1000+
1001+/**
1002+ * ccs_socket_shutdown - Check permission for shutdown().
1003+ *
1004+ * @sock: Pointer to "struct socket".
1005+ * @how: Shutdown mode.
1006+ *
1007+ * Returns 0 on success, negative value otherwise.
1008+ */
1009+static int ccs_socket_shutdown(struct socket *sock, int how)
1010+{
1011+ int rc = ccs_validate_socket(sock);
1012+ if (rc < 0)
1013+ return rc;
1014+ while (!original_security_ops.socket_shutdown)
1015+ smp_rmb();
1016+ return original_security_ops.socket_shutdown(sock, how);
1017+}
1018+
1019+#define SOCKFS_MAGIC 0x534F434B
1020+
1021+/**
1022+ * ccs_inode_free_security - Release memory associated with an inode.
1023+ *
1024+ * @inode: Pointer to "struct inode".
1025+ *
1026+ * Returns nothing.
1027+ *
1028+ * We use this hook for releasing memory associated with an accept()ed socket.
1029+ */
1030+static void ccs_inode_free_security(struct inode *inode)
1031+{
1032+ while (!original_security_ops.inode_free_security)
1033+ smp_rmb();
1034+ original_security_ops.inode_free_security(inode);
1035+ if (inode->i_sb && inode->i_sb->s_magic == SOCKFS_MAGIC)
1036+ ccs_update_socket_tag(inode, 0);
1037+}
1038+
1039+#endif
1040+
1041+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
1042+
1043+/**
1044+ * ccs_sb_pivotroot - Check permission for pivot_root().
1045+ *
1046+ * @old_nd: Pointer to "struct nameidata".
1047+ * @new_nd: Pointer to "struct nameidata".
1048+ *
1049+ * Returns 0 on success, negative value otherwise.
1050+ */
1051+static int ccs_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
1052+{
1053+ int rc = ccs_pivot_root_permission(old_nd, new_nd);
1054+ if (rc)
1055+ return rc;
1056+ while (!original_security_ops.sb_pivotroot)
1057+ smp_rmb();
1058+ return original_security_ops.sb_pivotroot(old_nd, new_nd);
1059+}
1060+
1061+/**
1062+ * ccs_sb_mount - Check permission for mount().
1063+ *
1064+ * @dev_name: Name of device file.
1065+ * @nd: Pointer to "struct nameidata".
1066+ * @type: Name of filesystem type. Maybe NULL.
1067+ * @flags: Mount options.
1068+ * @data_page: Optional data. Maybe NULL.
1069+ *
1070+ * Returns 0 on success, negative value otherwise.
1071+ */
1072+static int ccs_sb_mount(char *dev_name, struct nameidata *nd, char *type,
1073+ unsigned long flags, void *data_page)
1074+{
1075+ int rc = ccs_mount_permission(dev_name, nd, type, flags, data_page);
1076+ if (rc)
1077+ return rc;
1078+ while (!original_security_ops.sb_mount)
1079+ smp_rmb();
1080+ return original_security_ops.sb_mount(dev_name, nd, type, flags,
1081+ data_page);
1082+}
1083+
1084+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
1085+
1086+/**
1087+ * ccs_sb_pivotroot - Check permission for pivot_root().
1088+ *
1089+ * @old_nd: Pointer to "struct nameidata".
1090+ * @new_nd: Pointer to "struct nameidata".
1091+ *
1092+ * Returns 0 on success, negative value otherwise.
1093+ */
1094+static int ccs_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
1095+{
1096+ int rc = ccs_pivot_root_permission(&old_nd->path, &new_nd->path);
1097+ if (rc)
1098+ return rc;
1099+ while (!original_security_ops.sb_pivotroot)
1100+ smp_rmb();
1101+ return original_security_ops.sb_pivotroot(old_nd, new_nd);
1102+}
1103+
1104+/**
1105+ * ccs_sb_mount - Check permission for mount().
1106+ *
1107+ * @dev_name: Name of device file.
1108+ * @nd: Pointer to "struct nameidata".
1109+ * @type: Name of filesystem type. Maybe NULL.
1110+ * @flags: Mount options.
1111+ * @data_page: Optional data. Maybe NULL.
1112+ *
1113+ * Returns 0 on success, negative value otherwise.
1114+ */
1115+static int ccs_sb_mount(char *dev_name, struct nameidata *nd, char *type,
1116+ unsigned long flags, void *data_page)
1117+{
1118+ int rc = ccs_mount_permission(dev_name, &nd->path, type, flags,
1119+ data_page);
1120+ if (rc)
1121+ return rc;
1122+ while (!original_security_ops.sb_mount)
1123+ smp_rmb();
1124+ return original_security_ops.sb_mount(dev_name, nd, type, flags,
1125+ data_page);
1126+}
1127+
1128+#else
1129+
1130+/**
1131+ * ccs_sb_pivotroot - Check permission for pivot_root().
1132+ *
1133+ * @old_path: Pointer to "struct path".
1134+ * @new_path: Pointer to "struct path".
1135+ *
1136+ * Returns 0 on success, negative value otherwise.
1137+ */
1138+static int ccs_sb_pivotroot(struct path *old_path, struct path *new_path)
1139+{
1140+ int rc = ccs_pivot_root_permission(old_path, new_path);
1141+ if (rc)
1142+ return rc;
1143+ while (!original_security_ops.sb_pivotroot)
1144+ smp_rmb();
1145+ return original_security_ops.sb_pivotroot(old_path, new_path);
1146+}
1147+
1148+/**
1149+ * ccs_sb_mount - Check permission for mount().
1150+ *
1151+ * @dev_name: Name of device file.
1152+ * @path: Pointer to "struct path".
1153+ * @type: Name of filesystem type. Maybe NULL.
1154+ * @flags: Mount options.
1155+ * @data_page: Optional data. Maybe NULL.
1156+ *
1157+ * Returns 0 on success, negative value otherwise.
1158+ */
1159+static int ccs_sb_mount(char *dev_name, struct path *path, char *type,
1160+ unsigned long flags, void *data_page)
1161+{
1162+ int rc = ccs_mount_permission(dev_name, path, type, flags, data_page);
1163+ if (rc)
1164+ return rc;
1165+ while (!original_security_ops.sb_mount)
1166+ smp_rmb();
1167+ return original_security_ops.sb_mount(dev_name, path, type, flags,
1168+ data_page);
1169+}
1170+
1171+#endif
1172+
1173+/**
1174+ * ccs_sb_umount - Check permission for umount().
1175+ *
1176+ * @mnt: Pointer to "struct vfsmount".
1177+ * @flags: Unmount flags.
1178+ *
1179+ * Returns 0 on success, negative value otherwise.
1180+ */
1181+static int ccs_sb_umount(struct vfsmount *mnt, int flags)
1182+{
1183+ int rc = ccs_umount_permission(mnt, flags);
1184+ if (rc)
1185+ return rc;
1186+ while (!original_security_ops.sb_umount)
1187+ smp_rmb();
1188+ return original_security_ops.sb_umount(mnt, flags);
1189+}
1190+
1191+/**
1192+ * ccs_file_fcntl - Check permission for fcntl().
1193+ *
1194+ * @file: Pointer to "struct file".
1195+ * @cmd: Command number.
1196+ * @arg: Value for @cmd.
1197+ *
1198+ * Returns 0 on success, negative value otherwise.
1199+ */
1200+static int ccs_file_fcntl(struct file *file, unsigned int cmd,
1201+ unsigned long arg)
1202+{
1203+ int rc = ccs_fcntl_permission(file, cmd, arg);
1204+ if (rc)
1205+ return rc;
1206+ while (!original_security_ops.file_fcntl)
1207+ smp_rmb();
1208+ return original_security_ops.file_fcntl(file, cmd, arg);
1209+}
1210+
1211+/**
1212+ * ccs_file_ioctl - Check permission for ioctl().
1213+ *
1214+ * @filp: Pointer to "struct file".
1215+ * @cmd: Command number.
1216+ * @arg: Value for @cmd.
1217+ *
1218+ * Returns 0 on success, negative value otherwise.
1219+ */
1220+static int ccs_file_ioctl(struct file *filp, unsigned int cmd,
1221+ unsigned long arg)
1222+{
1223+ int rc = ccs_ioctl_permission(filp, cmd, arg);
1224+ if (rc)
1225+ return rc;
1226+ while (!original_security_ops.file_ioctl)
1227+ smp_rmb();
1228+ return original_security_ops.file_ioctl(filp, cmd, arg);
1229+}
1230+
1231+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) && defined(CONFIG_SYSCTL_SYSCALL)
1232+int ccs_path_permission(struct ccs_request_info *r, u8 operation,
1233+ const struct ccs_path_info *filename);
1234+
1235+/**
1236+ * ccs_prepend - Copy of prepend() in fs/dcache.c.
1237+ *
1238+ * @buffer: Pointer to "struct char *".
1239+ * @buflen: Pointer to int which holds size of @buffer.
1240+ * @str: String to copy.
1241+ *
1242+ * Returns 0 on success, negative value otherwise.
1243+ *
1244+ * @buffer and @buflen are updated upon success.
1245+ */
1246+static int ccs_prepend(char **buffer, int *buflen, const char *str)
1247+{
1248+ int namelen = strlen(str);
1249+ if (*buflen < namelen)
1250+ return -ENOMEM;
1251+ *buflen -= namelen;
1252+ *buffer -= namelen;
1253+ memcpy(*buffer, str, namelen);
1254+ return 0;
1255+}
1256+
1257+/**
1258+ * ccs_sysctl_permission - Check permission for sysctl().
1259+ *
1260+ * @table: Pointer to "struct ctl_table".
1261+ * @op: Operation. (MAY_READ and/or MAY_WRITE)
1262+ *
1263+ * Returns 0 on success, negative value otherwise.
1264+ */
1265+static int ccs_sysctl(struct ctl_table *table, int op)
1266+{
1267+ int error;
1268+ struct ccs_path_info buf;
1269+ struct ccs_request_info r;
1270+ int buflen;
1271+ char *buffer;
1272+ int idx;
1273+ while (!original_security_ops.sysctl)
1274+ smp_rmb();
1275+ error = original_security_ops.sysctl(table, op);
1276+ if (error)
1277+ return error;
1278+ op &= MAY_READ | MAY_WRITE;
1279+ if (!op)
1280+ return 0;
1281+ buffer = NULL;
1282+ buf.name = NULL;
1283+ idx = ccs_read_lock();
1284+ if (ccs_init_request_info(&r, CCS_MAC_FILE_OPEN)
1285+ == CCS_CONFIG_DISABLED)
1286+ goto out;
1287+ error = -ENOMEM;
1288+ buflen = 4096;
1289+ buffer = kmalloc(buflen, CCS_GFP_FLAGS);
1290+ if (buffer) {
1291+ char *end = buffer + buflen;
1292+ *--end = '\0';
1293+ buflen--;
1294+ while (table) {
1295+ char num[32];
1296+ const char *sp = table->procname;
1297+ if (!sp) {
1298+ memset(num, 0, sizeof(num));
1299+ snprintf(num, sizeof(num) - 1, "=%d=",
1300+ table->ctl_name);
1301+ sp = num;
1302+ }
1303+ if (ccs_prepend(&end, &buflen, sp) ||
1304+ ccs_prepend(&end, &buflen, "/"))
1305+ goto out;
1306+ table = table->parent;
1307+ }
1308+ if (ccs_prepend(&end, &buflen, "proc:/sys"))
1309+ goto out;
1310+ buf.name = ccs_encode(end);
1311+ }
1312+ if (buf.name) {
1313+ ccs_fill_path_info(&buf);
1314+ if (op & MAY_READ)
1315+ error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
1316+ else
1317+ error = 0;
1318+ if (!error && (op & MAY_WRITE))
1319+ error = ccs_path_permission(&r, CCS_TYPE_WRITE, &buf);
1320+ }
1321+out:
1322+ ccs_read_unlock(idx);
1323+ kfree(buf.name);
1324+ kfree(buffer);
1325+ return error;
1326+}
1327+
1328+#endif
1329+
1330+/*
1331+ * Why not to copy all operations by "original_security_ops = *ops" ?
1332+ * Because copying byte array is not atomic. Reader checks
1333+ * original_security_ops.op != NULL before doing original_security_ops.op().
1334+ * Thus, modifying original_security_ops.op has to be atomic.
1335+ */
1336+#define swap_security_ops(op) \
1337+ original_security_ops.op = ops->op; smp_wmb(); ops->op = ccs_##op;
1338+
1339+/**
1340+ * ccs_update_security_ops - Overwrite original "struct security_operations".
1341+ *
1342+ * @ops: Pointer to "struct security_operations".
1343+ *
1344+ * Returns nothing.
1345+ */
1346+static void __init ccs_update_security_ops(struct security_operations *ops)
1347+{
1348+ /* Security context allocator. */
1349+ swap_security_ops(task_alloc_security);
1350+ swap_security_ops(task_free_security);
1351+ swap_security_ops(bprm_alloc_security);
1352+ swap_security_ops(bprm_free_security);
1353+ /* Security context updater for successful execve(). */
1354+ swap_security_ops(bprm_check_security);
1355+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 6)
1356+ swap_security_ops(bprm_compute_creds);
1357+#else
1358+ swap_security_ops(bprm_apply_creds);
1359+#endif
1360+ /* Various permission checker. */
1361+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1362+ swap_security_ops(dentry_open);
1363+#else
1364+ swap_security_ops(inode_permission);
1365+#endif
1366+ swap_security_ops(file_fcntl);
1367+ swap_security_ops(file_ioctl);
1368+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) && defined(CONFIG_SYSCTL_SYSCALL)
1369+ swap_security_ops(sysctl);
1370+#endif
1371+ swap_security_ops(sb_pivotroot);
1372+ swap_security_ops(sb_mount);
1373+ swap_security_ops(sb_umount);
1374+ swap_security_ops(inode_mknod);
1375+ swap_security_ops(inode_mkdir);
1376+ swap_security_ops(inode_rmdir);
1377+ swap_security_ops(inode_unlink);
1378+ swap_security_ops(inode_symlink);
1379+ swap_security_ops(inode_rename);
1380+ swap_security_ops(inode_link);
1381+ swap_security_ops(inode_create);
1382+ swap_security_ops(inode_setattr);
1383+ swap_security_ops(inode_getattr);
1384+#ifdef CONFIG_SECURITY_NETWORK
1385+ swap_security_ops(socket_bind);
1386+ swap_security_ops(socket_connect);
1387+ swap_security_ops(socket_listen);
1388+ swap_security_ops(socket_sendmsg);
1389+ swap_security_ops(socket_recvmsg);
1390+ swap_security_ops(socket_getsockname);
1391+ swap_security_ops(socket_getpeername);
1392+ swap_security_ops(socket_getsockopt);
1393+ swap_security_ops(socket_setsockopt);
1394+ swap_security_ops(socket_shutdown);
1395+ swap_security_ops(socket_accept);
1396+ swap_security_ops(inode_free_security);
1397+#endif
1398+}
1399+
1400+#undef swap_security_ops
1401+
1402+/**
1403+ * ccs_init - Initialize this module.
1404+ *
1405+ * Returns 0 on success, negative value otherwise.
1406+ */
1407+static int __init ccs_init(void)
1408+{
1409+ struct security_operations *ops = probe_security_ops();
1410+ if (!ops)
1411+ goto out;
1412+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1413+ ccsecurity_exports.find_task_by_vpid = probe_find_task_by_vpid();
1414+ if (!ccsecurity_exports.find_task_by_vpid)
1415+ goto out;
1416+ ccsecurity_exports.find_task_by_pid_ns = probe_find_task_by_pid_ns();
1417+ if (!ccsecurity_exports.find_task_by_pid_ns)
1418+ goto out;
1419+#endif
1420+ ccsecurity_exports.vfsmount_lock = probe_vfsmount_lock();
1421+ if (!ccsecurity_exports.vfsmount_lock)
1422+ goto out;
1423+ ccs_main_init();
1424+ ccs_update_security_ops(ops);
1425+ printk(KERN_INFO "AKARI: 1.0.48 2023/05/27\n");
1426+ printk(KERN_INFO
1427+ "Access Keeping And Regulating Instrument registered.\n");
1428+ return 0;
1429+out:
1430+ return -EINVAL;
1431+}
1432+
1433+module_init(ccs_init);
1434+MODULE_LICENSE("GPL");
1435+
1436+/**
1437+ * ccs_used_by_cred - Check whether the given domain is in use or not.
1438+ *
1439+ * @domain: Pointer to "struct ccs_domain_info".
1440+ *
1441+ * Returns true if @domain is in use, false otherwise.
1442+ *
1443+ * Caller holds rcu_read_lock().
1444+ */
1445+bool ccs_used_by_cred(const struct ccs_domain_info *domain)
1446+{
1447+ return false;
1448+}
1449+
1450+/**
1451+ * ccs_add_task_security - Add "struct ccs_security" to list.
1452+ *
1453+ * @ptr: Pointer to "struct ccs_security".
1454+ * @list: Pointer to "struct list_head".
1455+ *
1456+ * Returns nothing.
1457+ */
1458+static void ccs_add_task_security(struct ccs_security *ptr,
1459+ struct list_head *list)
1460+{
1461+ unsigned long flags;
1462+ spin_lock_irqsave(&ccs_task_security_list_lock, flags);
1463+ list_add_rcu(&ptr->list, list);
1464+ spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
1465+}
1466+
1467+/**
1468+ * __ccs_alloc_task_security - Allocate memory for new tasks.
1469+ *
1470+ * @task: Pointer to "struct task_struct".
1471+ *
1472+ * Returns 0 on success, negative value otherwise.
1473+ */
1474+static int __ccs_alloc_task_security(const struct task_struct *task)
1475+{
1476+ struct ccs_security *old_security = ccs_current_security();
1477+ struct ccs_security *new_security = kzalloc(sizeof(*new_security),
1478+ GFP_KERNEL);
1479+ struct list_head *list = &ccs_task_security_list
1480+ [hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
1481+ if (!new_security)
1482+ return -ENOMEM;
1483+ new_security->task = task;
1484+ new_security->ccs_domain_info = old_security->ccs_domain_info;
1485+ new_security->ccs_flags = old_security->ccs_flags;
1486+ ccs_add_task_security(new_security, list);
1487+ return 0;
1488+}
1489+
1490+/**
1491+ * ccs_find_task_security - Find "struct ccs_security" for given task.
1492+ *
1493+ * @task: Pointer to "struct task_struct".
1494+ *
1495+ * Returns pointer to "struct ccs_security" on success, &ccs_oom_security on
1496+ * out of memory, &ccs_default_security otherwise.
1497+ *
1498+ * If @task is current thread and "struct ccs_security" for current thread was
1499+ * not found, I try to allocate it. But if allocation failed, current thread
1500+ * will be killed by SIGKILL. Note that if current->pid == 1, sending SIGKILL
1501+ * won't work.
1502+ */
1503+struct ccs_security *ccs_find_task_security(const struct task_struct *task)
1504+{
1505+ struct ccs_security *ptr;
1506+ struct list_head *list = &ccs_task_security_list
1507+ [hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
1508+ /* Make sure INIT_LIST_HEAD() in ccs_mm_init() takes effect. */
1509+ while (!list->next)
1510+ smp_rmb();
1511+ rcu_read_lock();
1512+ list_for_each_entry_rcu(ptr, list, list) {
1513+ if (ptr->task != task)
1514+ continue;
1515+ rcu_read_unlock();
1516+ return ptr;
1517+ }
1518+ rcu_read_unlock();
1519+ if (task != current)
1520+ return &ccs_default_security;
1521+ /* Use GFP_ATOMIC because caller may have called rcu_read_lock(). */
1522+ ptr = kzalloc(sizeof(*ptr), GFP_ATOMIC);
1523+ if (!ptr) {
1524+ printk(KERN_WARNING "Unable to allocate memory for pid=%u\n",
1525+ task->pid);
1526+ send_sig(SIGKILL, current, 0);
1527+ return &ccs_oom_security;
1528+ }
1529+ *ptr = ccs_default_security;
1530+ ptr->task = task;
1531+ ccs_add_task_security(ptr, list);
1532+ return ptr;
1533+}
1534+
1535+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
1536+
1537+/**
1538+ * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
1539+ *
1540+ * @rcu: Pointer to "struct rcu_head".
1541+ *
1542+ * Returns nothing.
1543+ */
1544+static void ccs_rcu_free(struct rcu_head *rcu)
1545+{
1546+ struct ccs_security *ptr = container_of(rcu, typeof(*ptr), rcu);
1547+ kfree(ptr);
1548+}
1549+
1550+#else
1551+
1552+/**
1553+ * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
1554+ *
1555+ * @arg: Pointer to "void".
1556+ *
1557+ * Returns nothing.
1558+ */
1559+static void ccs_rcu_free(void *arg)
1560+{
1561+ struct ccs_security *ptr = arg;
1562+ kfree(ptr);
1563+}
1564+
1565+#endif
1566+
1567+/**
1568+ * __ccs_free_task_security - Release memory associated with "struct task_struct".
1569+ *
1570+ * @task: Pointer to "struct task_struct".
1571+ *
1572+ * Returns nothing.
1573+ */
1574+static void __ccs_free_task_security(const struct task_struct *task)
1575+{
1576+ unsigned long flags;
1577+ struct ccs_security *ptr = ccs_find_task_security(task);
1578+ if (ptr == &ccs_default_security || ptr == &ccs_oom_security)
1579+ return;
1580+ spin_lock_irqsave(&ccs_task_security_list_lock, flags);
1581+ list_del_rcu(&ptr->list);
1582+ spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
1583+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
1584+ call_rcu(&ptr->rcu, ccs_rcu_free);
1585+#else
1586+ call_rcu(&ptr->rcu, ccs_rcu_free, ptr);
1587+#endif
1588+}
--- tags/patches/1.0.48/lsm-2.6.0.c (nonexistent)
+++ tags/patches/1.0.48/lsm-2.6.0.c (revision 695)
@@ -0,0 +1,1568 @@
1+/*
2+ * lsm.c
3+ *
4+ * Copyright (C) 2010-2015 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5+ *
6+ * Version: 1.0.48 2023/05/27
7+ */
8+
9+#include "internal.h"
10+#include "probe.h"
11+
12+/* Prototype definition. */
13+
14+static int __ccs_alloc_task_security(const struct task_struct *task);
15+static void __ccs_free_task_security(const struct task_struct *task);
16+
17+/* Dummy security context for avoiding NULL pointer dereference. */
18+static struct ccs_security ccs_oom_security = {
19+ .ccs_domain_info = &ccs_kernel_domain
20+};
21+
22+/* Dummy security context for avoiding NULL pointer dereference. */
23+static struct ccs_security ccs_default_security = {
24+ .ccs_domain_info = &ccs_kernel_domain
25+};
26+
27+/* List of "struct ccs_security". */
28+struct list_head ccs_task_security_list[CCS_MAX_TASK_SECURITY_HASH];
29+/* Lock for protecting ccs_task_security_list[]. */
30+static DEFINE_SPINLOCK(ccs_task_security_list_lock);
31+
32+/* Dummy marker for calling security_bprm_free(). */
33+static const unsigned long ccs_bprm_security;
34+
35+/* For exporting variables and functions. */
36+struct ccsecurity_exports ccsecurity_exports;
37+/* Members are updated by loadable kernel module. */
38+struct ccsecurity_operations ccsecurity_ops;
39+
40+/* Function pointers originally registered by register_security(). */
41+static struct security_operations original_security_ops /* = *security_ops; */;
42+
43+#ifdef CONFIG_AKARI_TRACE_EXECVE_COUNT
44+
45+/**
46+ * ccs_update_ee_counter - Update "struct ccs_execve" counter.
47+ *
48+ * @count: Count to increment or decrement.
49+ *
50+ * Returns updated counter.
51+ */
52+static unsigned int ccs_update_ee_counter(int count)
53+{
54+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10) || defined(atomic_add_return)
55+ /* Debug counter for detecting "struct ccs_execve" memory leak. */
56+ static atomic_t ccs_ee_counter = ATOMIC_INIT(0);
57+ return atomic_add_return(count, &ccs_ee_counter);
58+#else
59+ static DEFINE_SPINLOCK(ccs_ee_lock);
60+ static unsigned int ccs_ee_counter;
61+ unsigned long flags;
62+ spin_lock_irqsave(&ccs_ee_lock, flags);
63+ ccs_ee_counter += count;
64+ count = ccs_ee_counter;
65+ spin_unlock_irqrestore(&ccs_ee_lock, flags);
66+ return count;
67+#endif
68+}
69+
70+/**
71+ * ccs_audit_alloc_execve - Audit allocation of "struct ccs_execve".
72+ *
73+ * @ee: Pointer to "struct ccs_execve".
74+ *
75+ * Returns nothing.
76+ */
77+void ccs_audit_alloc_execve(const struct ccs_execve * const ee)
78+{
79+ printk(KERN_INFO "AKARI: Allocated %p by pid=%u (count=%u)\n", ee,
80+ current->pid, ccs_update_ee_counter(1) - 1);
81+}
82+
83+/**
84+ * ccs_audit_free_execve - Audit release of "struct ccs_execve".
85+ *
86+ * @ee: Pointer to "struct ccs_execve".
87+ * @task: True if released by current task, false otherwise.
88+ *
89+ * Returns nothing.
90+ */
91+void ccs_audit_free_execve(const struct ccs_execve * const ee,
92+ const bool is_current)
93+{
94+ const unsigned int tmp = ccs_update_ee_counter(-1);
95+ if (is_current)
96+ printk(KERN_INFO "AKARI: Releasing %p by pid=%u (count=%u)\n",
97+ ee, current->pid, tmp);
98+ else
99+ printk(KERN_INFO "AKARI: Releasing %p by kernel (count=%u)\n",
100+ ee, tmp);
101+}
102+
103+#endif
104+
105+#if !defined(CONFIG_AKARI_DEBUG)
106+#define ccs_debug_trace(pos) do { } while (0)
107+#else
108+#define ccs_debug_trace(pos) \
109+ do { \
110+ static bool done; \
111+ if (!done) { \
112+ printk(KERN_INFO \
113+ "AKARI: Debug trace: " pos " of 4\n"); \
114+ done = true; \
115+ } \
116+ } while (0)
117+#endif
118+
119+/**
120+ * ccs_clear_execve - Release memory used by do_execve().
121+ *
122+ * @ret: 0 if do_execve() succeeded, negative value otherwise.
123+ * @security: Pointer to "struct ccs_security".
124+ *
125+ * Returns nothing.
126+ */
127+static void ccs_clear_execve(int ret, struct ccs_security *security)
128+{
129+ struct ccs_execve *ee;
130+ if (security == &ccs_default_security || security == &ccs_oom_security)
131+ return;
132+ ee = security->ee;
133+ security->ee = NULL;
134+ if (!ee)
135+ return;
136+ ccs_finish_execve(ret, ee);
137+}
138+
139+/**
140+ * ccs_task_alloc_security - Allocate memory for new tasks.
141+ *
142+ * @p: Pointer to "struct task_struct".
143+ *
144+ * Returns 0 on success, negative value otherwise.
145+ */
146+static int ccs_task_alloc_security(struct task_struct *p)
147+{
148+ int rc = __ccs_alloc_task_security(p);
149+ if (rc)
150+ return rc;
151+ while (!original_security_ops.task_alloc_security)
152+ smp_rmb();
153+ rc = original_security_ops.task_alloc_security(p);
154+ if (rc)
155+ __ccs_free_task_security(p);
156+ return rc;
157+}
158+
159+/**
160+ * ccs_task_free_security - Release memory for "struct task_struct".
161+ *
162+ * @p: Pointer to "struct task_struct".
163+ *
164+ * Returns nothing.
165+ */
166+static void ccs_task_free_security(struct task_struct *p)
167+{
168+ while (!original_security_ops.task_free_security)
169+ smp_rmb();
170+ original_security_ops.task_free_security(p);
171+ __ccs_free_task_security(p);
172+}
173+
174+/**
175+ * ccs_bprm_alloc_security - Allocate memory for "struct linux_binprm".
176+ *
177+ * @bprm: Pointer to "struct linux_binprm".
178+ *
179+ * Returns 0 on success, negative value otherwise.
180+ */
181+static int ccs_bprm_alloc_security(struct linux_binprm *bprm)
182+{
183+ int rc;
184+ while (!original_security_ops.bprm_alloc_security)
185+ smp_rmb();
186+ rc = original_security_ops.bprm_alloc_security(bprm);
187+ if (bprm->security || rc)
188+ return rc;
189+ /*
190+ * Update bprm->security to &ccs_bprm_security so that
191+ * security_bprm_free() is called even if do_execve() failed at
192+ * search_binary_handler() without allocating memory at
193+ * security_bprm_alloc(). This trick assumes that active LSM module
194+ * does not access bprm->security if that module did not allocate
195+ * memory at security_bprm_alloc().
196+ */
197+ bprm->security = (void *) &ccs_bprm_security;
198+ return 0;
199+}
200+
201+/**
202+ * ccs_bprm_free_security - Release memory for "struct linux_binprm".
203+ *
204+ * @bprm: Pointer to "struct linux_binprm".
205+ *
206+ * Returns nothing.
207+ */
208+static void ccs_bprm_free_security(struct linux_binprm *bprm)
209+{
210+ /*
211+ * If do_execve() succeeded, bprm->security will be updated to NULL at
212+ * security_bprm_compute_creds()/security_bprm_apply_creds() if
213+ * bprm->security was set to &ccs_bprm_security at
214+ * security_bprm_alloc().
215+ *
216+ * If do_execve() failed, bprm->security remains at &ccs_bprm_security
217+ * if bprm->security was set to &ccs_bprm_security at
218+ * security_bprm_alloc().
219+ *
220+ * And do_execve() does not call security_bprm_free() if do_execve()
221+ * failed and bprm->security == NULL. Therefore, do not call
222+ * original_security_ops.bprm_free_security() if bprm->security remains
223+ * at &ccs_bprm_security .
224+ */
225+ if (bprm->security != &ccs_bprm_security) {
226+ while (!original_security_ops.bprm_free_security)
227+ smp_rmb();
228+ original_security_ops.bprm_free_security(bprm);
229+ }
230+ /*
231+ * If do_execve() succeeded,
232+ * ccs_clear_execve(0, ccs_current_security());
233+ * is called before calling below one.
234+ * Thus, below call becomes no-op if do_execve() succeeded.
235+ */
236+ ccs_clear_execve(-1, ccs_current_security());
237+}
238+
239+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 6)
240+
241+/**
242+ * ccs_bprm_compute_creds - A hook which is called when do_execve() succeeded.
243+ *
244+ * @bprm: Pointer to "struct linux_binprm".
245+ *
246+ * Returns nothing.
247+ */
248+static void ccs_bprm_compute_creds(struct linux_binprm *bprm)
249+{
250+ if (bprm->security == &ccs_bprm_security)
251+ bprm->security = NULL;
252+ while (!original_security_ops.bprm_compute_creds)
253+ smp_rmb();
254+ original_security_ops.bprm_compute_creds(bprm);
255+ ccs_clear_execve(0, ccs_current_security());
256+}
257+
258+#else
259+
260+/**
261+ * ccs_bprm_apply_creds - A hook which is called when do_execve() succeeded.
262+ *
263+ * @bprm: Pointer to "struct linux_binprm".
264+ * @unsafe: Unsafe flag.
265+ *
266+ * Returns nothing.
267+ */
268+static void ccs_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
269+{
270+ if (bprm->security == &ccs_bprm_security)
271+ bprm->security = NULL;
272+ while (!original_security_ops.bprm_apply_creds)
273+ smp_rmb();
274+ original_security_ops.bprm_apply_creds(bprm, unsafe);
275+ ccs_clear_execve(0, ccs_current_security());
276+}
277+
278+#endif
279+
280+/**
281+ * ccs_bprm_check_security - Check permission for execve().
282+ *
283+ * @bprm: Pointer to "struct linux_binprm".
284+ *
285+ * Returns 0 on success, negative value otherwise.
286+ */
287+static int ccs_bprm_check_security(struct linux_binprm *bprm)
288+{
289+ struct ccs_security *security = ccs_current_security();
290+ if (security == &ccs_default_security || security == &ccs_oom_security)
291+ return -ENOMEM;
292+ if (!security->ee) {
293+ int rc;
294+#ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
295+ if (!ccs_policy_loaded)
296+ ccs_load_policy(bprm->filename);
297+#endif
298+ rc = ccs_start_execve(bprm, &security->ee);
299+ if (rc)
300+ return rc;
301+ }
302+ while (!original_security_ops.bprm_check_security)
303+ smp_rmb();
304+ return original_security_ops.bprm_check_security(bprm);
305+}
306+
307+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
308+
309+/**
310+ * ccs_open - Check permission for open().
311+ *
312+ * @f: Pointer to "struct file".
313+ *
314+ * Returns 0 on success, negative value otherwise.
315+ */
316+static int ccs_open(struct file *f)
317+{
318+ return ccs_open_permission(f->f_path.dentry, f->f_path.mnt,
319+ f->f_flags + 1);
320+}
321+
322+#endif
323+
324+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
325+
326+/**
327+ * ccs_dentry_open - Check permission for open().
328+ *
329+ * @f: Pointer to "struct file".
330+ *
331+ * Returns 0 on success, negative value otherwise.
332+ */
333+static int ccs_dentry_open(struct file *f)
334+{
335+ int rc = ccs_open(f);
336+ if (rc)
337+ return rc;
338+ while (!original_security_ops.dentry_open)
339+ smp_rmb();
340+ return original_security_ops.dentry_open(f);
341+}
342+
343+#else
344+
345+/**
346+ * ccs_open - Check permission for open().
347+ *
348+ * @inode: Pointer to "struct inode".
349+ * @mask: Open mode.
350+ * @nd: Pointer to "struct nameidata".
351+ *
352+ * Returns 0 on success, negative value otherwise.
353+ */
354+static int ccs_open(struct inode *inode, int mask, struct nameidata *nd)
355+{
356+ int flags;
357+ if (!nd || !nd->dentry)
358+ return 0;
359+ /* open_exec() passes MAY_EXEC . */
360+ if (mask == MAY_EXEC && inode && S_ISREG(inode->i_mode) &&
361+ (ccs_current_flags() & CCS_TASK_IS_IN_EXECVE))
362+ mask = MAY_READ;
363+ /*
364+ * This flags value is passed to ACC_MODE().
365+ * ccs_open_permission() for older versions uses old ACC_MODE().
366+ */
367+ switch (mask & (MAY_READ | MAY_WRITE)) {
368+ case MAY_READ:
369+ flags = 01;
370+ break;
371+ case MAY_WRITE:
372+ flags = 02;
373+ break;
374+ case MAY_READ | MAY_WRITE:
375+ flags = 03;
376+ break;
377+ default:
378+ return 0;
379+ }
380+ return ccs_open_permission(nd->dentry, nd->mnt, flags);
381+}
382+
383+/**
384+ * ccs_inode_permission - Check permission for open().
385+ *
386+ * @inode: Pointer to "struct inode".
387+ * @mask: Open mode.
388+ * @nd: Pointer to "struct nameidata".
389+ *
390+ * Returns 0 on success, negative value otherwise.
391+ *
392+ * Note that this hook is called from permission(), and may not be called for
393+ * open(). Maybe it is better to use security_file_permission().
394+ */
395+static int ccs_inode_permission(struct inode *inode, int mask,
396+ struct nameidata *nd)
397+{
398+ int rc = ccs_open(inode, mask, nd);
399+ if (rc)
400+ return rc;
401+ while (!original_security_ops.inode_permission)
402+ smp_rmb();
403+ return original_security_ops.inode_permission(inode, mask, nd);
404+}
405+
406+#endif
407+
408+/**
409+ * ccs_inode_setattr - Check permission for chown()/chgrp()/chmod()/truncate().
410+ *
411+ * @dentry: Pointer to "struct dentry".
412+ * @attr: Pointer to "struct iattr".
413+ *
414+ * Returns 0 on success, negative value otherwise.
415+ */
416+static int ccs_inode_setattr(struct dentry *dentry, struct iattr *attr)
417+{
418+ int rc = 0;
419+ if (attr->ia_valid & ATTR_UID)
420+ rc = ccs_chown_permission(dentry, NULL, attr->ia_uid, -1);
421+ if (!rc && (attr->ia_valid & ATTR_GID))
422+ rc = ccs_chown_permission(dentry, NULL, -1, attr->ia_gid);
423+ if (!rc && (attr->ia_valid & ATTR_MODE))
424+ rc = ccs_chmod_permission(dentry, NULL, attr->ia_mode);
425+ if (!rc && (attr->ia_valid & ATTR_SIZE))
426+ rc = ccs_truncate_permission(dentry, NULL);
427+ if (rc)
428+ return rc;
429+ while (!original_security_ops.inode_setattr)
430+ smp_rmb();
431+ return original_security_ops.inode_setattr(dentry, attr);
432+}
433+
434+/**
435+ * ccs_inode_getattr - Check permission for stat().
436+ *
437+ * @mnt: Pointer to "struct vfsmount".
438+ * @dentry: Pointer to "struct dentry".
439+ *
440+ * Returns 0 on success, negative value otherwise.
441+ */
442+static int ccs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
443+{
444+ int rc = ccs_getattr_permission(mnt, dentry);
445+ if (rc)
446+ return rc;
447+ while (!original_security_ops.inode_getattr)
448+ smp_rmb();
449+ return original_security_ops.inode_getattr(mnt, dentry);
450+}
451+
452+/**
453+ * ccs_inode_mknod - Check permission for mknod().
454+ *
455+ * @dir: Pointer to "struct inode".
456+ * @dentry: Pointer to "struct dentry".
457+ * @mode: Create mode.
458+ * @dev: Device major/minor number.
459+ *
460+ * Returns 0 on success, negative value otherwise.
461+ */
462+static int ccs_inode_mknod(struct inode *dir, struct dentry *dentry, int mode,
463+ dev_t dev)
464+{
465+ int rc = ccs_mknod_permission(dentry, NULL, mode, dev);
466+ if (rc)
467+ return rc;
468+ while (!original_security_ops.inode_mknod)
469+ smp_rmb();
470+ return original_security_ops.inode_mknod(dir, dentry, mode, dev);
471+}
472+
473+/**
474+ * ccs_inode_mkdir - Check permission for mkdir().
475+ *
476+ * @dir: Pointer to "struct inode".
477+ * @dentry: Pointer to "struct dentry".
478+ * @mode: Create mode.
479+ *
480+ * Returns 0 on success, negative value otherwise.
481+ */
482+static int ccs_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
483+{
484+ int rc = ccs_mkdir_permission(dentry, NULL, mode);
485+ if (rc)
486+ return rc;
487+ while (!original_security_ops.inode_mkdir)
488+ smp_rmb();
489+ return original_security_ops.inode_mkdir(dir, dentry, mode);
490+}
491+
492+/**
493+ * ccs_inode_rmdir - Check permission for rmdir().
494+ *
495+ * @dir: Pointer to "struct inode".
496+ * @dentry: Pointer to "struct dentry".
497+ *
498+ * Returns 0 on success, negative value otherwise.
499+ */
500+static int ccs_inode_rmdir(struct inode *dir, struct dentry *dentry)
501+{
502+ int rc = ccs_rmdir_permission(dentry, NULL);
503+ if (rc)
504+ return rc;
505+ while (!original_security_ops.inode_rmdir)
506+ smp_rmb();
507+ return original_security_ops.inode_rmdir(dir, dentry);
508+}
509+
510+/**
511+ * ccs_inode_unlink - Check permission for unlink().
512+ *
513+ * @dir: Pointer to "struct inode".
514+ * @dentry: Pointer to "struct dentry".
515+ *
516+ * Returns 0 on success, negative value otherwise.
517+ */
518+static int ccs_inode_unlink(struct inode *dir, struct dentry *dentry)
519+{
520+ int rc = ccs_unlink_permission(dentry, NULL);
521+ if (rc)
522+ return rc;
523+ while (!original_security_ops.inode_unlink)
524+ smp_rmb();
525+ return original_security_ops.inode_unlink(dir, dentry);
526+}
527+
528+/**
529+ * ccs_inode_symlink - Check permission for symlink().
530+ *
531+ * @dir: Pointer to "struct inode".
532+ * @dentry: Pointer to "struct dentry".
533+ * @old_name: Content of symbolic link.
534+ *
535+ * Returns 0 on success, negative value otherwise.
536+ */
537+static int ccs_inode_symlink(struct inode *dir, struct dentry *dentry,
538+ const char *old_name)
539+{
540+ int rc = ccs_symlink_permission(dentry, NULL, old_name);
541+ if (rc)
542+ return rc;
543+ while (!original_security_ops.inode_symlink)
544+ smp_rmb();
545+ return original_security_ops.inode_symlink(dir, dentry, old_name);
546+}
547+
548+/**
549+ * ccs_inode_rename - Check permission for rename().
550+ *
551+ * @old_dir: Pointer to "struct inode".
552+ * @old_dentry: Pointer to "struct dentry".
553+ * @new_dir: Pointer to "struct inode".
554+ * @new_dentry: Pointer to "struct dentry".
555+ *
556+ * Returns 0 on success, negative value otherwise.
557+ */
558+static int ccs_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
559+ struct inode *new_dir, struct dentry *new_dentry)
560+{
561+ int rc = ccs_rename_permission(old_dentry, new_dentry, NULL);
562+ if (rc)
563+ return rc;
564+ while (!original_security_ops.inode_rename)
565+ smp_rmb();
566+ return original_security_ops.inode_rename(old_dir, old_dentry, new_dir,
567+ new_dentry);
568+}
569+
570+/**
571+ * ccs_inode_link - Check permission for link().
572+ *
573+ * @old_dentry: Pointer to "struct dentry".
574+ * @dir: Pointer to "struct inode".
575+ * @new_dentry: Pointer to "struct dentry".
576+ *
577+ * Returns 0 on success, negative value otherwise.
578+ */
579+static int ccs_inode_link(struct dentry *old_dentry, struct inode *dir,
580+ struct dentry *new_dentry)
581+{
582+ int rc = ccs_link_permission(old_dentry, new_dentry, NULL);
583+ if (rc)
584+ return rc;
585+ while (!original_security_ops.inode_link)
586+ smp_rmb();
587+ return original_security_ops.inode_link(old_dentry, dir, new_dentry);
588+}
589+
590+/**
591+ * ccs_inode_create - Check permission for creat().
592+ *
593+ * @dir: Pointer to "struct inode".
594+ * @dentry: Pointer to "struct dentry".
595+ * @mode: Create mode.
596+ *
597+ * Returns 0 on success, negative value otherwise.
598+ */
599+static int ccs_inode_create(struct inode *dir, struct dentry *dentry,
600+ int mode)
601+{
602+ int rc = ccs_mknod_permission(dentry, NULL, mode, 0);
603+ if (rc)
604+ return rc;
605+ while (!original_security_ops.inode_create)
606+ smp_rmb();
607+ return original_security_ops.inode_create(dir, dentry, mode);
608+}
609+
610+#ifdef CONFIG_SECURITY_NETWORK
611+
612+#include <net/sock.h>
613+
614+/* Structure for remembering an accept()ed socket's status. */
615+struct ccs_socket_tag {
616+ struct list_head list;
617+ struct inode *inode;
618+ int status;
619+ struct rcu_head rcu;
620+};
621+
622+/*
623+ * List for managing accept()ed sockets.
624+ * Since we don't need to keep an accept()ed socket into this list after
625+ * once the permission was granted, the number of entries in this list is
626+ * likely small. Therefore, we don't use hash tables.
627+ */
628+static LIST_HEAD(ccs_accepted_socket_list);
629+/* Lock for protecting ccs_accepted_socket_list . */
630+static DEFINE_SPINLOCK(ccs_accepted_socket_list_lock);
631+
632+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
633+
634+/**
635+ * ccs_socket_rcu_free - RCU callback for releasing "struct ccs_socket_tag".
636+ *
637+ * @rcu: Pointer to "struct rcu_head".
638+ *
639+ * Returns nothing.
640+ */
641+static void ccs_socket_rcu_free(struct rcu_head *rcu)
642+{
643+ struct ccs_socket_tag *ptr = container_of(rcu, typeof(*ptr), rcu);
644+ kfree(ptr);
645+}
646+
647+#else
648+
649+/**
650+ * ccs_socket_rcu_free - RCU callback for releasing "struct ccs_socket_tag".
651+ *
652+ * @arg: Pointer to "void".
653+ *
654+ * Returns nothing.
655+ */
656+static void ccs_socket_rcu_free(void *arg)
657+{
658+ struct ccs_socket_tag *ptr = arg;
659+ kfree(ptr);
660+}
661+
662+#endif
663+
664+/**
665+ * ccs_update_socket_tag - Update tag associated with accept()ed sockets.
666+ *
667+ * @inode: Pointer to "struct inode".
668+ * @status: New status.
669+ *
670+ * Returns nothing.
671+ *
672+ * If @status == 0, memory for that socket will be released after RCU grace
673+ * period.
674+ */
675+static void ccs_update_socket_tag(struct inode *inode, int status)
676+{
677+ struct ccs_socket_tag *ptr;
678+ /*
679+ * Protect whole section because multiple threads may call this
680+ * function with same "sock" via ccs_validate_socket().
681+ */
682+ spin_lock(&ccs_accepted_socket_list_lock);
683+ rcu_read_lock();
684+ list_for_each_entry_rcu(ptr, &ccs_accepted_socket_list, list) {
685+ if (ptr->inode != inode)
686+ continue;
687+ ptr->status = status;
688+ if (status)
689+ break;
690+ list_del_rcu(&ptr->list);
691+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
692+ call_rcu(&ptr->rcu, ccs_socket_rcu_free);
693+#else
694+ call_rcu(&ptr->rcu, ccs_socket_rcu_free, ptr);
695+#endif
696+ break;
697+ }
698+ rcu_read_unlock();
699+ spin_unlock(&ccs_accepted_socket_list_lock);
700+}
701+
702+/**
703+ * ccs_validate_socket - Check post accept() permission if needed.
704+ *
705+ * @sock: Pointer to "struct socket".
706+ *
707+ * Returns 0 on success, negative value otherwise.
708+ */
709+static int ccs_validate_socket(struct socket *sock)
710+{
711+ struct inode *inode = SOCK_INODE(sock);
712+ struct ccs_socket_tag *ptr;
713+ int ret = 0;
714+ rcu_read_lock();
715+ list_for_each_entry_rcu(ptr, &ccs_accepted_socket_list, list) {
716+ if (ptr->inode != inode)
717+ continue;
718+ ret = ptr->status;
719+ break;
720+ }
721+ rcu_read_unlock();
722+ if (ret <= 0)
723+ /*
724+ * This socket is not an accept()ed socket or this socket is
725+ * an accept()ed socket and post accept() permission is done.
726+ */
727+ return ret;
728+ /*
729+ * Check post accept() permission now.
730+ *
731+ * Strictly speaking, we need to pass both listen()ing socket and
732+ * accept()ed socket to __ccs_socket_post_accept_permission().
733+ * But since socket's family and type are same for both sockets,
734+ * passing the accept()ed socket in place for the listen()ing socket
735+ * will work.
736+ */
737+ ret = ccs_socket_post_accept_permission(sock, sock);
738+ /*
739+ * If permission was granted, we forget that this is an accept()ed
740+ * socket. Otherwise, we remember that this socket needs to return
741+ * error for subsequent socketcalls.
742+ */
743+ ccs_update_socket_tag(inode, ret);
744+ return ret;
745+}
746+
747+/**
748+ * ccs_socket_accept - Check permission for accept().
749+ *
750+ * @sock: Pointer to "struct socket".
751+ * @newsock: Pointer to "struct socket".
752+ *
753+ * Returns 0 on success, negative value otherwise.
754+ *
755+ * This hook is used for setting up environment for doing post accept()
756+ * permission check. If dereferencing sock->ops->something() were ordered by
757+ * rcu_dereference(), we could replace sock->ops with "a copy of original
758+ * sock->ops with modified sock->ops->accept()" using rcu_assign_pointer()
759+ * in order to do post accept() permission check before returning to userspace.
760+ * If we make the copy in security_socket_post_create(), it would be possible
761+ * to safely replace sock->ops here, but we don't do so because we don't want
762+ * to allocate memory for sockets which do not call sock->ops->accept().
763+ * Therefore, we do post accept() permission check upon next socket syscalls
764+ * rather than between sock->ops->accept() and returning to userspace.
765+ * This means that if a socket was close()d before calling some socket
766+ * syscalls, post accept() permission check will not be done.
767+ */
768+static int ccs_socket_accept(struct socket *sock, struct socket *newsock)
769+{
770+ struct ccs_socket_tag *ptr;
771+ int rc = ccs_validate_socket(sock);
772+ if (rc < 0)
773+ return rc;
774+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
775+ if (!ptr)
776+ return -ENOMEM;
777+ while (!original_security_ops.socket_accept)
778+ smp_rmb();
779+ rc = original_security_ops.socket_accept(sock, newsock);
780+ if (rc) {
781+ kfree(ptr);
782+ return rc;
783+ }
784+ /*
785+ * Subsequent LSM hooks will receive "newsock". Therefore, I mark
786+ * "newsock" as "an accept()ed socket but post accept() permission
787+ * check is not done yet" by allocating memory using inode of the
788+ * "newsock" as a search key.
789+ */
790+ ptr->inode = SOCK_INODE(newsock);
791+ ptr->status = 1; /* Check post accept() permission later. */
792+ spin_lock(&ccs_accepted_socket_list_lock);
793+ list_add_tail_rcu(&ptr->list, &ccs_accepted_socket_list);
794+ spin_unlock(&ccs_accepted_socket_list_lock);
795+ return 0;
796+}
797+
798+/**
799+ * ccs_socket_listen - Check permission for listen().
800+ *
801+ * @sock: Pointer to "struct socket".
802+ * @backlog: Backlog parameter.
803+ *
804+ * Returns 0 on success, negative value otherwise.
805+ */
806+static int ccs_socket_listen(struct socket *sock, int backlog)
807+{
808+ int rc = ccs_validate_socket(sock);
809+ if (rc < 0)
810+ return rc;
811+ rc = ccs_socket_listen_permission(sock);
812+ if (rc)
813+ return rc;
814+ while (!original_security_ops.socket_listen)
815+ smp_rmb();
816+ return original_security_ops.socket_listen(sock, backlog);
817+}
818+
819+/**
820+ * ccs_socket_connect - Check permission for connect().
821+ *
822+ * @sock: Pointer to "struct socket".
823+ * @addr: Pointer to "struct sockaddr".
824+ * @addr_len: Size of @addr.
825+ *
826+ * Returns 0 on success, negative value otherwise.
827+ */
828+static int ccs_socket_connect(struct socket *sock, struct sockaddr *addr,
829+ int addr_len)
830+{
831+ int rc = ccs_validate_socket(sock);
832+ if (rc < 0)
833+ return rc;
834+ rc = ccs_socket_connect_permission(sock, addr, addr_len);
835+ if (rc)
836+ return rc;
837+ while (!original_security_ops.socket_connect)
838+ smp_rmb();
839+ return original_security_ops.socket_connect(sock, addr, addr_len);
840+}
841+
842+/**
843+ * ccs_socket_bind - Check permission for bind().
844+ *
845+ * @sock: Pointer to "struct socket".
846+ * @addr: Pointer to "struct sockaddr".
847+ * @addr_len: Size of @addr.
848+ *
849+ * Returns 0 on success, negative value otherwise.
850+ */
851+static int ccs_socket_bind(struct socket *sock, struct sockaddr *addr,
852+ int addr_len)
853+{
854+ int rc = ccs_validate_socket(sock);
855+ if (rc < 0)
856+ return rc;
857+ rc = ccs_socket_bind_permission(sock, addr, addr_len);
858+ if (rc)
859+ return rc;
860+ while (!original_security_ops.socket_bind)
861+ smp_rmb();
862+ return original_security_ops.socket_bind(sock, addr, addr_len);
863+}
864+
865+/**
866+ * ccs_socket_sendmsg - Check permission for sendmsg().
867+ *
868+ * @sock: Pointer to "struct socket".
869+ * @msg: Pointer to "struct msghdr".
870+ * @size: Size of message.
871+ *
872+ * Returns 0 on success, negative value otherwise.
873+ */
874+static int ccs_socket_sendmsg(struct socket *sock, struct msghdr *msg,
875+ int size)
876+{
877+ int rc = ccs_validate_socket(sock);
878+ if (rc < 0)
879+ return rc;
880+ rc = ccs_socket_sendmsg_permission(sock, msg, size);
881+ if (rc)
882+ return rc;
883+ while (!original_security_ops.socket_sendmsg)
884+ smp_rmb();
885+ return original_security_ops.socket_sendmsg(sock, msg, size);
886+}
887+
888+/**
889+ * ccs_socket_recvmsg - Check permission for recvmsg().
890+ *
891+ * @sock: Pointer to "struct socket".
892+ * @msg: Pointer to "struct msghdr".
893+ * @size: Size of message.
894+ * @flags: Flags.
895+ *
896+ * Returns 0 on success, negative value otherwise.
897+ */
898+static int ccs_socket_recvmsg(struct socket *sock, struct msghdr *msg,
899+ int size, int flags)
900+{
901+ int rc = ccs_validate_socket(sock);
902+ if (rc < 0)
903+ return rc;
904+ while (!original_security_ops.socket_recvmsg)
905+ smp_rmb();
906+ return original_security_ops.socket_recvmsg(sock, msg, size, flags);
907+}
908+
909+/**
910+ * ccs_socket_getsockname - Check permission for getsockname().
911+ *
912+ * @sock: Pointer to "struct socket".
913+ *
914+ * Returns 0 on success, negative value otherwise.
915+ */
916+static int ccs_socket_getsockname(struct socket *sock)
917+{
918+ int rc = ccs_validate_socket(sock);
919+ if (rc < 0)
920+ return rc;
921+ while (!original_security_ops.socket_getsockname)
922+ smp_rmb();
923+ return original_security_ops.socket_getsockname(sock);
924+}
925+
926+/**
927+ * ccs_socket_getpeername - Check permission for getpeername().
928+ *
929+ * @sock: Pointer to "struct socket".
930+ *
931+ * Returns 0 on success, negative value otherwise.
932+ */
933+static int ccs_socket_getpeername(struct socket *sock)
934+{
935+ int rc = ccs_validate_socket(sock);
936+ if (rc < 0)
937+ return rc;
938+ while (!original_security_ops.socket_getpeername)
939+ smp_rmb();
940+ return original_security_ops.socket_getpeername(sock);
941+}
942+
943+/**
944+ * ccs_socket_getsockopt - Check permission for getsockopt().
945+ *
946+ * @sock: Pointer to "struct socket".
947+ * @level: Level.
948+ * @optname: Option's name,
949+ *
950+ * Returns 0 on success, negative value otherwise.
951+ */
952+static int ccs_socket_getsockopt(struct socket *sock, int level, int optname)
953+{
954+ int rc = ccs_validate_socket(sock);
955+ if (rc < 0)
956+ return rc;
957+ while (!original_security_ops.socket_getsockopt)
958+ smp_rmb();
959+ return original_security_ops.socket_getsockopt(sock, level, optname);
960+}
961+
962+/**
963+ * ccs_socket_setsockopt - Check permission for setsockopt().
964+ *
965+ * @sock: Pointer to "struct socket".
966+ * @level: Level.
967+ * @optname: Option's name,
968+ *
969+ * Returns 0 on success, negative value otherwise.
970+ */
971+static int ccs_socket_setsockopt(struct socket *sock, int level, int optname)
972+{
973+ int rc = ccs_validate_socket(sock);
974+ if (rc < 0)
975+ return rc;
976+ while (!original_security_ops.socket_setsockopt)
977+ smp_rmb();
978+ return original_security_ops.socket_setsockopt(sock, level, optname);
979+}
980+
981+/**
982+ * ccs_socket_shutdown - Check permission for shutdown().
983+ *
984+ * @sock: Pointer to "struct socket".
985+ * @how: Shutdown mode.
986+ *
987+ * Returns 0 on success, negative value otherwise.
988+ */
989+static int ccs_socket_shutdown(struct socket *sock, int how)
990+{
991+ int rc = ccs_validate_socket(sock);
992+ if (rc < 0)
993+ return rc;
994+ while (!original_security_ops.socket_shutdown)
995+ smp_rmb();
996+ return original_security_ops.socket_shutdown(sock, how);
997+}
998+
999+#define SOCKFS_MAGIC 0x534F434B
1000+
1001+/**
1002+ * ccs_inode_free_security - Release memory associated with an inode.
1003+ *
1004+ * @inode: Pointer to "struct inode".
1005+ *
1006+ * Returns nothing.
1007+ *
1008+ * We use this hook for releasing memory associated with an accept()ed socket.
1009+ */
1010+static void ccs_inode_free_security(struct inode *inode)
1011+{
1012+ while (!original_security_ops.inode_free_security)
1013+ smp_rmb();
1014+ original_security_ops.inode_free_security(inode);
1015+ if (inode->i_sb && inode->i_sb->s_magic == SOCKFS_MAGIC)
1016+ ccs_update_socket_tag(inode, 0);
1017+}
1018+
1019+#endif
1020+
1021+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
1022+
1023+/**
1024+ * ccs_sb_pivotroot - Check permission for pivot_root().
1025+ *
1026+ * @old_nd: Pointer to "struct nameidata".
1027+ * @new_nd: Pointer to "struct nameidata".
1028+ *
1029+ * Returns 0 on success, negative value otherwise.
1030+ */
1031+static int ccs_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
1032+{
1033+ int rc = ccs_pivot_root_permission(old_nd, new_nd);
1034+ if (rc)
1035+ return rc;
1036+ while (!original_security_ops.sb_pivotroot)
1037+ smp_rmb();
1038+ return original_security_ops.sb_pivotroot(old_nd, new_nd);
1039+}
1040+
1041+/**
1042+ * ccs_sb_mount - Check permission for mount().
1043+ *
1044+ * @dev_name: Name of device file.
1045+ * @nd: Pointer to "struct nameidata".
1046+ * @type: Name of filesystem type. Maybe NULL.
1047+ * @flags: Mount options.
1048+ * @data_page: Optional data. Maybe NULL.
1049+ *
1050+ * Returns 0 on success, negative value otherwise.
1051+ */
1052+static int ccs_sb_mount(char *dev_name, struct nameidata *nd, char *type,
1053+ unsigned long flags, void *data_page)
1054+{
1055+ int rc = ccs_mount_permission(dev_name, nd, type, flags, data_page);
1056+ if (rc)
1057+ return rc;
1058+ while (!original_security_ops.sb_mount)
1059+ smp_rmb();
1060+ return original_security_ops.sb_mount(dev_name, nd, type, flags,
1061+ data_page);
1062+}
1063+
1064+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
1065+
1066+/**
1067+ * ccs_sb_pivotroot - Check permission for pivot_root().
1068+ *
1069+ * @old_nd: Pointer to "struct nameidata".
1070+ * @new_nd: Pointer to "struct nameidata".
1071+ *
1072+ * Returns 0 on success, negative value otherwise.
1073+ */
1074+static int ccs_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd)
1075+{
1076+ int rc = ccs_pivot_root_permission(&old_nd->path, &new_nd->path);
1077+ if (rc)
1078+ return rc;
1079+ while (!original_security_ops.sb_pivotroot)
1080+ smp_rmb();
1081+ return original_security_ops.sb_pivotroot(old_nd, new_nd);
1082+}
1083+
1084+/**
1085+ * ccs_sb_mount - Check permission for mount().
1086+ *
1087+ * @dev_name: Name of device file.
1088+ * @nd: Pointer to "struct nameidata".
1089+ * @type: Name of filesystem type. Maybe NULL.
1090+ * @flags: Mount options.
1091+ * @data_page: Optional data. Maybe NULL.
1092+ *
1093+ * Returns 0 on success, negative value otherwise.
1094+ */
1095+static int ccs_sb_mount(char *dev_name, struct nameidata *nd, char *type,
1096+ unsigned long flags, void *data_page)
1097+{
1098+ int rc = ccs_mount_permission(dev_name, &nd->path, type, flags,
1099+ data_page);
1100+ if (rc)
1101+ return rc;
1102+ while (!original_security_ops.sb_mount)
1103+ smp_rmb();
1104+ return original_security_ops.sb_mount(dev_name, nd, type, flags,
1105+ data_page);
1106+}
1107+
1108+#else
1109+
1110+/**
1111+ * ccs_sb_pivotroot - Check permission for pivot_root().
1112+ *
1113+ * @old_path: Pointer to "struct path".
1114+ * @new_path: Pointer to "struct path".
1115+ *
1116+ * Returns 0 on success, negative value otherwise.
1117+ */
1118+static int ccs_sb_pivotroot(struct path *old_path, struct path *new_path)
1119+{
1120+ int rc = ccs_pivot_root_permission(old_path, new_path);
1121+ if (rc)
1122+ return rc;
1123+ while (!original_security_ops.sb_pivotroot)
1124+ smp_rmb();
1125+ return original_security_ops.sb_pivotroot(old_path, new_path);
1126+}
1127+
1128+/**
1129+ * ccs_sb_mount - Check permission for mount().
1130+ *
1131+ * @dev_name: Name of device file.
1132+ * @path: Pointer to "struct path".
1133+ * @type: Name of filesystem type. Maybe NULL.
1134+ * @flags: Mount options.
1135+ * @data_page: Optional data. Maybe NULL.
1136+ *
1137+ * Returns 0 on success, negative value otherwise.
1138+ */
1139+static int ccs_sb_mount(char *dev_name, struct path *path, char *type,
1140+ unsigned long flags, void *data_page)
1141+{
1142+ int rc = ccs_mount_permission(dev_name, path, type, flags, data_page);
1143+ if (rc)
1144+ return rc;
1145+ while (!original_security_ops.sb_mount)
1146+ smp_rmb();
1147+ return original_security_ops.sb_mount(dev_name, path, type, flags,
1148+ data_page);
1149+}
1150+
1151+#endif
1152+
1153+/**
1154+ * ccs_sb_umount - Check permission for umount().
1155+ *
1156+ * @mnt: Pointer to "struct vfsmount".
1157+ * @flags: Unmount flags.
1158+ *
1159+ * Returns 0 on success, negative value otherwise.
1160+ */
1161+static int ccs_sb_umount(struct vfsmount *mnt, int flags)
1162+{
1163+ int rc = ccs_umount_permission(mnt, flags);
1164+ if (rc)
1165+ return rc;
1166+ while (!original_security_ops.sb_umount)
1167+ smp_rmb();
1168+ return original_security_ops.sb_umount(mnt, flags);
1169+}
1170+
1171+/**
1172+ * ccs_file_fcntl - Check permission for fcntl().
1173+ *
1174+ * @file: Pointer to "struct file".
1175+ * @cmd: Command number.
1176+ * @arg: Value for @cmd.
1177+ *
1178+ * Returns 0 on success, negative value otherwise.
1179+ */
1180+static int ccs_file_fcntl(struct file *file, unsigned int cmd,
1181+ unsigned long arg)
1182+{
1183+ int rc = ccs_fcntl_permission(file, cmd, arg);
1184+ if (rc)
1185+ return rc;
1186+ while (!original_security_ops.file_fcntl)
1187+ smp_rmb();
1188+ return original_security_ops.file_fcntl(file, cmd, arg);
1189+}
1190+
1191+/**
1192+ * ccs_file_ioctl - Check permission for ioctl().
1193+ *
1194+ * @filp: Pointer to "struct file".
1195+ * @cmd: Command number.
1196+ * @arg: Value for @cmd.
1197+ *
1198+ * Returns 0 on success, negative value otherwise.
1199+ */
1200+static int ccs_file_ioctl(struct file *filp, unsigned int cmd,
1201+ unsigned long arg)
1202+{
1203+ int rc = ccs_ioctl_permission(filp, cmd, arg);
1204+ if (rc)
1205+ return rc;
1206+ while (!original_security_ops.file_ioctl)
1207+ smp_rmb();
1208+ return original_security_ops.file_ioctl(filp, cmd, arg);
1209+}
1210+
1211+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) && defined(CONFIG_SYSCTL_SYSCALL)
1212+int ccs_path_permission(struct ccs_request_info *r, u8 operation,
1213+ const struct ccs_path_info *filename);
1214+
1215+/**
1216+ * ccs_prepend - Copy of prepend() in fs/dcache.c.
1217+ *
1218+ * @buffer: Pointer to "struct char *".
1219+ * @buflen: Pointer to int which holds size of @buffer.
1220+ * @str: String to copy.
1221+ *
1222+ * Returns 0 on success, negative value otherwise.
1223+ *
1224+ * @buffer and @buflen are updated upon success.
1225+ */
1226+static int ccs_prepend(char **buffer, int *buflen, const char *str)
1227+{
1228+ int namelen = strlen(str);
1229+ if (*buflen < namelen)
1230+ return -ENOMEM;
1231+ *buflen -= namelen;
1232+ *buffer -= namelen;
1233+ memcpy(*buffer, str, namelen);
1234+ return 0;
1235+}
1236+
1237+/**
1238+ * ccs_sysctl_permission - Check permission for sysctl().
1239+ *
1240+ * @table: Pointer to "struct ctl_table".
1241+ * @op: Operation. (MAY_READ and/or MAY_WRITE)
1242+ *
1243+ * Returns 0 on success, negative value otherwise.
1244+ */
1245+static int ccs_sysctl(struct ctl_table *table, int op)
1246+{
1247+ int error;
1248+ struct ccs_path_info buf;
1249+ struct ccs_request_info r;
1250+ int buflen;
1251+ char *buffer;
1252+ int idx;
1253+ while (!original_security_ops.sysctl)
1254+ smp_rmb();
1255+ error = original_security_ops.sysctl(table, op);
1256+ if (error)
1257+ return error;
1258+ op &= MAY_READ | MAY_WRITE;
1259+ if (!op)
1260+ return 0;
1261+ buffer = NULL;
1262+ buf.name = NULL;
1263+ idx = ccs_read_lock();
1264+ if (ccs_init_request_info(&r, CCS_MAC_FILE_OPEN)
1265+ == CCS_CONFIG_DISABLED)
1266+ goto out;
1267+ error = -ENOMEM;
1268+ buflen = 4096;
1269+ buffer = kmalloc(buflen, CCS_GFP_FLAGS);
1270+ if (buffer) {
1271+ char *end = buffer + buflen;
1272+ *--end = '\0';
1273+ buflen--;
1274+ while (table) {
1275+ char num[32];
1276+ const char *sp = table->procname;
1277+ if (!sp) {
1278+ memset(num, 0, sizeof(num));
1279+ snprintf(num, sizeof(num) - 1, "=%d=",
1280+ table->ctl_name);
1281+ sp = num;
1282+ }
1283+ if (ccs_prepend(&end, &buflen, sp) ||
1284+ ccs_prepend(&end, &buflen, "/"))
1285+ goto out;
1286+ table = table->parent;
1287+ }
1288+ if (ccs_prepend(&end, &buflen, "proc:/sys"))
1289+ goto out;
1290+ buf.name = ccs_encode(end);
1291+ }
1292+ if (buf.name) {
1293+ ccs_fill_path_info(&buf);
1294+ if (op & MAY_READ)
1295+ error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
1296+ else
1297+ error = 0;
1298+ if (!error && (op & MAY_WRITE))
1299+ error = ccs_path_permission(&r, CCS_TYPE_WRITE, &buf);
1300+ }
1301+out:
1302+ ccs_read_unlock(idx);
1303+ kfree(buf.name);
1304+ kfree(buffer);
1305+ return error;
1306+}
1307+
1308+#endif
1309+
1310+/*
1311+ * Why not to copy all operations by "original_security_ops = *ops" ?
1312+ * Because copying byte array is not atomic. Reader checks
1313+ * original_security_ops.op != NULL before doing original_security_ops.op().
1314+ * Thus, modifying original_security_ops.op has to be atomic.
1315+ */
1316+#define swap_security_ops(op) \
1317+ original_security_ops.op = ops->op; smp_wmb(); ops->op = ccs_##op;
1318+
1319+/**
1320+ * ccs_update_security_ops - Overwrite original "struct security_operations".
1321+ *
1322+ * @ops: Pointer to "struct security_operations".
1323+ *
1324+ * Returns nothing.
1325+ */
1326+static void __init ccs_update_security_ops(struct security_operations *ops)
1327+{
1328+ /* Security context allocator. */
1329+ swap_security_ops(task_alloc_security);
1330+ swap_security_ops(task_free_security);
1331+ swap_security_ops(bprm_alloc_security);
1332+ swap_security_ops(bprm_free_security);
1333+ /* Security context updater for successful execve(). */
1334+ swap_security_ops(bprm_check_security);
1335+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 6)
1336+ swap_security_ops(bprm_compute_creds);
1337+#else
1338+ swap_security_ops(bprm_apply_creds);
1339+#endif
1340+ /* Various permission checker. */
1341+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1342+ swap_security_ops(dentry_open);
1343+#else
1344+ swap_security_ops(inode_permission);
1345+#endif
1346+ swap_security_ops(file_fcntl);
1347+ swap_security_ops(file_ioctl);
1348+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 21) && defined(CONFIG_SYSCTL_SYSCALL)
1349+ swap_security_ops(sysctl);
1350+#endif
1351+ swap_security_ops(sb_pivotroot);
1352+ swap_security_ops(sb_mount);
1353+ swap_security_ops(sb_umount);
1354+ swap_security_ops(inode_mknod);
1355+ swap_security_ops(inode_mkdir);
1356+ swap_security_ops(inode_rmdir);
1357+ swap_security_ops(inode_unlink);
1358+ swap_security_ops(inode_symlink);
1359+ swap_security_ops(inode_rename);
1360+ swap_security_ops(inode_link);
1361+ swap_security_ops(inode_create);
1362+ swap_security_ops(inode_setattr);
1363+ swap_security_ops(inode_getattr);
1364+#ifdef CONFIG_SECURITY_NETWORK
1365+ swap_security_ops(socket_bind);
1366+ swap_security_ops(socket_connect);
1367+ swap_security_ops(socket_listen);
1368+ swap_security_ops(socket_sendmsg);
1369+ swap_security_ops(socket_recvmsg);
1370+ swap_security_ops(socket_getsockname);
1371+ swap_security_ops(socket_getpeername);
1372+ swap_security_ops(socket_getsockopt);
1373+ swap_security_ops(socket_setsockopt);
1374+ swap_security_ops(socket_shutdown);
1375+ swap_security_ops(socket_accept);
1376+ swap_security_ops(inode_free_security);
1377+#endif
1378+}
1379+
1380+#undef swap_security_ops
1381+
1382+/**
1383+ * ccs_init - Initialize this module.
1384+ *
1385+ * Returns 0 on success, negative value otherwise.
1386+ */
1387+static int __init ccs_init(void)
1388+{
1389+ struct security_operations *ops = probe_security_ops();
1390+ if (!ops)
1391+ goto out;
1392+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1393+ ccsecurity_exports.find_task_by_vpid = probe_find_task_by_vpid();
1394+ if (!ccsecurity_exports.find_task_by_vpid)
1395+ goto out;
1396+ ccsecurity_exports.find_task_by_pid_ns = probe_find_task_by_pid_ns();
1397+ if (!ccsecurity_exports.find_task_by_pid_ns)
1398+ goto out;
1399+#endif
1400+ ccsecurity_exports.vfsmount_lock = probe_vfsmount_lock();
1401+ if (!ccsecurity_exports.vfsmount_lock)
1402+ goto out;
1403+ ccs_main_init();
1404+ ccs_update_security_ops(ops);
1405+ printk(KERN_INFO "AKARI: 1.0.48 2023/05/27\n");
1406+ printk(KERN_INFO
1407+ "Access Keeping And Regulating Instrument registered.\n");
1408+ return 0;
1409+out:
1410+ return -EINVAL;
1411+}
1412+
1413+module_init(ccs_init);
1414+MODULE_LICENSE("GPL");
1415+
1416+/**
1417+ * ccs_used_by_cred - Check whether the given domain is in use or not.
1418+ *
1419+ * @domain: Pointer to "struct ccs_domain_info".
1420+ *
1421+ * Returns true if @domain is in use, false otherwise.
1422+ *
1423+ * Caller holds rcu_read_lock().
1424+ */
1425+bool ccs_used_by_cred(const struct ccs_domain_info *domain)
1426+{
1427+ return false;
1428+}
1429+
1430+/**
1431+ * ccs_add_task_security - Add "struct ccs_security" to list.
1432+ *
1433+ * @ptr: Pointer to "struct ccs_security".
1434+ * @list: Pointer to "struct list_head".
1435+ *
1436+ * Returns nothing.
1437+ */
1438+static void ccs_add_task_security(struct ccs_security *ptr,
1439+ struct list_head *list)
1440+{
1441+ unsigned long flags;
1442+ spin_lock_irqsave(&ccs_task_security_list_lock, flags);
1443+ list_add_rcu(&ptr->list, list);
1444+ spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
1445+}
1446+
1447+/**
1448+ * __ccs_alloc_task_security - Allocate memory for new tasks.
1449+ *
1450+ * @task: Pointer to "struct task_struct".
1451+ *
1452+ * Returns 0 on success, negative value otherwise.
1453+ */
1454+static int __ccs_alloc_task_security(const struct task_struct *task)
1455+{
1456+ struct ccs_security *old_security = ccs_current_security();
1457+ struct ccs_security *new_security = kzalloc(sizeof(*new_security),
1458+ GFP_KERNEL);
1459+ struct list_head *list = &ccs_task_security_list
1460+ [hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
1461+ if (!new_security)
1462+ return -ENOMEM;
1463+ new_security->task = task;
1464+ new_security->ccs_domain_info = old_security->ccs_domain_info;
1465+ new_security->ccs_flags = old_security->ccs_flags;
1466+ ccs_add_task_security(new_security, list);
1467+ return 0;
1468+}
1469+
1470+/**
1471+ * ccs_find_task_security - Find "struct ccs_security" for given task.
1472+ *
1473+ * @task: Pointer to "struct task_struct".
1474+ *
1475+ * Returns pointer to "struct ccs_security" on success, &ccs_oom_security on
1476+ * out of memory, &ccs_default_security otherwise.
1477+ *
1478+ * If @task is current thread and "struct ccs_security" for current thread was
1479+ * not found, I try to allocate it. But if allocation failed, current thread
1480+ * will be killed by SIGKILL. Note that if current->pid == 1, sending SIGKILL
1481+ * won't work.
1482+ */
1483+struct ccs_security *ccs_find_task_security(const struct task_struct *task)
1484+{
1485+ struct ccs_security *ptr;
1486+ struct list_head *list = &ccs_task_security_list
1487+ [hash_ptr((void *) task, CCS_TASK_SECURITY_HASH_BITS)];
1488+ /* Make sure INIT_LIST_HEAD() in ccs_mm_init() takes effect. */
1489+ while (!list->next)
1490+ smp_rmb();
1491+ rcu_read_lock();
1492+ list_for_each_entry_rcu(ptr, list, list) {
1493+ if (ptr->task != task)
1494+ continue;
1495+ rcu_read_unlock();
1496+ return ptr;
1497+ }
1498+ rcu_read_unlock();
1499+ if (task != current)
1500+ return &ccs_default_security;
1501+ /* Use GFP_ATOMIC because caller may have called rcu_read_lock(). */
1502+ ptr = kzalloc(sizeof(*ptr), GFP_ATOMIC);
1503+ if (!ptr) {
1504+ printk(KERN_WARNING "Unable to allocate memory for pid=%u\n",
1505+ task->pid);
1506+ send_sig(SIGKILL, current, 0);
1507+ return &ccs_oom_security;
1508+ }
1509+ *ptr = ccs_default_security;
1510+ ptr->task = task;
1511+ ccs_add_task_security(ptr, list);
1512+ return ptr;
1513+}
1514+
1515+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
1516+
1517+/**
1518+ * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
1519+ *
1520+ * @rcu: Pointer to "struct rcu_head".
1521+ *
1522+ * Returns nothing.
1523+ */
1524+static void ccs_rcu_free(struct rcu_head *rcu)
1525+{
1526+ struct ccs_security *ptr = container_of(rcu, typeof(*ptr), rcu);
1527+ kfree(ptr);
1528+}
1529+
1530+#else
1531+
1532+/**
1533+ * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
1534+ *
1535+ * @arg: Pointer to "void".
1536+ *
1537+ * Returns nothing.
1538+ */
1539+static void ccs_rcu_free(void *arg)
1540+{
1541+ struct ccs_security *ptr = arg;
1542+ kfree(ptr);
1543+}
1544+
1545+#endif
1546+
1547+/**
1548+ * __ccs_free_task_security - Release memory associated with "struct task_struct".
1549+ *
1550+ * @task: Pointer to "struct task_struct".
1551+ *
1552+ * Returns nothing.
1553+ */
1554+static void __ccs_free_task_security(const struct task_struct *task)
1555+{
1556+ unsigned long flags;
1557+ struct ccs_security *ptr = ccs_find_task_security(task);
1558+ if (ptr == &ccs_default_security || ptr == &ccs_oom_security)
1559+ return;
1560+ spin_lock_irqsave(&ccs_task_security_list_lock, flags);
1561+ list_del_rcu(&ptr->list);
1562+ spin_unlock_irqrestore(&ccs_task_security_list_lock, flags);
1563+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
1564+ call_rcu(&ptr->rcu, ccs_rcu_free);
1565+#else
1566+ call_rcu(&ptr->rcu, ccs_rcu_free, ptr);
1567+#endif
1568+}
--- tags/patches/1.0.48/lsm-2.6.29.c (nonexistent)
+++ tags/patches/1.0.48/lsm-2.6.29.c (revision 695)
@@ -0,0 +1,2246 @@
1+/*
2+ * lsm.c
3+ *
4+ * Copyright (C) 2010-2015 Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
5+ *
6+ * Version: 1.0.48 2023/05/27
7+ */
8+
9+#include "internal.h"
10+#include "probe.h"
11+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)
12+#define USE_UMODE_T
13+#else
14+#include "check_umode_t.h"
15+#endif
16+
17+/* Prototype definition. */
18+static void ccs_task_security_gc(void);
19+static int ccs_copy_cred_security(const struct cred *new,
20+ const struct cred *old, gfp_t gfp);
21+static struct ccs_security *ccs_find_cred_security(const struct cred *cred);
22+static DEFINE_SPINLOCK(ccs_task_security_list_lock);
23+static atomic_t ccs_in_execve_tasks = ATOMIC_INIT(0);
24+/*
25+ * List of "struct ccs_security" for "struct pid".
26+ *
27+ * All instances on this list is guaranteed that "struct ccs_security"->pid !=
28+ * NULL. Also, instances on this list that are in execve() are guaranteed that
29+ * "struct ccs_security"->cred remembers "struct linux_binprm"->cred with a
30+ * refcount on "struct linux_binprm"->cred.
31+ */
32+struct list_head ccs_task_security_list[CCS_MAX_TASK_SECURITY_HASH];
33+/*
34+ * List of "struct ccs_security" for "struct cred".
35+ *
36+ * Since the number of "struct cred" is nearly equals to the number of
37+ * "struct pid", we allocate hash tables like ccs_task_security_list.
38+ *
39+ * All instances on this list are guaranteed that "struct ccs_security"->pid ==
40+ * NULL and "struct ccs_security"->cred != NULL.
41+ */
42+static struct list_head ccs_cred_security_list[CCS_MAX_TASK_SECURITY_HASH];
43+
44+/* Dummy security context for avoiding NULL pointer dereference. */
45+static struct ccs_security ccs_oom_security = {
46+ .ccs_domain_info = &ccs_kernel_domain
47+};
48+
49+/* Dummy security context for avoiding NULL pointer dereference. */
50+static struct ccs_security ccs_default_security = {
51+ .ccs_domain_info = &ccs_kernel_domain
52+};
53+
54+/* For exporting variables and functions. */
55+struct ccsecurity_exports ccsecurity_exports;
56+/* Members are updated by loadable kernel module. */
57+struct ccsecurity_operations ccsecurity_ops;
58+
59+/* Function pointers originally registered by register_security(). */
60+static struct security_operations original_security_ops /* = *security_ops; */;
61+
62+#ifdef CONFIG_AKARI_TRACE_EXECVE_COUNT
63+
64+/**
65+ * ccs_update_ee_counter - Update "struct ccs_execve" counter.
66+ *
67+ * @count: Count to increment or decrement.
68+ *
69+ * Returns updated counter.
70+ */
71+static unsigned int ccs_update_ee_counter(int count)
72+{
73+ /* Debug counter for detecting "struct ccs_execve" memory leak. */
74+ static atomic_t ccs_ee_counter = ATOMIC_INIT(0);
75+ return atomic_add_return(count, &ccs_ee_counter);
76+}
77+
78+/**
79+ * ccs_audit_alloc_execve - Audit allocation of "struct ccs_execve".
80+ *
81+ * @ee: Pointer to "struct ccs_execve".
82+ *
83+ * Returns nothing.
84+ */
85+void ccs_audit_alloc_execve(const struct ccs_execve * const ee)
86+{
87+ printk(KERN_INFO "AKARI: Allocated %p by pid=%u (count=%u)\n", ee,
88+ current->pid, ccs_update_ee_counter(1) - 1);
89+}
90+
91+/**
92+ * ccs_audit_free_execve - Audit release of "struct ccs_execve".
93+ *
94+ * @ee: Pointer to "struct ccs_execve".
95+ * @task: True if released by current task, false otherwise.
96+ *
97+ * Returns nothing.
98+ */
99+void ccs_audit_free_execve(const struct ccs_execve * const ee,
100+ const bool is_current)
101+{
102+ const unsigned int tmp = ccs_update_ee_counter(-1);
103+ if (is_current)
104+ printk(KERN_INFO "AKARI: Releasing %p by pid=%u (count=%u)\n",
105+ ee, current->pid, tmp);
106+ else
107+ printk(KERN_INFO "AKARI: Releasing %p by kernel (count=%u)\n",
108+ ee, tmp);
109+}
110+
111+#endif
112+
113+#if !defined(CONFIG_AKARI_DEBUG)
114+#define ccs_debug_trace(pos) do { } while (0)
115+#else
116+#define ccs_debug_trace(pos) \
117+ do { \
118+ static bool done; \
119+ if (!done) { \
120+ printk(KERN_INFO \
121+ "AKARI: Debug trace: " pos " of 4\n"); \
122+ done = true; \
123+ } \
124+ } while (0)
125+#endif
126+
127+/**
128+ * ccs_clear_execve - Release memory used by do_execve().
129+ *
130+ * @ret: 0 if do_execve() succeeded, negative value otherwise.
131+ * @security: Pointer to "struct ccs_security".
132+ *
133+ * Returns nothing.
134+ */
135+static void ccs_clear_execve(int ret, struct ccs_security *security)
136+{
137+ struct ccs_execve *ee;
138+ if (security == &ccs_default_security || security == &ccs_oom_security)
139+ return;
140+ ee = security->ee;
141+ security->ee = NULL;
142+ if (!ee)
143+ return;
144+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
145+ /*
146+ * Drop refcount on "struct cred" in "struct linux_binprm" and forget
147+ * it.
148+ */
149+ put_cred(security->cred);
150+ security->cred = NULL;
151+#endif
152+ atomic_dec(&ccs_in_execve_tasks);
153+ ccs_finish_execve(ret, ee);
154+}
155+
156+/**
157+ * ccs_rcu_free - RCU callback for releasing "struct ccs_security".
158+ *
159+ * @rcu: Pointer to "struct rcu_head".
160+ *
161+ * Returns nothing.
162+ */
163+static void ccs_rcu_free(struct rcu_head *rcu)
164+{
165+ struct ccs_security *ptr = container_of(rcu, typeof(*ptr), rcu);
166+ struct ccs_execve *ee = ptr->ee;
167+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
168+ /*
169+ * If this security context was associated with "struct pid" and
170+ * ptr->ccs_flags has CCS_TASK_IS_IN_EXECVE set, it indicates that a
171+ * "struct task_struct" associated with this security context exited
172+ * immediately after do_execve() has failed.
173