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

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

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp