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,
 /* Write operation for /sys/kernel/security/tomoyo/ interface. */
 static int tomoyo_write_control(struct file *file, const char __user *buffer,
 				const int buffer_len);
+/* Check whether the domain has too many ACL entries to hold. */
+static bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
 
 /**
  * tomoyo_parse_name_union - Parse a tomoyo_name_union.
@@ -1031,7 +1033,7 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
  *
  * Caller holds tomoyo_read_lock().
  */
-bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
+static bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
 {
 	unsigned int count = 0;
 	struct tomoyo_domain_info *domain = r->domain;
@@ -1530,6 +1532,24 @@ static int tomoyo_delete_domain(char *domainname)
 	return 0;
 }
 
+/**
+ * tomoyo_write_domain_policy2 - Write domain policy.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0 on success, negative value otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
+ */
+static int tomoyo_write_domain_policy2(char *data,
+				       struct tomoyo_domain_info *domain,
+				       const bool is_delete)
+{
+	if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_MOUNT))
+                return tomoyo_write_mount_policy(data, domain, is_delete);
+	return tomoyo_write_file_policy(data, domain, is_delete);
+}
+
 /**
  * tomoyo_write_domain_policy - Write domain policy.
  *
@@ -1580,9 +1600,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
 		domain->ignore_global_allow_read = !is_delete;
 		return 0;
 	}
-        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_MOUNT))
-                return tomoyo_write_mount_policy(data, domain, is_delete);
-	return tomoyo_write_file_policy(data, domain, is_delete);
+	return tomoyo_write_domain_policy2(data, domain, is_delete);
 }
 
 /**
@@ -2185,6 +2203,357 @@ void tomoyo_load_policy(const char *filename)
 	}
 }
 
+/**
+ * tomoyo_print_header - Get header line of audit log.
+ *
+ * @r: Pointer to "struct tomoyo_request_info".
+ *
+ * Returns string representation.
+ *
+ * This function uses kmalloc(), so caller must kfree() if this function
+ * didn't return NULL.
+ */
+static char *tomoyo_print_header(struct tomoyo_request_info *r)
+{
+	static const char *tomoyo_mode_4[4] = {
+		"disabled", "learning", "permissive", "enforcing"
+	};
+	struct timeval tv;
+	const pid_t gpid = task_pid_nr(current);
+	static const int tomoyo_buffer_len = 4096;
+	char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
+	if (!buffer)
+		return NULL;
+	do_gettimeofday(&tv);
+	snprintf(buffer, tomoyo_buffer_len - 1,
+		 "#timestamp=%lu profile=%u mode=%s (global-pid=%u)"
+		 " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u"
+		 " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }",
+		 tv.tv_sec, r->profile, tomoyo_mode_4[r->mode], gpid,
+		 (pid_t) sys_getpid(), (pid_t) sys_getppid(),
+		 current_uid(), current_gid(), current_euid(),
+		 current_egid(), current_suid(), current_sgid(),
+		 current_fsuid(), current_fsgid());
+	return buffer;
+}
+
+/**
+ * tomoyo_init_audit_log - Allocate buffer for audit logs.
+ *
+ * @len: Required size.
+ * @r:   Pointer to "struct tomoyo_request_info".
+ *
+ * Returns pointer to allocated memory.
+ *
+ * The @len is updated to add the header lines' size on success.
+ *
+ * This function uses kzalloc(), so caller must kfree() if this function
+ * didn't return NULL.
+ */
+static char *tomoyo_init_audit_log(int *len, struct tomoyo_request_info *r)
+{
+	char *buf = NULL;
+	const char *header;
+	const char *domainname;
+	if (!r->domain)
+		r->domain = tomoyo_domain();
+	domainname = r->domain->domainname->name;
+	header = tomoyo_print_header(r);
+	if (!header)
+		return NULL;
+	*len += strlen(domainname) + strlen(header) + 10;
+	buf = kzalloc(*len, GFP_NOFS);
+	if (buf)
+		snprintf(buf, (*len) - 1, "%s\n%s\n", header, domainname);
+	kfree(header);
+	return buf;
+}
+
+/* Wait queue for tomoyo_query_list. */
+static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait);
+
+/* Lock for manipulating tomoyo_query_list. */
+static DEFINE_SPINLOCK(tomoyo_query_list_lock);
+
+/* Structure for query. */
+struct tomoyo_query_entry {
+	struct list_head list;
+	char *query;
+	int query_len;
+	unsigned int serial;
+	int timer;
+	int answer;
+};
+
+/* The list for "struct tomoyo_query_entry". */
+static LIST_HEAD(tomoyo_query_list);
+
+/*
+ * Number of "struct file" referring /sys/kernel/security/tomoyo/query
+ * interface.
+ */
+static atomic_t tomoyo_query_observers = ATOMIC_INIT(0);
+
+/**
+ * tomoyo_supervisor - Ask for the supervisor's decision.
+ *
+ * @r:       Pointer to "struct tomoyo_request_info".
+ * @fmt:     The printf()'s format string, followed by parameters.
+ *
+ * Returns 0 if the supervisor decided to permit the access request which
+ * violated the policy in enforcing mode, TOMOYO_RETRY_REQUEST if the
+ * supervisor decided to retry the access request which violated the policy in
+ * enforcing mode, 0 if it is not in enforcing mode, -EPERM otherwise.
+ */
+int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
+{
+	va_list args;
+	int error = -EPERM;
+	int pos;
+	int len;
+	static unsigned int tomoyo_serial;
+	struct tomoyo_query_entry *tomoyo_query_entry = NULL;
+	bool quota_exceeded = false;
+	char *header;
+	switch (r->mode) {
+		char *buffer;
+	case TOMOYO_CONFIG_LEARNING:
+		if (!tomoyo_domain_quota_is_ok(r))
+			return 0;
+		va_start(args, fmt);
+		len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;
+		va_end(args);
+		buffer = kmalloc(len, GFP_NOFS);
+		if (!buffer)
+			return 0;
+		va_start(args, fmt);
+		vsnprintf(buffer, len - 1, fmt, args);
+		va_end(args);
+		tomoyo_normalize_line(buffer);
+		tomoyo_write_domain_policy2(buffer, r->domain, false);
+		kfree(buffer);
+		/* fall through */
+	case TOMOYO_CONFIG_PERMISSIVE:
+		return 0;
+	}
+	if (!r->domain)
+		r->domain = tomoyo_domain();
+	if (!atomic_read(&tomoyo_query_observers))
+		return -EPERM;
+	va_start(args, fmt);
+	len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
+	va_end(args);
+	header = tomoyo_init_audit_log(&len, r);
+	if (!header)
+		goto out;
+	tomoyo_query_entry = kzalloc(sizeof(*tomoyo_query_entry), GFP_NOFS);
+	if (!tomoyo_query_entry)
+		goto out;
+	tomoyo_query_entry->query = kzalloc(len, GFP_NOFS);
+	if (!tomoyo_query_entry->query)
+		goto out;
+	len = ksize(tomoyo_query_entry->query);
+	INIT_LIST_HEAD(&tomoyo_query_entry->list);
+	spin_lock(&tomoyo_query_list_lock);
+	if (tomoyo_quota_for_query && tomoyo_query_memory_size + len +
+	    sizeof(*tomoyo_query_entry) >= tomoyo_quota_for_query) {
+		quota_exceeded = true;
+	} else {
+		tomoyo_query_memory_size += len + sizeof(*tomoyo_query_entry);
+		tomoyo_query_entry->serial = tomoyo_serial++;
+	}
+	spin_unlock(&tomoyo_query_list_lock);
+	if (quota_exceeded)
+		goto out;
+	pos = snprintf(tomoyo_query_entry->query, len - 1, "Q%u-%hu\n%s",
+		       tomoyo_query_entry->serial, r->retry, header);
+	kfree(header);
+	header = NULL;
+	va_start(args, fmt);
+	vsnprintf(tomoyo_query_entry->query + pos, len - 1 - pos, fmt, args);
+	tomoyo_query_entry->query_len = strlen(tomoyo_query_entry->query) + 1;
+	va_end(args);
+	spin_lock(&tomoyo_query_list_lock);
+	list_add_tail(&tomoyo_query_entry->list, &tomoyo_query_list);
+	spin_unlock(&tomoyo_query_list_lock);
+	/* Give 10 seconds for supervisor's opinion. */
+	for (tomoyo_query_entry->timer = 0;
+	     atomic_read(&tomoyo_query_observers) && tomoyo_query_entry->timer < 100;
+	     tomoyo_query_entry->timer++) {
+		wake_up(&tomoyo_query_wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(HZ / 10);
+		if (tomoyo_query_entry->answer)
+			break;
+	}
+	spin_lock(&tomoyo_query_list_lock);
+	list_del(&tomoyo_query_entry->list);
+	tomoyo_query_memory_size -= len + sizeof(*tomoyo_query_entry);
+	spin_unlock(&tomoyo_query_list_lock);
+	switch (tomoyo_query_entry->answer) {
+	case 3: /* Asked to retry by administrator. */
+		error = TOMOYO_RETRY_REQUEST;
+		r->retry++;
+		break;
+	case 1:
+		/* Granted by administrator. */
+		error = 0;
+		break;
+	case 0:
+		/* Timed out. */
+		break;
+	default:
+		/* Rejected by administrator. */
+		break;
+	}
+ out:
+	if (tomoyo_query_entry)
+		kfree(tomoyo_query_entry->query);
+	kfree(tomoyo_query_entry);
+	kfree(header);
+	return error;
+}
+
+/**
+ * tomoyo_poll_query - poll() for /sys/kernel/security/tomoyo/query.
+ *
+ * @file: Pointer to "struct file".
+ * @wait: Pointer to "poll_table".
+ *
+ * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise.
+ *
+ * Waits for access requests which violated policy in enforcing mode.
+ */
+static int tomoyo_poll_query(struct file *file, poll_table *wait)
+{
+	struct list_head *tmp;
+	bool found = false;
+	u8 i;
+	for (i = 0; i < 2; i++) {
+		spin_lock(&tomoyo_query_list_lock);
+		list_for_each(tmp, &tomoyo_query_list) {
+			struct tomoyo_query_entry *ptr
+				= list_entry(tmp, struct tomoyo_query_entry,
+					     list);
+			if (ptr->answer)
+				continue;
+			found = true;
+			break;
+		}
+		spin_unlock(&tomoyo_query_list_lock);
+		if (found)
+			return POLLIN | POLLRDNORM;
+		if (i)
+			break;
+		poll_wait(file, &tomoyo_query_wait, wait);
+	}
+	return 0;
+}
+
+/**
+ * tomoyo_read_query - Read access requests which violated policy in enforcing mode.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0.
+ */
+static int tomoyo_read_query(struct tomoyo_io_buffer *head)
+{
+	struct list_head *tmp;
+	int pos = 0;
+	int len = 0;
+	char *buf;
+	if (head->read_avail)
+		return 0;
+	if (head->read_buf) {
+		kfree(head->read_buf);
+		head->read_buf = NULL;
+		head->readbuf_size = 0;
+	}
+	spin_lock(&tomoyo_query_list_lock);
+	list_for_each(tmp, &tomoyo_query_list) {
+		struct tomoyo_query_entry *ptr
+			= list_entry(tmp, struct tomoyo_query_entry, list);
+		if (ptr->answer)
+			continue;
+		if (pos++ != head->read_step)
+			continue;
+		len = ptr->query_len;
+		break;
+	}
+	spin_unlock(&tomoyo_query_list_lock);
+	if (!len) {
+		head->read_step = 0;
+		return 0;
+	}
+	buf = kzalloc(len, GFP_NOFS);
+	if (!buf)
+		return 0;
+	pos = 0;
+	spin_lock(&tomoyo_query_list_lock);
+	list_for_each(tmp, &tomoyo_query_list) {
+		struct tomoyo_query_entry *ptr
+			= list_entry(tmp, struct tomoyo_query_entry, list);
+		if (ptr->answer)
+			continue;
+		if (pos++ != head->read_step)
+			continue;
+		/*
+		 * Some query can be skipped because tomoyo_query_list
+		 * can change, but I don't care.
+		 */
+		if (len == ptr->query_len)
+			memmove(buf, ptr->query, len);
+		break;
+	}
+	spin_unlock(&tomoyo_query_list_lock);
+	if (buf[0]) {
+		head->read_avail = len;
+		head->readbuf_size = head->read_avail;
+		head->read_buf = buf;
+		head->read_step++;
+	} else {
+		kfree(buf);
+	}
+	return 0;
+}
+
+/**
+ * tomoyo_write_answer - Write the supervisor's decision.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0 on success, -EINVAL otherwise.
+ */
+static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
+{
+	char *data = head->write_buf;
+	struct list_head *tmp;
+	unsigned int serial;
+	unsigned int answer;
+	spin_lock(&tomoyo_query_list_lock);
+	list_for_each(tmp, &tomoyo_query_list) {
+		struct tomoyo_query_entry *ptr
+			= list_entry(tmp, struct tomoyo_query_entry, list);
+		ptr->timer = 0;
+	}
+	spin_unlock(&tomoyo_query_list_lock);
+	if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
+		return -EINVAL;
+	spin_lock(&tomoyo_query_list_lock);
+	list_for_each(tmp, &tomoyo_query_list) {
+		struct tomoyo_query_entry *ptr
+			= list_entry(tmp, struct tomoyo_query_entry, list);
+		if (ptr->serial != serial)
+			continue;
+		if (!ptr->answer)
+			ptr->answer = answer;
+		break;
+	}
+	spin_unlock(&tomoyo_query_list_lock);
+	return 0;
+}
+
 /**
  * tomoyo_read_version: Get version.
  *
@@ -2239,6 +2608,7 @@ static int tomoyo_open_control(const u8 type, struct file *file)
 	if (!head)
 		return -ENOMEM;
 	mutex_init(&head->io_sem);
+	head->type = type;
 	switch (type) {
 	case TOMOYO_DOMAINPOLICY:
 		/* /sys/kernel/security/tomoyo/domain_policy */
@@ -2280,6 +2650,11 @@ static int tomoyo_open_control(const u8 type, struct file *file)
 		head->write = tomoyo_write_profile;
 		head->read = tomoyo_read_profile;
 		break;
+	case TOMOYO_QUERY: /* /sys/kernel/security/tomoyo/query */
+		head->poll = tomoyo_poll_query;
+		head->write = tomoyo_write_answer;
+		head->read = tomoyo_read_query;
+		break;
 	case TOMOYO_MANAGER:
 		/* /sys/kernel/security/tomoyo/manager */
 		head->write = tomoyo_write_manager_policy;
@@ -2292,7 +2667,9 @@ static int tomoyo_open_control(const u8 type, struct file *file)
 		 * for reading.
 		 */
 		head->read = NULL;
-	} else {
+		head->poll = NULL;
+	} else if (!head->poll) {
+		/* Don't allocate read_buf for poll() access. */
 		if (!head->readbuf_size)
 			head->readbuf_size = 4096 * 2;
 		head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS);
@@ -2316,7 +2693,8 @@ static int tomoyo_open_control(const u8 type, struct file *file)
 			return -ENOMEM;
 		}
 	}
-	head->reader_idx = tomoyo_read_lock();
+	if (type != TOMOYO_QUERY)
+		head->reader_idx = tomoyo_read_lock();
 	file->private_data = head;
 	/*
 	 * Call the handler now if the file is
@@ -2327,9 +2705,34 @@ static int tomoyo_open_control(const u8 type, struct file *file)
 	 */
 	if (type == TOMOYO_SELFDOMAIN)
 		tomoyo_read_control(file, NULL, 0);
+	/*
+	 * If the file is /sys/kernel/security/tomoyo/query , increment the
+	 * observer counter.
+	 * The obserber counter is used by tomoyo_supervisor() to see if
+	 * there is some process monitoring /sys/kernel/security/tomoyo/query.
+	 */
+	else if (type == TOMOYO_QUERY)
+		atomic_inc(&tomoyo_query_observers);
 	return 0;
 }
 
+/**
+ * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface.
+ *
+ * @file: Pointer to "struct file".
+ * @wait: Pointer to "poll_table".
+ *
+ * Waits for read readiness.
+ * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd .
+ */
+int tomoyo_poll_control(struct file *file, poll_table *wait)
+{
+	struct tomoyo_io_buffer *head = file->private_data;
+	if (!head->poll)
+		return -ENOSYS;
+	return head->poll(file, wait);
+}
+
 /**
  * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
  *
@@ -2443,7 +2846,14 @@ static int tomoyo_close_control(struct file *file)
 	struct tomoyo_io_buffer *head = file->private_data;
 	const bool is_write = !!head->write_buf;
 
-	tomoyo_read_unlock(head->reader_idx);
+	/*
+	 * If the file is /sys/kernel/security/tomoyo/query , decrement the
+	 * observer counter.
+	 */
+	if (head->type == TOMOYO_QUERY)
+		atomic_dec(&tomoyo_query_observers);
+	else
+		tomoyo_read_unlock(head->reader_idx);
 	/* Release memory used for policy I/O. */
 	kfree(head->read_buf);
 	head->read_buf = NULL;
@@ -2562,6 +2972,8 @@ static int __init tomoyo_initerface_init(void)
 		return 0;
 
 	tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
+	tomoyo_create_entry("query",            0600, tomoyo_dir,
+			    TOMOYO_QUERY);
 	tomoyo_create_entry("domain_policy",    0600, tomoyo_dir,
 			    TOMOYO_DOMAINPOLICY);
 	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 @@
 #include <linux/mount.h>
 #include <linux/list.h>
 #include <linux/cred.h>
+#include <linux/poll.h>
 struct linux_binprm;
 
 /********** Constants definitions. **********/
@@ -156,9 +157,12 @@ enum tomoyo_securityfs_interface_index {
 	TOMOYO_SELFDOMAIN,
 	TOMOYO_VERSION,
 	TOMOYO_PROFILE,
+	TOMOYO_QUERY,
 	TOMOYO_MANAGER
 };
 
+#define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */
+
 /********** Structure definitions. **********/
 
 /*
@@ -176,10 +180,14 @@ struct tomoyo_page_buffer {
  * tomoyo_request_info is a structure which is used for holding
  *
  * (1) Domain information of current process.
- * (2) Access control mode of the profile.
+ * (2) How many retries are made for this request.
+ * (3) Profile number used for this request.
+ * (4) Access control mode of the profile.
  */
 struct tomoyo_request_info {
 	struct tomoyo_domain_info *domain;
+	u8 retry;
+	u8 profile;
 	u8 mode; /* One of tomoyo_mode_index . */
 };
 
@@ -484,6 +492,7 @@ struct tomoyo_mount_acl {
 struct tomoyo_io_buffer {
 	int (*read) (struct tomoyo_io_buffer *);
 	int (*write) (struct tomoyo_io_buffer *);
+	int (*poll) (struct file *file, poll_table *wait);
 	/* Exclusive lock for this structure.   */
 	struct mutex io_sem;
 	/* Index returned by tomoyo_read_lock(). */
@@ -514,6 +523,8 @@ struct tomoyo_io_buffer {
 	int write_avail;
 	/* Size of write buffer.                */
 	int writebuf_size;
+	/* Type of this interface.              */
+	u8 type;
 };
 
 /*
@@ -659,14 +670,15 @@ struct tomoyo_policy_manager_entry {
 
 /********** Function prototypes. **********/
 
+extern asmlinkage long sys_getpid(void);
+extern asmlinkage long sys_getppid(void);
+
 /* Check whether the given name matches the given name_union. */
 bool tomoyo_compare_name_union(const struct tomoyo_path_info *name,
 			       const struct tomoyo_name_union *ptr);
 /* Check whether the given number matches the given number_union. */
 bool tomoyo_compare_number_union(const unsigned long value,
 				 const struct tomoyo_number_union *ptr);
-/* Check whether the domain has too many ACL entries to hold. */
-bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
 /* Transactional sprintf() for policy dump. */
 bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
 	__attribute__ ((format(printf, 2, 3)));
@@ -763,6 +775,8 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
 int tomoyo_write_pattern_policy(char *data, const bool is_delete);
 /* Create "path_group" entry in exception policy. */
 int tomoyo_write_path_group_policy(char *data, const bool is_delete);
+int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
+     __attribute__ ((format(printf, 2, 3)));
 /* Create "number_group" entry in exception policy. */
 int tomoyo_write_number_group_policy(char *data, const bool is_delete);
 /* Find a domain by the given name. */
@@ -771,9 +785,6 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
 struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
 							    domainname,
 							    const u8 profile);
-/* Get patterned pathname. */
-const struct tomoyo_path_info *
-tomoyo_get_file_pattern(const struct tomoyo_path_info *filename);
 /* Allocate memory for "struct tomoyo_path_group". */
 struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name);
 struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name);
@@ -807,6 +818,8 @@ char *tomoyo_realpath(const char *pathname);
 char *tomoyo_realpath_nofollow(const char *pathname);
 /* Same with tomoyo_realpath() except that the pathname is already solved. */
 char *tomoyo_realpath_from_path(struct path *path);
+/* Get patterned pathname. */
+const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename);
 
 /* Check memory quota. */
 bool tomoyo_memory_ok(void *ptr);
@@ -878,6 +891,9 @@ extern bool tomoyo_policy_loaded;
 /* The kernel's domain. */
 extern struct tomoyo_domain_info tomoyo_kernel_domain;
 
+extern unsigned int tomoyo_quota_for_query;
+extern unsigned int tomoyo_query_memory_size;
+
 /********** Inlined functions. **********/
 
 static 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 *
  */
 int tomoyo_find_next_domain(struct linux_binprm *bprm)
 {
+	struct tomoyo_request_info r;
 	/*
 	 * This function assumes that the size of buffer returned by
 	 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
@@ -693,11 +694,12 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 	const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE);
 	const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING);
 	int retval = -ENOMEM;
-	struct tomoyo_path_info r; /* real name */
-	struct tomoyo_path_info s; /* symlink name */
-	struct tomoyo_path_info l; /* last name */
+	struct tomoyo_path_info rn; /* real name */
+	struct tomoyo_path_info sn; /* symlink name */
+	struct tomoyo_path_info ln; /* last name */
 	static bool initialized;
 
+	tomoyo_init_request_info(&r, NULL);
 	if (!tmp)
 		goto out;
 
@@ -713,6 +715,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 		initialized = true;
 	}
 
+ retry:
 	/* Get tomoyo_realpath of program. */
 	retval = -ENOENT;
 	/* I hope tomoyo_realpath() won't fail with -ENOMEM. */
@@ -724,37 +727,39 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 	if (!symlink_program_name)
 		goto out;
 
-	r.name = real_program_name;
-	tomoyo_fill_path_info(&r);
-	s.name = symlink_program_name;
-	tomoyo_fill_path_info(&s);
-	l.name = tomoyo_get_last_name(old_domain);
-	tomoyo_fill_path_info(&l);
+	rn.name = real_program_name;
+	tomoyo_fill_path_info(&rn);
+	sn.name = symlink_program_name;
+	tomoyo_fill_path_info(&sn);
+	ln.name = tomoyo_get_last_name(old_domain);
+	tomoyo_fill_path_info(&ln);
 
 	/* Check 'alias' directive. */
-	if (tomoyo_pathcmp(&r, &s)) {
+	if (tomoyo_pathcmp(&rn, &sn)) {
 		struct tomoyo_alias_entry *ptr;
 		/* Is this program allowed to be called via symbolic links? */
 		list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
 			if (ptr->is_deleted ||
-			    tomoyo_pathcmp(&r, ptr->original_name) ||
-			    tomoyo_pathcmp(&s, ptr->aliased_name))
+			    tomoyo_pathcmp(&rn, ptr->original_name) ||
+			    tomoyo_pathcmp(&sn, ptr->aliased_name))
 				continue;
 			memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN);
 			strncpy(real_program_name, ptr->aliased_name->name,
 				TOMOYO_MAX_PATHNAME_LEN - 1);
-			tomoyo_fill_path_info(&r);
+			tomoyo_fill_path_info(&rn);
 			break;
 		}
 	}
 
 	/* Check execute permission. */
-	retval = tomoyo_check_exec_perm(old_domain, &r);
+	retval = tomoyo_check_exec_perm(old_domain, &rn);
+	if (retval == TOMOYO_RETRY_REQUEST)
+		goto retry;
 	if (retval < 0)
 		goto out;
 
 	new_domain_name = tmp->buffer;
-	if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) {
+	if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) {
 		/* Transit to the child of tomoyo_kernel_domain domain. */
 		snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1,
 			 TOMOYO_ROOT_NAME " " "%s", real_program_name);
@@ -766,7 +771,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 		 * initializers because they might start before /sbin/init.
 		 */
 		domain = old_domain;
-	} else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) {
+	} else if (tomoyo_is_domain_keeper(old_domain->domainname, &rn, &ln)) {
 		/* Keep current domain. */
 		domain = old_domain;
 	} else {
@@ -779,8 +784,14 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 	domain = tomoyo_find_domain(new_domain_name);
 	if (domain)
 		goto done;
-	if (is_enforce)
-		goto done;
+	if (is_enforce) {
+		int error = tomoyo_supervisor(&r, "# wants to create domain\n"
+					      "%s\n", new_domain_name);
+		if (error == TOMOYO_RETRY_REQUEST)
+			goto retry;
+		if (error < 0)
+			goto done;
+	}
 	domain = tomoyo_find_or_assign_new_domain(new_domain_name,
 						  old_domain->profile);
  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,
 }
 
 /**
- * tomoyo_get_file_pattern - Get patterned pathname.
+ * tomoyo_file_pattern - Get patterned pathname.
  *
  * @filename: The filename to find patterned pathname.
  *
@@ -486,8 +486,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
  *
  * Caller holds tomoyo_read_lock().
  */
-const struct tomoyo_path_info *
-tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
+const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename)
 {
 	struct tomoyo_pattern_entry *ptr;
 	const struct tomoyo_path_info *pattern = NULL;
@@ -507,7 +506,7 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
 	}
 	if (pattern)
 		filename = pattern;
-	return filename;
+	return filename->name;
 }
 
 /**
@@ -812,23 +811,25 @@ static int tomoyo_file_perm(struct tomoyo_request_info *r,
 		perm = 1 << TOMOYO_TYPE_EXECUTE;
 	} else
 		BUG();
-	error = tomoyo_path_acl(r, filename, perm, mode != 1);
-	if (error && mode == 4 && !r->domain->ignore_global_allow_read
-	    && tomoyo_is_globally_readable_file(filename))
+	do {
+		error = tomoyo_path_acl(r, filename, perm, mode != 1);
+		if (error && mode == 4 && !r->domain->ignore_global_allow_read
+		    && tomoyo_is_globally_readable_file(filename))
+			error = 0;
+		if (!error)
+			break;
+		tomoyo_warn_log(r, "%s %s", msg, filename->name);
+		error = tomoyo_supervisor(r, "allow_%s %s\n", msg,
+					  mode == 1 ? filename->name :
+					  tomoyo_file_pattern(filename));
+		/*
+                 * Do not retry for execute request, for alias may have
+		 * changed.
+                 */
+	} while (error == TOMOYO_RETRY_REQUEST && mode != 1);
+	if (r->mode != TOMOYO_CONFIG_ENFORCING)
 		error = 0;
-	if (!error)
-		return 0;
-	tomoyo_warn_log(r, "%s %s", msg, filename->name);
-	if (r->mode == TOMOYO_CONFIG_ENFORCING)
-		return error;
-	if (tomoyo_domain_quota_is_ok(r)) {
-		/* Don't use patterns for execute permission. */
-		const struct tomoyo_path_info *patterned_file = (mode != 1) ?
-			tomoyo_get_file_pattern(filename) : filename;
-		tomoyo_update_file_acl(mode, patterned_file->name, r->domain,
-				       false);
-	}
-	return 0;
+	return error;
 }
 
 /**
@@ -1123,21 +1124,21 @@ static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type,
 static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
 				  const struct tomoyo_path_info *filename)
 {
+	const char *msg;
 	int error;
 
  next:
-	error = tomoyo_path_acl(r, filename, 1 << operation, 1);
-	if (!error)
-		goto ok;
-	tomoyo_warn_log(r, "%s %s", tomoyo_path2keyword(operation),
-			filename->name);
-	if (tomoyo_domain_quota_is_ok(r)) {
-		const char *name = tomoyo_get_file_pattern(filename)->name;
-		tomoyo_update_path_acl(operation, name, r->domain, false);
-	}
+	do {
+		error = tomoyo_path_acl(r, filename, 1 << operation, 1);
+		if (!error)
+			break;
+		msg = tomoyo_path2keyword(operation);
+		tomoyo_warn_log(r, "%s %s", msg, filename->name);
+		error = tomoyo_supervisor(r, "allow_%s %s\n", msg,
+					  tomoyo_file_pattern(filename));
+	} while (error == TOMOYO_RETRY_REQUEST);
 	if (r->mode != TOMOYO_CONFIG_ENFORCING)
 		error = 0;
- ok:
 	/*
 	 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
 	 * 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,
 	char buffer[64];
 	int error;
 	u8 radix;
+	const char *msg;
 
 	if (!filename)
 		return 0;
@@ -1286,15 +1288,16 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r,
 		break;
 	}
 	tomoyo_print_ulong(buffer, sizeof(buffer), number, radix);
-	error = tomoyo_path_number_acl(r, type, filename, number);
-	if (!error)
-		return 0;
-	tomoyo_warn_log(r, "%s %s %s", tomoyo_path_number2keyword(type),
-			filename->name, buffer);
-	if (tomoyo_domain_quota_is_ok(r))
-		tomoyo_update_path_number_acl(type,
-					      tomoyo_get_file_pattern(filename)
-					      ->name, buffer, r->domain, false);
+	do {
+		error = tomoyo_path_number_acl(r, type, filename, number);
+		if (!error)
+			break;
+		msg = tomoyo_path_number2keyword(type);
+		tomoyo_warn_log(r, "%s %s %s", msg, filename->name, buffer);
+		error = tomoyo_supervisor(r, "allow_%s %s %s\n", msg,
+					  tomoyo_file_pattern(filename),
+					  buffer);
+	} while (error == TOMOYO_RETRY_REQUEST);
 	if (r->mode != TOMOYO_CONFIG_ENFORCING)
 		error = 0;
 	return error;
@@ -1484,32 +1487,23 @@ static int tomoyo_path_number3_perm2(struct tomoyo_request_info *r,
 				     const unsigned int dev)
 {
 	int error;
+	const char *msg;
 	const unsigned int major = MAJOR(dev);
 	const unsigned int minor = MINOR(dev);
 
-	error = tomoyo_path_number3_acl(r, filename, 1 << operation, mode,
-					major, minor);
-	if (!error)
-		return 0;
-	tomoyo_warn_log(r, "%s %s 0%o %u %u",
-			tomoyo_path_number32keyword(operation),
-			filename->name, mode, major, minor);
-	if (tomoyo_domain_quota_is_ok(r)) {
-		char mode_buf[64];
-		char major_buf[64];
-		char minor_buf[64];
-		memset(mode_buf, 0, sizeof(mode_buf));
-		memset(major_buf, 0, sizeof(major_buf));
-		memset(minor_buf, 0, sizeof(minor_buf));
-		snprintf(mode_buf, sizeof(mode_buf) - 1, "0%o", mode);
-		snprintf(major_buf, sizeof(major_buf) - 1, "%u", major);
-		snprintf(minor_buf, sizeof(minor_buf) - 1, "%u", minor);
-		tomoyo_update_path_number3_acl(operation,
-					       tomoyo_get_file_pattern(filename)
-					       ->name, mode_buf, major_buf,
-					       minor_buf, r->domain, false);
-	}
-	if (r->mode != TOMOYO_CONFIG_ENFORCING)
+	do {
+		error = tomoyo_path_number3_acl(r, filename, 1 << operation,
+						mode, major, minor);
+		if (!error)
+			break;
+		msg = tomoyo_path_number32keyword(operation);
+		tomoyo_warn_log(r, "%s %s 0%o %u %u", msg, filename->name,
+				mode, major, minor);
+		error = tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", msg,
+					  tomoyo_file_pattern(filename), mode,
+					  major, minor);
+	} while (error == TOMOYO_RETRY_REQUEST);
+        if (r->mode != TOMOYO_CONFIG_ENFORCING)
 		error = 0;
 	return error;
 }
@@ -1562,6 +1556,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
 		      struct path *path2)
 {
 	int error = -ENOMEM;
+	const char *msg;
 	struct tomoyo_path_info *buf1;
 	struct tomoyo_path_info *buf2;
 	struct tomoyo_request_info r;
@@ -1591,17 +1586,16 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
 			}
 		}
 	}
-	error = tomoyo_path2_acl(&r, operation, buf1, buf2);
-	if (!error)
-		goto out;
-	tomoyo_warn_log(&r, "%s %s %s", tomoyo_path22keyword(operation),
-			buf1->name, buf2->name);
-	if (tomoyo_domain_quota_is_ok(&r)) {
-		const char *name1 = tomoyo_get_file_pattern(buf1)->name;
-		const char *name2 = tomoyo_get_file_pattern(buf2)->name;
-		tomoyo_update_path2_acl(operation, name1, name2, r.domain,
-					false);
-	}
+	do {
+		error = tomoyo_path2_acl(&r, operation, buf1, buf2);
+		if (!error)
+			break;
+		msg = tomoyo_path22keyword(operation);
+		tomoyo_warn_log(&r, "%s %s %s", msg, buf1->name, buf2->name);
+		error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg,
+					  tomoyo_file_pattern(buf1),
+					  tomoyo_file_pattern(buf2));
+        } while (error == TOMOYO_RETRY_REQUEST);
  out:
 	kfree(buf1);
 	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,
 		error = 0;
 		break;
 	}
-	if (error) {
-		const char *dev = tomoyo_get_file_pattern(&rdev)->name;
-		const char *dir = tomoyo_get_file_pattern(&rdir)->name;
-		int len = strlen(dev) + strlen(dir) + strlen(requested_type)
-			+ 64;
-		char *buf = kzalloc(len, GFP_NOFS);
-		if (buf) {
-			snprintf(buf, len - 1, "%s %s %s 0x%lX",
-				 dev, dir, requested_type, flags);
-			tomoyo_write_mount_policy(buf, r->domain, false);
-			kfree(buf);
-		}
-	}
+	if (error)
+		error = tomoyo_supervisor(r, TOMOYO_KEYWORD_ALLOW_MOUNT
+					  "%s %s %s 0x%lX\n",
+					  tomoyo_file_pattern(&rdev),
+					  tomoyo_file_pattern(&rdir),
+					  requested_type, flags);
  out:
 	kfree(requested_dev_name);
 	kfree(requested_dir_name);
@@ -279,7 +272,10 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
 				      TOMOYO_MOUNT_MAKE_SHARED_KEYWORD,
 				      flags & ~MS_SHARED);
 	else
-		error = tomoyo_mount_acl2(r, dev_name, dir, type, flags);
+		do {
+			error = tomoyo_mount_acl2(r, dev_name, dir, type,
+						  flags);
+		} while (error == TOMOYO_RETRY_REQUEST);
 	if (r->mode != TOMOYO_CONFIG_ENFORCING)
 		error = 0;
 	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)
 		panic("Can't register tomoyo_kernel_domain");
 }
 
+unsigned int tomoyo_quota_for_query;
+unsigned int tomoyo_query_memory_size;
+
 /**
  * tomoyo_read_memory_counter - Check for memory usage in bytes.
  *
@@ -345,6 +348,7 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
 	if (!head->read_eof) {
 		const unsigned int policy
 			= atomic_read(&tomoyo_policy_memory_size);
+		const unsigned int query = tomoyo_query_memory_size;
 		char buffer[64];
 
 		memset(buffer, 0, sizeof(buffer));
@@ -354,8 +358,17 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
 				 tomoyo_quota_for_policy);
 		else
 			buffer[0] = '\0';
-		tomoyo_io_printf(head, "Policy:  %10u%s\n", policy, buffer);
-		tomoyo_io_printf(head, "Total:   %10u\n", policy);
+		tomoyo_io_printf(head, "Policy:       %10u%s\n", policy,
+				 buffer);
+		if (tomoyo_quota_for_query)
+			snprintf(buffer, sizeof(buffer) - 1,
+				 "   (Quota: %10u)",
+				 tomoyo_quota_for_query);
+		else
+			buffer[0] = '\0';
+		tomoyo_io_printf(head, "Query lists:  %10u%s\n", query,
+				 buffer);
+		tomoyo_io_printf(head, "Total:        %10u\n", policy + query);
 		head->read_eof = true;
 	}
 	return 0;
@@ -375,5 +388,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
 
 	if (sscanf(data, "Policy: %u", &size) == 1)
 		tomoyo_quota_for_policy = size;
+	else if (sscanf(data, "Query lists: %u", &size) == 1)
+		tomoyo_quota_for_query = size;
 	return 0;
 }