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

TOMOYO Linux Cross Reference
Linux/akari/permission.c

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

~ [ 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