オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /trunk/1.6.x/ccs-patch/fs/tomoyo_audit.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2020 - (show annotations) (download) (as text)
Fri Dec 26 03:37:12 2008 UTC (15 years, 5 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 9892 byte(s)


1 /*
2 * fs/tomoyo_audit.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2008 NTT DATA CORPORATION
7 *
8 * Version: 1.6.6-pre 2008/12/24
9 *
10 * This file is applicable to both 2.4.30 and 2.6.11 and later.
11 * See README.ccs for ChangeLog.
12 *
13 */
14
15 #include <linux/ccs_common.h>
16 #include <linux/tomoyo.h>
17 #include <linux/realpath.h>
18 #include <linux/highmem.h>
19
20 /**
21 * ccs_print_bprm - Print "struct linux_binprm" for auditing.
22 *
23 * @bprm: Pointer to "struct linux_binprm".
24 *
25 * Returns the contents of @bprm on success, NULL otherwise.
26 */
27 static char *ccs_print_bprm(struct linux_binprm *bprm)
28 {
29 static const int ccs_buffer_len = 4096 * 2;
30 char *buffer = ccs_alloc(ccs_buffer_len, false);
31 char *cp;
32 char *last_start;
33 int len;
34 unsigned long pos = bprm->p;
35 int offset = pos % PAGE_SIZE;
36 int argv_count = bprm->argc;
37 int envp_count = bprm->envc;
38 bool truncated = false;
39 if (!buffer)
40 return NULL;
41 len = snprintf(buffer, ccs_buffer_len - 1,
42 "argc=%d envc=%d argv[]={ ", argv_count, envp_count);
43 cp = buffer + len;
44 if (!argv_count) {
45 memmove(cp, "} envp[]={ ", 11);
46 cp += 11;
47 }
48 last_start = cp;
49 while (argv_count || envp_count) {
50 struct page *page = ccs_get_arg_page(bprm, pos);
51 const char *kaddr;
52 if (!page)
53 goto out;
54 pos += PAGE_SIZE - offset;
55 /* Map */
56 kaddr = kmap(page);
57 /* Read. */
58 while (offset < PAGE_SIZE) {
59 const unsigned char c = kaddr[offset++];
60 if (cp == last_start)
61 *cp++ = '"';
62 if (cp >= buffer + ccs_buffer_len - 32) {
63 /* Reserve some room for "..." string. */
64 truncated = true;
65 } else if (c == '\\') {
66 *cp++ = '\\';
67 *cp++ = '\\';
68 } else if (c > ' ' && c < 127) {
69 *cp++ = c;
70 } else if (!c) {
71 *cp++ = '"';
72 *cp++ = ' ';
73 last_start = cp;
74 } else {
75 *cp++ = '\\';
76 *cp++ = (c >> 6) + '0';
77 *cp++ = ((c >> 3) & 7) + '0';
78 *cp++ = (c & 7) + '0';
79 }
80 if (c)
81 continue;
82 if (argv_count) {
83 if (--argv_count == 0) {
84 if (truncated) {
85 cp = last_start;
86 memmove(cp, "... ", 4);
87 cp += 4;
88 }
89 memmove(cp, "} envp[]={ ", 11);
90 cp += 11;
91 last_start = cp;
92 truncated = false;
93 }
94 } else if (envp_count) {
95 if (--envp_count == 0) {
96 if (truncated) {
97 cp = last_start;
98 memmove(cp, "... ", 4);
99 cp += 4;
100 }
101 }
102 }
103 if (!argv_count && !envp_count)
104 break;
105 }
106 /* Unmap. */
107 kunmap(page);
108 ccs_put_arg_page(page);
109 offset = 0;
110 }
111 *cp++ = '}';
112 *cp = '\0';
113 return buffer;
114 out:
115 snprintf(buffer, ccs_buffer_len - 1,
116 "argc=%d envc=%d argv[]={ ... } envp[]= { ... }",
117 argv_count, envp_count);
118 return buffer;
119 }
120
121 static DECLARE_WAIT_QUEUE_HEAD(ccs_grant_log_wait);
122 static DECLARE_WAIT_QUEUE_HEAD(ccs_reject_log_wait);
123
124 static DEFINE_SPINLOCK(ccs_audit_log_lock);
125
126 /* Structure for audit log. */
127 struct ccs_log_entry {
128 struct list_head list;
129 char *log;
130 };
131
132 /* The list for "struct ccs_log_entry". */
133 static LIST_HEAD(ccs_grant_log);
134
135 /* The list for "struct ccs_log_entry". */
136 static LIST_HEAD(ccs_reject_log);
137
138 static int ccs_grant_log_count;
139 static int ccs_reject_log_count;
140
141 /**
142 * ccs_init_audit_log - Allocate buffer for audit logs.
143 *
144 * @len: Required size.
145 * @r: Pointer to "struct ccs_request_info".
146 *
147 * Returns pointer to allocated memory.
148 *
149 * The @len is updated to add the header lines' size on success.
150 */
151 char *ccs_init_audit_log(int *len, struct ccs_request_info *r)
152 {
153 static const char *ccs_mode_4[4] = {
154 "disabled", "learning", "permissive", "enforcing"
155 };
156 char *buf;
157 char *bprm_info = "";
158 struct timeval tv;
159 u32 tomoyo_flags = current->tomoyo_flags;
160 const char *domainname;
161 if (!r->domain)
162 r->domain = current->domain_info;
163 domainname = r->domain->domainname->name;
164 do_gettimeofday(&tv);
165 *len += strlen(domainname) + 256;
166 if (r->bprm) {
167 bprm_info = ccs_print_bprm(r->bprm);
168 if (!bprm_info)
169 return NULL;
170 *len += strlen(bprm_info);
171 }
172 buf = ccs_alloc(*len, true);
173 if (buf)
174 snprintf(buf, (*len) - 1,
175 "#timestamp=%lu profile=%u mode=%s pid=%d uid=%d "
176 "gid=%d euid=%d egid=%d suid=%d sgid=%d fsuid=%d "
177 "fsgid=%d state[0]=%u state[1]=%u state[2]=%u %s\n"
178 "%s\n",
179 tv.tv_sec, r->profile, ccs_mode_4[r->mode],
180 (pid_t) sys_getpid(), current_uid(), current_gid(),
181 current_euid(), current_egid(), current_suid(),
182 current_sgid(), current_fsuid(), current_fsgid(),
183 (u8) (tomoyo_flags >> 24), (u8) (tomoyo_flags >> 16),
184 (u8) (tomoyo_flags >> 8), bprm_info, domainname);
185 if (r->bprm)
186 ccs_free(bprm_info);
187 return buf;
188 }
189
190 /**
191 * ccs_can_save_audit_log - Check whether the kernel can save new audit log.
192 *
193 * @domain: Pointer to "struct domain_info". NULL for current->domain_info.
194 * @is_granted: True if this is a granted log.
195 *
196 * Returns true if the kernel can save, false otherwise.
197 */
198 static bool ccs_can_save_audit_log(const struct domain_info *domain,
199 const bool is_granted)
200 {
201 if (is_granted)
202 return ccs_grant_log_count
203 < ccs_check_flags(domain, CCS_TOMOYO_MAX_GRANT_LOG);
204 return ccs_reject_log_count
205 < ccs_check_flags(domain, CCS_TOMOYO_MAX_REJECT_LOG);
206 }
207
208 /**
209 * ccs_write_audit_log - Write audit log.
210 *
211 * @is_granted: True if this is a granted log.
212 * @r: Pointer to "struct ccs_request_info".
213 * @fmt: The printf()'s format string, followed by parameters.
214 *
215 * Returns 0 on success, -ENOMEM otherwise.
216 */
217 int ccs_write_audit_log(const bool is_granted, struct ccs_request_info *r,
218 const char *fmt, ...)
219 {
220 va_list args;
221 int error = -ENOMEM;
222 int pos;
223 int len;
224 char *buf;
225 struct ccs_log_entry *new_entry;
226 const struct ccs_condition_list *ptr;
227 struct task_struct *task = current;
228 if (!r->domain)
229 r->domain = task->domain_info;
230 if (!ccs_can_save_audit_log(r->domain, is_granted))
231 goto out;
232 va_start(args, fmt);
233 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
234 va_end(args);
235 buf = ccs_init_audit_log(&len, r);
236 if (!buf)
237 goto out;
238 pos = strlen(buf);
239 va_start(args, fmt);
240 vsnprintf(buf + pos, len - pos - 1, fmt, args);
241 va_end(args);
242 new_entry = ccs_alloc(sizeof(*new_entry), true);
243 if (!new_entry) {
244 ccs_free(buf);
245 goto out;
246 }
247 new_entry->log = buf;
248 /***** CRITICAL SECTION START *****/
249 spin_lock(&ccs_audit_log_lock);
250 if (is_granted) {
251 list_add_tail(&new_entry->list, &ccs_grant_log);
252 ccs_grant_log_count++;
253 ccs_update_counter(CCS_UPDATES_COUNTER_GRANT_LOG);
254 } else {
255 list_add_tail(&new_entry->list, &ccs_reject_log);
256 ccs_reject_log_count++;
257 ccs_update_counter(CCS_UPDATES_COUNTER_REJECT_LOG);
258 }
259 spin_unlock(&ccs_audit_log_lock);
260 /***** CRITICAL SECTION END *****/
261 if (is_granted)
262 wake_up(&ccs_grant_log_wait);
263 else
264 wake_up(&ccs_reject_log_wait);
265 error = 0;
266 out:
267 /*
268 * Update task's state.
269 *
270 * Don't change the lowest byte because it is reserved for
271 * TOMOYO_CHECK_READ_FOR_OPEN_EXEC / CCS_DONT_SLEEP_ON_ENFORCE_ERROR /
272 * TOMOYO_TASK_IS_EXECUTE_HANDLER.
273 */
274 ptr = r->cond;
275 if (ptr) {
276 const u8 flags = ptr->post_state[3];
277 u32 tomoyo_flags = task->tomoyo_flags;
278 if (flags & 1) {
279 tomoyo_flags &= ~0xFF000000;
280 tomoyo_flags |= ptr->post_state[0] << 24;
281 }
282 if (flags & 2) {
283 tomoyo_flags &= ~0x00FF0000;
284 tomoyo_flags |= ptr->post_state[1] << 16;
285 }
286 if (flags & 4) {
287 tomoyo_flags &= ~0x0000FF00;
288 tomoyo_flags |= ptr->post_state[2] << 8;
289 }
290 task->tomoyo_flags = tomoyo_flags;
291 r->cond = NULL;
292 }
293 return error;
294 }
295
296 /**
297 * ccs_read_grant_log - Read a grant log.
298 *
299 * @head: Pointer to "struct ccs_io_buffer".
300 *
301 * Returns 0.
302 */
303 int ccs_read_grant_log(struct ccs_io_buffer *head)
304 {
305 struct ccs_log_entry *ptr = NULL;
306 if (head->read_avail)
307 return 0;
308 if (head->read_buf) {
309 ccs_free(head->read_buf);
310 head->read_buf = NULL;
311 head->readbuf_size = 0;
312 }
313 /***** CRITICAL SECTION START *****/
314 spin_lock(&ccs_audit_log_lock);
315 if (!list_empty(&ccs_grant_log)) {
316 ptr = list_entry(ccs_grant_log.next, struct ccs_log_entry,
317 list);
318 list_del(&ptr->list);
319 ccs_grant_log_count--;
320 }
321 spin_unlock(&ccs_audit_log_lock);
322 /***** CRITICAL SECTION END *****/
323 if (ptr) {
324 head->read_buf = ptr->log;
325 head->read_avail = strlen(ptr->log) + 1;
326 head->readbuf_size = head->read_avail;
327 ccs_free(ptr);
328 }
329 return 0;
330 }
331
332 /**
333 * ccs_poll_grant_log - Wait for a grant log.
334 *
335 * @file: Pointer to "struct file".
336 * @wait: Pointer to "poll_table".
337 *
338 * Returns POLLIN | POLLRDNORM when ready to read a grant log.
339 */
340 int ccs_poll_grant_log(struct file *file, poll_table *wait)
341 {
342 if (ccs_grant_log_count)
343 return POLLIN | POLLRDNORM;
344 poll_wait(file, &ccs_grant_log_wait, wait);
345 if (ccs_grant_log_count)
346 return POLLIN | POLLRDNORM;
347 return 0;
348 }
349
350 /**
351 * ccs_read_reject_log - Read a reject log.
352 *
353 * @head: Pointer to "struct ccs_io_buffer".
354 *
355 * Returns 0.
356 */
357 int ccs_read_reject_log(struct ccs_io_buffer *head)
358 {
359 struct ccs_log_entry *ptr = NULL;
360 if (head->read_avail)
361 return 0;
362 if (head->read_buf) {
363 ccs_free(head->read_buf);
364 head->read_buf = NULL;
365 head->readbuf_size = 0;
366 }
367 /***** CRITICAL SECTION START *****/
368 spin_lock(&ccs_audit_log_lock);
369 if (!list_empty(&ccs_reject_log)) {
370 ptr = list_entry(ccs_reject_log.next, struct ccs_log_entry,
371 list);
372 list_del(&ptr->list);
373 ccs_reject_log_count--;
374 }
375 spin_unlock(&ccs_audit_log_lock);
376 /***** CRITICAL SECTION END *****/
377 if (ptr) {
378 head->read_buf = ptr->log;
379 head->read_avail = strlen(ptr->log) + 1;
380 head->readbuf_size = head->read_avail;
381 ccs_free(ptr);
382 }
383 return 0;
384 }
385
386 /**
387 * ccs_poll_reject_log - Wait for a reject log.
388 *
389 * @file: Pointer to "struct file".
390 * @wait: Pointer to "poll_table".
391 *
392 * Returns POLLIN | POLLRDNORM when ready to read a reject log.
393 */
394 int ccs_poll_reject_log(struct file *file, poll_table *wait)
395 {
396 if (ccs_reject_log_count)
397 return POLLIN | POLLRDNORM;
398 poll_wait(file, &ccs_reject_log_wait, wait);
399 if (ccs_reject_log_count)
400 return POLLIN | POLLRDNORM;
401 return 0;
402 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26