TOMOYO: Use stack memory for pending entry.

Use stack memory for pending entry to reduce kmalloc() which will be kfree()d.

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/file.c b/security/tomoyo/file.c
index 060bbf3..6651cac8 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -164,38 +164,36 @@
 static int tomoyo_update_globally_readable_entry(const char *filename,
 						 const bool is_delete)
 {
-	struct tomoyo_globally_readable_file_entry *entry = NULL;
 	struct tomoyo_globally_readable_file_entry *ptr;
-	const struct tomoyo_path_info *saved_filename;
+	struct tomoyo_globally_readable_file_entry e = { };
 	int error = is_delete ? -ENOENT : -ENOMEM;
 
 	if (!tomoyo_is_correct_path(filename, 1, 0, -1))
 		return -EINVAL;
-	saved_filename = tomoyo_get_name(filename);
-	if (!saved_filename)
+	e.filename = tomoyo_get_name(filename);
+	if (!e.filename)
 		return -ENOMEM;
-	if (!is_delete)
-		entry = kmalloc(sizeof(*entry), GFP_NOFS);
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		goto out;
 	list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
-		if (ptr->filename != saved_filename)
+		if (ptr->filename != e.filename)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
 		break;
 	}
-	if (!is_delete && error && tomoyo_memory_ok(entry)) {
-		entry->filename = saved_filename;
-		saved_filename = NULL;
-		list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list);
-		entry = NULL;
-		error = 0;
+	if (!is_delete && error) {
+		struct tomoyo_globally_readable_file_entry *entry =
+			tomoyo_commit_ok(&e, sizeof(e));
+		if (entry) {
+			list_add_tail_rcu(&entry->list,
+					  &tomoyo_globally_readable_list);
+			error = 0;
+		}
 	}
 	mutex_unlock(&tomoyo_policy_lock);
  out:
-	tomoyo_put_name(saved_filename);
-	kfree(entry);
+	tomoyo_put_name(e.filename);
 	return error;
 }
 
@@ -313,38 +311,34 @@
 static int tomoyo_update_file_pattern_entry(const char *pattern,
 					    const bool is_delete)
 {
-	struct tomoyo_pattern_entry *entry = NULL;
 	struct tomoyo_pattern_entry *ptr;
-	const struct tomoyo_path_info *saved_pattern;
+	struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) };
 	int error = is_delete ? -ENOENT : -ENOMEM;
 
-	saved_pattern = tomoyo_get_name(pattern);
-	if (!saved_pattern)
+	if (!e.pattern)
 		return error;
-	if (!saved_pattern->is_patterned)
+	if (!e.pattern->is_patterned)
 		goto out;
-	if (!is_delete)
-		entry = kmalloc(sizeof(*entry), GFP_NOFS);
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		goto out;
 	list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
-		if (saved_pattern != ptr->pattern)
+		if (e.pattern != ptr->pattern)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
 		break;
 	}
-	if (!is_delete && error && tomoyo_memory_ok(entry)) {
-		entry->pattern = saved_pattern;
-		saved_pattern = NULL;
-		list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
-		entry = NULL;
-		error = 0;
+	if (!is_delete && error) {
+		struct tomoyo_pattern_entry *entry =
+			tomoyo_commit_ok(&e, sizeof(e));
+		if (entry) {
+			list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
+			error = 0;
+		}
 	}
 	mutex_unlock(&tomoyo_policy_lock);
  out:
-	kfree(entry);
-	tomoyo_put_name(saved_pattern);
+	tomoyo_put_name(e.pattern);
 	return error;
 }
 
@@ -467,38 +461,36 @@
 static int tomoyo_update_no_rewrite_entry(const char *pattern,
 					  const bool is_delete)
 {
-	struct tomoyo_no_rewrite_entry *entry = NULL;
 	struct tomoyo_no_rewrite_entry *ptr;
-	const struct tomoyo_path_info *saved_pattern;
+	struct tomoyo_no_rewrite_entry e = { };
 	int error = is_delete ? -ENOENT : -ENOMEM;
 
 	if (!tomoyo_is_correct_path(pattern, 0, 0, 0))
 		return -EINVAL;
-	saved_pattern = tomoyo_get_name(pattern);
-	if (!saved_pattern)
+	e.pattern = tomoyo_get_name(pattern);
+	if (!e.pattern)
 		return error;
-	if (!is_delete)
-		entry = kmalloc(sizeof(*entry), GFP_NOFS);
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		goto out;
 	list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
-		if (ptr->pattern != saved_pattern)
+		if (ptr->pattern != e.pattern)
 			continue;
 		ptr->is_deleted = is_delete;
 		error = 0;
 		break;
 	}
-	if (!is_delete && error && tomoyo_memory_ok(entry)) {
-		entry->pattern = saved_pattern;
-		saved_pattern = NULL;
-		list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list);
-		entry = NULL;
-		error = 0;
+	if (!is_delete && error) {
+		struct tomoyo_no_rewrite_entry *entry =
+			tomoyo_commit_ok(&e, sizeof(e));
+		if (entry) {
+			list_add_tail_rcu(&entry->list,
+					  &tomoyo_no_rewrite_list);
+			error = 0;
+		}
 	}
 	mutex_unlock(&tomoyo_policy_lock);
  out:
-	tomoyo_put_name(saved_pattern);
-	kfree(entry);
+	tomoyo_put_name(e.pattern);
 	return error;
 }
 
@@ -810,23 +802,26 @@
 				  struct tomoyo_domain_info *const domain,
 				  const bool is_delete)
 {
-	static const u32 rw_mask =
+	static const u32 tomoyo_rw_mask =
 		(1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
-	const struct tomoyo_path_info *saved_filename;
-	struct tomoyo_acl_info *ptr;
-	struct tomoyo_path_acl *entry = NULL;
-	int error = is_delete ? -ENOENT : -ENOMEM;
 	const u32 perm = 1 << type;
+	struct tomoyo_acl_info *ptr;
+	struct tomoyo_path_acl e = {
+		.head.type = TOMOYO_TYPE_PATH_ACL,
+		.perm_high = perm >> 16,
+		.perm = perm
+	};
+	int error = is_delete ? -ENOENT : -ENOMEM;
 
+	if (type == TOMOYO_TYPE_READ_WRITE)
+		e.perm |= tomoyo_rw_mask;
 	if (!domain)
 		return -EINVAL;
 	if (!tomoyo_is_correct_path(filename, 0, 0, 0))
 		return -EINVAL;
-	saved_filename = tomoyo_get_name(filename);
-	if (!saved_filename)
+	e.filename = tomoyo_get_name(filename);
+	if (!e.filename)
 		return -ENOMEM;
-	if (!is_delete)
-		entry = kmalloc(sizeof(*entry), GFP_NOFS);
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		goto out;
 	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
@@ -834,48 +829,42 @@
 			container_of(ptr, struct tomoyo_path_acl, head);
 		if (ptr->type != TOMOYO_TYPE_PATH_ACL)
 			continue;
-		if (acl->filename != saved_filename)
+		if (acl->filename != e.filename)
 			continue;
 		if (is_delete) {
 			if (perm <= 0xFFFF)
 				acl->perm &= ~perm;
 			else
 				acl->perm_high &= ~(perm >> 16);
-			if ((acl->perm & rw_mask) != rw_mask)
+			if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask)
 				acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
 			else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
-				acl->perm &= ~rw_mask;
+				acl->perm &= ~tomoyo_rw_mask;
 		} else {
 			if (perm <= 0xFFFF)
 				acl->perm |= perm;
 			else
 				acl->perm_high |= (perm >> 16);
-			if ((acl->perm & rw_mask) == rw_mask)
+			if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask)
 				acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
 			else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
-				acl->perm |= rw_mask;
+				acl->perm |= tomoyo_rw_mask;
 		}
 		error = 0;
 		break;
 	}
-	if (!is_delete && error && tomoyo_memory_ok(entry)) {
-		entry->head.type = TOMOYO_TYPE_PATH_ACL;
-		if (perm <= 0xFFFF)
-			entry->perm = perm;
-		else
-			entry->perm_high = (perm >> 16);
-		if (perm == (1 << TOMOYO_TYPE_READ_WRITE))
-			entry->perm |= rw_mask;
-		entry->filename = saved_filename;
-		saved_filename = NULL;
-		list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
-		entry = NULL;
-		error = 0;
+	if (!is_delete && error) {
+		struct tomoyo_path_acl *entry =
+			tomoyo_commit_ok(&e, sizeof(e));
+		if (entry) {
+			list_add_tail_rcu(&entry->head.list,
+					  &domain->acl_info_list);
+			error = 0;
+		}
 	}
 	mutex_unlock(&tomoyo_policy_lock);
  out:
-	kfree(entry);
-	tomoyo_put_name(saved_filename);
+	tomoyo_put_name(e.filename);
 	return error;
 }
 
@@ -897,24 +886,23 @@
 				   struct tomoyo_domain_info *const domain,
 				   const bool is_delete)
 {
-	const struct tomoyo_path_info *saved_filename1;
-	const struct tomoyo_path_info *saved_filename2;
-	struct tomoyo_acl_info *ptr;
-	struct tomoyo_path2_acl *entry = NULL;
-	int error = is_delete ? -ENOENT : -ENOMEM;
 	const u8 perm = 1 << type;
+	struct tomoyo_path2_acl e = {
+		.head.type = TOMOYO_TYPE_PATH2_ACL,
+		.perm = perm
+	};
+	struct tomoyo_acl_info *ptr;
+	int error = is_delete ? -ENOENT : -ENOMEM;
 
 	if (!domain)
 		return -EINVAL;
 	if (!tomoyo_is_correct_path(filename1, 0, 0, 0) ||
 	    !tomoyo_is_correct_path(filename2, 0, 0, 0))
 		return -EINVAL;
-	saved_filename1 = tomoyo_get_name(filename1);
-	saved_filename2 = tomoyo_get_name(filename2);
-	if (!saved_filename1 || !saved_filename2)
+	e.filename1 = tomoyo_get_name(filename1);
+	e.filename2 = tomoyo_get_name(filename2);
+	if (!e.filename1 || !e.filename2)
 		goto out;
-	if (!is_delete)
-		entry = kmalloc(sizeof(*entry), GFP_NOFS);
 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
 		goto out;
 	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
@@ -922,8 +910,8 @@
 			container_of(ptr, struct tomoyo_path2_acl, head);
 		if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
 			continue;
-		if (acl->filename1 != saved_filename1 ||
-		    acl->filename2 != saved_filename2)
+		if (acl->filename1 != e.filename1 ||
+		    acl->filename2 != e.filename2)
 			continue;
 		if (is_delete)
 			acl->perm &= ~perm;
@@ -932,22 +920,19 @@
 		error = 0;
 		break;
 	}
-	if (!is_delete && error && tomoyo_memory_ok(entry)) {
-		entry->head.type = TOMOYO_TYPE_PATH2_ACL;
-		entry->perm = perm;
-		entry->filename1 = saved_filename1;
-		saved_filename1 = NULL;
-		entry->filename2 = saved_filename2;
-		saved_filename2 = NULL;
-		list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
-		entry = NULL;
-		error = 0;
+	if (!is_delete && error) {
+		struct tomoyo_path2_acl *entry =
+			tomoyo_commit_ok(&e, sizeof(e));
+		if (entry) {
+			list_add_tail_rcu(&entry->head.list,
+					  &domain->acl_info_list);
+			error = 0;
+		}
 	}
 	mutex_unlock(&tomoyo_policy_lock);
  out:
-	tomoyo_put_name(saved_filename1);
-	tomoyo_put_name(saved_filename2);
-	kfree(entry);
+	tomoyo_put_name(e.filename1);
+	tomoyo_put_name(e.filename2);
 	return error;
 }