diff options
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r-- | security/tomoyo/common.c | 311 |
1 files changed, 151 insertions, 160 deletions
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); |