aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2010-05-16 21:11:36 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:33:38 -0400
commit17fcfbd9d45b57f38d40e31f9d28db53f4af5c88 (patch)
treee221937affe4d886706e880f39e1424333490cc0 /security/tomoyo
parent2106ccd972dcd9fda7df9b181505fac1741b3508 (diff)
TOMOYO: Add interactive enforcing mode.
Since the behavior of the system is restricted by policy, we may need to update policy when you update packages. We need to update policy in the following cases. * The pathname of files has changed. * The dependency of files has changed. * The access permissions required has increased. The ideal way to update policy is to rebuild from the scratch using learning mode. But it is not desirable to change from enforcing mode to other mode if the system has once entered in production state. Suppose MAC could support per-application enforcing mode, the MAC becomes useless if an application that is not running in enforcing mode was cracked. For example, the whole system becomes vulnerable if only HTTP server application is running in learning mode to rebuild policy for the application. So, in TOMOYO Linux, updating policy is done while the system is running in enforcing mode. This patch implements "interactive enforcing mode" which allows administrators to judge whether to accept policy violation in enforcing mode or not. A demo movie is available at http://www.youtube.com/watch?v=b9q1Jo25LPA . Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo')
-rw-r--r--security/tomoyo/common.c426
-rw-r--r--security/tomoyo/common.h28
-rw-r--r--security/tomoyo/domain.c47
-rw-r--r--security/tomoyo/file.c140
-rw-r--r--security/tomoyo/mount.c24
-rw-r--r--security/tomoyo/realpath.c19
6 files changed, 564 insertions, 120 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 0c6f9a5c37a5..ee46aaa3566f 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -74,6 +74,8 @@ static int tomoyo_read_control(struct file *file, char __user *buffer,
74/* Write operation for /sys/kernel/security/tomoyo/ interface. */ 74/* Write operation for /sys/kernel/security/tomoyo/ interface. */
75static int tomoyo_write_control(struct file *file, const char __user *buffer, 75static int tomoyo_write_control(struct file *file, const char __user *buffer,
76 const int buffer_len); 76 const int buffer_len);
77/* Check whether the domain has too many ACL entries to hold. */
78static bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
77 79
78/** 80/**
79 * tomoyo_parse_name_union - Parse a tomoyo_name_union. 81 * tomoyo_parse_name_union - Parse a tomoyo_name_union.
@@ -1031,7 +1033,7 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
1031 * 1033 *
1032 * Caller holds tomoyo_read_lock(). 1034 * Caller holds tomoyo_read_lock().
1033 */ 1035 */
1034bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) 1036static bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
1035{ 1037{
1036 unsigned int count = 0; 1038 unsigned int count = 0;
1037 struct tomoyo_domain_info *domain = r->domain; 1039 struct tomoyo_domain_info *domain = r->domain;
@@ -1531,6 +1533,24 @@ static int tomoyo_delete_domain(char *domainname)
1531} 1533}
1532 1534
1533/** 1535/**
1536 * tomoyo_write_domain_policy2 - Write domain policy.
1537 *
1538 * @head: Pointer to "struct tomoyo_io_buffer".
1539 *
1540 * Returns 0 on success, negative value otherwise.
1541 *
1542 * Caller holds tomoyo_read_lock().
1543 */
1544static int tomoyo_write_domain_policy2(char *data,
1545 struct tomoyo_domain_info *domain,
1546 const bool is_delete)
1547{
1548 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_MOUNT))
1549 return tomoyo_write_mount_policy(data, domain, is_delete);
1550 return tomoyo_write_file_policy(data, domain, is_delete);
1551}
1552
1553/**
1534 * tomoyo_write_domain_policy - Write domain policy. 1554 * tomoyo_write_domain_policy - Write domain policy.
1535 * 1555 *
1536 * @head: Pointer to "struct tomoyo_io_buffer". 1556 * @head: Pointer to "struct tomoyo_io_buffer".
@@ -1580,9 +1600,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1580 domain->ignore_global_allow_read = !is_delete; 1600 domain->ignore_global_allow_read = !is_delete;
1581 return 0; 1601 return 0;
1582 } 1602 }
1583 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_MOUNT)) 1603 return tomoyo_write_domain_policy2(data, domain, is_delete);
1584 return tomoyo_write_mount_policy(data, domain, is_delete);
1585 return tomoyo_write_file_policy(data, domain, is_delete);
1586} 1604}
1587 1605
1588/** 1606/**
@@ -2186,6 +2204,357 @@ void tomoyo_load_policy(const char *filename)
2186} 2204}
2187 2205
2188/** 2206/**
2207 * tomoyo_print_header - Get header line of audit log.
2208 *
2209 * @r: Pointer to "struct tomoyo_request_info".
2210 *
2211 * Returns string representation.
2212 *
2213 * This function uses kmalloc(), so caller must kfree() if this function
2214 * didn't return NULL.
2215 */
2216static char *tomoyo_print_header(struct tomoyo_request_info *r)
2217{
2218 static const char *tomoyo_mode_4[4] = {
2219 "disabled", "learning", "permissive", "enforcing"
2220 };
2221 struct timeval tv;
2222 const pid_t gpid = task_pid_nr(current);
2223 static const int tomoyo_buffer_len = 4096;
2224 char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
2225 if (!buffer)
2226 return NULL;
2227 do_gettimeofday(&tv);
2228 snprintf(buffer, tomoyo_buffer_len - 1,
2229 "#timestamp=%lu profile=%u mode=%s (global-pid=%u)"
2230 " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u"
2231 " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }",
2232 tv.tv_sec, r->profile, tomoyo_mode_4[r->mode], gpid,
2233 (pid_t) sys_getpid(), (pid_t) sys_getppid(),
2234 current_uid(), current_gid(), current_euid(),
2235 current_egid(), current_suid(), current_sgid(),
2236 current_fsuid(), current_fsgid());
2237 return buffer;
2238}
2239
2240/**
2241 * tomoyo_init_audit_log - Allocate buffer for audit logs.
2242 *
2243 * @len: Required size.
2244 * @r: Pointer to "struct tomoyo_request_info".
2245 *
2246 * Returns pointer to allocated memory.
2247 *
2248 * The @len is updated to add the header lines' size on success.
2249 *
2250 * This function uses kzalloc(), so caller must kfree() if this function
2251 * didn't return NULL.
2252 */
2253static char *tomoyo_init_audit_log(int *len, struct tomoyo_request_info *r)
2254{
2255 char *buf = NULL;
2256 const char *header;
2257 const char *domainname;
2258 if (!r->domain)
2259 r->domain = tomoyo_domain();
2260 domainname = r->domain->domainname->name;
2261 header = tomoyo_print_header(r);
2262 if (!header)
2263 return NULL;
2264 *len += strlen(domainname) + strlen(header) + 10;
2265 buf = kzalloc(*len, GFP_NOFS);
2266 if (buf)
2267 snprintf(buf, (*len) - 1, "%s\n%s\n", header, domainname);
2268 kfree(header);
2269 return buf;
2270}
2271
2272/* Wait queue for tomoyo_query_list. */
2273static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait);
2274
2275/* Lock for manipulating tomoyo_query_list. */
2276static DEFINE_SPINLOCK(tomoyo_query_list_lock);
2277
2278/* Structure for query. */
2279struct tomoyo_query_entry {
2280 struct list_head list;
2281 char *query;
2282 int query_len;
2283 unsigned int serial;
2284 int timer;
2285 int answer;
2286};
2287
2288/* The list for "struct tomoyo_query_entry". */
2289static LIST_HEAD(tomoyo_query_list);
2290
2291/*
2292 * Number of "struct file" referring /sys/kernel/security/tomoyo/query
2293 * interface.
2294 */
2295static atomic_t tomoyo_query_observers = ATOMIC_INIT(0);
2296
2297/**
2298 * tomoyo_supervisor - Ask for the supervisor's decision.
2299 *
2300 * @r: Pointer to "struct tomoyo_request_info".
2301 * @fmt: The printf()'s format string, followed by parameters.
2302 *
2303 * Returns 0 if the supervisor decided to permit the access request which
2304 * violated the policy in enforcing mode, TOMOYO_RETRY_REQUEST if the
2305 * supervisor decided to retry the access request which violated the policy in
2306 * enforcing mode, 0 if it is not in enforcing mode, -EPERM otherwise.
2307 */
2308int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
2309{
2310 va_list args;
2311 int error = -EPERM;
2312 int pos;
2313 int len;
2314 static unsigned int tomoyo_serial;
2315 struct tomoyo_query_entry *tomoyo_query_entry = NULL;
2316 bool quota_exceeded = false;
2317 char *header;
2318 switch (r->mode) {
2319 char *buffer;
2320 case TOMOYO_CONFIG_LEARNING:
2321 if (!tomoyo_domain_quota_is_ok(r))
2322 return 0;
2323 va_start(args, fmt);
2324 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;
2325 va_end(args);
2326 buffer = kmalloc(len, GFP_NOFS);
2327 if (!buffer)
2328 return 0;
2329 va_start(args, fmt);
2330 vsnprintf(buffer, len - 1, fmt, args);
2331 va_end(args);
2332 tomoyo_normalize_line(buffer);
2333 tomoyo_write_domain_policy2(buffer, r->domain, false);
2334 kfree(buffer);
2335 /* fall through */
2336 case TOMOYO_CONFIG_PERMISSIVE:
2337 return 0;
2338 }
2339 if (!r->domain)
2340 r->domain = tomoyo_domain();
2341 if (!atomic_read(&tomoyo_query_observers))
2342 return -EPERM;
2343 va_start(args, fmt);
2344 len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
2345 va_end(args);
2346 header = tomoyo_init_audit_log(&len, r);
2347 if (!header)
2348 goto out;
2349 tomoyo_query_entry = kzalloc(sizeof(*tomoyo_query_entry), GFP_NOFS);
2350 if (!tomoyo_query_entry)
2351 goto out;
2352 tomoyo_query_entry->query = kzalloc(len, GFP_NOFS);
2353 if (!tomoyo_query_entry->query)
2354 goto out;
2355 len = ksize(tomoyo_query_entry->query);
2356 INIT_LIST_HEAD(&tomoyo_query_entry->list);
2357 spin_lock(&tomoyo_query_list_lock);
2358 if (tomoyo_quota_for_query && tomoyo_query_memory_size + len +
2359 sizeof(*tomoyo_query_entry) >= tomoyo_quota_for_query) {
2360 quota_exceeded = true;
2361 } else {
2362 tomoyo_query_memory_size += len + sizeof(*tomoyo_query_entry);
2363 tomoyo_query_entry->serial = tomoyo_serial++;
2364 }
2365 spin_unlock(&tomoyo_query_list_lock);
2366 if (quota_exceeded)
2367 goto out;
2368 pos = snprintf(tomoyo_query_entry->query, len - 1, "Q%u-%hu\n%s",
2369 tomoyo_query_entry->serial, r->retry, header);
2370 kfree(header);
2371 header = NULL;
2372 va_start(args, fmt);
2373 vsnprintf(tomoyo_query_entry->query + pos, len - 1 - pos, fmt, args);
2374 tomoyo_query_entry->query_len = strlen(tomoyo_query_entry->query) + 1;
2375 va_end(args);
2376 spin_lock(&tomoyo_query_list_lock);
2377 list_add_tail(&tomoyo_query_entry->list, &tomoyo_query_list);
2378 spin_unlock(&tomoyo_query_list_lock);
2379 /* Give 10 seconds for supervisor's opinion. */
2380 for (tomoyo_query_entry->timer = 0;
2381 atomic_read(&tomoyo_query_observers) && tomoyo_query_entry->timer < 100;
2382 tomoyo_query_entry->timer++) {
2383 wake_up(&tomoyo_query_wait);
2384 set_current_state(TASK_INTERRUPTIBLE);
2385 schedule_timeout(HZ / 10);
2386 if (tomoyo_query_entry->answer)
2387 break;
2388 }
2389 spin_lock(&tomoyo_query_list_lock);
2390 list_del(&tomoyo_query_entry->list);
2391 tomoyo_query_memory_size -= len + sizeof(*tomoyo_query_entry);
2392 spin_unlock(&tomoyo_query_list_lock);
2393 switch (tomoyo_query_entry->answer) {
2394 case 3: /* Asked to retry by administrator. */
2395 error = TOMOYO_RETRY_REQUEST;
2396 r->retry++;
2397 break;
2398 case 1:
2399 /* Granted by administrator. */
2400 error = 0;
2401 break;
2402 case 0:
2403 /* Timed out. */
2404 break;
2405 default:
2406 /* Rejected by administrator. */
2407 break;
2408 }
2409 out:
2410 if (tomoyo_query_entry)
2411 kfree(tomoyo_query_entry->query);
2412 kfree(tomoyo_query_entry);
2413 kfree(header);
2414 return error;
2415}
2416
2417/**
2418 * tomoyo_poll_query - poll() for /sys/kernel/security/tomoyo/query.
2419 *
2420 * @file: Pointer to "struct file".
2421 * @wait: Pointer to "poll_table".
2422 *
2423 * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise.
2424 *
2425 * Waits for access requests which violated policy in enforcing mode.
2426 */
2427static int tomoyo_poll_query(struct file *file, poll_table *wait)
2428{
2429 struct list_head *tmp;
2430 bool found = false;
2431 u8 i;
2432 for (i = 0; i < 2; i++) {
2433 spin_lock(&tomoyo_query_list_lock);
2434 list_for_each(tmp, &tomoyo_query_list) {
2435 struct tomoyo_query_entry *ptr
2436 = list_entry(tmp, struct tomoyo_query_entry,
2437 list);
2438 if (ptr->answer)
2439 continue;
2440 found = true;
2441 break;
2442 }
2443 spin_unlock(&tomoyo_query_list_lock);
2444 if (found)
2445 return POLLIN | POLLRDNORM;
2446 if (i)
2447 break;
2448 poll_wait(file, &tomoyo_query_wait, wait);
2449 }
2450 return 0;
2451}
2452
2453/**
2454 * tomoyo_read_query - Read access requests which violated policy in enforcing mode.
2455 *
2456 * @head: Pointer to "struct tomoyo_io_buffer".
2457 *
2458 * Returns 0.
2459 */
2460static int tomoyo_read_query(struct tomoyo_io_buffer *head)
2461{
2462 struct list_head *tmp;
2463 int pos = 0;
2464 int len = 0;
2465 char *buf;
2466 if (head->read_avail)
2467 return 0;
2468 if (head->read_buf) {
2469 kfree(head->read_buf);
2470 head->read_buf = NULL;
2471 head->readbuf_size = 0;
2472 }
2473 spin_lock(&tomoyo_query_list_lock);
2474 list_for_each(tmp, &tomoyo_query_list) {
2475 struct tomoyo_query_entry *ptr
2476 = list_entry(tmp, struct tomoyo_query_entry, list);
2477 if (ptr->answer)
2478 continue;
2479 if (pos++ != head->read_step)
2480 continue;
2481 len = ptr->query_len;
2482 break;
2483 }
2484 spin_unlock(&tomoyo_query_list_lock);
2485 if (!len) {
2486 head->read_step = 0;
2487 return 0;
2488 }
2489 buf = kzalloc(len, GFP_NOFS);
2490 if (!buf)
2491 return 0;
2492 pos = 0;
2493 spin_lock(&tomoyo_query_list_lock);
2494 list_for_each(tmp, &tomoyo_query_list) {
2495 struct tomoyo_query_entry *ptr
2496 = list_entry(tmp, struct tomoyo_query_entry, list);
2497 if (ptr->answer)
2498 continue;
2499 if (pos++ != head->read_step)
2500 continue;
2501 /*
2502 * Some query can be skipped because tomoyo_query_list
2503 * can change, but I don't care.
2504 */
2505 if (len == ptr->query_len)
2506 memmove(buf, ptr->query, len);
2507 break;
2508 }
2509 spin_unlock(&tomoyo_query_list_lock);
2510 if (buf[0]) {
2511 head->read_avail = len;
2512 head->readbuf_size = head->read_avail;
2513 head->read_buf = buf;
2514 head->read_step++;
2515 } else {
2516 kfree(buf);
2517 }
2518 return 0;
2519}
2520
2521/**
2522 * tomoyo_write_answer - Write the supervisor's decision.
2523 *
2524 * @head: Pointer to "struct tomoyo_io_buffer".
2525 *
2526 * Returns 0 on success, -EINVAL otherwise.
2527 */
2528static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
2529{
2530 char *data = head->write_buf;
2531 struct list_head *tmp;
2532 unsigned int serial;
2533 unsigned int answer;
2534 spin_lock(&tomoyo_query_list_lock);
2535 list_for_each(tmp, &tomoyo_query_list) {
2536 struct tomoyo_query_entry *ptr
2537 = list_entry(tmp, struct tomoyo_query_entry, list);
2538 ptr->timer = 0;
2539 }
2540 spin_unlock(&tomoyo_query_list_lock);
2541 if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
2542 return -EINVAL;
2543 spin_lock(&tomoyo_query_list_lock);
2544 list_for_each(tmp, &tomoyo_query_list) {
2545 struct tomoyo_query_entry *ptr
2546 = list_entry(tmp, struct tomoyo_query_entry, list);
2547 if (ptr->serial != serial)
2548 continue;
2549 if (!ptr->answer)
2550 ptr->answer = answer;
2551 break;
2552 }
2553 spin_unlock(&tomoyo_query_list_lock);
2554 return 0;
2555}
2556
2557/**
2189 * tomoyo_read_version: Get version. 2558 * tomoyo_read_version: Get version.
2190 * 2559 *
2191 * @head: Pointer to "struct tomoyo_io_buffer". 2560 * @head: Pointer to "struct tomoyo_io_buffer".
@@ -2239,6 +2608,7 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2239 if (!head) 2608 if (!head)
2240 return -ENOMEM; 2609 return -ENOMEM;
2241 mutex_init(&head->io_sem); 2610 mutex_init(&head->io_sem);
2611 head->type = type;
2242 switch (type) { 2612 switch (type) {
2243 case TOMOYO_DOMAINPOLICY: 2613 case TOMOYO_DOMAINPOLICY:
2244 /* /sys/kernel/security/tomoyo/domain_policy */ 2614 /* /sys/kernel/security/tomoyo/domain_policy */
@@ -2280,6 +2650,11 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2280 head->write = tomoyo_write_profile; 2650 head->write = tomoyo_write_profile;
2281 head->read = tomoyo_read_profile; 2651 head->read = tomoyo_read_profile;
2282 break; 2652 break;
2653 case TOMOYO_QUERY: /* /sys/kernel/security/tomoyo/query */
2654 head->poll = tomoyo_poll_query;
2655 head->write = tomoyo_write_answer;
2656 head->read = tomoyo_read_query;
2657 break;
2283 case TOMOYO_MANAGER: 2658 case TOMOYO_MANAGER:
2284 /* /sys/kernel/security/tomoyo/manager */ 2659 /* /sys/kernel/security/tomoyo/manager */
2285 head->write = tomoyo_write_manager_policy; 2660 head->write = tomoyo_write_manager_policy;
@@ -2292,7 +2667,9 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2292 * for reading. 2667 * for reading.
2293 */ 2668 */
2294 head->read = NULL; 2669 head->read = NULL;
2295 } else { 2670 head->poll = NULL;
2671 } else if (!head->poll) {
2672 /* Don't allocate read_buf for poll() access. */
2296 if (!head->readbuf_size) 2673 if (!head->readbuf_size)
2297 head->readbuf_size = 4096 * 2; 2674 head->readbuf_size = 4096 * 2;
2298 head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS); 2675 head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS);
@@ -2316,7 +2693,8 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2316 return -ENOMEM; 2693 return -ENOMEM;
2317 } 2694 }
2318 } 2695 }
2319 head->reader_idx = tomoyo_read_lock(); 2696 if (type != TOMOYO_QUERY)
2697 head->reader_idx = tomoyo_read_lock();
2320 file->private_data = head; 2698 file->private_data = head;
2321 /* 2699 /*
2322 * Call the handler now if the file is 2700 * Call the handler now if the file is
@@ -2327,10 +2705,35 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2327 */ 2705 */
2328 if (type == TOMOYO_SELFDOMAIN) 2706 if (type == TOMOYO_SELFDOMAIN)
2329 tomoyo_read_control(file, NULL, 0); 2707 tomoyo_read_control(file, NULL, 0);
2708 /*
2709 * If the file is /sys/kernel/security/tomoyo/query , increment the
2710 * observer counter.
2711 * The obserber counter is used by tomoyo_supervisor() to see if
2712 * there is some process monitoring /sys/kernel/security/tomoyo/query.
2713 */
2714 else if (type == TOMOYO_QUERY)
2715 atomic_inc(&tomoyo_query_observers);
2330 return 0; 2716 return 0;
2331} 2717}
2332 2718
2333/** 2719/**
2720 * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface.
2721 *
2722 * @file: Pointer to "struct file".
2723 * @wait: Pointer to "poll_table".
2724 *
2725 * Waits for read readiness.
2726 * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd .
2727 */
2728int tomoyo_poll_control(struct file *file, poll_table *wait)
2729{
2730 struct tomoyo_io_buffer *head = file->private_data;
2731 if (!head->poll)
2732 return -ENOSYS;
2733 return head->poll(file, wait);
2734}
2735
2736/**
2334 * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. 2737 * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
2335 * 2738 *
2336 * @file: Pointer to "struct file". 2739 * @file: Pointer to "struct file".
@@ -2443,7 +2846,14 @@ static int tomoyo_close_control(struct file *file)
2443 struct tomoyo_io_buffer *head = file->private_data; 2846 struct tomoyo_io_buffer *head = file->private_data;
2444 const bool is_write = !!head->write_buf; 2847 const bool is_write = !!head->write_buf;
2445 2848
2446 tomoyo_read_unlock(head->reader_idx); 2849 /*
2850 * If the file is /sys/kernel/security/tomoyo/query , decrement the
2851 * observer counter.
2852 */
2853 if (head->type == TOMOYO_QUERY)
2854 atomic_dec(&tomoyo_query_observers);
2855 else
2856 tomoyo_read_unlock(head->reader_idx);
2447 /* Release memory used for policy I/O. */ 2857 /* Release memory used for policy I/O. */
2448 kfree(head->read_buf); 2858 kfree(head->read_buf);
2449 head->read_buf = NULL; 2859 head->read_buf = NULL;
@@ -2562,6 +2972,8 @@ static int __init tomoyo_initerface_init(void)
2562 return 0; 2972 return 0;
2563 2973
2564 tomoyo_dir = securityfs_create_dir("tomoyo", NULL); 2974 tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
2975 tomoyo_create_entry("query", 0600, tomoyo_dir,
2976 TOMOYO_QUERY);
2565 tomoyo_create_entry("domain_policy", 0600, tomoyo_dir, 2977 tomoyo_create_entry("domain_policy", 0600, tomoyo_dir,
2566 TOMOYO_DOMAINPOLICY); 2978 TOMOYO_DOMAINPOLICY);
2567 tomoyo_create_entry("exception_policy", 0600, tomoyo_dir, 2979 tomoyo_create_entry("exception_policy", 0600, tomoyo_dir,
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 3d819b139165..dc5f98f52f61 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -20,6 +20,7 @@
20#include <linux/mount.h> 20#include <linux/mount.h>
21#include <linux/list.h> 21#include <linux/list.h>
22#include <linux/cred.h> 22#include <linux/cred.h>
23#include <linux/poll.h>
23struct linux_binprm; 24struct linux_binprm;
24 25
25/********** Constants definitions. **********/ 26/********** Constants definitions. **********/
@@ -156,9 +157,12 @@ enum tomoyo_securityfs_interface_index {
156 TOMOYO_SELFDOMAIN, 157 TOMOYO_SELFDOMAIN,
157 TOMOYO_VERSION, 158 TOMOYO_VERSION,
158 TOMOYO_PROFILE, 159 TOMOYO_PROFILE,
160 TOMOYO_QUERY,
159 TOMOYO_MANAGER 161 TOMOYO_MANAGER
160}; 162};
161 163
164#define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */
165
162/********** Structure definitions. **********/ 166/********** Structure definitions. **********/
163 167
164/* 168/*
@@ -176,10 +180,14 @@ struct tomoyo_page_buffer {
176 * tomoyo_request_info is a structure which is used for holding 180 * tomoyo_request_info is a structure which is used for holding
177 * 181 *
178 * (1) Domain information of current process. 182 * (1) Domain information of current process.
179 * (2) Access control mode of the profile. 183 * (2) How many retries are made for this request.
184 * (3) Profile number used for this request.
185 * (4) Access control mode of the profile.
180 */ 186 */
181struct tomoyo_request_info { 187struct tomoyo_request_info {
182 struct tomoyo_domain_info *domain; 188 struct tomoyo_domain_info *domain;
189 u8 retry;
190 u8 profile;
183 u8 mode; /* One of tomoyo_mode_index . */ 191 u8 mode; /* One of tomoyo_mode_index . */
184}; 192};
185 193
@@ -484,6 +492,7 @@ struct tomoyo_mount_acl {
484struct tomoyo_io_buffer { 492struct tomoyo_io_buffer {
485 int (*read) (struct tomoyo_io_buffer *); 493 int (*read) (struct tomoyo_io_buffer *);
486 int (*write) (struct tomoyo_io_buffer *); 494 int (*write) (struct tomoyo_io_buffer *);
495 int (*poll) (struct file *file, poll_table *wait);
487 /* Exclusive lock for this structure. */ 496 /* Exclusive lock for this structure. */
488 struct mutex io_sem; 497 struct mutex io_sem;
489 /* Index returned by tomoyo_read_lock(). */ 498 /* Index returned by tomoyo_read_lock(). */
@@ -514,6 +523,8 @@ struct tomoyo_io_buffer {
514 int write_avail; 523 int write_avail;
515 /* Size of write buffer. */ 524 /* Size of write buffer. */
516 int writebuf_size; 525 int writebuf_size;
526 /* Type of this interface. */
527 u8 type;
517}; 528};
518 529
519/* 530/*
@@ -659,14 +670,15 @@ struct tomoyo_policy_manager_entry {
659 670
660/********** Function prototypes. **********/ 671/********** Function prototypes. **********/
661 672
673extern asmlinkage long sys_getpid(void);
674extern asmlinkage long sys_getppid(void);
675
662/* Check whether the given name matches the given name_union. */ 676/* Check whether the given name matches the given name_union. */
663bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, 677bool tomoyo_compare_name_union(const struct tomoyo_path_info *name,
664 const struct tomoyo_name_union *ptr); 678 const struct tomoyo_name_union *ptr);
665/* Check whether the given number matches the given number_union. */ 679/* Check whether the given number matches the given number_union. */
666bool tomoyo_compare_number_union(const unsigned long value, 680bool tomoyo_compare_number_union(const unsigned long value,
667 const struct tomoyo_number_union *ptr); 681 const struct tomoyo_number_union *ptr);
668/* Check whether the domain has too many ACL entries to hold. */
669bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
670/* Transactional sprintf() for policy dump. */ 682/* Transactional sprintf() for policy dump. */
671bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 683bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
672 __attribute__ ((format(printf, 2, 3))); 684 __attribute__ ((format(printf, 2, 3)));
@@ -763,6 +775,8 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
763int tomoyo_write_pattern_policy(char *data, const bool is_delete); 775int tomoyo_write_pattern_policy(char *data, const bool is_delete);
764/* Create "path_group" entry in exception policy. */ 776/* Create "path_group" entry in exception policy. */
765int tomoyo_write_path_group_policy(char *data, const bool is_delete); 777int tomoyo_write_path_group_policy(char *data, const bool is_delete);
778int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
779 __attribute__ ((format(printf, 2, 3)));
766/* Create "number_group" entry in exception policy. */ 780/* Create "number_group" entry in exception policy. */
767int tomoyo_write_number_group_policy(char *data, const bool is_delete); 781int tomoyo_write_number_group_policy(char *data, const bool is_delete);
768/* Find a domain by the given name. */ 782/* Find a domain by the given name. */
@@ -771,9 +785,6 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
771struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 785struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
772 domainname, 786 domainname,
773 const u8 profile); 787 const u8 profile);
774/* Get patterned pathname. */
775const struct tomoyo_path_info *
776tomoyo_get_file_pattern(const struct tomoyo_path_info *filename);
777/* Allocate memory for "struct tomoyo_path_group". */ 788/* Allocate memory for "struct tomoyo_path_group". */
778struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); 789struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name);
779struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name); 790struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name);
@@ -807,6 +818,8 @@ char *tomoyo_realpath(const char *pathname);
807char *tomoyo_realpath_nofollow(const char *pathname); 818char *tomoyo_realpath_nofollow(const char *pathname);
808/* Same with tomoyo_realpath() except that the pathname is already solved. */ 819/* Same with tomoyo_realpath() except that the pathname is already solved. */
809char *tomoyo_realpath_from_path(struct path *path); 820char *tomoyo_realpath_from_path(struct path *path);
821/* Get patterned pathname. */
822const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename);
810 823
811/* Check memory quota. */ 824/* Check memory quota. */
812bool tomoyo_memory_ok(void *ptr); 825bool tomoyo_memory_ok(void *ptr);
@@ -878,6 +891,9 @@ extern bool tomoyo_policy_loaded;
878/* The kernel's domain. */ 891/* The kernel's domain. */
879extern struct tomoyo_domain_info tomoyo_kernel_domain; 892extern struct tomoyo_domain_info tomoyo_kernel_domain;
880 893
894extern unsigned int tomoyo_quota_for_query;
895extern unsigned int tomoyo_query_memory_size;
896
881/********** Inlined functions. **********/ 897/********** Inlined functions. **********/
882 898
883static inline int tomoyo_read_lock(void) 899static inline int tomoyo_read_lock(void)
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index afdf26128bfe..7e242d27da5a 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -678,6 +678,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
678 */ 678 */
679int tomoyo_find_next_domain(struct linux_binprm *bprm) 679int tomoyo_find_next_domain(struct linux_binprm *bprm)
680{ 680{
681 struct tomoyo_request_info r;
681 /* 682 /*
682 * This function assumes that the size of buffer returned by 683 * This function assumes that the size of buffer returned by
683 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. 684 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
@@ -693,11 +694,12 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
693 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); 694 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
694 const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); 695 const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
695 int retval = -ENOMEM; 696 int retval = -ENOMEM;
696 struct tomoyo_path_info r; /* real name */ 697 struct tomoyo_path_info rn; /* real name */
697 struct tomoyo_path_info s; /* symlink name */ 698 struct tomoyo_path_info sn; /* symlink name */
698 struct tomoyo_path_info l; /* last name */ 699 struct tomoyo_path_info ln; /* last name */
699 static bool initialized; 700 static bool initialized;
700 701
702 tomoyo_init_request_info(&r, NULL);
701 if (!tmp) 703 if (!tmp)
702 goto out; 704 goto out;
703 705
@@ -713,6 +715,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
713 initialized = true; 715 initialized = true;
714 } 716 }
715 717
718 retry:
716 /* Get tomoyo_realpath of program. */ 719 /* Get tomoyo_realpath of program. */
717 retval = -ENOENT; 720 retval = -ENOENT;
718 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ 721 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */
@@ -724,37 +727,39 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
724 if (!symlink_program_name) 727 if (!symlink_program_name)
725 goto out; 728 goto out;
726 729
727 r.name = real_program_name; 730 rn.name = real_program_name;
728 tomoyo_fill_path_info(&r); 731 tomoyo_fill_path_info(&rn);
729 s.name = symlink_program_name; 732 sn.name = symlink_program_name;
730 tomoyo_fill_path_info(&s); 733 tomoyo_fill_path_info(&sn);
731 l.name = tomoyo_get_last_name(old_domain); 734 ln.name = tomoyo_get_last_name(old_domain);
732 tomoyo_fill_path_info(&l); 735 tomoyo_fill_path_info(&ln);
733 736
734 /* Check 'alias' directive. */ 737 /* Check 'alias' directive. */
735 if (tomoyo_pathcmp(&r, &s)) { 738 if (tomoyo_pathcmp(&rn, &sn)) {
736 struct tomoyo_alias_entry *ptr; 739 struct tomoyo_alias_entry *ptr;
737 /* Is this program allowed to be called via symbolic links? */ 740 /* Is this program allowed to be called via symbolic links? */
738 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 741 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
739 if (ptr->is_deleted || 742 if (ptr->is_deleted ||
740 tomoyo_pathcmp(&r, ptr->original_name) || 743 tomoyo_pathcmp(&rn, ptr->original_name) ||
741 tomoyo_pathcmp(&s, ptr->aliased_name)) 744 tomoyo_pathcmp(&sn, ptr->aliased_name))
742 continue; 745 continue;
743 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); 746 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
744 strncpy(real_program_name, ptr->aliased_name->name, 747 strncpy(real_program_name, ptr->aliased_name->name,
745 TOMOYO_MAX_PATHNAME_LEN - 1); 748 TOMOYO_MAX_PATHNAME_LEN - 1);
746 tomoyo_fill_path_info(&r); 749 tomoyo_fill_path_info(&rn);
747 break; 750 break;
748 } 751 }
749 } 752 }
750 753
751 /* Check execute permission. */ 754 /* Check execute permission. */
752 retval = tomoyo_check_exec_perm(old_domain, &r); 755 retval = tomoyo_check_exec_perm(old_domain, &rn);
756 if (retval == TOMOYO_RETRY_REQUEST)
757 goto retry;
753 if (retval < 0) 758 if (retval < 0)
754 goto out; 759 goto out;
755 760
756 new_domain_name = tmp->buffer; 761 new_domain_name = tmp->buffer;
757 if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) { 762 if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) {
758 /* Transit to the child of tomoyo_kernel_domain domain. */ 763 /* Transit to the child of tomoyo_kernel_domain domain. */
759 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 764 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
760 TOMOYO_ROOT_NAME " " "%s", real_program_name); 765 TOMOYO_ROOT_NAME " " "%s", real_program_name);
@@ -766,7 +771,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
766 * initializers because they might start before /sbin/init. 771 * initializers because they might start before /sbin/init.
767 */ 772 */
768 domain = old_domain; 773 domain = old_domain;
769 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) { 774 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &rn, &ln)) {
770 /* Keep current domain. */ 775 /* Keep current domain. */
771 domain = old_domain; 776 domain = old_domain;
772 } else { 777 } else {
@@ -779,8 +784,14 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
779 domain = tomoyo_find_domain(new_domain_name); 784 domain = tomoyo_find_domain(new_domain_name);
780 if (domain) 785 if (domain)
781 goto done; 786 goto done;
782 if (is_enforce) 787 if (is_enforce) {
783 goto done; 788 int error = tomoyo_supervisor(&r, "# wants to create domain\n"
789 "%s\n", new_domain_name);
790 if (error == TOMOYO_RETRY_REQUEST)
791 goto retry;
792 if (error < 0)
793 goto done;
794 }
784 domain = tomoyo_find_or_assign_new_domain(new_domain_name, 795 domain = tomoyo_find_or_assign_new_domain(new_domain_name,
785 old_domain->profile); 796 old_domain->profile);
786 done: 797 done:
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index ae32cab8ec7e..c629cb4e2c66 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -478,7 +478,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
478} 478}
479 479
480/** 480/**
481 * tomoyo_get_file_pattern - Get patterned pathname. 481 * tomoyo_file_pattern - Get patterned pathname.
482 * 482 *
483 * @filename: The filename to find patterned pathname. 483 * @filename: The filename to find patterned pathname.
484 * 484 *
@@ -486,8 +486,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
486 * 486 *
487 * Caller holds tomoyo_read_lock(). 487 * Caller holds tomoyo_read_lock().
488 */ 488 */
489const struct tomoyo_path_info * 489const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename)
490tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
491{ 490{
492 struct tomoyo_pattern_entry *ptr; 491 struct tomoyo_pattern_entry *ptr;
493 const struct tomoyo_path_info *pattern = NULL; 492 const struct tomoyo_path_info *pattern = NULL;
@@ -507,7 +506,7 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
507 } 506 }
508 if (pattern) 507 if (pattern)
509 filename = pattern; 508 filename = pattern;
510 return filename; 509 return filename->name;
511} 510}
512 511
513/** 512/**
@@ -812,23 +811,25 @@ static int tomoyo_file_perm(struct tomoyo_request_info *r,
812 perm = 1 << TOMOYO_TYPE_EXECUTE; 811 perm = 1 << TOMOYO_TYPE_EXECUTE;
813 } else 812 } else
814 BUG(); 813 BUG();
815 error = tomoyo_path_acl(r, filename, perm, mode != 1); 814 do {
816 if (error && mode == 4 && !r->domain->ignore_global_allow_read 815 error = tomoyo_path_acl(r, filename, perm, mode != 1);
817 && tomoyo_is_globally_readable_file(filename)) 816 if (error && mode == 4 && !r->domain->ignore_global_allow_read
817 && tomoyo_is_globally_readable_file(filename))
818 error = 0;
819 if (!error)
820 break;
821 tomoyo_warn_log(r, "%s %s", msg, filename->name);
822 error = tomoyo_supervisor(r, "allow_%s %s\n", msg,
823 mode == 1 ? filename->name :
824 tomoyo_file_pattern(filename));
825 /*
826 * Do not retry for execute request, for alias may have
827 * changed.
828 */
829 } while (error == TOMOYO_RETRY_REQUEST && mode != 1);
830 if (r->mode != TOMOYO_CONFIG_ENFORCING)
818 error = 0; 831 error = 0;
819 if (!error) 832 return error;
820 return 0;
821 tomoyo_warn_log(r, "%s %s", msg, filename->name);
822 if (r->mode == TOMOYO_CONFIG_ENFORCING)
823 return error;
824 if (tomoyo_domain_quota_is_ok(r)) {
825 /* Don't use patterns for execute permission. */
826 const struct tomoyo_path_info *patterned_file = (mode != 1) ?
827 tomoyo_get_file_pattern(filename) : filename;
828 tomoyo_update_file_acl(mode, patterned_file->name, r->domain,
829 false);
830 }
831 return 0;
832} 833}
833 834
834/** 835/**
@@ -1123,21 +1124,21 @@ static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type,
1123static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, 1124static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
1124 const struct tomoyo_path_info *filename) 1125 const struct tomoyo_path_info *filename)
1125{ 1126{
1127 const char *msg;
1126 int error; 1128 int error;
1127 1129
1128 next: 1130 next:
1129 error = tomoyo_path_acl(r, filename, 1 << operation, 1); 1131 do {
1130 if (!error) 1132 error = tomoyo_path_acl(r, filename, 1 << operation, 1);
1131 goto ok; 1133 if (!error)
1132 tomoyo_warn_log(r, "%s %s", tomoyo_path2keyword(operation), 1134 break;
1133 filename->name); 1135 msg = tomoyo_path2keyword(operation);
1134 if (tomoyo_domain_quota_is_ok(r)) { 1136 tomoyo_warn_log(r, "%s %s", msg, filename->name);
1135 const char *name = tomoyo_get_file_pattern(filename)->name; 1137 error = tomoyo_supervisor(r, "allow_%s %s\n", msg,
1136 tomoyo_update_path_acl(operation, name, r->domain, false); 1138 tomoyo_file_pattern(filename));
1137 } 1139 } while (error == TOMOYO_RETRY_REQUEST);
1138 if (r->mode != TOMOYO_CONFIG_ENFORCING) 1140 if (r->mode != TOMOYO_CONFIG_ENFORCING)
1139 error = 0; 1141 error = 0;
1140 ok:
1141 /* 1142 /*
1142 * Since "allow_truncate" doesn't imply "allow_rewrite" permission, 1143 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
1143 * we need to check "allow_rewrite" permission if the filename is 1144 * we need to check "allow_rewrite" permission if the filename is
@@ -1267,6 +1268,7 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r,
1267 char buffer[64]; 1268 char buffer[64];
1268 int error; 1269 int error;
1269 u8 radix; 1270 u8 radix;
1271 const char *msg;
1270 1272
1271 if (!filename) 1273 if (!filename)
1272 return 0; 1274 return 0;
@@ -1286,15 +1288,16 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r,
1286 break; 1288 break;
1287 } 1289 }
1288 tomoyo_print_ulong(buffer, sizeof(buffer), number, radix); 1290 tomoyo_print_ulong(buffer, sizeof(buffer), number, radix);
1289 error = tomoyo_path_number_acl(r, type, filename, number); 1291 do {
1290 if (!error) 1292 error = tomoyo_path_number_acl(r, type, filename, number);
1291 return 0; 1293 if (!error)
1292 tomoyo_warn_log(r, "%s %s %s", tomoyo_path_number2keyword(type), 1294 break;
1293 filename->name, buffer); 1295 msg = tomoyo_path_number2keyword(type);
1294 if (tomoyo_domain_quota_is_ok(r)) 1296 tomoyo_warn_log(r, "%s %s %s", msg, filename->name, buffer);
1295 tomoyo_update_path_number_acl(type, 1297 error = tomoyo_supervisor(r, "allow_%s %s %s\n", msg,
1296 tomoyo_get_file_pattern(filename) 1298 tomoyo_file_pattern(filename),
1297 ->name, buffer, r->domain, false); 1299 buffer);
1300 } while (error == TOMOYO_RETRY_REQUEST);
1298 if (r->mode != TOMOYO_CONFIG_ENFORCING) 1301 if (r->mode != TOMOYO_CONFIG_ENFORCING)
1299 error = 0; 1302 error = 0;
1300 return error; 1303 return error;
@@ -1484,32 +1487,23 @@ static int tomoyo_path_number3_perm2(struct tomoyo_request_info *r,
1484 const unsigned int dev) 1487 const unsigned int dev)
1485{ 1488{
1486 int error; 1489 int error;
1490 const char *msg;
1487 const unsigned int major = MAJOR(dev); 1491 const unsigned int major = MAJOR(dev);
1488 const unsigned int minor = MINOR(dev); 1492 const unsigned int minor = MINOR(dev);
1489 1493
1490 error = tomoyo_path_number3_acl(r, filename, 1 << operation, mode, 1494 do {
1491 major, minor); 1495 error = tomoyo_path_number3_acl(r, filename, 1 << operation,
1492 if (!error) 1496 mode, major, minor);
1493 return 0; 1497 if (!error)
1494 tomoyo_warn_log(r, "%s %s 0%o %u %u", 1498 break;
1495 tomoyo_path_number32keyword(operation), 1499 msg = tomoyo_path_number32keyword(operation);
1496 filename->name, mode, major, minor); 1500 tomoyo_warn_log(r, "%s %s 0%o %u %u", msg, filename->name,
1497 if (tomoyo_domain_quota_is_ok(r)) { 1501 mode, major, minor);
1498 char mode_buf[64]; 1502 error = tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", msg,
1499 char major_buf[64]; 1503 tomoyo_file_pattern(filename), mode,
1500 char minor_buf[64]; 1504 major, minor);
1501 memset(mode_buf, 0, sizeof(mode_buf)); 1505 } while (error == TOMOYO_RETRY_REQUEST);
1502 memset(major_buf, 0, sizeof(major_buf)); 1506 if (r->mode != TOMOYO_CONFIG_ENFORCING)
1503 memset(minor_buf, 0, sizeof(minor_buf));
1504 snprintf(mode_buf, sizeof(mode_buf) - 1, "0%o", mode);
1505 snprintf(major_buf, sizeof(major_buf) - 1, "%u", major);
1506 snprintf(minor_buf, sizeof(minor_buf) - 1, "%u", minor);
1507 tomoyo_update_path_number3_acl(operation,
1508 tomoyo_get_file_pattern(filename)
1509 ->name, mode_buf, major_buf,
1510 minor_buf, r->domain, false);
1511 }
1512 if (r->mode != TOMOYO_CONFIG_ENFORCING)
1513 error = 0; 1507 error = 0;
1514 return error; 1508 return error;
1515} 1509}
@@ -1562,6 +1556,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1562 struct path *path2) 1556 struct path *path2)
1563{ 1557{
1564 int error = -ENOMEM; 1558 int error = -ENOMEM;
1559 const char *msg;
1565 struct tomoyo_path_info *buf1; 1560 struct tomoyo_path_info *buf1;
1566 struct tomoyo_path_info *buf2; 1561 struct tomoyo_path_info *buf2;
1567 struct tomoyo_request_info r; 1562 struct tomoyo_request_info r;
@@ -1591,17 +1586,16 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
1591 } 1586 }
1592 } 1587 }
1593 } 1588 }
1594 error = tomoyo_path2_acl(&r, operation, buf1, buf2); 1589 do {
1595 if (!error) 1590 error = tomoyo_path2_acl(&r, operation, buf1, buf2);
1596 goto out; 1591 if (!error)
1597 tomoyo_warn_log(&r, "%s %s %s", tomoyo_path22keyword(operation), 1592 break;
1598 buf1->name, buf2->name); 1593 msg = tomoyo_path22keyword(operation);
1599 if (tomoyo_domain_quota_is_ok(&r)) { 1594 tomoyo_warn_log(&r, "%s %s %s", msg, buf1->name, buf2->name);
1600 const char *name1 = tomoyo_get_file_pattern(buf1)->name; 1595 error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg,
1601 const char *name2 = tomoyo_get_file_pattern(buf2)->name; 1596 tomoyo_file_pattern(buf1),
1602 tomoyo_update_path2_acl(operation, name1, name2, r.domain, 1597 tomoyo_file_pattern(buf2));
1603 false); 1598 } while (error == TOMOYO_RETRY_REQUEST);
1604 }
1605 out: 1599 out:
1606 kfree(buf1); 1600 kfree(buf1);
1607 kfree(buf2); 1601 kfree(buf2);
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
index 507be09e93a9..aeac619f787d 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -178,19 +178,12 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name,
178 error = 0; 178 error = 0;
179 break; 179 break;
180 } 180 }
181 if (error) { 181 if (error)
182 const char *dev = tomoyo_get_file_pattern(&rdev)->name; 182 error = tomoyo_supervisor(r, TOMOYO_KEYWORD_ALLOW_MOUNT
183 const char *dir = tomoyo_get_file_pattern(&rdir)->name; 183 "%s %s %s 0x%lX\n",
184 int len = strlen(dev) + strlen(dir) + strlen(requested_type) 184 tomoyo_file_pattern(&rdev),
185 + 64; 185 tomoyo_file_pattern(&rdir),
186 char *buf = kzalloc(len, GFP_NOFS); 186 requested_type, flags);
187 if (buf) {
188 snprintf(buf, len - 1, "%s %s %s 0x%lX",
189 dev, dir, requested_type, flags);
190 tomoyo_write_mount_policy(buf, r->domain, false);
191 kfree(buf);
192 }
193 }
194 out: 187 out:
195 kfree(requested_dev_name); 188 kfree(requested_dev_name);
196 kfree(requested_dir_name); 189 kfree(requested_dir_name);
@@ -279,7 +272,10 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
279 TOMOYO_MOUNT_MAKE_SHARED_KEYWORD, 272 TOMOYO_MOUNT_MAKE_SHARED_KEYWORD,
280 flags & ~MS_SHARED); 273 flags & ~MS_SHARED);
281 else 274 else
282 error = tomoyo_mount_acl2(r, dev_name, dir, type, flags); 275 do {
276 error = tomoyo_mount_acl2(r, dev_name, dir, type,
277 flags);
278 } while (error == TOMOYO_RETRY_REQUEST);
283 if (r->mode != TOMOYO_CONFIG_ENFORCING) 279 if (r->mode != TOMOYO_CONFIG_ENFORCING)
284 error = 0; 280 error = 0;
285 return error; 281 return error;
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index d1b96f019621..3ceb1724c92d 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -333,6 +333,9 @@ void __init tomoyo_realpath_init(void)
333 panic("Can't register tomoyo_kernel_domain"); 333 panic("Can't register tomoyo_kernel_domain");
334} 334}
335 335
336unsigned int tomoyo_quota_for_query;
337unsigned int tomoyo_query_memory_size;
338
336/** 339/**
337 * tomoyo_read_memory_counter - Check for memory usage in bytes. 340 * tomoyo_read_memory_counter - Check for memory usage in bytes.
338 * 341 *
@@ -345,6 +348,7 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
345 if (!head->read_eof) { 348 if (!head->read_eof) {
346 const unsigned int policy 349 const unsigned int policy
347 = atomic_read(&tomoyo_policy_memory_size); 350 = atomic_read(&tomoyo_policy_memory_size);
351 const unsigned int query = tomoyo_query_memory_size;
348 char buffer[64]; 352 char buffer[64];
349 353
350 memset(buffer, 0, sizeof(buffer)); 354 memset(buffer, 0, sizeof(buffer));
@@ -354,8 +358,17 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
354 tomoyo_quota_for_policy); 358 tomoyo_quota_for_policy);
355 else 359 else
356 buffer[0] = '\0'; 360 buffer[0] = '\0';
357 tomoyo_io_printf(head, "Policy: %10u%s\n", policy, buffer); 361 tomoyo_io_printf(head, "Policy: %10u%s\n", policy,
358 tomoyo_io_printf(head, "Total: %10u\n", policy); 362 buffer);
363 if (tomoyo_quota_for_query)
364 snprintf(buffer, sizeof(buffer) - 1,
365 " (Quota: %10u)",
366 tomoyo_quota_for_query);
367 else
368 buffer[0] = '\0';
369 tomoyo_io_printf(head, "Query lists: %10u%s\n", query,
370 buffer);
371 tomoyo_io_printf(head, "Total: %10u\n", policy + query);
359 head->read_eof = true; 372 head->read_eof = true;
360 } 373 }
361 return 0; 374 return 0;
@@ -375,5 +388,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
375 388
376 if (sscanf(data, "Policy: %u", &size) == 1) 389 if (sscanf(data, "Policy: %u", &size) == 1)
377 tomoyo_quota_for_policy = size; 390 tomoyo_quota_for_policy = size;
391 else if (sscanf(data, "Query lists: %u", &size) == 1)
392 tomoyo_quota_for_query = size;
378 return 0; 393 return 0;
379} 394}