audit.c revision bd03a3e4c9a9df0c6b007045fa7fc8889111a478
1/* 2 * security/tomoyo/audit.c 3 * 4 * Pathname restriction functions. 5 * 6 * Copyright (C) 2005-2010 NTT DATA CORPORATION 7 */ 8 9#include "common.h" 10#include <linux/slab.h> 11 12/** 13 * tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss. 14 * 15 * @time: Seconds since 1970/01/01 00:00:00. 16 * @stamp: Pointer to "struct tomoyo_time". 17 * 18 * Returns nothing. 19 * 20 * This function does not handle Y2038 problem. 21 */ 22static void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp) 23{ 24 static const u16 tomoyo_eom[2][12] = { 25 { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 26 { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } 27 }; 28 u16 y; 29 u8 m; 30 bool r; 31 stamp->sec = time % 60; 32 time /= 60; 33 stamp->min = time % 60; 34 time /= 60; 35 stamp->hour = time % 24; 36 time /= 24; 37 for (y = 1970; ; y++) { 38 const unsigned short days = (y & 3) ? 365 : 366; 39 if (time < days) 40 break; 41 time -= days; 42 } 43 r = (y & 3) == 0; 44 for (m = 0; m < 11 && time >= tomoyo_eom[r][m]; m++) 45 ; 46 if (m) 47 time -= tomoyo_eom[r][m - 1]; 48 stamp->year = y; 49 stamp->month = ++m; 50 stamp->day = ++time; 51} 52 53/** 54 * tomoyo_print_header - Get header line of audit log. 55 * 56 * @r: Pointer to "struct tomoyo_request_info". 57 * 58 * Returns string representation. 59 * 60 * This function uses kmalloc(), so caller must kfree() if this function 61 * didn't return NULL. 62 */ 63static char *tomoyo_print_header(struct tomoyo_request_info *r) 64{ 65 struct tomoyo_time stamp; 66 const pid_t gpid = task_pid_nr(current); 67 static const int tomoyo_buffer_len = 4096; 68 char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); 69 pid_t ppid; 70 if (!buffer) 71 return NULL; 72 { 73 struct timeval tv; 74 do_gettimeofday(&tv); 75 tomoyo_convert_time(tv.tv_sec, &stamp); 76 } 77 rcu_read_lock(); 78 ppid = task_tgid_vnr(current->real_parent); 79 rcu_read_unlock(); 80 snprintf(buffer, tomoyo_buffer_len - 1, 81 "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s " 82 "granted=%s (global-pid=%u) task={ pid=%u ppid=%u " 83 "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u " 84 "fsuid=%u fsgid=%u }", 85 stamp.year, stamp.month, stamp.day, stamp.hour, 86 stamp.min, stamp.sec, r->profile, tomoyo_mode[r->mode], 87 tomoyo_yesno(r->granted), gpid, task_tgid_vnr(current), ppid, 88 current_uid(), current_gid(), current_euid(), current_egid(), 89 current_suid(), current_sgid(), current_fsuid(), 90 current_fsgid()); 91 return buffer; 92} 93 94/** 95 * tomoyo_init_log - Allocate buffer for audit logs. 96 * 97 * @r: Pointer to "struct tomoyo_request_info". 98 * @len: Buffer size needed for @fmt and @args. 99 * @fmt: The printf()'s format string. 100 * @args: va_list structure for @fmt. 101 * 102 * Returns pointer to allocated memory. 103 * 104 * This function uses kzalloc(), so caller must kfree() if this function 105 * didn't return NULL. 106 */ 107char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, 108 va_list args) 109{ 110 char *buf = NULL; 111 const char *header = NULL; 112 int pos; 113 const char *domainname = tomoyo_domain()->domainname->name; 114 header = tomoyo_print_header(r); 115 if (!header) 116 return NULL; 117 /* +10 is for '\n' etc. and '\0'. */ 118 len += strlen(domainname) + strlen(header) + 10; 119 len = tomoyo_round2(len); 120 buf = kzalloc(len, GFP_NOFS); 121 if (!buf) 122 goto out; 123 len--; 124 pos = snprintf(buf, len, "%s", header); 125 pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname); 126 vsnprintf(buf + pos, len - pos, fmt, args); 127out: 128 kfree(header); 129 return buf; 130} 131 132/* Wait queue for /sys/kernel/security/tomoyo/audit. */ 133static DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait); 134 135/* Structure for audit log. */ 136struct tomoyo_log { 137 struct list_head list; 138 char *log; 139 int size; 140}; 141 142/* The list for "struct tomoyo_log". */ 143static LIST_HEAD(tomoyo_log); 144 145/* Lock for "struct list_head tomoyo_log". */ 146static DEFINE_SPINLOCK(tomoyo_log_lock); 147 148/* Length of "stuct list_head tomoyo_log". */ 149static unsigned int tomoyo_log_count; 150 151/** 152 * tomoyo_get_audit - Get audit mode. 153 * 154 * @ns: Pointer to "struct tomoyo_policy_namespace". 155 * @profile: Profile number. 156 * @index: Index number of functionality. 157 * @is_granted: True if granted log, false otherwise. 158 * 159 * Returns true if this request should be audited, false otherwise. 160 */ 161static bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns, 162 const u8 profile, const u8 index, 163 const bool is_granted) 164{ 165 u8 mode; 166 const u8 category = TOMOYO_MAC_CATEGORY_FILE + TOMOYO_MAX_MAC_INDEX; 167 struct tomoyo_profile *p; 168 if (!tomoyo_policy_loaded) 169 return false; 170 p = tomoyo_profile(ns, profile); 171 if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG]) 172 return false; 173 mode = p->config[index]; 174 if (mode == TOMOYO_CONFIG_USE_DEFAULT) 175 mode = p->config[category]; 176 if (mode == TOMOYO_CONFIG_USE_DEFAULT) 177 mode = p->default_config; 178 if (is_granted) 179 return mode & TOMOYO_CONFIG_WANT_GRANT_LOG; 180 return mode & TOMOYO_CONFIG_WANT_REJECT_LOG; 181} 182 183/** 184 * tomoyo_write_log2 - Write an audit log. 185 * 186 * @r: Pointer to "struct tomoyo_request_info". 187 * @len: Buffer size needed for @fmt and @args. 188 * @fmt: The printf()'s format string. 189 * @args: va_list structure for @fmt. 190 * 191 * Returns nothing. 192 */ 193void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, 194 va_list args) 195{ 196 char *buf; 197 struct tomoyo_log *entry; 198 bool quota_exceeded = false; 199 if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type, r->granted)) 200 goto out; 201 buf = tomoyo_init_log(r, len, fmt, args); 202 if (!buf) 203 goto out; 204 entry = kzalloc(sizeof(*entry), GFP_NOFS); 205 if (!entry) { 206 kfree(buf); 207 goto out; 208 } 209 entry->log = buf; 210 len = tomoyo_round2(strlen(buf) + 1); 211 /* 212 * The entry->size is used for memory quota checks. 213 * Don't go beyond strlen(entry->log). 214 */ 215 entry->size = len + tomoyo_round2(sizeof(*entry)); 216 spin_lock(&tomoyo_log_lock); 217 if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] && 218 tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >= 219 tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT]) { 220 quota_exceeded = true; 221 } else { 222 tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] += entry->size; 223 list_add_tail(&entry->list, &tomoyo_log); 224 tomoyo_log_count++; 225 } 226 spin_unlock(&tomoyo_log_lock); 227 if (quota_exceeded) { 228 kfree(buf); 229 kfree(entry); 230 goto out; 231 } 232 wake_up(&tomoyo_log_wait); 233out: 234 return; 235} 236 237/** 238 * tomoyo_write_log - Write an audit log. 239 * 240 * @r: Pointer to "struct tomoyo_request_info". 241 * @fmt: The printf()'s format string, followed by parameters. 242 * 243 * Returns nothing. 244 */ 245void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) 246{ 247 va_list args; 248 int len; 249 va_start(args, fmt); 250 len = vsnprintf((char *) &len, 1, fmt, args) + 1; 251 va_end(args); 252 va_start(args, fmt); 253 tomoyo_write_log2(r, len, fmt, args); 254 va_end(args); 255} 256 257/** 258 * tomoyo_read_log - Read an audit log. 259 * 260 * @head: Pointer to "struct tomoyo_io_buffer". 261 * 262 * Returns nothing. 263 */ 264void tomoyo_read_log(struct tomoyo_io_buffer *head) 265{ 266 struct tomoyo_log *ptr = NULL; 267 if (head->r.w_pos) 268 return; 269 kfree(head->read_buf); 270 head->read_buf = NULL; 271 spin_lock(&tomoyo_log_lock); 272 if (!list_empty(&tomoyo_log)) { 273 ptr = list_entry(tomoyo_log.next, typeof(*ptr), list); 274 list_del(&ptr->list); 275 tomoyo_log_count--; 276 tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] -= ptr->size; 277 } 278 spin_unlock(&tomoyo_log_lock); 279 if (ptr) { 280 head->read_buf = ptr->log; 281 head->r.w[head->r.w_pos++] = head->read_buf; 282 kfree(ptr); 283 } 284} 285 286/** 287 * tomoyo_poll_log - Wait for an audit log. 288 * 289 * @file: Pointer to "struct file". 290 * @wait: Pointer to "poll_table". 291 * 292 * Returns POLLIN | POLLRDNORM when ready to read an audit log. 293 */ 294int tomoyo_poll_log(struct file *file, poll_table *wait) 295{ 296 if (tomoyo_log_count) 297 return POLLIN | POLLRDNORM; 298 poll_wait(file, &tomoyo_log_wait, wait); 299 if (tomoyo_log_count) 300 return POLLIN | POLLRDNORM; 301 return 0; 302} 303