diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-06-26 10:18:58 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-06-28 19:31:20 -0400 |
commit | eadd99cc85347b4f9eb10122ac90032eb4971b02 (patch) | |
tree | fa6075ad4917422288222ee52bfcb66b7ed30a0e /security | |
parent | d5ca1725ac9ba876c2dd614bb9826d0c4e13d818 (diff) |
TOMOYO: Add auditing interface.
Add /sys/kernel/security/tomoyo/audit interface. This interface generates audit
logs in the form of domain policy so that /usr/sbin/tomoyo-auditd can reuse
audit logs for appending to /sys/kernel/security/tomoyo/domain_policy
interface.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/tomoyo/Makefile | 2 | ||||
-rw-r--r-- | security/tomoyo/audit.c | 300 | ||||
-rw-r--r-- | security/tomoyo/common.c | 311 | ||||
-rw-r--r-- | security/tomoyo/common.h | 83 | ||||
-rw-r--r-- | security/tomoyo/file.c | 49 | ||||
-rw-r--r-- | security/tomoyo/memory.c | 5 | ||||
-rw-r--r-- | security/tomoyo/mount.c | 26 | ||||
-rw-r--r-- | security/tomoyo/securityfs_if.c | 2 | ||||
-rw-r--r-- | security/tomoyo/util.c | 14 |
9 files changed, 557 insertions, 235 deletions
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 91640e96bd06..b13f7f9fbb52 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile | |||
@@ -1 +1 @@ | |||
obj-y = common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o | obj-y = audit.o common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o | ||
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c new file mode 100644 index 000000000000..e882f17065f2 --- /dev/null +++ b/security/tomoyo/audit.c | |||
@@ -0,0 +1,300 @@ | |||
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 | */ | ||
22 | static 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 | */ | ||
63 | static 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 | */ | ||
107 | char *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); | ||
127 | out: | ||
128 | kfree(header); | ||
129 | return buf; | ||
130 | } | ||
131 | |||
132 | /* Wait queue for /sys/kernel/security/tomoyo/audit. */ | ||
133 | static DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait); | ||
134 | |||
135 | /* Structure for audit log. */ | ||
136 | struct tomoyo_log { | ||
137 | struct list_head list; | ||
138 | char *log; | ||
139 | int size; | ||
140 | }; | ||
141 | |||
142 | /* The list for "struct tomoyo_log". */ | ||
143 | static LIST_HEAD(tomoyo_log); | ||
144 | |||
145 | /* Lock for "struct list_head tomoyo_log". */ | ||
146 | static DEFINE_SPINLOCK(tomoyo_log_lock); | ||
147 | |||
148 | /* Length of "stuct list_head tomoyo_log". */ | ||
149 | static unsigned int tomoyo_log_count; | ||
150 | |||
151 | /** | ||
152 | * tomoyo_get_audit - Get audit mode. | ||
153 | * | ||
154 | * @profile: Profile number. | ||
155 | * @index: Index number of functionality. | ||
156 | * @is_granted: True if granted log, false otherwise. | ||
157 | * | ||
158 | * Returns true if this request should be audited, false otherwise. | ||
159 | */ | ||
160 | static bool tomoyo_get_audit(const u8 profile, const u8 index, | ||
161 | const bool is_granted) | ||
162 | { | ||
163 | u8 mode; | ||
164 | const u8 category = TOMOYO_MAC_CATEGORY_FILE + TOMOYO_MAX_MAC_INDEX; | ||
165 | struct tomoyo_profile *p; | ||
166 | if (!tomoyo_policy_loaded) | ||
167 | return false; | ||
168 | p = tomoyo_profile(profile); | ||
169 | if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG]) | ||
170 | return false; | ||
171 | mode = p->config[index]; | ||
172 | if (mode == TOMOYO_CONFIG_USE_DEFAULT) | ||
173 | mode = p->config[category]; | ||
174 | if (mode == TOMOYO_CONFIG_USE_DEFAULT) | ||
175 | mode = p->default_config; | ||
176 | if (is_granted) | ||
177 | return mode & TOMOYO_CONFIG_WANT_GRANT_LOG; | ||
178 | return mode & TOMOYO_CONFIG_WANT_REJECT_LOG; | ||
179 | } | ||
180 | |||
181 | /** | ||
182 | * tomoyo_write_log2 - Write an audit log. | ||
183 | * | ||
184 | * @r: Pointer to "struct tomoyo_request_info". | ||
185 | * @len: Buffer size needed for @fmt and @args. | ||
186 | * @fmt: The printf()'s format string. | ||
187 | * @args: va_list structure for @fmt. | ||
188 | * | ||
189 | * Returns nothing. | ||
190 | */ | ||
191 | void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, | ||
192 | va_list args) | ||
193 | { | ||
194 | char *buf; | ||
195 | struct tomoyo_log *entry; | ||
196 | bool quota_exceeded = false; | ||
197 | if (!tomoyo_get_audit(r->profile, r->type, r->granted)) | ||
198 | goto out; | ||
199 | buf = tomoyo_init_log(r, len, fmt, args); | ||
200 | if (!buf) | ||
201 | goto out; | ||
202 | entry = kzalloc(sizeof(*entry), GFP_NOFS); | ||
203 | if (!entry) { | ||
204 | kfree(buf); | ||
205 | goto out; | ||
206 | } | ||
207 | entry->log = buf; | ||
208 | len = tomoyo_round2(strlen(buf) + 1); | ||
209 | /* | ||
210 | * The entry->size is used for memory quota checks. | ||
211 | * Don't go beyond strlen(entry->log). | ||
212 | */ | ||
213 | entry->size = len + tomoyo_round2(sizeof(*entry)); | ||
214 | spin_lock(&tomoyo_log_lock); | ||
215 | if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] && | ||
216 | tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >= | ||
217 | tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT]) { | ||
218 | quota_exceeded = true; | ||
219 | } else { | ||
220 | tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] += entry->size; | ||
221 | list_add_tail(&entry->list, &tomoyo_log); | ||
222 | tomoyo_log_count++; | ||
223 | } | ||
224 | spin_unlock(&tomoyo_log_lock); | ||
225 | if (quota_exceeded) { | ||
226 | kfree(buf); | ||
227 | kfree(entry); | ||
228 | goto out; | ||
229 | } | ||
230 | wake_up(&tomoyo_log_wait); | ||
231 | out: | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * tomoyo_write_log - Write an audit log. | ||
237 | * | ||
238 | * @r: Pointer to "struct tomoyo_request_info". | ||
239 | * @fmt: The printf()'s format string, followed by parameters. | ||
240 | * | ||
241 | * Returns nothing. | ||
242 | */ | ||
243 | void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) | ||
244 | { | ||
245 | va_list args; | ||
246 | int len; | ||
247 | va_start(args, fmt); | ||
248 | len = vsnprintf((char *) &len, 1, fmt, args) + 1; | ||
249 | va_end(args); | ||
250 | va_start(args, fmt); | ||
251 | tomoyo_write_log2(r, len, fmt, args); | ||
252 | va_end(args); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * tomoyo_read_log - Read an audit log. | ||
257 | * | ||
258 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
259 | * | ||
260 | * Returns nothing. | ||
261 | */ | ||
262 | void tomoyo_read_log(struct tomoyo_io_buffer *head) | ||
263 | { | ||
264 | struct tomoyo_log *ptr = NULL; | ||
265 | if (head->r.w_pos) | ||
266 | return; | ||
267 | kfree(head->read_buf); | ||
268 | head->read_buf = NULL; | ||
269 | spin_lock(&tomoyo_log_lock); | ||
270 | if (!list_empty(&tomoyo_log)) { | ||
271 | ptr = list_entry(tomoyo_log.next, typeof(*ptr), list); | ||
272 | list_del(&ptr->list); | ||
273 | tomoyo_log_count--; | ||
274 | tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] -= ptr->size; | ||
275 | } | ||
276 | spin_unlock(&tomoyo_log_lock); | ||
277 | if (ptr) { | ||
278 | head->read_buf = ptr->log; | ||
279 | head->r.w[head->r.w_pos++] = head->read_buf; | ||
280 | kfree(ptr); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * tomoyo_poll_log - Wait for an audit log. | ||
286 | * | ||
287 | * @file: Pointer to "struct file". | ||
288 | * @wait: Pointer to "poll_table". | ||
289 | * | ||
290 | * Returns POLLIN | POLLRDNORM when ready to read an audit log. | ||
291 | */ | ||
292 | int tomoyo_poll_log(struct file *file, poll_table *wait) | ||
293 | { | ||
294 | if (tomoyo_log_count) | ||
295 | return POLLIN | POLLRDNORM; | ||
296 | poll_wait(file, &tomoyo_log_wait, wait); | ||
297 | if (tomoyo_log_count) | ||
298 | return POLLIN | POLLRDNORM; | ||
299 | return 0; | ||
300 | } | ||
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 2b280350708f..6580ef35074b 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -17,9 +17,12 @@ static unsigned int tomoyo_profile_version; | |||
17 | /* Profile table. Memory is allocated as needed. */ | 17 | /* Profile table. Memory is allocated as needed. */ |
18 | static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES]; | 18 | static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES]; |
19 | 19 | ||
20 | /* String table for functionality that takes 4 modes. */ | 20 | /* String table for operation mode. */ |
21 | static const char *tomoyo_mode[4] = { | 21 | const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE] = { |
22 | "disabled", "learning", "permissive", "enforcing" | 22 | [TOMOYO_CONFIG_DISABLED] = "disabled", |
23 | [TOMOYO_CONFIG_LEARNING] = "learning", | ||
24 | [TOMOYO_CONFIG_PERMISSIVE] = "permissive", | ||
25 | [TOMOYO_CONFIG_ENFORCING] = "enforcing" | ||
23 | }; | 26 | }; |
24 | 27 | ||
25 | /* String table for /sys/kernel/security/tomoyo/profile */ | 28 | /* String table for /sys/kernel/security/tomoyo/profile */ |
@@ -53,6 +56,7 @@ static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX | |||
53 | 56 | ||
54 | /* String table for PREFERENCE keyword. */ | 57 | /* String table for PREFERENCE keyword. */ |
55 | static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = { | 58 | static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = { |
59 | [TOMOYO_PREF_MAX_AUDIT_LOG] = "max_audit_log", | ||
56 | [TOMOYO_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry", | 60 | [TOMOYO_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry", |
57 | }; | 61 | }; |
58 | 62 | ||
@@ -66,12 +70,10 @@ static bool tomoyo_manage_by_non_root; | |||
66 | * | 70 | * |
67 | * @value: Bool value. | 71 | * @value: Bool value. |
68 | */ | 72 | */ |
69 | /* | 73 | const char *tomoyo_yesno(const unsigned int value) |
70 | static const char *tomoyo_yesno(const unsigned int value) | ||
71 | { | 74 | { |
72 | return value ? "yes" : "no"; | 75 | return value ? "yes" : "no"; |
73 | } | 76 | } |
74 | */ | ||
75 | 77 | ||
76 | /** | 78 | /** |
77 | * tomoyo_addprintf - strncat()-like-snprintf(). | 79 | * tomoyo_addprintf - strncat()-like-snprintf(). |
@@ -117,7 +119,7 @@ static bool tomoyo_flush(struct tomoyo_io_buffer *head) | |||
117 | head->r.w[0] = w; | 119 | head->r.w[0] = w; |
118 | if (*w) | 120 | if (*w) |
119 | return false; | 121 | return false; |
120 | /* Add '\0' for query. */ | 122 | /* Add '\0' for audit logs and query. */ |
121 | if (head->poll) { | 123 | if (head->poll) { |
122 | if (!head->read_user_buf_avail || | 124 | if (!head->read_user_buf_avail || |
123 | copy_to_user(head->read_user_buf, "", 1)) | 125 | copy_to_user(head->read_user_buf, "", 1)) |
@@ -300,9 +302,12 @@ static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile) | |||
300 | ptr = tomoyo_profile_ptr[profile]; | 302 | ptr = tomoyo_profile_ptr[profile]; |
301 | if (!ptr && tomoyo_memory_ok(entry)) { | 303 | if (!ptr && tomoyo_memory_ok(entry)) { |
302 | ptr = entry; | 304 | ptr = entry; |
303 | ptr->default_config = TOMOYO_CONFIG_DISABLED; | 305 | ptr->default_config = TOMOYO_CONFIG_DISABLED | |
306 | TOMOYO_CONFIG_WANT_GRANT_LOG | | ||
307 | TOMOYO_CONFIG_WANT_REJECT_LOG; | ||
304 | memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT, | 308 | memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT, |
305 | sizeof(ptr->config)); | 309 | sizeof(ptr->config)); |
310 | ptr->pref[TOMOYO_PREF_MAX_AUDIT_LOG] = 1024; | ||
306 | ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048; | 311 | ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048; |
307 | mb(); /* Avoid out-of-order execution. */ | 312 | mb(); /* Avoid out-of-order execution. */ |
308 | tomoyo_profile_ptr[profile] = ptr; | 313 | tomoyo_profile_ptr[profile] = ptr; |
@@ -338,7 +343,6 @@ struct tomoyo_profile *tomoyo_profile(const u8 profile) | |||
338 | * | 343 | * |
339 | * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise. | 344 | * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise. |
340 | */ | 345 | */ |
341 | /* | ||
342 | static s8 tomoyo_find_yesno(const char *string, const char *find) | 346 | static s8 tomoyo_find_yesno(const char *string, const char *find) |
343 | { | 347 | { |
344 | const char *cp = strstr(string, find); | 348 | const char *cp = strstr(string, find); |
@@ -351,7 +355,6 @@ static s8 tomoyo_find_yesno(const char *string, const char *find) | |||
351 | } | 355 | } |
352 | return -1; | 356 | return -1; |
353 | } | 357 | } |
354 | */ | ||
355 | 358 | ||
356 | /** | 359 | /** |
357 | * tomoyo_set_uint - Set value for specified preference. | 360 | * tomoyo_set_uint - Set value for specified preference. |
@@ -412,6 +415,24 @@ static int tomoyo_set_mode(char *name, const char *value, | |||
412 | * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'. | 415 | * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'. |
413 | */ | 416 | */ |
414 | config = (config & ~7) | mode; | 417 | config = (config & ~7) | mode; |
418 | if (config != TOMOYO_CONFIG_USE_DEFAULT) { | ||
419 | switch (tomoyo_find_yesno(value, "grant_log")) { | ||
420 | case 1: | ||
421 | config |= TOMOYO_CONFIG_WANT_GRANT_LOG; | ||
422 | break; | ||
423 | case 0: | ||
424 | config &= ~TOMOYO_CONFIG_WANT_GRANT_LOG; | ||
425 | break; | ||
426 | } | ||
427 | switch (tomoyo_find_yesno(value, "reject_log")) { | ||
428 | case 1: | ||
429 | config |= TOMOYO_CONFIG_WANT_REJECT_LOG; | ||
430 | break; | ||
431 | case 0: | ||
432 | config &= ~TOMOYO_CONFIG_WANT_REJECT_LOG; | ||
433 | break; | ||
434 | } | ||
435 | } | ||
415 | } | 436 | } |
416 | if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) | 437 | if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) |
417 | profile->config[i] = config; | 438 | profile->config[i] = config; |
@@ -469,15 +490,30 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
469 | return tomoyo_set_mode(data, cp, profile); | 490 | return tomoyo_set_mode(data, cp, profile); |
470 | } | 491 | } |
471 | 492 | ||
493 | /** | ||
494 | * tomoyo_print_config - Print mode for specified functionality. | ||
495 | * | ||
496 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
497 | * @config: Mode for that functionality. | ||
498 | * | ||
499 | * Returns nothing. | ||
500 | * | ||
501 | * Caller prints functionality's name. | ||
502 | */ | ||
472 | static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config) | 503 | static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config) |
473 | { | 504 | { |
474 | tomoyo_io_printf(head, "={ mode=%s }\n", tomoyo_mode[config & 3]); | 505 | tomoyo_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n", |
506 | tomoyo_mode[config & 3], | ||
507 | tomoyo_yesno(config & TOMOYO_CONFIG_WANT_GRANT_LOG), | ||
508 | tomoyo_yesno(config & TOMOYO_CONFIG_WANT_REJECT_LOG)); | ||
475 | } | 509 | } |
476 | 510 | ||
477 | /** | 511 | /** |
478 | * tomoyo_read_profile - Read profile table. | 512 | * tomoyo_read_profile - Read profile table. |
479 | * | 513 | * |
480 | * @head: Pointer to "struct tomoyo_io_buffer". | 514 | * @head: Pointer to "struct tomoyo_io_buffer". |
515 | * | ||
516 | * Returns nothing. | ||
481 | */ | 517 | */ |
482 | static void tomoyo_read_profile(struct tomoyo_io_buffer *head) | 518 | static void tomoyo_read_profile(struct tomoyo_io_buffer *head) |
483 | { | 519 | { |
@@ -488,7 +524,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head) | |||
488 | profile = tomoyo_profile_ptr[index]; | 524 | profile = tomoyo_profile_ptr[index]; |
489 | switch (head->r.step) { | 525 | switch (head->r.step) { |
490 | case 0: | 526 | case 0: |
491 | tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903"); | 527 | tomoyo_io_printf(head, "PROFILE_VERSION=%u\n", 20090903); |
492 | head->r.step++; | 528 | head->r.step++; |
493 | break; | 529 | break; |
494 | case 1: | 530 | case 1: |
@@ -1359,92 +1395,28 @@ static void tomoyo_read_exception(struct tomoyo_io_buffer *head) | |||
1359 | head->r.eof = true; | 1395 | head->r.eof = true; |
1360 | } | 1396 | } |
1361 | 1397 | ||
1362 | /** | 1398 | /* Wait queue for kernel -> userspace notification. */ |
1363 | * tomoyo_print_header - Get header line of audit log. | ||
1364 | * | ||
1365 | * @r: Pointer to "struct tomoyo_request_info". | ||
1366 | * | ||
1367 | * Returns string representation. | ||
1368 | * | ||
1369 | * This function uses kmalloc(), so caller must kfree() if this function | ||
1370 | * didn't return NULL. | ||
1371 | */ | ||
1372 | static char *tomoyo_print_header(struct tomoyo_request_info *r) | ||
1373 | { | ||
1374 | struct timeval tv; | ||
1375 | const pid_t gpid = task_pid_nr(current); | ||
1376 | static const int tomoyo_buffer_len = 4096; | ||
1377 | char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); | ||
1378 | pid_t ppid; | ||
1379 | if (!buffer) | ||
1380 | return NULL; | ||
1381 | do_gettimeofday(&tv); | ||
1382 | rcu_read_lock(); | ||
1383 | ppid = task_tgid_vnr(current->real_parent); | ||
1384 | rcu_read_unlock(); | ||
1385 | snprintf(buffer, tomoyo_buffer_len - 1, | ||
1386 | "#timestamp=%lu profile=%u mode=%s (global-pid=%u)" | ||
1387 | " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u" | ||
1388 | " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", | ||
1389 | tv.tv_sec, r->profile, tomoyo_mode[r->mode], gpid, | ||
1390 | task_tgid_vnr(current), ppid, | ||
1391 | current_uid(), current_gid(), current_euid(), | ||
1392 | current_egid(), current_suid(), current_sgid(), | ||
1393 | current_fsuid(), current_fsgid()); | ||
1394 | return buffer; | ||
1395 | } | ||
1396 | |||
1397 | /** | ||
1398 | * tomoyo_init_audit_log - Allocate buffer for audit logs. | ||
1399 | * | ||
1400 | * @len: Required size. | ||
1401 | * @r: Pointer to "struct tomoyo_request_info". | ||
1402 | * | ||
1403 | * Returns pointer to allocated memory. | ||
1404 | * | ||
1405 | * The @len is updated to add the header lines' size on success. | ||
1406 | * | ||
1407 | * This function uses kzalloc(), so caller must kfree() if this function | ||
1408 | * didn't return NULL. | ||
1409 | */ | ||
1410 | static char *tomoyo_init_audit_log(int *len, struct tomoyo_request_info *r) | ||
1411 | { | ||
1412 | char *buf = NULL; | ||
1413 | const char *header; | ||
1414 | const char *domainname; | ||
1415 | if (!r->domain) | ||
1416 | r->domain = tomoyo_domain(); | ||
1417 | domainname = r->domain->domainname->name; | ||
1418 | header = tomoyo_print_header(r); | ||
1419 | if (!header) | ||
1420 | return NULL; | ||
1421 | *len += strlen(domainname) + strlen(header) + 10; | ||
1422 | buf = kzalloc(*len, GFP_NOFS); | ||
1423 | if (buf) | ||
1424 | snprintf(buf, (*len) - 1, "%s\n%s\n", header, domainname); | ||
1425 | kfree(header); | ||
1426 | return buf; | ||
1427 | } | ||
1428 | |||
1429 | /* Wait queue for tomoyo_query_list. */ | ||
1430 | static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait); | 1399 | static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait); |
1431 | 1400 | /* Wait queue for userspace -> kernel notification. */ | |
1432 | /* Lock for manipulating tomoyo_query_list. */ | 1401 | static DECLARE_WAIT_QUEUE_HEAD(tomoyo_answer_wait); |
1433 | static DEFINE_SPINLOCK(tomoyo_query_list_lock); | ||
1434 | 1402 | ||
1435 | /* Structure for query. */ | 1403 | /* Structure for query. */ |
1436 | struct tomoyo_query { | 1404 | struct tomoyo_query { |
1437 | struct list_head list; | 1405 | struct list_head list; |
1438 | char *query; | 1406 | char *query; |
1439 | int query_len; | 1407 | size_t query_len; |
1440 | unsigned int serial; | 1408 | unsigned int serial; |
1441 | int timer; | 1409 | u8 timer; |
1442 | int answer; | 1410 | u8 answer; |
1411 | u8 retry; | ||
1443 | }; | 1412 | }; |
1444 | 1413 | ||
1445 | /* The list for "struct tomoyo_query". */ | 1414 | /* The list for "struct tomoyo_query". */ |
1446 | static LIST_HEAD(tomoyo_query_list); | 1415 | static LIST_HEAD(tomoyo_query_list); |
1447 | 1416 | ||
1417 | /* Lock for manipulating tomoyo_query_list. */ | ||
1418 | static DEFINE_SPINLOCK(tomoyo_query_list_lock); | ||
1419 | |||
1448 | /* | 1420 | /* |
1449 | * Number of "struct file" referring /sys/kernel/security/tomoyo/query | 1421 | * Number of "struct file" referring /sys/kernel/security/tomoyo/query |
1450 | * interface. | 1422 | * interface. |
@@ -1452,10 +1424,39 @@ static LIST_HEAD(tomoyo_query_list); | |||
1452 | static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); | 1424 | static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); |
1453 | 1425 | ||
1454 | /** | 1426 | /** |
1427 | * tomoyo_add_entry - Add an ACL to current thread's domain. Used by learning mode. | ||
1428 | * | ||
1429 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1430 | * @header: Lines containing ACL. | ||
1431 | * | ||
1432 | * Returns nothing. | ||
1433 | */ | ||
1434 | static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) | ||
1435 | { | ||
1436 | char *buffer; | ||
1437 | char *cp = strchr(header, '\n'); | ||
1438 | int len; | ||
1439 | if (!cp) | ||
1440 | return; | ||
1441 | cp = strchr(cp + 1, '\n'); | ||
1442 | if (!cp) | ||
1443 | return; | ||
1444 | *cp++ = '\0'; | ||
1445 | len = strlen(cp) + 1; | ||
1446 | buffer = kmalloc(len, GFP_NOFS); | ||
1447 | if (!buffer) | ||
1448 | return; | ||
1449 | snprintf(buffer, len - 1, "%s", cp); | ||
1450 | tomoyo_normalize_line(buffer); | ||
1451 | tomoyo_write_domain2(&domain->acl_info_list, buffer, false); | ||
1452 | kfree(buffer); | ||
1453 | } | ||
1454 | |||
1455 | /** | ||
1455 | * tomoyo_supervisor - Ask for the supervisor's decision. | 1456 | * tomoyo_supervisor - Ask for the supervisor's decision. |
1456 | * | 1457 | * |
1457 | * @r: Pointer to "struct tomoyo_request_info". | 1458 | * @r: Pointer to "struct tomoyo_request_info". |
1458 | * @fmt: The printf()'s format string, followed by parameters. | 1459 | * @fmt: The printf()'s format string, followed by parameters. |
1459 | * | 1460 | * |
1460 | * Returns 0 if the supervisor decided to permit the access request which | 1461 | * Returns 0 if the supervisor decided to permit the access request which |
1461 | * violated the policy in enforcing mode, TOMOYO_RETRY_REQUEST if the | 1462 | * violated the policy in enforcing mode, TOMOYO_RETRY_REQUEST if the |
@@ -1465,88 +1466,77 @@ static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); | |||
1465 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) | 1466 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) |
1466 | { | 1467 | { |
1467 | va_list args; | 1468 | va_list args; |
1468 | int error = -EPERM; | 1469 | int error; |
1469 | int pos; | ||
1470 | int len; | 1470 | int len; |
1471 | static unsigned int tomoyo_serial; | 1471 | static unsigned int tomoyo_serial; |
1472 | struct tomoyo_query *entry = NULL; | 1472 | struct tomoyo_query entry = { }; |
1473 | bool quota_exceeded = false; | 1473 | bool quota_exceeded = false; |
1474 | char *header; | 1474 | va_start(args, fmt); |
1475 | len = vsnprintf((char *) &len, 1, fmt, args) + 1; | ||
1476 | va_end(args); | ||
1477 | /* Write /sys/kernel/security/tomoyo/audit. */ | ||
1478 | va_start(args, fmt); | ||
1479 | tomoyo_write_log2(r, len, fmt, args); | ||
1480 | va_end(args); | ||
1481 | /* Nothing more to do if granted. */ | ||
1482 | if (r->granted) | ||
1483 | return 0; | ||
1475 | switch (r->mode) { | 1484 | switch (r->mode) { |
1476 | char *buffer; | 1485 | case TOMOYO_CONFIG_ENFORCING: |
1486 | error = -EPERM; | ||
1487 | if (atomic_read(&tomoyo_query_observers)) | ||
1488 | break; | ||
1489 | goto out; | ||
1477 | case TOMOYO_CONFIG_LEARNING: | 1490 | case TOMOYO_CONFIG_LEARNING: |
1478 | if (!tomoyo_domain_quota_is_ok(r)) | 1491 | error = 0; |
1479 | return 0; | 1492 | /* Check max_learning_entry parameter. */ |
1480 | va_start(args, fmt); | 1493 | if (tomoyo_domain_quota_is_ok(r)) |
1481 | len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4; | 1494 | break; |
1482 | va_end(args); | ||
1483 | buffer = kmalloc(len, GFP_NOFS); | ||
1484 | if (!buffer) | ||
1485 | return 0; | ||
1486 | va_start(args, fmt); | ||
1487 | vsnprintf(buffer, len - 1, fmt, args); | ||
1488 | va_end(args); | ||
1489 | tomoyo_normalize_line(buffer); | ||
1490 | tomoyo_write_domain2(&r->domain->acl_info_list, buffer, false); | ||
1491 | kfree(buffer); | ||
1492 | /* fall through */ | 1495 | /* fall through */ |
1493 | case TOMOYO_CONFIG_PERMISSIVE: | 1496 | default: |
1494 | return 0; | 1497 | return 0; |
1495 | } | 1498 | } |
1496 | if (!r->domain) | 1499 | /* Get message. */ |
1497 | r->domain = tomoyo_domain(); | ||
1498 | if (!atomic_read(&tomoyo_query_observers)) | ||
1499 | return -EPERM; | ||
1500 | va_start(args, fmt); | 1500 | va_start(args, fmt); |
1501 | len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32; | 1501 | entry.query = tomoyo_init_log(r, len, fmt, args); |
1502 | va_end(args); | 1502 | va_end(args); |
1503 | header = tomoyo_init_audit_log(&len, r); | 1503 | if (!entry.query) |
1504 | if (!header) | ||
1505 | goto out; | 1504 | goto out; |
1506 | entry = kzalloc(sizeof(*entry), GFP_NOFS); | 1505 | entry.query_len = strlen(entry.query) + 1; |
1507 | if (!entry) | 1506 | if (!error) { |
1508 | goto out; | 1507 | tomoyo_add_entry(r->domain, entry.query); |
1509 | entry->query = kzalloc(len, GFP_NOFS); | ||
1510 | if (!entry->query) | ||
1511 | goto out; | 1508 | goto out; |
1512 | len = ksize(entry->query); | 1509 | } |
1510 | len = tomoyo_round2(entry.query_len); | ||
1513 | spin_lock(&tomoyo_query_list_lock); | 1511 | spin_lock(&tomoyo_query_list_lock); |
1514 | if (tomoyo_quota_for_query && tomoyo_query_memory_size + len + | 1512 | if (tomoyo_memory_quota[TOMOYO_MEMORY_QUERY] && |
1515 | sizeof(*entry) >= tomoyo_quota_for_query) { | 1513 | tomoyo_memory_used[TOMOYO_MEMORY_QUERY] + len |
1514 | >= tomoyo_memory_quota[TOMOYO_MEMORY_QUERY]) { | ||
1516 | quota_exceeded = true; | 1515 | quota_exceeded = true; |
1517 | } else { | 1516 | } else { |
1518 | tomoyo_query_memory_size += len + sizeof(*entry); | 1517 | entry.serial = tomoyo_serial++; |
1519 | entry->serial = tomoyo_serial++; | 1518 | entry.retry = r->retry; |
1519 | tomoyo_memory_used[TOMOYO_MEMORY_QUERY] += len; | ||
1520 | list_add_tail(&entry.list, &tomoyo_query_list); | ||
1520 | } | 1521 | } |
1521 | spin_unlock(&tomoyo_query_list_lock); | 1522 | spin_unlock(&tomoyo_query_list_lock); |
1522 | if (quota_exceeded) | 1523 | if (quota_exceeded) |
1523 | goto out; | 1524 | goto out; |
1524 | pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s", | ||
1525 | entry->serial, r->retry, header); | ||
1526 | kfree(header); | ||
1527 | header = NULL; | ||
1528 | va_start(args, fmt); | ||
1529 | vsnprintf(entry->query + pos, len - 1 - pos, fmt, args); | ||
1530 | entry->query_len = strlen(entry->query) + 1; | ||
1531 | va_end(args); | ||
1532 | spin_lock(&tomoyo_query_list_lock); | ||
1533 | list_add_tail(&entry->list, &tomoyo_query_list); | ||
1534 | spin_unlock(&tomoyo_query_list_lock); | ||
1535 | /* Give 10 seconds for supervisor's opinion. */ | 1525 | /* Give 10 seconds for supervisor's opinion. */ |
1536 | for (entry->timer = 0; | 1526 | while (entry.timer < 10) { |
1537 | atomic_read(&tomoyo_query_observers) && entry->timer < 100; | 1527 | wake_up_all(&tomoyo_query_wait); |
1538 | entry->timer++) { | 1528 | if (wait_event_interruptible_timeout |
1539 | wake_up(&tomoyo_query_wait); | 1529 | (tomoyo_answer_wait, entry.answer || |
1540 | set_current_state(TASK_INTERRUPTIBLE); | 1530 | !atomic_read(&tomoyo_query_observers), HZ)) |
1541 | schedule_timeout(HZ / 10); | ||
1542 | if (entry->answer) | ||
1543 | break; | 1531 | break; |
1532 | else | ||
1533 | entry.timer++; | ||
1544 | } | 1534 | } |
1545 | spin_lock(&tomoyo_query_list_lock); | 1535 | spin_lock(&tomoyo_query_list_lock); |
1546 | list_del(&entry->list); | 1536 | list_del(&entry.list); |
1547 | tomoyo_query_memory_size -= len + sizeof(*entry); | 1537 | tomoyo_memory_used[TOMOYO_MEMORY_QUERY] -= len; |
1548 | spin_unlock(&tomoyo_query_list_lock); | 1538 | spin_unlock(&tomoyo_query_list_lock); |
1549 | switch (entry->answer) { | 1539 | switch (entry.answer) { |
1550 | case 3: /* Asked to retry by administrator. */ | 1540 | case 3: /* Asked to retry by administrator. */ |
1551 | error = TOMOYO_RETRY_REQUEST; | 1541 | error = TOMOYO_RETRY_REQUEST; |
1552 | r->retry++; | 1542 | r->retry++; |
@@ -1555,18 +1545,12 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) | |||
1555 | /* Granted by administrator. */ | 1545 | /* Granted by administrator. */ |
1556 | error = 0; | 1546 | error = 0; |
1557 | break; | 1547 | break; |
1558 | case 0: | ||
1559 | /* Timed out. */ | ||
1560 | break; | ||
1561 | default: | 1548 | default: |
1562 | /* Rejected by administrator. */ | 1549 | /* Timed out or rejected by administrator. */ |
1563 | break; | 1550 | break; |
1564 | } | 1551 | } |
1565 | out: | 1552 | out: |
1566 | if (entry) | 1553 | kfree(entry.query); |
1567 | kfree(entry->query); | ||
1568 | kfree(entry); | ||
1569 | kfree(header); | ||
1570 | return error; | 1554 | return error; |
1571 | } | 1555 | } |
1572 | 1556 | ||
@@ -1637,7 +1621,7 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head) | |||
1637 | head->r.query_index = 0; | 1621 | head->r.query_index = 0; |
1638 | return; | 1622 | return; |
1639 | } | 1623 | } |
1640 | buf = kzalloc(len, GFP_NOFS); | 1624 | buf = kzalloc(len + 32, GFP_NOFS); |
1641 | if (!buf) | 1625 | if (!buf) |
1642 | return; | 1626 | return; |
1643 | pos = 0; | 1627 | pos = 0; |
@@ -1653,7 +1637,8 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head) | |||
1653 | * can change, but I don't care. | 1637 | * can change, but I don't care. |
1654 | */ | 1638 | */ |
1655 | if (len == ptr->query_len) | 1639 | if (len == ptr->query_len) |
1656 | memmove(buf, ptr->query, len); | 1640 | snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial, |
1641 | ptr->retry, ptr->query); | ||
1657 | break; | 1642 | break; |
1658 | } | 1643 | } |
1659 | spin_unlock(&tomoyo_query_list_lock); | 1644 | spin_unlock(&tomoyo_query_list_lock); |
@@ -1764,6 +1749,11 @@ int tomoyo_open_control(const u8 type, struct file *file) | |||
1764 | head->write = tomoyo_write_exception; | 1749 | head->write = tomoyo_write_exception; |
1765 | head->read = tomoyo_read_exception; | 1750 | head->read = tomoyo_read_exception; |
1766 | break; | 1751 | break; |
1752 | case TOMOYO_AUDIT: | ||
1753 | /* /sys/kernel/security/tomoyo/audit */ | ||
1754 | head->poll = tomoyo_poll_log; | ||
1755 | head->read = tomoyo_read_log; | ||
1756 | break; | ||
1767 | case TOMOYO_SELFDOMAIN: | 1757 | case TOMOYO_SELFDOMAIN: |
1768 | /* /sys/kernel/security/tomoyo/self_domain */ | 1758 | /* /sys/kernel/security/tomoyo/self_domain */ |
1769 | head->read = tomoyo_read_self_domain; | 1759 | head->read = tomoyo_read_self_domain; |
@@ -1837,7 +1827,7 @@ int tomoyo_open_control(const u8 type, struct file *file) | |||
1837 | return -ENOMEM; | 1827 | return -ENOMEM; |
1838 | } | 1828 | } |
1839 | } | 1829 | } |
1840 | if (type != TOMOYO_QUERY) | 1830 | if (type != TOMOYO_QUERY && type != TOMOYO_AUDIT) |
1841 | head->reader_idx = tomoyo_read_lock(); | 1831 | head->reader_idx = tomoyo_read_lock(); |
1842 | file->private_data = head; | 1832 | file->private_data = head; |
1843 | /* | 1833 | /* |
@@ -1858,7 +1848,8 @@ int tomoyo_open_control(const u8 type, struct file *file) | |||
1858 | * @wait: Pointer to "poll_table". | 1848 | * @wait: Pointer to "poll_table". |
1859 | * | 1849 | * |
1860 | * Waits for read readiness. | 1850 | * Waits for read readiness. |
1861 | * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd . | 1851 | * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd and |
1852 | * /sys/kernel/security/tomoyo/audit is handled by /usr/sbin/tomoyo-auditd. | ||
1862 | */ | 1853 | */ |
1863 | int tomoyo_poll_control(struct file *file, poll_table *wait) | 1854 | int tomoyo_poll_control(struct file *file, poll_table *wait) |
1864 | { | 1855 | { |
@@ -1970,7 +1961,7 @@ int tomoyo_close_control(struct tomoyo_io_buffer *head) | |||
1970 | */ | 1961 | */ |
1971 | if (head->type == TOMOYO_QUERY) | 1962 | if (head->type == TOMOYO_QUERY) |
1972 | atomic_dec(&tomoyo_query_observers); | 1963 | atomic_dec(&tomoyo_query_observers); |
1973 | else | 1964 | else if (head->type != TOMOYO_AUDIT) |
1974 | tomoyo_read_unlock(head->reader_idx); | 1965 | tomoyo_read_unlock(head->reader_idx); |
1975 | /* Release memory used for policy I/O. */ | 1966 | /* Release memory used for policy I/O. */ |
1976 | kfree(head->read_buf); | 1967 | kfree(head->read_buf); |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 2b39e63234c8..f40ec1fcbc5d 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -44,7 +44,10 @@ enum tomoyo_mode_index { | |||
44 | TOMOYO_CONFIG_LEARNING, | 44 | TOMOYO_CONFIG_LEARNING, |
45 | TOMOYO_CONFIG_PERMISSIVE, | 45 | TOMOYO_CONFIG_PERMISSIVE, |
46 | TOMOYO_CONFIG_ENFORCING, | 46 | TOMOYO_CONFIG_ENFORCING, |
47 | TOMOYO_CONFIG_USE_DEFAULT = 255 | 47 | TOMOYO_CONFIG_MAX_MODE, |
48 | TOMOYO_CONFIG_WANT_REJECT_LOG = 64, | ||
49 | TOMOYO_CONFIG_WANT_GRANT_LOG = 128, | ||
50 | TOMOYO_CONFIG_USE_DEFAULT = 255, | ||
48 | }; | 51 | }; |
49 | 52 | ||
50 | /* Index numbers for entry type. */ | 53 | /* Index numbers for entry type. */ |
@@ -115,6 +118,13 @@ enum tomoyo_path_acl_index { | |||
115 | TOMOYO_MAX_PATH_OPERATION | 118 | TOMOYO_MAX_PATH_OPERATION |
116 | }; | 119 | }; |
117 | 120 | ||
121 | enum tomoyo_memory_stat_type { | ||
122 | TOMOYO_MEMORY_POLICY, | ||
123 | TOMOYO_MEMORY_AUDIT, | ||
124 | TOMOYO_MEMORY_QUERY, | ||
125 | TOMOYO_MAX_MEMORY_STAT | ||
126 | }; | ||
127 | |||
118 | enum tomoyo_mkdev_acl_index { | 128 | enum tomoyo_mkdev_acl_index { |
119 | TOMOYO_TYPE_MKBLOCK, | 129 | TOMOYO_TYPE_MKBLOCK, |
120 | TOMOYO_TYPE_MKCHAR, | 130 | TOMOYO_TYPE_MKCHAR, |
@@ -150,6 +160,7 @@ enum tomoyo_securityfs_interface_index { | |||
150 | TOMOYO_PROCESS_STATUS, | 160 | TOMOYO_PROCESS_STATUS, |
151 | TOMOYO_MEMINFO, | 161 | TOMOYO_MEMINFO, |
152 | TOMOYO_SELFDOMAIN, | 162 | TOMOYO_SELFDOMAIN, |
163 | TOMOYO_AUDIT, | ||
153 | TOMOYO_VERSION, | 164 | TOMOYO_VERSION, |
154 | TOMOYO_PROFILE, | 165 | TOMOYO_PROFILE, |
155 | TOMOYO_QUERY, | 166 | TOMOYO_QUERY, |
@@ -213,6 +224,7 @@ enum tomoyo_mac_category_index { | |||
213 | 224 | ||
214 | /* Index numbers for profile's PREFERENCE values. */ | 225 | /* Index numbers for profile's PREFERENCE values. */ |
215 | enum tomoyo_pref_index { | 226 | enum tomoyo_pref_index { |
227 | TOMOYO_PREF_MAX_AUDIT_LOG, | ||
216 | TOMOYO_PREF_MAX_LEARNING_ENTRY, | 228 | TOMOYO_PREF_MAX_LEARNING_ENTRY, |
217 | TOMOYO_MAX_PREF | 229 | TOMOYO_MAX_PREF |
218 | }; | 230 | }; |
@@ -506,13 +518,21 @@ struct tomoyo_profile { | |||
506 | unsigned int pref[TOMOYO_MAX_PREF]; | 518 | unsigned int pref[TOMOYO_MAX_PREF]; |
507 | }; | 519 | }; |
508 | 520 | ||
521 | /* Structure for representing YYYY/MM/DD hh/mm/ss. */ | ||
522 | struct tomoyo_time { | ||
523 | u16 year; | ||
524 | u8 month; | ||
525 | u8 day; | ||
526 | u8 hour; | ||
527 | u8 min; | ||
528 | u8 sec; | ||
529 | }; | ||
530 | |||
509 | /********** Function prototypes. **********/ | 531 | /********** Function prototypes. **********/ |
510 | 532 | ||
511 | bool tomoyo_str_starts(char **src, const char *find); | 533 | bool tomoyo_str_starts(char **src, const char *find); |
512 | const char *tomoyo_get_exe(void); | 534 | const char *tomoyo_get_exe(void); |
513 | void tomoyo_normalize_line(unsigned char *buffer); | 535 | void tomoyo_normalize_line(unsigned char *buffer); |
514 | void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) | ||
515 | __attribute__ ((format(printf, 2, 3))); | ||
516 | void tomoyo_check_profile(void); | 536 | void tomoyo_check_profile(void); |
517 | int tomoyo_open_control(const u8 type, struct file *file); | 537 | int tomoyo_open_control(const u8 type, struct file *file); |
518 | int tomoyo_close_control(struct tomoyo_io_buffer *head); | 538 | int tomoyo_close_control(struct tomoyo_io_buffer *head); |
@@ -620,6 +640,14 @@ void tomoyo_check_acl(struct tomoyo_request_info *r, | |||
620 | char *tomoyo_read_token(struct tomoyo_acl_param *param); | 640 | char *tomoyo_read_token(struct tomoyo_acl_param *param); |
621 | bool tomoyo_permstr(const char *string, const char *keyword); | 641 | bool tomoyo_permstr(const char *string, const char *keyword); |
622 | 642 | ||
643 | const char *tomoyo_yesno(const unsigned int value); | ||
644 | void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, | ||
645 | va_list args); | ||
646 | void tomoyo_read_log(struct tomoyo_io_buffer *head); | ||
647 | int tomoyo_poll_log(struct file *file, poll_table *wait); | ||
648 | char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, | ||
649 | va_list args); | ||
650 | |||
623 | /********** External variable definitions. **********/ | 651 | /********** External variable definitions. **********/ |
624 | 652 | ||
625 | /* Lock for GC. */ | 653 | /* Lock for GC. */ |
@@ -650,8 +678,9 @@ extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; | |||
650 | extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION]; | 678 | extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION]; |
651 | extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; | 679 | extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; |
652 | 680 | ||
653 | extern unsigned int tomoyo_quota_for_query; | 681 | extern const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE]; |
654 | extern unsigned int tomoyo_query_memory_size; | 682 | extern unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; |
683 | extern unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; | ||
655 | 684 | ||
656 | /********** Inlined functions. **********/ | 685 | /********** Inlined functions. **********/ |
657 | 686 | ||
@@ -773,6 +802,50 @@ static inline bool tomoyo_same_number_union | |||
773 | a->value_type[1] == b->value_type[1]; | 802 | a->value_type[1] == b->value_type[1]; |
774 | } | 803 | } |
775 | 804 | ||
805 | #if defined(CONFIG_SLOB) | ||
806 | |||
807 | /** | ||
808 | * tomoyo_round2 - Round up to power of 2 for calculating memory usage. | ||
809 | * | ||
810 | * @size: Size to be rounded up. | ||
811 | * | ||
812 | * Returns @size. | ||
813 | * | ||
814 | * Since SLOB does not round up, this function simply returns @size. | ||
815 | */ | ||
816 | static inline int tomoyo_round2(size_t size) | ||
817 | { | ||
818 | return size; | ||
819 | } | ||
820 | |||
821 | #else | ||
822 | |||
823 | /** | ||
824 | * tomoyo_round2 - Round up to power of 2 for calculating memory usage. | ||
825 | * | ||
826 | * @size: Size to be rounded up. | ||
827 | * | ||
828 | * Returns rounded size. | ||
829 | * | ||
830 | * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of | ||
831 | * (e.g.) 128 bytes. | ||
832 | */ | ||
833 | static inline int tomoyo_round2(size_t size) | ||
834 | { | ||
835 | #if PAGE_SIZE == 4096 | ||
836 | size_t bsize = 32; | ||
837 | #else | ||
838 | size_t bsize = 64; | ||
839 | #endif | ||
840 | if (!size) | ||
841 | return 0; | ||
842 | while (size > bsize) | ||
843 | bsize <<= 1; | ||
844 | return bsize; | ||
845 | } | ||
846 | |||
847 | #endif | ||
848 | |||
776 | /** | 849 | /** |
777 | * list_for_each_cookie - iterate over a list with cookie. | 850 | * list_for_each_cookie - iterate over a list with cookie. |
778 | * @pos: the &struct list_head to use as a loop cursor. | 851 | * @pos: the &struct list_head to use as a loop cursor. |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 0673a69b1320..4f8526af9069 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -206,12 +206,9 @@ static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) | |||
206 | */ | 206 | */ |
207 | static int tomoyo_audit_path_log(struct tomoyo_request_info *r) | 207 | static int tomoyo_audit_path_log(struct tomoyo_request_info *r) |
208 | { | 208 | { |
209 | const char *operation = tomoyo_path_keyword[r->param.path.operation]; | 209 | return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword |
210 | const struct tomoyo_path_info *filename = r->param.path.filename; | 210 | [r->param.path.operation], |
211 | if (r->granted) | 211 | r->param.path.filename->name); |
212 | return 0; | ||
213 | tomoyo_warn_log(r, "%s %s", operation, filename->name); | ||
214 | return tomoyo_supervisor(r, "file %s %s\n", operation, filename->name); | ||
215 | } | 212 | } |
216 | 213 | ||
217 | /** | 214 | /** |
@@ -223,15 +220,10 @@ static int tomoyo_audit_path_log(struct tomoyo_request_info *r) | |||
223 | */ | 220 | */ |
224 | static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) | 221 | static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) |
225 | { | 222 | { |
226 | const char *operation = tomoyo_path2_keyword[r->param.path2.operation]; | 223 | return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_path2_keyword |
227 | const struct tomoyo_path_info *filename1 = r->param.path2.filename1; | 224 | [r->param.path2.operation], |
228 | const struct tomoyo_path_info *filename2 = r->param.path2.filename2; | 225 | r->param.path2.filename1->name, |
229 | if (r->granted) | 226 | r->param.path2.filename2->name); |
230 | return 0; | ||
231 | tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, | ||
232 | filename2->name); | ||
233 | return tomoyo_supervisor(r, "file %s %s %s\n", operation, | ||
234 | filename1->name, filename2->name); | ||
235 | } | 227 | } |
236 | 228 | ||
237 | /** | 229 | /** |
@@ -243,17 +235,12 @@ static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) | |||
243 | */ | 235 | */ |
244 | static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) | 236 | static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) |
245 | { | 237 | { |
246 | const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation]; | 238 | return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n", |
247 | const struct tomoyo_path_info *filename = r->param.mkdev.filename; | 239 | tomoyo_mkdev_keyword |
248 | const unsigned int major = r->param.mkdev.major; | 240 | [r->param.mkdev.operation], |
249 | const unsigned int minor = r->param.mkdev.minor; | 241 | r->param.mkdev.filename->name, |
250 | const unsigned int mode = r->param.mkdev.mode; | 242 | r->param.mkdev.mode, r->param.mkdev.major, |
251 | if (r->granted) | 243 | r->param.mkdev.minor); |
252 | return 0; | ||
253 | tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, | ||
254 | major, minor); | ||
255 | return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n", operation, | ||
256 | filename->name, mode, major, minor); | ||
257 | } | 244 | } |
258 | 245 | ||
259 | /** | 246 | /** |
@@ -267,11 +254,7 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) | |||
267 | { | 254 | { |
268 | const u8 type = r->param.path_number.operation; | 255 | const u8 type = r->param.path_number.operation; |
269 | u8 radix; | 256 | u8 radix; |
270 | const struct tomoyo_path_info *filename = r->param.path_number.filename; | ||
271 | const char *operation = tomoyo_path_number_keyword[type]; | ||
272 | char buffer[64]; | 257 | char buffer[64]; |
273 | if (r->granted) | ||
274 | return 0; | ||
275 | switch (type) { | 258 | switch (type) { |
276 | case TOMOYO_TYPE_CREATE: | 259 | case TOMOYO_TYPE_CREATE: |
277 | case TOMOYO_TYPE_MKDIR: | 260 | case TOMOYO_TYPE_MKDIR: |
@@ -289,9 +272,9 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) | |||
289 | } | 272 | } |
290 | tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, | 273 | tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, |
291 | radix); | 274 | radix); |
292 | tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); | 275 | return tomoyo_supervisor(r, "file %s %s %s\n", |
293 | return tomoyo_supervisor(r, "file %s %s %s\n", operation, | 276 | tomoyo_path_number_keyword[type], |
294 | filename->name, buffer); | 277 | r->param.path_number.filename->name, buffer); |
295 | } | 278 | } |
296 | 279 | ||
297 | /** | 280 | /** |
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 839b8ebc6fe6..598282cd0bdd 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c | |||
@@ -29,6 +29,11 @@ void tomoyo_warn_oom(const char *function) | |||
29 | panic("MAC Initialization failed.\n"); | 29 | panic("MAC Initialization failed.\n"); |
30 | } | 30 | } |
31 | 31 | ||
32 | /* Memoy currently used by policy/audit log/query. */ | ||
33 | unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; | ||
34 | /* Memory quota for "policy"/"audit log"/"query". */ | ||
35 | unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; | ||
36 | |||
32 | /* Memory allocated for policy. */ | 37 | /* Memory allocated for policy. */ |
33 | static atomic_t tomoyo_policy_memory_size; | 38 | static atomic_t tomoyo_policy_memory_size; |
34 | /* Quota for holding policy. */ | 39 | /* Quota for holding policy. */ |
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 1e610f96c99d..8ba28fda4727 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c | |||
@@ -27,29 +27,11 @@ static const char * const tomoyo_mounts[TOMOYO_MAX_SPECIAL_MOUNT] = { | |||
27 | */ | 27 | */ |
28 | static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) | 28 | static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) |
29 | { | 29 | { |
30 | const char *dev = r->param.mount.dev->name; | 30 | return tomoyo_supervisor(r, "file mount %s %s %s 0x%lX\n", |
31 | const char *dir = r->param.mount.dir->name; | ||
32 | const char *type = r->param.mount.type->name; | ||
33 | const unsigned long flags = r->param.mount.flags; | ||
34 | if (r->granted) | ||
35 | return 0; | ||
36 | if (type == tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]) | ||
37 | tomoyo_warn_log(r, "mount -o remount %s 0x%lX", dir, flags); | ||
38 | else if (type == tomoyo_mounts[TOMOYO_MOUNT_BIND] | ||
39 | || type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) | ||
40 | tomoyo_warn_log(r, "mount %s %s %s 0x%lX", type, dev, dir, | ||
41 | flags); | ||
42 | else if (type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE] || | ||
43 | type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE] || | ||
44 | type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE] || | ||
45 | type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]) | ||
46 | tomoyo_warn_log(r, "mount %s %s 0x%lX", type, dir, flags); | ||
47 | else | ||
48 | tomoyo_warn_log(r, "mount -t %s %s %s 0x%lX", type, dev, dir, | ||
49 | flags); | ||
50 | return tomoyo_supervisor(r, "allow_mount %s %s %s 0x%lX\n", | ||
51 | r->param.mount.dev->name, | 31 | r->param.mount.dev->name, |
52 | r->param.mount.dir->name, type, flags); | 32 | r->param.mount.dir->name, |
33 | r->param.mount.type->name, | ||
34 | r->param.mount.flags); | ||
53 | } | 35 | } |
54 | 36 | ||
55 | /** | 37 | /** |
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c index 6410868c8a3d..e056609b422b 100644 --- a/security/tomoyo/securityfs_if.c +++ b/security/tomoyo/securityfs_if.c | |||
@@ -135,6 +135,8 @@ static int __init tomoyo_initerface_init(void) | |||
135 | TOMOYO_DOMAINPOLICY); | 135 | TOMOYO_DOMAINPOLICY); |
136 | tomoyo_create_entry("exception_policy", 0600, tomoyo_dir, | 136 | tomoyo_create_entry("exception_policy", 0600, tomoyo_dir, |
137 | TOMOYO_EXCEPTIONPOLICY); | 137 | TOMOYO_EXCEPTIONPOLICY); |
138 | tomoyo_create_entry("audit", 0400, tomoyo_dir, | ||
139 | TOMOYO_AUDIT); | ||
138 | tomoyo_create_entry("self_domain", 0400, tomoyo_dir, | 140 | tomoyo_create_entry("self_domain", 0400, tomoyo_dir, |
139 | TOMOYO_SELFDOMAIN); | 141 | TOMOYO_SELFDOMAIN); |
140 | tomoyo_create_entry(".domain_status", 0600, tomoyo_dir, | 142 | tomoyo_create_entry(".domain_status", 0600, tomoyo_dir, |
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index adcbdebd7352..bc71528ff440 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
@@ -892,20 +892,6 @@ const char *tomoyo_last_word(const char *name) | |||
892 | } | 892 | } |
893 | 893 | ||
894 | /** | 894 | /** |
895 | * tomoyo_warn_log - Print warning or error message on console. | ||
896 | * | ||
897 | * @r: Pointer to "struct tomoyo_request_info". | ||
898 | * @fmt: The printf()'s format string, followed by parameters. | ||
899 | */ | ||
900 | void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) | ||
901 | { | ||
902 | /* | ||
903 | * Temporarily disabled. | ||
904 | * Will be replaced with /sys/kernel/security/tomoyo/audit interface. | ||
905 | */ | ||
906 | } | ||
907 | |||
908 | /** | ||
909 | * tomoyo_domain_quota_is_ok - Check for domain's quota. | 895 | * tomoyo_domain_quota_is_ok - Check for domain's quota. |
910 | * | 896 | * |
911 | * @r: Pointer to "struct tomoyo_request_info". | 897 | * @r: Pointer to "struct tomoyo_request_info". |