~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/security/ccsecurity/permission.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php