1 /* 2 * security/ccsecurity/policy_io.c 3 * 4 * Copyright (C) 2005-2012 NTT DATA CORPORATION 5 * 6 * Version: 1.8.6+ 2020/04/13 7 */ 8 9 #include "internal.h" 10 11 /***** SECTION1: Constants definition *****/ 12 13 /* Define this to enable debug mode. */ 14 /* #define DEBUG_CONDITION */ 15 16 #ifdef DEBUG_CONDITION 17 #define dprintk printk 18 #else 19 #define dprintk(...) do { } while (0) 20 #endif 21 22 /* Mapping table from "enum ccs_mac_index" to "enum ccs_mac_category_index". */ 23 static const u8 ccs_index2category[CCS_MAX_MAC_INDEX] = { 24 /* CONFIG::file group */ 25 [CCS_MAC_FILE_EXECUTE] = CCS_MAC_CATEGORY_FILE, 26 [CCS_MAC_FILE_OPEN] = CCS_MAC_CATEGORY_FILE, 27 [CCS_MAC_FILE_CREATE] = CCS_MAC_CATEGORY_FILE, 28 [CCS_MAC_FILE_UNLINK] = CCS_MAC_CATEGORY_FILE, 29 #ifdef CONFIG_CCSECURITY_FILE_GETATTR 30 [CCS_MAC_FILE_GETATTR] = CCS_MAC_CATEGORY_FILE, 31 #endif 32 [CCS_MAC_FILE_MKDIR] = CCS_MAC_CATEGORY_FILE, 33 [CCS_MAC_FILE_RMDIR] = CCS_MAC_CATEGORY_FILE, 34 [CCS_MAC_FILE_MKFIFO] = CCS_MAC_CATEGORY_FILE, 35 [CCS_MAC_FILE_MKSOCK] = CCS_MAC_CATEGORY_FILE, 36 [CCS_MAC_FILE_TRUNCATE] = CCS_MAC_CATEGORY_FILE, 37 [CCS_MAC_FILE_SYMLINK] = CCS_MAC_CATEGORY_FILE, 38 [CCS_MAC_FILE_MKBLOCK] = CCS_MAC_CATEGORY_FILE, 39 [CCS_MAC_FILE_MKCHAR] = CCS_MAC_CATEGORY_FILE, 40 [CCS_MAC_FILE_LINK] = CCS_MAC_CATEGORY_FILE, 41 [CCS_MAC_FILE_RENAME] = CCS_MAC_CATEGORY_FILE, 42 [CCS_MAC_FILE_CHMOD] = CCS_MAC_CATEGORY_FILE, 43 [CCS_MAC_FILE_CHOWN] = CCS_MAC_CATEGORY_FILE, 44 [CCS_MAC_FILE_CHGRP] = CCS_MAC_CATEGORY_FILE, 45 [CCS_MAC_FILE_IOCTL] = CCS_MAC_CATEGORY_FILE, 46 [CCS_MAC_FILE_CHROOT] = CCS_MAC_CATEGORY_FILE, 47 [CCS_MAC_FILE_MOUNT] = CCS_MAC_CATEGORY_FILE, 48 [CCS_MAC_FILE_UMOUNT] = CCS_MAC_CATEGORY_FILE, 49 [CCS_MAC_FILE_PIVOT_ROOT] = CCS_MAC_CATEGORY_FILE, 50 #ifdef CONFIG_CCSECURITY_MISC 51 /* CONFIG::misc group */ 52 [CCS_MAC_ENVIRON] = CCS_MAC_CATEGORY_MISC, 53 #endif 54 #ifdef CONFIG_CCSECURITY_NETWORK 55 /* CONFIG::network group */ 56 [CCS_MAC_NETWORK_INET_STREAM_BIND] = CCS_MAC_CATEGORY_NETWORK, 57 [CCS_MAC_NETWORK_INET_STREAM_LISTEN] = CCS_MAC_CATEGORY_NETWORK, 58 [CCS_MAC_NETWORK_INET_STREAM_CONNECT] = CCS_MAC_CATEGORY_NETWORK, 59 [CCS_MAC_NETWORK_INET_STREAM_ACCEPT] = CCS_MAC_CATEGORY_NETWORK, 60 [CCS_MAC_NETWORK_INET_DGRAM_BIND] = CCS_MAC_CATEGORY_NETWORK, 61 [CCS_MAC_NETWORK_INET_DGRAM_SEND] = CCS_MAC_CATEGORY_NETWORK, 62 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG 63 [CCS_MAC_NETWORK_INET_DGRAM_RECV] = CCS_MAC_CATEGORY_NETWORK, 64 #endif 65 [CCS_MAC_NETWORK_INET_RAW_BIND] = CCS_MAC_CATEGORY_NETWORK, 66 [CCS_MAC_NETWORK_INET_RAW_SEND] = CCS_MAC_CATEGORY_NETWORK, 67 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG 68 [CCS_MAC_NETWORK_INET_RAW_RECV] = CCS_MAC_CATEGORY_NETWORK, 69 #endif 70 [CCS_MAC_NETWORK_UNIX_STREAM_BIND] = CCS_MAC_CATEGORY_NETWORK, 71 [CCS_MAC_NETWORK_UNIX_STREAM_LISTEN] = CCS_MAC_CATEGORY_NETWORK, 72 [CCS_MAC_NETWORK_UNIX_STREAM_CONNECT] = CCS_MAC_CATEGORY_NETWORK, 73 [CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT] = CCS_MAC_CATEGORY_NETWORK, 74 [CCS_MAC_NETWORK_UNIX_DGRAM_BIND] = CCS_MAC_CATEGORY_NETWORK, 75 [CCS_MAC_NETWORK_UNIX_DGRAM_SEND] = CCS_MAC_CATEGORY_NETWORK, 76 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG 77 [CCS_MAC_NETWORK_UNIX_DGRAM_RECV] = CCS_MAC_CATEGORY_NETWORK, 78 #endif 79 [CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND] = CCS_MAC_CATEGORY_NETWORK, 80 [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = CCS_MAC_CATEGORY_NETWORK, 81 [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = CCS_MAC_CATEGORY_NETWORK, 82 [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT] = CCS_MAC_CATEGORY_NETWORK, 83 #endif 84 #ifdef CONFIG_CCSECURITY_IPC 85 /* CONFIG::ipc group */ 86 [CCS_MAC_SIGNAL] = CCS_MAC_CATEGORY_IPC, 87 #endif 88 #ifdef CONFIG_CCSECURITY_CAPABILITY 89 /* CONFIG::capability group */ 90 [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET] = CCS_MAC_CATEGORY_CAPABILITY, 91 [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = CCS_MAC_CATEGORY_CAPABILITY, 92 [CCS_MAC_CAPABILITY_SYS_REBOOT] = CCS_MAC_CATEGORY_CAPABILITY, 93 [CCS_MAC_CAPABILITY_SYS_VHANGUP] = CCS_MAC_CATEGORY_CAPABILITY, 94 [CCS_MAC_CAPABILITY_SYS_SETTIME] = CCS_MAC_CATEGORY_CAPABILITY, 95 [CCS_MAC_CAPABILITY_SYS_NICE] = CCS_MAC_CATEGORY_CAPABILITY, 96 [CCS_MAC_CAPABILITY_SYS_SETHOSTNAME] = CCS_MAC_CATEGORY_CAPABILITY, 97 [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = CCS_MAC_CATEGORY_CAPABILITY, 98 [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD] = CCS_MAC_CATEGORY_CAPABILITY, 99 [CCS_MAC_CAPABILITY_SYS_PTRACE] = CCS_MAC_CATEGORY_CAPABILITY, 100 #endif 101 }; 102 103 /* String table for operation mode. */ 104 static const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = { 105 [CCS_CONFIG_DISABLED] = "disabled", 106 [CCS_CONFIG_LEARNING] = "learning", 107 [CCS_CONFIG_PERMISSIVE] = "permissive", 108 [CCS_CONFIG_ENFORCING] = "enforcing" 109 }; 110 111 /* String table for /proc/ccs/profile interface. */ 112 static const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX 113 + CCS_MAX_MAC_CATEGORY_INDEX] = { 114 /* CONFIG::file group */ 115 [CCS_MAC_FILE_EXECUTE] = "execute", 116 [CCS_MAC_FILE_OPEN] = "open", 117 [CCS_MAC_FILE_CREATE] = "create", 118 [CCS_MAC_FILE_UNLINK] = "unlink", 119 #ifdef CONFIG_CCSECURITY_FILE_GETATTR 120 [CCS_MAC_FILE_GETATTR] = "getattr", 121 #endif 122 [CCS_MAC_FILE_MKDIR] = "mkdir", 123 [CCS_MAC_FILE_RMDIR] = "rmdir", 124 [CCS_MAC_FILE_MKFIFO] = "mkfifo", 125 [CCS_MAC_FILE_MKSOCK] = "mksock", 126 [CCS_MAC_FILE_TRUNCATE] = "truncate", 127 [CCS_MAC_FILE_SYMLINK] = "symlink", 128 [CCS_MAC_FILE_MKBLOCK] = "mkblock", 129 [CCS_MAC_FILE_MKCHAR] = "mkchar", 130 [CCS_MAC_FILE_LINK] = "link", 131 [CCS_MAC_FILE_RENAME] = "rename", 132 [CCS_MAC_FILE_CHMOD] = "chmod", 133 [CCS_MAC_FILE_CHOWN] = "chown", 134 [CCS_MAC_FILE_CHGRP] = "chgrp", 135 [CCS_MAC_FILE_IOCTL] = "ioctl", 136 [CCS_MAC_FILE_CHROOT] = "chroot", 137 [CCS_MAC_FILE_MOUNT] = "mount", 138 [CCS_MAC_FILE_UMOUNT] = "unmount", 139 [CCS_MAC_FILE_PIVOT_ROOT] = "pivot_root", 140 #ifdef CONFIG_CCSECURITY_MISC 141 /* CONFIG::misc group */ 142 [CCS_MAC_ENVIRON] = "env", 143 #endif 144 #ifdef CONFIG_CCSECURITY_NETWORK 145 /* CONFIG::network group */ 146 [CCS_MAC_NETWORK_INET_STREAM_BIND] = "inet_stream_bind", 147 [CCS_MAC_NETWORK_INET_STREAM_LISTEN] = "inet_stream_listen", 148 [CCS_MAC_NETWORK_INET_STREAM_CONNECT] = "inet_stream_connect", 149 [CCS_MAC_NETWORK_INET_STREAM_ACCEPT] = "inet_stream_accept", 150 [CCS_MAC_NETWORK_INET_DGRAM_BIND] = "inet_dgram_bind", 151 [CCS_MAC_NETWORK_INET_DGRAM_SEND] = "inet_dgram_send", 152 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG 153 [CCS_MAC_NETWORK_INET_DGRAM_RECV] = "inet_dgram_recv", 154 #endif 155 [CCS_MAC_NETWORK_INET_RAW_BIND] = "inet_raw_bind", 156 [CCS_MAC_NETWORK_INET_RAW_SEND] = "inet_raw_send", 157 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG 158 [CCS_MAC_NETWORK_INET_RAW_RECV] = "inet_raw_recv", 159 #endif 160 [CCS_MAC_NETWORK_UNIX_STREAM_BIND] = "unix_stream_bind", 161 [CCS_MAC_NETWORK_UNIX_STREAM_LISTEN] = "unix_stream_listen", 162 [CCS_MAC_NETWORK_UNIX_STREAM_CONNECT] = "unix_stream_connect", 163 [CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT] = "unix_stream_accept", 164 [CCS_MAC_NETWORK_UNIX_DGRAM_BIND] = "unix_dgram_bind", 165 [CCS_MAC_NETWORK_UNIX_DGRAM_SEND] = "unix_dgram_send", 166 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG 167 [CCS_MAC_NETWORK_UNIX_DGRAM_RECV] = "unix_dgram_recv", 168 #endif 169 [CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND] = "unix_seqpacket_bind", 170 [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = "unix_seqpacket_listen", 171 [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect", 172 [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT] = "unix_seqpacket_accept", 173 #endif 174 #ifdef CONFIG_CCSECURITY_IPC 175 /* CONFIG::ipc group */ 176 [CCS_MAC_SIGNAL] = "signal", 177 #endif 178 #ifdef CONFIG_CCSECURITY_CAPABILITY 179 /* CONFIG::capability group */ 180 [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET] = "use_route", 181 [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = "use_packet", 182 [CCS_MAC_CAPABILITY_SYS_REBOOT] = "SYS_REBOOT", 183 [CCS_MAC_CAPABILITY_SYS_VHANGUP] = "SYS_VHANGUP", 184 [CCS_MAC_CAPABILITY_SYS_SETTIME] = "SYS_TIME", 185 [CCS_MAC_CAPABILITY_SYS_NICE] = "SYS_NICE", 186 [CCS_MAC_CAPABILITY_SYS_SETHOSTNAME] = "SYS_SETHOSTNAME", 187 [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = "use_kernel_module", 188 [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD] = "SYS_KEXEC_LOAD", 189 [CCS_MAC_CAPABILITY_SYS_PTRACE] = "SYS_PTRACE", 190 #endif 191 /* CONFIG group */ 192 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_FILE] = "file", 193 #ifdef CONFIG_CCSECURITY_NETWORK 194 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_NETWORK] = "network", 195 #endif 196 #ifdef CONFIG_CCSECURITY_MISC 197 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_MISC] = "misc", 198 #endif 199 #ifdef CONFIG_CCSECURITY_IPC 200 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_IPC] = "ipc", 201 #endif 202 #ifdef CONFIG_CCSECURITY_CAPABILITY 203 [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_CAPABILITY] = "capability", 204 #endif 205 }; 206 207 /* String table for path operation. */ 208 static const char * const ccs_path_keyword[CCS_MAX_PATH_OPERATION] = { 209 [CCS_TYPE_EXECUTE] = "execute", 210 [CCS_TYPE_READ] = "read", 211 [CCS_TYPE_WRITE] = "write", 212 [CCS_TYPE_APPEND] = "append", 213 [CCS_TYPE_UNLINK] = "unlink", 214 #ifdef CONFIG_CCSECURITY_FILE_GETATTR 215 [CCS_TYPE_GETATTR] = "getattr", 216 #endif 217 [CCS_TYPE_RMDIR] = "rmdir", 218 [CCS_TYPE_TRUNCATE] = "truncate", 219 [CCS_TYPE_SYMLINK] = "symlink", 220 [CCS_TYPE_CHROOT] = "chroot", 221 [CCS_TYPE_UMOUNT] = "unmount", 222 }; 223 224 #ifdef CONFIG_CCSECURITY_NETWORK 225 226 /* String table for socket's operation. */ 227 static const char * const ccs_socket_keyword[CCS_MAX_NETWORK_OPERATION] = { 228 [CCS_NETWORK_BIND] = "bind", 229 [CCS_NETWORK_LISTEN] = "listen", 230 [CCS_NETWORK_CONNECT] = "connect", 231 [CCS_NETWORK_ACCEPT] = "accept", 232 [CCS_NETWORK_SEND] = "send", 233 #ifdef CONFIG_CCSECURITY_NETWORK_RECVMSG 234 [CCS_NETWORK_RECV] = "recv", 235 #endif 236 }; 237 238 /* String table for socket's protocols. */ 239 static const char * const ccs_proto_keyword[CCS_SOCK_MAX] = { 240 [SOCK_STREAM] = "stream", 241 [SOCK_DGRAM] = "dgram", 242 [SOCK_RAW] = "raw", 243 [SOCK_SEQPACKET] = "seqpacket", 244 [0] = " ", /* Dummy for avoiding NULL pointer dereference. */ 245 [4] = " ", /* Dummy for avoiding NULL pointer dereference. */ 246 }; 247 248 #endif 249 250 /* String table for categories. */ 251 static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = { 252 [CCS_MAC_CATEGORY_FILE] = "file", 253 #ifdef CONFIG_CCSECURITY_NETWORK 254 [CCS_MAC_CATEGORY_NETWORK] = "network", 255 #endif 256 #ifdef CONFIG_CCSECURITY_MISC 257 [CCS_MAC_CATEGORY_MISC] = "misc", 258 #endif 259 #ifdef CONFIG_CCSECURITY_IPC 260 [CCS_MAC_CATEGORY_IPC] = "ipc", 261 #endif 262 #ifdef CONFIG_CCSECURITY_CAPABILITY 263 [CCS_MAC_CATEGORY_CAPABILITY] = "capability", 264 #endif 265 }; 266 267 /* String table for conditions. */ 268 static const char * const ccs_condition_keyword[CCS_MAX_CONDITION_KEYWORD] = { 269 [CCS_TASK_UID] = "task.uid", 270 [CCS_TASK_EUID] = "task.euid", 271 [CCS_TASK_SUID] = "task.suid", 272 [CCS_TASK_FSUID] = "task.fsuid", 273 [CCS_TASK_GID] = "task.gid", 274 [CCS_TASK_EGID] = "task.egid", 275 [CCS_TASK_SGID] = "task.sgid", 276 [CCS_TASK_FSGID] = "task.fsgid", 277 [CCS_TASK_PID] = "task.pid", 278 [CCS_TASK_PPID] = "task.ppid", 279 [CCS_EXEC_ARGC] = "exec.argc", 280 [CCS_EXEC_ENVC] = "exec.envc", 281 [CCS_TYPE_IS_SOCKET] = "socket", 282 [CCS_TYPE_IS_SYMLINK] = "symlink", 283 [CCS_TYPE_IS_FILE] = "file", 284 [CCS_TYPE_IS_BLOCK_DEV] = "block", 285 [CCS_TYPE_IS_DIRECTORY] = "directory", 286 [CCS_TYPE_IS_CHAR_DEV] = "char", 287 [CCS_TYPE_IS_FIFO] = "fifo", 288 [CCS_MODE_SETUID] = "setuid", 289 [CCS_MODE_SETGID] = "setgid", 290 [CCS_MODE_STICKY] = "sticky", 291 [CCS_MODE_OWNER_READ] = "owner_read", 292 [CCS_MODE_OWNER_WRITE] = "owner_write", 293 [CCS_MODE_OWNER_EXECUTE] = "owner_execute", 294 [CCS_MODE_GROUP_READ] = "group_read", 295 [CCS_MODE_GROUP_WRITE] = "group_write", 296 [CCS_MODE_GROUP_EXECUTE] = "group_execute", 297 [CCS_MODE_OTHERS_READ] = "others_read", 298 [CCS_MODE_OTHERS_WRITE] = "others_write", 299 [CCS_MODE_OTHERS_EXECUTE] = "others_execute", 300 [CCS_TASK_TYPE] = "task.type", 301 [CCS_TASK_EXECUTE_HANDLER] = "execute_handler", 302 [CCS_EXEC_REALPATH] = "exec.realpath", 303 [CCS_SYMLINK_TARGET] = "symlink.target", 304 [CCS_PATH1_UID] = "path1.uid", 305 [CCS_PATH1_GID] = "path1.gid", 306 [CCS_PATH1_INO] = "path1.ino", 307 [CCS_PATH1_MAJOR] = "path1.major", 308 [CCS_PATH1_MINOR] = "path1.minor", 309 [CCS_PATH1_PERM] = "path1.perm", 310 [CCS_PATH1_TYPE] = "path1.type", 311 [CCS_PATH1_DEV_MAJOR] = "path1.dev_major", 312 [CCS_PATH1_DEV_MINOR] = "path1.dev_minor", 313 [CCS_PATH2_UID] = "path2.uid", 314 [CCS_PATH2_GID] = "path2.gid", 315 [CCS_PATH2_INO] = "path2.ino", 316 [CCS_PATH2_MAJOR] = "path2.major", 317 [CCS_PATH2_MINOR] = "path2.minor", 318 [CCS_PATH2_PERM] = "path2.perm", 319 [CCS_PATH2_TYPE] = "path2.type", 320 [CCS_PATH2_DEV_MAJOR] = "path2.dev_major", 321 [CCS_PATH2_DEV_MINOR] = "path2.dev_minor", 322 [CCS_PATH1_PARENT_UID] = "path1.parent.uid", 323 [CCS_PATH1_PARENT_GID] = "path1.parent.gid", 324 [CCS_PATH1_PARENT_INO] = "path1.parent.ino", 325 [CCS_PATH1_PARENT_PERM] = "path1.parent.perm", 326 [CCS_PATH2_PARENT_UID] = "path2.parent.uid", 327 [CCS_PATH2_PARENT_GID] = "path2.parent.gid", 328 [CCS_PATH2_PARENT_INO] = "path2.parent.ino", 329 [CCS_PATH2_PARENT_PERM] = "path2.parent.perm", 330 }; 331 332 /* String table for PREFERENCE keyword. */ 333 static const char * const ccs_pref_keywords[CCS_MAX_PREF] = { 334 [CCS_PREF_MAX_AUDIT_LOG] = "max_audit_log", 335 [CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry", 336 [CCS_PREF_ENFORCING_PENALTY] = "enforcing_penalty", 337 }; 338 339 /* String table for domain flags. */ 340 const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = { 341 [CCS_DIF_QUOTA_WARNED] = "quota_exceeded\n", 342 [CCS_DIF_TRANSITION_FAILED] = "transition_failed\n", 343 }; 344 345 /* String table for domain transition control keywords. */ 346 static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = { 347 [CCS_TRANSITION_CONTROL_NO_RESET] = "no_reset_domain ", 348 [CCS_TRANSITION_CONTROL_RESET] = "reset_domain ", 349 [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ", 350 [CCS_TRANSITION_CONTROL_INITIALIZE] = "initialize_domain ", 351 [CCS_TRANSITION_CONTROL_NO_KEEP] = "no_keep_domain ", 352 [CCS_TRANSITION_CONTROL_KEEP] = "keep_domain ", 353 }; 354 355 /* String table for grouping keywords. */ 356 static const char * const ccs_group_name[CCS_MAX_GROUP] = { 357 [CCS_PATH_GROUP] = "path_group ", 358 [CCS_NUMBER_GROUP] = "number_group ", 359 #ifdef CONFIG_CCSECURITY_NETWORK 360 [CCS_ADDRESS_GROUP] = "address_group ", 361 #endif 362 }; 363 364 /* String table for /proc/ccs/stat interface. */ 365 static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = { 366 [CCS_STAT_POLICY_UPDATES] = "update:", 367 [CCS_STAT_POLICY_LEARNING] = "violation in learning mode:", 368 [CCS_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:", 369 [CCS_STAT_POLICY_ENFORCING] = "violation in enforcing mode:", 370 }; 371 372 /* String table for /proc/ccs/stat interface. */ 373 static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = { 374 [CCS_MEMORY_POLICY] = "policy:", 375 [CCS_MEMORY_AUDIT] = "audit log:", 376 [CCS_MEMORY_QUERY] = "query message:", 377 }; 378 379 /***** SECTION2: Structure definition *****/ 380 381 struct iattr; 382 383 /* Structure for query. */ 384 struct ccs_query { 385 struct list_head list; 386 struct ccs_domain_info *domain; 387 char *query; 388 size_t query_len; 389 unsigned int serial; 390 u8 timer; 391 u8 answer; 392 u8 retry; 393 }; 394 395 /* Structure for audit log. */ 396 struct ccs_log { 397 struct list_head list; 398 char *log; 399 int size; 400 }; 401 402 /***** SECTION3: Prototype definition section *****/ 403 404 int ccs_audit_log(struct ccs_request_info *r); 405 struct ccs_domain_info *ccs_assign_domain(const char *domainname, 406 const bool transit); 407 u8 ccs_get_config(const u8 profile, const u8 index); 408 void ccs_transition_failed(const char *domainname); 409 void ccs_write_log(struct ccs_request_info *r, const char *fmt, ...); 410 411 static bool ccs_correct_domain(const unsigned char *domainname); 412 static bool ccs_correct_path(const char *filename); 413 static bool ccs_correct_word(const char *string); 414 static bool ccs_correct_word2(const char *string, size_t len); 415 static bool ccs_domain_def(const unsigned char *buffer); 416 static bool ccs_domain_quota_ok(struct ccs_request_info *r); 417 static bool ccs_flush(struct ccs_io_buffer *head); 418 static bool ccs_get_audit(const struct ccs_request_info *r); 419 static bool ccs_has_more_namespace(struct ccs_io_buffer *head); 420 static bool ccs_manager(void); 421 static bool ccs_namespace_jump(const char *domainname); 422 static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv); 423 static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp); 424 static bool ccs_parse_name_union(struct ccs_acl_param *param, 425 struct ccs_name_union *ptr); 426 static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param, 427 struct ccs_name_union *ptr); 428 static bool ccs_parse_number_union(struct ccs_acl_param *param, 429 struct ccs_number_union *ptr); 430 static bool ccs_permstr(const char *string, const char *keyword); 431 static bool ccs_print_condition(struct ccs_io_buffer *head, 432 const struct ccs_condition *cond); 433 static bool ccs_print_entry(struct ccs_io_buffer *head, 434 const struct ccs_acl_info *acl); 435 static bool ccs_print_group(struct ccs_io_buffer *head, 436 const struct ccs_group *group); 437 static bool ccs_read_acl(struct ccs_io_buffer *head, struct list_head *list); 438 static bool ccs_read_group(struct ccs_io_buffer *head, const int idx); 439 static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx); 440 static bool ccs_same_condition(const struct ccs_condition *a, 441 const struct ccs_condition *b); 442 static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data); 443 static bool ccs_set_lf(struct ccs_io_buffer *head); 444 static bool ccs_str_starts(char **src, const char *find); 445 static char *ccs_get_transit_preference(struct ccs_acl_param *param, 446 struct ccs_condition *e); 447 static char *ccs_init_log(struct ccs_request_info *r, int len, const char *fmt, 448 va_list args); 449 static char *ccs_print_bprm(struct linux_binprm *bprm, 450 struct ccs_page_dump *dump); 451 static char *ccs_print_header(struct ccs_request_info *r); 452 static char *ccs_read_token(struct ccs_acl_param *param); 453 static const char *ccs_yesno(const unsigned int value); 454 static const struct ccs_path_info *ccs_get_domainname 455 (struct ccs_acl_param *param); 456 static const struct ccs_path_info *ccs_get_dqword(char *start); 457 static int __init ccs_init_module(void); 458 static int ccs_delete_domain(char *domainname); 459 static int ccs_open(struct inode *inode, struct file *file); 460 static int ccs_parse_policy(struct ccs_io_buffer *head, char *line); 461 static int ccs_release(struct inode *inode, struct file *file); 462 static int ccs_set_mode(char *name, const char *value, 463 struct ccs_profile *profile); 464 static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...) 465 __printf(2, 3); 466 static int ccs_truncate(char *str); 467 static int ccs_update_acl(const int size, struct ccs_acl_param *param); 468 static int ccs_update_manager_entry(const char *manager, const bool is_delete); 469 static int ccs_update_policy(const int size, struct ccs_acl_param *param); 470 static int ccs_write_acl(struct ccs_policy_namespace *ns, 471 struct list_head *list, char *data, 472 const bool is_delete); 473 static int ccs_write_aggregator(struct ccs_acl_param *param); 474 static int ccs_write_answer(struct ccs_io_buffer *head); 475 static int ccs_write_domain(struct ccs_io_buffer *head); 476 static int ccs_write_exception(struct ccs_io_buffer *head); 477 static int ccs_write_file(struct ccs_acl_param *param); 478 static int ccs_write_group(struct ccs_acl_param *param, const u8 type); 479 static int ccs_write_manager(struct ccs_io_buffer *head); 480 static int ccs_write_pid(struct ccs_io_buffer *head); 481 static int ccs_write_profile(struct ccs_io_buffer *head); 482 static int ccs_write_stat(struct ccs_io_buffer *head); 483 static int ccs_write_task(struct ccs_acl_param *param); 484 static int ccs_write_transition_control(struct ccs_acl_param *param, 485 const u8 type); 486 static s8 ccs_find_yesno(const char *string, const char *find); 487 static ssize_t ccs_read(struct file *file, char __user *buf, size_t count, 488 loff_t *ppos); 489 static ssize_t ccs_read_self(struct file *file, char __user *buf, size_t count, 490 loff_t *ppos); 491 static ssize_t ccs_write(struct file *file, const char __user *buf, 492 size_t count, loff_t *ppos); 493 static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry); 494 static struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param); 495 static struct ccs_domain_info *ccs_find_domain(const char *domainname); 496 static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial); 497 static struct ccs_group *ccs_get_group(struct ccs_acl_param *param, 498 const u8 idx); 499 static struct ccs_policy_namespace *ccs_assign_namespace 500 (const char *domainname); 501 static struct ccs_policy_namespace *ccs_find_namespace(const char *name, 502 const unsigned int len); 503 static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns, 504 const unsigned int profile); 505 static struct ccs_profile *ccs_profile(const u8 profile); 506 static u8 ccs_condition_type(const char *word); 507 static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3); 508 static u8 ccs_parse_ulong(unsigned long *result, char **str); 509 static unsigned int ccs_poll(struct file *file, poll_table *wait); 510 static void __init ccs_create_entry(const char *name, const umode_t mode, 511 struct proc_dir_entry *parent, 512 const u8 key); 513 static void __init ccs_load_builtin_policy(void); 514 static void __init ccs_policy_io_init(void); 515 static void __init ccs_proc_init(void); 516 static void ccs_add_entry(char *header); 517 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...) 518 __printf(3, 4); 519 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...); 520 static void ccs_check_profile(void); 521 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) 522 static void ccs_convert_time(time_t time, struct ccs_time *stamp); 523 #else 524 static void ccs_convert_time(time64_t time, struct ccs_time *stamp); 525 #endif 526 static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns); 527 static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...) 528 __printf(2, 3); 529 static void ccs_normalize_line(unsigned char *buffer); 530 static void ccs_print_config(struct ccs_io_buffer *head, const u8 config); 531 static void ccs_print_name_union(struct ccs_io_buffer *head, 532 const struct ccs_name_union *ptr); 533 static void ccs_print_name_union_quoted(struct ccs_io_buffer *head, 534 const struct ccs_name_union *ptr); 535 static void ccs_print_namespace(struct ccs_io_buffer *head); 536 static void ccs_print_number_union(struct ccs_io_buffer *head, 537 const struct ccs_number_union *ptr); 538 static void ccs_print_number_union_nospace(struct ccs_io_buffer *head, 539 const struct ccs_number_union *ptr); 540 static void ccs_read_domain(struct ccs_io_buffer *head); 541 static void ccs_read_exception(struct ccs_io_buffer *head); 542 static void ccs_read_log(struct ccs_io_buffer *head); 543 static void ccs_read_manager(struct ccs_io_buffer *head); 544 static void ccs_read_pid(struct ccs_io_buffer *head); 545 static void ccs_read_profile(struct ccs_io_buffer *head); 546 static void ccs_read_query(struct ccs_io_buffer *head); 547 static void ccs_read_stat(struct ccs_io_buffer *head); 548 static void ccs_read_version(struct ccs_io_buffer *head); 549 static void ccs_set_group(struct ccs_io_buffer *head, const char *category); 550 static void ccs_set_namespace_cursor(struct ccs_io_buffer *head); 551 static void ccs_set_slash(struct ccs_io_buffer *head); 552 static void ccs_set_space(struct ccs_io_buffer *head); 553 static void ccs_set_string(struct ccs_io_buffer *head, const char *string); 554 static void ccs_set_uint(unsigned int *i, const char *string, 555 const char *find); 556 static void ccs_update_stat(const u8 index); 557 static void ccs_update_task_domain(struct ccs_request_info *r); 558 static void ccs_write_log2(struct ccs_request_info *r, int len, 559 const char *fmt, va_list args); 560 561 #ifdef CONFIG_CCSECURITY_PORTRESERVE 562 static bool __ccs_lport_reserved(const u16 port); 563 static int ccs_write_reserved_port(struct ccs_acl_param *param); 564 #endif 565 566 #ifdef CONFIG_CCSECURITY_NETWORK 567 static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param, 568 struct ccs_ipaddr_union *ptr); 569 static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len, 570 const u32 *ip); 571 static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len, 572 const struct in6_addr *ip); 573 static int ccs_write_inet_network(struct ccs_acl_param *param); 574 static int ccs_write_unix_network(struct ccs_acl_param *param); 575 static void ccs_print_ip(char *buf, const unsigned int size, 576 const struct ccs_ipaddr_union *ptr); 577 #endif 578 579 #ifdef CONFIG_CCSECURITY_CAPABILITY 580 static int ccs_write_capability(struct ccs_acl_param *param); 581 #endif 582 583 #ifdef CONFIG_CCSECURITY_MISC 584 static int ccs_write_misc(struct ccs_acl_param *param); 585 #endif 586 587 #ifdef CONFIG_CCSECURITY_IPC 588 static int ccs_write_ipc(struct ccs_acl_param *param); 589 #endif 590 591 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION 592 static ssize_t ccs_write_self(struct file *file, const char __user *buf, 593 size_t count, loff_t *ppos); 594 #endif 595 596 /***** SECTION4: Standalone functions section *****/ 597 598 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) 599 600 /** 601 * fatal_signal_pending - Check whether SIGKILL is pending or not. 602 * 603 * @p: Pointer to "struct task_struct". 604 * 605 * Returns true if SIGKILL is pending on @p, false otherwise. 606 * 607 * This is for compatibility with older kernels. 608 */ 609 #define fatal_signal_pending(p) (signal_pending(p) && \ 610 sigismember(&p->pending.signal, SIGKILL)) 611 612 #endif 613 614 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) 615 616 /** 617 * __wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses. 618 * 619 * @wq: The waitqueue to wait on. 620 * @condition: A C expression for the event to wait for. 621 * @ret: Timeout, in jiffies. 622 * 623 * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a 624 * signal, and the remaining jiffies otherwise if the condition evaluated to 625 * true before the timeout elapsed. 626 * 627 * This is for compatibility with older kernels. 628 */ 629 #define __wait_event_interruptible_timeout(wq, condition, ret) \ 630 do { \ 631 wait_queue_t __wait; \ 632 init_waitqueue_entry(&__wait, current); \ 633 \ 634 add_wait_queue(&wq, &__wait); \ 635 for (;;) { \ 636 set_current_state(TASK_INTERRUPTIBLE); \ 637 if (condition) \ 638 break; \ 639 if (!signal_pending(current)) { \ 640 ret = schedule_timeout(ret); \ 641 if (!ret) \ 642 break; \ 643 continue; \ 644 } \ 645 ret = -ERESTARTSYS; \ 646 break; \ 647 } \ 648 current->state = TASK_RUNNING; \ 649 remove_wait_queue(&wq, &__wait); \ 650 } while (0) 651 652 /** 653 * wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses. 654 * 655 * @wq: The waitqueue to wait on. 656 * @condition: A C expression for the event to wait for. 657 * @timeout: Timeout, in jiffies. 658 * 659 * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a 660 * signal, and the remaining jiffies otherwise if the condition evaluated to 661 * true before the timeout elapsed. 662 * 663 * This is for compatibility with older kernels. 664 */ 665 #define wait_event_interruptible_timeout(wq, condition, timeout) \ 666 ({ \ 667 long __ret = timeout; \ 668 if (!(condition)) \ 669 __wait_event_interruptible_timeout(wq, condition, __ret); \ 670 __ret; \ 671 }) 672 673 #endif 674 675 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) 676 /** 677 * ccs_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss. 678 * 679 * @time: Seconds since 1970/01/01 00:00:00. 680 * @stamp: Pointer to "struct ccs_time". 681 * 682 * Returns nothing. 683 * 684 * This function does not handle Y2038 problem. 685 */ 686 static void ccs_convert_time(time_t time, struct ccs_time *stamp) 687 { 688 static const u16 ccs_eom[2][12] = { 689 { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 690 { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } 691 }; 692 u16 y; 693 u8 m; 694 bool r; 695 stamp->sec = time % 60; 696 time /= 60; 697 stamp->min = time % 60; 698 time /= 60; 699 stamp->hour = time % 24; 700 time /= 24; 701 for (y = 1970; ; y++) { 702 const unsigned short days = (y & 3) ? 365 : 366; 703 if (time < days) 704 break; 705 time -= days; 706 } 707 r = (y & 3) == 0; 708 for (m = 0; m < 11 && time >= ccs_eom[r][m]; m++); 709 if (m) 710 time -= ccs_eom[r][m - 1]; 711 stamp->year = y; 712 stamp->month = ++m; 713 stamp->day = ++time; 714 } 715 #else 716 /** 717 * ccs_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss. 718 * 719 * @time: Seconds since 1970/01/01 00:00:00. 720 * @stamp: Pointer to "struct ccs_time". 721 * 722 * Returns nothing. 723 */ 724 static void ccs_convert_time(time64_t time, struct ccs_time *stamp) 725 { 726 struct tm tm; 727 728 time64_to_tm(time, 0, &tm); 729 stamp->sec = tm.tm_sec; 730 stamp->min = tm.tm_min; 731 stamp->hour = tm.tm_hour; 732 stamp->day = tm.tm_mday; 733 stamp->month = tm.tm_mon + 1; 734 stamp->year = tm.tm_year + 1900; 735 } 736 #endif 737 738 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 23) 739 #if !defined(RHEL_VERSION) || RHEL_VERSION != 3 740 741 /** 742 * PDE - Get "struct proc_dir_entry". 743 * 744 * @inode: Pointer to "struct inode". 745 * 746 * Returns pointer to "struct proc_dir_entry". 747 * 748 * This is for compatibility with older kernels. 749 */ 750 static inline struct proc_dir_entry *PDE(const struct inode *inode) 751 { 752 return (struct proc_dir_entry *) inode->u.generic_ip; 753 } 754 755 #endif 756 #endif 757 758 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) 759 760 /** 761 * proc_notify_change - Update inode's attributes and reflect to the dentry. 762 * 763 * @dentry: Pointer to "struct dentry". 764 * @iattr: Pointer to "struct iattr". 765 * 766 * Returns 0 on success, negative value otherwise. 767 * 768 * The 2.4 kernels don't allow chmod()/chown() for files in /proc, 769 * while the 2.6 kernels allow. 770 * To permit management of /proc/ccs/ interface by non-root user, 771 * I modified to allow chmod()/chown() of /proc/ccs/ interface like 2.6 kernels 772 * by adding "struct inode_operations"->setattr hook. 773 */ 774 static int proc_notify_change(struct dentry *dentry, struct iattr *iattr) 775 { 776 struct inode *inode = dentry->d_inode; 777 struct proc_dir_entry *de = PDE(inode); 778 int error; 779 780 error = inode_change_ok(inode, iattr); 781 if (error) 782 goto out; 783 784 error = inode_setattr(inode, iattr); 785 if (error) 786 goto out; 787 788 de->uid = inode->i_uid; 789 de->gid = inode->i_gid; 790 de->mode = inode->i_mode; 791 out: 792 return error; 793 } 794 795 #endif 796 797 #ifdef CONFIG_CCSECURITY_NETWORK 798 799 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) && defined(CONFIG_NET) 800 #define ccs_in4_pton in4_pton 801 #define ccs_in6_pton in6_pton 802 #else 803 /* 804 * Routines for parsing IPv4 or IPv6 address. 805 * These are copied from lib/hexdump.c net/core/utils.c . 806 */ 807 #include <linux/ctype.h> 808 809 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) 810 static int hex_to_bin(char ch) 811 { 812 if ((ch >= '') && (ch <= '9')) 813 return ch - ''; 814 ch = tolower(ch); 815 if ((ch >= 'a') && (ch <= 'f')) 816 return ch - 'a' + 10; 817 return -1; 818 } 819 #endif 820 821 #define IN6PTON_XDIGIT 0x00010000 822 #define IN6PTON_DIGIT 0x00020000 823 #define IN6PTON_COLON_MASK 0x00700000 824 #define IN6PTON_COLON_1 0x00100000 /* single : requested */ 825 #define IN6PTON_COLON_2 0x00200000 /* second : requested */ 826 #define IN6PTON_COLON_1_2 0x00400000 /* :: requested */ 827 #define IN6PTON_DOT 0x00800000 /* . */ 828 #define IN6PTON_DELIM 0x10000000 829 #define IN6PTON_NULL 0x20000000 /* first/tail */ 830 #define IN6PTON_UNKNOWN 0x40000000 831 832 static inline int xdigit2bin(char c, int delim) 833 { 834 int val; 835 836 if (c == delim || c == '\0') 837 return IN6PTON_DELIM; 838 if (c == ':') 839 return IN6PTON_COLON_MASK; 840 if (c == '.') 841 return IN6PTON_DOT; 842 843 val = hex_to_bin(c); 844 if (val >= 0) 845 return val | IN6PTON_XDIGIT | (val < 10 ? IN6PTON_DIGIT : 0); 846 847 if (delim == -1) 848 return IN6PTON_DELIM; 849 return IN6PTON_UNKNOWN; 850 } 851 852 static int ccs_in4_pton(const char *src, int srclen, u8 *dst, int delim, 853 const char **end) 854 { 855 const char *s; 856 u8 *d; 857 u8 dbuf[4]; 858 int ret = 0; 859 int i; 860 int w = 0; 861 862 if (srclen < 0) 863 srclen = strlen(src); 864 s = src; 865 d = dbuf; 866 i = 0; 867 while (1) { 868 int c; 869 c = xdigit2bin(srclen > 0 ? *s : '\0', delim); 870 if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM | 871 IN6PTON_COLON_MASK))) 872 goto out; 873 if (c & (IN6PTON_DOT | IN6PTON_DELIM | IN6PTON_COLON_MASK)) { 874 if (w == 0) 875 goto out; 876 *d++ = w & 0xff; 877 w = 0; 878 i++; 879 if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) { 880 if (i != 4) 881 goto out; 882 break; 883 } 884 goto cont; 885 } 886 w = (w * 10) + c; 887 if ((w & 0xffff) > 255) 888 goto out; 889 cont: 890 if (i >= 4) 891 goto out; 892 s++; 893 srclen--; 894 } 895 ret = 1; 896 memcpy(dst, dbuf, sizeof(dbuf)); 897 out: 898 if (end) 899 *end = s; 900 return ret; 901 } 902 903 static int ccs_in6_pton(const char *src, int srclen, u8 *dst, int delim, 904 const char **end) 905 { 906 const char *s, *tok = NULL; 907 u8 *d, *dc = NULL; 908 u8 dbuf[16]; 909 int ret = 0; 910 int i; 911 int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL; 912 int w = 0; 913 914 memset(dbuf, 0, sizeof(dbuf)); 915 916 s = src; 917 d = dbuf; 918 if (srclen < 0) 919 srclen = strlen(src); 920 921 while (1) { 922 int c; 923 924 c = xdigit2bin(srclen > 0 ? *s : '\0', delim); 925 if (!(c & state)) 926 goto out; 927 if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) { 928 /* process one 16-bit word */ 929 if (!(state & IN6PTON_NULL)) { 930 *d++ = (w >> 8) & 0xff; 931 *d++ = w & 0xff; 932 } 933 w = 0; 934 if (c & IN6PTON_DELIM) { 935 /* We've processed last word */ 936 break; 937 } 938 /* 939 * COLON_1 => XDIGIT 940 * COLON_2 => XDIGIT|DELIM 941 * COLON_1_2 => COLON_2 942 */ 943 switch (state & IN6PTON_COLON_MASK) { 944 case IN6PTON_COLON_2: 945 dc = d; 946 state = IN6PTON_XDIGIT | IN6PTON_DELIM; 947 if (dc - dbuf >= sizeof(dbuf)) 948 state |= IN6PTON_NULL; 949 break; 950 case IN6PTON_COLON_1|IN6PTON_COLON_1_2: 951 state = IN6PTON_XDIGIT | IN6PTON_COLON_2; 952 break; 953 case IN6PTON_COLON_1: 954 state = IN6PTON_XDIGIT; 955 break; 956 case IN6PTON_COLON_1_2: 957 state = IN6PTON_COLON_2; 958 break; 959 default: 960 state = 0; 961 } 962 tok = s + 1; 963 goto cont; 964 } 965 966 if (c & IN6PTON_DOT) { 967 ret = ccs_in4_pton(tok ? tok : s, srclen + 968 (int)(s - tok), d, delim, &s); 969 if (ret > 0) { 970 d += 4; 971 break; 972 } 973 goto out; 974 } 975 976 w = (w << 4) | (0xff & c); 977 state = IN6PTON_COLON_1 | IN6PTON_DELIM; 978 if (!(w & 0xf000)) 979 state |= IN6PTON_XDIGIT; 980 if (!dc && d + 2 < dbuf + sizeof(dbuf)) { 981 state |= IN6PTON_COLON_1_2; 982 state &= ~IN6PTON_DELIM; 983 } 984 if (d + 2 >= dbuf + sizeof(dbuf)) 985 state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2); 986 cont: 987 if ((dc && d + 4 < dbuf + sizeof(dbuf)) || 988 d + 4 == dbuf + sizeof(dbuf)) 989 state |= IN6PTON_DOT; 990 if (d >= dbuf + sizeof(dbuf)) 991 state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK); 992 s++; 993 srclen--; 994 } 995 996 i = 15; d--; 997 998 if (dc) { 999 while (d >= dc) 1000 dst[i--] = *d--; 1001 while (i >= dc - dbuf) 1002 dst[i--] = 0; 1003 while (i >= 0) 1004 dst[i--] = *d--; 1005 } else 1006 memcpy(dst, dbuf, sizeof(dbuf)); 1007 1008 ret = 1; 1009 out: 1010 if (end) 1011 *end = s; 1012 return ret; 1013 } 1014 #endif 1015 1016 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) 1017 1018 /* 1019 * Routines for printing IPv4 or IPv6 address. 1020 * These are copied from include/linux/kernel.h include/net/ipv6.h 1021 * include/net/addrconf.h lib/hexdump.c lib/vsprintf.c and simplified. 1022 */ 1023 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) 1024 #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5 || !defined(RHEL_MINOR) || RHEL_MINOR < 9 1025 static const char hex_asc[] = "0123456789abcdef"; 1026 #define hex_asc_lo(x) hex_asc[((x) & 0x0f)] 1027 #define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] 1028 1029 static inline char *pack_hex_byte(char *buf, u8 byte) 1030 { 1031 *buf++ = hex_asc_hi(byte); 1032 *buf++ = hex_asc_lo(byte); 1033 return buf; 1034 } 1035 #endif 1036 #endif 1037 1038 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) 1039 static inline int ipv6_addr_v4mapped(const struct in6_addr *a) 1040 { 1041 return (a->s6_addr32[0] | a->s6_addr32[1] | 1042 (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0; 1043 } 1044 #endif 1045 1046 static inline int ipv6_addr_is_isatap(const struct in6_addr *addr) 1047 { 1048 return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE); 1049 } 1050 1051 static char *ip4_string(char *p, const u8 *addr) 1052 { 1053 /* 1054 * Since this function is called outside vsnprintf(), I can use 1055 * sprintf() here. 1056 */ 1057 return p + 1058 sprintf(p, "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]); 1059 } 1060 1061 static char *ip6_compressed_string(char *p, const char *addr) 1062 { 1063 int i, j, range; 1064 unsigned char zerolength[8]; 1065 int longest = 1; 1066 int colonpos = -1; 1067 u16 word; 1068 u8 hi, lo; 1069 bool needcolon = false; 1070 bool useIPv4; 1071 struct in6_addr in6; 1072 1073 memcpy(&in6, addr, sizeof(struct in6_addr)); 1074 1075 useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6); 1076 1077 memset(zerolength, 0, sizeof(zerolength)); 1078 1079 if (useIPv4) 1080 range = 6; 1081 else 1082 range = 8; 1083 1084 /* find position of longest 0 run */ 1085 for (i = 0; i < range; i++) { 1086 for (j = i; j < range; j++) { 1087 if (in6.s6_addr16[j] != 0) 1088 break; 1089 zerolength[i]++; 1090 } 1091 } 1092 for (i = 0; i < range; i++) { 1093 if (zerolength[i] > longest) { 1094 longest = zerolength[i]; 1095 colonpos = i; 1096 } 1097 } 1098 if (longest == 1) /* don't compress a single 0 */ 1099 colonpos = -1; 1100 1101 /* emit address */ 1102 for (i = 0; i < range; i++) { 1103 if (i == colonpos) { 1104 if (needcolon || i == 0) 1105 *p++ = ':'; 1106 *p++ = ':'; 1107 needcolon = false; 1108 i += longest - 1; 1109 continue; 1110 } 1111 if (needcolon) { 1112 *p++ = ':'; 1113 needcolon = false; 1114 } 1115 /* hex u16 without leading 0s */ 1116 word = ntohs(in6.s6_addr16[i]); 1117 hi = word >> 8; 1118 lo = word & 0xff; 1119 if (hi) { 1120 if (hi > 0x0f) 1121 p = pack_hex_byte(p, hi); 1122 else 1123 *p++ = hex_asc_lo(hi); 1124 p = pack_hex_byte(p, lo); 1125 } else if (lo > 0x0f) 1126 p = pack_hex_byte(p, lo); 1127 else 1128 *p++ = hex_asc_lo(lo); 1129 needcolon = true; 1130 } 1131 1132 if (useIPv4) { 1133 if (needcolon) 1134 *p++ = ':'; 1135 p = ip4_string(p, &in6.s6_addr[12]); 1136 } 1137 *p = '\0'; 1138 1139 return p; 1140 } 1141 #endif 1142 1143 /** 1144 * ccs_print_ipv4 - Print an IPv4 address. 1145 * 1146 * @buffer: Buffer to write to. 1147 * @buffer_len: Size of @buffer. 1148 * @ip: Pointer to "u32 in network byte order". 1149 * 1150 * Returns written length. 1151 */ 1152 static int ccs_print_ipv4(char *buffer, const unsigned int buffer_len, 1153 const u32 *ip) 1154 { 1155 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) 1156 return snprintf(buffer, buffer_len, "%pI4", ip); 1157 #else 1158 char addr[sizeof("255.255.255.255")]; 1159 ip4_string(addr, (const u8 *) ip); 1160 return snprintf(buffer, buffer_len, "%s", addr); 1161 #endif 1162 } 1163 1164 /** 1165 * ccs_print_ipv6 - Print an IPv6 address. 1166 * 1167 * @buffer: Buffer to write to. 1168 * @buffer_len: Size of @buffer. 1169 * @ip: Pointer to "struct in6_addr". 1170 * 1171 * Returns written length. 1172 */ 1173 static int ccs_print_ipv6(char *buffer, const unsigned int buffer_len, 1174 const struct in6_addr *ip) 1175 { 1176 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) 1177 return snprintf(buffer, buffer_len, "%pI6c", ip); 1178 #else 1179 char addr[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")]; 1180 ip6_compressed_string(addr, (const u8 *) ip); 1181 return snprintf(buffer, buffer_len, "%s", addr); 1182 #endif 1183 } 1184 1185 /** 1186 * ccs_print_ip - Print an IP address. 1187 * 1188 * @buf: Buffer to write to. 1189 * @size: Size of @buf. 1190 * @ptr: Pointer to "struct ipaddr_union". 1191 * 1192 * Returns nothing. 1193 */ 1194 static void ccs_print_ip(char *buf, const unsigned int size, 1195 const struct ccs_ipaddr_union *ptr) 1196 { 1197 int len; 1198 if (ptr->is_ipv6) 1199 len = ccs_print_ipv6(buf, size, &ptr->ip[0]); 1200 else 1201 len = ccs_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0]); 1202 if (!memcmp(&ptr->ip[0], &ptr->ip[1], 16) || len >= size / 2) 1203 return; 1204 buf[len++] = '-'; 1205 if (ptr->is_ipv6) 1206 ccs_print_ipv6(buf + len, size - len, &ptr->ip[1]); 1207 else 1208 ccs_print_ipv4(buf + len, size - len, 1209 &ptr->ip[1].s6_addr32[0]); 1210 } 1211 1212 #endif 1213 1214 /***** SECTION5: Variables definition section *****/ 1215 1216 /* Permit policy management by non-root user? */ 1217 static bool ccs_manage_by_non_root; 1218 1219 /* Lock for protecting policy. */ 1220 DEFINE_MUTEX(ccs_policy_lock); 1221 1222 /* Has /sbin/init started? */ 1223 bool ccs_policy_loaded; 1224 1225 /* List of namespaces. */ 1226 LIST_HEAD(ccs_namespace_list); 1227 /* True if namespace other than ccs_kernel_namespace is defined. */ 1228 static bool ccs_namespace_enabled; 1229 1230 /* Initial namespace.*/ 1231 static struct ccs_policy_namespace ccs_kernel_namespace; 1232 1233 /* List of "struct ccs_condition". */ 1234 LIST_HEAD(ccs_condition_list); 1235 1236 #ifdef CONFIG_CCSECURITY_PORTRESERVE 1237 /* Bitmap for reserved local port numbers.*/ 1238 static u8 ccs_reserved_port_map[8192]; 1239 #endif 1240 1241 /* Wait queue for kernel -> userspace notification. */ 1242 static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait); 1243 /* Wait queue for userspace -> kernel notification. */ 1244 static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait); 1245 1246 /* The list for "struct ccs_query". */ 1247 static LIST_HEAD(ccs_query_list); 1248 1249 /* Lock for manipulating ccs_query_list. */ 1250 static DEFINE_SPINLOCK(ccs_query_list_lock); 1251 1252 /* Number of "struct file" referring /proc/ccs/query interface. */ 1253 static atomic_t ccs_query_observers = ATOMIC_INIT(0); 1254 1255 /* Wait queue for /proc/ccs/audit. */ 1256 static DECLARE_WAIT_QUEUE_HEAD(ccs_log_wait); 1257 1258 /* The list for "struct ccs_log". */ 1259 static LIST_HEAD(ccs_log); 1260 1261 /* Lock for "struct list_head ccs_log". */ 1262 static DEFINE_SPINLOCK(ccs_log_lock); 1263 1264 /* Length of "stuct list_head ccs_log". */ 1265 static unsigned int ccs_log_count; 1266 1267 /* Counter for number of updates. */ 1268 static atomic_t ccs_stat_updated[CCS_MAX_POLICY_STAT]; 1269 1270 /* Timestamp counter for last updated. */ 1271 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) 1272 static unsigned int ccs_stat_modified[CCS_MAX_POLICY_STAT]; 1273 #else 1274 static time64_t ccs_stat_modified[CCS_MAX_POLICY_STAT]; 1275 #endif 1276 1277 /* Operations for /proc/ccs/self_domain interface. */ 1278 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 1279 static const struct proc_ops ccs_self_operations = { 1280 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION 1281 .proc_write = ccs_write_self, 1282 #endif 1283 .proc_read = ccs_read_self, 1284 }; 1285 #else 1286 static 1287 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17) 1288 const 1289 #endif 1290 struct file_operations ccs_self_operations = { 1291 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION 1292 .write = ccs_write_self, 1293 #endif 1294 .read = ccs_read_self, 1295 }; 1296 #endif 1297 1298 /* Operations for /proc/ccs/ interface. */ 1299 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) 1300 static const struct proc_ops ccs_operations = { 1301 .proc_open = ccs_open, 1302 .proc_release = ccs_release, 1303 .proc_poll = ccs_poll, 1304 .proc_read = ccs_read, 1305 .proc_write = ccs_write, 1306 }; 1307 #else 1308 static 1309 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17) 1310 const 1311 #endif 1312 struct file_operations ccs_operations = { 1313 .open = ccs_open, 1314 .release = ccs_release, 1315 .poll = ccs_poll, 1316 .read = ccs_read, 1317 .write = ccs_write, 1318 }; 1319 #endif 1320 1321 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) 1322 1323 /* The inode operations for /proc/ccs/ directory. */ 1324 static struct inode_operations ccs_dir_inode_operations; 1325 1326 /* The inode operations for files under /proc/ccs/ directory. */ 1327 static struct inode_operations ccs_file_inode_operations; 1328 1329 #endif 1330 1331 /***** SECTION6: Dependent functions section *****/ 1332 1333 /** 1334 * list_for_each_cookie - iterate over a list with cookie. 1335 * 1336 * @pos: Pointer to "struct list_head". 1337 * @head: Pointer to "struct list_head". 1338 */ 1339 #define list_for_each_cookie(pos, head) \ 1340 for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \ 1341 pos != (head); pos = srcu_dereference(pos->next, &ccs_ss)) 1342 1343 /** 1344 * ccs_read_token - Read a word from a line. 1345 * 1346 * @param: Pointer to "struct ccs_acl_param". 1347 * 1348 * Returns a word on success, "" otherwise. 1349 * 1350 * To allow the caller to skip NULL check, this function returns "" rather than 1351 * NULL if there is no more words to read. 1352 */ 1353 static char *ccs_read_token(struct ccs_acl_param *param) 1354 { 1355 char *pos = param->data; 1356 char *del = strchr(pos, ' '); 1357 if (del) 1358 *del++ = '\0'; 1359 else 1360 del = pos + strlen(pos); 1361 param->data = del; 1362 return pos; 1363 } 1364 1365 /** 1366 * ccs_make_byte - Make byte value from three octal characters. 1367 * 1368 * @c1: The first character. 1369 * @c2: The second character. 1370 * @c3: The third character. 1371 * 1372 * Returns byte value. 1373 */ 1374 static u8 ccs_make_byte(const u8 c1, const u8 c2, const u8 c3) 1375 { 1376 return ((c1 - '') << 6) + ((c2 - '') << 3) + (c3 - ''); 1377 } 1378 1379 /** 1380 * ccs_correct_word2 - Check whether the given string follows the naming rules. 1381 * 1382 * @string: The byte sequence to check. Not '\0'-terminated. 1383 * @len: Length of @string. 1384 * 1385 * Returns true if @string follows the naming rules, false otherwise. 1386 */ 1387 static bool ccs_correct_word2(const char *string, size_t len) 1388 { 1389 u8 recursion = 20; 1390 const char *const start = string; 1391 bool in_repetition = false; 1392 if (!len) 1393 goto out; 1394 while (len--) { 1395 unsigned char c = *string++; 1396 if (c == '\\') { 1397 if (!len--) 1398 goto out; 1399 c = *string++; 1400 if (c >= '' && c <= '3') { 1401 unsigned char d; 1402 unsigned char e; 1403 if (!len-- || !len--) 1404 goto out; 1405 d = *string++; 1406 e = *string++; 1407 if (d < '' || d > '7' || e < '' || e > '7') 1408 goto out; 1409 c = ccs_make_byte(c, d, e); 1410 if (c <= ' ' || c >= 127) 1411 continue; 1412 goto out; 1413 } 1414 switch (c) { 1415 case '\\': /* "\\" */ 1416 case '+': /* "\+" */ 1417 case '?': /* "\?" */ 1418 case 'x': /* "\x" */ 1419 case 'a': /* "\a" */ 1420 case '-': /* "\-" */ 1421 continue; 1422 } 1423 if (!recursion--) 1424 goto out; 1425 switch (c) { 1426 case '*': /* "\*" */ 1427 case '@': /* "\@" */ 1428 case '$': /* "\$" */ 1429 case 'X': /* "\X" */ 1430 case 'A': /* "\A" */ 1431 continue; 1432 case '{': /* "/\{" */ 1433 if (string - 3 < start || *(string - 3) != '/') 1434 goto out; 1435 in_repetition = true; 1436 continue; 1437 case '}': /* "\}/" */ 1438 if (*string != '/') 1439 goto out; 1440 if (!in_repetition) 1441 goto out; 1442 in_repetition = false; 1443 continue; 1444 } 1445 goto out; 1446 } else if (in_repetition && c == '/') { 1447 goto out; 1448 } else if (c <= ' ' || c >= 127) { 1449 goto out; 1450 } 1451 } 1452 if (in_repetition) 1453 goto out; 1454 return true; 1455 out: 1456 return false; 1457 } 1458 1459 /** 1460 * ccs_correct_word - Check whether the given string follows the naming rules. 1461 * 1462 * @string: The string to check. 1463 * 1464 * Returns true if @string follows the naming rules, false otherwise. 1465 */ 1466 static bool ccs_correct_word(const char *string) 1467 { 1468 return ccs_correct_word2(string, strlen(string)); 1469 } 1470 1471 /** 1472 * ccs_get_group - Allocate memory for "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group". 1473 * 1474 * @param: Pointer to "struct ccs_acl_param". 1475 * @idx: Index number. 1476 * 1477 * Returns pointer to "struct ccs_group" on success, NULL otherwise. 1478 */ 1479 static struct ccs_group *ccs_get_group(struct ccs_acl_param *param, 1480 const u8 idx) 1481 { 1482 struct ccs_group e = { }; 1483 struct ccs_group *group = NULL; 1484 struct list_head *list; 1485 const char *group_name = ccs_read_token(param); 1486 bool found = false; 1487 if (!ccs_correct_word(group_name) || idx >= CCS_MAX_GROUP) 1488 return NULL; 1489 e.group_name = ccs_get_name(group_name); 1490 if (!e.group_name) 1491 return NULL; 1492 if (mutex_lock_interruptible(&ccs_policy_lock)) 1493 goto out; 1494 list = ¶m->ns->group_list[idx]; 1495 list_for_each_entry(group, list, head.list) { 1496 if (e.group_name != group->group_name || 1497 atomic_read(&group->head.users) == CCS_GC_IN_PROGRESS) 1498 continue; 1499 atomic_inc(&group->head.users); 1500 found = true; 1501 break; 1502 } 1503 if (!found) { 1504 struct ccs_group *entry = ccs_commit_ok(&e, sizeof(e)); 1505 if (entry) { 1506 INIT_LIST_HEAD(&entry->member_list); 1507 atomic_set(&entry->head.users, 1); 1508 list_add_tail_rcu(&entry->head.list, list); 1509 group = entry; 1510 found = true; 1511 } 1512 } 1513 mutex_unlock(&ccs_policy_lock); 1514 out: 1515 ccs_put_name(e.group_name); 1516 return found ? group : NULL; 1517 } 1518 1519 /** 1520 * ccs_parse_name_union - Parse a ccs_name_union. 1521 * 1522 * @param: Pointer to "struct ccs_acl_param". 1523 * @ptr: Pointer to "struct ccs_name_union". 1524 * 1525 * Returns true on success, false otherwise. 1526 */ 1527 static bool ccs_parse_name_union(struct ccs_acl_param *param, 1528 struct ccs_name_union *ptr) 1529 { 1530 char *filename; 1531 if (param->data[0] == '@') { 1532 param->data++; 1533 ptr->group = ccs_get_group(param, CCS_PATH_GROUP); 1534 return ptr->group != NULL; 1535 } 1536 filename = ccs_read_token(param); 1537 if (!ccs_correct_word(filename)) 1538 return false; 1539 ptr->filename = ccs_get_name(filename); 1540 return ptr->filename != NULL; 1541 } 1542 1543 /** 1544 * ccs_parse_ulong - Parse an "unsigned long" value. 1545 * 1546 * @result: Pointer to "unsigned long". 1547 * @str: Pointer to string to parse. 1548 * 1549 * Returns one of values in "enum ccs_value_type". 1550 * 1551 * The @src is updated to point the first character after the value 1552 * on success. 1553 */ 1554 static u8 ccs_parse_ulong(unsigned long *result, char **str) 1555 { 1556 const char *cp = *str; 1557 char *ep; 1558 int base = 10; 1559 if (*cp == '') { 1560 char c = *(cp + 1); 1561 if (c == 'x' || c == 'X') { 1562 base = 16; 1563 cp += 2; 1564 } else if (c >= '' && c <= '7') { 1565 base = 8; 1566 cp++; 1567 } 1568 } 1569 *result = simple_strtoul(cp, &ep, base); 1570 if (cp == ep) 1571 return CCS_VALUE_TYPE_INVALID; 1572 *str = ep; 1573 switch (base) { 1574 case 16: 1575 return CCS_VALUE_TYPE_HEXADECIMAL; 1576 case 8: 1577 return CCS_VALUE_TYPE_OCTAL; 1578 default: 1579 return CCS_VALUE_TYPE_DECIMAL; 1580 } 1581 } 1582 1583 /** 1584 * ccs_parse_number_union - Parse a ccs_number_union. 1585 * 1586 * @param: Pointer to "struct ccs_acl_param". 1587 * @ptr: Pointer to "struct ccs_number_union". 1588 * 1589 * Returns true on success, false otherwise. 1590 */ 1591 static bool ccs_parse_number_union(struct ccs_acl_param *param, 1592 struct ccs_number_union *ptr) 1593 { 1594 char *data; 1595 u8 type; 1596 unsigned long v; 1597 memset(ptr, 0, sizeof(*ptr)); 1598 if (param->data[0] == '@') { 1599 param->data++; 1600 ptr->group = ccs_get_group(param, CCS_NUMBER_GROUP); 1601 return ptr->group != NULL; 1602 } 1603 data = ccs_read_token(param); 1604 type = ccs_parse_ulong(&v, &data); 1605 if (type == CCS_VALUE_TYPE_INVALID) 1606 return false; 1607 ptr->values[0] = v; 1608 ptr->value_type[0] = type; 1609 if (!*data) { 1610 ptr->values[1] = v; 1611 ptr->value_type[1] = type; 1612 return true; 1613 } 1614 if (*data++ != '-') 1615 return false; 1616 type = ccs_parse_ulong(&v, &data); 1617 if (type == CCS_VALUE_TYPE_INVALID || *data || ptr->values[0] > v) 1618 return false; 1619 ptr->values[1] = v; 1620 ptr->value_type[1] = type; 1621 return true; 1622 } 1623 1624 #ifdef CONFIG_CCSECURITY_NETWORK 1625 1626 /** 1627 * ccs_parse_ipaddr_union - Parse an IP address. 1628 * 1629 * @param: Pointer to "struct ccs_acl_param". 1630 * @ptr: Pointer to "struct ccs_ipaddr_union". 1631 * 1632 * Returns true on success, false otherwise. 1633 */ 1634 static bool ccs_parse_ipaddr_union(struct ccs_acl_param *param, 1635 struct ccs_ipaddr_union *ptr) 1636 { 1637 u8 * const min = ptr->ip[0].in6_u.u6_addr8; 1638 u8 * const max = ptr->ip[1].in6_u.u6_addr8; 1639 char *address = ccs_read_token(param); 1640 const char *end; 1641 if (!strchr(address, ':') && 1642 ccs_in4_pton(address, -1, min, '-', &end) > 0) { 1643 ptr->is_ipv6 = false; 1644 if (!*end) 1645 ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0]; 1646 else if (*end++ != '-' || 1647 ccs_in4_pton(end, -1, max, '\0', &end) <= 0 || *end) 1648 return false; 1649 return true; 1650 } 1651 if (ccs_in6_pton(address, -1, min, '-', &end) > 0) { 1652 ptr->is_ipv6 = true; 1653 if (!*end) 1654 memmove(max, min, sizeof(u16) * 8); 1655 else if (*end++ != '-' || 1656 ccs_in6_pton(end, -1, max, '\0', &end) <= 0 || *end) 1657 return false; 1658 return true; 1659 } 1660 return false; 1661 } 1662 1663 #endif 1664 1665 /** 1666 * ccs_get_dqword - ccs_get_name() for a quoted string. 1667 * 1668 * @start: String to save. 1669 * 1670 * Returns pointer to "struct ccs_path_info" on success, NULL otherwise. 1671 */ 1672 static const struct ccs_path_info *ccs_get_dqword(char *start) 1673 { 1674 char *cp = start + strlen(start) - 1; 1675 if (cp == start || *start++ != '"' || *cp != '"') 1676 return NULL; 1677 *cp = '\0'; 1678 if (*start && !ccs_correct_word(start)) 1679 return NULL; 1680 return ccs_get_name(start); 1681 } 1682 1683 /** 1684 * ccs_parse_name_union_quoted - Parse a quoted word. 1685 * 1686 * @param: Pointer to "struct ccs_acl_param". 1687 * @ptr: Pointer to "struct ccs_name_union". 1688 * 1689 * Returns true on success, false otherwise. 1690 */ 1691 static bool ccs_parse_name_union_quoted(struct ccs_acl_param *param, 1692 struct ccs_name_union *ptr) 1693 { 1694 char *filename = param->data; 1695 if (*filename == '@') 1696 return ccs_parse_name_union(param, ptr); 1697 ptr->filename = ccs_get_dqword(filename); 1698 return ptr->filename != NULL; 1699 } 1700 1701 /** 1702 * ccs_parse_argv - Parse an argv[] condition part. 1703 * 1704 * @left: Lefthand value. 1705 * @right: Righthand value. 1706 * @argv: Pointer to "struct ccs_argv". 1707 * 1708 * Returns true on success, false otherwise. 1709 */ 1710 static bool ccs_parse_argv(char *left, char *right, struct ccs_argv *argv) 1711 { 1712 if (ccs_parse_ulong(&argv->index, &left) != CCS_VALUE_TYPE_DECIMAL || 1713 *left++ != ']' || *left) 1714 return false; 1715 argv->value = ccs_get_dqword(right); 1716 return argv->value != NULL; 1717 } 1718 1719 /** 1720 * ccs_parse_envp - Parse an envp[] condition part. 1721 * 1722 * @left: Lefthand value. 1723 * @right: Righthand value. 1724 * @envp: Pointer to "struct ccs_envp". 1725 * 1726 * Returns true on success, false otherwise. 1727 */ 1728 static bool ccs_parse_envp(char *left, char *right, struct ccs_envp *envp) 1729 { 1730 const struct ccs_path_info *name; 1731 const struct ccs_path_info *value; 1732 char *cp = left + strlen(left) - 1; 1733 if (*cp-- != ']' || *cp != '"') 1734 goto out; 1735 *cp = '\0'; 1736 if (!ccs_correct_word(left)) 1737 goto out; 1738 name = ccs_get_name(left); 1739 if (!name) 1740 goto out; 1741 if (!strcmp(right, "NULL")) { 1742 value = NULL; 1743 } else { 1744 value = ccs_get_dqword(right); 1745 if (!value) { 1746 ccs_put_name(name); 1747 goto out; 1748 } 1749 } 1750 envp->name = name; 1751 envp->value = value; 1752 return true; 1753 out: 1754 return false; 1755 } 1756 1757 /** 1758 * ccs_same_condition - Check for duplicated "struct ccs_condition" entry. 1759 * 1760 * @a: Pointer to "struct ccs_condition". 1761 * @b: Pointer to "struct ccs_condition". 1762 * 1763 * Returns true if @a == @b, false otherwise. 1764 */ 1765 static bool ccs_same_condition(const struct ccs_condition *a, 1766 const struct ccs_condition *b) 1767 { 1768 return a->size == b->size && a->condc == b->condc && 1769 a->numbers_count == b->numbers_count && 1770 a->names_count == b->names_count && 1771 a->argc == b->argc && a->envc == b->envc && 1772 a->grant_log == b->grant_log && 1773 a->exec_transit == b->exec_transit && a->transit == b->transit 1774 && !memcmp(a + 1, b + 1, a->size - sizeof(*a)); 1775 } 1776 1777 /** 1778 * ccs_condition_type - Get condition type. 1779 * 1780 * @word: Keyword string. 1781 * 1782 * Returns one of values in "enum ccs_conditions_index" on success, 1783 * CCS_MAX_CONDITION_KEYWORD otherwise. 1784 */ 1785 static u8 ccs_condition_type(const char *word) 1786 { 1787 u8 i; 1788 for (i = 0; i < CCS_MAX_CONDITION_KEYWORD; i++) { 1789 if (!strcmp(word, ccs_condition_keyword[i])) 1790 break; 1791 } 1792 return i; 1793 } 1794 1795 /** 1796 * ccs_commit_condition - Commit "struct ccs_condition". 1797 * 1798 * @entry: Pointer to "struct ccs_condition". 1799 * 1800 * Returns pointer to "struct ccs_condition" on success, NULL otherwise. 1801 * 1802 * This function merges duplicated entries. This function returns NULL if 1803 * @entry is not duplicated but memory quota for policy has exceeded. 1804 */ 1805 static struct ccs_condition *ccs_commit_condition(struct ccs_condition *entry) 1806 { 1807 struct ccs_condition *ptr; 1808 bool found = false; 1809 if (mutex_lock_interruptible(&ccs_policy_lock)) { 1810 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__); 1811 ptr = NULL; 1812 found = true; 1813 goto out; 1814 } 1815 list_for_each_entry(ptr, &ccs_condition_list, head.list) { 1816 if (!ccs_same_condition(ptr, entry) || 1817 atomic_read(&ptr->head.users) == CCS_GC_IN_PROGRESS) 1818 continue; 1819 /* Same entry found. Share this entry. */ 1820 atomic_inc(&ptr->head.users); 1821 found = true; 1822 break; 1823 } 1824 if (!found) { 1825 if (ccs_memory_ok(entry, entry->size)) { 1826 atomic_set(&entry->head.users, 1); 1827 list_add(&entry->head.list, &ccs_condition_list); 1828 } else { 1829 found = true; 1830 ptr = NULL; 1831 } 1832 } 1833 mutex_unlock(&ccs_policy_lock); 1834 out: 1835 if (found) { 1836 ccs_del_condition(&entry->head.list); 1837 kfree(entry); 1838 entry = ptr; 1839 } 1840 return entry; 1841 } 1842 1843 /** 1844 * ccs_correct_path - Check whether the given pathname follows the naming rules. 1845 * 1846 * @filename: The pathname to check. 1847 * 1848 * Returns true if @filename follows the naming rules, false otherwise. 1849 */ 1850 static bool ccs_correct_path(const char *filename) 1851 { 1852 return *filename == '/' && ccs_correct_word(filename); 1853 } 1854 1855 /** 1856 * ccs_domain_def - Check whether the given token can be a domainname. 1857 * 1858 * @buffer: The token to check. 1859 * 1860 * Returns true if @buffer possibly be a domainname, false otherwise. 1861 */ 1862 static bool ccs_domain_def(const unsigned char *buffer) 1863 { 1864 const unsigned char *cp; 1865 int len; 1866 if (*buffer != '<') 1867 return false; 1868 cp = strchr(buffer, ' '); 1869 if (!cp) 1870 len = strlen(buffer); 1871 else 1872 len = cp - buffer; 1873 if (buffer[len - 1] != '>' || !ccs_correct_word2(buffer + 1, len - 2)) 1874 return false; 1875 return true; 1876 } 1877 1878 /** 1879 * ccs_correct_domain - Check whether the given domainname follows the naming rules. 1880 * 1881 * @domainname: The domainname to check. 1882 * 1883 * Returns true if @domainname follows the naming rules, false otherwise. 1884 */ 1885 static bool ccs_correct_domain(const unsigned char *domainname) 1886 { 1887 if (!domainname || !ccs_domain_def(domainname)) 1888 return false; 1889 domainname = strchr(domainname, ' '); 1890 if (!domainname++) 1891 return true; 1892 while (1) { 1893 const unsigned char *cp = strchr(domainname, ' '); 1894 if (!cp) 1895 break; 1896 if (*domainname != '/' || 1897 !ccs_correct_word2(domainname, cp - domainname)) 1898 return false; 1899 domainname = cp + 1; 1900 } 1901 return ccs_correct_path(domainname); 1902 } 1903 1904 /** 1905 * ccs_normalize_line - Format string. 1906 * 1907 * @buffer: The line to normalize. 1908 * 1909 * Returns nothing. 1910 * 1911 * Leading and trailing whitespaces are removed. 1912 * Multiple whitespaces are packed into single space. 1913 */ 1914 static void ccs_normalize_line(unsigned char *buffer) 1915 { 1916 unsigned char *sp = buffer; 1917 unsigned char *dp = buffer; 1918 bool first = true; 1919 while (*sp && (*sp <= ' ' || *sp >= 127)) 1920 sp++; 1921 while (*sp) { 1922 if (!first) 1923 *dp++ = ' '; 1924 first = false; 1925 while (*sp > ' ' && *sp < 127) 1926 *dp++ = *sp++; 1927 while (*sp && (*sp <= ' ' || *sp >= 127)) 1928 sp++; 1929 } 1930 *dp = '\0'; 1931 } 1932 1933 /** 1934 * ccs_get_domainname - Read a domainname from a line. 1935 * 1936 * @param: Pointer to "struct ccs_acl_param". 1937 * 1938 * Returns a domainname on success, NULL otherwise. 1939 */ 1940 static const struct ccs_path_info *ccs_get_domainname 1941 (struct ccs_acl_param *param) 1942 { 1943 char *start = param->data; 1944 char *pos = start; 1945 while (*pos) { 1946 if (*pos++ != ' ' || *pos++ == '/') 1947 continue; 1948 pos -= 2; 1949 *pos++ = '\0'; 1950 break; 1951 } 1952 param->data = pos; 1953 if (ccs_correct_domain(start)) 1954 return ccs_get_name(start); 1955 return NULL; 1956 } 1957 1958 /** 1959 * ccs_get_transit_preference - Parse domain transition preference for execve(). 1960 * 1961 * @param: Pointer to "struct ccs_acl_param". 1962 * @e: Pointer to "struct ccs_condition". 1963 * 1964 * Returns the condition string part. 1965 */ 1966 static char *ccs_get_transit_preference(struct ccs_acl_param *param, 1967 struct ccs_condition *e) 1968 { 1969 char * const pos = param->data; 1970 bool flag; 1971 if (*pos == '<') { 1972 e->transit = ccs_get_domainname(param); 1973 goto done; 1974 } 1975 { 1976 char *cp = strchr(pos, ' '); 1977 if (cp) 1978 *cp = '\0'; 1979 flag = ccs_correct_path(pos) || !strcmp(pos, "keep") || 1980 !strcmp(pos, "initialize") || !strcmp(pos, "reset") || 1981 !strcmp(pos, "child") || !strcmp(pos, "parent"); 1982 if (cp) 1983 *cp = ' '; 1984 } 1985 if (!flag) 1986 return pos; 1987 e->transit = ccs_get_name(ccs_read_token(param)); 1988 done: 1989 if (e->transit) { 1990 e->exec_transit = true; 1991 return param->data; 1992 } 1993 /* 1994 * Return a bad read-only condition string that will let 1995 * ccs_get_condition() return NULL. 1996 */ 1997 return "/"; 1998 } 1999 2000 /** 2001 * ccs_get_condition - Parse condition part. 2002 * 2003 * @param: Pointer to "struct ccs_acl_param". 2004 * 2005 * Returns pointer to "struct ccs_condition" on success, NULL otherwise. 2006 */ 2007 static struct ccs_condition *ccs_get_condition(struct ccs_acl_param *param) 2008 { 2009 struct ccs_condition *entry = NULL; 2010 struct ccs_condition_element *condp = NULL; 2011 struct ccs_number_union *numbers_p = NULL; 2012 struct ccs_name_union *names_p = NULL; 2013 struct ccs_argv *argv = NULL; 2014 struct ccs_envp *envp = NULL; 2015 struct ccs_condition e = { }; 2016 char * const start_of_string = ccs_get_transit_preference(param, &e); 2017 char * const end_of_string = start_of_string + strlen(start_of_string); 2018 char *pos; 2019 rerun: 2020 pos = start_of_string; 2021 while (1) { 2022 u8 left = -1; 2023 u8 right = -1; 2024 char *left_word = pos; 2025 char *cp; 2026 char *right_word; 2027 bool is_not; 2028 if (!*left_word) 2029 break; 2030 /* 2031 * Since left-hand condition does not allow use of "path_group" 2032 * or "number_group" and environment variable's names do not 2033 * accept '=', it is guaranteed that the original line consists 2034 * of one or more repetition of $left$operator$right blocks 2035 * where "$left is free from '=' and ' '" and "$operator is 2036 * either '=' or '!='" and "$right is free from ' '". 2037 * Therefore, we can reconstruct the original line at the end 2038 * of dry run even if we overwrite $operator with '\0'. 2039 */ 2040 cp = strchr(pos, ' '); 2041 if (cp) { 2042 *cp = '\0'; /* Will restore later. */ 2043 pos = cp + 1; 2044 } else { 2045 pos = ""; 2046 } 2047 right_word = strchr(left_word, '='); 2048 if (!right_word || right_word == left_word) 2049 goto out; 2050 is_not = *(right_word - 1) == '!'; 2051 if (is_not) 2052 *(right_word++ - 1) = '\0'; /* Will restore later. */ 2053 else if (*(right_word + 1) != '=') 2054 *right_word++ = '\0'; /* Will restore later. */ 2055 else 2056 goto out; 2057 dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word, 2058 is_not ? "!" : "", right_word); 2059 if (!strcmp(left_word, "grant_log")) { 2060 if (entry) { 2061 if (is_not || 2062 entry->grant_log != CCS_GRANTLOG_AUTO) 2063 goto out; 2064 else if (!strcmp(right_word, "yes")) 2065 entry->grant_log = CCS_GRANTLOG_YES; 2066 else if (!strcmp(right_word, "no")) 2067 entry->grant_log = CCS_GRANTLOG_NO; 2068 else 2069 goto out; 2070 } 2071 continue; 2072 } 2073 if (!strcmp(left_word, "auto_domain_transition")) { 2074 if (entry) { 2075 if (is_not || entry->transit) 2076 goto out; 2077 entry->transit = ccs_get_dqword(right_word); 2078 if (!entry->transit || 2079 (entry->transit->name[0] != '/' && 2080 !ccs_domain_def(entry->transit->name))) 2081 goto out; 2082 } 2083 continue; 2084 } 2085 if (!strncmp(left_word, "exec.argv[", 10)) { 2086 if (!argv) { 2087 e.argc++; 2088 e.condc++; 2089 } else { 2090 e.argc--; 2091 e.condc--; 2092 left = CCS_ARGV_ENTRY; 2093 argv->is_not = is_not; 2094 if (!ccs_parse_argv(left_word + 10, 2095 right_word, argv++)) 2096 goto out; 2097 } 2098 goto store_value; 2099 } 2100 if (!strncmp(left_word, "exec.envp[\"", 11)) { 2101 if (!envp) { 2102 e.envc++; 2103 e.condc++; 2104 } else { 2105 e.envc--; 2106 e.condc--; 2107 left = CCS_ENVP_ENTRY; 2108 envp->is_not = is_not; 2109 if (!ccs_parse_envp(left_word + 11, 2110 right_word, envp++)) 2111 goto out; 2112 } 2113 goto store_value; 2114 } 2115 left = ccs_condition_type(left_word); 2116 dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word, 2117 left); 2118 if (left == CCS_MAX_CONDITION_KEYWORD) { 2119 if (!numbers_p) { 2120 e.numbers_count++; 2121 } else { 2122 e.numbers_count--; 2123 left = CCS_NUMBER_UNION; 2124 param->data = left_word; 2125 if (*left_word == '@' || 2126 !ccs_parse_number_union(param, 2127 numbers_p++)) 2128 goto out; 2129 } 2130 } 2131 if (!condp) 2132 e.condc++; 2133 else 2134 e.condc--; 2135 if (left == CCS_EXEC_REALPATH || left == CCS_SYMLINK_TARGET) { 2136 if (!names_p) { 2137 e.names_count++; 2138 } else { 2139 e.names_count--; 2140 right = CCS_NAME_UNION; 2141 param->data = right_word; 2142 if (!ccs_parse_name_union_quoted(param, 2143 names_p++)) 2144 goto out; 2145 } 2146 goto store_value; 2147 } 2148 right = ccs_condition_type(right_word); 2149 if (right == CCS_MAX_CONDITION_KEYWORD) { 2150 if (!numbers_p) { 2151 e.numbers_count++; 2152 } else { 2153 e.numbers_count--; 2154 right = CCS_NUMBER_UNION; 2155 param->data = right_word; 2156 if (!ccs_parse_number_union(param, 2157 numbers_p++)) 2158 goto out; 2159 } 2160 } 2161 store_value: 2162 if (!condp) { 2163 dprintk(KERN_WARNING "%u: dry_run left=%u right=%u " 2164 "match=%u\n", __LINE__, left, right, !is_not); 2165 continue; 2166 } 2167 condp->left = left; 2168 condp->right = right; 2169 condp->equals = !is_not; 2170 dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n", 2171 __LINE__, condp->left, condp->right, 2172 condp->equals); 2173 condp++; 2174 } 2175 dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n", 2176 __LINE__, e.condc, e.numbers_count, e.names_count, e.argc, 2177 e.envc); 2178 if (entry) { 2179 BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc | 2180 e.condc); 2181 return ccs_commit_condition(entry); 2182 } 2183 e.size = sizeof(*entry) 2184 + e.condc * sizeof(struct ccs_condition_element) 2185 + e.numbers_count * sizeof(struct ccs_number_union) 2186 + e.names_count * sizeof(struct ccs_name_union) 2187 + e.argc * sizeof(struct ccs_argv) 2188 + e.envc * sizeof(struct ccs_envp); 2189 entry = kzalloc(e.size, CCS_GFP_FLAGS); 2190 if (!entry) 2191 goto out2; 2192 *entry = e; 2193 e.transit = NULL; 2194 condp = (struct ccs_condition_element *) (entry + 1); 2195 numbers_p = (struct ccs_number_union *) (condp + e.condc); 2196 names_p = (struct ccs_name_union *) (numbers_p + e.numbers_count); 2197 argv = (struct ccs_argv *) (names_p + e.names_count); 2198 envp = (struct ccs_envp *) (argv + e.argc); 2199 { 2200 bool flag = false; 2201 for (pos = start_of_string; pos < end_of_string; pos++) { 2202 if (*pos) 2203 continue; 2204 if (flag) /* Restore " ". */ 2205 *pos = ' '; 2206 else if (*(pos + 1) == '=') /* Restore "!=". */ 2207 *pos = '!'; 2208 else /* Restore "=". */ 2209 *pos = '='; 2210 flag = !flag; 2211 } 2212 } 2213 goto rerun; 2214 out: 2215 dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__); 2216 if (entry) { 2217 ccs_del_condition(&entry->head.list); 2218 kfree(entry); 2219 } 2220 out2: 2221 ccs_put_name(e.transit); 2222 return NULL; 2223 } 2224 2225 /** 2226 * ccs_yesno - Return "yes" or "no". 2227 * 2228 * @value: Bool value. 2229 * 2230 * Returns "yes" if @value is not 0, "no" otherwise. 2231 */ 2232 static const char *ccs_yesno(const unsigned int value) 2233 { 2234 return value ? "yes" : "no"; 2235 } 2236 2237 /** 2238 * ccs_addprintf - strncat()-like-snprintf(). 2239 * 2240 * @buffer: Buffer to write to. Must be '\0'-terminated. 2241 * @len: Size of @buffer. 2242 * @fmt: The printf()'s format string, followed by parameters. 2243 * 2244 * Returns nothing. 2245 */ 2246 static void ccs_addprintf(char *buffer, int len, const char *fmt, ...) 2247 { 2248 va_list args; 2249 const int pos = strlen(buffer); 2250 va_start(args, fmt); 2251 vsnprintf(buffer + pos, len - pos - 1, fmt, args); 2252 va_end(args); 2253 } 2254 2255 /** 2256 * ccs_flush - Flush queued string to userspace's buffer. 2257 * 2258 * @head: Pointer to "struct ccs_io_buffer". 2259 * 2260 * Returns true if all data was flushed, false otherwise. 2261 */ 2262 static bool ccs_flush(struct ccs_io_buffer *head) 2263 { 2264 while (head->r.w_pos) { 2265 const char *w = head->r.w[0]; 2266 size_t len = strlen(w); 2267 if (len) { 2268 if (len > head->read_user_buf_avail) 2269 len = head->read_user_buf_avail; 2270 if (!len) 2271 return false; 2272 if (copy_to_user(head->read_user_buf, w, len)) 2273 return false; 2274 head->read_user_buf_avail -= len; 2275 head->read_user_buf += len; 2276 w += len; 2277 } 2278 head->r.w[0] = w; 2279 if (*w) 2280 return false; 2281 /* Add '\0' for audit logs and query. */ 2282 if (head->type == CCS_AUDIT || head->type == CCS_QUERY) { 2283 if (!head->read_user_buf_avail || 2284 copy_to_user(head->read_user_buf, "", 1)) 2285 return false; 2286 head->read_user_buf_avail--; 2287 head->read_user_buf++; 2288 } 2289 head->r.w_pos--; 2290 for (len = 0; len < head->r.w_pos; len++) 2291 head->r.w[len] = head->r.w[len + 1]; 2292 } 2293 head->r.avail = 0; 2294 return true; 2295 } 2296 2297 /** 2298 * ccs_set_string - Queue string to "struct ccs_io_buffer" structure. 2299 * 2300 * @head: Pointer to "struct ccs_io_buffer". 2301 * @string: String to print. 2302 * 2303 * Returns nothing. 2304 * 2305 * Note that @string has to be kept valid until @head is kfree()d. 2306 * This means that char[] allocated on stack memory cannot be passed to 2307 * this function. Use ccs_io_printf() for char[] allocated on stack memory. 2308 */ 2309 static void ccs_set_string(struct ccs_io_buffer *head, const char *string) 2310 { 2311 if (head->r.w_pos < CCS_MAX_IO_READ_QUEUE) { 2312 head->r.w[head->r.w_pos++] = string; 2313 ccs_flush(head); 2314 } else 2315 printk(KERN_WARNING "Too many words in a line.\n"); 2316 } 2317 2318 /** 2319 * ccs_io_printf - printf() to "struct ccs_io_buffer" structure. 2320 * 2321 * @head: Pointer to "struct ccs_io_buffer". 2322 * @fmt: The printf()'s format string, followed by parameters. 2323 * 2324 * Returns nothing. 2325 */ 2326 static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...) 2327 { 2328 va_list args; 2329 size_t len; 2330 size_t pos = head->r.avail; 2331 int size = head->readbuf_size - pos; 2332 if (size <= 0) 2333 return; 2334 va_start(args, fmt); 2335 len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1; 2336 va_end(args); 2337 if (pos + len >= head->readbuf_size) { 2338 printk(KERN_WARNING "Too many words in a line.\n"); 2339 return; 2340 } 2341 head->r.avail += len; 2342 ccs_set_string(head, head->read_buf + pos); 2343 } 2344 2345 /** 2346 * ccs_set_space - Put a space to "struct ccs_io_buffer" structure. 2347 * 2348 * @head: Pointer to "struct ccs_io_buffer". 2349 * 2350 * Returns nothing. 2351 */ 2352 static void ccs_set_space(struct ccs_io_buffer *head) 2353 { 2354 ccs_set_string(head, " "); 2355 } 2356 2357 /** 2358 * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure. 2359 * 2360 * @head: Pointer to "struct ccs_io_buffer". 2361 * 2362 * Returns true if all data was flushed, false otherwise. 2363 */ 2364 static bool ccs_set_lf(struct ccs_io_buffer *head) 2365 { 2366 ccs_set_string(head, "\n"); 2367 return !head->r.w_pos; 2368 } 2369 2370 /** 2371 * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure. 2372 * 2373 * @head: Pointer to "struct ccs_io_buffer". 2374 * 2375 * Returns nothing. 2376 */ 2377 static void ccs_set_slash(struct ccs_io_buffer *head) 2378 { 2379 ccs_set_string(head, "/"); 2380 } 2381 2382 /** 2383 * ccs_init_policy_namespace - Initialize namespace. 2384 * 2385 * @ns: Pointer to "struct ccs_policy_namespace". 2386 * 2387 * Returns nothing. 2388 */ 2389 static void ccs_init_policy_namespace(struct ccs_policy_namespace *ns) 2390 { 2391 unsigned int idx; 2392 for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++) 2393 INIT_LIST_HEAD(&ns->acl_group[idx]); 2394 for (idx = 0; idx < CCS_MAX_GROUP; idx++) 2395 INIT_LIST_HEAD(&ns->group_list[idx]); 2396 for (idx = 0; idx < CCS_MAX_POLICY; idx++) 2397 INIT_LIST_HEAD(&ns->policy_list[idx]); 2398 ns->profile_version = 20150505; 2399 ccs_namespace_enabled = !list_empty(&ccs_namespace_list); 2400 list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list); 2401 } 2402 2403 /** 2404 * ccs_print_namespace - Print namespace header. 2405 * 2406 * @head: Pointer to "struct ccs_io_buffer". 2407 * 2408 * Returns nothing. 2409 */ 2410 static void ccs_print_namespace(struct ccs_io_buffer *head) 2411 { 2412 if (!ccs_namespace_enabled) 2413 return; 2414 ccs_set_string(head, 2415 container_of(head->r.ns, struct ccs_policy_namespace, 2416 namespace_list)->name); 2417 ccs_set_space(head); 2418 } 2419 2420 /** 2421 * ccs_assign_profile - Create a new profile. 2422 * 2423 * @ns: Pointer to "struct ccs_policy_namespace". 2424 * @profile: Profile number to create. 2425 * 2426 * Returns pointer to "struct ccs_profile" on success, NULL otherwise. 2427 */ 2428 static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns, 2429 const unsigned int profile) 2430 { 2431 struct ccs_profile *ptr; 2432 struct ccs_profile *entry; 2433 if (profile >= CCS_MAX_PROFILES) 2434 return NULL; 2435 ptr = ns->profile_ptr[profile]; 2436 if (ptr) 2437 return ptr; 2438 entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS); 2439 if (mutex_lock_interruptible(&ccs_policy_lock)) 2440 goto out; 2441 ptr = ns->profile_ptr[profile]; 2442 if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) { 2443 ptr = entry; 2444 ptr->default_config = CCS_CONFIG_DISABLED | 2445 CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG; 2446 memset(ptr->config, CCS_CONFIG_USE_DEFAULT, 2447 sizeof(ptr->config)); 2448 ptr->pref[CCS_PREF_MAX_AUDIT_LOG] = 2449 CONFIG_CCSECURITY_MAX_AUDIT_LOG; 2450 ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] = 2451 CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY; 2452 mb(); /* Avoid out-of-order execution. */ 2453 ns->profile_ptr[profile] = ptr; 2454 entry = NULL; 2455 } 2456 mutex_unlock(&ccs_policy_lock); 2457 out: 2458 kfree(entry); 2459 return ptr; 2460 } 2461 2462 /** 2463 * ccs_check_profile - Check all profiles currently assigned to domains are defined. 2464 * 2465 * Returns nothing. 2466 */ 2467 static void ccs_check_profile(void) 2468 { 2469 struct ccs_domain_info *domain; 2470 const int idx = ccs_read_lock(); 2471 ccs_policy_loaded = true; 2472 printk(KERN_INFO "CCSecurity: 1.8.6+ 2020/04/13\n"); 2473 list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) { 2474 const u8 profile = domain->profile; 2475 struct ccs_policy_namespace *ns = domain->ns; 2476 if (ns->profile_version == 20100903) { 2477 static bool done; 2478 if (!done) 2479 printk(KERN_INFO "Converting profile version " 2480 "from %u to %u.\n", 20100903, 20150505); 2481 done = true; 2482 ns->profile_version = 20150505; 2483 } 2484 if (ns->profile_version != 20150505) 2485 printk(KERN_ERR 2486 "Profile version %u is not supported.\n", 2487 ns->profile_version); 2488 else if (!ns->profile_ptr[profile]) 2489 printk(KERN_ERR 2490 "Profile %u (used by '%s') is not defined.\n", 2491 profile, domain->domainname->name); 2492 else 2493 continue; 2494 printk(KERN_ERR 2495 "Userland tools for TOMOYO 1.8 must be installed and " 2496 "policy must be initialized.\n"); 2497 printk(KERN_ERR "Please see https://tomoyo.osdn.jp/1.8/ " 2498 "for more information.\n"); 2499 panic("STOP!"); 2500 } 2501 ccs_read_unlock(idx); 2502 printk(KERN_INFO "Mandatory Access Control activated.\n"); 2503 } 2504 2505 /** 2506 * ccs_profile - Find a profile. 2507 * 2508 * @profile: Profile number to find. 2509 * 2510 * Returns pointer to "struct ccs_profile". 2511 */ 2512 static struct ccs_profile *ccs_profile(const u8 profile) 2513 { 2514 static struct ccs_profile ccs_null_profile; 2515 struct ccs_profile *ptr = ccs_current_namespace()-> 2516 profile_ptr[profile]; 2517 if (!ptr) 2518 ptr = &ccs_null_profile; 2519 return ptr; 2520 } 2521 2522 /** 2523 * ccs_get_config - Get config for specified profile's specified functionality. 2524 * 2525 * @profile: Profile number. 2526 * @index: Index number of functionality. 2527 * 2528 * Returns config. 2529 * 2530 * First, check for CONFIG::category::functionality. 2531 * If CONFIG::category::functionality is set to use default, then check 2532 * CONFIG::category. If CONFIG::category is set to use default, then use 2533 * CONFIG. CONFIG cannot be set to use default. 2534 */ 2535 u8 ccs_get_config(const u8 profile, const u8 index) 2536 { 2537 u8 config; 2538 const struct ccs_profile *p; 2539 if (!ccs_policy_loaded) 2540 return CCS_CONFIG_DISABLED; 2541 p = ccs_profile(profile); 2542 config = p->config[index]; 2543 if (config == CCS_CONFIG_USE_DEFAULT) 2544 config = p->config[ccs_index2category[index] 2545 + CCS_MAX_MAC_INDEX]; 2546 if (config == CCS_CONFIG_USE_DEFAULT) 2547 config = p->default_config; 2548 return config; 2549 } 2550 2551 /** 2552 * ccs_find_yesno - Find values for specified keyword. 2553 * 2554 * @string: String to check. 2555 * @find: Name of keyword. 2556 * 2557 * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise. 2558 */ 2559 static s8 ccs_find_yesno(const char *string, const char *find) 2560 { 2561 const char *cp = strstr(string, find); 2562 if (cp) { 2563 cp += strlen(find); 2564 if (!strncmp(cp, "=yes", 4)) 2565 return 1; 2566 else if (!strncmp(cp, "=no", 3)) 2567 return 0; 2568 } 2569 return -1; 2570 } 2571 2572 /** 2573 * ccs_set_uint - Set value for specified preference. 2574 * 2575 * @i: Pointer to "unsigned int". 2576 * @string: String to check. 2577 * @find: Name of keyword. 2578 * 2579 * Returns nothing. 2580 */ 2581 static void ccs_set_uint(unsigned int *i, const char *string, const char *find) 2582 { 2583 const char *cp = strstr(string, find); 2584 if (cp) 2585 sscanf(cp + strlen(find), "=%u", i); 2586 } 2587 2588 /** 2589 * ccs_str_starts - Check whether the given string starts with the given keyword. 2590 * 2591 * @src: Pointer to pointer to the string. 2592 * @find: Pointer to the keyword. 2593 * 2594 * Returns true if @src starts with @find, false otherwise. 2595 * 2596 * The @src is updated to point the first character after the @find 2597 * if @src starts with @find. 2598 */ 2599 static bool ccs_str_starts(char **src, const char *find) 2600 { 2601 const int len = strlen(find); 2602 char *tmp = *src; 2603 if (strncmp(tmp, find, len)) 2604 return false; 2605 tmp += len; 2606 *src = tmp; 2607 return true; 2608 } 2609 2610 /** 2611 * ccs_print_group - Print group's name. 2612 * 2613 * @head: Pointer to "struct ccs_io_buffer". 2614 * @group: Pointer to "struct ccsgroup". Maybe NULL. 2615 * 2616 * Returns true if @group is not NULL. false otherwise. 2617 */ 2618 static bool ccs_print_group(struct ccs_io_buffer *head, 2619 const struct ccs_group *group) 2620 { 2621 if (group) { 2622 ccs_set_string(head, "@"); 2623 ccs_set_string(head, group->group_name->name); 2624 return true; 2625 } 2626 return false; 2627 } 2628 2629 /** 2630 * ccs_set_mode - Set mode for specified profile. 2631 * 2632 * @name: Name of functionality. 2633 * @value: Mode for @name. 2634 * @profile: Pointer to "struct ccs_profile". 2635 * 2636 * Returns 0 on success, negative value otherwise. 2637 */ 2638 static int ccs_set_mode(char *name, const char *value, 2639 struct ccs_profile *profile) 2640 { 2641 u8 i; 2642 u8 config; 2643 if (!strcmp(name, "CONFIG")) { 2644 i = CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX; 2645 config = profile->default_config; 2646 } else if (ccs_str_starts(&name, "CONFIG::")) { 2647 config = 0; 2648 for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX; 2649 i++) { 2650 int len = 0; 2651 if (i < CCS_MAX_MAC_INDEX) { 2652 const u8 c = ccs_index2category[i]; 2653 const char *category = 2654 ccs_category_keywords[c]; 2655 len = strlen(category); 2656 if (strncmp(name, category, len) || 2657 name[len++] != ':' || name[len++] != ':') 2658 continue; 2659 } 2660 if (strcmp(name + len, ccs_mac_keywords[i])) 2661 continue; 2662 config = profile->config[i]; 2663 break; 2664 } 2665 if (i == CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX) 2666 return -EINVAL; 2667 } else { 2668 return -EINVAL; 2669 } 2670 if (strstr(value, "use_default")) { 2671 config = CCS_CONFIG_USE_DEFAULT; 2672 } else { 2673 u8 mode; 2674 for (mode = 0; mode < CCS_CONFIG_MAX_MODE; mode++) 2675 if (strstr(value, ccs_mode[mode])) 2676 /* 2677 * Update lower 3 bits in order to distinguish 2678 * 'config' from 'CCS_CONFIG_USE_DEAFULT'. 2679 */ 2680 config = (config & ~7) | mode; 2681 if (config != CCS_CONFIG_USE_DEFAULT) { 2682 switch (ccs_find_yesno(value, "grant_log")) { 2683 case 1: 2684 config |= CCS_CONFIG_WANT_GRANT_LOG; 2685 break; 2686 case 0: 2687 config &= ~CCS_CONFIG_WANT_GRANT_LOG; 2688 break; 2689 } 2690 switch (ccs_find_yesno(value, "reject_log")) { 2691 case 1: 2692 config |= CCS_CONFIG_WANT_REJECT_LOG; 2693 break; 2694 case 0: 2695 config &= ~CCS_CONFIG_WANT_REJECT_LOG; 2696 break; 2697 } 2698 } 2699 } 2700 if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX) 2701 profile->config[i] = config; 2702 else if (config != CCS_CONFIG_USE_DEFAULT) 2703 profile->default_config = config; 2704 return 0; 2705 } 2706 2707 /** 2708 * ccs_write_profile - Write profile table. 2709 * 2710 * @head: Pointer to "struct ccs_io_buffer". 2711 * 2712 * Returns 0 on success, negative value otherwise. 2713 */ 2714 static int ccs_write_profile(struct ccs_io_buffer *head) 2715 { 2716 char *data = head->write_buf; 2717 unsigned int i; 2718 char *cp; 2719 struct ccs_profile *profile; 2720 if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version) 2721 == 1) 2722 return 0; 2723 i = simple_strtoul(data, &cp, 10); 2724 if (*cp != '-') 2725 return -EINVAL; 2726 data = cp + 1; 2727 profile = ccs_assign_profile(head->w.ns, i); 2728 if (!profile) 2729 return -EINVAL; 2730 cp = strchr(data, '='); 2731 if (!cp) 2732 return -EINVAL; 2733 *cp++ = '\0'; 2734 if (!strcmp(data, "COMMENT")) { 2735 static DEFINE_SPINLOCK(lock); 2736 const struct ccs_path_info *new_comment = ccs_get_name(cp); 2737 const struct ccs_path_info *old_comment; 2738 if (!new_comment) 2739 return -ENOMEM; 2740 spin_lock(&lock); 2741 old_comment = profile->comment; 2742 profile->comment = new_comment; 2743 spin_unlock(&lock); 2744 ccs_put_name(old_comment); 2745 return 0; 2746 } 2747 if (!strcmp(data, "PREFERENCE")) { 2748 for (i = 0; i < CCS_MAX_PREF; i++) 2749 ccs_set_uint(&profile->pref[i], cp, 2750 ccs_pref_keywords[i]); 2751 return 0; 2752 } 2753 return ccs_set_mode(data, cp, profile); 2754 } 2755 2756 /** 2757 * ccs_print_config - Print mode for specified functionality. 2758 * 2759 * @head: Pointer to "struct ccs_io_buffer". 2760 * @config: Mode for that functionality. 2761 * 2762 * Returns nothing. 2763 * 2764 * Caller prints functionality's name. 2765 */ 2766 static void ccs_print_config(struct ccs_io_buffer *head, const u8 config) 2767 { 2768 ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n", 2769 ccs_mode[config & 3], 2770 ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG), 2771 ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG)); 2772 } 2773 2774 /** 2775 * ccs_read_profile - Read profile table. 2776 * 2777 * @head: Pointer to "struct ccs_io_buffer". 2778 * 2779 * Returns nothing. 2780 */ 2781 static void ccs_read_profile(struct ccs_io_buffer *head) 2782 { 2783 u8 index; 2784 struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns), 2785 namespace_list); 2786 const struct ccs_profile *profile; 2787 if (head->r.eof) 2788 return; 2789 next: 2790 index = head->r.index; 2791 profile = ns->profile_ptr[index]; 2792 switch (head->r.step) { 2793 case 0: 2794 ccs_print_namespace(head); 2795 ccs_io_printf(head, "PROFILE_VERSION=%u\n", 2796 ns->profile_version); 2797 head->r.step++; 2798 break; 2799 case 1: 2800 for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++) 2801 if (ns->profile_ptr[head->r.index]) 2802 break; 2803 if (head->r.index == CCS_MAX_PROFILES) { 2804 head->r.eof = true; 2805 return; 2806 } 2807 head->r.step++; 2808 break; 2809 case 2: 2810 { 2811 u8 i; 2812 const struct ccs_path_info *comment = profile->comment; 2813 ccs_print_namespace(head); 2814 ccs_io_printf(head, "%u-COMMENT=", index); 2815 ccs_set_string(head, comment ? comment->name : ""); 2816 ccs_set_lf(head); 2817 ccs_print_namespace(head); 2818 ccs_io_printf(head, "%u-PREFERENCE={ ", index); 2819 for (i = 0; i < CCS_MAX_PREF; i++) 2820 ccs_io_printf(head, "%s=%u ", 2821 ccs_pref_keywords[i], 2822 profile->pref[i]); 2823 ccs_set_string(head, "}\n"); 2824 head->r.step++; 2825 } 2826 break; 2827 case 3: 2828 { 2829 ccs_print_namespace(head); 2830 ccs_io_printf(head, "%u-%s", index, "CONFIG"); 2831 ccs_print_config(head, profile->default_config); 2832 head->r.bit = 0; 2833 head->r.step++; 2834 } 2835 break; 2836 case 4: 2837 for ( ; head->r.bit < CCS_MAX_MAC_INDEX 2838 + CCS_MAX_MAC_CATEGORY_INDEX; head->r.bit++) { 2839 const u8 i = head->r.bit; 2840 const u8 config = profile->config[i]; 2841 if (config == CCS_CONFIG_USE_DEFAULT) 2842 continue; 2843 ccs_print_namespace(head); 2844 if (i < CCS_MAX_MAC_INDEX) 2845 ccs_io_printf(head, "%u-CONFIG::%s::%s", index, 2846 ccs_category_keywords 2847 [ccs_index2category[i]], 2848 ccs_mac_keywords[i]); 2849 else 2850 ccs_io_printf(head, "%u-CONFIG::%s", index, 2851 ccs_mac_keywords[i]); 2852 ccs_print_config(head, config); 2853 head->r.bit++; 2854 break; 2855 } 2856 if (head->r.bit == CCS_MAX_MAC_INDEX 2857 + CCS_MAX_MAC_CATEGORY_INDEX) { 2858 head->r.index++; 2859 head->r.step = 1; 2860 } 2861 break; 2862 } 2863 if (ccs_flush(head)) 2864 goto next; 2865 } 2866 2867 /** 2868 * ccs_update_policy - Update an entry for exception policy. 2869 * 2870 * @size: Size of new entry in bytes. 2871 * @param: Pointer to "struct ccs_acl_param". 2872 * 2873 * Returns 0 on success, negative value otherwise. 2874 * 2875 * Caller holds ccs_read_lock(). 2876 */ 2877 static int ccs_update_policy(const int size, struct ccs_acl_param *param) 2878 { 2879 struct ccs_acl_head *new_entry = ¶m->e.acl_head; 2880 int error = param->is_delete ? -ENOENT : -ENOMEM; 2881 struct ccs_acl_head *entry; 2882 struct list_head *list = param->list; 2883 BUG_ON(size < sizeof(*entry)); 2884 if (mutex_lock_interruptible(&ccs_policy_lock)) 2885 return -ENOMEM; 2886 list_for_each_entry_srcu(entry, list, list, &ccs_ss) { 2887 if (entry->is_deleted == CCS_GC_IN_PROGRESS) 2888 continue; 2889 if (memcmp(entry + 1, new_entry + 1, size - sizeof(*entry))) 2890 continue; 2891 entry->is_deleted = param->is_delete; 2892 error = 0; 2893 break; 2894 } 2895 if (error && !param->is_delete) { 2896 entry = ccs_commit_ok(new_entry, size); 2897 if (entry) { 2898 list_add_tail_rcu(&entry->list, list); 2899 error = 0; 2900 } 2901 } 2902 mutex_unlock(&ccs_policy_lock); 2903 return error; 2904 } 2905 2906 /** 2907 * ccs_update_manager_entry - Add a manager entry. 2908 * 2909 * @manager: The path to manager or the domainnamme. 2910 * @is_delete: True if it is a delete request. 2911 * 2912 * Returns 0 on success, negative value otherwise. 2913 */ 2914 static int ccs_update_manager_entry(const char *manager, 2915 const bool is_delete) 2916 { 2917 struct ccs_acl_param param = { 2918 /* .ns = &ccs_kernel_namespace, */ 2919 .is_delete = is_delete, 2920 .list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER], 2921 }; 2922 struct ccs_manager *e = ¶m.e.manager; 2923 int error = is_delete ? -ENOENT : -ENOMEM; 2924 /* Forced zero clear for using memcmp() at ccs_update_policy(). */ 2925 memset(¶m.e, 0, sizeof(param.e)); 2926 if (!ccs_correct_domain(manager) && !ccs_correct_word(manager)) 2927 return -EINVAL; 2928 e->manager = ccs_get_name(manager); 2929 if (e->manager) { 2930 error = ccs_update_policy(sizeof(*e), ¶m); 2931 ccs_put_name(e->manager); 2932 } 2933 return error; 2934 } 2935 2936 /** 2937 * ccs_write_manager - Write manager policy. 2938 * 2939 * @head: Pointer to "struct ccs_io_buffer". 2940 * 2941 * Returns 0 on success, negative value otherwise. 2942 */ 2943 static int ccs_write_manager(struct ccs_io_buffer *head) 2944 { 2945 const char *data = head->write_buf; 2946 if (!strcmp(data, "manage_by_non_root")) { 2947 ccs_manage_by_non_root = !head->w.is_delete; 2948 return 0; 2949 } 2950 return ccs_update_manager_entry(data, head->w.is_delete); 2951 } 2952 2953 /** 2954 * ccs_read_manager - Read manager policy. 2955 * 2956 * @head: Pointer to "struct ccs_io_buffer". 2957 * 2958 * Returns nothing. 2959 * 2960 * Caller holds ccs_read_lock(). 2961 */ 2962 static void ccs_read_manager(struct ccs_io_buffer *head) 2963 { 2964 if (head->r.eof) 2965 return; 2966 list_for_each_cookie(head->r.acl, &ccs_kernel_namespace. 2967 policy_list[CCS_ID_MANAGER]) { 2968 struct ccs_manager *ptr = 2969 list_entry(head->r.acl, typeof(*ptr), head.list); 2970 if (ptr->head.is_deleted) 2971 continue; 2972 if (!ccs_flush(head)) 2973 return; 2974 ccs_set_string(head, ptr->manager->name); 2975 ccs_set_lf(head); 2976 } 2977 head->r.eof = true; 2978 } 2979 2980 /** 2981 * ccs_manager - Check whether the current process is a policy manager. 2982 * 2983 * Returns true if the current process is permitted to modify policy 2984 * via /proc/ccs/ interface. 2985 * 2986 * Caller holds ccs_read_lock(). 2987 */ 2988 static bool ccs_manager(void) 2989 { 2990 struct ccs_manager *ptr; 2991 struct ccs_path_info exe; 2992 struct ccs_security *task = ccs_current_security(); 2993 const struct ccs_path_info *domainname 2994 = ccs_current_domain()->domainname; 2995 bool found = false; 2996 if (!ccs_policy_loaded) 2997 return true; 2998 if (task->ccs_flags & CCS_TASK_IS_MANAGER) 2999 return true; 3000 if (!ccs_manage_by_non_root && 3001 (!uid_eq(current_uid(), GLOBAL_ROOT_UID) || 3002 !uid_eq(current_euid(), GLOBAL_ROOT_UID))) 3003 return false; 3004 exe.name = ccs_get_exe(); 3005 if (!exe.name) 3006 return false; 3007 ccs_fill_path_info(&exe); 3008 list_for_each_entry_srcu(ptr, &ccs_kernel_namespace. 3009 policy_list[CCS_ID_MANAGER], head.list, 3010 &ccs_ss) { 3011 if (ptr->head.is_deleted) 3012 continue; 3013 if (ccs_pathcmp(domainname, ptr->manager) && 3014 ccs_pathcmp(&exe, ptr->manager)) 3015 continue; 3016 /* Set manager flag. */ 3017 task->ccs_flags |= CCS_TASK_IS_MANAGER; 3018 found = true; 3019 break; 3020 } 3021 if (!found) { /* Reduce error messages. */ 3022 static pid_t ccs_last_pid; 3023 const pid_t pid = current->pid; 3024 if (ccs_last_pid != pid) { 3025 printk(KERN_WARNING "%s ( %s ) is not permitted to " 3026 "update policies.\n", domainname->name, 3027 exe.name); 3028 ccs_last_pid = pid; 3029 } 3030 } 3031 kfree(exe.name); 3032 return found; 3033 } 3034 3035 /** 3036 * ccs_find_domain - Find a domain by the given name. 3037 * 3038 * @domainname: The domainname to find. 3039 * 3040 * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise. 3041 * 3042 * Caller holds ccs_read_lock(). 3043 */ 3044 static struct ccs_domain_info *ccs_find_domain(const char *domainname) 3045 { 3046 struct ccs_domain_info *domain; 3047 struct ccs_path_info name; 3048 name.name = domainname; 3049 ccs_fill_path_info(&name); 3050 list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) { 3051 if (!domain->is_deleted && 3052 !ccs_pathcmp(&name, domain->domainname)) 3053 return domain; 3054 } 3055 return NULL; 3056 } 3057 3058 /** 3059 * ccs_select_domain - Parse select command. 3060 * 3061 * @head: Pointer to "struct ccs_io_buffer". 3062 * @data: String to parse. 3063 * 3064 * Returns true on success, false otherwise. 3065 * 3066 * Caller holds ccs_read_lock(). 3067 */ 3068 static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data) 3069 { 3070 unsigned int pid; 3071 struct ccs_domain_info *domain = NULL; 3072 bool global_pid = false; 3073 if (strncmp(data, "select ", 7)) 3074 return false; 3075 data += 7; 3076 if (sscanf(data, "pid=%u", &pid) == 1 || 3077 (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { 3078 struct task_struct *p; 3079 ccs_tasklist_lock(); 3080 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) 3081 if (global_pid) 3082 p = ccsecurity_exports.find_task_by_pid_ns(pid, 3083 &init_pid_ns); 3084 else 3085 p = ccsecurity_exports.find_task_by_vpid(pid); 3086 #else 3087 p = find_task_by_pid(pid); 3088 #endif 3089 if (p) 3090 domain = ccs_task_domain(p); 3091 ccs_tasklist_unlock(); 3092 } else if (!strncmp(data, "domain=", 7)) { 3093 if (*(data + 7) == '<') 3094 domain = ccs_find_domain(data + 7); 3095 } else if (sscanf(data, "Q=%u", &pid) == 1) { 3096 domain = ccs_find_domain_by_qid(pid); 3097 } else 3098 return false; 3099 head->w.domain = domain; 3100 /* Accessing read_buf is safe because head->io_sem is held. */ 3101 if (!head->read_buf) 3102 return true; /* Do nothing if open(O_WRONLY). */ 3103 memset(&head->r, 0, sizeof(head->r)); 3104 head->r.print_this_domain_only = true; 3105 if (domain) 3106 head->r.domain = &domain->list; 3107 else 3108 head->r.eof = true; 3109 ccs_io_printf(head, "# select %s\n", data); 3110 if (domain && domain->is_deleted) 3111 ccs_set_string(head, "# This is a deleted domain.\n"); 3112 return true; 3113 } 3114 3115 /** 3116 * ccs_update_acl - Update "struct ccs_acl_info" entry. 3117 * 3118 * @size: Size of new entry in bytes. 3119 * @param: Pointer to "struct ccs_acl_param". 3120 * 3121 * Returns 0 on success, negative value otherwise. 3122 * 3123 * Caller holds ccs_read_lock(). 3124 */ 3125 static int ccs_update_acl(const int size, struct ccs_acl_param *param) 3126 { 3127 struct ccs_acl_info *new_entry = ¶m->e.acl_info; 3128 const bool is_delete = param->is_delete; 3129 int error = is_delete ? -ENOENT : -ENOMEM; 3130 struct ccs_acl_info *entry; 3131 struct list_head * const list = param->list; 3132 BUG_ON(size < sizeof(*entry)); 3133 if (param->data[0]) { 3134 new_entry->cond = ccs_get_condition(param); 3135 if (!new_entry->cond) 3136 return -EINVAL; 3137 /* 3138 * Domain transition preference is allowed for only 3139 * "file execute"/"task auto_execute_handler"/ 3140 * "task denied_auto_execute_handler" entries. 3141 */ 3142 if (new_entry->cond->exec_transit && 3143 !(new_entry->type == CCS_TYPE_PATH_ACL && 3144 new_entry->perm == 1 << CCS_TYPE_EXECUTE) 3145 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER 3146 && new_entry->type != CCS_TYPE_AUTO_EXECUTE_HANDLER && 3147 new_entry->type != CCS_TYPE_DENIED_EXECUTE_HANDLER 3148 #endif 3149 ) 3150 return -EINVAL; 3151 } 3152 if (mutex_lock_interruptible(&ccs_policy_lock)) 3153 return -ENOMEM; 3154 list_for_each_entry_srcu(entry, list, list, &ccs_ss) { 3155 if (entry->is_deleted == CCS_GC_IN_PROGRESS) 3156 continue; 3157 if (entry->type != new_entry->type || 3158 entry->cond != new_entry->cond || 3159 memcmp(entry + 1, new_entry + 1, size - sizeof(*entry))) 3160 continue; 3161 if (is_delete) 3162 entry->perm &= ~new_entry->perm; 3163 else 3164 entry->perm |= new_entry->perm; 3165 entry->is_deleted = !entry->perm; 3166 error = 0; 3167 break; 3168 } 3169 if (error && !is_delete) { 3170 entry = ccs_commit_ok(new_entry, size); 3171 if (entry) { 3172 list_add_tail_rcu(&entry->list, list); 3173 error = 0; 3174 } 3175 } 3176 mutex_unlock(&ccs_policy_lock); 3177 return error; 3178 } 3179 3180 /** 3181 * ccs_permstr - Find permission keywords. 3182 * 3183 * @string: String representation for permissions in foo/bar/buz format. 3184 * @keyword: Keyword to find from @string/ 3185 * 3186 * Returns true if @keyword was found in @string, false otherwise. 3187 * 3188 * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2. 3189 */ 3190 static bool ccs_permstr(const char *string, const char *keyword) 3191 { 3192 const char *cp = strstr(string, keyword); 3193 if (cp) 3194 return cp == string || *(cp - 1) == '/'; 3195 return false; 3196 } 3197 3198 /** 3199 * ccs_write_task - Update task related list. 3200 * 3201 * @param: Pointer to "struct ccs_acl_param". 3202 * 3203 * Returns 0 on success, negative value otherwise. 3204 * 3205 * Caller holds ccs_read_lock(). 3206 */ 3207 static int ccs_write_task(struct ccs_acl_param *param) 3208 { 3209 int error; 3210 const bool is_auto = ccs_str_starts(¶m->data, 3211 "auto_domain_transition "); 3212 if (!is_auto && !ccs_str_starts(¶m->data, 3213 "manual_domain_transition ")) { 3214 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER 3215 struct ccs_handler_acl *e = ¶m->e.handler_acl; 3216 char *handler; 3217 if (ccs_str_starts(¶m->data, "auto_execute_handler ")) 3218 e->head.type = CCS_TYPE_AUTO_EXECUTE_HANDLER; 3219 else if (ccs_str_starts(¶m->data, 3220 "denied_execute_handler ")) 3221 e->head.type = CCS_TYPE_DENIED_EXECUTE_HANDLER; 3222 else 3223 return -EINVAL; 3224 handler = ccs_read_token(param); 3225 if (!ccs_correct_path(handler)) 3226 return -EINVAL; 3227 e->handler = ccs_get_name(handler); 3228 if (!e->handler) 3229 return -ENOMEM; 3230 if (e->handler->is_patterned) 3231 return -EINVAL; /* No patterns allowed. */ 3232 return ccs_update_acl(sizeof(*e), param); 3233 #else 3234 error = -EINVAL; 3235 #endif 3236 } else { 3237 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION 3238 struct ccs_task_acl *e = ¶m->e.task_acl; 3239 e->head.type = is_auto ? 3240 CCS_TYPE_AUTO_TASK_ACL : CCS_TYPE_MANUAL_TASK_ACL; 3241 e->domainname = ccs_get_domainname(param); 3242 if (!e->domainname) 3243 return -EINVAL; 3244 return ccs_update_acl(sizeof(*e), param); 3245 #else 3246 error = -EINVAL; 3247 #endif 3248 } 3249 return error; 3250 } 3251 3252 #ifdef CONFIG_CCSECURITY_NETWORK 3253 3254 /** 3255 * ccs_write_inet_network - Write "struct ccs_inet_acl" list. 3256 * 3257 * @param: Pointer to "struct ccs_acl_param". 3258 * 3259 * Returns 0 on success, negative value otherwise. 3260 * 3261 * Caller holds ccs_read_lock(). 3262 */ 3263 static int ccs_write_inet_network(struct ccs_acl_param *param) 3264 { 3265 struct ccs_inet_acl *e = ¶m->e.inet_acl; 3266 u8 type; 3267 const char *protocol = ccs_read_token(param); 3268 const char *operation = ccs_read_token(param); 3269 e->head.type = CCS_TYPE_INET_ACL; 3270 for (type = 0; type < CCS_SOCK_MAX; type++) 3271 if (!strcmp(protocol, ccs_proto_keyword[type])) 3272 break; 3273 if (type == CCS_SOCK_MAX) 3274 return -EINVAL; 3275 e->protocol = type; 3276 e->head.perm = 0; 3277 for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++) 3278 if (ccs_permstr(operation, ccs_socket_keyword[type])) 3279 e->head.perm |= 1 << type; 3280 if (!e->head.perm) 3281 return -EINVAL; 3282 if (param->data[0] == '@') { 3283 param->data++; 3284 e->address.group = ccs_get_group(param, CCS_ADDRESS_GROUP); 3285 if (!e->address.group) 3286 return -ENOMEM; 3287 } else { 3288 if (!ccs_parse_ipaddr_union(param, &e->address)) 3289 return -EINVAL; 3290 } 3291 if (!ccs_parse_number_union(param, &e->port) || 3292 e->port.values[1] > 65535) 3293 return -EINVAL; 3294 return ccs_update_acl(sizeof(*e), param); 3295 } 3296 3297 /** 3298 * ccs_write_unix_network - Write "struct ccs_unix_acl" list. 3299 * 3300 * @param: Pointer to "struct ccs_acl_param". 3301 * 3302 * Returns 0 on success, negative value otherwise. 3303 */ 3304 static int ccs_write_unix_network(struct ccs_acl_param *param) 3305 { 3306 struct ccs_unix_acl *e = ¶m->e.unix_acl; 3307 u8 type; 3308 const char *protocol = ccs_read_token(param); 3309 const char *operation = ccs_read_token(param); 3310 e->head.type = CCS_TYPE_UNIX_ACL; 3311 for (type = 0; type < CCS_SOCK_MAX; type++) 3312 if (!strcmp(protocol, ccs_proto_keyword[type])) 3313 break; 3314 if (type == CCS_SOCK_MAX) 3315 return -EINVAL; 3316 e->protocol = type; 3317 e->head.perm = 0; 3318 for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++) 3319 if (ccs_permstr(operation, ccs_socket_keyword[type])) 3320 e->head.perm |= 1 << type; 3321 if (!e->head.perm) 3322 return -EINVAL; 3323 if (!ccs_parse_name_union(param, &e->name)) 3324 return -EINVAL; 3325 return ccs_update_acl(sizeof(*e), param); 3326 } 3327 3328 #endif 3329 3330 /** 3331 * ccs_write_file - Update file related list. 3332 * 3333 * @param: Pointer to "struct ccs_acl_param". 3334 * 3335 * Returns 0 on success, negative value otherwise. 3336 * 3337 * Caller holds ccs_read_lock(). 3338 */ 3339 static int ccs_write_file(struct ccs_acl_param *param) 3340 { 3341 u16 perm = 0; 3342 u8 type; 3343 const char *operation = ccs_read_token(param); 3344 for (type = 0; type < CCS_MAX_PATH_OPERATION; type++) 3345 if (ccs_permstr(operation, ccs_path_keyword[type])) 3346 perm |= 1 << type; 3347 if (perm) { 3348 struct ccs_path_acl *e = ¶m->e.path_acl; 3349 e->head.type = CCS_TYPE_PATH_ACL; 3350 e->head.perm = perm; 3351 if (!ccs_parse_name_union(param, &e->name)) 3352 return -EINVAL; 3353 return ccs_update_acl(sizeof(*e), param); 3354 } 3355 for (type = 0; type < CCS_MAX_PATH2_OPERATION; type++) 3356 if (ccs_permstr(operation, ccs_mac_keywords[ccs_pp2mac[type]])) 3357 perm |= 1 << type; 3358 if (perm) { 3359 struct ccs_path2_acl *e = ¶m->e.path2_acl; 3360 e->head.type = CCS_TYPE_PATH2_ACL; 3361 e->head.perm = perm; 3362 if (!ccs_parse_name_union(param, &e->name1) || 3363 !ccs_parse_name_union(param, &e->name2)) 3364 return -EINVAL; 3365 return ccs_update_acl(sizeof(*e), param); 3366 } 3367 for (type = 0; type < CCS_MAX_PATH_NUMBER_OPERATION; type++) 3368 if (ccs_permstr(operation, ccs_mac_keywords[ccs_pn2mac[type]])) 3369 perm |= 1 << type; 3370 if (perm) { 3371 struct ccs_path_number_acl *e = ¶m->e.path_number_acl; 3372 e->head.type = CCS_TYPE_PATH_NUMBER_ACL; 3373 e->head.perm = perm; 3374 if (!ccs_parse_name_union(param, &e->name) || 3375 !ccs_parse_number_union(param, &e->number)) 3376 return -EINVAL; 3377 return ccs_update_acl(sizeof(*e), param); 3378 } 3379 for (type = 0; type < CCS_MAX_MKDEV_OPERATION; type++) 3380 if (ccs_permstr(operation, 3381 ccs_mac_keywords[ccs_pnnn2mac[type]])) 3382 perm |= 1 << type; 3383 if (perm) { 3384 struct ccs_mkdev_acl *e = ¶m->e.mkdev_acl; 3385 e->head.type = CCS_TYPE_MKDEV_ACL; 3386 e->head.perm = perm; 3387 if (!ccs_parse_name_union(param, &e->name) || 3388 !ccs_parse_number_union(param, &e->mode) || 3389 !ccs_parse_number_union(param, &e->major) || 3390 !ccs_parse_number_union(param, &e->minor)) 3391 return -EINVAL; 3392 return ccs_update_acl(sizeof(*e), param); 3393 } 3394 if (ccs_permstr(operation, ccs_mac_keywords[CCS_MAC_FILE_MOUNT])) { 3395 struct ccs_mount_acl *e = ¶m->e.mount_acl; 3396 e->head.type = CCS_TYPE_MOUNT_ACL; 3397 if (!ccs_parse_name_union(param, &e->dev_name) || 3398 !ccs_parse_name_union(param, &e->dir_name) || 3399 !ccs_parse_name_union(param, &e->fs_type) || 3400 !ccs_parse_number_union(param, &e->flags)) 3401 return -EINVAL; 3402 return ccs_update_acl(sizeof(*e), param); 3403 } 3404 return -EINVAL; 3405 } 3406 3407 #ifdef CONFIG_CCSECURITY_MISC 3408 3409 /** 3410 * ccs_write_misc - Update environment variable list. 3411 * 3412 * @param: Pointer to "struct ccs_acl_param". 3413 * 3414 * Returns 0 on success, negative value otherwise. 3415 */ 3416 static int ccs_write_misc(struct ccs_acl_param *param) 3417 { 3418 if (ccs_str_starts(¶m->data, "env ")) { 3419 struct ccs_env_acl *e = ¶m->e.env_acl; 3420 const char *data = ccs_read_token(param); 3421 e->head.type = CCS_TYPE_ENV_ACL; 3422 if (!ccs_correct_word(data) || strchr(data, '=')) 3423 return -EINVAL; 3424 e->env = ccs_get_name(data); 3425 if (!e->env) 3426 return -ENOMEM; 3427 return ccs_update_acl(sizeof(*e), param); 3428 } 3429 return -EINVAL; 3430 } 3431 3432 #endif 3433 3434 #ifdef CONFIG_CCSECURITY_IPC 3435 3436 /** 3437 * ccs_write_ipc - Update "struct ccs_signal_acl" list. 3438 * 3439 * @param: Pointer to "struct ccs_acl_param". 3440 * 3441 * Returns 0 on success, negative value otherwise. 3442 */ 3443 static int ccs_write_ipc(struct ccs_acl_param *param) 3444 { 3445 struct ccs_signal_acl *e = ¶m->e.signal_acl; 3446 e->head.type = CCS_TYPE_SIGNAL_ACL; 3447 if (!ccs_parse_number_union(param, &e->sig)) 3448 return -EINVAL; 3449 e->domainname = ccs_get_domainname(param); 3450 if (!e->domainname) 3451 return -EINVAL; 3452 return ccs_update_acl(sizeof(*e), param); 3453 } 3454 3455 #endif 3456 3457 #ifdef CONFIG_CCSECURITY_CAPABILITY 3458 3459 /** 3460 * ccs_write_capability - Write "struct ccs_capability_acl" list. 3461 * 3462 * @param: Pointer to "struct ccs_acl_param". 3463 * 3464 * Returns 0 on success, negative value otherwise. 3465 * 3466 * Caller holds ccs_read_lock(). 3467 */ 3468 static int ccs_write_capability(struct ccs_acl_param *param) 3469 { 3470 struct ccs_capability_acl *e = ¶m->e.capability_acl; 3471 const char *operation = ccs_read_token(param); 3472 u8 type; 3473 e->head.type = CCS_TYPE_CAPABILITY_ACL; 3474 for (type = 0; type < CCS_MAX_CAPABILITY_INDEX; type++) { 3475 if (strcmp(operation, ccs_mac_keywords[ccs_c2mac[type]])) 3476 continue; 3477 e->operation = type; 3478 return ccs_update_acl(sizeof(*e), param); 3479 } 3480 return -EINVAL; 3481 } 3482 3483 #endif 3484 3485 /** 3486 * ccs_write_acl - Write "struct ccs_acl_info" list. 3487 * 3488 * @ns: Pointer to "struct ccs_policy_namespace". 3489 * @list: Pointer to "struct list_head". 3490 * @data: Policy to be interpreted. 3491 * @is_delete: True if it is a delete request. 3492 * 3493 * Returns 0 on success, negative value otherwise. 3494 * 3495 * Caller holds ccs_read_lock(). 3496 */ 3497 static int ccs_write_acl(struct ccs_policy_namespace *ns, 3498 struct list_head *list, char *data, 3499 const bool is_delete) 3500 { 3501 struct ccs_acl_param param = { 3502 .ns = ns, 3503 .list = list, 3504 .data = data, 3505 .is_delete = is_delete, 3506 }; 3507 static const struct { 3508 const char *keyword; 3509 int (*write) (struct ccs_acl_param *); 3510 } ccs_callback[] = { 3511 { "file ", ccs_write_file }, 3512 #ifdef CONFIG_CCSECURITY_NETWORK 3513 { "network inet ", ccs_write_inet_network }, 3514 { "network unix ", ccs_write_unix_network }, 3515 #endif 3516 #ifdef CONFIG_CCSECURITY_MISC 3517 { "misc ", ccs_write_misc }, 3518 #endif 3519 #ifdef CONFIG_CCSECURITY_CAPABILITY 3520 { "capability ", ccs_write_capability }, 3521 #endif 3522 #ifdef CONFIG_CCSECURITY_IPC 3523 { "ipc signal ", ccs_write_ipc }, 3524 #endif 3525 { "task ", ccs_write_task }, 3526 }; 3527 u8 i; 3528 /* Forced zero clear for using memcmp() at ccs_update_acl(). */ 3529 memset(¶m.e, 0, sizeof(param.e)); 3530 param.e.acl_info.perm = 1; 3531 for (i = 0; i < ARRAY_SIZE(ccs_callback); i++) { 3532 int error; 3533 if (!ccs_str_starts(¶m.data, ccs_callback[i].keyword)) 3534 continue; 3535 error = ccs_callback[i].write(¶m); 3536 ccs_del_acl(¶m.e.acl_info.list); 3537 return error; 3538 } 3539 return -EINVAL; 3540 } 3541 3542 /** 3543 * ccs_delete_domain - Delete a domain. 3544 * 3545 * @domainname: The name of domain. 3546 * 3547 * Returns 0. 3548 */ 3549 static int ccs_delete_domain(char *domainname) 3550 { 3551 struct ccs_domain_info *domain; 3552 struct ccs_path_info name; 3553 name.name = domainname; 3554 ccs_fill_path_info(&name); 3555 if (mutex_lock_interruptible(&ccs_policy_lock)) 3556 return 0; 3557 /* Is there an active domain? */ 3558 list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) { 3559 /* Never delete ccs_kernel_domain. */ 3560 if (domain == &ccs_kernel_domain) 3561 continue; 3562 if (domain->is_deleted || 3563 ccs_pathcmp(domain->domainname, &name)) 3564 continue; 3565 domain->is_deleted = true; 3566 break; 3567 } 3568 mutex_unlock(&ccs_policy_lock); 3569 return 0; 3570 } 3571 3572 /** 3573 * ccs_write_domain - Write domain policy. 3574 * 3575 * @head: Pointer to "struct ccs_io_buffer". 3576 * 3577 * Returns 0 on success, negative value otherwise. 3578 * 3579 * Caller holds ccs_read_lock(). 3580 */ 3581 static int ccs_write_domain(struct ccs_io_buffer *head) 3582 { 3583 char *data = head->write_buf; 3584 struct ccs_policy_namespace *ns; 3585 struct ccs_domain_info *domain = head->w.domain; 3586 const bool is_delete = head->w.is_delete; 3587 const bool is_select = !is_delete && ccs_str_starts(&data, "select "); 3588 unsigned int idx; 3589 if (*data == '<') { 3590 domain = NULL; 3591 if (is_delete) 3592 ccs_delete_domain(data); 3593 else if (is_select) 3594 domain = ccs_find_domain(data); 3595 else 3596 domain = ccs_assign_domain(data, false); 3597 head->w.domain = domain; 3598 return 0; 3599 } 3600 if (!domain) 3601 return -EINVAL; 3602 ns = domain->ns; 3603 if (sscanf(data, "use_profile %u\n", &idx) == 1 && 3604 idx < CCS_MAX_PROFILES) { 3605 if (!ccs_policy_loaded || ns->profile_ptr[(u8) idx]) 3606 if (!is_delete) 3607 domain->profile = (u8) idx; 3608 return 0; 3609 } 3610 if (sscanf(data, "use_group %u\n", &idx) == 1 && 3611 idx < CCS_MAX_ACL_GROUPS) { 3612 if (!is_delete) 3613 set_bit(idx, domain->group); 3614 else 3615 clear_bit(idx, domain->group); 3616 return 0; 3617 } 3618 for (idx = 0; idx < CCS_MAX_DOMAIN_INFO_FLAGS; idx++) { 3619 const char *cp = ccs_dif[idx]; 3620 if (strncmp(data, cp, strlen(cp) - 1)) 3621 continue; 3622 domain->flags[idx] = !is_delete; 3623 return 0; 3624 } 3625 return ccs_write_acl(ns, &domain->acl_info_list, data, is_delete); 3626 } 3627 3628 /** 3629 * ccs_print_name_union - Print a ccs_name_union. 3630 * 3631 * @head: Pointer to "struct ccs_io_buffer". 3632 * @ptr: Pointer to "struct ccs_name_union". 3633 * 3634 * Returns nothing. 3635 */ 3636 static void ccs_print_name_union(struct ccs_io_buffer *head, 3637 const struct ccs_name_union *ptr) 3638 { 3639 ccs_set_space(head); 3640 if (!ccs_print_group(head, ptr->group)) 3641 ccs_set_string(head, ptr->filename->name); 3642 } 3643 3644 /** 3645 * ccs_print_name_union_quoted - Print a ccs_name_union with a quote. 3646 * 3647 * @head: Pointer to "struct ccs_io_buffer". 3648 * @ptr: Pointer to "struct ccs_name_union". 3649 * 3650 * Returns nothing. 3651 */ 3652 static void ccs_print_name_union_quoted(struct ccs_io_buffer *head, 3653 const struct ccs_name_union *ptr) 3654 { 3655 if (!ccs_print_group(head, ptr->group)) { 3656 ccs_set_string(head, "\""); 3657 ccs_set_string(head, ptr->filename->name); 3658 ccs_set_string(head, "\""); 3659 } 3660 } 3661 3662 /** 3663 * ccs_print_number_union_nospace - Print a ccs_number_union without a space. 3664 * 3665 * @head: Pointer to "struct ccs_io_buffer". 3666 * @ptr: Pointer to "struct ccs_number_union". 3667 * 3668 * Returns nothing. 3669 */ 3670 static void ccs_print_number_union_nospace(struct ccs_io_buffer *head, 3671 const struct ccs_number_union *ptr) 3672 { 3673 if (!ccs_print_group(head, ptr->group)) { 3674 int i; 3675 unsigned long min = ptr->values[0]; 3676 const unsigned long max = ptr->values[1]; 3677 u8 min_type = ptr->value_type[0]; 3678 const u8 max_type = ptr->value_type[1]; 3679 char buffer[128]; 3680 buffer[0] = '\0'; 3681 for (i = 0; i < 2; i++) { 3682 switch (min_type) { 3683 case CCS_VALUE_TYPE_HEXADECIMAL: 3684 ccs_addprintf(buffer, sizeof(buffer), "0x%lX", 3685 min); 3686 break; 3687 case CCS_VALUE_TYPE_OCTAL: 3688 ccs_addprintf(buffer, sizeof(buffer), "0%lo", 3689 min); 3690 break; 3691 default: 3692 ccs_addprintf(buffer, sizeof(buffer), "%lu", 3693 min); 3694 break; 3695 } 3696 if (min == max && min_type == max_type) 3697 break; 3698 ccs_addprintf(buffer, sizeof(buffer), "-"); 3699 min_type = max_type; 3700 min = max; 3701 } 3702 ccs_io_printf(head, "%s", buffer); 3703 } 3704 } 3705 3706 /** 3707 * ccs_print_number_union - Print a ccs_number_union. 3708 * 3709 * @head: Pointer to "struct ccs_io_buffer". 3710 * @ptr: Pointer to "struct ccs_number_union". 3711 * 3712 * Returns nothing. 3713 */ 3714 static void ccs_print_number_union(struct ccs_io_buffer *head, 3715 const struct ccs_number_union *ptr) 3716 { 3717 ccs_set_space(head); 3718 ccs_print_number_union_nospace(head, ptr); 3719 } 3720 3721 /** 3722 * ccs_print_condition - Print condition part. 3723 * 3724 * @head: Pointer to "struct ccs_io_buffer". 3725 * @cond: Pointer to "struct ccs_condition". 3726 * 3727 * Returns true on success, false otherwise. 3728 */ 3729 static bool ccs_print_condition(struct ccs_io_buffer *head, 3730 const struct ccs_condition *cond) 3731 { 3732 switch (head->r.cond_step) { 3733 case 0: 3734 head->r.cond_index = 0; 3735 head->r.cond_step++; 3736 if (cond->transit && cond->exec_transit) { 3737 ccs_set_space(head); 3738 ccs_set_string(head, cond->transit->name); 3739 } 3740 /* fall through */ 3741 case 1: 3742 { 3743 const u16 condc = cond->condc; 3744 const struct ccs_condition_element *condp = 3745 (typeof(condp)) (cond + 1); 3746 const struct ccs_number_union *numbers_p = 3747 (typeof(numbers_p)) (condp + condc); 3748 const struct ccs_name_union *names_p = 3749 (typeof(names_p)) 3750 (numbers_p + cond->numbers_count); 3751 const struct ccs_argv *argv = 3752 (typeof(argv)) (names_p + cond->names_count); 3753 const struct ccs_envp *envp = 3754 (typeof(envp)) (argv + cond->argc); 3755 u16 skip; 3756 for (skip = 0; skip < head->r.cond_index; skip++) { 3757 const u8 left = condp->left; 3758 const u8 right = condp->right; 3759 condp++; 3760 switch (left) { 3761 case CCS_ARGV_ENTRY: 3762 argv++; 3763 continue; 3764 case CCS_ENVP_ENTRY: 3765 envp++; 3766 continue; 3767 case CCS_NUMBER_UNION: 3768 numbers_p++; 3769 break; 3770 } 3771 switch (right) { 3772 case CCS_NAME_UNION: 3773 names_p++; 3774 break; 3775 case CCS_NUMBER_UNION: 3776 numbers_p++; 3777 break; 3778 } 3779 } 3780 while (head->r.cond_index < condc) { 3781 const u8 match = condp->equals; 3782 const u8 left = condp->left; 3783 const u8 right = condp->right; 3784 if (!ccs_flush(head)) 3785 return false; 3786 condp++; 3787 head->r.cond_index++; 3788 ccs_set_space(head); 3789 switch (left) { 3790 case CCS_ARGV_ENTRY: 3791 ccs_io_printf(head, 3792 "exec.argv[%lu]%s=\"", 3793 argv->index, 3794 argv->is_not ? "!" : ""); 3795 ccs_set_string(head, 3796 argv->value->name); 3797 ccs_set_string(head, "\""); 3798 argv++; 3799 continue; 3800 case CCS_ENVP_ENTRY: 3801 ccs_set_string(head, "exec.envp[\""); 3802 ccs_set_string(head, envp->name->name); 3803 ccs_io_printf(head, "\"]%s=", 3804 envp->is_not ? "!" : ""); 3805 if (envp->value) { 3806 ccs_set_string(head, "\""); 3807 ccs_set_string(head, envp-> 3808 value->name); 3809 ccs_set_string(head, "\""); 3810 } else { 3811 ccs_set_string(head, "NULL"); 3812 } 3813 envp++; 3814 continue; 3815 case CCS_NUMBER_UNION: 3816 ccs_print_number_union_nospace 3817 (head, numbers_p++); 3818 break; 3819 default: 3820 ccs_set_string(head, 3821 ccs_condition_keyword[left]); 3822 break; 3823 } 3824 ccs_set_string(head, match ? "=" : "!="); 3825 switch (right) { 3826 case CCS_NAME_UNION: 3827 ccs_print_name_union_quoted 3828 (head, names_p++); 3829 break; 3830 case CCS_NUMBER_UNION: 3831 ccs_print_number_union_nospace 3832 (head, numbers_p++); 3833 break; 3834 default: 3835 ccs_set_string(head, 3836 ccs_condition_keyword[right]); 3837 break; 3838 } 3839 } 3840 } 3841 head->r.cond_step++; 3842 /* fall through */ 3843 case 2: 3844 if (!ccs_flush(head)) 3845 break; 3846 head->r.cond_step++; 3847 /* fall through */ 3848 case 3: 3849 if (cond->grant_log != CCS_GRANTLOG_AUTO) 3850 ccs_io_printf(head, " grant_log=%s", 3851 ccs_yesno(cond->grant_log == 3852 CCS_GRANTLOG_YES)); 3853 if (cond->transit && !cond->exec_transit) { 3854 const char *name = cond->transit->name; 3855 ccs_set_string(head, " auto_domain_transition=\""); 3856 ccs_set_string(head, name); 3857 ccs_set_string(head, "\""); 3858 } 3859 ccs_set_lf(head); 3860 return true; 3861 } 3862 return false; 3863 } 3864 3865 /** 3866 * ccs_set_group - Print "acl_group " header keyword and category name. 3867 * 3868 * @head: Pointer to "struct ccs_io_buffer". 3869 * @category: Category name. 3870 * 3871 * Returns nothing. 3872 */ 3873 static void ccs_set_group(struct ccs_io_buffer *head, const char *category) 3874 { 3875 if (head->type == CCS_EXCEPTION_POLICY) { 3876 ccs_print_namespace(head); 3877 ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index); 3878 } 3879 ccs_set_string(head, category); 3880 } 3881 3882 /** 3883 * ccs_print_entry - Print an ACL entry. 3884 * 3885 * @head: Pointer to "struct ccs_io_buffer". 3886 * @acl: Pointer to an ACL entry. 3887 * 3888 * Returns true on success, false otherwise. 3889 */ 3890 static bool ccs_print_entry(struct ccs_io_buffer *head, 3891 const struct ccs_acl_info *acl) 3892 { 3893 const u8 acl_type = acl->type; 3894 const bool may_trigger_transition = acl->cond && acl->cond->transit; 3895 bool first = true; 3896 u8 bit; 3897 if (head->r.print_cond_part) 3898 goto print_cond_part; 3899 if (acl->is_deleted) 3900 return true; 3901 if (!ccs_flush(head)) 3902 return false; 3903 else if (acl_type == CCS_TYPE_PATH_ACL) { 3904 struct ccs_path_acl *ptr 3905 = container_of(acl, typeof(*ptr), head); 3906 for (bit = 0; bit < CCS_MAX_PATH_OPERATION; bit++) { 3907 if (!(acl->perm & (1 << bit))) 3908 continue; 3909 if (head->r.print_transition_related_only && 3910 bit != CCS_TYPE_EXECUTE && !may_trigger_transition) 3911 continue; 3912 if (first) { 3913 ccs_set_group(head, "file "); 3914 first = false; 3915 } else { 3916 ccs_set_slash(head); 3917 } 3918 ccs_set_string(head, ccs_path_keyword[bit]); 3919 } 3920 if (first) 3921 return true; 3922 ccs_print_name_union(head, &ptr->name); 3923 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER 3924 } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER || 3925 acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) { 3926 struct ccs_handler_acl *ptr 3927 = container_of(acl, typeof(*ptr), head); 3928 ccs_set_group(head, "task "); 3929 ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER 3930 ? "auto_execute_handler " : 3931 "denied_execute_handler "); 3932 ccs_set_string(head, ptr->handler->name); 3933 #endif 3934 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION 3935 } else if (acl_type == CCS_TYPE_AUTO_TASK_ACL || 3936 acl_type == CCS_TYPE_MANUAL_TASK_ACL) { 3937 struct ccs_task_acl *ptr = 3938 container_of(acl, typeof(*ptr), head); 3939 ccs_set_group(head, "task "); 3940 ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ? 3941 "auto_domain_transition " : 3942 "manual_domain_transition "); 3943 ccs_set_string(head, ptr->domainname->name); 3944 #endif 3945 } else if (head->r.print_transition_related_only && 3946 !may_trigger_transition) { 3947 return true; 3948 } else if (acl_type == CCS_TYPE_MKDEV_ACL) { 3949 struct ccs_mkdev_acl *ptr = 3950 container_of(acl, typeof(*ptr), head); 3951 for (bit = 0; bit < CCS_MAX_MKDEV_OPERATION; bit++) { 3952 if (!(acl->perm & (1 << bit))) 3953 continue; 3954 if (first) { 3955 ccs_set_group(head, "file "); 3956 first = false; 3957 } else { 3958 ccs_set_slash(head); 3959 } 3960 ccs_set_string(head, ccs_mac_keywords 3961 [ccs_pnnn2mac[bit]]); 3962 } 3963 if (first) 3964 return true; 3965 ccs_print_name_union(head, &ptr->name); 3966 ccs_print_number_union(head, &ptr->mode); 3967 ccs_print_number_union(head, &ptr->major); 3968 ccs_print_number_union(head, &ptr->minor); 3969 } else if (acl_type == CCS_TYPE_PATH2_ACL) { 3970 struct ccs_path2_acl *ptr = 3971 container_of(acl, typeof(*ptr), head); 3972 for (bit = 0; bit < CCS_MAX_PATH2_OPERATION; bit++) { 3973 if (!(acl->perm & (1 << bit))) 3974 continue; 3975 if (first) { 3976 ccs_set_group(head, "file "); 3977 first = false; 3978 } else { 3979 ccs_set_slash(head); 3980 } 3981 ccs_set_string(head, ccs_mac_keywords 3982 [ccs_pp2mac[bit]]); 3983 } 3984 if (first) 3985 return true; 3986 ccs_print_name_union(head, &ptr->name1); 3987 ccs_print_name_union(head, &ptr->name2); 3988 } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) { 3989 struct ccs_path_number_acl *ptr = 3990 container_of(acl, typeof(*ptr), head); 3991 for (bit = 0; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) { 3992 if (!(acl->perm & (1 << bit))) 3993 continue; 3994 if (first) { 3995 ccs_set_group(head, "file "); 3996 first = false; 3997 } else { 3998 ccs_set_slash(head); 3999 } 4000 ccs_set_string(head, ccs_mac_keywords 4001 [ccs_pn2mac[bit]]); 4002 } 4003 if (first) 4004 return true; 4005 ccs_print_name_union(head, &ptr->name); 4006 ccs_print_number_union(head, &ptr->number); 4007 #ifdef CONFIG_CCSECURITY_MISC 4008 } else if (acl_type == CCS_TYPE_ENV_ACL) { 4009 struct ccs_env_acl *ptr = 4010 container_of(acl, typeof(*ptr), head); 4011 ccs_set_group(head, "misc env "); 4012 ccs_set_string(head, ptr->env->name); 4013 #endif 4014 #ifdef CONFIG_CCSECURITY_CAPABILITY 4015 } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) { 4016 struct ccs_capability_acl *ptr = 4017 container_of(acl, typeof(*ptr), head); 4018 ccs_set_group(head, "capability "); 4019 ccs_set_string(head, ccs_mac_keywords 4020 [ccs_c2mac[ptr->operation]]); 4021 #endif 4022 #ifdef CONFIG_CCSECURITY_NETWORK 4023 } else if (acl_type == CCS_TYPE_INET_ACL) { 4024 struct ccs_inet_acl *ptr = 4025 container_of(acl, typeof(*ptr), head); 4026 for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) { 4027 if (!(acl->perm & (1 << bit))) 4028 continue; 4029 if (first) { 4030 ccs_set_group(head, "network inet "); 4031 ccs_set_string(head, ccs_proto_keyword 4032 [ptr->protocol]); 4033 ccs_set_space(head); 4034 first = false; 4035 } else { 4036 ccs_set_slash(head); 4037 } 4038 ccs_set_string(head, ccs_socket_keyword[bit]); 4039 } 4040 if (first) 4041 return true; 4042 ccs_set_space(head); 4043 if (!ccs_print_group(head, ptr->address.group)) { 4044 char buf[128]; 4045 ccs_print_ip(buf, sizeof(buf), &ptr->address); 4046 ccs_io_printf(head, "%s", buf); 4047 } 4048 ccs_print_number_union(head, &ptr->port); 4049 } else if (acl_type == CCS_TYPE_UNIX_ACL) { 4050 struct ccs_unix_acl *ptr = 4051 container_of(acl, typeof(*ptr), head); 4052 for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) { 4053 if (!(acl->perm & (1 << bit))) 4054 continue; 4055 if (first) { 4056 ccs_set_group(head, "network unix "); 4057 ccs_set_string(head, ccs_proto_keyword 4058 [ptr->protocol]); 4059 ccs_set_space(head); 4060 first = false; 4061 } else { 4062 ccs_set_slash(head); 4063 } 4064 ccs_set_string(head, ccs_socket_keyword[bit]); 4065 } 4066 if (first) 4067 return true; 4068 ccs_print_name_union(head, &ptr->name); 4069 #endif 4070 #ifdef CONFIG_CCSECURITY_IPC 4071 } else if (acl_type == CCS_TYPE_SIGNAL_ACL) { 4072 struct ccs_signal_acl *ptr = 4073 container_of(acl, typeof(*ptr), head); 4074 ccs_set_group(head, "ipc signal "); 4075 ccs_print_number_union_nospace(head, &ptr->sig); 4076 ccs_set_space(head); 4077 ccs_set_string(head, ptr->domainname->name); 4078 #endif 4079 } else if (acl_type == CCS_TYPE_MOUNT_ACL) { 4080 struct ccs_mount_acl *ptr = 4081 container_of(acl, typeof(*ptr), head); 4082 ccs_set_group(head, "file mount"); 4083 ccs_print_name_union(head, &ptr->dev_name); 4084 ccs_print_name_union(head, &ptr->dir_name); 4085 ccs_print_name_union(head, &ptr->fs_type); 4086 ccs_print_number_union(head, &ptr->flags); 4087 } 4088 if (acl->cond) { 4089 head->r.print_cond_part = true; 4090 head->r.cond_step = 0; 4091 if (!ccs_flush(head)) 4092 return false; 4093 print_cond_part: 4094 if (!ccs_print_condition(head, acl->cond)) 4095 return false; 4096 head->r.print_cond_part = false; 4097 } else { 4098 ccs_set_lf(head); 4099 } 4100 return true; 4101 } 4102 4103 /** 4104 * ccs_read_acl - Read "struct ccs_acl_info" list. 4105 * 4106 * @head: Pointer to "struct ccs_io_buffer". 4107 * @list: Pointer to "struct list_head". 4108 * 4109 * Returns true on success, false otherwise. 4110 * 4111 * Caller holds ccs_read_lock(). 4112 */ 4113 static bool ccs_read_acl(struct ccs_io_buffer *head, struct list_head *list) 4114 { 4115 list_for_each_cookie(head->r.acl, list) { 4116 struct ccs_acl_info *ptr = 4117 list_entry(head->r.acl, typeof(*ptr), list); 4118 if (!ccs_print_entry(head, ptr)) 4119 return false; 4120 } 4121 head->r.acl = NULL; 4122 return true; 4123 } 4124 4125 /** 4126 * ccs_read_domain - Read domain policy. 4127 * 4128 * @head: Pointer to "struct ccs_io_buffer". 4129 * 4130 * Returns nothing. 4131 * 4132 * Caller holds ccs_read_lock(). 4133 */ 4134 static void ccs_read_domain(struct ccs_io_buffer *head) 4135 { 4136 if (head->r.eof) 4137 return; 4138 list_for_each_cookie(head->r.domain, &ccs_domain_list) { 4139 struct ccs_domain_info *domain = 4140 list_entry(head->r.domain, typeof(*domain), list); 4141 switch (head->r.step) { 4142 u8 i; 4143 case 0: 4144 if (domain->is_deleted && 4145 !head->r.print_this_domain_only) 4146 continue; 4147 /* Print domainname and flags. */ 4148 ccs_set_string(head, domain->domainname->name); 4149 ccs_set_lf(head); 4150 ccs_io_printf(head, "use_profile %u\n", 4151 domain->profile); 4152 for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++) 4153 if (domain->flags[i]) 4154 ccs_set_string(head, ccs_dif[i]); 4155 head->r.index = 0; 4156 head->r.step++; 4157 /* fall through */ 4158 case 1: 4159 while (head->r.index < CCS_MAX_ACL_GROUPS) { 4160 i = head->r.index++; 4161 if (!test_bit(i, domain->group)) 4162 continue; 4163 ccs_io_printf(head, "use_group %u\n", i); 4164 if (!ccs_flush(head)) 4165 return; 4166 } 4167 head->r.index = 0; 4168 head->r.step++; 4169 ccs_set_lf(head); 4170 /* fall through */ 4171 case 2: 4172 if (!ccs_read_acl(head, &domain->acl_info_list)) 4173 return; 4174 head->r.step++; 4175 if (!ccs_set_lf(head)) 4176 return; 4177 /* fall through */ 4178 case 3: 4179 head->r.step = 0; 4180 if (head->r.print_this_domain_only) 4181 goto done; 4182 } 4183 } 4184 done: 4185 head->r.eof = true; 4186 } 4187 4188 /** 4189 * ccs_write_pid - Specify PID to obtain domainname. 4190 * 4191 * @head: Pointer to "struct ccs_io_buffer". 4192 * 4193 * Returns 0. 4194 */ 4195 static int ccs_write_pid(struct ccs_io_buffer *head) 4196 { 4197 head->r.eof = false; 4198 return 0; 4199 } 4200 4201 /** 4202 * ccs_read_pid - Read information of a process. 4203 * 4204 * @head: Pointer to "struct ccs_io_buffer". 4205 * 4206 * Returns the domainname which the specified PID is in or 4207 * process information of the specified PID on success, 4208 * empty string otherwise. 4209 * 4210 * Caller holds ccs_read_lock(). 4211 */ 4212 static void ccs_read_pid(struct ccs_io_buffer *head) 4213 { 4214 char *buf = head->write_buf; 4215 bool task_info = false; 4216 bool global_pid = false; 4217 unsigned int pid; 4218 struct task_struct *p; 4219 struct ccs_domain_info *domain = NULL; 4220 u32 ccs_flags = 0; 4221 /* Accessing write_buf is safe because head->io_sem is held. */ 4222 if (!buf) { 4223 head->r.eof = true; 4224 return; /* Do nothing if open(O_RDONLY). */ 4225 } 4226 if (head->r.w_pos || head->r.eof) 4227 return; 4228 head->r.eof = true; 4229 if (ccs_str_starts(&buf, "info ")) 4230 task_info = true; 4231 if (ccs_str_starts(&buf, "global-pid ")) 4232 global_pid = true; 4233 pid = (unsigned int) simple_strtoul(buf, NULL, 10); 4234 ccs_tasklist_lock(); 4235 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) 4236 if (global_pid) 4237 p = ccsecurity_exports.find_task_by_pid_ns(pid, &init_pid_ns); 4238 else 4239 p = ccsecurity_exports.find_task_by_vpid(pid); 4240 #else 4241 p = find_task_by_pid(pid); 4242 #endif 4243 if (p) { 4244 domain = ccs_task_domain(p); 4245 ccs_flags = ccs_task_flags(p); 4246 } 4247 ccs_tasklist_unlock(); 4248 if (!domain) 4249 return; 4250 if (!task_info) { 4251 ccs_io_printf(head, "%u %u ", pid, domain->profile); 4252 ccs_set_string(head, domain->domainname->name); 4253 } else { 4254 ccs_io_printf(head, "%u manager=%s execute_handler=%s ", pid, 4255 ccs_yesno(ccs_flags & 4256 CCS_TASK_IS_MANAGER), 4257 ccs_yesno(ccs_flags & 4258 CCS_TASK_IS_EXECUTE_HANDLER)); 4259 } 4260 } 4261 4262 /** 4263 * ccs_write_group - Write "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list. 4264 * 4265 * @param: Pointer to "struct ccs_acl_param". 4266 * @type: Type of this group. 4267 * 4268 * Returns 0 on success, negative value otherwise. 4269 */ 4270 static int ccs_write_group(struct ccs_acl_param *param, const u8 type) 4271 { 4272 struct ccs_group *group = ccs_get_group(param, type); 4273 int error = -EINVAL; 4274 if (!group) 4275 return -ENOMEM; 4276 param->list = &group->member_list; 4277 if (type == CCS_PATH_GROUP) { 4278 struct ccs_path_group *e = ¶m->e.path_group; 4279 e->member_name = ccs_get_name(ccs_read_token(param)); 4280 if (!e->member_name) { 4281 error = -ENOMEM; 4282 goto out; 4283 } 4284 error = ccs_update_policy(sizeof(*e), param); 4285 ccs_put_name(e->member_name); 4286 } else if (type == CCS_NUMBER_GROUP) { 4287 struct ccs_number_group *e = ¶m->e.number_group; 4288 if (param->data[0] == '@' || 4289 !ccs_parse_number_union(param, &e->number)) 4290 goto out; 4291 error = ccs_update_policy(sizeof(*e), param); 4292 #ifdef CONFIG_CCSECURITY_NETWORK 4293 } else { 4294 struct ccs_address_group *e = ¶m->e.address_group; 4295 if (param->data[0] == '@' || 4296 !ccs_parse_ipaddr_union(param, &e->address)) 4297 goto out; 4298 error = ccs_update_policy(sizeof(*e), param); 4299 #endif 4300 } 4301 out: 4302 ccs_put_group(group); 4303 return error; 4304 } 4305 4306 #ifdef CONFIG_CCSECURITY_PORTRESERVE 4307 /** 4308 * ccs_lport_reserved - Check whether local port is reserved or not. 4309 * 4310 * @port: Port number. 4311 * 4312 * Returns true if local port is reserved, false otherwise. 4313 */ 4314 static bool __ccs_lport_reserved(const u16 port) 4315 { 4316 return ccs_reserved_port_map[port >> 3] & (1 << (port & 7)) 4317 ? true : false; 4318 } 4319 4320 /** 4321 * ccs_write_reserved_port - Update "struct ccs_reserved" list. 4322 * 4323 * @param: Pointer to "struct ccs_acl_param". 4324 * 4325 * Returns 0 on success, negative value otherwise. 4326 * 4327 * Caller holds ccs_read_lock(). 4328 */ 4329 static int ccs_write_reserved_port(struct ccs_acl_param *param) 4330 { 4331 struct ccs_reserved *e = ¶m->e.reserved; 4332 struct ccs_policy_namespace *ns = param->ns; 4333 int error; 4334 u8 *tmp; 4335 if (param->data[0] == '@' || 4336 !ccs_parse_number_union(param, &e->port) || 4337 e->port.values[1] > 65535 || param->data[0]) 4338 return -EINVAL; 4339 param->list = &ns->policy_list[CCS_ID_RESERVEDPORT]; 4340 error = ccs_update_policy(sizeof(*e), param); 4341 if (error) 4342 return error; 4343 tmp = kzalloc(sizeof(ccs_reserved_port_map), CCS_GFP_FLAGS); 4344 if (!tmp) 4345 return -ENOMEM; 4346 list_for_each_entry_srcu(ns, &ccs_namespace_list, namespace_list, 4347 &ccs_ss) { 4348 struct ccs_reserved *ptr; 4349 struct list_head *list = &ns->policy_list[CCS_ID_RESERVEDPORT]; 4350 list_for_each_entry_srcu(ptr, list, head.list, &ccs_ss) { 4351 unsigned int port; 4352 if (ptr->head.is_deleted) 4353 continue; 4354 for (port = ptr->port.values[0]; 4355 port <= ptr->port.values[1]; port++) 4356 tmp[port >> 3] |= 1 << (port & 7); 4357 } 4358 } 4359 memmove(ccs_reserved_port_map, tmp, sizeof(ccs_reserved_port_map)); 4360 kfree(tmp); 4361 /* 4362 * Since this feature is no-op by default, we don't need to register 4363 * this callback hook unless the first entry is added. 4364 */ 4365 ccsecurity_ops.lport_reserved = __ccs_lport_reserved; 4366 return 0; 4367 } 4368 #endif 4369 4370 /** 4371 * ccs_write_aggregator - Write "struct ccs_aggregator" list. 4372 * 4373 * @param: Pointer to "struct ccs_acl_param". 4374 * 4375 * Returns 0 on success, negative value otherwise. 4376 */ 4377 static int ccs_write_aggregator(struct ccs_acl_param *param) 4378 { 4379 struct ccs_aggregator *e = ¶m->e.aggregator; 4380 int error = param->is_delete ? -ENOENT : -ENOMEM; 4381 const char *original_name = ccs_read_token(param); 4382 const char *aggregated_name = ccs_read_token(param); 4383 if (!ccs_correct_word(original_name) || 4384 !ccs_correct_path(aggregated_name)) 4385 return -EINVAL; 4386 e->original_name = ccs_get_name(original_name); 4387 e->aggregated_name = ccs_get_name(aggregated_name); 4388 if (!e->original_name || !e->aggregated_name || 4389 e->aggregated_name->is_patterned) /* No patterns allowed. */ 4390 goto out; 4391 param->list = ¶m->ns->policy_list[CCS_ID_AGGREGATOR]; 4392 error = ccs_update_policy(sizeof(*e), param); 4393 out: 4394 ccs_put_name(e->original_name); 4395 ccs_put_name(e->aggregated_name); 4396 return error; 4397 } 4398 4399 /** 4400 * ccs_write_transition_control - Write "struct ccs_transition_control" list. 4401 * 4402 * @param: Pointer to "struct ccs_acl_param". 4403 * @type: Type of this entry. 4404 * 4405 * Returns 0 on success, negative value otherwise. 4406 */ 4407 static int ccs_write_transition_control(struct ccs_acl_param *param, 4408 const u8 type) 4409 { 4410 struct ccs_transition_control *e = ¶m->e.transition_control; 4411 int error = param->is_delete ? -ENOENT : -ENOMEM; 4412 char *program = param->data; 4413 char *domainname = strstr(program, " from "); 4414 e->type = type; 4415 if (domainname) { 4416 *domainname = '\0'; 4417 domainname += 6; 4418 } else if (type == CCS_TRANSITION_CONTROL_NO_KEEP || 4419 type == CCS_TRANSITION_CONTROL_KEEP) { 4420 domainname = program; 4421 program = NULL; 4422 } 4423 if (program && strcmp(program, "any")) { 4424 if (!ccs_correct_path(program)) 4425 return -EINVAL; 4426 e->program = ccs_get_name(program); 4427 if (!e->program) 4428 goto out; 4429 } 4430 if (domainname && strcmp(domainname, "any")) { 4431 if (!ccs_correct_domain(domainname)) { 4432 if (!ccs_correct_path(domainname)) 4433 goto out; 4434 e->is_last_name = true; 4435 } 4436 e->domainname = ccs_get_name(domainname); 4437 if (!e->domainname) 4438 goto out; 4439 } 4440 param->list = ¶m->ns->policy_list[CCS_ID_TRANSITION_CONTROL]; 4441 error = ccs_update_policy(sizeof(*e), param); 4442 out: 4443 ccs_put_name(e->domainname); 4444 ccs_put_name(e->program); 4445 return error; 4446 } 4447 4448 /** 4449 * ccs_write_exception - Write exception policy. 4450 * 4451 * @head: Pointer to "struct ccs_io_buffer". 4452 * 4453 * Returns 0 on success, negative value otherwise. 4454 */ 4455 static int ccs_write_exception(struct ccs_io_buffer *head) 4456 { 4457 const bool is_delete = head->w.is_delete; 4458 struct ccs_acl_param param = { 4459 .ns = head->w.ns, 4460 .is_delete = is_delete, 4461 .data = head->write_buf, 4462 }; 4463 u8 i; 4464 /* Forced zero clear for using memcmp() at ccs_update_policy(). */ 4465 memset(¶m.e, 0, sizeof(param.e)); 4466 if (ccs_str_starts(¶m.data, "aggregator ")) 4467 return ccs_write_aggregator(¶m); 4468 #ifdef CONFIG_CCSECURITY_PORTRESERVE 4469 if (ccs_str_starts(¶m.data, "deny_autobind ")) 4470 return ccs_write_reserved_port(¶m); 4471 #endif 4472 for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) 4473 if (ccs_str_starts(¶m.data, ccs_transition_type[i])) 4474 return ccs_write_transition_control(¶m, i); 4475 for (i = 0; i < CCS_MAX_GROUP; i++) 4476 if (ccs_str_starts(¶m.data, ccs_group_name[i])) 4477 return ccs_write_group(¶m, i); 4478 if (ccs_str_starts(¶m.data, "acl_group ")) { 4479 unsigned int group; 4480 char *data; 4481 group = simple_strtoul(param.data, &data, 10); 4482 if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ') 4483 return ccs_write_acl(head->w.ns, 4484 &head->w.ns->acl_group[group], 4485 data, is_delete); 4486 } 4487 return -EINVAL; 4488 } 4489 4490 /** 4491 * ccs_read_group - Read "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list. 4492 * 4493 * @head: Pointer to "struct ccs_io_buffer". 4494 * @idx: Index number. 4495 * 4496 * Returns true on success, false otherwise. 4497 * 4498 * Caller holds ccs_read_lock(). 4499 */ 4500 static bool ccs_read_group(struct ccs_io_buffer *head, const int idx) 4501 { 4502 struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns), 4503 namespace_list); 4504 struct list_head *list = &ns->group_list[idx]; 4505 list_for_each_cookie(head->r.group, list) { 4506 struct ccs_group *group = 4507 list_entry(head->r.group, typeof(*group), head.list); 4508 list_for_each_cookie(head->r.acl, &group->member_list) { 4509 struct ccs_acl_head *ptr = 4510 list_entry(head->r.acl, typeof(*ptr), list); 4511 if (ptr->is_deleted) 4512 continue; 4513 if (!ccs_flush(head)) 4514 return false; 4515 ccs_print_namespace(head); 4516 ccs_set_string(head, ccs_group_name[idx]); 4517 ccs_set_string(head, group->group_name->name); 4518 if (idx == CCS_PATH_GROUP) { 4519 ccs_set_space(head); 4520 ccs_set_string(head, container_of 4521 (ptr, struct ccs_path_group, 4522 head)->member_name->name); 4523 } else if (idx == CCS_NUMBER_GROUP) { 4524 ccs_print_number_union(head, &container_of 4525 (ptr, struct ccs_number_group, 4526 head)->number); 4527 #ifdef CONFIG_CCSECURITY_NETWORK 4528 } else if (idx == CCS_ADDRESS_GROUP) { 4529 char buffer[128]; 4530 struct ccs_address_group *member = 4531 container_of(ptr, typeof(*member), 4532 head); 4533 ccs_print_ip(buffer, sizeof(buffer), 4534 &member->address); 4535 ccs_io_printf(head, " %s", buffer); 4536 #endif 4537 } 4538 ccs_set_lf(head); 4539 } 4540 head->r.acl = NULL; 4541 } 4542 head->r.group = NULL; 4543 return true; 4544 } 4545 4546 /** 4547 * ccs_read_policy - Read "struct ccs_..._entry" list. 4548 * 4549 * @head: Pointer to "struct ccs_io_buffer". 4550 * @idx: Index number. 4551 * 4552 * Returns true on success, false otherwise. 4553 * 4554 * Caller holds ccs_read_lock(). 4555 */ 4556 static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx) 4557 { 4558 struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns), 4559 namespace_list); 4560 struct list_head *list = &ns->policy_list[idx]; 4561 list_for_each_cookie(head->r.acl, list) { 4562 struct ccs_acl_head *acl = 4563 container_of(head->r.acl, typeof(*acl), list); 4564 if (acl->is_deleted) 4565 continue; 4566 if (head->r.print_transition_related_only && 4567 idx != CCS_ID_TRANSITION_CONTROL) 4568 continue; 4569 if (!ccs_flush(head)) 4570 return false; 4571 switch (idx) { 4572 case CCS_ID_TRANSITION_CONTROL: 4573 { 4574 struct ccs_transition_control *ptr = 4575 container_of(acl, typeof(*ptr), head); 4576 ccs_print_namespace(head); 4577 ccs_set_string(head, 4578 ccs_transition_type[ptr->type]); 4579 ccs_set_string(head, ptr->program ? 4580 ptr->program->name : "any"); 4581 ccs_set_string(head, " from "); 4582 ccs_set_string(head, ptr->domainname ? 4583 ptr->domainname->name : "any"); 4584 } 4585 break; 4586 case CCS_ID_AGGREGATOR: 4587 { 4588 struct ccs_aggregator *ptr = 4589 container_of(acl, typeof(*ptr), head); 4590 ccs_print_namespace(head); 4591 ccs_set_string(head, "aggregator "); 4592 ccs_set_string(head, ptr->original_name->name); 4593 ccs_set_space(head); 4594 ccs_set_string(head, 4595 ptr->aggregated_name->name); 4596 } 4597 break; 4598 #ifdef CONFIG_CCSECURITY_PORTRESERVE 4599 case CCS_ID_RESERVEDPORT: 4600 { 4601 struct ccs_reserved *ptr = 4602 container_of(acl, typeof(*ptr), head); 4603 ccs_print_namespace(head); 4604 ccs_set_string(head, "deny_autobind "); 4605 ccs_print_number_union_nospace(head, 4606 &ptr->port); 4607 } 4608 break; 4609 #endif 4610 default: 4611 continue; 4612 } 4613 ccs_set_lf(head); 4614 } 4615 head->r.acl = NULL; 4616 return true; 4617 } 4618 4619 /** 4620 * ccs_read_exception - Read exception policy. 4621 * 4622 * @head: Pointer to "struct ccs_io_buffer". 4623 * 4624 * Returns nothing. 4625 * 4626 * Caller holds ccs_read_lock(). 4627 */ 4628 static void ccs_read_exception(struct ccs_io_buffer *head) 4629 { 4630 struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns), 4631 namespace_list); 4632 if (head->r.eof) 4633 return; 4634 while (head->r.step < CCS_MAX_POLICY && 4635 ccs_read_policy(head, head->r.step)) 4636 head->r.step++; 4637 if (head->r.step < CCS_MAX_POLICY) 4638 return; 4639 while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP && 4640 ccs_read_group(head, head->r.step - CCS_MAX_POLICY)) 4641 head->r.step++; 4642 if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP) 4643 return; 4644 while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP 4645 + CCS_MAX_ACL_GROUPS) { 4646 head->r.acl_group_index = 4647 head->r.step - CCS_MAX_POLICY - CCS_MAX_GROUP; 4648 if (!ccs_read_acl(head, &ns->acl_group 4649 [head->r.acl_group_index])) 4650 return; 4651 head->r.step++; 4652 } 4653 head->r.eof = true; 4654 } 4655 4656 /** 4657 * ccs_truncate - Truncate a line. 4658 * 4659 * @str: String to truncate. 4660 * 4661 * Returns length of truncated @str. 4662 */ 4663 static int ccs_truncate(char *str) 4664 { 4665 char *start = str; 4666 while (*(unsigned char *) str > (unsigned char) ' ') 4667 str++; 4668 *str = '\0'; 4669 return strlen(start) + 1; 4670 } 4671 4672 /** 4673 * ccs_add_entry - Add an ACL to current thread's domain. Used by learning mode. 4674 * 4675 * @header: Lines containing ACL. 4676 * 4677 * Returns nothing. 4678 */ 4679 static void ccs_add_entry(char *header) 4680 { 4681 char *buffer; 4682 char *realpath = NULL; 4683 char *argv0 = NULL; 4684 char *symlink = NULL; 4685 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER 4686 char *handler; 4687 #endif 4688 char *cp = strchr(header, '\n'); 4689 int len; 4690 if (!cp) 4691 return; 4692 cp = strchr(cp + 1, '\n'); 4693 if (!cp) 4694 return; 4695 *cp++ = '\0'; 4696 len = strlen(cp) + 1; 4697 /* strstr() will return NULL if ordering is wrong. */ 4698 if (*cp == 'f') { 4699 argv0 = strstr(header, " argv[]={ \""); 4700 if (argv0) { 4701 argv0 += 10; 4702 len += ccs_truncate(argv0) + 14; 4703 } 4704 realpath = strstr(header, " exec={ realpath=\""); 4705 if (realpath) { 4706 realpath += 8; 4707 len += ccs_truncate(realpath) + 6; 4708 } 4709 symlink = strstr(header, " symlink.target=\""); 4710 if (symlink) 4711 len += ccs_truncate(symlink + 1) + 1; 4712 } 4713 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER 4714 handler = strstr(header, "type=execute_handler"); 4715 if (handler) 4716 len += ccs_truncate(handler) + 6; 4717 #endif 4718 buffer = kmalloc(len, CCS_GFP_FLAGS); 4719 if (!buffer) 4720 return; 4721 snprintf(buffer, len - 1, "%s", cp); 4722 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER 4723 if (handler) 4724 ccs_addprintf(buffer, len, " task.%s", handler); 4725 #endif 4726 if (realpath) 4727 ccs_addprintf(buffer, len, " exec.%s", realpath); 4728 if (argv0) 4729 ccs_addprintf(buffer, len, " exec.argv[0]=%s", argv0); 4730 if (symlink) 4731 ccs_addprintf(buffer, len, "%s", symlink); 4732 ccs_normalize_line(buffer); 4733 { 4734 struct ccs_domain_info *domain = ccs_current_domain(); 4735 if (!ccs_write_acl(domain->ns, &domain->acl_info_list, 4736 buffer, false)) 4737 ccs_update_stat(CCS_STAT_POLICY_UPDATES); 4738 } 4739 kfree(buffer); 4740 } 4741 4742 /** 4743 * ccs_domain_quota_ok - Check for domain's quota. 4744 * 4745 * @r: Pointer to "struct ccs_request_info". 4746 * 4747 * Returns true if the domain is not exceeded quota, false otherwise. 4748 * 4749 * Caller holds ccs_read_lock(). 4750 */ 4751 static bool ccs_domain_quota_ok(struct ccs_request_info *r) 4752 { 4753 unsigned int count = 0; 4754 struct ccs_domain_info * const domain = ccs_current_domain(); 4755 struct ccs_acl_info *ptr; 4756 if (r->mode != CCS_CONFIG_LEARNING) 4757 return false; 4758 if (!domain) 4759 return true; 4760 list_for_each_entry_srcu(ptr, &domain->acl_info_list, list, &ccs_ss) { 4761 u16 perm; 4762 u8 i; 4763 if (ptr->is_deleted) 4764 continue; 4765 switch (ptr->type) { 4766 case CCS_TYPE_PATH_ACL: 4767 case CCS_TYPE_PATH2_ACL: 4768 case CCS_TYPE_PATH_NUMBER_ACL: 4769 case CCS_TYPE_MKDEV_ACL: 4770 #ifdef CONFIG_CCSECURITY_NETWORK 4771 case CCS_TYPE_INET_ACL: 4772 case CCS_TYPE_UNIX_ACL: 4773 #endif 4774 perm = ptr->perm; 4775 break; 4776 #ifdef CONFIG_CCSECURITY_TASK_EXECUTE_HANDLER 4777 case CCS_TYPE_AUTO_EXECUTE_HANDLER: 4778 case CCS_TYPE_DENIED_EXECUTE_HANDLER: 4779 #endif 4780 #ifdef CONFIG_CCSECURITY_TASK_DOMAIN_TRANSITION 4781 case CCS_TYPE_AUTO_TASK_ACL: 4782 case CCS_TYPE_MANUAL_TASK_ACL: 4783 #endif 4784 perm = 0; 4785 break; 4786 default: 4787 perm = 1; 4788 } 4789 for (i = 0; i < 16; i++) 4790 if (perm & (1 << i)) 4791 count++; 4792 } 4793 if (count < ccs_profile(r->profile)->pref[CCS_PREF_MAX_LEARNING_ENTRY]) 4794 return true; 4795 if (!domain->flags[CCS_DIF_QUOTA_WARNED]) { 4796 domain->flags[CCS_DIF_QUOTA_WARNED] = true; 4797 /* r->granted = false; */ 4798 ccs_write_log(r, "%s", ccs_dif[CCS_DIF_QUOTA_WARNED]); 4799 printk(KERN_WARNING "WARNING: " 4800 "Domain '%s' has too many ACLs to hold. " 4801 "Stopped learning mode.\n", domain->domainname->name); 4802 } 4803 return false; 4804 } 4805 4806 /** 4807 * ccs_supervisor - Ask for the supervisor's decision. 4808 * 4809 * @r: Pointer to "struct ccs_request_info". 4810 * @fmt: The printf()'s format string, followed by parameters. 4811 * 4812 * Returns 0 if the supervisor decided to permit the access request which 4813 * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor 4814 * decided to retry the access request which violated the policy in enforcing 4815 * mode, 0 if it is not in enforcing mode, -EPERM otherwise. 4816 */ 4817 static int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...) 4818 { 4819 va_list args; 4820 int error; 4821 int len; 4822 static unsigned int ccs_serial; 4823 struct ccs_query entry = { }; 4824 bool quota_exceeded = false; 4825 va_start(args, fmt); 4826 len = vsnprintf((char *) &len, 1, fmt, args) + 1; 4827 va_end(args); 4828 /* Write /proc/ccs/audit. */ 4829 va_start(args, fmt); 4830 ccs_write_log2(r, len, fmt, args); 4831 va_end(args); 4832 /* Nothing more to do if granted. */ 4833 if (r->granted) 4834 return 0; 4835 if (r->mode) 4836 ccs_update_stat(r->mode); 4837 switch (r->mode) { 4838 int i; 4839 struct ccs_profile *p; 4840 case CCS_CONFIG_ENFORCING: 4841 error = -EPERM; 4842 if (atomic_read(&ccs_query_observers)) 4843 break; 4844 if (r->dont_sleep_on_enforce_error) 4845 goto out; 4846 p = ccs_profile(r->profile); 4847 /* Check enforcing_penalty parameter. */ 4848 for (i = 0; i < p->pref[CCS_PREF_ENFORCING_PENALTY]; i++) { 4849 set_current_state(TASK_INTERRUPTIBLE); 4850 schedule_timeout(HZ / 10); 4851 } 4852 goto out; 4853 case CCS_CONFIG_LEARNING: 4854 error = 0; 4855 /* Check max_learning_entry parameter. */ 4856 if (ccs_domain_quota_ok(r)) 4857 break; 4858 /* fall through */ 4859 default: 4860 return 0; 4861 } 4862 /* Get message. */ 4863 va_start(args, fmt); 4864 entry.query = ccs_init_log(r, len, fmt, args); 4865 va_end(args); 4866 if (!entry.query) 4867 goto out; 4868 entry.query_len = strlen(entry.query) + 1; 4869 if (!error) { 4870 ccs_add_entry(entry.query); 4871 goto out; 4872 } 4873 len = ccs_round2(entry.query_len); 4874 entry.domain = ccs_current_domain(); 4875 spin_lock(&ccs_query_list_lock); 4876 if (ccs_memory_quota[CCS_MEMORY_QUERY] && 4877 ccs_memory_used[CCS_MEMORY_QUERY] + len 4878 >= ccs_memory_quota[CCS_MEMORY_QUERY]) { 4879 quota_exceeded = true; 4880 } else { 4881 entry.serial = ccs_serial++; 4882 entry.retry = r->retry; 4883 ccs_memory_used[CCS_MEMORY_QUERY] += len; 4884 list_add_tail(&entry.list, &ccs_query_list); 4885 } 4886 spin_unlock(&ccs_query_list_lock); 4887 if (quota_exceeded) 4888 goto out; 4889 /* Give 10 seconds for supervisor's opinion. */ 4890 while (entry.timer < 10) { 4891 wake_up_all(&ccs_query_wait); 4892 if (wait_event_interruptible_timeout 4893 (ccs_answer_wait, entry.answer || 4894 !atomic_read(&ccs_query_observers), HZ)) 4895 break; 4896 else 4897 entry.timer++; 4898 } 4899 spin_lock(&ccs_query_list_lock); 4900 list_del(&entry.list); 4901 ccs_memory_used[CCS_MEMORY_QUERY] -= len; 4902 spin_unlock(&ccs_query_list_lock); 4903 switch (entry.answer) { 4904 case 3: /* Asked to retry by administrator. */ 4905 error = CCS_RETRY_REQUEST; 4906 r->retry++; 4907 break; 4908 case 1: 4909 /* Granted by administrator. */ 4910 error = 0; 4911 break; 4912 default: 4913 /* Timed out or rejected by administrator. */ 4914 break; 4915 } 4916 out: 4917 kfree(entry.query); 4918 return error; 4919 } 4920 4921 /** 4922 * ccs_audit_log - Audit permission check log. 4923 * 4924 * @r: Pointer to "struct ccs_request_info". 4925 * 4926 * Returns return value of ccs_supervisor(). 4927 */ 4928 int ccs_audit_log(struct ccs_request_info *r) 4929 { 4930 switch (r->param_type) { 4931 u8 type; 4932 char buf[48]; 4933 #ifdef CONFIG_CCSECURITY_NETWORK 4934 const u32 *address; 4935 #endif 4936 case CCS_TYPE_PATH_ACL: 4937 return ccs_supervisor(r, "file %s %s\n", ccs_path_keyword 4938 [r->param.path.operation], 4939 r->param.path.filename->name); 4940 case CCS_TYPE_PATH2_ACL: 4941 return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords 4942 [ccs_pp2mac[r->param.path2.operation]], 4943 r->param.path2.filename1->name, 4944 r->param.path2.filename2->name); 4945 case CCS_TYPE_PATH_NUMBER_ACL: 4946 type = r->param.path_number.operation; 4947 switch (type) { 4948 case CCS_TYPE_CREATE: 4949 case CCS_TYPE_MKDIR: 4950 case CCS_TYPE_MKFIFO: 4951 case CCS_TYPE_MKSOCK: 4952 case CCS_TYPE_CHMOD: 4953 snprintf(buf, sizeof(buf), "0%lo", 4954 r->param.path_number.number); 4955 break; 4956 case CCS_TYPE_IOCTL: 4957 snprintf(buf, sizeof(buf), "0x%lX", 4958 r->param.path_number.number); 4959 break; 4960 default: 4961 snprintf(buf, sizeof(buf), "%lu", 4962 r->param.path_number.number); 4963 break; 4964 } 4965 return ccs_supervisor(r, "file %s %s %s\n", ccs_mac_keywords 4966 [ccs_pn2mac[type]], 4967 r->param.path_number.filename->name, 4968 buf); 4969 case CCS_TYPE_MKDEV_ACL: 4970 return ccs_supervisor(r, "file %s %s 0%o %u %u\n", 4971 ccs_mac_keywords 4972 [ccs_pnnn2mac[r->param.mkdev.operation]], 4973 r->param.mkdev.filename->name, 4974 r->param.mkdev.mode, 4975 r->param.mkdev.major, 4976 r->param.mkdev.minor); 4977 case CCS_TYPE_MOUNT_ACL: 4978 return ccs_supervisor(r, "file mount %s %s %s 0x%lX\n", 4979 r->param.mount.dev->name, 4980 r->param.mount.dir->name, 4981 r->param.mount.type->name, 4982 r->param.mount.flags); 4983 #ifdef CONFIG_CCSECURITY_MISC 4984 case CCS_TYPE_ENV_ACL: 4985 return ccs_supervisor(r, "misc env %s\n", 4986 r->param.environ.name->name); 4987 #endif 4988 #ifdef CONFIG_CCSECURITY_CAPABILITY 4989 case CCS_TYPE_CAPABILITY_ACL: 4990 return ccs_supervisor(r, "capability %s\n", ccs_mac_keywords 4991 [ccs_c2mac[r->param.capability. 4992 operation]]); 4993 #endif 4994 #ifdef CONFIG_CCSECURITY_NETWORK 4995 case CCS_TYPE_INET_ACL: 4996 address = r->param.inet_network.address; 4997 if (r->param.inet_network.is_ipv6) 4998 ccs_print_ipv6(buf, sizeof(buf), 4999 (const struct in6_addr *) address); 5000 else 5001 ccs_print_ipv4(buf, sizeof(buf), address); 5002 return ccs_supervisor(r, "network inet %s %s %s %u\n", 5003 ccs_proto_keyword[r->param.inet_network. 5004 protocol], 5005 ccs_socket_keyword[r->param.inet_network. 5006 operation], 5007 buf, r->param.inet_network.port); 5008 case CCS_TYPE_UNIX_ACL: 5009 return ccs_supervisor(r, "network unix %s %s %s\n", 5010 ccs_proto_keyword[r->param. 5011 unix_network.protocol], 5012 ccs_socket_keyword[r->param.unix_network. 5013 operation], 5014 r->param.unix_network.address->name); 5015 #endif 5016 #ifdef CONFIG_CCSECURITY_IPC 5017 case CCS_TYPE_SIGNAL_ACL: 5018 return ccs_supervisor(r, "ipc signal %d %s\n", 5019 r->param.signal.sig, 5020 r->param.signal.dest_pattern); 5021 #endif 5022 } 5023 return 0; 5024 } 5025 5026 /** 5027 * ccs_find_domain_by_qid - Get domain by query id. 5028 * 5029 * @serial: Query ID assigned by ccs_supervisor(). 5030 * 5031 * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise. 5032 */ 5033 static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial) 5034 { 5035 struct ccs_query *ptr; 5036 struct ccs_domain_info *domain = NULL; 5037 spin_lock(&ccs_query_list_lock); 5038 list_for_each_entry(ptr, &ccs_query_list, list) { 5039 if (ptr->serial != serial) 5040 continue; 5041 domain = ptr->domain; 5042 break; 5043 } 5044 spin_unlock(&ccs_query_list_lock); 5045 return domain; 5046 } 5047 5048 /** 5049 * ccs_read_query - Read access requests which violated policy in enforcing mode. 5050 * 5051 * @head: Pointer to "struct ccs_io_buffer". 5052 * 5053 * Returns nothing. 5054 */ 5055 static void ccs_read_query(struct ccs_io_buffer *head) 5056 { 5057 struct list_head *tmp; 5058 unsigned int pos = 0; 5059 size_t len = 0; 5060 char *buf; 5061 if (head->r.w_pos) 5062 return; 5063 kfree(head->read_buf); 5064 head->read_buf = NULL; 5065 spin_lock(&ccs_query_list_lock); 5066 list_for_each(tmp, &ccs_query_list) { 5067 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); 5068 if (pos++ != head->r.query_index) 5069 continue; 5070 len = ptr->query_len; 5071 break; 5072 } 5073 spin_unlock(&ccs_query_list_lock); 5074 if (!len) { 5075 head->r.query_index = 0; 5076 return; 5077 } 5078 buf = kzalloc(len + 32, CCS_GFP_FLAGS); 5079 if (!buf) 5080 return; 5081 pos = 0; 5082 spin_lock(&ccs_query_list_lock); 5083 list_for_each(tmp, &ccs_query_list) { 5084 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); 5085 if (pos++ != head->r.query_index) 5086 continue; 5087 /* 5088 * Some query can be skipped because ccs_query_list 5089 * can change, but I don't care. 5090 */ 5091 if (len == ptr->query_len) 5092 snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial, 5093 ptr->retry, ptr->query); 5094 break; 5095 } 5096 spin_unlock(&ccs_query_list_lock); 5097 if (buf[0]) { 5098 head->read_buf = buf; 5099 head->r.w[head->r.w_pos++] = buf; 5100 head->r.query_index++; 5101 } else { 5102 kfree(buf); 5103 } 5104 } 5105 5106 /** 5107 * ccs_write_answer - Write the supervisor's decision. 5108 * 5109 * @head: Pointer to "struct ccs_io_buffer". 5110 * 5111 * Returns 0 on success, -EINVAL otherwise. 5112 */ 5113 static int ccs_write_answer(struct ccs_io_buffer *head) 5114 { 5115 char *data = head->write_buf; 5116 struct list_head *tmp; 5117 unsigned int serial; 5118 unsigned int answer; 5119 spin_lock(&ccs_query_list_lock); 5120 list_for_each(tmp, &ccs_query_list) { 5121 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); 5122 ptr->timer = 0; 5123 } 5124 spin_unlock(&ccs_query_list_lock); 5125 if (sscanf(data, "A%u=%u", &serial, &answer) != 2) 5126 return -EINVAL; 5127 spin_lock(&ccs_query_list_lock); 5128 list_for_each(tmp, &ccs_query_list) { 5129 struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list); 5130 if (ptr->serial != serial) 5131 continue; 5132 ptr->answer = (u8) answer; 5133 /* Remove from ccs_query_list. */ 5134 if (ptr->answer) { 5135 list_del(&ptr->list); 5136 INIT_LIST_HEAD(&ptr->list); 5137 } 5138 break; 5139 } 5140 spin_unlock(&ccs_query_list_lock); 5141 wake_up_all(&ccs_answer_wait); 5142 return 0; 5143 } 5144 5145 /** 5146 * ccs_read_version - Get version. 5147 * 5148 * @head: Pointer to "struct ccs_io_buffer". 5149 * 5150 * Returns nothing. 5151 */ 5152 static void ccs_read_version(struct ccs_io_buffer *head) 5153 { 5154 if (head->r.eof) 5155 return; 5156 ccs_set_string(head, "1.8.6"); 5157 head->r.eof = true; 5158 } 5159 5160 /** 5161 * ccs_update_stat - Update statistic counters. 5162 * 5163 * @index: Index for policy type. 5164 * 5165 * Returns nothing. 5166 */ 5167 static void ccs_update_stat(const u8 index) 5168 { 5169 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) 5170 struct timeval tv; 5171 #endif 5172 5173 atomic_inc(&ccs_stat_updated[index]); 5174 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) 5175 do_gettimeofday(&tv); 5176 ccs_stat_modified[index] = tv.tv_sec; 5177 #elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) 5178 ccs_stat_modified[index] = get_seconds(); 5179 #else 5180 ccs_stat_modified[index] = ktime_get_real_seconds(); 5181 #endif 5182 } 5183 5184 /** 5185 * ccs_read_stat - Read statistic data. 5186 * 5187 * @head: Pointer to "struct ccs_io_buffer". 5188 * 5189 * Returns nothing. 5190 */ 5191 static void ccs_read_stat(struct ccs_io_buffer *head) 5192 { 5193 u8 i; 5194 unsigned int total = 0; 5195 if (head->r.eof) 5196 return; 5197 for (i = 0; i < CCS_MAX_POLICY_STAT; i++) { 5198 ccs_io_printf(head, "Policy %-30s %10u", ccs_policy_headers[i], 5199 atomic_read(&ccs_stat_updated[i])); 5200 if (ccs_stat_modified[i]) { 5201 struct ccs_time stamp; 5202 ccs_convert_time(ccs_stat_modified[i], &stamp); 5203 ccs_io_printf(head, " (Last: %04u/%02u/%02u " 5204 "%02u:%02u:%02u)", 5205 stamp.year, stamp.month, stamp.day, 5206 stamp.hour, stamp.min, stamp.sec); 5207 } 5208 ccs_set_lf(head); 5209 } 5210 for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) { 5211 unsigned int used = ccs_memory_used[i]; 5212 total += used; 5213 ccs_io_printf(head, "Memory used by %-22s %10u", 5214 ccs_memory_headers[i], used); 5215 used = ccs_memory_quota[i]; 5216 if (used) 5217 ccs_io_printf(head, " (Quota: %10u)", used); 5218 ccs_set_lf(head); 5219 } 5220 ccs_io_printf(head, "Total memory used: %10u\n", 5221 total); 5222 head->r.eof = true; 5223 } 5224 5225 /** 5226 * ccs_write_stat - Set memory quota. 5227 * 5228 * @head: Pointer to "struct ccs_io_buffer". 5229 * 5230 * Returns 0. 5231 */ 5232 static int ccs_write_stat(struct ccs_io_buffer *head) 5233 { 5234 char *data = head->write_buf; 5235 u8 i; 5236 if (ccs_str_starts(&data, "Memory used by ")) 5237 for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) 5238 if (ccs_str_starts(&data, ccs_memory_headers[i])) { 5239 if (*data == ' ') 5240 data++; 5241 ccs_memory_quota[i] = 5242 simple_strtoul(data, NULL, 10); 5243 } 5244 return 0; 5245 } 5246 5247 /** 5248 * ccs_print_bprm - Print "struct linux_binprm" for auditing. 5249 * 5250 * @bprm: Pointer to "struct linux_binprm". 5251 * @dump: Pointer to "struct ccs_page_dump". 5252 * 5253 * Returns the contents of @bprm on success, NULL otherwise. 5254 * 5255 * This function uses kzalloc(), so caller must kfree() if this function 5256 * didn't return NULL. 5257 */ 5258 static char *ccs_print_bprm(struct linux_binprm *bprm, 5259 struct ccs_page_dump *dump) 5260 { 5261 static const int ccs_buffer_len = 4096 * 2; 5262 char *buffer = kzalloc(ccs_buffer_len, CCS_GFP_FLAGS); 5263 char *cp; 5264 char *last_start; 5265 int len; 5266 unsigned long pos = bprm->p; 5267 int offset = pos % PAGE_SIZE; 5268 int argv_count = bprm->argc; 5269 int envp_count = bprm->envc; 5270 bool truncated = false; 5271 if (!buffer) 5272 return NULL; 5273 len = snprintf(buffer, ccs_buffer_len - 1, "argv[]={ "); 5274 cp = buffer + len; 5275 if (!argv_count) { 5276 memmove(cp, "} envp[]={ ", 11); 5277 cp += 11; 5278 } 5279 last_start = cp; 5280 while (argv_count || envp_count) { 5281 if (!ccs_dump_page(bprm, pos, dump)) 5282 goto out; 5283 pos += PAGE_SIZE - offset; 5284 /* Read. */ 5285 while (offset < P