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