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