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

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

Version: ~ [ linux-5.15-rc5 ] ~ [ linux-5.14.11 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.72 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.152 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.210 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.250 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.286 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.288 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * security/ccsecurity/permission.c
  3  *
  4  * Copyright (C) 2005-2012  NTT DATA CORPORATION
  5  *
  6  * Version: 1.8.5+   2018/04/01
  7  */
  8 
  9 #include "internal.h"
 10 
 11 /***** SECTION1: Constants definition *****/
 12 
 13 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
 14 
 15 /*
 16  * may_open() receives open flags modified by open_to_namei_flags() until
 17  * 2.6.32. We stop here in case some distributions backported ACC_MODE changes,
 18  * for we can't determine whether may_open() receives open flags modified by
 19  * open_to_namei_flags() or not.
 20  */
 21 #ifdef ACC_MODE
 22 #error ACC_MODE already defined.
 23 #endif
 24 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 25 
 26 #if defined(RHEL_MAJOR) && RHEL_MAJOR == 6
 27 /* RHEL6 passes unmodified flags since 2.6.32-71.14.1.el6 . */
 28 #undef ACC_MODE
 29 #define ACC_MODE(x) ("\004\002\006"[(x)&O_ACCMODE])
 30 #endif
 31 
 32 #endif
 33 
 34 /* String table for special mount operations. */
 35 static const char * const ccs_mounts[CCS_MAX_SPECIAL_MOUNT] = {
 36         [CCS_MOUNT_BIND]            = "--bind",
 37         [CCS_MOUNT_MOVE]            = "--move",
 38         [CCS_MOUNT_REMOUNT]         = "--remount",
 39         [CCS_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable",
 40         [CCS_MOUNT_MAKE_PRIVATE]    = "--make-private",
 41         [CCS_MOUNT_MAKE_SLAVE]      = "--make-slave",
 42         [CCS_MOUNT_MAKE_SHARED]     = "--make-shared",
 43 };
 44 
 45 /* Mapping table from "enum ccs_path_acl_index" to "enum ccs_mac_index". */
 46 static const u8 ccs_p2mac[CCS_MAX_PATH_OPERATION] = {
 47         [CCS_TYPE_EXECUTE]    = CCS_MAC_FILE_EXECUTE,
 48         [CCS_TYPE_READ]       = CCS_MAC_FILE_OPEN,
 49         [CCS_TYPE_WRITE]      = CCS_MAC_FILE_OPEN,
 50         [CCS_TYPE_APPEND]     = CCS_MAC_FILE_OPEN,
 51         [CCS_TYPE_UNLINK]     = CCS_MAC_FILE_UNLINK,
 52 #ifdef CONFIG_CCSECURITY_FILE_GETATTR
 53         [CCS_TYPE_GETATTR]    = CCS_MAC_FILE_GETATTR,
 54 #endif
 55         [CCS_TYPE_RMDIR]      = CCS_MAC_FILE_RMDIR,
 56         [CCS_TYPE_TRUNCATE]   = CCS_MAC_FILE_TRUNCATE,
 57         [CCS_TYPE_SYMLINK]    = CCS_MAC_FILE_SYMLINK,
 58         [CCS_TYPE_CHROOT]     = CCS_MAC_FILE_CHROOT,
 59         [CCS_TYPE_UMOUNT]     = CCS_MAC_FILE_UMOUNT,
 60 };
 61 
 62 /* Mapping table from "enum ccs_mkdev_acl_index" to "enum ccs_mac_index". */
 63 const u8 ccs_pnnn2mac[CCS_MAX_MKDEV_OPERATION] = {
 64         [CCS_TYPE_MKBLOCK] = CCS_MAC_FILE_MKBLOCK,
 65         [CCS_TYPE_MKCHAR]  = CCS_MAC_FILE_MKCHAR,
 66 };
 67 
 68 /* Mapping table from "enum ccs_path2_acl_index" to "enum ccs_mac_index". */
 69 const u8 ccs_pp2mac[CCS_MAX_PATH2_OPERATION] = {
 70         [CCS_TYPE_LINK]       = CCS_MAC_FILE_LINK,
 71         [CCS_TYPE_RENAME]     = CCS_MAC_FILE_RENAME,
 72         [CCS_TYPE_PIVOT_ROOT] = CCS_MAC_FILE_PIVOT_ROOT,
 73 };
 74 
 75 /*
 76  * Mapping table from "enum ccs_path_number_acl_index" to "enum ccs_mac_index".
 77  */
 78 const u8 ccs_pn2mac[CCS_MAX_PATH_NUMBER_OPERATION] = {
 79         [CCS_TYPE_CREATE] = CCS_MAC_FILE_CREATE,
 80         [CCS_TYPE_MKDIR]  = CCS_MAC_FILE_MKDIR,
 81         [CCS_TYPE_MKFIFO] = CCS_MAC_FILE_MKFIFO,
 82         [CCS_TYPE_MKSOCK] = CCS_MAC_FILE_MKSOCK,
 83         [CCS_TYPE_IOCTL]  = CCS_MAC_FILE_IOCTL,
 84         [CCS_TYPE_CHMOD]  = CCS_MAC_FILE_CHMOD,
 85         [CCS_TYPE_CHOWN]  = CCS_MAC_FILE_CHOWN,
 86         [CCS_TYPE_CHGRP]  = CCS_MAC_FILE_CHGRP,
 87 };
 88 
 89 #ifdef CONFIG_CCSECURITY_NETWORK
 90 
 91 /*
 92  * Mapping table from "enum ccs_network_acl_index" to "enum ccs_mac_index" for
 93  * inet domain socket.
 94  */
 95 static const u8 ccs_inet2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
 96         [SOCK_STREAM] = {
 97                 [CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_INET_STREAM_BIND,
 98                 [CCS_NETWORK_LISTEN]  = CCS_MAC_NETWORK_INET_STREAM_LISTEN,
 99                 [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_INET_STREAM_CONNECT,
100                 [CCS_NETWORK_ACCEPT]  = CCS_MAC_NETWORK_INET_STREAM_ACCEPT,
101         },
102         [SOCK_DGRAM] = {
103                 [CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_INET_DGRAM_BIND,
104                 [CCS_NETWORK_SEND]    = CCS_MAC_NETWORK_INET_DGRAM_SEND,
105 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
106                 [CCS_NETWORK_RECV]    = CCS_MAC_NETWORK_INET_DGRAM_RECV,
107 #endif
108         },
109         [SOCK_RAW]    = {
110                 [CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_INET_RAW_BIND,
111                 [CCS_NETWORK_SEND]    = CCS_MAC_NETWORK_INET_RAW_SEND,
112 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
113                 [CCS_NETWORK_RECV]    = CCS_MAC_NETWORK_INET_RAW_RECV,
114 #endif
115         },
116 };
117 
118 /*
119  * Mapping table from "enum ccs_network_acl_index" to "enum ccs_mac_index" for
120  * unix domain socket.
121  */
122 static const u8 ccs_unix2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
123         [SOCK_STREAM] = {
124                 [CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_UNIX_STREAM_BIND,
125                 [CCS_NETWORK_LISTEN]  = CCS_MAC_NETWORK_UNIX_STREAM_LISTEN,
126                 [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_STREAM_CONNECT,
127                 [CCS_NETWORK_ACCEPT]  = CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT,
128         },
129         [SOCK_DGRAM] = {
130                 [CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_UNIX_DGRAM_BIND,
131                 [CCS_NETWORK_SEND]    = CCS_MAC_NETWORK_UNIX_DGRAM_SEND,
132 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
133                 [CCS_NETWORK_RECV]    = CCS_MAC_NETWORK_UNIX_DGRAM_RECV,
134 #endif
135         },
136         [SOCK_SEQPACKET] = {
137                 [CCS_NETWORK_BIND]    = CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND,
138                 [CCS_NETWORK_LISTEN]  = CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
139                 [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
140                 [CCS_NETWORK_ACCEPT]  = CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT,
141         },
142 };
143 
144 #endif
145 
146 #ifdef CONFIG_CCSECURITY_CAPABILITY
147 
148 /*
149  * Mapping table from "enum ccs_capability_acl_index" to "enum ccs_mac_index".
150  */
151 const u8 ccs_c2mac[CCS_MAX_CAPABILITY_INDEX] = {
152         [CCS_USE_ROUTE_SOCKET]  = CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET,
153         [CCS_USE_PACKET_SOCKET] = CCS_MAC_CAPABILITY_USE_PACKET_SOCKET,
154         [CCS_SYS_REBOOT]        = CCS_MAC_CAPABILITY_SYS_REBOOT,
155         [CCS_SYS_VHANGUP]       = CCS_MAC_CAPABILITY_SYS_VHANGUP,
156         [CCS_SYS_SETTIME]       = CCS_MAC_CAPABILITY_SYS_SETTIME,
157         [CCS_SYS_NICE]          = CCS_MAC_CAPABILITY_SYS_NICE,
158         [CCS_SYS_SETHOSTNAME]   = CCS_MAC_CAPABILITY_SYS_SETHOSTNAME,
159         [CCS_USE_KERNEL_MODULE] = CCS_MAC_CAPABILITY_USE_KERNEL_MODULE,
160         [CCS_SYS_KEXEC_LOAD]    = CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD,
161         [CCS_SYS_PTRACE]        = CCS_MAC_CAPABILITY_SYS_PTRACE,
162 };
163 
164 #endif
165 
166 /***** SECTION2: Structure definition *****/
167 
168 /* Structure for holding inet domain socket's address. */
169 struct ccs_inet_addr_info {
170         u16 port;           /* In network byte order. */
171         const u32 *address; /* In network byte order. */
172         bool is_ipv6;
173 };
174 
175 /* Structure for holding unix domain socket's address. */
176 struct ccs_unix_addr_info {
177         u8 *addr; /* This may not be '\0' terminated string. */
178         unsigned int addr_len;
179 };
180 
181 /* Structure for holding socket address. */
182 struct ccs_addr_info {
183         u8 protocol;
184         u8 operation;
185         struct ccs_inet_addr_info inet;
186         struct ccs_unix_addr_info unix0;
187 };
188 
189 /***** SECTION3: Prototype definition section *****/
190 
191 bool ccs_dump_page(struct linux_binprm *bprm, unsigned long pos,
192                    struct ccs_page_dump *dump);
193 void ccs_get_attributes(struct ccs_obj_info *obj);
194 
195 static bool ccs_alphabet_char(const char c);
196 static bool ccs_argv(const unsigned int index, const char *arg_ptr,
197                      const int argc, const struct ccs_argv *argv, u8 *checked);
198 static bool ccs_byte_range(const char *str);
199 static bool ccs_check_entry(struct ccs_request_info *r,
200                             struct ccs_acl_info *ptr);
201 static bool ccs_check_mkdev_acl(struct ccs_request_info *r,
202                                 const struct ccs_acl_info *ptr);
203 static bool ccs_check_mount_acl(struct ccs_request_info *r,
204                                 const struct ccs_acl_info *ptr);
205 static bool ccs_check_path2_acl(struct ccs_request_info *r,
206                                 const struct ccs_acl_info *ptr);
207 static bool ccs_check_path_acl(struct ccs_request_info *r,
208                                const struct ccs_acl_info *ptr);
209 static bool ccs_check_path_number_acl(struct ccs_request_info *r,
210                                       const struct ccs_acl_info *ptr);
211 static bool ccs_compare_number_union(const unsigned long value,
212                                      const struct ccs_number_union *ptr);
213 static bool ccs_condition(struct ccs_request_info *r,
214                           const struct ccs_condition *cond);
215 static bool ccs_decimal(const char c);
216 static bool ccs_envp(const char *env_name, const char *env_value,
217                      const int envc, const struct ccs_envp *envp, u8 *checked);
218 static bool ccs_file_matches_pattern(const char *filename,
219                                      const char *filename_end,
220                                      const char *pattern,
221                                      const char *pattern_end);
222 static bool ccs_file_matches_pattern2(const char *filename,
223                                       const char *filename_end,
224                                       const char *pattern,
225                                       const char *pattern_end);
226 static bool ccs_get_realpath(struct ccs_path_info *buf, struct path *path);
227 static bool ccs_hexadecimal(const char c);
228 static bool ccs_number_matches_group(const unsigned long min,
229                                      const unsigned long max,
230                                      const struct ccs_group *group);
231 static bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
232                                      const struct ccs_path_info *pattern);
233 static bool ccs_path_matches_pattern2(const char *f, const char *p);
234 static bool ccs_scan_bprm(struct ccs_execve *ee, const u16 argc,
235                           const struct ccs_argv *argv, const u16 envc,
236                           const struct ccs_envp *envp);
237 static bool ccs_scan_exec_realpath(struct file *file,
238                                    const struct ccs_name_union *ptr,
239                                    const bool match);
240 static bool ccs_scan_transition(const struct list_head *list,
241                                 const struct ccs_path_info *domainname,
242                                 const struct ccs_path_info *program,
243                                 const char *last_name,
244                                 const enum ccs_transition_type type);
245 static const char *ccs_last_word(const char *name);
246 static const struct ccs_path_info *ccs_compare_name_union
247 (const struct ccs_path_info *name, const struct ccs_name_union *ptr);
248 static const struct ccs_path_info *ccs_path_matches_group
249 (const struct ccs_path_info *pathname, const struct ccs_group *group);
250 static enum ccs_transition_type ccs_transition_type
251 (const struct ccs_policy_namespace *ns, const struct ccs_path_info *domainname,
252  const struct ccs_path_info *program);
253 static int __ccs_chmod_permission(struct dentry *dentry,
254                                   struct vfsmount *vfsmnt, mode_t mode);
255 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
256 static int __ccs_chown_permission(struct dentry *dentry,
257                                   struct vfsmount *vfsmnt, kuid_t user,
258                                   kgid_t group);
259 #else
260 static int __ccs_chown_permission(struct dentry *dentry,
261                                   struct vfsmount *vfsmnt, uid_t user,
262                                   gid_t group);
263 #endif
264 static int __ccs_chroot_permission(const struct path *path);
265 static int __ccs_fcntl_permission(struct file *file, unsigned int cmd,
266                                   unsigned long arg);
267 static int __ccs_ioctl_permission(struct file *filp, unsigned int cmd,
268                                   unsigned long arg);
269 static int __ccs_link_permission(struct dentry *old_dentry,
270                                  struct dentry *new_dentry,
271                                  struct vfsmount *mnt);
272 static int __ccs_mkdir_permission(struct dentry *dentry, struct vfsmount *mnt,
273                                   unsigned int mode);
274 static int __ccs_mknod_permission(struct dentry *dentry, struct vfsmount *mnt,
275                                   const unsigned int mode, unsigned int dev);
276 static int __ccs_mount_permission(const char *dev_name,
277                                   const struct path *path, const char *type,
278                                   unsigned long flags, void *data_page);
279 #if LINUX_VERSION_CODE < KERNEL_VERSION(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(const struct path *old_path,
290                                        const 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                          const 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 static int ccs_path_permission(struct ccs_request_info *r, u8 operation,
342                                const struct ccs_path_info *filename);
343 static int ccs_start_execve(struct linux_binprm *bprm,
344                             struct ccs_execve **eep);
345 static int ccs_symlink_path(const char *pathname, struct ccs_path_info *name);
346 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
347 static void __ccs_clear_open_mode(void);
348 static void __ccs_save_open_mode(int mode);
349 #endif
350 static void ccs_add_slash(struct ccs_path_info *buf);
351 static void ccs_finish_execve(int retval, struct ccs_execve *ee);
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 LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
1433         if (get_user_pages_remote(current, bprm->mm, pos, 1, FOLL_FORCE, &page,
1434                                   NULL, NULL) <= 0)
1435                 return false;
1436 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)
1437         if (get_user_pages_remote(current, bprm->mm, pos, 1, FOLL_FORCE, &page,
1438                                   NULL) <= 0)
1439                 return false;
1440 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
1441         if (get_user_pages_remote(current, bprm->mm, pos, 1, 0, 1, &page,
1442                                   NULL) <= 0)
1443                 return false;
1444 #else
1445         if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1446                 return false;
1447 #endif
1448 #else
1449         page = bprm->page[pos / PAGE_SIZE];
1450 #endif
1451         if (page != dump->page) {
1452                 const unsigned int offset = pos % PAGE_SIZE;
1453                 /*
1454                  * Maybe kmap()/kunmap() should be used here.
1455                  * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
1456                  * So do I.
1457                  */
1458 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
1459                 char *kaddr = kmap_atomic(page);
1460 #else
1461                 char *kaddr = kmap_atomic(page, KM_USER0);
1462 #endif
1463                 dump->page = page;
1464                 memcpy(dump->data + offset, kaddr + offset,
1465                        PAGE_SIZE - offset);
1466 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
1467                 kunmap_atomic(kaddr);
1468 #else
1469                 kunmap_atomic(kaddr, KM_USER0);
1470 #endif
1471         }
1472         /* Same with put_arg_page(page) in fs/exec.c */
1473 #ifdef CCS_BPRM_MMU
1474         put_page(page);
1475 #endif
1476         return true;
1477 }
1478 
1479 /**
1480  * ccs_start_execve - Prepare for execve() operation.
1481  *
1482  * @bprm: Pointer to "struct linux_binprm".
1483  * @eep:  Pointer to "struct ccs_execve *".
1484  *
1485  * Returns 0 on success, negative value otherwise.
1486  */
1487 static int ccs_start_execve(struct linux_binprm *bprm,
1488                             struct ccs_execve **eep)
1489 {
1490         int retval;
1491         struct ccs_security *task = ccs_current_security();
1492         struct ccs_execve *ee;
1493         int idx;
1494         *eep = NULL;
1495         ee = kzalloc(sizeof(*ee), CCS_GFP_FLAGS);
1496         if (!ee)
1497                 return -ENOMEM;
1498         ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
1499         if (!ee->tmp) {
1500                 kfree(ee);
1501                 return -ENOMEM;
1502         }
1503         idx = ccs_read_lock();
1504         /* ee->dump->data is allocated by ccs_dump_page(). */
1505         ee->previous_domain = task->ccs_domain_info;
1506         /* Clear manager flag. */
1507         task->ccs_flags &= ~CCS_TASK_IS_MANAGER;
1508         *eep = ee;
1509         ccs_init_request_info(&ee->r, CCS_MAC_FILE_EXECUTE);
1510         ee->r.ee = ee;
1511         ee->bprm = bprm;
1512         ee->r.obj = &ee->obj;
1513 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
1514         ee->obj.path1 = bprm->file->f_path;
1515 #else
1516         ee->obj.path1.dentry = bprm->file->f_dentry;
1517         ee->obj.path1.mnt = bprm->file->f_vfsmnt;
1518 #endif
1519 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
1520         /*
1521          * No need to call ccs_environ() for execute handler because envp[] is
1522          * moved to argv[].
1523          */
1524         if (ccs_find_execute_handler(ee, CCS_TYPE_AUTO_EXECUTE_HANDLER)) {
1525                 retval = ccs_try_alt_exec(ee);
1526                 goto done;
1527         }
1528 #endif
1529         retval = ccs_find_next_domain(ee);
1530 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
1531         if (retval == -EPERM &&
1532             ccs_find_execute_handler(ee, CCS_TYPE_DENIED_EXECUTE_HANDLER)) {
1533                 retval = ccs_try_alt_exec(ee);
1534                 goto done;
1535         }
1536 #endif
1537 #ifdef CONFIG_CCSECURITY_MISC
1538         if (!retval)
1539                 retval = ccs_environ(ee);
1540 #endif
1541 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER
1542 done:
1543 #endif
1544         ccs_read_unlock(idx);
1545         kfree(ee->tmp);
1546         ee->tmp = NULL;
1547         kfree(ee->dump.data);
1548         ee->dump.data = NULL;
1549         return retval;
1550 }
1551 
1552 /**
1553  * ccs_finish_execve - Clean up execve() operation.
1554  *
1555  * @retval: Return code of an execve() operation.
1556  * @ee:     Pointer to "struct ccs_execve".
1557  *
1558  * Returns nothing.
1559  */
1560 static void ccs_finish_execve(int retval, struct ccs_execve *ee)
1561 {
1562         struct ccs_security *task = ccs_current_security();
1563         if (!ee)
1564                 return;
1565         if (retval < 0) {
1566                 task->ccs_domain_info = ee->previous_domain;
1567                 /*
1568                  * Make task->ccs_domain_info visible to GC before changing
1569                  * task->ccs_flags.
1570                  */
1571                 smp_wmb();
1572         } else {
1573                 /* Mark the current process as execute handler. */
1574                 if (ee->handler)
1575                         task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
1576                 /* Mark the current process as normal process. */
1577                 else
1578                         task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
1579         }
1580         /* Tell GC that I finished execve(). */
1581         task->ccs_flags &= ~CCS_TASK_IS_IN_EXECVE;
1582         kfree(ee->handler_path);
1583         kfree(ee);
1584 }
1585 
1586 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1587 
1588 /**
1589  * __ccs_search_binary_handler - Main routine for do_execve().
1590  *
1591  * @bprm: Pointer to "struct linux_binprm".
1592  *
1593  * Returns 0 on success, negative value otherwise.
1594  *
1595  * Performs permission checks for do_execve() and domain transition.
1596  * Domain transition by "struct ccs_domain_transition_control" and
1597  * "auto_domain_transition=" parameter of "struct ccs_condition" are reverted
1598  * if do_execve() failed.
1599  * Garbage collector does not remove "struct ccs_domain_info" from
1600  * ccs_domain_list nor kfree("struct ccs_domain_info") if the current thread is
1601  * marked as CCS_TASK_IS_IN_EXECVE.
1602  */
1603 static int __ccs_search_binary_handler(struct linux_binprm *bprm)
1604 {
1605         struct ccs_execve *ee;
1606         int retval;
1607 #ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
1608         if (!ccs_policy_loaded)
1609                 ccsecurity_exports.load_policy(bprm->filename);
1610 #endif
1611         retval = ccs_start_execve(bprm, &ee);
1612         if (!retval)
1613                 retval = search_binary_handler(bprm);
1614         ccs_finish_execve(retval, ee);
1615         return retval;
1616 }
1617 
1618 #else
1619 
1620 /**
1621  * __ccs_search_binary_handler - Main routine for do_execve().
1622  *
1623  * @bprm: Pointer to "struct linux_binprm".
1624  * @regs: Pointer to "struct pt_regs".
1625  *
1626  * Returns 0 on success, negative value otherwise.
1627  *
1628  * Performs permission checks for do_execve() and domain transition.
1629  * Domain transition by "struct ccs_domain_transition_control" and
1630  * "auto_domain_transition=" parameter of "struct ccs_condition" are reverted
1631  * if do_execve() failed.
1632  * Garbage collector does not remove "struct ccs_domain_info" from
1633  * ccs_domain_list nor kfree("struct ccs_domain_info") if the current thread is
1634  * marked as CCS_TASK_IS_IN_EXECVE.
1635  */
1636 static int __ccs_search_binary_handler(struct linux_binprm *bprm,
1637                                        struct pt_regs *regs)
1638 {
1639         struct ccs_execve *ee;
1640         int retval;
1641 #ifndef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
1642         if (!ccs_policy_loaded)
1643                 ccsecurity_exports.load_policy(bprm->filename);
1644 #endif
1645         retval = ccs_start_execve(bprm, &ee);
1646         if (!retval)
1647                 retval = search_binary_handler(bprm, regs);
1648         ccs_finish_execve(retval, ee);
1649         return retval;
1650 }
1651 
1652 #endif
1653 
1654 /**
1655  * ccs_permission_init - Register permission check hooks.
1656  *
1657  * Returns nothing.
1658  */
1659 void __init ccs_permission_init(void)
1660 {
1661 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
1662         ccsecurity_ops.save_open_mode = __ccs_save_open_mode;
1663         ccsecurity_ops.clear_open_mode = __ccs_clear_open_mode;
1664         ccsecurity_ops.open_permission = __ccs_open_permission;
1665 #else
1666         ccsecurity_ops.open_permission = ccs_new_open_permission;
1667 #endif
1668         ccsecurity_ops.fcntl_permission = __ccs_fcntl_permission;
1669         ccsecurity_ops.ioctl_permission = __ccs_ioctl_permission;
1670         ccsecurity_ops.chmod_permission = __ccs_chmod_permission;
1671         ccsecurity_ops.chown_permission = __ccs_chown_permission;
1672 #ifdef CONFIG_CCSECURITY_FILE_GETATTR
1673         ccsecurity_ops.getattr_permission = __ccs_getattr_permission;
1674 #endif
1675 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1676         ccsecurity_ops.pivot_root_permission = __ccs_pivot_root_permission;
1677         ccsecurity_ops.chroot_permission = __ccs_chroot_permission;
1678 #else
1679         ccsecurity_ops.pivot_root_permission = ccs_old_pivot_root_permission;
1680         ccsecurity_ops.chroot_permission = ccs_old_chroot_permission;
1681 #endif
1682         ccsecurity_ops.umount_permission = __ccs_umount_permission;
1683         ccsecurity_ops.mknod_permission = __ccs_mknod_permission;
1684         ccsecurity_ops.mkdir_permission = __ccs_mkdir_permission;
1685         ccsecurity_ops.rmdir_permission = __ccs_rmdir_permission;
1686         ccsecurity_ops.unlink_permission = __ccs_unlink_permission;
1687         ccsecurity_ops.symlink_permission = __ccs_symlink_permission;
1688         ccsecurity_ops.truncate_permission = __ccs_truncate_permission;
1689         ccsecurity_ops.rename_permission = __ccs_rename_permission;
1690         ccsecurity_ops.link_permission = __ccs_link_permission;
1691 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
1692         ccsecurity_ops.open_exec_permission = __ccs_open_exec_permission;
1693         ccsecurity_ops.uselib_permission = __ccs_uselib_permission;
1694 #endif
1695 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18) || (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) && defined(CONFIG_SYSCTL_SYSCALL))
1696         ccsecurity_ops.parse_table = __ccs_parse_table;
1697 #endif
1698 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1699         ccsecurity_ops.mount_permission = __ccs_mount_permission;
1700 #else
1701         ccsecurity_ops.mount_permission = ccs_old_mount_permission;
1702 #endif
1703 #ifdef CONFIG_CCSECURITY_CAPABILITY
1704         ccsecurity_ops.socket_create_permission =
1705                 __ccs_socket_create_permission;
1706 #endif
1707 #ifdef CONFIG_CCSECURITY_NETWORK
1708         ccsecurity_ops.socket_listen_permission =
1709                 __ccs_socket_listen_permission;
1710         ccsecurity_ops.socket_connect_permission =
1711                 __ccs_socket_connect_permission;
1712         ccsecurity_ops.socket_bind_permission = __ccs_socket_bind_permission;
1713         ccsecurity_ops.socket_post_accept_permission =
1714                 __ccs_socket_post_accept_permission;
1715         ccsecurity_ops.socket_sendmsg_permission =
1716                 __ccs_socket_sendmsg_permission;
1717 #endif
1718 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
1719         ccsecurity_ops.socket_post_recvmsg_permission =
1720                 __ccs_socket_post_recvmsg_permission;
1721 #endif
1722 #ifdef CONFIG_CCSECURITY_IPC
1723         ccsecurity_ops.kill_permission = ccs_signal_acl;
1724         ccsecurity_ops.tgkill_permission = ccs_signal_acl0;
1725         ccsecurity_ops.tkill_permission = ccs_signal_acl;
1726         ccsecurity_ops.sigqueue_permission = ccs_signal_acl;
1727         ccsecurity_ops.tgsigqueue_permission = ccs_signal_acl0;
1728 #endif
1729 #ifdef CONFIG_CCSECURITY_CAPABILITY
1730         ccsecurity_ops.capable = __ccs_capable;
1731         ccsecurity_ops.ptrace_permission = __ccs_ptrace_permission;
1732 #endif
1733         ccsecurity_ops.search_binary_handler = __ccs_search_binary_handler;
1734 }
1735 
1736 /**
1737  * ccs_kern_path - Wrapper for kern_path().
1738  *
1739  * @pathname: Pathname to resolve. Maybe NULL.
1740  * @flags:    Lookup flags.
1741  * @path:     Pointer to "struct path".
1742  *
1743  * Returns 0 on success, negative value otherwise.
1744  */
1745 static int ccs_kern_path(const char *pathname, int flags, struct path *path)
1746 {
1747 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
1748         if (!pathname || kern_path(pathname, flags, path))
1749                 return -ENOENT;
1750 #else
1751         struct nameidata nd;
1752         if (!pathname || path_lookup(pathname, flags, &nd))
1753                 return -ENOENT;
1754 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1755         *path = nd.path;
1756 #else
1757         path->dentry = nd.dentry;
1758         path->mnt = nd.mnt;
1759 #endif
1760 #endif
1761         return 0;
1762 }
1763 
1764 /**
1765  * ccs_get_path - Get dentry/vfsmmount of a pathname.
1766  *
1767  * @pathname: The pathname to solve. Maybe NULL.
1768  * @path:     Pointer to "struct path".
1769  *
1770  * Returns 0 on success, negative value otherwise.
1771  */
1772 static int ccs_get_path(const char *pathname, struct path *path)
1773 {
1774 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1775         return ccs_kern_path(pathname, LOOKUP_FOLLOW, path);
1776 #else
1777         return ccs_kern_path(pathname, LOOKUP_FOLLOW | LOOKUP_POSITIVE, path);
1778 #endif
1779 }
1780 
1781 /**
1782  * ccs_symlink_path - Get symlink's pathname.
1783  *
1784  * @pathname: The pathname to solve. Maybe NULL.
1785  * @name:     Pointer to "struct ccs_path_info".
1786  *
1787  * Returns 0 on success, negative value otherwise.
1788  *
1789  * This function uses kzalloc(), so caller must kfree() if this function
1790  * didn't return NULL.
1791  */
1792 static int ccs_symlink_path(const char *pathname, struct ccs_path_info *name)
1793 {
1794         char *buf;
1795         struct path path;
1796 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
1797         if (ccs_kern_path(pathname, 0, &path))
1798                 return -ENOENT;
1799 #else
1800         if (ccs_kern_path(pathname, LOOKUP_POSITIVE, &path))
1801                 return -ENOENT;
1802 #endif
1803         buf = ccs_realpath(&path);
1804         path_put(&path);
1805         if (buf) {
1806                 name->name = buf;
1807                 ccs_fill_path_info(name);
1808                 return 0;
1809         }
1810         return -ENOMEM;
1811 }
1812 
1813 /**
1814  * ccs_check_mount_acl - Check permission for path path path number operation.
1815  *
1816  * @r:   Pointer to "struct ccs_request_info".
1817  * @ptr: Pointer to "struct ccs_acl_info".
1818  *
1819  * Returns true if granted, false otherwise.
1820  */
1821 static bool ccs_check_mount_acl(struct ccs_request_info *r,
1822                                 const struct ccs_acl_info *ptr)
1823 {
1824         const struct ccs_mount_acl *acl =
1825                 container_of(ptr, typeof(*acl), head);
1826         return ccs_compare_number_union(r->param.mount.flags, &acl->flags) &&
1827                 ccs_compare_name_union(r->param.mount.type, &acl->fs_type) &&
1828                 ccs_compare_name_union(r->param.mount.dir, &acl->dir_name) &&
1829                 (!r->param.mount.need_dev ||
1830                  ccs_compare_name_union(r->param.mount.dev, &acl->dev_name));
1831 }
1832 
1833 /**
1834  * ccs_mount_acl - Check permission for mount() operation.
1835  *
1836  * @r:        Pointer to "struct ccs_request_info".
1837  * @dev_name: Name of device file. Maybe NULL.
1838  * @dir:      Pointer to "struct path".
1839  * @type:     Name of filesystem type.
1840  * @flags:    Mount options.
1841  *
1842  * Returns 0 on success, negative value otherwise.
1843  *
1844  * Caller holds ccs_read_lock().
1845  */
1846 static int ccs_mount_acl(struct ccs_request_info *r, const char *dev_name,
1847                          const struct path *dir, const char *type,
1848                          unsigned long flags)
1849 {
1850         struct ccs_obj_info obj = { };
1851         struct file_system_type *fstype = NULL;
1852         const char *requested_type = NULL;
1853         const char *requested_dir_name = NULL;
1854         const char *requested_dev_name = NULL;
1855         struct ccs_path_info rtype;
1856         struct ccs_path_info rdev;
1857         struct ccs_path_info rdir;
1858         int need_dev = 0;
1859         int error = -ENOMEM;
1860         r->obj = &obj;
1861 
1862         /* Get fstype. */
1863         requested_type = ccs_encode(type);
1864         if (!requested_type)
1865                 goto out;
1866         rtype.name = requested_type;
1867         ccs_fill_path_info(&rtype);
1868 
1869         /* Get mount point. */
1870         obj.path2 = *dir;
1871         requested_dir_name = ccs_realpath(dir);
1872         if (!requested_dir_name) {
1873                 error = -ENOMEM;
1874                 goto out;
1875         }
1876         rdir.name = requested_dir_name;
1877         ccs_fill_path_info(&rdir);
1878 
1879         /* Compare fs name. */
1880         if (type == ccs_mounts[CCS_MOUNT_REMOUNT]) {
1881                 /* dev_name is ignored. */
1882         } else if (type == ccs_mounts[CCS_MOUNT_MAKE_UNBINDABLE] ||
1883                    type == ccs_mounts[CCS_MOUNT_MAKE_PRIVATE] ||
1884                    type == ccs_mounts[CCS_MOUNT_MAKE_SLAVE] ||
1885                    type == ccs_mounts[CCS_MOUNT_MAKE_SHARED]) {
1886                 /* dev_name is ignored. */
1887         } else if (type == ccs_mounts[CCS_MOUNT_BIND] ||
1888                    type == ccs_mounts[CCS_MOUNT_MOVE]) {
1889                 need_dev = -1; /* dev_name is a directory */
1890         } else {
1891                 fstype = get_fs_type(type);
1892                 if (!fstype) {
1893                         error = -ENODEV;
1894                         goto out;
1895                 }
1896                 if (fstype->fs_flags & FS_REQUIRES_DEV)
1897                         /* dev_name is a block device file. */
1898                         need_dev = 1;
1899         }
1900         if (need_dev) {
1901                 /* Get mount point or device file. */
1902                 if (ccs_get_path(dev_name, &obj.path1)) {
1903                         error = -ENOENT;
1904                         goto out;
1905                 }
1906                 requested_dev_name = ccs_realpath(&obj.path1);
1907                 if (!requested_dev_name) {
1908                         error = -ENOENT;
1909                         goto out;
1910                 }
1911         } else {
1912                 /* Map dev_name to "<NULL>" if no dev_name given. */
1913                 if (!dev_name)
1914                         dev_name = "<NULL>";
1915                 requested_dev_name = ccs_encode(dev_name);
1916                 if (!requested_dev_name) {
1917                         error = -ENOMEM;
1918                         goto out;
1919                 }
1920         }
1921         rdev.name = requested_dev_name;
1922         ccs_fill_path_info(&rdev);
1923         r->param_type = CCS_TYPE_MOUNT_ACL;
1924         r->param.mount.need_dev = need_dev;
1925         r->param.mount.dev = &rdev;
1926         r->param.mount.dir = &rdir;
1927         r->param.mount.type = &rtype;
1928         r->param.mount.flags = flags;
1929         error = ccs_check_acl(r);
1930 out:
1931         kfree(requested_dev_name);
1932         kfree(requested_dir_name);
1933         if (fstype)
1934                 ccs_put_filesystem(fstype);
1935         kfree(requested_type);
1936         /* Drop refcount obtained by ccs_get_path(). */
1937         if (obj.path1.dentry)
1938                 path_put(&obj.path1);
1939         return error;
1940 }
1941 
1942 /**
1943  * __ccs_mount_permission - Check permission for mount() operation.
1944  *
1945  * @dev_name:  Name of device file. Maybe NULL.
1946  * @path:      Pointer to "struct path".
1947  * @type:      Name of filesystem type. Maybe NULL.
1948  * @flags:     Mount options.
1949  * @data_page: Optional data. Maybe NULL.
1950  *
1951  * Returns 0 on success, negative value otherwise.
1952  */
1953 static int __ccs_mount_permission(const char *dev_name,
1954                                   const struct path *path, const char *type,
1955                                   unsigned long flags, void *data_page)
1956 {
1957         struct ccs_request_info r;
1958         int error = 0;
1959         int idx;
1960         if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
1961                 flags &= ~MS_MGC_MSK;
1962         if (flags & MS_REMOUNT) {
1963                 type = ccs_mounts[CCS_MOUNT_REMOUNT];
1964                 flags &= ~MS_REMOUNT;
1965         } else if (flags & MS_BIND) {
1966                 type = ccs_mounts[CCS_MOUNT_BIND];
1967                 flags &= ~MS_BIND;
1968         } else if (flags & MS_SHARED) {
1969                 if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
1970                         return -EINVAL;
1971                 type = ccs_mounts[CCS_MOUNT_MAKE_SHARED];
1972                 flags &= ~MS_SHARED;
1973         } else if (flags & MS_PRIVATE) {
1974                 if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
1975                         return -EINVAL;
1976                 type = ccs_mounts[CCS_MOUNT_MAKE_PRIVATE];
1977                 flags &= ~MS_PRIVATE;
1978         } else if (flags & MS_SLAVE) {
1979                 if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
1980                         return -EINVAL;
1981                 type = ccs_mounts[CCS_MOUNT_MAKE_SLAVE];
1982                 flags &= ~MS_SLAVE;
1983         } else if (flags & MS_UNBINDABLE) {
1984                 if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
1985                         return -EINVAL;
1986                 type = ccs_mounts[CCS_MOUNT_MAKE_UNBINDABLE];
1987                 flags &= ~MS_UNBINDABLE;
1988         } else if (flags & MS_MOVE) {
1989                 type = ccs_mounts[CCS_MOUNT_MOVE];
1990                 flags &= ~MS_MOVE;
1991         }
1992         if (!type)
1993                 type = "<NULL>";
1994         idx = ccs_read_lock();
1995         if (ccs_init_request_info(&r, CCS_MAC_FILE_MOUNT)
1996             != CCS_CONFIG_DISABLED)
1997                 error = ccs_mount_acl(&r, dev_name, path, type, flags);
1998         ccs_read_unlock(idx);
1999         return error;
2000 }
2001 
2002 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24)
2003 
2004 /**
2005  * ccs_old_mount_permission - Check permission for mount() operation.
2006  *
2007  * @dev_name:  Name of device file.
2008  * @nd:        Pointer to "struct nameidata".
2009  * @type:      Name of filesystem type. Maybe NULL.
2010  * @flags:     Mount options.
2011  * @data_page: Optional data. Maybe NULL.
2012  *
2013  * Returns 0 on success, negative value otherwise.
2014  */
2015 static int ccs_old_mount_permission(const char *dev_name, struct nameidata *nd,
2016                                     const char *type, unsigned long flags,
2017                                     void *data_page)
2018 {
2019         struct path path = { nd->mnt, nd->dentry };
2020         return __ccs_mount_permission(dev_name, &path, type, flags, data_page);
2021 }
2022 
2023 #endif
2024 
2025 /**
2026  * ccs_compare_number_union - Check whether a value matches "struct ccs_number_union" or not.
2027  *
2028  * @value: Number to check.
2029  * @ptr:   Pointer to "struct ccs_number_union".
2030  *
2031  * Returns true if @value matches @ptr, false otherwise.
2032  */
2033 static bool ccs_compare_number_union(const unsigned long value,
2034                                      const struct ccs_number_union *ptr)
2035 {
2036         if (ptr->group)
2037                 return ccs_number_matches_group(value, value, ptr->group);
2038         return value >= ptr->values[0] && value <= ptr->values[1];
2039 }
2040 
2041 /**
2042  * ccs_compare_name_union - Check whether a name matches "struct ccs_name_union" or not.
2043  *
2044  * @name: Pointer to "struct ccs_path_info".
2045  * @ptr:  Pointer to "struct ccs_name_union".
2046  *
2047  * Returns "struct ccs_path_info" if @name matches @ptr, NULL otherwise.
2048  */
2049 static const struct ccs_path_info *ccs_compare_name_union
2050 (const struct ccs_path_info *name, const struct ccs_name_union *ptr)
2051 {
2052         if (ptr->group)
2053                 return ccs_path_matches_group(name, ptr->group);
2054         if (ccs_path_matches_pattern(name, ptr->filename))
2055                 return ptr->filename;
2056         return NULL;
2057 }
2058 
2059 /**
2060  * ccs_add_slash - Add trailing '/' if needed.
2061  *
2062  * @buf: Pointer to "struct ccs_path_info".
2063  *
2064  * Returns nothing.
2065  *
2066  * @buf must be generated by ccs_encode() because this function does not
2067  * allocate memory for adding '/'.
2068  */
2069 static void ccs_add_slash(struct ccs_path_info *buf)
2070 {
2071         if (buf->is_dir)
2072                 return;
2073         /* This is OK because ccs_encode() reserves space for appending "/". */
2074         strcat((char *) buf->name, "/");
2075         ccs_fill_path_info(buf);
2076 }
2077 
2078 /**
2079  * ccs_get_realpath - Get realpath.
2080  *
2081  * @buf:  Pointer to "struct ccs_path_info".
2082  * @path: Pointer to "struct path". @path->mnt may be NULL.
2083  *
2084  * Returns true on success, false otherwise.
2085  */
2086 static bool ccs_get_realpath(struct ccs_path_info *buf, struct path *path)
2087 {
2088         buf->name = ccs_realpath(path);
2089         if (buf->name) {
2090                 ccs_fill_path_info(buf);
2091                 return true;
2092         }
2093         return false;
2094 }
2095 
2096 /**
2097  * ccs_check_path_acl - Check permission for path operation.
2098  *
2099  * @r:   Pointer to "struct ccs_request_info".
2100  * @ptr: Pointer to "struct ccs_acl_info".
2101  *
2102  * Returns true if granted, false otherwise.
2103  *
2104  * To be able to use wildcard for domain transition, this function sets
2105  * matching entry on success. Since the caller holds ccs_read_lock(),
2106  * it is safe to set matching entry.
2107  */
2108 static bool ccs_check_path_acl(struct ccs_request_info *r,
2109                                const struct ccs_acl_info *ptr)
2110 {
2111         const struct ccs_path_acl *acl = container_of(ptr, typeof(*acl), head);
2112         if (ptr->perm & (1 << r->param.path.operation)) {
2113                 r->param.path.matched_path =
2114                         ccs_compare_name_union(r->param.path.filename,
2115                                                &acl->name);
2116                 return r->param.path.matched_path != NULL;
2117         }
2118         return false;
2119 }
2120 
2121 /**
2122  * ccs_check_path_number_acl - Check permission for path number operation.
2123  *
2124  * @r:   Pointer to "struct ccs_request_info".
2125  * @ptr: Pointer to "struct ccs_acl_info".
2126  *
2127  * Returns true if granted, false otherwise.
2128  */
2129 static bool ccs_check_path_number_acl(struct ccs_request_info *r,
2130                                       const struct ccs_acl_info *ptr)
2131 {
2132         const struct ccs_path_number_acl *acl =
2133                 container_of(ptr, typeof(*acl), head);
2134         return (ptr->perm & (1 << r->param.path_number.operation)) &&
2135                 ccs_compare_number_union(r->param.path_number.number,
2136                                          &acl->number) &&
2137                 ccs_compare_name_union(r->param.path_number.filename,
2138                                        &acl->name);
2139 }
2140 
2141 /**
2142  * ccs_check_path2_acl - Check permission for path path operation.
2143  *
2144  * @r:   Pointer to "struct ccs_request_info".
2145  * @ptr: Pointer to "struct ccs_acl_info".
2146  *
2147  * Returns true if granted, false otherwise.
2148  */
2149 static bool ccs_check_path2_acl(struct ccs_request_info *r,
2150                                 const struct ccs_acl_info *ptr)
2151 {
2152         const struct ccs_path2_acl *acl =
2153                 container_of(ptr, typeof(*acl), head);
2154         return (ptr->perm & (1 << r->param.path2.operation)) &&
2155                 ccs_compare_name_union(r->param.path2.filename1, &acl->name1)
2156                 && ccs_compare_name_union(r->param.path2.filename2,
2157                                           &acl->name2);
2158 }
2159 
2160 /**
2161  * ccs_check_mkdev_acl - Check permission for path number number number operation.
2162  *
2163  * @r:   Pointer to "struct ccs_request_info".
2164  * @ptr: Pointer to "struct ccs_acl_info".
2165  *
2166  * Returns true if granted, false otherwise.
2167  */
2168 static bool ccs_check_mkdev_acl(struct ccs_request_info *r,
2169                                 const struct ccs_acl_info *ptr)
2170 {
2171         const struct ccs_mkdev_acl *acl =
2172                 container_of(ptr, typeof(*acl), head);
2173         return (ptr->perm & (1 << r->param.mkdev.operation)) &&
2174                 ccs_compare_number_union(r->param.mkdev.mode, &acl->mode) &&
2175                 ccs_compare_number_union(r->param.mkdev.major, &acl->major) &&
2176                 ccs_compare_number_union(r->param.mkdev.minor, &acl->minor) &&
2177                 ccs_compare_name_union(r->param.mkdev.filename, &acl->name);
2178 }
2179 
2180 /**
2181  * ccs_path_permission - Check permission for path operation.
2182  *
2183  * @r:         Pointer to "struct ccs_request_info".
2184  * @operation: Type of operation.
2185  * @filename:  Filename to check.
2186  *
2187  * Returns 0 on success, negative value otherwise.
2188  *
2189  * Caller holds ccs_read_lock().
2190  */
2191 static int ccs_path_permission(struct ccs_request_info *r, u8 operation,
2192                                const struct ccs_path_info *filename)
2193 {
2194         r->type = ccs_p2mac[operation];
2195         r->mode = ccs_get_mode(r->profile, r->type);
2196         if (r->mode == CCS_CONFIG_DISABLED)
2197                 return 0;
2198         r->param_type = CCS_TYPE_PATH_ACL;
2199         r->param.path.filename = filename;
2200         r->param.path.operation = operation;
2201         return ccs_check_acl(r);
2202 }
2203 
2204 /**
2205  * ccs_execute_permission - Check permission for execute operation.
2206  *
2207  * @r:         Pointer to "struct ccs_request_info".
2208  * @filename:  Filename to check.
2209  *
2210  * Returns 0 on success, CCS_RETRY_REQUEST on retry, negative value otherwise.
2211  *
2212  * Caller holds ccs_read_lock().
2213  */
2214 static int ccs_execute_permission(struct ccs_request_info *r,
2215                                   const struct ccs_path_info *filename)
2216 {
2217         int error;
2218         /*
2219          * Unlike other permission checks, this check is done regardless of
2220          * profile mode settings in order to check for domain transition
2221          * preference.
2222          */
2223         r->type = CCS_MAC_FILE_EXECUTE;
2224         r->mode = ccs_get_mode(r->profile, r->type);
2225         r->param_type = CCS_TYPE_PATH_ACL;
2226         r->param.path.filename = filename;
2227         r->param.path.operation = CCS_TYPE_EXECUTE;
2228         error = ccs_check_acl(r);
2229         r->ee->transition = r->matched_acl && r->matched_acl->cond &&
2230                 r->matched_acl->cond->exec_transit ?
2231                 r->matched_acl->cond->transit : NULL;
2232         return error;
2233 }
2234 
2235 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
2236 
2237 /**
2238  * __ccs_save_open_mode - Remember original flags passed to sys_open().
2239  *
2240  * @mode: Flags passed to sys_open().
2241  *
2242  * Returns nothing.
2243  *
2244  * TOMOYO does not check "file write" if open(path, O_TRUNC | O_RDONLY) was
2245  * requested because write() is not permitted. Instead, TOMOYO checks
2246  * "file truncate" if O_TRUNC is passed.
2247  *
2248  * TOMOYO does not check "file read" and "file write" if open(path, 3) was
2249  * requested because read()/write() are not permitted. Instead, TOMOYO checks
2250  * "file ioctl" when ioctl() is requested.
2251  */
2252 static void __ccs_save_open_mode(int mode)
2253 {
2254         if ((mode & 3) == 3)
2255                 ccs_current_security()->ccs_flags |= CCS_OPEN_FOR_IOCTL_ONLY;
2256 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 14)
2257         /* O_TRUNC passes MAY_WRITE to ccs_open_permission(). */
2258         else if (!(mode & 3) && (mode & O_TRUNC))
2259                 ccs_current_security()->ccs_flags |=
2260                         CCS_OPEN_FOR_READ_TRUNCATE;
2261 #endif
2262 }
2263 
2264 /**
2265  * __ccs_clear_open_mode - Forget original flags passed to sys_open().
2266  *
2267  * Returns nothing.
2268  */
2269 static void __ccs_clear_open_mode(void)
2270 {
2271         ccs_current_security()->ccs_flags &= ~(CCS_OPEN_FOR_IOCTL_ONLY |
2272                                                CCS_OPEN_FOR_READ_TRUNCATE);
2273 }
2274 
2275 #endif
2276 
2277 /**
2278  * __ccs_open_permission - Check permission for "read" and "write".
2279  *
2280  * @dentry: Pointer to "struct dentry".
2281  * @mnt:    Pointer to "struct vfsmount". Maybe NULL.
2282  * @flag:   Flags for open().
2283  *
2284  * Returns 0 on success, negative value otherwise.
2285  */
2286 static int __ccs_open_permission(struct dentry *dentry, struct vfsmount *mnt,
2287                                  const int flag)
2288 {
2289         struct ccs_request_info r;
2290         struct ccs_obj_info obj = {
2291                 .path1.dentry = dentry,
2292                 .path1.mnt = mnt,
2293         };
2294         const u32 ccs_flags = ccs_current_flags();
2295 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
2296         const u8 acc_mode = (flag & 3) == 3 ? 0 : ACC_MODE(flag);
2297 #else
2298         const u8 acc_mode = (ccs_flags & CCS_OPEN_FOR_IOCTL_ONLY) ? 0 :
2299 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 14)
2300                 (ccs_flags & CCS_OPEN_FOR_READ_TRUNCATE) ? 4 :
2301 #endif
2302                 ACC_MODE(flag);
2303 #endif
2304         int error = 0;
2305         struct ccs_path_info buf;
2306         int idx;
2307 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
2308         if (current->in_execve && !(ccs_flags & CCS_TASK_IS_IN_EXECVE))
2309                 return 0;
2310 #endif
2311 #ifndef CONFIG_CCSECURITY_FILE_READDIR
2312         if (d_is_dir(dentry))
2313                 return 0;
2314 #endif
2315         buf.name = NULL;
2316         r.mode = CCS_CONFIG_DISABLED;
2317         idx = ccs_read_lock();
2318         if (acc_mode && ccs_init_request_info(&r, CCS_MAC_FILE_OPEN)
2319             != CCS_CONFIG_DISABLED) {
2320                 if (!ccs_get_realpath(&buf, &obj.path1)) {
2321                         error = -ENOMEM;
2322                         goto out;
2323                 }
2324                 r.obj = &obj;
2325                 if (acc_mode & MAY_READ)
2326                         error = ccs_path_permission(&r, CCS_TYPE_READ, &buf);
2327                 if (!error && (acc_mode & MAY_WRITE))
2328                         error = ccs_path_permission(&r, (flag & O_APPEND) ?
2329                                                     CCS_TYPE_APPEND :
2330                                                     CCS_TYPE_WRITE, &buf);
2331         }
2332 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
2333         if (!error && (flag & O_TRUNC) &&
2334             ccs_init_request_info(&r, CCS_MAC_FILE_TRUNCATE)
2335             != CCS_CONFIG_DISABLED) {
2336                 if (!buf.name && !ccs_get_realpath(&buf, &obj.path1)) {
2337                         error = -ENOMEM;
2338                         goto out;
2339                 }
2340                 r.obj = &obj;
2341                 error = ccs_path_permission(&r, CCS_TYPE_TRUNCATE, &buf);
2342         }
2343 #endif
2344 out:
2345         kfree(buf.name);
2346         ccs_read_unlock(idx);
2347         if (r.mode != CCS_CONFIG_ENFORCING)
2348                 error = 0;
2349         return error;
2350 }
2351 
2352 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)
2353 
2354 /**
2355  * ccs_new_open_permission - Check permission for "read" and "write".
2356  *
2357  * @filp: Pointer to "struct file".
2358  *
2359  * Returns 0 on success, negative value otherwise.
2360  */
2361 static int ccs_new_open_permission(struct file *filp)
2362 {
2363         return __ccs_open_permission(filp->f_path.dentry, filp->f_path.mnt,
2364                                      filp->f_flags);
2365 }
2366 
2367 #endif
2368 
2369 /**
2370  * ccs_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "getattr", "chroot" and "unmount".
2371  *
2372  * @operation: Type of operation.
2373  * @dentry:    Pointer to "struct dentry".
2374  * @mnt:       Pointer to "struct vfsmount". Maybe NULL.
2375  * @target:    Symlink's target if @operation is CCS_TYPE_SYMLINK,
2376  *             NULL otherwise.
2377  *
2378  * Returns 0 on success, negative value otherwise.
2379  */
2380 static int ccs_path_perm(const u8 operation, struct dentry *dentry,
2381                          struct vfsmount *mnt, const char *target)
2382 {
2383         struct ccs_request_info r;
2384         struct ccs_obj_info obj = {
2385                 .path1.dentry = dentry,
2386                 .path1.mnt = mnt,
2387         };
2388         int error = 0;
2389         struct ccs_path_info buf;
2390         bool is_enforce = false;
2391         struct ccs_path_info symlink_target;
2392         int idx;
2393         buf.name = NULL;
2394         symlink_target.name = NULL;
2395         idx = ccs_read_lock();
2396         if (ccs_init_request_info(&r, ccs_p2mac[operation])
2397             == CCS_CONFIG_DISABLED)
2398                 goto out;
2399         is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
2400         error = -ENOMEM;
2401         if (!ccs_get_realpath(&buf, &obj.path1))
2402                 goto out;
2403         r.obj = &obj;
2404         switch (operation) {
2405         case CCS_TYPE_RMDIR:
2406         case CCS_TYPE_CHROOT:
2407                 ccs_add_slash(&buf);
2408                 break;
2409         case CCS_TYPE_SYMLINK:
2410                 symlink_target.name = ccs_encode(target);
2411                 if (!symlink_target.name)
2412                         goto out;
2413                 ccs_fill_path_info(&symlink_target);
2414                 obj.symlink_target = &symlink_target;
2415                 break;
2416         }
2417         error = ccs_path_permission(&r, operation, &buf);
2418         if (operation == CCS_TYPE_SYMLINK)
2419                 kfree(symlink_target.name);
2420 out:
2421         kfree(buf.name);
2422         ccs_read_unlock(idx);
2423         if (!is_enforce)
2424                 error = 0;
2425         return error;
2426 }
2427 
2428 /**
2429  * ccs_mkdev_perm - Check permission for "mkblock" and "mkchar".
2430  *
2431  * @operation: Type of operation. (CCS_TYPE_MKCHAR or CCS_TYPE_MKBLOCK)
2432  * @dentry:    Pointer to "struct dentry".
2433  * @mnt:       Pointer to "struct vfsmount". Maybe NULL.
2434  * @mode:      Create mode.
2435  * @dev:       Device number.
2436  *
2437  * Returns 0 on success, negative value otherwise.
2438  */
2439 static int ccs_mkdev_perm(const u8 operation, struct dentry *dentry,
2440                           struct vfsmount *mnt, const unsigned int mode,
2441                           unsigned int dev)
2442 {
2443         struct ccs_request_info r;
2444         struct ccs_obj_info obj = {
2445                 .path1.dentry = dentry,
2446                 .path1.mnt = mnt,
2447         };
2448         int error = 0;
2449         struct ccs_path_info buf;
2450         bool is_enforce = false;
2451         int idx;
2452         idx = ccs_read_lock();
2453         if (ccs_init_request_info(&r, ccs_pnnn2mac[operation])
2454             == CCS_CONFIG_DISABLED)
2455                 goto out;
2456         is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
2457         error = -EPERM;
2458         if (!capable(CAP_MKNOD))
2459                 goto out;
2460         error = -ENOMEM;
2461         if (!ccs_get_realpath(&buf, &obj.path1))
2462                 goto out;
2463         r.obj = &obj;
2464 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
2465         dev = new_decode_dev(dev);
2466 #endif
2467         r.param_type = CCS_TYPE_MKDEV_ACL;
2468         r.param.mkdev.filename = &buf;
2469         r.param.mkdev.operation = operation;
2470         r.param.mkdev.mode = mode;
2471         r.param.mkdev.major = MAJOR(dev);
2472         r.param.mkdev.minor = MINOR(dev);
2473         error = ccs_check_acl(&r);
2474         kfree(buf.name);
2475 out:
2476         ccs_read_unlock(idx);
2477         if (!is_enforce)
2478                 error = 0;
2479         return error;
2480 }
2481 
2482 /**
2483  * ccs_path2_perm - Check permission for "rename", "link" and "pivot_root".
2484  *
2485  * @operation: Type of operation.
2486  * @dentry1:   Pointer to "struct dentry".
2487  * @mnt1:      Pointer to "struct vfsmount". Maybe NULL.
2488  * @dentry2:   Pointer to "struct dentry".
2489  * @mnt2:      Pointer to "struct vfsmount". Maybe NULL.
2490  *
2491  * Returns 0 on success, negative value otherwise.
2492  */
2493 static int ccs_path2_perm(const u8 operation, struct dentry *dentry1,
2494                           struct vfsmount *mnt1, struct dentry *dentry2,
2495                           struct vfsmount *mnt2)
2496 {
2497         struct ccs_request_info r;
2498         int error = 0;
2499         struct ccs_path_info buf1;
2500         struct ccs_path_info buf2;
2501         bool is_enforce = false;
2502         struct ccs_obj_info obj = {
2503                 .path1.dentry = dentry1,
2504                 .path1.mnt = mnt1,
2505                 .path2.dentry = dentry2,
2506                 .path2.mnt = mnt2,
2507         };
2508         int idx;
2509         buf1.name = NULL;
2510         buf2.name = NULL;
2511         idx = ccs_read_lock();
2512         if (ccs_init_request_info(&r, ccs_pp2mac[operation])
2513             == CCS_CONFIG_DISABLED)
2514                 goto out;
2515         is_enforce = (r.mode == CCS_CONFIG_ENFORCING);
2516         error = -ENOMEM;
2517         if (!ccs_get_realpath(&buf1, &obj.path1) ||
2518             !ccs_get_realpath(&buf2, &obj.path2))
2519                 goto out;
2520         switch (operation) {
2521         case CCS_TYPE_RENAME:
2522         case CCS_TYPE_LINK:
2523                 if (!d_is_dir(dentry1))
2524                         break;
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(const struct path *old_path,
2719                                        const 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(const 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 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
3365         {
3366                 const int error = sock->ops->getname(sock, (struct sockaddr *)
3367                                                      &addr, &addr_len, 0);
3368                 if (error)
3369                         return error;
3370         }
3371 #else
3372         addr_len = sock->ops->getname(sock, (struct sockaddr *) &addr, 0);
3373         if (addr_len < 0)
3374                 return addr_len;
3375 #endif
3376         address.protocol = type;
3377         address.operation = CCS_NETWORK_LISTEN;
3378         if (family == PF_UNIX)
3379                 return ccs_check_unix_address((struct sockaddr *) &addr,
3380                                               addr_len, &address);
3381         return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
3382                                       &address);
3383 }
3384 
3385 /**
3386  * __ccs_socket_connect_permission - Check permission for setting the remote address of a socket.
3387  *
3388  * @sock:     Pointer to "struct socket".
3389  * @addr:     Pointer to "struct sockaddr".
3390  * @addr_len: Size of @addr.
3391  *
3392  * Returns 0 on success, negative value otherwise.
3393  */
3394 static int __ccs_socket_connect_permission(struct socket *sock,
3395                                            struct sockaddr *addr, int addr_len)
3396 {
3397         struct ccs_addr_info address;
3398         const u8 family = ccs_sock_family(sock->sk);
3399         const unsigned int type = sock->type;
3400         if (!family)
3401                 return 0;
3402         address.protocol = type;
3403         switch (type) {
3404         case SOCK_DGRAM:
3405         case SOCK_RAW:
3406                 address.operation = CCS_NETWORK_SEND;
3407                 break;
3408         case SOCK_STREAM:
3409         case SOCK_SEQPACKET:
3410                 address.operation = CCS_NETWORK_CONNECT;
3411                 break;
3412         default:
3413                 return 0;
3414         }
3415         if (family == PF_UNIX)
3416                 return ccs_check_unix_address(addr, addr_len, &address);
3417         return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
3418                                       &address);
3419 }
3420 
3421 /**
3422  * __ccs_socket_bind_permission - Check permission for setting the local address of a socket.
3423  *
3424  * @sock:     Pointer to "struct socket".
3425  * @addr:     Pointer to "struct sockaddr".
3426  * @addr_len: Size of @addr.
3427  *
3428  * Returns 0 on success, negative value otherwise.
3429  */
3430 static int __ccs_socket_bind_permission(struct socket *sock,
3431                                         struct sockaddr *addr, int addr_len)
3432 {
3433         struct ccs_addr_info address;
3434         const u8 family = ccs_sock_family(sock->sk);
3435         const unsigned int type = sock->type;
3436         if (!family)
3437                 return 0;
3438         switch (type) {
3439         case SOCK_STREAM:
3440         case SOCK_DGRAM:
3441         case SOCK_RAW:
3442         case SOCK_SEQPACKET:
3443                 address.protocol = type;
3444                 address.operation = CCS_NETWORK_BIND;
3445                 break;
3446         default:
3447                 return 0;
3448         }
3449         if (family == PF_UNIX)
3450                 return ccs_check_unix_address(addr, addr_len, &address);
3451         return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
3452                                       &address);
3453 }
3454 
3455 /**
3456  * __ccs_socket_sendmsg_permission - Check permission for sending a datagram.
3457  *
3458  * @sock: Pointer to "struct socket".
3459  * @msg:  Pointer to "struct msghdr".
3460  * @size: Unused.
3461  *
3462  * Returns 0 on success, negative value otherwise.
3463  */
3464 static int __ccs_socket_sendmsg_permission(struct socket *sock,
3465                                            struct msghdr *msg, int size)
3466 {
3467         struct ccs_addr_info address;
3468         const u8 family = ccs_sock_family(sock->sk);
3469         const unsigned int type = sock->type;
3470         if (!msg->msg_name || !family ||
3471             (type != SOCK_DGRAM && type != SOCK_RAW))
3472                 return 0;
3473         address.protocol = type;
3474         address.operation = CCS_NETWORK_SEND;
3475         if (family == PF_UNIX)
3476                 return ccs_check_unix_address((struct sockaddr *)
3477                                               msg->msg_name, msg->msg_namelen,
3478                                               &address);
3479         return ccs_check_inet_address((struct sockaddr *) msg->msg_name,
3480                                       msg->msg_namelen, sock->sk->sk_protocol,
3481                                       &address);
3482 }
3483 
3484 /**
3485  * __ccs_socket_post_accept_permission - Check permission for accepting a socket.
3486  *
3487  * @sock:    Pointer to "struct socket".
3488  * @newsock: Pointer to "struct socket".
3489  *
3490  * Returns 0 on success, negative value otherwise.
3491  */
3492 static int __ccs_socket_post_accept_permission(struct socket *sock,
3493                                                struct socket *newsock)
3494 {
3495         struct ccs_addr_info address;
3496         const u8 family = ccs_sock_family(sock->sk);
3497         const unsigned int type = sock->type;
3498         struct sockaddr_storage addr;
3499         int addr_len;
3500         if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
3501                 return 0;
3502 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0)
3503         {
3504                 const int error = newsock->ops->getname(newsock,
3505                                                         (struct sockaddr *)
3506                                                         &addr, &addr_len, 2);
3507                 if (error)
3508                         return error;
3509         }
3510 #else
3511         addr_len = newsock->ops->getname(newsock, (struct sockaddr *) &addr,
3512                                          2);
3513         if (addr_len < 0)
3514                 return addr_len;
3515 #endif
3516         address.protocol = type;
3517         address.operation = CCS_NETWORK_ACCEPT;
3518         if (family == PF_UNIX)
3519                 return ccs_check_unix_address((struct sockaddr *) &addr,
3520                                               addr_len, &address);
3521         return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
3522                                       &address);
3523 }
3524 
3525 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG
3526 
3527 /**
3528  * __ccs_socket_post_recvmsg_permission - Check permission for receiving a datagram.
3529  *
3530  * @sk:    Pointer to "struct sock".
3531  * @skb:   Pointer to "struct sk_buff".
3532  * @flags: Flags passed to skb_recv_datagram().
3533  *
3534  * Returns 0 on success, negative value otherwise.
3535  */
3536 static int __ccs_socket_post_recvmsg_permission(struct sock *sk,
3537                                                 struct sk_buff *skb, int flags)
3538 {
3539         struct ccs_addr_info address;
3540         const u8 family = ccs_sock_family(sk);
3541         const unsigned int type = sk->sk_type;
3542         struct sockaddr_storage addr;
3543         if (!family)
3544                 return 0;
3545         switch (type) {
3546         case SOCK_DGRAM:
3547         case SOCK_RAW:
3548                 address.protocol = type;
3549                 break;
3550         default:
3551                 return 0;
3552         }
3553         address.operation = CCS_NETWORK_RECV;
3554         switch (family) {
3555         case PF_INET6:
3556                 {
3557                         struct in6_addr *sin6 = (struct in6_addr *) &addr;
3558                         address.inet.is_ipv6 = true;
3559                         if (type == SOCK_DGRAM &&
3560                             skb->protocol == htons(ETH_P_IP))
3561                                 ipv6_addr_set(sin6, 0, 0, htonl(0xffff),
3562                                               ip_hdr(skb)->saddr);
3563                         else
3564                                 *sin6 = ipv6_hdr(skb)->saddr;
3565                         break;
3566                 }
3567         case PF_INET:
3568                 {
3569                         struct in_addr *sin4 = (struct in_addr *) &addr;
3570                         address.inet.is_ipv6 = false;
3571                         sin4->s_addr = ip_hdr(skb)->saddr;
3572                         break;
3573                 }
3574         default: /* == PF_UNIX */
3575                 {
3576 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
3577                         struct unix_address *u = unix_sk(skb->sk)->addr;
3578 #else
3579                         struct unix_address *u =
3580                                 skb->sk->protinfo.af_unix.addr;
3581 #endif
3582                         unsigned int addr_len;
3583                         if (u && u->len <= sizeof(addr)) {
3584                                 addr_len = u->len;
3585                                 memcpy(&addr, u->name, addr_len);
3586                         } else {
3587                                 addr_len = 0;
3588                                 addr.ss_family = AF_UNIX;
3589                         }
3590                         if (ccs_check_unix_address((struct sockaddr *) &addr,
3591                                                    addr_len, &address))
3592                                 goto out;
3593                         return 0;
3594                 }
3595         }
3596         address.inet.address = (u32 *) &addr;
3597         if (type == SOCK_DGRAM)
3598                 address.inet.port = udp_hdr(skb)->source;
3599         else
3600                 address.inet.port = htons(sk->sk_protocol);
3601         if (ccs_inet_entry(&address))
3602                 goto out;
3603         return 0;
3604 out:
3605         /*
3606          * Remove from queue if MSG_PEEK is used so that
3607          * the head message from unwanted source in receive queue will not
3608          * prevent the caller from picking up next message from wanted source
3609          * when the caller is using MSG_PEEK flag for picking up.
3610          */
3611         {
3612 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
3613                 bool slow = false;
3614                 if (type == SOCK_DGRAM && family != PF_UNIX)
3615                         slow = lock_sock_fast(sk);
3616 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
3617                 if (type == SOCK_DGRAM && family != PF_UNIX)
3618                         lock_sock(sk);
3619 #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 2
3620                 if (type == SOCK_DGRAM && family != PF_UNIX)
3621                         lock_sock(sk);
3622 #endif
3623                 skb_kill_datagram(sk, skb, flags);
3624 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
3625                 if (type == SOCK_DGRAM && family != PF_UNIX)
3626                         unlock_sock_fast(sk, slow);
3627 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
3628                 if (type == SOCK_DGRAM && family != PF_UNIX)
3629                         release_sock(sk);
3630 #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 2
3631                 if (type == SOCK_DGRAM && family != PF_UNIX)
3632                         release_sock(sk);
3633 #endif
3634         }
3635         return -EPERM;
3636 }
3637 
3638 #endif
3639 
3640 #endif
3641 
3642 #if defined(CONFIG_CCSECURITY_CAPABILITY) || defined(CONFIG_CCSECURITY_NETWORK)
3643 
3644 /**
3645  * ccs_kernel_service - Check whether I'm kernel service or not.
3646  *
3647  * Returns true if I'm kernel service, false otherwise.
3648  */
3649 static bool ccs_kernel_service(void)
3650 {
3651         /* Nothing to do if I am a kernel service. */
3652         return segment_eq(get_fs(), KERNEL_DS);
3653 }
3654 
3655 #endif
3656 
3657 #ifdef CONFIG_CCSECURITY_CAPABILITY
3658 
3659 /**
3660  * ccs_check_capability_acl - Check permission for capability operation.
3661  *
3662  * @r:   Pointer to "struct ccs_request_info".
3663  * @ptr: Pointer to "struct ccs_acl_info".
3664  *
3665  * Returns true if granted, false otherwise.
3666  */
3667 static bool ccs_check_capability_acl(struct ccs_request_info *r,
3668                                      const struct ccs_acl_info *ptr)
3669 {
3670         const struct ccs_capability_acl *acl =
3671                 container_of(ptr, typeof(*acl), head);
3672         return acl->operation == r->param.capability.operation;
3673 }
3674 
3675 /**
3676  * ccs_capable - Check permission for capability.
3677  *
3678  * @operation: Type of operation.
3679  *
3680  * Returns true on success, false otherwise.
3681  */
3682 static bool __ccs_capable(const u8 operation)
3683 {
3684         struct ccs_request_info r;
3685         int error = 0;
3686         const int idx = ccs_read_lock();
3687         if (ccs_init_request_info(&r, ccs_c2mac[operation])
3688             != CCS_CONFIG_DISABLED) {
3689                 r.param_type = CCS_TYPE_CAPABILITY_ACL;
3690                 r.param.capability.operation = operation;
3691                 error = ccs_check_acl(&r);
3692         }
3693         ccs_read_unlock(idx);
3694         return !error;
3695 }
3696 
3697 /**
3698  * __ccs_socket_create_permission - Check permission for creating a socket.
3699  *
3700  * @family:   Protocol family.
3701  * @type:     Unused.
3702  * @protocol: Unused.
3703  *
3704  * Returns 0 on success, negative value otherwise.
3705  */
3706 static int __ccs_socket_create_permission(int family, int type, int protocol)
3707 {
3708         if (ccs_kernel_service())
3709                 return 0;
3710         if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
3711                 return -EPERM;
3712         if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
3713                 return -EPERM;
3714         return 0;
3715 }
3716 
3717 /**
3718  * __ccs_ptrace_permission - Check permission for ptrace().
3719  *
3720  * @request: Unused.
3721  * @pid:     Unused.
3722  *
3723  * Returns 0 on success, negative value otherwise.
3724  *
3725  * Since this function is called from location where it is permitted to sleep,
3726  * it is racy to check target process's domainname anyway. Therefore, we don't
3727  * use target process's domainname.
3728  */
3729 static int __ccs_ptrace_permission(long request, long pid)
3730 {
3731         return __ccs_capable(CCS_SYS_PTRACE) ? 0 : -EPERM;
3732 }
3733 
3734 #endif
3735 
3736 #ifdef CONFIG_CCSECURITY_IPC
3737 
3738 /**
3739  * ccs_check_signal_acl - Check permission for signal operation.
3740  *
3741  * @r:   Pointer to "struct ccs_request_info".
3742  * @ptr: Pointer to "struct ccs_acl_info".
3743  *
3744  * Returns true if granted, false otherwise.
3745  */
3746 static bool ccs_check_signal_acl(struct ccs_request_info *r,
3747                                  const struct ccs_acl_info *ptr)
3748 {
3749         const struct ccs_signal_acl *acl =
3750                 container_of(ptr, typeof(*acl), head);
3751         if (ccs_compare_number_union(r->param.signal.sig, &acl->sig)) {
3752                 const int len = acl->domainname->total_len;
3753                 if (!strncmp(acl->domainname->name,
3754                              r->param.signal.dest_pattern, len)) {
3755                         switch (r->param.signal.dest_pattern[len]) {
3756                         case ' ':
3757                         case '\0':
3758                                 return true;
3759                         }
3760                 }
3761         }
3762         return false;
3763 }
3764 
3765 /**
3766  * ccs_signal_acl2 - Check permission for signal.
3767  *
3768  * @sig: Signal number.
3769  * @pid: Target's PID.
3770  *
3771  * Returns 0 on success, negative value otherwise.
3772  *
3773  * Caller holds ccs_read_lock().
3774  */
3775 static int ccs_signal_acl2(const int sig, const int pid)
3776 {
3777         struct ccs_request_info r;
3778         struct ccs_domain_info *dest = NULL;
3779         const struct ccs_domain_info * const domain = ccs_current_domain();
3780         if (ccs_init_request_info(&r, CCS_MAC_SIGNAL) == CCS_CONFIG_DISABLED)
3781                 return 0;
3782         if (!sig)
3783                 return 0;                /* No check for NULL signal. */
3784         r.param_type = CCS_TYPE_SIGNAL_ACL;
3785         r.param.signal.sig = sig;
3786         r.param.signal.dest_pattern = domain->domainname->name;
3787         r.granted = true;
3788         if (ccs_sys_getpid() == pid) {
3789                 ccs_audit_log(&r);
3790                 return 0;                /* No check for self process. */
3791         }
3792         { /* Simplified checking. */
3793                 struct task_struct *p = NULL;
3794                 ccs_tasklist_lock();
3795 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
3796                 if (pid > 0)
3797                         p = ccsecurity_exports.find_task_by_vpid((pid_t) pid);
3798                 else if (pid == 0)
3799                         p = current;
3800                 else if (pid == -1)
3801                         dest = &ccs_kernel_domain;
3802                 else
3803                         p = ccsecurity_exports.find_task_by_vpid((pid_t) -pid);
3804 #else
3805                 if (pid > 0)
3806                         p = find_task_by_pid((pid_t) pid);
3807                 else if (pid == 0)
3808                         p = current;
3809                 else if (pid == -1)
3810                         dest = &ccs_kernel_domain;
3811                 else
3812                         p = find_task_by_pid((pid_t) -pid);
3813 #endif
3814                 if (p)
3815                         dest = ccs_task_domain(p);
3816                 ccs_tasklist_unlock();
3817         }
3818         if (!dest)
3819                 return 0; /* I can't find destinatioin. */
3820         if (domain == dest) {
3821                 ccs_audit_log(&r);
3822                 return 0;                /* No check for self domain. */
3823         }
3824         r.param.signal.dest_pattern = dest->domainname->name;
3825         return ccs_check_acl(&r);
3826 }
3827 
3828 /**
3829  * ccs_signal_acl - Check permission for signal.
3830  *
3831  * @pid: Target's PID.
3832  * @sig: Signal number.
3833  *
3834  * Returns 0 on success, negative value otherwise.
3835  */
3836 static int ccs_signal_acl(const int pid, const int sig)
3837 {
3838         int error;
3839         if (!sig)
3840                 error = 0;
3841         else {
3842                 const int idx = ccs_read_lock();
3843                 error = ccs_signal_acl2(sig, pid);
3844                 ccs_read_unlock(idx);
3845         }
3846         return error;
3847 }
3848 
3849 /**
3850  * ccs_signal_acl0 - Permission check for signal().
3851  *
3852  * @tgid: Unused.
3853  * @pid:  Target's PID.
3854  * @sig:  Signal number.
3855  *
3856  * Returns 0 on success, negative value otherwise.
3857  */
3858 static int ccs_signal_acl0(pid_t tgid, pid_t pid, int sig)
3859 {
3860         return ccs_signal_acl(pid, sig);
3861 }
3862 
3863 #endif
3864 
3865 #ifdef CONFIG_CCSECURITY_MISC
3866 
3867 /**
3868  * ccs_check_env_acl - Check permission for environment variable's name.
3869  *
3870  * @r:   Pointer to "struct ccs_request_info".
3871  * @ptr: Pointer to "struct ccs_acl_info".
3872  *
3873  * Returns true if granted, false otherwise.
3874  */
3875 static bool ccs_check_env_acl(struct ccs_request_info *r,
3876                               const struct ccs_acl_info *ptr)
3877 {
3878         const struct ccs_env_acl *acl = container_of(ptr, typeof(*acl), head);
3879         return ccs_path_matches_pattern(r->param.environ.name, acl->env);
3880 }
3881 
3882 /**
3883  * ccs_env_perm - Check permission for environment variable's name.
3884  *
3885  * @r:   Pointer to "struct ccs_request_info".
3886  * @env: The name of environment variable.
3887  *
3888  * Returns 0 on success, negative value otherwise.
3889  *
3890  * Caller holds ccs_read_lock().
3891  */
3892 static int ccs_env_perm(struct ccs_request_info *r, const char *env)
3893 {
3894         struct ccs_path_info environ;
3895         if (!env || !*env)
3896                 return 0;
3897         environ.name = env;
3898         ccs_fill_path_info(&environ);
3899         r->param_type = CCS_TYPE_ENV_ACL;
3900         r->param.environ.name = &environ;
3901         return ccs_check_acl(r);
3902 }
3903 
3904 /**
3905  * ccs_environ - Check permission for environment variable names.
3906  *
3907  * @ee: Pointer to "struct ccs_execve".
3908  *
3909  * Returns 0 on success, negative value otherwise.
3910  */
3911 static int ccs_environ(struct ccs_execve *ee)
3912 {
3913         struct ccs_request_info *r = &ee->r;
3914         struct linux_binprm *bprm = ee->bprm;
3915         /* env_page.data is allocated by ccs_dump_page(). */
3916         struct ccs_page_dump env_page = { };
3917         char *arg_ptr; /* Size is CCS_EXEC_TMPSIZE bytes */
3918         int arg_len = 0;
3919         unsigned long pos = bprm->p;
3920         int offset = pos % PAGE_SIZE;
3921         int argv_count = bprm->argc;
3922         int envp_count = bprm->envc;
3923         /* printk(KERN_DEBUG "start %d %d\n", argv_count, envp_count); */
3924         int error = -ENOMEM;
3925         ee->r.type = CCS_MAC_ENVIRON;
3926         ee->r.profile = ccs_current_domain()->profile;
3927         ee->r.mode = ccs_get_mode(ee->r.profile, CCS_MAC_ENVIRON);
3928         if (!r->mode || !envp_count)
3929                 return 0;
3930         arg_ptr = kzalloc(CCS_EXEC_TMPSIZE, CCS_GFP_FLAGS);
3931         if (!arg_ptr)
3932                 goto out;
3933         while (error == -ENOMEM) {
3934                 if (!ccs_dump_page(bprm, pos, &env_page))
3935                         goto out;
3936                 pos += PAGE_SIZE - offset;
3937                 /* Read. */
3938                 while (argv_count && offset < PAGE_SIZE) {
3939                         if (!env_page.data[offset++])
3940                                 argv_count--;
3941                 }
3942                 if (argv_count) {
3943                         offset = 0;
3944                         continue;
3945                 }
3946                 while (offset < PAGE_SIZE) {
3947                         const unsigned char c = env_page.data[offset++];
3948                         if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
3949                                 if (c == '=') {
3950                                         arg_ptr[arg_len++] = '\0';
3951                                 } else if (c == '\\') {
3952                                         arg_ptr[arg_len++] = '\\';
3953                                         arg_ptr[arg_len++] = '\\';
3954                                 } else if (c > ' ' && c < 127) {
3955                                         arg_ptr[arg_len++] = c;
3956                                 } else {
3957                                         arg_ptr[arg_len++] = '\\';
3958                                         arg_ptr[arg_len++] = (c >> 6) + '';
3959                                         arg_ptr[arg_len++]
3960                                                 = ((c >> 3) & 7) + '';
3961                                         arg_ptr[arg_len++] = (c & 7) + '';
3962                                 }
3963                         } else {
3964                                 arg_ptr[arg_len] = '\0';
3965                         }
3966                         if (c)
3967                                 continue;
3968                         if (ccs_env_perm(r, arg_ptr)) {
3969                                 error = -EPERM;
3970                                 break;
3971                         }
3972                         if (!--envp_count) {
3973                                 error = 0;
3974                                 break;
3975                         }
3976                         arg_len = 0;
3977                 }
3978                 offset = 0;
3979         }
3980 out:
3981         if (r->mode != CCS_CONFIG_ENFORCING)
3982                 error = 0;
3983         kfree(env_page.data);
3984         kfree(arg_ptr);
3985         return error;
3986 }
3987 
3988 #endif
3989 
3990 /**
3991  * ccs_argv - Check argv[] in "struct linux_binbrm".
3992  *
3993  * @index:   Index number of @arg_ptr.
3994  * @arg_ptr: Contents of argv[@index].
3995  * @argc:    Length of @argv.
3996  * @argv:    Pointer to "struct ccs_argv".
3997  * @checked: Set to true if @argv[@index] was found.
3998  *
3999  * Returns true on success, false otherwise.
4000  */
4001 static bool ccs_argv(const unsigned int index, const char *arg_ptr,
4002                      const int argc, const struct ccs_argv *argv,
4003                      u8 *checked)
4004 {
4005         int i;
4006         struct ccs_path_info arg;
4007         arg.name = arg_ptr;
4008         for (i = 0; i < argc; argv++, checked++, i++) {
4009                 bool result;
4010                 if (index != argv->index)
4011                         continue;
4012                 *checked = 1;
4013                 ccs_fill_path_info(&arg);
4014                 result = ccs_path_matches_pattern(&arg, argv->value);
4015                 if (argv->is_not)
4016                         result = !result;
4017                 if (!result)
4018                         return false;
4019         }
4020         return true;
4021 }
4022 
4023 /**
4024  * ccs_envp - Check envp[] in "struct linux_binbrm".
4025  *
4026  * @env_name:  The name of environment variable.
4027  * @env_value: The value of environment variable.
4028  * @envc:      Length of @envp.
4029  * @envp:      Pointer to "struct ccs_envp".
4030  * @checked:   Set to true if @envp[@env_name] was found.
4031  *
4032  * Returns true on success, false otherwise.
4033  */
4034 static bool ccs_envp(const char *env_name, const char *env_value,
4035                      const int envc, const struct ccs_envp *envp,
4036                      u8 *checked)
4037 {
4038         int i;
4039         struct ccs_path_info name;
4040         struct ccs_path_info value;
4041         name.name = env_name;
4042         ccs_fill_path_info(&name);
4043         value.name = env_value;
4044         ccs_fill_path_info(&value);
4045         for (i = 0; i < envc; envp++, checked++, i++) {
4046                 bool result;
4047                 if (!ccs_path_matches_pattern(&name, envp->name))
4048                         continue;
4049                 *checked = 1;
4050                 if (envp->value) {
4051                         result = ccs_path_matches_pattern(&value, envp->value);
4052                         if (envp->is_not)
4053                                 result = !result;
4054                 } else {
4055                         result = true;
4056                         if (!envp->is_not)
4057                                 result = !result;
4058                 }
4059                 if (!result)
4060                         return false;
4061         }
4062         return true;
4063 }
4064 
4065 /**
4066  * ccs_scan_bprm - Scan "struct linux_binprm".
4067  *
4068  * @ee:   Pointer to "struct ccs_execve".
4069  * @argc: Length of @argc.
4070  * @argv: Pointer to "struct ccs_argv".
4071  * @envc: Length of @envp.
4072  * @envp: Poiner to "struct ccs_envp".
4073  *
4074  * Returns true on success, false otherwise.
4075  */
4076 static bool ccs_scan_bprm(struct ccs_execve *ee,
4077                           const u16 argc, const struct ccs_argv *argv,
4078                           const u16 envc, const struct ccs_envp *envp)
4079 {
4080         struct linux_binprm *bprm = ee->bprm;
4081         struct ccs_page_dump *dump = &ee->dump;
4082         char *arg_ptr = ee->tmp;
4083         int arg_len = 0;
4084         unsigned long pos = bprm->p;
4085         int offset = pos % PAGE_SIZE;
4086         int argv_count = bprm->argc;
4087         int envp_count = bprm->envc;
4088         bool result = true;
4089         u8 local_checked[32];
4090         u8 *checked;
4091         if (argc + envc <= sizeof(local_checked)) {
4092                 checked = local_checked;
4093                 memset(local_checked, 0, sizeof(local_checked));
4094         } else {
4095                 checked = kzalloc(argc + envc, CCS_GFP_FLAGS);
4096                 if (!checked)
4097                         return false;
4098         }
4099         while (argv_count || envp_count) {
4100                 if (!ccs_dump_page(bprm, pos, dump)) {
4101                         result = false;
4102                         goto out;
4103                 }
4104                 pos += PAGE_SIZE - offset;
4105                 while (offset < PAGE_SIZE) {
4106                         /* Read. */
4107                         const char *kaddr = dump->data;
4108                         const unsigned char c = kaddr[offset++];
4109                         if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
4110                                 if (c == '\\') {
4111                                         arg_ptr[arg_len++] = '\\';
4112                                         arg_ptr[arg_len++] = '\\';
4113                                 } else if (c > ' ' && c < 127) {
4114                                         arg_ptr[arg_len++] = c;
4115                                 } else {
4116                                         arg_ptr[arg_len++] = '\\';
4117                                         arg_ptr[arg_len++] = (c >> 6) + '';
4118                                         arg_ptr[arg_len++] =
4119                                                 ((c >> 3) & 7) + '';
4120                                         arg_ptr[arg_len++] = (c & 7) + '';
4121                                 }
4122                         } else {
4123                                 arg_ptr[arg_len] = '\0';
4124                         }
4125                         if (c)
4126                                 continue;
4127                         /* Check. */
4128                         if (argv_count) {
4129                                 if (!ccs_argv(bprm->argc - argv_count,
4130                                               arg_ptr, argc, argv,
4131                                               checked)) {
4132                                         result = false;
4133                                         break;
4134                                 }
4135                                 argv_count--;
4136                         } else if (envp_count) {
4137                                 char *cp = strchr(arg_ptr, '=');
4138                                 if (cp) {
4139                                         *cp = '\0';
4140                                         if (!ccs_envp(arg_ptr, cp + 1,
4141                                                       envc, envp,
4142                                                       checked + argc)) {
4143                                                 result = false;
4144                                                 break;
4145                                         }
4146                                 }
4147                                 envp_count--;
4148                         } else {
4149                                 break;
4150                         }
4151                         arg_len = 0;
4152                 }
4153                 offset = 0;
4154                 if (!result)
4155                         break;
4156         }
4157 out:
4158         if (result) {
4159                 int i;
4160                 /* Check not-yet-checked entries. */
4161                 for (i = 0; i < argc; i++) {
4162                         if (checked[i])
4163                                 continue;
4164                         /*
4165                          * Return true only if all unchecked indexes in
4166                          * bprm->argv[] are not matched.
4167                          */
4168                         if (argv[i].is_not)
4169                                 continue;
4170                         result = false;
4171                         break;
4172                 }
4173                 for (i = 0; i < envc; envp++, i++) {
4174                         if (checked[argc + i])
4175                                 continue;
4176                         /*
4177                          * Return true only if all unchecked environ variables
4178                          * in bprm->envp[] are either undefined or not matched.
4179                          */
4180                         if ((!envp->value && !envp->is_not) ||
4181                             (envp->value && envp->is_not))
4182                                 continue;
4183                         result = false;
4184                         break;
4185                 }
4186         }
4187         if (checked != local_checked)
4188                 kfree(checked);
4189         return result;
4190 }
4191 
4192 /**
4193  * ccs_scan_exec_realpath - Check "exec.realpath" parameter of "struct ccs_condition".
4194  *
4195  * @file:  Pointer to "struct file".
4196  * @ptr:   Pointer to "struct ccs_name_union".
4197  * @match: True if "exec.realpath=", false if "exec.realpath!=".
4198  *
4199  * Returns true on success, false otherwise.
4200  */
4201 static bool ccs_scan_exec_realpath(struct file *file,
4202                                    const struct ccs_name_union *ptr,
4203                                    const bool match)
4204 {
4205         bool result;
4206         struct ccs_path_info exe;
4207 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
4208         struct path path;
4209 #endif
4210         if (!file)
4211                 return false;
4212 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
4213         exe.name = ccs_realpath(&file->f_path);
4214 #else
4215         path.mnt = file->f_vfsmnt;
4216         path.dentry = file->f_dentry;
4217         exe.name = ccs_realpath(&path);
4218 #endif
4219         if (!exe.name)
4220                 return false;
4221         ccs_fill_path_info(&exe);
4222         result = ccs_compare_name_union(&exe, ptr);
4223         kfree(exe.name);
4224         return result == match;
4225 }
4226 
4227 /**
4228  * ccs_get_attributes - Revalidate "struct inode".
4229  *
4230  * @obj: Pointer to "struct ccs_obj_info".
4231  *
4232  * Returns nothing.
4233  */
4234 void ccs_get_attributes(struct ccs_obj_info *obj)
4235 {
4236         u8 i;
4237         struct dentry *dentry = NULL;
4238 
4239         for (i = 0; i < CCS_MAX_PATH_STAT; i++) {
4240                 struct inode *inode;
4241                 switch (i) {
4242                 case CCS_PATH1:
4243                         dentry = obj->path1.dentry;
4244                         if (!dentry)
4245                                 continue;
4246                         break;
4247                 case CCS_PATH2:
4248                         dentry = obj->path2.dentry;
4249                         if (!dentry)
4250                                 continue;
4251                         break;
4252                 default:
4253                         if (!dentry)
4254                                 continue;
4255 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
4256                         spin_lock(&dcache_lock);
4257                         dentry = dget(dentry->d_parent);
4258                         spin_unlock(&dcache_lock);
4259 #else
4260                         dentry = dget_parent(dentry);
4261 #endif
4262                         break;
4263                 }
4264                 inode = d_backing_inode(dentry);
4265                 if (inode) {
4266                         struct ccs_mini_stat *stat = &obj->stat[i];
4267                         stat->uid  = inode->i_uid;
4268                         stat->gid  = inode->i_gid;
4269                         stat->ino  = inode->i_ino;
4270                         stat->mode = inode->i_mode;
4271 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
4272                         stat->dev  = inode->i_dev;
4273 #else
4274                         stat->dev  = inode->i_sb->s_dev;
4275 #endif
4276                         stat->rdev = inode->i_rdev;
4277                         obj->stat_valid[i] = true;
4278                 }
4279                 if (i & 1) /* i == CCS_PATH1_PARENT || i == CCS_PATH2_PARENT */
4280                         dput(dentry);
4281         }
4282 }
4283 
4284 /**
4285  * ccs_condition - Check condition part.
4286  *
4287  * @r:    Pointer to "struct ccs_request_info".
4288  * @cond: Pointer to "struct ccs_condition". Maybe NULL.
4289  *
4290  * Returns true on success, false otherwise.
4291  *
4292  * Caller holds ccs_read_lock().
4293  */
4294 static bool ccs_condition(struct ccs_request_info *r,
4295                           const struct ccs_condition *cond)
4296 {
4297         const u32 ccs_flags = ccs_current_flags();
4298         u32 i;
4299         unsigned long min_v[2] = { 0, 0 };
4300         unsigned long max_v[2] = { 0, 0 };
4301         const struct ccs_condition_element *condp;
4302         const struct ccs_number_union *numbers_p;
4303         const struct ccs_name_union *names_p;
4304         const struct ccs_argv *argv;
4305         const struct ccs_envp *envp;
4306         struct ccs_obj_info *obj;
4307         u16 condc;
4308         u16 argc;
4309         u16 envc;
4310         struct linux_binprm *bprm = NULL;
4311         if (!cond)
4312                 return true;
4313         condc = cond->condc;
4314         argc = cond->argc;
4315         envc = cond->envc;
4316         obj = r->obj;
4317         if (r->ee)
4318                 bprm = r->ee->bprm;
4319         if (!bprm && (argc || envc))
4320                 return false;
4321         condp = (struct ccs_condition_element *) (cond + 1);
4322         numbers_p = (const struct ccs_number_union *) (condp + condc);
4323         names_p = (const struct ccs_name_union *)
4324                 (numbers_p + cond->numbers_count);
4325         argv = (const struct ccs_argv *) (names_p + cond->names_count);
4326         envp = (const struct ccs_envp *) (argv + argc);
4327         for (i = 0; i < condc; i++) {
4328                 const bool match = condp->equals;
4329                 const u8 left = condp->left;
4330                 const u8 right = condp->right;
4331                 bool is_bitop[2] = { false, false };
4332                 u8 j;
4333                 condp++;
4334                 /* Check argv[] and envp[] later. */
4335                 if (left == CCS_ARGV_ENTRY || left == CCS_ENVP_ENTRY)
4336                         continue;
4337                 /* Check string expressions. */
4338                 if (right == CCS_NAME_UNION) {
4339                         const struct ccs_name_union *ptr = names_p++;
4340                         switch (left) {
4341                                 struct ccs_path_info *symlink;
4342                                 struct ccs_execve *ee;
4343                                 struct file *file;
4344                         case CCS_SYMLINK_TARGET:
4345                                 symlink = obj ? obj->symlink_target : NULL;
4346                                 if (!symlink ||
4347                                     !ccs_compare_name_union(symlink, ptr)
4348                                     == match)
4349                                         goto out;
4350                                 break;
4351                         case CCS_EXEC_REALPATH:
4352                                 ee = r->ee;
4353                                 file = ee ? ee->bprm->file : NULL;
4354                                 if (!ccs_scan_exec_realpath(file, ptr, match))
4355                                         goto out;
4356                                 break;
4357                         }
4358                         continue;
4359                 }
4360                 /* Check numeric or bit-op expressions. */
4361                 for (j = 0; j < 2; j++) {
4362                         const u8 index = j ? right : left;
4363                         unsigned long value = 0;
4364                         switch (index) {
4365                         case CCS_TASK_UID:
4366                                 value = from_kuid(&init_user_ns,
4367                                                   current_uid());
4368                                 break;
4369                         case CCS_TASK_EUID:
4370                                 value = from_kuid(&init_user_ns,
4371                                                   current_euid());
4372                                 break;
4373                         case CCS_TASK_SUID:
4374                                 value = from_kuid(&init_user_ns,
4375                                                   current_suid());
4376                                 break;
4377                         case CCS_TASK_FSUID:
4378                                 value = from_kuid(&init_user_ns,
4379                                                   current_fsuid());
4380                                 break;
4381                         case CCS_TASK_GID:
4382                                 value = from_kgid(&init_user_ns,
4383                                                   current_gid());
4384                                 break;
4385                         case CCS_TASK_EGID:
4386                                 value = from_kgid(&init_user_ns,
4387                                                   current_egid());
4388                                 break;
4389                         case CCS_TASK_SGID:
4390                                 value = from_kgid(&init_user_ns,
4391                                                   current_sgid());
4392                                 break;
4393                         case CCS_TASK_FSGID:
4394                                 value = from_kgid(&init_user_ns,
4395                                                   current_fsgid());
4396                                 break;
4397                         case CCS_TASK_PID:
4398                                 value = ccs_sys_getpid();
4399                                 break;
4400                         case CCS_TASK_PPID:
4401                                 value = ccs_sys_getppid();
4402                                 break;
4403                         case CCS_TYPE_IS_SOCKET:
4404                                 value = S_IFSOCK;
4405                                 break;
4406                         case CCS_TYPE_IS_SYMLINK:
4407                                 value = S_IFLNK;
4408                                 break;
4409                         case CCS_TYPE_IS_FILE:
4410                                 value = S_IFREG;
4411                                 break;
4412                         case CCS_TYPE_IS_BLOCK_DEV:
4413                                 value = S_IFBLK;
4414                                 break;
4415                         case CCS_TYPE_IS_DIRECTORY:
4416                                 value = S_IFDIR;
4417                                 break;
4418                         case CCS_TYPE_IS_CHAR_DEV:
4419                                 value = S_IFCHR;
4420                                 break;
4421                         case CCS_TYPE_IS_FIFO:
4422                                 value = S_IFIFO;
4423                                 break;
4424                         case CCS_MODE_SETUID:
4425                                 value = S_ISUID;
4426                                 break;
4427                         case CCS_MODE_SETGID:
4428                                 value = S_ISGID;
4429                                 break;
4430                         case CCS_MODE_STICKY:
4431                                 value = S_ISVTX;
4432                                 break;
4433                         case CCS_MODE_OWNER_READ:
4434                                 value = S_IRUSR;
4435                                 break;
4436                         case CCS_MODE_OWNER_WRITE:
4437                                 value = S_IWUSR;
4438                                 break;
4439                         case CCS_MODE_OWNER_EXECUTE:
4440                                 value = S_IXUSR;
4441                                 break;
4442                         case CCS_MODE_GROUP_READ:
4443                                 value = S_IRGRP;
4444                                 break;
4445                         case CCS_MODE_GROUP_WRITE:
4446                                 value = S_IWGRP;
4447                                 break;
4448                         case CCS_MODE_GROUP_EXECUTE:
4449                                 value = S_IXGRP;
4450                                 break;
4451                         case CCS_MODE_OTHERS_READ:
4452                                 value = S_IROTH;
4453                                 break;
4454                         case CCS_MODE_OTHERS_WRITE:
4455                                 value = S_IWOTH;
4456                                 break;
4457                         case CCS_MODE_OTHERS_EXECUTE:
4458                                 value = S_IXOTH;
4459                                 break;
4460                         case CCS_EXEC_ARGC:
4461                                 if (!bprm)
4462                                         goto out;
4463                                 value = bprm->argc;
4464                                 break;
4465                         case CCS_EXEC_ENVC:
4466                                 if (!bprm)
4467                                         goto out;
4468                                 value = bprm->envc;
4469                                 break;
4470                         case CCS_TASK_TYPE:
4471                                 value = ((u8) ccs_flags)
4472                                         & CCS_TASK_IS_EXECUTE_HANDLER;
4473                                 break;
4474                         case CCS_TASK_EXECUTE_HANDLER:
4475                                 value = CCS_TASK_IS_EXECUTE_HANDLER;
4476                                 break;
4477                         case CCS_NUMBER_UNION:
4478                                 /* Fetch values later. */
4479                                 break;
4480                         default:
4481                                 if (!obj)
4482                                         goto out;
4483                                 if (!obj->validate_done) {
4484                                         ccs_get_attributes(obj);
4485                                         obj->validate_done = true;
4486                                 }
4487                                 {
4488                                         u8 stat_index;
4489                                         struct ccs_mini_stat *stat;
4490                                         switch (index) {
4491                                         case CCS_PATH1_UID:
4492                                         case CCS_PATH1_GID:
4493                                         case CCS_PATH1_INO:
4494                                         case CCS_PATH1_MAJOR:
4495                                         case CCS_PATH1_MINOR:
4496                                         case CCS_PATH1_TYPE:
4497                                         case CCS_PATH1_DEV_MAJOR:
4498                                         case CCS_PATH1_DEV_MINOR:
4499                                         case CCS_PATH1_PERM:
4500                                                 stat_index = CCS_PATH1;
4501                                                 break;
4502                                         case CCS_PATH2_UID:
4503                                         case CCS_PATH2_GID:
4504                                         case CCS_PATH2_INO:
4505                                         case CCS_PATH2_MAJOR:
4506                                         case CCS_PATH2_MINOR:
4507                                         case CCS_PATH2_TYPE:
4508                                         case CCS_PATH2_DEV_MAJOR:
4509                                         case CCS_PATH2_DEV_MINOR:
4510                                         case CCS_PATH2_PERM:
4511                                                 stat_index = CCS_PATH2;
4512                                                 break;
4513                                         case CCS_PATH1_PARENT_UID:
4514                                         case CCS_PATH1_PARENT_GID:
4515                                         case CCS_PATH1_PARENT_INO:
4516                                         case CCS_PATH1_PARENT_PERM:
4517                                                 stat_index = CCS_PATH1_PARENT;
4518                                                 break;
4519                                         case CCS_PATH2_PARENT_UID:
4520                                         case CCS_PATH2_PARENT_GID:
4521                                         case CCS_PATH2_PARENT_INO:
4522                                         case CCS_PATH2_PARENT_PERM:
4523                                                 stat_index = CCS_PATH2_PARENT;
4524                                                 break;
4525                                         default:
4526                                                 goto out;
4527                                         }
4528                                         if (!obj->stat_valid[stat_index])
4529                                                 goto out;
4530                                         stat = &obj->stat[stat_index];
4531                                         switch (index) {
4532                                         case CCS_PATH1_UID:
4533                                         case CCS_PATH2_UID:
4534                                         case CCS_PATH1_PARENT_UID:
4535                                         case CCS_PATH2_PARENT_UID:
4536                                                 value = from_kuid
4537                                                         (&init_user_ns,
4538                                                          stat->uid);
4539                                                 break;
4540                                         case CCS_PATH1_GID:
4541                                         case CCS_PATH2_GID:
4542                                         case CCS_PATH1_PARENT_GID:
4543                                         case CCS_PATH2_PARENT_GID:
4544                                                 value = from_kgid
4545                                                         (&init_user_ns,
4546                                                          stat->gid);
4547                                                 break;
4548                                         case CCS_PATH1_INO:
4549                                         case CCS_PATH2_INO:
4550                                         case CCS_PATH1_PARENT_INO:
4551                                         case CCS_PATH2_PARENT_INO:
4552                                                 value = stat->ino;
4553                                                 break;
4554                                         case CCS_PATH1_MAJOR:
4555                                         case CCS_PATH2_MAJOR:
4556                                                 value = MAJOR(stat->dev);
4557                                                 break;
4558                                         case CCS_PATH1_MINOR:
4559                                         case CCS_PATH2_MINOR:
4560                                                 value = MINOR(stat->dev);
4561                                                 break;
4562                                         case CCS_PATH1_TYPE:
4563                                         case CCS_PATH2_TYPE:
4564                                                 value = stat->mode & S_IFMT;
4565                                                 break;
4566                                         case CCS_PATH1_DEV_MAJOR:
4567                                         case CCS_PATH2_DEV_MAJOR:
4568                                                 value = MAJOR(stat->rdev);
4569                                                 break;
4570                                         case CCS_PATH1_DEV_MINOR:
4571                                         case CCS_PATH2_DEV_MINOR:
4572                                                 value = MINOR(stat->rdev);
4573                                                 break;
4574                                         case CCS_PATH1_PERM:
4575                                         case CCS_PATH2_PERM:
4576                                         case CCS_PATH1_PARENT_PERM:
4577                                         case CCS_PATH2_PARENT_PERM:
4578                                                 value = stat->mode & S_IALLUGO;
4579                                                 break;
4580                                         }
4581                                 }
4582                                 break;
4583                         }
4584                         max_v[j] = value;
4585                         min_v[j] = value;
4586                         switch (index) {
4587                         case CCS_MODE_SETUID:
4588                         case CCS_MODE_SETGID:
4589                         case CCS_MODE_STICKY:
4590                         case CCS_MODE_OWNER_READ:
4591                         case CCS_MODE_OWNER_WRITE:
4592                         case CCS_MODE_OWNER_EXECUTE:
4593                         case CCS_MODE_GROUP_READ:
4594                         case CCS_MODE_GROUP_WRITE:
4595                         case CCS_MODE_GROUP_EXECUTE:
4596                         case CCS_MODE_OTHERS_READ:
4597                         case CCS_MODE_OTHERS_WRITE:
4598                         case CCS_MODE_OTHERS_EXECUTE:
4599                                 is_bitop[j] = true;
4600                         }
4601                 }
4602                 if (left == CCS_NUMBER_UNION) {
4603                         /* Fetch values now. */
4604                         const struct ccs_number_union *ptr = numbers_p++;
4605                         min_v[0] = ptr->values[0];
4606                         max_v[0] = ptr->values[1];
4607                 }
4608                 if (right == CCS_NUMBER_UNION) {
4609                         /* Fetch values now. */
4610                         const struct ccs_number_union *ptr = numbers_p++;
4611                         if (ptr->group) {
4612                                 if (ccs_number_matches_group(min_v[0],
4613                                                              max_v[0],
4614                                                              ptr->group)
4615                                     == match)
4616                                         continue;
4617                         } else {
4618                                 if ((min_v[0] <= ptr->values[1] &&
4619                                      max_v[0] >= ptr->values[0]) == match)
4620                                         continue;
4621                         }
4622                         goto out;
4623                 }
4624                 /*
4625                  * Bit operation is valid only when counterpart value
4626                  * represents permission.
4627                  */
4628                 if (is_bitop[0] && is_bitop[1]) {
4629                         goto out;
4630                 } else if (is_bitop[0]) {
4631                         switch (right) {
4632                         case CCS_PATH1_PERM:
4633                         case CCS_PATH1_PARENT_PERM:
4634                         case CCS_PATH2_PERM:
4635                         case CCS_PATH2_PARENT_PERM:
4636                                 if (!(max_v[0] & max_v[1]) == !match)
4637                                         continue;
4638                         }
4639                         goto out;
4640                 } else if (is_bitop[1]) {
4641                         switch (left) {
4642                         case CCS_PATH1_PERM:
4643                         case CCS_PATH1_PARENT_PERM:
4644                         case CCS_PATH2_PERM:
4645                         case CCS_PATH2_PARENT_PERM:
4646                                 if (!(max_v[0] & max_v[1]) == !match)
4647                                         continue;
4648                         }
4649                         goto out;
4650                 }
4651                 /* Normal value range comparison. */
4652                 if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match)
4653                         continue;
4654 out:
4655                 return false;
4656         }
4657         /* Check argv[] and envp[] now. */
4658         if (r->ee && (argc || envc))
4659                 return ccs_scan_bprm(r->ee, argc, argv, envc, envp);
4660         return true;
4661 }
4662 
4663 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
4664 
4665 /**
4666  * ccs_check_task_acl - Check permission for task operation.
4667  *
4668  * @r:   Pointer to "struct ccs_request_info".
4669  * @ptr: Pointer to "struct ccs_acl_info".
4670  *
4671  * Returns true if granted, false otherwise.
4672  */
4673 static bool ccs_check_task_acl(struct ccs_request_info *r,
4674                                const struct ccs_acl_info *ptr)
4675 {
4676         const struct ccs_task_acl *acl = container_of(ptr, typeof(*acl), head);
4677         return !ccs_pathcmp(r->param.task.domainname, acl->domainname);
4678 }
4679 
4680 #endif
4681 
4682 /**
4683  * ccs_init_request_info - Initialize "struct ccs_request_info" members.
4684  *
4685  * @r:     Pointer to "struct ccs_request_info" to initialize.
4686  * @index: Index number of functionality.
4687  *
4688  * Returns mode.
4689  *
4690  * "task auto_domain_transition" keyword is evaluated before returning mode for
4691  * @index. If "task auto_domain_transition" keyword was specified and
4692  * transition to that domain failed, the current thread will be killed by
4693  * SIGKILL. Note that if current->pid == 1, sending SIGKILL won't work.
4694  */
4695 int ccs_init_request_info(struct ccs_request_info *r, const u8 index)
4696 {
4697 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION
4698         u8 i;
4699         const char *buf;
4700         for (i = 0; i < 255; i++) {
4701                 const u8 profile = ccs_current_domain()->profile;
4702                 memset(r, 0, sizeof(*r));
4703                 r->profile = profile;
4704                 r->type = index;
4705                 r->mode = ccs_get_mode(profile, index);
4706                 r->param_type = CCS_TYPE_AUTO_TASK_ACL;
4707                 ccs_check_acl(r);
4708                 if (!r->granted)
4709                         return r->mode;
4710                 buf = container_of(r->matched_acl, typeof(struct ccs_task_acl),
4711                                    head)->domainname->name;
4712                 if (!ccs_assign_domain(buf, true))
4713                         break;
4714         }
4715         ccs_transition_failed(buf);
4716         return CCS_CONFIG_DISABLED;
4717 #else
4718         const u8 profile = ccs_current_domain()->profile;
4719         memset(r, 0, sizeof(*r));
4720         r->profile = profile;
4721         r->type = index;
4722         r->mode = ccs_get_mode(profile, index);
4723         return r->mode;
4724 #endif
4725 }
4726 
4727 /**
4728  * ccs_byte_range - Check whether the string is a \ooo style octal value.
4729  *
4730  * @str: Pointer to the string.
4731  *
4732  * Returns true if @str is a \ooo style octal value, false otherwise.
4733  */
4734 static bool ccs_byte_range(const char *str)
4735 {
4736         return *str >= '' && *str++ <= '3' &&
4737                 *str >= '' && *str++ <= '7' &&
4738                 *str >= '' && *str <= '7';
4739 }
4740 
4741 /**
4742  * ccs_decimal - Check whether the character is a decimal character.
4743  *
4744  * @c: The character to check.
4745  *
4746  * Returns true if @c is a decimal character, false otherwise.
4747  */
4748 static bool ccs_decimal(const char c)
4749 {
4750         return c >= '' && c <= '9';
4751 }
4752 
4753 /**
4754  * ccs_hexadecimal - Check whether the character is a hexadecimal character.
4755  *
4756  * @c: The character to check.
4757  *
4758  * Returns true if @c is a hexadecimal character, false otherwise.
4759  */
4760 static bool ccs_hexadecimal(const char c)
4761 {
4762         return (c >= '' && c <= '9') ||
4763                 (c >= 'A' && c <= 'F') ||
4764                 (c >= 'a' && c <= 'f');
4765 }
4766 
4767 /**
4768  * ccs_alphabet_char - Check whether the character is an alphabet.
4769  *
4770  * @c: The character to check.
4771  *
4772  * Returns true if @c is an alphabet character, false otherwise.
4773  */
4774 static bool ccs_alphabet_char(const char c)
4775 {
4776         return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
4777 }
4778 
4779 /**
4780  * ccs_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
4781  *
4782  * @filename:     The start of string to check.
4783  * @filename_end: The end of string to check.
4784  * @pattern:      The start of pattern to compare.
4785  * @pattern_end:  The end of pattern to compare.
4786  *
4787  * Returns true if @filename matches @pattern, false otherwise.
4788  */
4789 static bool ccs_file_matches_pattern2(const char *filename,
4790                                       const char *filename_end,
4791                                       const char *pattern,
4792                                       const char *pattern_end)
4793 {
4794         while (filename < filename_end && pattern < pattern_end) {
4795                 char c;
4796                 if (*pattern != '\\') {
4797                         if (*filename++ != *pattern++)
4798                                 return false;
4799                         continue;
4800                 }
4801                 c = *filename;
4802                 pattern++;
4803                 switch (*pattern) {
4804                         int i;
4805                         int j;
4806                 case '?':
4807                         if (c == '/') {
4808                                 return false;
4809                         } else if (c == '\\') {
4810                                 if (filename[1] == '\\')
4811                                         filename++;
4812                                 else if (ccs_byte_range(filename + 1))
4813                                         filename += 3;
4814                                 else
4815                                         return false;
4816                         }
4817                         break;
4818                 case '\\':
4819                         if (c != '\\')
4820                                 return false;
4821                         if (*++filename != '\\')
4822                                 return false;
4823                         break;
4824                 case '+':
4825                         if (!ccs_decimal(c))
4826                                 return false;
4827                         break;
4828                 case 'x':
4829                         if (!ccs_hexadecimal(c))
4830                                 return false;
4831                         break;
4832                 case 'a':
4833                         if (!ccs_alphabet_char(c))
4834                                 return false;
4835                         break;
4836                 case '':
4837                 case '1':
4838                 case '2':
4839                 case '3':
4840                         if (c == '\\' && ccs_byte_range(filename + 1)
4841                             && !strncmp(filename + 1, pattern, 3)) {
4842                                 filename += 3;
4843                                 pattern += 2;
4844                                 break;
4845                         }
4846                         return false; /* Not matched. */
4847                 case '*':
4848                 case '@':
4849                         for (i = 0; i <= filename_end - filename; i++) {
4850                                 if (ccs_file_matches_pattern2(filename + i,
4851                                                               filename_end,
4852                                                               pattern + 1,
4853                                                               pattern_end))
4854                                         return true;
4855                                 c = filename[i];
4856                                 if (c == '.' && *pattern == '@')
4857                                         break;
4858                                 if (c != '\\')
4859                                         continue;
4860                                 if (filename[i + 1] == '\\')
4861                                         i++;
4862                                 else if (ccs_byte_range(filename + i + 1))
4863                                         i += 3;
4864                                 else
4865                                         break; /* Bad pattern. */
4866                         }
4867                         return false; /* Not matched. */
4868                 default:
4869                         j = 0;
4870                         c = *pattern;
4871                         if (c == '$') {
4872                                 while (ccs_decimal(filename[j]))
4873                                         j++;
4874                         } else if (c == 'X') {
4875                                 while (ccs_hexadecimal(filename[j]))
4876                                         j++;
4877                         } else if (c == 'A') {
4878                                 while (ccs_alphabet_char(filename[j]))
4879                                         j++;
4880                         }
4881                         for (i = 1; i <= j; i++) {
4882                                 if (ccs_file_matches_pattern2(filename + i,
4883                                                               filename_end,
4884                                                               pattern + 1,
4885                                                               pattern_end))
4886                                         return true;
4887                         }
4888                         return false; /* Not matched or bad pattern. */
4889                 }
4890                 filename++;
4891                 pattern++;
4892         }
4893         while (*pattern == '\\' &&
4894                (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
4895                 pattern += 2;
4896         return filename == filename_end && pattern == pattern_end;
4897 }
4898 
4899 /**
4900  * ccs_file_matches_pattern - Pattern matching without '/' character.
4901  *
4902  * @filename:     The start of string to check.
4903  * @filename_end: The end of string to check.
4904  * @pattern:      The start of pattern to compare.
4905  * @pattern_end:  The end of pattern to compare.
4906  *
4907  * Returns true if @filename matches @pattern, false otherwise.
4908  */
4909 static bool ccs_file_matches_pattern(const char *filename,
4910                                      const char *filename_end,
4911                                      const char *pattern,
4912                                      const char *pattern_end)
4913 {
4914         const char *pattern_start = pattern;
4915         bool first = true;
4916         bool result;
4917         while (pattern < pattern_end - 1) {
4918                 /* Split at "\-" pattern. */
4919                 if (*pattern++ != '\\' || *pattern++ != '-')
4920                         continue;
4921                 result = ccs_file_matches_pattern2(filename, filename_end,
4922                                                    pattern_start, pattern - 2);
4923                 if (first)
4924                         result = !result;
4925                 if (result)
4926                         return false;
4927                 first = false;
4928                 pattern_start = pattern;
4929         }
4930         result = ccs_file_matches_pattern2(filename, filename_end,
4931                                            pattern_start, pattern_end);
4932         return first ? result : !result;
4933 }
4934 
4935 /**
4936  * ccs_path_matches_pattern2 - Do pathname pattern matching.
4937  *
4938  * @f: The start of string to check.
4939  * @p: The start of pattern to compare.
4940  *
4941  * Returns true if @f matches @p, false otherwise.
4942  */
4943 static bool ccs_path_matches_pattern2(const char *f, const char *p)
4944 {
4945         const char *f_delimiter;
4946         const char *p_delimiter;
4947         while (*f && *p) {
4948                 f_delimiter = strchr(f, '/');
4949                 if (!f_delimiter)
4950                         f_delimiter = f + strlen(f);
4951                 p_delimiter = strchr(p, '/');
4952                 if (!p_delimiter)
4953                         p_delimiter = p + strlen(p);
4954                 if (*p == '\\' && *(p + 1) == '{')
4955                         goto recursive;
4956                 if (!ccs_file_matches_pattern(f, f_delimiter, p, p_delimiter))
4957                         return false;
4958                 f = f_delimiter;
4959                 if (*f)
4960                         f++;
4961                 p = p_delimiter;
4962                 if (*p)
4963                         p++;
4964         }
4965         /* Ignore trailing "\*" and "\@" in @pattern. */
4966         while (*p == '\\' &&
4967                (*(p + 1) == '*' || *(p + 1) == '@'))
4968                 p += 2;
4969         return !*f && !*p;
4970 recursive:
4971         /*
4972          * The "\{" pattern is permitted only after '/' character.
4973          * This guarantees that below "*(p - 1)" is safe.
4974          * Also, the "\}" pattern is permitted only before '/' character
4975          * so that "\{" + "\}" pair will not break the "\-" operator.
4976          */
4977         if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
4978             *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
4979                 return false; /* Bad pattern. */
4980         do {
4981                 /* Compare current component with pattern. */
4982                 if (!ccs_file_matches_pattern(f, f_delimiter, p + 2,
4983                                               p_delimiter - 2))
4984                         break;
4985                 /* Proceed to next component. */
4986                 f = f_delimiter;
4987                 if (!*f)
4988                         break;
4989                 f++;
4990                 /* Continue comparison. */
4991                 if (ccs_path_matches_pattern2(f, p_delimiter + 1))
4992                         return true;
4993                 f_delimiter = strchr(f, '/');
4994         } while (f_delimiter);
4995         return false; /* Not matched. */
4996 }
4997 
4998 /**
4999  * ccs_path_matches_pattern - Check whether the given filename matches the given pattern.
5000  *
5001  * @filename: The filename to check.
5002  * @pattern:  The pattern to compare.
5003  *
5004  * Returns true if matches, false otherwise.
5005  *
5006  * The following patterns are available.
5007  *   \\     \ itself.
5008  *   \ooo   Octal representation of a byte.
5009  *   \*     Zero or more repetitions of characters other than '/'.
5010  *   \@     Zero or more repetitions of characters other than '/' or '.'.
5011  *   \?     1 byte character other than '/'.
5012  *   \$     One or more repetitions of decimal digits.
5013  *   \+     1 decimal digit.
5014  *   \X     One or more repetitions of hexadecimal digits.
5015  *   \x     1 hexadecimal digit.
5016  *   \A     One or more repetitions of alphabet characters.
5017  *   \a     1 alphabet character.
5018  *
5019  *   \-     Subtraction operator.
5020  *
5021  *   /\{dir\}/   '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
5022  *               /dir/dir/dir/ ).
5023  */
5024 static bool ccs_path_matches_pattern(const struct ccs_path_info *filename,
5025                                      const struct ccs_path_info *pattern)
5026 {
5027         const char *f = filename->name;
5028         const char *p = pattern->name;
5029         const int len = pattern->const_len;
5030         /* If @pattern doesn't contain pattern, I can use strcmp(). */
5031         if (!pattern->is_patterned)
5032                 return !ccs_pathcmp(filename, pattern);
5033         /* Don't compare directory and non-directory. */
5034         if (filename->is_dir != pattern->is_dir)
5035                 return false;
5036         /* Compare the initial length without patterns. */
5037         if (strncmp(f, p, len))
5038                 return false;
5039         f += len;
5040         p += len;
5041         return ccs_path_matches_pattern2(f, p);
5042 }
5043 

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