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

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

TOMOYO: Use stack memory for pending entry.



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

Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 83c36ccf
Loading
Loading
Loading
Loading
+14 −18
Original line number Original line Diff line number Diff line
@@ -1071,46 +1071,42 @@ LIST_HEAD(tomoyo_policy_manager_list);
static int tomoyo_update_manager_entry(const char *manager,
static int tomoyo_update_manager_entry(const char *manager,
				       const bool is_delete)
				       const bool is_delete)
{
{
	struct tomoyo_policy_manager_entry *entry = NULL;
	struct tomoyo_policy_manager_entry *ptr;
	struct tomoyo_policy_manager_entry *ptr;
	const struct tomoyo_path_info *saved_manager;
	struct tomoyo_policy_manager_entry e = { };
	int error = is_delete ? -ENOENT : -ENOMEM;
	int error = is_delete ? -ENOENT : -ENOMEM;
	bool is_domain = false;


	if (tomoyo_is_domain_def(manager)) {
	if (tomoyo_is_domain_def(manager)) {
		if (!tomoyo_is_correct_domain(manager))
		if (!tomoyo_is_correct_domain(manager))
			return -EINVAL;
			return -EINVAL;
		is_domain = true;
		e.is_domain = true;
	} else {
	} else {
		if (!tomoyo_is_correct_path(manager, 1, -1, -1))
		if (!tomoyo_is_correct_path(manager, 1, -1, -1))
			return -EINVAL;
			return -EINVAL;
	}
	}
	saved_manager = tomoyo_get_name(manager);
	e.manager = tomoyo_get_name(manager);
	if (!saved_manager)
	if (!e.manager)
		return -ENOMEM;
		return -ENOMEM;
	if (!is_delete)
		entry = kmalloc(sizeof(*entry), GFP_NOFS);
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
		goto out;
		goto out;
	list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
		if (ptr->manager != saved_manager)
		if (ptr->manager != e.manager)
			continue;
			continue;
		ptr->is_deleted = is_delete;
		ptr->is_deleted = is_delete;
		error = 0;
		error = 0;
		break;
		break;
	}
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
	if (!is_delete && error) {
		entry->manager = saved_manager;
		struct tomoyo_policy_manager_entry *entry =
		saved_manager = NULL;
			tomoyo_commit_ok(&e, sizeof(e));
		entry->is_domain = is_domain;
		if (entry) {
		list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list);
			list_add_tail_rcu(&entry->list,
		entry = NULL;
					  &tomoyo_policy_manager_list);
			error = 0;
			error = 0;
		}
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
	mutex_unlock(&tomoyo_policy_lock);
 out:
 out:
	tomoyo_put_name(saved_manager);
	tomoyo_put_name(e.manager);
	kfree(entry);
	return error;
	return error;
}
}


+26 −0
Original line number Original line Diff line number Diff line
@@ -616,6 +616,7 @@ char *tomoyo_realpath_from_path(struct path *path);


/* Check memory quota. */
/* Check memory quota. */
bool tomoyo_memory_ok(void *ptr);
bool tomoyo_memory_ok(void *ptr);
void *tomoyo_commit_ok(void *data, const unsigned int size);


/*
/*
 * Keep the given name on the RAM.
 * Keep the given name on the RAM.
@@ -735,6 +736,31 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
	return task_cred_xxx(task, security);
	return task_cred_xxx(task, security);
}
}


static inline bool tomoyo_is_same_domain_initializer_entry
(const struct tomoyo_domain_initializer_entry *p1,
 const struct tomoyo_domain_initializer_entry *p2)
{
	return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
		&& p1->domainname == p2->domainname
		&& p1->program == p2->program;
}

static inline bool tomoyo_is_same_domain_keeper_entry
(const struct tomoyo_domain_keeper_entry *p1,
 const struct tomoyo_domain_keeper_entry *p2)
{
	return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
		&& p1->domainname == p2->domainname
		&& p1->program == p2->program;
}

static inline bool tomoyo_is_same_alias_entry
(const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2)
{
	return p1->original_name == p2->original_name &&
		p1->aliased_name == p2->aliased_name;
}

/**
/**
 * list_for_each_cookie - iterate over a list with cookie.
 * list_for_each_cookie - iterate over a list with cookie.
 * @pos:        the &struct list_head to use as a loop cursor.
 * @pos:        the &struct list_head to use as a loop cursor.
+48 −76
Original line number Original line Diff line number Diff line
@@ -130,58 +130,47 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
						  const bool is_not,
						  const bool is_not,
						  const bool is_delete)
						  const bool is_delete)
{
{
	struct tomoyo_domain_initializer_entry *entry = NULL;
	struct tomoyo_domain_initializer_entry *ptr;
	struct tomoyo_domain_initializer_entry *ptr;
	const struct tomoyo_path_info *saved_program = NULL;
	struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
	const struct tomoyo_path_info *saved_domainname = NULL;
	int error = is_delete ? -ENOENT : -ENOMEM;
	int error = is_delete ? -ENOENT : -ENOMEM;
	bool is_last_name = false;


	if (!tomoyo_is_correct_path(program, 1, -1, -1))
	if (!tomoyo_is_correct_path(program, 1, -1, -1))
		return -EINVAL; /* No patterns allowed. */
		return -EINVAL; /* No patterns allowed. */
	if (domainname) {
	if (domainname) {
		if (!tomoyo_is_domain_def(domainname) &&
		if (!tomoyo_is_domain_def(domainname) &&
		    tomoyo_is_correct_path(domainname, 1, -1, -1))
		    tomoyo_is_correct_path(domainname, 1, -1, -1))
			is_last_name = true;
			e.is_last_name = true;
		else if (!tomoyo_is_correct_domain(domainname))
		else if (!tomoyo_is_correct_domain(domainname))
			return -EINVAL;
			return -EINVAL;
		saved_domainname = tomoyo_get_name(domainname);
		e.domainname = tomoyo_get_name(domainname);
		if (!saved_domainname)
		if (!e.domainname)
			goto out;
			goto out;
	}
	}
	saved_program = tomoyo_get_name(program);
	e.program = tomoyo_get_name(program);
	if (!saved_program)
	if (!e.program)
		goto out;
		goto out;
	if (!is_delete)
		entry = kmalloc(sizeof(*entry), GFP_NOFS);
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
		goto out;
		goto out;
	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
		if (ptr->is_not != is_not ||
		if (!tomoyo_is_same_domain_initializer_entry(ptr, &e))
		    ptr->domainname != saved_domainname ||
		    ptr->program != saved_program)
			continue;
			continue;
		ptr->is_deleted = is_delete;
		ptr->is_deleted = is_delete;
		error = 0;
		error = 0;
		break;
		break;
	}
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
	if (!is_delete && error) {
		entry->domainname = saved_domainname;
		struct tomoyo_domain_initializer_entry *entry =
		saved_domainname = NULL;
			tomoyo_commit_ok(&e, sizeof(e));
		entry->program = saved_program;
		if (entry) {
		saved_program = NULL;
		entry->is_not = is_not;
		entry->is_last_name = is_last_name;
			list_add_tail_rcu(&entry->list,
			list_add_tail_rcu(&entry->list,
					  &tomoyo_domain_initializer_list);
					  &tomoyo_domain_initializer_list);
		entry = NULL;
			error = 0;
			error = 0;
		}
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
	mutex_unlock(&tomoyo_policy_lock);
 out:
 out:
	tomoyo_put_name(saved_domainname);
	tomoyo_put_name(e.domainname);
	tomoyo_put_name(saved_program);
	tomoyo_put_name(e.program);
	kfree(entry);
	return error;
	return error;
}
}


@@ -351,57 +340,47 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
					     const bool is_not,
					     const bool is_not,
					     const bool is_delete)
					     const bool is_delete)
{
{
	struct tomoyo_domain_keeper_entry *entry = NULL;
	struct tomoyo_domain_keeper_entry *ptr;
	struct tomoyo_domain_keeper_entry *ptr;
	const struct tomoyo_path_info *saved_domainname = NULL;
	struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
	const struct tomoyo_path_info *saved_program = NULL;
	int error = is_delete ? -ENOENT : -ENOMEM;
	int error = is_delete ? -ENOENT : -ENOMEM;
	bool is_last_name = false;


	if (!tomoyo_is_domain_def(domainname) &&
	if (!tomoyo_is_domain_def(domainname) &&
	    tomoyo_is_correct_path(domainname, 1, -1, -1))
	    tomoyo_is_correct_path(domainname, 1, -1, -1))
		is_last_name = true;
		e.is_last_name = true;
	else if (!tomoyo_is_correct_domain(domainname))
	else if (!tomoyo_is_correct_domain(domainname))
		return -EINVAL;
		return -EINVAL;
	if (program) {
	if (program) {
		if (!tomoyo_is_correct_path(program, 1, -1, -1))
		if (!tomoyo_is_correct_path(program, 1, -1, -1))
			return -EINVAL;
			return -EINVAL;
		saved_program = tomoyo_get_name(program);
		e.program = tomoyo_get_name(program);
		if (!saved_program)
		if (!e.program)
			goto out;
			goto out;
	}
	}
	saved_domainname = tomoyo_get_name(domainname);
	e.domainname = tomoyo_get_name(domainname);
	if (!saved_domainname)
	if (!e.domainname)
		goto out;
		goto out;
	if (!is_delete)
		entry = kmalloc(sizeof(*entry), GFP_NOFS);
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
		goto out;
		goto out;
	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
		if (ptr->is_not != is_not ||
		if (!tomoyo_is_same_domain_keeper_entry(ptr, &e))
		    ptr->domainname != saved_domainname ||
		    ptr->program != saved_program)
			continue;
			continue;
		ptr->is_deleted = is_delete;
		ptr->is_deleted = is_delete;
		error = 0;
		error = 0;
		break;
		break;
	}
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
	if (!is_delete && error) {
		entry->domainname = saved_domainname;
		struct tomoyo_domain_keeper_entry *entry =
		saved_domainname = NULL;
			tomoyo_commit_ok(&e, sizeof(e));
		entry->program = saved_program;
		if (entry) {
		saved_program = NULL;
			list_add_tail_rcu(&entry->list,
		entry->is_not = is_not;
					  &tomoyo_domain_keeper_list);
		entry->is_last_name = is_last_name;
		list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list);
		entry = NULL;
			error = 0;
			error = 0;
		}
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
	mutex_unlock(&tomoyo_policy_lock);
 out:
 out:
	tomoyo_put_name(saved_domainname);
	tomoyo_put_name(e.domainname);
	tomoyo_put_name(saved_program);
	tomoyo_put_name(e.program);
	kfree(entry);
	return error;
	return error;
}
}


@@ -553,45 +532,38 @@ static int tomoyo_update_alias_entry(const char *original_name,
				     const char *aliased_name,
				     const char *aliased_name,
				     const bool is_delete)
				     const bool is_delete)
{
{
	struct tomoyo_alias_entry *entry = NULL;
	struct tomoyo_alias_entry *ptr;
	struct tomoyo_alias_entry *ptr;
	const struct tomoyo_path_info *saved_original_name;
	struct tomoyo_alias_entry e = { };
	const struct tomoyo_path_info *saved_aliased_name;
	int error = is_delete ? -ENOENT : -ENOMEM;
	int error = is_delete ? -ENOENT : -ENOMEM;


	if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
	if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
	    !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
	    !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
		return -EINVAL; /* No patterns allowed. */
		return -EINVAL; /* No patterns allowed. */
	saved_original_name = tomoyo_get_name(original_name);
	e.original_name = tomoyo_get_name(original_name);
	saved_aliased_name = tomoyo_get_name(aliased_name);
	e.aliased_name = tomoyo_get_name(aliased_name);
	if (!saved_original_name || !saved_aliased_name)
	if (!e.original_name || !e.aliased_name)
		goto out;
		goto out;
	if (!is_delete)
		entry = kmalloc(sizeof(*entry), GFP_NOFS);
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
		goto out;
		goto out;
	list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
		if (ptr->original_name != saved_original_name ||
		if (!tomoyo_is_same_alias_entry(ptr, &e))
		    ptr->aliased_name != saved_aliased_name)
			continue;
			continue;
		ptr->is_deleted = is_delete;
		ptr->is_deleted = is_delete;
		error = 0;
		error = 0;
		break;
		break;
	}
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
	if (!is_delete && error) {
		entry->original_name = saved_original_name;
		struct tomoyo_alias_entry *entry =
		saved_original_name = NULL;
			tomoyo_commit_ok(&e, sizeof(e));
		entry->aliased_name = saved_aliased_name;
		if (entry) {
		saved_aliased_name = NULL;
			list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
			list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
		entry = NULL;
			error = 0;
			error = 0;
		}
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
	mutex_unlock(&tomoyo_policy_lock);
 out:
 out:
	tomoyo_put_name(saved_original_name);
	tomoyo_put_name(e.original_name);
	tomoyo_put_name(saved_aliased_name);
	tomoyo_put_name(e.aliased_name);
	kfree(entry);
	return error;
	return error;
}
}


+83 −98
Original line number Original line Diff line number Diff line
@@ -164,38 +164,36 @@ LIST_HEAD(tomoyo_globally_readable_list);
static int tomoyo_update_globally_readable_entry(const char *filename,
static int tomoyo_update_globally_readable_entry(const char *filename,
						 const bool is_delete)
						 const bool is_delete)
{
{
	struct tomoyo_globally_readable_file_entry *entry = NULL;
	struct tomoyo_globally_readable_file_entry *ptr;
	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;
	int error = is_delete ? -ENOENT : -ENOMEM;


	if (!tomoyo_is_correct_path(filename, 1, 0, -1))
	if (!tomoyo_is_correct_path(filename, 1, 0, -1))
		return -EINVAL;
		return -EINVAL;
	saved_filename = tomoyo_get_name(filename);
	e.filename = tomoyo_get_name(filename);
	if (!saved_filename)
	if (!e.filename)
		return -ENOMEM;
		return -ENOMEM;
	if (!is_delete)
		entry = kmalloc(sizeof(*entry), GFP_NOFS);
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
		goto out;
		goto out;
	list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
		if (ptr->filename != saved_filename)
		if (ptr->filename != e.filename)
			continue;
			continue;
		ptr->is_deleted = is_delete;
		ptr->is_deleted = is_delete;
		error = 0;
		error = 0;
		break;
		break;
	}
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
	if (!is_delete && error) {
		entry->filename = saved_filename;
		struct tomoyo_globally_readable_file_entry *entry =
		saved_filename = NULL;
			tomoyo_commit_ok(&e, sizeof(e));
		list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list);
		if (entry) {
		entry = NULL;
			list_add_tail_rcu(&entry->list,
					  &tomoyo_globally_readable_list);
			error = 0;
			error = 0;
		}
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
	mutex_unlock(&tomoyo_policy_lock);
 out:
 out:
	tomoyo_put_name(saved_filename);
	tomoyo_put_name(e.filename);
	kfree(entry);
	return error;
	return error;
}
}


@@ -313,38 +311,34 @@ LIST_HEAD(tomoyo_pattern_list);
static int tomoyo_update_file_pattern_entry(const char *pattern,
static int tomoyo_update_file_pattern_entry(const char *pattern,
					    const bool is_delete)
					    const bool is_delete)
{
{
	struct tomoyo_pattern_entry *entry = NULL;
	struct tomoyo_pattern_entry *ptr;
	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;
	int error = is_delete ? -ENOENT : -ENOMEM;


	saved_pattern = tomoyo_get_name(pattern);
	if (!e.pattern)
	if (!saved_pattern)
		return error;
		return error;
	if (!saved_pattern->is_patterned)
	if (!e.pattern->is_patterned)
		goto out;
		goto out;
	if (!is_delete)
		entry = kmalloc(sizeof(*entry), GFP_NOFS);
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
		goto out;
		goto out;
	list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
		if (saved_pattern != ptr->pattern)
		if (e.pattern != ptr->pattern)
			continue;
			continue;
		ptr->is_deleted = is_delete;
		ptr->is_deleted = is_delete;
		error = 0;
		error = 0;
		break;
		break;
	}
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
	if (!is_delete && error) {
		entry->pattern = saved_pattern;
		struct tomoyo_pattern_entry *entry =
		saved_pattern = NULL;
			tomoyo_commit_ok(&e, sizeof(e));
		if (entry) {
			list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
			list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
		entry = NULL;
			error = 0;
			error = 0;
		}
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
	mutex_unlock(&tomoyo_policy_lock);
 out:
 out:
	kfree(entry);
	tomoyo_put_name(e.pattern);
	tomoyo_put_name(saved_pattern);
	return error;
	return error;
}
}


@@ -467,38 +461,36 @@ LIST_HEAD(tomoyo_no_rewrite_list);
static int tomoyo_update_no_rewrite_entry(const char *pattern,
static int tomoyo_update_no_rewrite_entry(const char *pattern,
					  const bool is_delete)
					  const bool is_delete)
{
{
	struct tomoyo_no_rewrite_entry *entry = NULL;
	struct tomoyo_no_rewrite_entry *ptr;
	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;
	int error = is_delete ? -ENOENT : -ENOMEM;


	if (!tomoyo_is_correct_path(pattern, 0, 0, 0))
	if (!tomoyo_is_correct_path(pattern, 0, 0, 0))
		return -EINVAL;
		return -EINVAL;
	saved_pattern = tomoyo_get_name(pattern);
	e.pattern = tomoyo_get_name(pattern);
	if (!saved_pattern)
	if (!e.pattern)
		return error;
		return error;
	if (!is_delete)
		entry = kmalloc(sizeof(*entry), GFP_NOFS);
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
		goto out;
		goto out;
	list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
		if (ptr->pattern != saved_pattern)
		if (ptr->pattern != e.pattern)
			continue;
			continue;
		ptr->is_deleted = is_delete;
		ptr->is_deleted = is_delete;
		error = 0;
		error = 0;
		break;
		break;
	}
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
	if (!is_delete && error) {
		entry->pattern = saved_pattern;
		struct tomoyo_no_rewrite_entry *entry =
		saved_pattern = NULL;
			tomoyo_commit_ok(&e, sizeof(e));
		list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list);
		if (entry) {
		entry = NULL;
			list_add_tail_rcu(&entry->list,
					  &tomoyo_no_rewrite_list);
			error = 0;
			error = 0;
		}
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
	mutex_unlock(&tomoyo_policy_lock);
 out:
 out:
	tomoyo_put_name(saved_pattern);
	tomoyo_put_name(e.pattern);
	kfree(entry);
	return error;
	return error;
}
}


@@ -810,23 +802,26 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
				  struct tomoyo_domain_info *const domain,
				  struct tomoyo_domain_info *const domain,
				  const bool is_delete)
				  const bool is_delete)
{
{
	static const u32 rw_mask =
	static const u32 tomoyo_rw_mask =
		(1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
		(1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
	const struct tomoyo_path_info *saved_filename;
	const u32 perm = 1 << type;
	struct tomoyo_acl_info *ptr;
	struct tomoyo_acl_info *ptr;
	struct tomoyo_path_acl *entry = NULL;
	struct tomoyo_path_acl e = {
		.head.type = TOMOYO_TYPE_PATH_ACL,
		.perm_high = perm >> 16,
		.perm = perm
	};
	int error = is_delete ? -ENOENT : -ENOMEM;
	int error = is_delete ? -ENOENT : -ENOMEM;
	const u32 perm = 1 << type;


	if (type == TOMOYO_TYPE_READ_WRITE)
		e.perm |= tomoyo_rw_mask;
	if (!domain)
	if (!domain)
		return -EINVAL;
		return -EINVAL;
	if (!tomoyo_is_correct_path(filename, 0, 0, 0))
	if (!tomoyo_is_correct_path(filename, 0, 0, 0))
		return -EINVAL;
		return -EINVAL;
	saved_filename = tomoyo_get_name(filename);
	e.filename = tomoyo_get_name(filename);
	if (!saved_filename)
	if (!e.filename)
		return -ENOMEM;
		return -ENOMEM;
	if (!is_delete)
		entry = kmalloc(sizeof(*entry), GFP_NOFS);
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
		goto out;
		goto out;
	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
@@ -834,48 +829,42 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
			container_of(ptr, struct tomoyo_path_acl, head);
			container_of(ptr, struct tomoyo_path_acl, head);
		if (ptr->type != TOMOYO_TYPE_PATH_ACL)
		if (ptr->type != TOMOYO_TYPE_PATH_ACL)
			continue;
			continue;
		if (acl->filename != saved_filename)
		if (acl->filename != e.filename)
			continue;
			continue;
		if (is_delete) {
		if (is_delete) {
			if (perm <= 0xFFFF)
			if (perm <= 0xFFFF)
				acl->perm &= ~perm;
				acl->perm &= ~perm;
			else
			else
				acl->perm_high &= ~(perm >> 16);
				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);
				acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
			else if (!(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 {
		} else {
			if (perm <= 0xFFFF)
			if (perm <= 0xFFFF)
				acl->perm |= perm;
				acl->perm |= perm;
			else
			else
				acl->perm_high |= (perm >> 16);
				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;
				acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
			else if (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;
		error = 0;
		break;
		break;
	}
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
	if (!is_delete && error) {
		entry->head.type = TOMOYO_TYPE_PATH_ACL;
		struct tomoyo_path_acl *entry =
		if (perm <= 0xFFFF)
			tomoyo_commit_ok(&e, sizeof(e));
			entry->perm = perm;
		if (entry) {
		else
			list_add_tail_rcu(&entry->head.list,
			entry->perm_high = (perm >> 16);
					  &domain->acl_info_list);
		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;
			error = 0;
		}
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
	mutex_unlock(&tomoyo_policy_lock);
 out:
 out:
	kfree(entry);
	tomoyo_put_name(e.filename);
	tomoyo_put_name(saved_filename);
	return error;
	return error;
}
}


@@ -897,24 +886,23 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
				   struct tomoyo_domain_info *const domain,
				   struct tomoyo_domain_info *const domain,
				   const bool is_delete)
				   const bool is_delete)
{
{
	const struct tomoyo_path_info *saved_filename1;
	const u8 perm = 1 << type;
	const struct tomoyo_path_info *saved_filename2;
	struct tomoyo_path2_acl e = {
		.head.type = TOMOYO_TYPE_PATH2_ACL,
		.perm = perm
	};
	struct tomoyo_acl_info *ptr;
	struct tomoyo_acl_info *ptr;
	struct tomoyo_path2_acl *entry = NULL;
	int error = is_delete ? -ENOENT : -ENOMEM;
	int error = is_delete ? -ENOENT : -ENOMEM;
	const u8 perm = 1 << type;


	if (!domain)
	if (!domain)
		return -EINVAL;
		return -EINVAL;
	if (!tomoyo_is_correct_path(filename1, 0, 0, 0) ||
	if (!tomoyo_is_correct_path(filename1, 0, 0, 0) ||
	    !tomoyo_is_correct_path(filename2, 0, 0, 0))
	    !tomoyo_is_correct_path(filename2, 0, 0, 0))
		return -EINVAL;
		return -EINVAL;
	saved_filename1 = tomoyo_get_name(filename1);
	e.filename1 = tomoyo_get_name(filename1);
	saved_filename2 = tomoyo_get_name(filename2);
	e.filename2 = tomoyo_get_name(filename2);
	if (!saved_filename1 || !saved_filename2)
	if (!e.filename1 || !e.filename2)
		goto out;
		goto out;
	if (!is_delete)
		entry = kmalloc(sizeof(*entry), GFP_NOFS);
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
	if (mutex_lock_interruptible(&tomoyo_policy_lock))
		goto out;
		goto out;
	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
@@ -922,8 +910,8 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
			container_of(ptr, struct tomoyo_path2_acl, head);
			container_of(ptr, struct tomoyo_path2_acl, head);
		if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
		if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
			continue;
			continue;
		if (acl->filename1 != saved_filename1 ||
		if (acl->filename1 != e.filename1 ||
		    acl->filename2 != saved_filename2)
		    acl->filename2 != e.filename2)
			continue;
			continue;
		if (is_delete)
		if (is_delete)
			acl->perm &= ~perm;
			acl->perm &= ~perm;
@@ -932,22 +920,19 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
		error = 0;
		error = 0;
		break;
		break;
	}
	}
	if (!is_delete && error && tomoyo_memory_ok(entry)) {
	if (!is_delete && error) {
		entry->head.type = TOMOYO_TYPE_PATH2_ACL;
		struct tomoyo_path2_acl *entry =
		entry->perm = perm;
			tomoyo_commit_ok(&e, sizeof(e));
		entry->filename1 = saved_filename1;
		if (entry) {
		saved_filename1 = NULL;
			list_add_tail_rcu(&entry->head.list,
		entry->filename2 = saved_filename2;
					  &domain->acl_info_list);
		saved_filename2 = NULL;
		list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
		entry = NULL;
			error = 0;
			error = 0;
		}
		}
	}
	mutex_unlock(&tomoyo_policy_lock);
	mutex_unlock(&tomoyo_policy_lock);
 out:
 out:
	tomoyo_put_name(saved_filename1);
	tomoyo_put_name(e.filename1);
	tomoyo_put_name(saved_filename2);
	tomoyo_put_name(e.filename2);
	kfree(entry);
	return error;
	return error;
}
}


+19 −0
Original line number Original line Diff line number Diff line
@@ -222,6 +222,25 @@ bool tomoyo_memory_ok(void *ptr)
	return false;
	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.
 */
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.
 * tomoyo_memory_free - Free memory for elements.
 *
 *