TOMOYO: Split files into some pieces.

security/tomoyo/common.c became too large to read.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c
new file mode 100644
index 0000000..8fb73ff
--- /dev/null
+++ b/security/tomoyo/memory.c
@@ -0,0 +1,236 @@
+/*
+ * security/tomoyo/memory.c
+ *
+ * Memory management functions for TOMOYO.
+ *
+ * Copyright (C) 2005-2010  NTT DATA CORPORATION
+ */
+
+#include <linux/hash.h>
+#include <linux/slab.h>
+#include "common.h"
+
+/**
+ * tomoyo_warn_oom - Print out of memory warning message.
+ *
+ * @function: Function's name.
+ */
+void tomoyo_warn_oom(const char *function)
+{
+	/* Reduce error messages. */
+	static pid_t tomoyo_last_pid;
+	const pid_t pid = current->pid;
+	if (tomoyo_last_pid != pid) {
+		printk(KERN_WARNING "ERROR: Out of memory at %s.\n",
+		       function);
+		tomoyo_last_pid = pid;
+	}
+	if (!tomoyo_policy_loaded)
+		panic("MAC Initialization failed.\n");
+}
+
+/* Memory allocated for policy. */
+static atomic_t tomoyo_policy_memory_size;
+/* Quota for holding policy. */
+static unsigned int tomoyo_quota_for_policy;
+
+/**
+ * tomoyo_memory_ok - Check memory quota.
+ *
+ * @ptr: Pointer to allocated memory.
+ *
+ * Returns true on success, false otherwise.
+ *
+ * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
+ */
+bool tomoyo_memory_ok(void *ptr)
+{
+	size_t s = ptr ? ksize(ptr) : 0;
+	atomic_add(s, &tomoyo_policy_memory_size);
+	if (ptr && (!tomoyo_quota_for_policy ||
+		    atomic_read(&tomoyo_policy_memory_size)
+		    <= tomoyo_quota_for_policy)) {
+		memset(ptr, 0, s);
+		return true;
+	}
+	atomic_sub(s, &tomoyo_policy_memory_size);
+	tomoyo_warn_oom(__func__);
+	return false;
+}
+
+/**
+ * tomoyo_commit_ok - Check memory quota.
+ *
+ * @data:   Data to copy from.
+ * @size:   Size in byte.
+ *
+ * Returns pointer to allocated memory on success, NULL otherwise.
+ * @data is zero-cleared on success.
+ */
+void *tomoyo_commit_ok(void *data, const unsigned int size)
+{
+	void *ptr = kzalloc(size, GFP_NOFS);
+	if (tomoyo_memory_ok(ptr)) {
+		memmove(ptr, data, size);
+		memset(data, 0, size);
+		return ptr;
+	}
+	return NULL;
+}
+
+/**
+ * tomoyo_memory_free - Free memory for elements.
+ *
+ * @ptr:  Pointer to allocated memory.
+ */
+void tomoyo_memory_free(void *ptr)
+{
+	atomic_sub(ksize(ptr), &tomoyo_policy_memory_size);
+	kfree(ptr);
+}
+
+/*
+ * tomoyo_name_list is used for holding string data used by TOMOYO.
+ * Since same string data is likely used for multiple times (e.g.
+ * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
+ * "const struct tomoyo_path_info *".
+ */
+struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
+
+/**
+ * tomoyo_get_name - Allocate permanent memory for string data.
+ *
+ * @name: The string to store into the permernent memory.
+ *
+ * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
+ */
+const struct tomoyo_path_info *tomoyo_get_name(const char *name)
+{
+	struct tomoyo_name_entry *ptr;
+	unsigned int hash;
+	int len;
+	int allocated_len;
+	struct list_head *head;
+
+	if (!name)
+		return NULL;
+	len = strlen(name) + 1;
+	hash = full_name_hash((const unsigned char *) name, len - 1);
+	head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
+	if (mutex_lock_interruptible(&tomoyo_policy_lock))
+		return NULL;
+	list_for_each_entry(ptr, head, list) {
+		if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
+			continue;
+		atomic_inc(&ptr->users);
+		goto out;
+	}
+	ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
+	allocated_len = ptr ? ksize(ptr) : 0;
+	if (!ptr || (tomoyo_quota_for_policy &&
+		     atomic_read(&tomoyo_policy_memory_size) + allocated_len
+		     > tomoyo_quota_for_policy)) {
+		kfree(ptr);
+		ptr = NULL;
+		tomoyo_warn_oom(__func__);
+		goto out;
+	}
+	atomic_add(allocated_len, &tomoyo_policy_memory_size);
+	ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
+	memmove((char *) ptr->entry.name, name, len);
+	atomic_set(&ptr->users, 1);
+	tomoyo_fill_path_info(&ptr->entry);
+	list_add_tail(&ptr->list, head);
+ out:
+	mutex_unlock(&tomoyo_policy_lock);
+	return ptr ? &ptr->entry : NULL;
+}
+
+/**
+ * tomoyo_mm_init - Initialize mm related code.
+ */
+void __init tomoyo_mm_init(void)
+{
+	int idx;
+
+	BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
+	for (idx = 0; idx < TOMOYO_MAX_HASH; idx++)
+		INIT_LIST_HEAD(&tomoyo_name_list[idx]);
+	INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
+	tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
+	list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
+	idx = tomoyo_read_lock();
+	if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
+		panic("Can't register tomoyo_kernel_domain");
+	{
+		/* Load built-in policy. */
+		tomoyo_write_domain_initializer_policy("/sbin/hotplug",
+						       false, false);
+		tomoyo_write_domain_initializer_policy("/sbin/modprobe",
+						       false, false);
+	}
+	tomoyo_read_unlock(idx);
+}
+
+
+/* Memory allocated for query lists. */
+unsigned int tomoyo_query_memory_size;
+/* Quota for holding query lists. */
+unsigned int tomoyo_quota_for_query;
+
+/**
+ * tomoyo_read_memory_counter - Check for memory usage in bytes.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns memory usage.
+ */
+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));
+		if (tomoyo_quota_for_policy)
+			snprintf(buffer, sizeof(buffer) - 1,
+				 "   (Quota: %10u)",
+				 tomoyo_quota_for_policy);
+		else
+			buffer[0] = '\0';
+		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;
+}
+
+/**
+ * tomoyo_write_memory_quota - Set memory quota.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Returns 0.
+ */
+int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
+{
+	char *data = head->write_buf;
+	unsigned int size;
+
+	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;
+}