Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf24fb01 authored by Tetsuo Handa's avatar Tetsuo Handa Committed by James Morris
Browse files

TOMOYO: Add refcounter on string data.



Add refcounter to "struct tomoyo_name_entry" and replace tomoyo_save_name()
with tomoyo_get_name()/tomoyo_put_name() pair so that we can kfree() when
garbage collector is added.

Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Acked-by: default avatarSerge Hallyn <serue@us.ibm.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent ca0b7df3
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -12,8 +12,8 @@
#include <linux/uaccess.h>
#include <linux/security.h>
#include <linux/hardirq.h>
#include "realpath.h"
#include "common.h"
#include "realpath.h"
#include "tomoyo.h"

/* Lock for protecting policy. */
@@ -943,7 +943,9 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
		return -EINVAL;
	*cp = '\0';
	if (!strcmp(data, "COMMENT")) {
		profile->comment = tomoyo_save_name(cp + 1);
		const struct tomoyo_path_info *old_comment = profile->comment;
		profile->comment = tomoyo_get_name(cp + 1);
		tomoyo_put_name(old_comment);
		return 0;
	}
	for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
@@ -1117,7 +1119,7 @@ static int tomoyo_update_manager_entry(const char *manager,
		if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__))
			return -EINVAL;
	}
	saved_manager = tomoyo_save_name(manager);
	saved_manager = tomoyo_get_name(manager);
	if (!saved_manager)
		return -ENOMEM;
	if (!is_delete)
@@ -1132,12 +1134,14 @@ static int tomoyo_update_manager_entry(const char *manager,
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
		entry->manager = saved_manager;
		saved_manager = NULL;
		entry->is_domain = is_domain;
		list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list);
		entry = NULL;
		error = 0;
	}
	mutex_unlock(&tomoyo_policy_lock);
	tomoyo_put_name(saved_manager);
	kfree(entry);
	return error;
}
+23 −9
Original line number Diff line number Diff line
@@ -203,7 +203,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
{
	struct tomoyo_domain_initializer_entry *entry = NULL;
	struct tomoyo_domain_initializer_entry *ptr;
	const struct tomoyo_path_info *saved_program;
	const struct tomoyo_path_info *saved_program = NULL;
	const struct tomoyo_path_info *saved_domainname = NULL;
	int error = is_delete ? -ENOENT : -ENOMEM;
	bool is_last_name = false;
@@ -216,11 +216,11 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
			is_last_name = true;
		else if (!tomoyo_is_correct_domain(domainname, __func__))
			return -EINVAL;
		saved_domainname = tomoyo_save_name(domainname);
		saved_domainname = tomoyo_get_name(domainname);
		if (!saved_domainname)
			goto out;
	}
	saved_program = tomoyo_save_name(program);
	saved_program = tomoyo_get_name(program);
	if (!saved_program)
		goto out;
	if (!is_delete)
@@ -237,7 +237,9 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
		entry->domainname = saved_domainname;
		saved_domainname = NULL;
		entry->program = saved_program;
		saved_program = NULL;
		entry->is_not = is_not;
		entry->is_last_name = is_last_name;
		list_add_tail_rcu(&entry->list,
@@ -247,6 +249,8 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
	}
	mutex_unlock(&tomoyo_policy_lock);
 out:
	tomoyo_put_name(saved_domainname);
	tomoyo_put_name(saved_program);
	kfree(entry);
	return error;
}
@@ -419,7 +423,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
{
	struct tomoyo_domain_keeper_entry *entry = NULL;
	struct tomoyo_domain_keeper_entry *ptr;
	const struct tomoyo_path_info *saved_domainname;
	const struct tomoyo_path_info *saved_domainname = NULL;
	const struct tomoyo_path_info *saved_program = NULL;
	int error = is_delete ? -ENOENT : -ENOMEM;
	bool is_last_name = false;
@@ -432,11 +436,11 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
	if (program) {
		if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__))
			return -EINVAL;
		saved_program = tomoyo_save_name(program);
		saved_program = tomoyo_get_name(program);
		if (!saved_program)
			goto out;
	}
	saved_domainname = tomoyo_save_name(domainname);
	saved_domainname = tomoyo_get_name(domainname);
	if (!saved_domainname)
		goto out;
	if (!is_delete)
@@ -453,7 +457,9 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
		entry->domainname = saved_domainname;
		saved_domainname = NULL;
		entry->program = saved_program;
		saved_program = NULL;
		entry->is_not = is_not;
		entry->is_last_name = is_last_name;
		list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list);
@@ -462,6 +468,8 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
	}
	mutex_unlock(&tomoyo_policy_lock);
 out:
	tomoyo_put_name(saved_domainname);
	tomoyo_put_name(saved_program);
	kfree(entry);
	return error;
}
@@ -623,8 +631,8 @@ static int tomoyo_update_alias_entry(const char *original_name,
	if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) ||
	    !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__))
		return -EINVAL; /* No patterns allowed. */
	saved_original_name = tomoyo_save_name(original_name);
	saved_aliased_name = tomoyo_save_name(aliased_name);
	saved_original_name = tomoyo_get_name(original_name);
	saved_aliased_name = tomoyo_get_name(aliased_name);
	if (!saved_original_name || !saved_aliased_name)
		goto out;
	if (!is_delete)
@@ -640,13 +648,17 @@ static int tomoyo_update_alias_entry(const char *original_name,
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
		entry->original_name = saved_original_name;
		saved_original_name = NULL;
		entry->aliased_name = saved_aliased_name;
		saved_aliased_name = NULL;
		list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
		entry = NULL;
		error = 0;
	}
	mutex_unlock(&tomoyo_policy_lock);
 out:
	tomoyo_put_name(saved_original_name);
	tomoyo_put_name(saved_aliased_name);
	kfree(entry);
	return error;
}
@@ -721,7 +733,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *

	if (!tomoyo_is_correct_domain(domainname, __func__))
		return NULL;
	saved_domainname = tomoyo_save_name(domainname);
	saved_domainname = tomoyo_get_name(domainname);
	if (!saved_domainname)
		return NULL;
	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
@@ -736,6 +748,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
	if (!found && tomoyo_memory_ok(entry)) {
		INIT_LIST_HEAD(&entry->acl_info_list);
		entry->domainname = saved_domainname;
		saved_domainname = NULL;
		entry->profile = profile;
		list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
		domain = entry;
@@ -743,6 +756,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
		found = true;
	}
	mutex_unlock(&tomoyo_policy_lock);
	tomoyo_put_name(saved_domainname);
	kfree(entry);
	return found ? domain : NULL;
}
+18 −6
Original line number Diff line number Diff line
@@ -222,7 +222,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename,

	if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
		return -EINVAL;
	saved_filename = tomoyo_save_name(filename);
	saved_filename = tomoyo_get_name(filename);
	if (!saved_filename)
		return -ENOMEM;
	if (!is_delete)
@@ -237,11 +237,13 @@ static int tomoyo_update_globally_readable_entry(const char *filename,
	}
	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;
	}
	mutex_unlock(&tomoyo_policy_lock);
	tomoyo_put_name(saved_filename);
	kfree(entry);
	return error;
}
@@ -365,7 +367,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
	const struct tomoyo_path_info *saved_pattern;
	int error = is_delete ? -ENOENT : -ENOMEM;

	saved_pattern = tomoyo_save_name(pattern);
	saved_pattern = tomoyo_get_name(pattern);
	if (!saved_pattern)
		return error;
	if (!saved_pattern->is_patterned)
@@ -382,6 +384,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
	}
	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;
@@ -389,6 +392,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
	mutex_unlock(&tomoyo_policy_lock);
 out:
	kfree(entry);
	tomoyo_put_name(saved_pattern);
	return error;
}

@@ -518,7 +522,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern,

	if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
		return -EINVAL;
	saved_pattern = tomoyo_save_name(pattern);
	saved_pattern = tomoyo_get_name(pattern);
	if (!saved_pattern)
		return error;
	if (!is_delete)
@@ -533,11 +537,13 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern,
	}
	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;
	}
	mutex_unlock(&tomoyo_policy_lock);
	tomoyo_put_name(saved_pattern);
	kfree(entry);
	return error;
}
@@ -867,7 +873,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
		return -EINVAL;
	if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
		return -EINVAL;
	saved_filename = tomoyo_save_name(filename);
	saved_filename = tomoyo_get_name(filename);
	if (!saved_filename)
		return -ENOMEM;
	if (!is_delete)
@@ -913,12 +919,14 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
		if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
			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;
	}
	mutex_unlock(&tomoyo_policy_lock);
	kfree(entry);
	tomoyo_put_name(saved_filename);
	return error;
}

@@ -952,8 +960,8 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
	if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
	    !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
		return -EINVAL;
	saved_filename1 = tomoyo_save_name(filename1);
	saved_filename2 = tomoyo_save_name(filename2);
	saved_filename1 = tomoyo_get_name(filename1);
	saved_filename2 = tomoyo_get_name(filename2);
	if (!saved_filename1 || !saved_filename2)
		goto out;
	if (!is_delete)
@@ -979,13 +987,17 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
		entry->head.type = TOMOYO_TYPE_DOUBLE_PATH_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;
	}
	mutex_unlock(&tomoyo_policy_lock);
 out:
	tomoyo_put_name(saved_filename1);
	tomoyo_put_name(saved_filename2);
	kfree(entry);
	return error;
}
+9 −21
Original line number Diff line number Diff line
@@ -253,21 +253,6 @@ static unsigned int tomoyo_quota_for_savename;
#define TOMOYO_HASH_BITS  8
#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)

/*
 * tomoyo_name_entry is a structure which is used for linking
 * "struct tomoyo_path_info" into tomoyo_name_list .
 *
 * Since tomoyo_name_list manages a list of strings which are shared by
 * multiple processes (whereas "struct tomoyo_path_info" inside
 * "struct tomoyo_path_info_with_data" is not shared), a reference counter will
 * be added to "struct tomoyo_name_entry" rather than "struct tomoyo_path_info"
 * when TOMOYO starts supporting garbage collector.
 */
struct tomoyo_name_entry {
	struct list_head list;
	struct tomoyo_path_info entry;
};

/*
 * tomoyo_name_list is used for holding string data used by TOMOYO.
 * Since same string data is likely used for multiple times (e.g.
@@ -277,13 +262,13 @@ struct tomoyo_name_entry {
static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];

/**
 * tomoyo_save_name - Allocate permanent memory for string data.
 * 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_save_name(const char *name)
const struct tomoyo_path_info *tomoyo_get_name(const char *name)
{
	static DEFINE_MUTEX(lock);
	struct tomoyo_name_entry *ptr;
@@ -299,7 +284,9 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
	head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
	mutex_lock(&lock);
	list_for_each_entry(ptr, head, list) {
		if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
		if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
			continue;
		atomic_inc(&ptr->users);
		goto out;
	}
	ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL);
@@ -309,7 +296,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
		     > tomoyo_quota_for_savename)) {
		kfree(ptr);
		printk(KERN_WARNING "ERROR: Out of memory "
		       "for tomoyo_save_name().\n");
		       "for tomoyo_get_name().\n");
		if (!tomoyo_policy_loaded)
			panic("MAC Initialization failed.\n");
		ptr = NULL;
@@ -318,6 +305,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
	tomoyo_allocated_memory_for_savename += allocated_len;
	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:
@@ -336,7 +324,7 @@ void __init tomoyo_realpath_init(void)
	for (i = 0; i < TOMOYO_MAX_HASH; i++)
		INIT_LIST_HEAD(&tomoyo_name_list[i]);
	INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
	tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME);
	tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
	/*
	 * tomoyo_read_lock() is not needed because this function is
	 * called before the first "delete" request.
+20 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ bool tomoyo_memory_ok(void *ptr);
 * Keep the given name on the RAM.
 * The RAM is shared, so NEVER try to modify or kfree() the returned name.
 */
const struct tomoyo_path_info *tomoyo_save_name(const char *name);
const struct tomoyo_path_info *tomoyo_get_name(const char *name);

/* Check for memory usage. */
int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
@@ -54,4 +54,23 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
/* Initialize realpath related code. */
void __init tomoyo_realpath_init(void);

/*
 * tomoyo_name_entry is a structure which is used for linking
 * "struct tomoyo_path_info" into tomoyo_name_list .
 */
struct tomoyo_name_entry {
	struct list_head list;
	atomic_t users;
	struct tomoyo_path_info entry;
};

static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
{
	if (name) {
		struct tomoyo_name_entry *ptr =
			container_of(name, struct tomoyo_name_entry, entry);
		atomic_dec(&ptr->users);
	}
}

#endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */