162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * security/tomoyo/audit.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2005-2011 NTT DATA CORPORATION 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "common.h" 962306a36Sopenharmony_ci#include <linux/slab.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/** 1262306a36Sopenharmony_ci * tomoyo_print_bprm - Print "struct linux_binprm" for auditing. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * @bprm: Pointer to "struct linux_binprm". 1562306a36Sopenharmony_ci * @dump: Pointer to "struct tomoyo_page_dump". 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci * Returns the contents of @bprm on success, NULL otherwise. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * This function uses kzalloc(), so caller must kfree() if this function 2062306a36Sopenharmony_ci * didn't return NULL. 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_cistatic char *tomoyo_print_bprm(struct linux_binprm *bprm, 2362306a36Sopenharmony_ci struct tomoyo_page_dump *dump) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci static const int tomoyo_buffer_len = 4096 * 2; 2662306a36Sopenharmony_ci char *buffer = kzalloc(tomoyo_buffer_len, GFP_NOFS); 2762306a36Sopenharmony_ci char *cp; 2862306a36Sopenharmony_ci char *last_start; 2962306a36Sopenharmony_ci int len; 3062306a36Sopenharmony_ci unsigned long pos = bprm->p; 3162306a36Sopenharmony_ci int offset = pos % PAGE_SIZE; 3262306a36Sopenharmony_ci int argv_count = bprm->argc; 3362306a36Sopenharmony_ci int envp_count = bprm->envc; 3462306a36Sopenharmony_ci bool truncated = false; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci if (!buffer) 3762306a36Sopenharmony_ci return NULL; 3862306a36Sopenharmony_ci len = snprintf(buffer, tomoyo_buffer_len - 1, "argv[]={ "); 3962306a36Sopenharmony_ci cp = buffer + len; 4062306a36Sopenharmony_ci if (!argv_count) { 4162306a36Sopenharmony_ci memmove(cp, "} envp[]={ ", 11); 4262306a36Sopenharmony_ci cp += 11; 4362306a36Sopenharmony_ci } 4462306a36Sopenharmony_ci last_start = cp; 4562306a36Sopenharmony_ci while (argv_count || envp_count) { 4662306a36Sopenharmony_ci if (!tomoyo_dump_page(bprm, pos, dump)) 4762306a36Sopenharmony_ci goto out; 4862306a36Sopenharmony_ci pos += PAGE_SIZE - offset; 4962306a36Sopenharmony_ci /* Read. */ 5062306a36Sopenharmony_ci while (offset < PAGE_SIZE) { 5162306a36Sopenharmony_ci const char *kaddr = dump->data; 5262306a36Sopenharmony_ci const unsigned char c = kaddr[offset++]; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (cp == last_start) 5562306a36Sopenharmony_ci *cp++ = '"'; 5662306a36Sopenharmony_ci if (cp >= buffer + tomoyo_buffer_len - 32) { 5762306a36Sopenharmony_ci /* Reserve some room for "..." string. */ 5862306a36Sopenharmony_ci truncated = true; 5962306a36Sopenharmony_ci } else if (c == '\\') { 6062306a36Sopenharmony_ci *cp++ = '\\'; 6162306a36Sopenharmony_ci *cp++ = '\\'; 6262306a36Sopenharmony_ci } else if (c > ' ' && c < 127) { 6362306a36Sopenharmony_ci *cp++ = c; 6462306a36Sopenharmony_ci } else if (!c) { 6562306a36Sopenharmony_ci *cp++ = '"'; 6662306a36Sopenharmony_ci *cp++ = ' '; 6762306a36Sopenharmony_ci last_start = cp; 6862306a36Sopenharmony_ci } else { 6962306a36Sopenharmony_ci *cp++ = '\\'; 7062306a36Sopenharmony_ci *cp++ = (c >> 6) + '0'; 7162306a36Sopenharmony_ci *cp++ = ((c >> 3) & 7) + '0'; 7262306a36Sopenharmony_ci *cp++ = (c & 7) + '0'; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci if (c) 7562306a36Sopenharmony_ci continue; 7662306a36Sopenharmony_ci if (argv_count) { 7762306a36Sopenharmony_ci if (--argv_count == 0) { 7862306a36Sopenharmony_ci if (truncated) { 7962306a36Sopenharmony_ci cp = last_start; 8062306a36Sopenharmony_ci memmove(cp, "... ", 4); 8162306a36Sopenharmony_ci cp += 4; 8262306a36Sopenharmony_ci } 8362306a36Sopenharmony_ci memmove(cp, "} envp[]={ ", 11); 8462306a36Sopenharmony_ci cp += 11; 8562306a36Sopenharmony_ci last_start = cp; 8662306a36Sopenharmony_ci truncated = false; 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci } else if (envp_count) { 8962306a36Sopenharmony_ci if (--envp_count == 0) { 9062306a36Sopenharmony_ci if (truncated) { 9162306a36Sopenharmony_ci cp = last_start; 9262306a36Sopenharmony_ci memmove(cp, "... ", 4); 9362306a36Sopenharmony_ci cp += 4; 9462306a36Sopenharmony_ci } 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci if (!argv_count && !envp_count) 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci offset = 0; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci *cp++ = '}'; 10362306a36Sopenharmony_ci *cp = '\0'; 10462306a36Sopenharmony_ci return buffer; 10562306a36Sopenharmony_ciout: 10662306a36Sopenharmony_ci snprintf(buffer, tomoyo_buffer_len - 1, 10762306a36Sopenharmony_ci "argv[]={ ... } envp[]= { ... }"); 10862306a36Sopenharmony_ci return buffer; 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/** 11262306a36Sopenharmony_ci * tomoyo_filetype - Get string representation of file type. 11362306a36Sopenharmony_ci * 11462306a36Sopenharmony_ci * @mode: Mode value for stat(). 11562306a36Sopenharmony_ci * 11662306a36Sopenharmony_ci * Returns file type string. 11762306a36Sopenharmony_ci */ 11862306a36Sopenharmony_cistatic inline const char *tomoyo_filetype(const umode_t mode) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci switch (mode & S_IFMT) { 12162306a36Sopenharmony_ci case S_IFREG: 12262306a36Sopenharmony_ci case 0: 12362306a36Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FILE]; 12462306a36Sopenharmony_ci case S_IFDIR: 12562306a36Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_DIRECTORY]; 12662306a36Sopenharmony_ci case S_IFLNK: 12762306a36Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SYMLINK]; 12862306a36Sopenharmony_ci case S_IFIFO: 12962306a36Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FIFO]; 13062306a36Sopenharmony_ci case S_IFSOCK: 13162306a36Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SOCKET]; 13262306a36Sopenharmony_ci case S_IFBLK: 13362306a36Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_BLOCK_DEV]; 13462306a36Sopenharmony_ci case S_IFCHR: 13562306a36Sopenharmony_ci return tomoyo_condition_keyword[TOMOYO_TYPE_IS_CHAR_DEV]; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci return "unknown"; /* This should not happen. */ 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci/** 14162306a36Sopenharmony_ci * tomoyo_print_header - Get header line of audit log. 14262306a36Sopenharmony_ci * 14362306a36Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci * Returns string representation. 14662306a36Sopenharmony_ci * 14762306a36Sopenharmony_ci * This function uses kmalloc(), so caller must kfree() if this function 14862306a36Sopenharmony_ci * didn't return NULL. 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_cistatic char *tomoyo_print_header(struct tomoyo_request_info *r) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci struct tomoyo_time stamp; 15362306a36Sopenharmony_ci const pid_t gpid = task_pid_nr(current); 15462306a36Sopenharmony_ci struct tomoyo_obj_info *obj = r->obj; 15562306a36Sopenharmony_ci static const int tomoyo_buffer_len = 4096; 15662306a36Sopenharmony_ci char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); 15762306a36Sopenharmony_ci int pos; 15862306a36Sopenharmony_ci u8 i; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci if (!buffer) 16162306a36Sopenharmony_ci return NULL; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci tomoyo_convert_time(ktime_get_real_seconds(), &stamp); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci pos = snprintf(buffer, tomoyo_buffer_len - 1, 16662306a36Sopenharmony_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 }", 16762306a36Sopenharmony_ci stamp.year, stamp.month, stamp.day, stamp.hour, 16862306a36Sopenharmony_ci stamp.min, stamp.sec, r->profile, tomoyo_mode[r->mode], 16962306a36Sopenharmony_ci str_yes_no(r->granted), gpid, tomoyo_sys_getpid(), 17062306a36Sopenharmony_ci tomoyo_sys_getppid(), 17162306a36Sopenharmony_ci from_kuid(&init_user_ns, current_uid()), 17262306a36Sopenharmony_ci from_kgid(&init_user_ns, current_gid()), 17362306a36Sopenharmony_ci from_kuid(&init_user_ns, current_euid()), 17462306a36Sopenharmony_ci from_kgid(&init_user_ns, current_egid()), 17562306a36Sopenharmony_ci from_kuid(&init_user_ns, current_suid()), 17662306a36Sopenharmony_ci from_kgid(&init_user_ns, current_sgid()), 17762306a36Sopenharmony_ci from_kuid(&init_user_ns, current_fsuid()), 17862306a36Sopenharmony_ci from_kgid(&init_user_ns, current_fsgid())); 17962306a36Sopenharmony_ci if (!obj) 18062306a36Sopenharmony_ci goto no_obj_info; 18162306a36Sopenharmony_ci if (!obj->validate_done) { 18262306a36Sopenharmony_ci tomoyo_get_attributes(obj); 18362306a36Sopenharmony_ci obj->validate_done = true; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) { 18662306a36Sopenharmony_ci struct tomoyo_mini_stat *stat; 18762306a36Sopenharmony_ci unsigned int dev; 18862306a36Sopenharmony_ci umode_t mode; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (!obj->stat_valid[i]) 19162306a36Sopenharmony_ci continue; 19262306a36Sopenharmony_ci stat = &obj->stat[i]; 19362306a36Sopenharmony_ci dev = stat->dev; 19462306a36Sopenharmony_ci mode = stat->mode; 19562306a36Sopenharmony_ci if (i & 1) { 19662306a36Sopenharmony_ci pos += snprintf(buffer + pos, 19762306a36Sopenharmony_ci tomoyo_buffer_len - 1 - pos, 19862306a36Sopenharmony_ci " path%u.parent={ uid=%u gid=%u ino=%lu perm=0%o }", 19962306a36Sopenharmony_ci (i >> 1) + 1, 20062306a36Sopenharmony_ci from_kuid(&init_user_ns, stat->uid), 20162306a36Sopenharmony_ci from_kgid(&init_user_ns, stat->gid), 20262306a36Sopenharmony_ci (unsigned long)stat->ino, 20362306a36Sopenharmony_ci stat->mode & S_IALLUGO); 20462306a36Sopenharmony_ci continue; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos, 20762306a36Sopenharmony_ci " path%u={ uid=%u gid=%u ino=%lu major=%u minor=%u perm=0%o type=%s", 20862306a36Sopenharmony_ci (i >> 1) + 1, 20962306a36Sopenharmony_ci from_kuid(&init_user_ns, stat->uid), 21062306a36Sopenharmony_ci from_kgid(&init_user_ns, stat->gid), 21162306a36Sopenharmony_ci (unsigned long)stat->ino, 21262306a36Sopenharmony_ci MAJOR(dev), MINOR(dev), 21362306a36Sopenharmony_ci mode & S_IALLUGO, tomoyo_filetype(mode)); 21462306a36Sopenharmony_ci if (S_ISCHR(mode) || S_ISBLK(mode)) { 21562306a36Sopenharmony_ci dev = stat->rdev; 21662306a36Sopenharmony_ci pos += snprintf(buffer + pos, 21762306a36Sopenharmony_ci tomoyo_buffer_len - 1 - pos, 21862306a36Sopenharmony_ci " dev_major=%u dev_minor=%u", 21962306a36Sopenharmony_ci MAJOR(dev), MINOR(dev)); 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos, 22262306a36Sopenharmony_ci " }"); 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_cino_obj_info: 22562306a36Sopenharmony_ci if (pos < tomoyo_buffer_len - 1) 22662306a36Sopenharmony_ci return buffer; 22762306a36Sopenharmony_ci kfree(buffer); 22862306a36Sopenharmony_ci return NULL; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci/** 23262306a36Sopenharmony_ci * tomoyo_init_log - Allocate buffer for audit logs. 23362306a36Sopenharmony_ci * 23462306a36Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 23562306a36Sopenharmony_ci * @len: Buffer size needed for @fmt and @args. 23662306a36Sopenharmony_ci * @fmt: The printf()'s format string. 23762306a36Sopenharmony_ci * @args: va_list structure for @fmt. 23862306a36Sopenharmony_ci * 23962306a36Sopenharmony_ci * Returns pointer to allocated memory. 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci * This function uses kzalloc(), so caller must kfree() if this function 24262306a36Sopenharmony_ci * didn't return NULL. 24362306a36Sopenharmony_ci */ 24462306a36Sopenharmony_cichar *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, 24562306a36Sopenharmony_ci va_list args) 24662306a36Sopenharmony_ci{ 24762306a36Sopenharmony_ci char *buf = NULL; 24862306a36Sopenharmony_ci char *bprm_info = NULL; 24962306a36Sopenharmony_ci const char *header = NULL; 25062306a36Sopenharmony_ci char *realpath = NULL; 25162306a36Sopenharmony_ci const char *symlink = NULL; 25262306a36Sopenharmony_ci int pos; 25362306a36Sopenharmony_ci const char *domainname = r->domain->domainname->name; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci header = tomoyo_print_header(r); 25662306a36Sopenharmony_ci if (!header) 25762306a36Sopenharmony_ci return NULL; 25862306a36Sopenharmony_ci /* +10 is for '\n' etc. and '\0'. */ 25962306a36Sopenharmony_ci len += strlen(domainname) + strlen(header) + 10; 26062306a36Sopenharmony_ci if (r->ee) { 26162306a36Sopenharmony_ci struct file *file = r->ee->bprm->file; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci realpath = tomoyo_realpath_from_path(&file->f_path); 26462306a36Sopenharmony_ci bprm_info = tomoyo_print_bprm(r->ee->bprm, &r->ee->dump); 26562306a36Sopenharmony_ci if (!realpath || !bprm_info) 26662306a36Sopenharmony_ci goto out; 26762306a36Sopenharmony_ci /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */ 26862306a36Sopenharmony_ci len += strlen(realpath) + 80 + strlen(bprm_info); 26962306a36Sopenharmony_ci } else if (r->obj && r->obj->symlink_target) { 27062306a36Sopenharmony_ci symlink = r->obj->symlink_target->name; 27162306a36Sopenharmony_ci /* +18 is for " symlink.target=\"%s\"" */ 27262306a36Sopenharmony_ci len += 18 + strlen(symlink); 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci len = kmalloc_size_roundup(len); 27562306a36Sopenharmony_ci buf = kzalloc(len, GFP_NOFS); 27662306a36Sopenharmony_ci if (!buf) 27762306a36Sopenharmony_ci goto out; 27862306a36Sopenharmony_ci len--; 27962306a36Sopenharmony_ci pos = snprintf(buf, len, "%s", header); 28062306a36Sopenharmony_ci if (realpath) { 28162306a36Sopenharmony_ci struct linux_binprm *bprm = r->ee->bprm; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci pos += snprintf(buf + pos, len - pos, 28462306a36Sopenharmony_ci " exec={ realpath=\"%s\" argc=%d envc=%d %s }", 28562306a36Sopenharmony_ci realpath, bprm->argc, bprm->envc, bprm_info); 28662306a36Sopenharmony_ci } else if (symlink) 28762306a36Sopenharmony_ci pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"", 28862306a36Sopenharmony_ci symlink); 28962306a36Sopenharmony_ci pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname); 29062306a36Sopenharmony_ci vsnprintf(buf + pos, len - pos, fmt, args); 29162306a36Sopenharmony_ciout: 29262306a36Sopenharmony_ci kfree(realpath); 29362306a36Sopenharmony_ci kfree(bprm_info); 29462306a36Sopenharmony_ci kfree(header); 29562306a36Sopenharmony_ci return buf; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci/* Wait queue for /sys/kernel/security/tomoyo/audit. */ 29962306a36Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci/* Structure for audit log. */ 30262306a36Sopenharmony_cistruct tomoyo_log { 30362306a36Sopenharmony_ci struct list_head list; 30462306a36Sopenharmony_ci char *log; 30562306a36Sopenharmony_ci int size; 30662306a36Sopenharmony_ci}; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci/* The list for "struct tomoyo_log". */ 30962306a36Sopenharmony_cistatic LIST_HEAD(tomoyo_log); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/* Lock for "struct list_head tomoyo_log". */ 31262306a36Sopenharmony_cistatic DEFINE_SPINLOCK(tomoyo_log_lock); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci/* Length of "struct list_head tomoyo_log". */ 31562306a36Sopenharmony_cistatic unsigned int tomoyo_log_count; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci/** 31862306a36Sopenharmony_ci * tomoyo_get_audit - Get audit mode. 31962306a36Sopenharmony_ci * 32062306a36Sopenharmony_ci * @ns: Pointer to "struct tomoyo_policy_namespace". 32162306a36Sopenharmony_ci * @profile: Profile number. 32262306a36Sopenharmony_ci * @index: Index number of functionality. 32362306a36Sopenharmony_ci * @matched_acl: Pointer to "struct tomoyo_acl_info". 32462306a36Sopenharmony_ci * @is_granted: True if granted log, false otherwise. 32562306a36Sopenharmony_ci * 32662306a36Sopenharmony_ci * Returns true if this request should be audited, false otherwise. 32762306a36Sopenharmony_ci */ 32862306a36Sopenharmony_cistatic bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns, 32962306a36Sopenharmony_ci const u8 profile, const u8 index, 33062306a36Sopenharmony_ci const struct tomoyo_acl_info *matched_acl, 33162306a36Sopenharmony_ci const bool is_granted) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci u8 mode; 33462306a36Sopenharmony_ci const u8 category = tomoyo_index2category[index] + 33562306a36Sopenharmony_ci TOMOYO_MAX_MAC_INDEX; 33662306a36Sopenharmony_ci struct tomoyo_profile *p; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci if (!tomoyo_policy_loaded) 33962306a36Sopenharmony_ci return false; 34062306a36Sopenharmony_ci p = tomoyo_profile(ns, profile); 34162306a36Sopenharmony_ci if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG]) 34262306a36Sopenharmony_ci return false; 34362306a36Sopenharmony_ci if (is_granted && matched_acl && matched_acl->cond && 34462306a36Sopenharmony_ci matched_acl->cond->grant_log != TOMOYO_GRANTLOG_AUTO) 34562306a36Sopenharmony_ci return matched_acl->cond->grant_log == TOMOYO_GRANTLOG_YES; 34662306a36Sopenharmony_ci mode = p->config[index]; 34762306a36Sopenharmony_ci if (mode == TOMOYO_CONFIG_USE_DEFAULT) 34862306a36Sopenharmony_ci mode = p->config[category]; 34962306a36Sopenharmony_ci if (mode == TOMOYO_CONFIG_USE_DEFAULT) 35062306a36Sopenharmony_ci mode = p->default_config; 35162306a36Sopenharmony_ci if (is_granted) 35262306a36Sopenharmony_ci return mode & TOMOYO_CONFIG_WANT_GRANT_LOG; 35362306a36Sopenharmony_ci return mode & TOMOYO_CONFIG_WANT_REJECT_LOG; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci/** 35762306a36Sopenharmony_ci * tomoyo_write_log2 - Write an audit log. 35862306a36Sopenharmony_ci * 35962306a36Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 36062306a36Sopenharmony_ci * @len: Buffer size needed for @fmt and @args. 36162306a36Sopenharmony_ci * @fmt: The printf()'s format string. 36262306a36Sopenharmony_ci * @args: va_list structure for @fmt. 36362306a36Sopenharmony_ci * 36462306a36Sopenharmony_ci * Returns nothing. 36562306a36Sopenharmony_ci */ 36662306a36Sopenharmony_civoid tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, 36762306a36Sopenharmony_ci va_list args) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci char *buf; 37062306a36Sopenharmony_ci struct tomoyo_log *entry; 37162306a36Sopenharmony_ci bool quota_exceeded = false; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type, 37462306a36Sopenharmony_ci r->matched_acl, r->granted)) 37562306a36Sopenharmony_ci goto out; 37662306a36Sopenharmony_ci buf = tomoyo_init_log(r, len, fmt, args); 37762306a36Sopenharmony_ci if (!buf) 37862306a36Sopenharmony_ci goto out; 37962306a36Sopenharmony_ci entry = kzalloc(sizeof(*entry), GFP_NOFS); 38062306a36Sopenharmony_ci if (!entry) { 38162306a36Sopenharmony_ci kfree(buf); 38262306a36Sopenharmony_ci goto out; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci entry->log = buf; 38562306a36Sopenharmony_ci len = kmalloc_size_roundup(strlen(buf) + 1); 38662306a36Sopenharmony_ci /* 38762306a36Sopenharmony_ci * The entry->size is used for memory quota checks. 38862306a36Sopenharmony_ci * Don't go beyond strlen(entry->log). 38962306a36Sopenharmony_ci */ 39062306a36Sopenharmony_ci entry->size = len + kmalloc_size_roundup(sizeof(*entry)); 39162306a36Sopenharmony_ci spin_lock(&tomoyo_log_lock); 39262306a36Sopenharmony_ci if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] && 39362306a36Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >= 39462306a36Sopenharmony_ci tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT]) { 39562306a36Sopenharmony_ci quota_exceeded = true; 39662306a36Sopenharmony_ci } else { 39762306a36Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] += entry->size; 39862306a36Sopenharmony_ci list_add_tail(&entry->list, &tomoyo_log); 39962306a36Sopenharmony_ci tomoyo_log_count++; 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci spin_unlock(&tomoyo_log_lock); 40262306a36Sopenharmony_ci if (quota_exceeded) { 40362306a36Sopenharmony_ci kfree(buf); 40462306a36Sopenharmony_ci kfree(entry); 40562306a36Sopenharmony_ci goto out; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci wake_up(&tomoyo_log_wait); 40862306a36Sopenharmony_ciout: 40962306a36Sopenharmony_ci return; 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci/** 41362306a36Sopenharmony_ci * tomoyo_write_log - Write an audit log. 41462306a36Sopenharmony_ci * 41562306a36Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 41662306a36Sopenharmony_ci * @fmt: The printf()'s format string, followed by parameters. 41762306a36Sopenharmony_ci * 41862306a36Sopenharmony_ci * Returns nothing. 41962306a36Sopenharmony_ci */ 42062306a36Sopenharmony_civoid tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci va_list args; 42362306a36Sopenharmony_ci int len; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci va_start(args, fmt); 42662306a36Sopenharmony_ci len = vsnprintf(NULL, 0, fmt, args) + 1; 42762306a36Sopenharmony_ci va_end(args); 42862306a36Sopenharmony_ci va_start(args, fmt); 42962306a36Sopenharmony_ci tomoyo_write_log2(r, len, fmt, args); 43062306a36Sopenharmony_ci va_end(args); 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci/** 43462306a36Sopenharmony_ci * tomoyo_read_log - Read an audit log. 43562306a36Sopenharmony_ci * 43662306a36Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 43762306a36Sopenharmony_ci * 43862306a36Sopenharmony_ci * Returns nothing. 43962306a36Sopenharmony_ci */ 44062306a36Sopenharmony_civoid tomoyo_read_log(struct tomoyo_io_buffer *head) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci struct tomoyo_log *ptr = NULL; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (head->r.w_pos) 44562306a36Sopenharmony_ci return; 44662306a36Sopenharmony_ci kfree(head->read_buf); 44762306a36Sopenharmony_ci head->read_buf = NULL; 44862306a36Sopenharmony_ci spin_lock(&tomoyo_log_lock); 44962306a36Sopenharmony_ci if (!list_empty(&tomoyo_log)) { 45062306a36Sopenharmony_ci ptr = list_entry(tomoyo_log.next, typeof(*ptr), list); 45162306a36Sopenharmony_ci list_del(&ptr->list); 45262306a36Sopenharmony_ci tomoyo_log_count--; 45362306a36Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] -= ptr->size; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci spin_unlock(&tomoyo_log_lock); 45662306a36Sopenharmony_ci if (ptr) { 45762306a36Sopenharmony_ci head->read_buf = ptr->log; 45862306a36Sopenharmony_ci head->r.w[head->r.w_pos++] = head->read_buf; 45962306a36Sopenharmony_ci kfree(ptr); 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci/** 46462306a36Sopenharmony_ci * tomoyo_poll_log - Wait for an audit log. 46562306a36Sopenharmony_ci * 46662306a36Sopenharmony_ci * @file: Pointer to "struct file". 46762306a36Sopenharmony_ci * @wait: Pointer to "poll_table". Maybe NULL. 46862306a36Sopenharmony_ci * 46962306a36Sopenharmony_ci * Returns EPOLLIN | EPOLLRDNORM when ready to read an audit log. 47062306a36Sopenharmony_ci */ 47162306a36Sopenharmony_ci__poll_t tomoyo_poll_log(struct file *file, poll_table *wait) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci if (tomoyo_log_count) 47462306a36Sopenharmony_ci return EPOLLIN | EPOLLRDNORM; 47562306a36Sopenharmony_ci poll_wait(file, &tomoyo_log_wait, wait); 47662306a36Sopenharmony_ci if (tomoyo_log_count) 47762306a36Sopenharmony_ci return EPOLLIN | EPOLLRDNORM; 47862306a36Sopenharmony_ci return 0; 47962306a36Sopenharmony_ci} 480