18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * security/tomoyo/audit.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005-2011 NTT DATA CORPORATION 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "common.h" 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci/** 128c2ecf20Sopenharmony_ci * tomoyo_print_bprm - Print "struct linux_binprm" for auditing. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * @bprm: Pointer to "struct linux_binprm". 158c2ecf20Sopenharmony_ci * @dump: Pointer to "struct tomoyo_page_dump". 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * Returns the contents of @bprm on success, NULL otherwise. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * This function uses kzalloc(), so caller must kfree() if this function 208c2ecf20Sopenharmony_ci * didn't return NULL. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_cistatic char *tomoyo_print_bprm(struct linux_binprm *bprm, 238c2ecf20Sopenharmony_ci struct tomoyo_page_dump *dump) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci static const int tomoyo_buffer_len = 4096 * 2; 268c2ecf20Sopenharmony_ci char *buffer = kzalloc(tomoyo_buffer_len, GFP_NOFS); 278c2ecf20Sopenharmony_ci char *cp; 288c2ecf20Sopenharmony_ci char *last_start; 298c2ecf20Sopenharmony_ci int len; 308c2ecf20Sopenharmony_ci unsigned long pos = bprm->p; 318c2ecf20Sopenharmony_ci int offset = pos % PAGE_SIZE; 328c2ecf20Sopenharmony_ci int argv_count = bprm->argc; 338c2ecf20Sopenharmony_ci int envp_count = bprm->envc; 348c2ecf20Sopenharmony_ci bool truncated = false; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci if (!buffer) 378c2ecf20Sopenharmony_ci return NULL; 388c2ecf20Sopenharmony_ci len = snprintf(buffer, tomoyo_buffer_len - 1, "argv[]={ "); 398c2ecf20Sopenharmony_ci cp = buffer + len; 408c2ecf20Sopenharmony_ci if (!argv_count) { 418c2ecf20Sopenharmony_ci memmove(cp, "} envp[]={ ", 11); 428c2ecf20Sopenharmony_ci cp += 11; 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci last_start = cp; 458c2ecf20Sopenharmony_ci while (argv_count || envp_count) { 468c2ecf20Sopenharmony_ci if (!tomoyo_dump_page(bprm, pos, dump)) 478c2ecf20Sopenharmony_ci goto out; 488c2ecf20Sopenharmony_ci pos += PAGE_SIZE - offset; 498c2ecf20Sopenharmony_ci /* Read. */ 508c2ecf20Sopenharmony_ci while (offset < PAGE_SIZE) { 518c2ecf20Sopenharmony_ci const char *kaddr = dump->data; 528c2ecf20Sopenharmony_ci const unsigned char c = kaddr[offset++]; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci if (cp == last_start) 558c2ecf20Sopenharmony_ci *cp++ = '"'; 568c2ecf20Sopenharmony_ci if (cp >= buffer + tomoyo_buffer_len - 32) { 578c2ecf20Sopenharmony_ci /* Reserve some room for "..." string. */ 588c2ecf20Sopenharmony_ci truncated = true; 598c2ecf20Sopenharmony_ci } else if (c == '\\') { 608c2ecf20Sopenharmony_ci *cp++ = '\\'; 618c2ecf20Sopenharmony_ci *cp++ = '\\'; 628c2ecf20Sopenharmony_ci } else if (c > ' ' && c < 127) { 638c2ecf20Sopenharmony_ci *cp++ = c; 648c2ecf20Sopenharmony_ci } else if (!c) { 658c2ecf20Sopenharmony_ci *cp++ = '"'; 668c2ecf20Sopenharmony_ci *cp++ = ' '; 678c2ecf20Sopenharmony_ci last_start = cp; 688c2ecf20Sopenharmony_ci } else { 698c2ecf20Sopenharmony_ci *cp++ = '\\'; 708c2ecf20Sopenharmony_ci *cp++ = (c >> 6) + '0'; 718c2ecf20Sopenharmony_ci *cp++ = ((c >> 3) & 7) + '0'; 728c2ecf20Sopenharmony_ci *cp++ = (c & 7) + '0'; 738c2ecf20Sopenharmony_ci } 748c2ecf20Sopenharmony_ci if (c) 758c2ecf20Sopenharmony_ci continue; 768c2ecf20Sopenharmony_ci if (argv_count) { 778c2ecf20Sopenharmony_ci if (--argv_count == 0) { 788c2ecf20Sopenharmony_ci if (truncated) { 798c2ecf20Sopenharmony_ci cp = last_start; 808c2ecf20Sopenharmony_ci memmove(cp, "... ", 4); 818c2ecf20Sopenharmony_ci cp += 4; 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci memmove(cp, "} envp[]={ ", 11); 848c2ecf20Sopenharmony_ci cp += 11; 858c2ecf20Sopenharmony_ci last_start = cp; 868c2ecf20Sopenharmony_ci truncated = false; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci } else if (envp_count) { 898c2ecf20Sopenharmony_ci if (--envp_count == 0) { 908c2ecf20Sopenharmony_ci if (truncated) { 918c2ecf20Sopenharmony_ci cp = last_start; 928c2ecf20Sopenharmony_ci memmove(cp, "... ", 4); 938c2ecf20Sopenharmony_ci cp += 4; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci } 978c2ecf20Sopenharmony_ci if (!argv_count && !envp_count) 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci offset = 0; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci *cp++ = '}'; 1038c2ecf20Sopenharmony_ci *cp = '\0'; 1048c2ecf20Sopenharmony_ci return buffer; 1058c2ecf20Sopenharmony_ciout: 1068c2ecf20Sopenharmony_ci snprintf(buffer, tomoyo_buffer_len - 1, 1078c2ecf20Sopenharmony_ci "argv[]={ ... } envp[]= { ... }"); 1088c2ecf20Sopenharmony_ci return buffer; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci/** 1128c2ecf20Sopenharmony_ci * tomoyo_filetype - Get string representation of file type. 1138c2ecf20Sopenharmony_ci * 1148c2ecf20Sopenharmony_ci * @mode: Mode value for stat(). 1158c2ecf20Sopenharmony_ci * 1168c2ecf20Sopenharmony_ci * Returns file type string. 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_cistatic inline const char *tomoyo_filetype(const umode_t mode) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci switch (mode & S_IFMT) { 1218c2ecf20Sopenharmony_ci case S_IFREG: 1228c2ecf20Sopenharmony_ci case 0: 1238c2ecf20Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FILE]; 1248c2ecf20Sopenharmony_ci case S_IFDIR: 1258c2ecf20Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_DIRECTORY]; 1268c2ecf20Sopenharmony_ci case S_IFLNK: 1278c2ecf20Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SYMLINK]; 1288c2ecf20Sopenharmony_ci case S_IFIFO: 1298c2ecf20Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FIFO]; 1308c2ecf20Sopenharmony_ci case S_IFSOCK: 1318c2ecf20Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SOCKET]; 1328c2ecf20Sopenharmony_ci case S_IFBLK: 1338c2ecf20Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_BLOCK_DEV]; 1348c2ecf20Sopenharmony_ci case S_IFCHR: 1358c2ecf20Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_CHAR_DEV]; 1368c2ecf20Sopenharmony_ci } 1378c2ecf20Sopenharmony_ci return "unknown"; /* This should not happen. */ 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/** 1418c2ecf20Sopenharmony_ci * tomoyo_print_header - Get header line of audit log. 1428c2ecf20Sopenharmony_ci * 1438c2ecf20Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 1448c2ecf20Sopenharmony_ci * 1458c2ecf20Sopenharmony_ci * Returns string representation. 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * This function uses kmalloc(), so caller must kfree() if this function 1488c2ecf20Sopenharmony_ci * didn't return NULL. 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_cistatic char *tomoyo_print_header(struct tomoyo_request_info *r) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci struct tomoyo_time stamp; 1538c2ecf20Sopenharmony_ci const pid_t gpid = task_pid_nr(current); 1548c2ecf20Sopenharmony_ci struct tomoyo_obj_info *obj = r->obj; 1558c2ecf20Sopenharmony_ci static const int tomoyo_buffer_len = 4096; 1568c2ecf20Sopenharmony_ci char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); 1578c2ecf20Sopenharmony_ci int pos; 1588c2ecf20Sopenharmony_ci u8 i; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (!buffer) 1618c2ecf20Sopenharmony_ci return NULL; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci tomoyo_convert_time(ktime_get_real_seconds(), &stamp); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci pos = snprintf(buffer, tomoyo_buffer_len - 1, 1668c2ecf20Sopenharmony_ci "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s granted=%s (global-pid=%u) task={ pid=%u ppid=%u uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", 1678c2ecf20Sopenharmony_ci stamp.year, stamp.month, stamp.day, stamp.hour, 1688c2ecf20Sopenharmony_ci stamp.min, stamp.sec, r->profile, tomoyo_mode[r->mode], 1698c2ecf20Sopenharmony_ci tomoyo_yesno(r->granted), gpid, tomoyo_sys_getpid(), 1708c2ecf20Sopenharmony_ci tomoyo_sys_getppid(), 1718c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, current_uid()), 1728c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, current_gid()), 1738c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, current_euid()), 1748c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, current_egid()), 1758c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, current_suid()), 1768c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, current_sgid()), 1778c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, current_fsuid()), 1788c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, current_fsgid())); 1798c2ecf20Sopenharmony_ci if (!obj) 1808c2ecf20Sopenharmony_ci goto no_obj_info; 1818c2ecf20Sopenharmony_ci if (!obj->validate_done) { 1828c2ecf20Sopenharmony_ci tomoyo_get_attributes(obj); 1838c2ecf20Sopenharmony_ci obj->validate_done = true; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) { 1868c2ecf20Sopenharmony_ci struct tomoyo_mini_stat *stat; 1878c2ecf20Sopenharmony_ci unsigned int dev; 1888c2ecf20Sopenharmony_ci umode_t mode; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if (!obj->stat_valid[i]) 1918c2ecf20Sopenharmony_ci continue; 1928c2ecf20Sopenharmony_ci stat = &obj->stat[i]; 1938c2ecf20Sopenharmony_ci dev = stat->dev; 1948c2ecf20Sopenharmony_ci mode = stat->mode; 1958c2ecf20Sopenharmony_ci if (i & 1) { 1968c2ecf20Sopenharmony_ci pos += snprintf(buffer + pos, 1978c2ecf20Sopenharmony_ci tomoyo_buffer_len - 1 - pos, 1988c2ecf20Sopenharmony_ci " path%u.parent={ uid=%u gid=%u ino=%lu perm=0%o }", 1998c2ecf20Sopenharmony_ci (i >> 1) + 1, 2008c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, stat->uid), 2018c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, stat->gid), 2028c2ecf20Sopenharmony_ci (unsigned long)stat->ino, 2038c2ecf20Sopenharmony_ci stat->mode & S_IALLUGO); 2048c2ecf20Sopenharmony_ci continue; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ci pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos, 2078c2ecf20Sopenharmony_ci " path%u={ uid=%u gid=%u ino=%lu major=%u minor=%u perm=0%o type=%s", 2088c2ecf20Sopenharmony_ci (i >> 1) + 1, 2098c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, stat->uid), 2108c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, stat->gid), 2118c2ecf20Sopenharmony_ci (unsigned long)stat->ino, 2128c2ecf20Sopenharmony_ci MAJOR(dev), MINOR(dev), 2138c2ecf20Sopenharmony_ci mode & S_IALLUGO, tomoyo_filetype(mode)); 2148c2ecf20Sopenharmony_ci if (S_ISCHR(mode) || S_ISBLK(mode)) { 2158c2ecf20Sopenharmony_ci dev = stat->rdev; 2168c2ecf20Sopenharmony_ci pos += snprintf(buffer + pos, 2178c2ecf20Sopenharmony_ci tomoyo_buffer_len - 1 - pos, 2188c2ecf20Sopenharmony_ci " dev_major=%u dev_minor=%u", 2198c2ecf20Sopenharmony_ci MAJOR(dev), MINOR(dev)); 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos, 2228c2ecf20Sopenharmony_ci " }"); 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_cino_obj_info: 2258c2ecf20Sopenharmony_ci if (pos < tomoyo_buffer_len - 1) 2268c2ecf20Sopenharmony_ci return buffer; 2278c2ecf20Sopenharmony_ci kfree(buffer); 2288c2ecf20Sopenharmony_ci return NULL; 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci/** 2328c2ecf20Sopenharmony_ci * tomoyo_init_log - Allocate buffer for audit logs. 2338c2ecf20Sopenharmony_ci * 2348c2ecf20Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 2358c2ecf20Sopenharmony_ci * @len: Buffer size needed for @fmt and @args. 2368c2ecf20Sopenharmony_ci * @fmt: The printf()'s format string. 2378c2ecf20Sopenharmony_ci * @args: va_list structure for @fmt. 2388c2ecf20Sopenharmony_ci * 2398c2ecf20Sopenharmony_ci * Returns pointer to allocated memory. 2408c2ecf20Sopenharmony_ci * 2418c2ecf20Sopenharmony_ci * This function uses kzalloc(), so caller must kfree() if this function 2428c2ecf20Sopenharmony_ci * didn't return NULL. 2438c2ecf20Sopenharmony_ci */ 2448c2ecf20Sopenharmony_cichar *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, 2458c2ecf20Sopenharmony_ci va_list args) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci char *buf = NULL; 2488c2ecf20Sopenharmony_ci char *bprm_info = NULL; 2498c2ecf20Sopenharmony_ci const char *header = NULL; 2508c2ecf20Sopenharmony_ci char *realpath = NULL; 2518c2ecf20Sopenharmony_ci const char *symlink = NULL; 2528c2ecf20Sopenharmony_ci int pos; 2538c2ecf20Sopenharmony_ci const char *domainname = r->domain->domainname->name; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci header = tomoyo_print_header(r); 2568c2ecf20Sopenharmony_ci if (!header) 2578c2ecf20Sopenharmony_ci return NULL; 2588c2ecf20Sopenharmony_ci /* +10 is for '\n' etc. and '\0'. */ 2598c2ecf20Sopenharmony_ci len += strlen(domainname) + strlen(header) + 10; 2608c2ecf20Sopenharmony_ci if (r->ee) { 2618c2ecf20Sopenharmony_ci struct file *file = r->ee->bprm->file; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci realpath = tomoyo_realpath_from_path(&file->f_path); 2648c2ecf20Sopenharmony_ci bprm_info = tomoyo_print_bprm(r->ee->bprm, &r->ee->dump); 2658c2ecf20Sopenharmony_ci if (!realpath || !bprm_info) 2668c2ecf20Sopenharmony_ci goto out; 2678c2ecf20Sopenharmony_ci /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */ 2688c2ecf20Sopenharmony_ci len += strlen(realpath) + 80 + strlen(bprm_info); 2698c2ecf20Sopenharmony_ci } else if (r->obj && r->obj->symlink_target) { 2708c2ecf20Sopenharmony_ci symlink = r->obj->symlink_target->name; 2718c2ecf20Sopenharmony_ci /* +18 is for " symlink.target=\"%s\"" */ 2728c2ecf20Sopenharmony_ci len += 18 + strlen(symlink); 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci len = tomoyo_round2(len); 2758c2ecf20Sopenharmony_ci buf = kzalloc(len, GFP_NOFS); 2768c2ecf20Sopenharmony_ci if (!buf) 2778c2ecf20Sopenharmony_ci goto out; 2788c2ecf20Sopenharmony_ci len--; 2798c2ecf20Sopenharmony_ci pos = snprintf(buf, len, "%s", header); 2808c2ecf20Sopenharmony_ci if (realpath) { 2818c2ecf20Sopenharmony_ci struct linux_binprm *bprm = r->ee->bprm; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci pos += snprintf(buf + pos, len - pos, 2848c2ecf20Sopenharmony_ci " exec={ realpath=\"%s\" argc=%d envc=%d %s }", 2858c2ecf20Sopenharmony_ci realpath, bprm->argc, bprm->envc, bprm_info); 2868c2ecf20Sopenharmony_ci } else if (symlink) 2878c2ecf20Sopenharmony_ci pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"", 2888c2ecf20Sopenharmony_ci symlink); 2898c2ecf20Sopenharmony_ci pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname); 2908c2ecf20Sopenharmony_ci vsnprintf(buf + pos, len - pos, fmt, args); 2918c2ecf20Sopenharmony_ciout: 2928c2ecf20Sopenharmony_ci kfree(realpath); 2938c2ecf20Sopenharmony_ci kfree(bprm_info); 2948c2ecf20Sopenharmony_ci kfree(header); 2958c2ecf20Sopenharmony_ci return buf; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci/* Wait queue for /sys/kernel/security/tomoyo/audit. */ 2998c2ecf20Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci/* Structure for audit log. */ 3028c2ecf20Sopenharmony_cistruct tomoyo_log { 3038c2ecf20Sopenharmony_ci struct list_head list; 3048c2ecf20Sopenharmony_ci char *log; 3058c2ecf20Sopenharmony_ci int size; 3068c2ecf20Sopenharmony_ci}; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci/* The list for "struct tomoyo_log". */ 3098c2ecf20Sopenharmony_cistatic LIST_HEAD(tomoyo_log); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci/* Lock for "struct list_head tomoyo_log". */ 3128c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(tomoyo_log_lock); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci/* Length of "stuct list_head tomoyo_log". */ 3158c2ecf20Sopenharmony_cistatic unsigned int tomoyo_log_count; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci/** 3188c2ecf20Sopenharmony_ci * tomoyo_get_audit - Get audit mode. 3198c2ecf20Sopenharmony_ci * 3208c2ecf20Sopenharmony_ci * @ns: Pointer to "struct tomoyo_policy_namespace". 3218c2ecf20Sopenharmony_ci * @profile: Profile number. 3228c2ecf20Sopenharmony_ci * @index: Index number of functionality. 3238c2ecf20Sopenharmony_ci * @is_granted: True if granted log, false otherwise. 3248c2ecf20Sopenharmony_ci * 3258c2ecf20Sopenharmony_ci * Returns true if this request should be audited, false otherwise. 3268c2ecf20Sopenharmony_ci */ 3278c2ecf20Sopenharmony_cistatic bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns, 3288c2ecf20Sopenharmony_ci const u8 profile, const u8 index, 3298c2ecf20Sopenharmony_ci const struct tomoyo_acl_info *matched_acl, 3308c2ecf20Sopenharmony_ci const bool is_granted) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci u8 mode; 3338c2ecf20Sopenharmony_ci const u8 category = tomoyo_index2category[index] + 3348c2ecf20Sopenharmony_ci TOMOYO_MAX_MAC_INDEX; 3358c2ecf20Sopenharmony_ci struct tomoyo_profile *p; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci if (!tomoyo_policy_loaded) 3388c2ecf20Sopenharmony_ci return false; 3398c2ecf20Sopenharmony_ci p = tomoyo_profile(ns, profile); 3408c2ecf20Sopenharmony_ci if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG]) 3418c2ecf20Sopenharmony_ci return false; 3428c2ecf20Sopenharmony_ci if (is_granted && matched_acl && matched_acl->cond && 3438c2ecf20Sopenharmony_ci matched_acl->cond->grant_log != TOMOYO_GRANTLOG_AUTO) 3448c2ecf20Sopenharmony_ci return matched_acl->cond->grant_log == TOMOYO_GRANTLOG_YES; 3458c2ecf20Sopenharmony_ci mode = p->config[index]; 3468c2ecf20Sopenharmony_ci if (mode == TOMOYO_CONFIG_USE_DEFAULT) 3478c2ecf20Sopenharmony_ci mode = p->config[category]; 3488c2ecf20Sopenharmony_ci if (mode == TOMOYO_CONFIG_USE_DEFAULT) 3498c2ecf20Sopenharmony_ci mode = p->default_config; 3508c2ecf20Sopenharmony_ci if (is_granted) 3518c2ecf20Sopenharmony_ci return mode & TOMOYO_CONFIG_WANT_GRANT_LOG; 3528c2ecf20Sopenharmony_ci return mode & TOMOYO_CONFIG_WANT_REJECT_LOG; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci/** 3568c2ecf20Sopenharmony_ci * tomoyo_write_log2 - Write an audit log. 3578c2ecf20Sopenharmony_ci * 3588c2ecf20Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 3598c2ecf20Sopenharmony_ci * @len: Buffer size needed for @fmt and @args. 3608c2ecf20Sopenharmony_ci * @fmt: The printf()'s format string. 3618c2ecf20Sopenharmony_ci * @args: va_list structure for @fmt. 3628c2ecf20Sopenharmony_ci * 3638c2ecf20Sopenharmony_ci * Returns nothing. 3648c2ecf20Sopenharmony_ci */ 3658c2ecf20Sopenharmony_civoid tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, 3668c2ecf20Sopenharmony_ci va_list args) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci char *buf; 3698c2ecf20Sopenharmony_ci struct tomoyo_log *entry; 3708c2ecf20Sopenharmony_ci bool quota_exceeded = false; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type, 3738c2ecf20Sopenharmony_ci r->matched_acl, r->granted)) 3748c2ecf20Sopenharmony_ci goto out; 3758c2ecf20Sopenharmony_ci buf = tomoyo_init_log(r, len, fmt, args); 3768c2ecf20Sopenharmony_ci if (!buf) 3778c2ecf20Sopenharmony_ci goto out; 3788c2ecf20Sopenharmony_ci entry = kzalloc(sizeof(*entry), GFP_NOFS); 3798c2ecf20Sopenharmony_ci if (!entry) { 3808c2ecf20Sopenharmony_ci kfree(buf); 3818c2ecf20Sopenharmony_ci goto out; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci entry->log = buf; 3848c2ecf20Sopenharmony_ci len = tomoyo_round2(strlen(buf) + 1); 3858c2ecf20Sopenharmony_ci /* 3868c2ecf20Sopenharmony_ci * The entry->size is used for memory quota checks. 3878c2ecf20Sopenharmony_ci * Don't go beyond strlen(entry->log). 3888c2ecf20Sopenharmony_ci */ 3898c2ecf20Sopenharmony_ci entry->size = len + tomoyo_round2(sizeof(*entry)); 3908c2ecf20Sopenharmony_ci spin_lock(&tomoyo_log_lock); 3918c2ecf20Sopenharmony_ci if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] && 3928c2ecf20Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >= 3938c2ecf20Sopenharmony_ci tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT]) { 3948c2ecf20Sopenharmony_ci quota_exceeded = true; 3958c2ecf20Sopenharmony_ci } else { 3968c2ecf20Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] += entry->size; 3978c2ecf20Sopenharmony_ci list_add_tail(&entry->list, &tomoyo_log); 3988c2ecf20Sopenharmony_ci tomoyo_log_count++; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_log_lock); 4018c2ecf20Sopenharmony_ci if (quota_exceeded) { 4028c2ecf20Sopenharmony_ci kfree(buf); 4038c2ecf20Sopenharmony_ci kfree(entry); 4048c2ecf20Sopenharmony_ci goto out; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci wake_up(&tomoyo_log_wait); 4078c2ecf20Sopenharmony_ciout: 4088c2ecf20Sopenharmony_ci return; 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci/** 4128c2ecf20Sopenharmony_ci * tomoyo_write_log - Write an audit log. 4138c2ecf20Sopenharmony_ci * 4148c2ecf20Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 4158c2ecf20Sopenharmony_ci * @fmt: The printf()'s format string, followed by parameters. 4168c2ecf20Sopenharmony_ci * 4178c2ecf20Sopenharmony_ci * Returns nothing. 4188c2ecf20Sopenharmony_ci */ 4198c2ecf20Sopenharmony_civoid tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci va_list args; 4228c2ecf20Sopenharmony_ci int len; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci va_start(args, fmt); 4258c2ecf20Sopenharmony_ci len = vsnprintf((char *) &len, 1, fmt, args) + 1; 4268c2ecf20Sopenharmony_ci va_end(args); 4278c2ecf20Sopenharmony_ci va_start(args, fmt); 4288c2ecf20Sopenharmony_ci tomoyo_write_log2(r, len, fmt, args); 4298c2ecf20Sopenharmony_ci va_end(args); 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci/** 4338c2ecf20Sopenharmony_ci * tomoyo_read_log - Read an audit log. 4348c2ecf20Sopenharmony_ci * 4358c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 4368c2ecf20Sopenharmony_ci * 4378c2ecf20Sopenharmony_ci * Returns nothing. 4388c2ecf20Sopenharmony_ci */ 4398c2ecf20Sopenharmony_civoid tomoyo_read_log(struct tomoyo_io_buffer *head) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci struct tomoyo_log *ptr = NULL; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci if (head->r.w_pos) 4448c2ecf20Sopenharmony_ci return; 4458c2ecf20Sopenharmony_ci kfree(head->read_buf); 4468c2ecf20Sopenharmony_ci head->read_buf = NULL; 4478c2ecf20Sopenharmony_ci spin_lock(&tomoyo_log_lock); 4488c2ecf20Sopenharmony_ci if (!list_empty(&tomoyo_log)) { 4498c2ecf20Sopenharmony_ci ptr = list_entry(tomoyo_log.next, typeof(*ptr), list); 4508c2ecf20Sopenharmony_ci list_del(&ptr->list); 4518c2ecf20Sopenharmony_ci tomoyo_log_count--; 4528c2ecf20Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] -= ptr->size; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_log_lock); 4558c2ecf20Sopenharmony_ci if (ptr) { 4568c2ecf20Sopenharmony_ci head->read_buf = ptr->log; 4578c2ecf20Sopenharmony_ci head->r.w[head->r.w_pos++] = head->read_buf; 4588c2ecf20Sopenharmony_ci kfree(ptr); 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci/** 4638c2ecf20Sopenharmony_ci * tomoyo_poll_log - Wait for an audit log. 4648c2ecf20Sopenharmony_ci * 4658c2ecf20Sopenharmony_ci * @file: Pointer to "struct file". 4668c2ecf20Sopenharmony_ci * @wait: Pointer to "poll_table". Maybe NULL. 4678c2ecf20Sopenharmony_ci * 4688c2ecf20Sopenharmony_ci * Returns EPOLLIN | EPOLLRDNORM when ready to read an audit log. 4698c2ecf20Sopenharmony_ci */ 4708c2ecf20Sopenharmony_ci__poll_t tomoyo_poll_log(struct file *file, poll_table *wait) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci if (tomoyo_log_count) 4738c2ecf20Sopenharmony_ci return EPOLLIN | EPOLLRDNORM; 4748c2ecf20Sopenharmony_ci poll_wait(file, &tomoyo_log_wait, wait); 4758c2ecf20Sopenharmony_ci if (tomoyo_log_count) 4768c2ecf20Sopenharmony_ci return EPOLLIN | EPOLLRDNORM; 4778c2ecf20Sopenharmony_ci return 0; 4788c2ecf20Sopenharmony_ci} 479