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

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

TOMOYO: Remove memory pool for list elements.



Currently, TOMOYO allocates memory for list elements from memory pool allocated
by kmalloc(PAGE_SIZE). But that makes it difficult to kfree() when garbage
collector is added. Thus, remove memory pool and use kmalloc(sizeof()).

Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent e41035a9
Loading
Loading
Loading
Loading
+8 −33
Original line number Diff line number Diff line
@@ -900,9 +900,11 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
	ptr = tomoyo_profile_ptr[profile];
	if (ptr)
		goto ok;
	ptr = tomoyo_alloc_element(sizeof(*ptr));
	if (!ptr)
	ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);
	if (!tomoyo_memory_ok(ptr)) {
		kfree(ptr);
		goto ok;
	}
	for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
		ptr->value[i] = tomoyo_control_array[i].current_value;
	mb(); /* Avoid out-of-order execution. */
@@ -1120,6 +1122,7 @@ static int tomoyo_update_manager_entry(const char *manager,
	saved_manager = tomoyo_save_name(manager);
	if (!saved_manager)
		return -ENOMEM;
	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
	mutex_lock(&tomoyo_policy_lock);
	list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
		if (ptr->manager != saved_manager)
@@ -1132,15 +1135,16 @@ static int tomoyo_update_manager_entry(const char *manager,
		error = -ENOENT;
		goto out;
	}
	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
	if (!new_entry)
	if (!tomoyo_memory_ok(new_entry))
		goto out;
	new_entry->manager = saved_manager;
	new_entry->is_domain = is_domain;
	list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list);
	new_entry = NULL;
	error = 0;
 out:
	mutex_unlock(&tomoyo_policy_lock);
	kfree(new_entry);
	return error;
}

@@ -2147,35 +2151,6 @@ static int tomoyo_close_control(struct file *file)
	return 0;
}

/**
 * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry.
 *
 * @acl_type:  Type of ACL entry.
 *
 * Returns pointer to the ACL entry on success, NULL otherwise.
 */
void *tomoyo_alloc_acl_element(const u8 acl_type)
{
	int len;
	struct tomoyo_acl_info *ptr;

	switch (acl_type) {
	case TOMOYO_TYPE_SINGLE_PATH_ACL:
		len = sizeof(struct tomoyo_single_path_acl_record);
		break;
	case TOMOYO_TYPE_DOUBLE_PATH_ACL:
		len = sizeof(struct tomoyo_double_path_acl_record);
		break;
	default:
		return NULL;
	}
	ptr = tomoyo_alloc_element(len);
	if (!ptr)
		return NULL;
	ptr->type = acl_type;
	return ptr;
}

/**
 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
 *
+0 −2
Original line number Diff line number Diff line
@@ -376,8 +376,6 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
/* Check mode for specified functionality. */
unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
				const u8 index);
/* Allocate memory for structures. */
void *tomoyo_alloc_acl_element(const u8 acl_type);
/* Fill in "struct tomoyo_path_info" members. */
void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
/* Run policy loader when /sbin/init starts. */
+19 −39
Original line number Diff line number Diff line
@@ -245,6 +245,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
	saved_program = tomoyo_save_name(program);
	if (!saved_program)
		return -ENOMEM;
	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
	mutex_lock(&tomoyo_policy_lock);
	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
		if (ptr->is_not != is_not ||
@@ -259,17 +260,18 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
		error = -ENOENT;
		goto out;
	}
	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
	if (!new_entry)
	if (!tomoyo_memory_ok(new_entry))
		goto out;
	new_entry->domainname = saved_domainname;
	new_entry->program = saved_program;
	new_entry->is_not = is_not;
	new_entry->is_last_name = is_last_name;
	list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list);
	new_entry = NULL;
	error = 0;
 out:
	mutex_unlock(&tomoyo_policy_lock);
	kfree(new_entry);
	return error;
}

@@ -461,6 +463,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
	saved_domainname = tomoyo_save_name(domainname);
	if (!saved_domainname)
		return -ENOMEM;
	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
	mutex_lock(&tomoyo_policy_lock);
	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
		if (ptr->is_not != is_not ||
@@ -475,17 +478,18 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
		error = -ENOENT;
		goto out;
	}
	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
	if (!new_entry)
	if (!tomoyo_memory_ok(new_entry))
		goto out;
	new_entry->domainname = saved_domainname;
	new_entry->program = saved_program;
	new_entry->is_not = is_not;
	new_entry->is_last_name = is_last_name;
	list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list);
	new_entry = NULL;
	error = 0;
 out:
	mutex_unlock(&tomoyo_policy_lock);
	kfree(new_entry);
	return error;
}

@@ -650,6 +654,7 @@ static int tomoyo_update_alias_entry(const char *original_name,
	saved_aliased_name = tomoyo_save_name(aliased_name);
	if (!saved_original_name || !saved_aliased_name)
		return -ENOMEM;
	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
	mutex_lock(&tomoyo_policy_lock);
	list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
		if (ptr->original_name != saved_original_name ||
@@ -663,15 +668,16 @@ static int tomoyo_update_alias_entry(const char *original_name,
		error = -ENOENT;
		goto out;
	}
	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
	if (!new_entry)
	if (!tomoyo_memory_ok(new_entry))
		goto out;
	new_entry->original_name = saved_original_name;
	new_entry->aliased_name = saved_aliased_name;
	list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list);
	new_entry = NULL;
	error = 0;
 out:
	mutex_unlock(&tomoyo_policy_lock);
	kfree(new_entry);
	return error;
}

@@ -738,7 +744,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
							    domainname,
							    const u8 profile)
{
	struct tomoyo_domain_info *domain = NULL;
	struct tomoyo_domain_info *domain;
	const struct tomoyo_path_info *saved_domainname;

	mutex_lock(&tomoyo_policy_lock);
@@ -750,43 +756,17 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
	saved_domainname = tomoyo_save_name(domainname);
	if (!saved_domainname)
		goto out;
	/* Can I reuse memory of deleted domain? */
	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
		struct task_struct *p;
		struct tomoyo_acl_info *ptr;
		bool flag;
		if (!domain->is_deleted ||
		    domain->domainname != saved_domainname)
			continue;
		flag = false;
		read_lock(&tasklist_lock);
		for_each_process(p) {
			if (tomoyo_real_domain(p) != domain)
				continue;
			flag = true;
			break;
		}
		read_unlock(&tasklist_lock);
		if (flag)
			continue;
		list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
			ptr->type |= TOMOYO_ACL_DELETED;
		}
		tomoyo_set_domain_flag(domain, true, domain->flags);
		domain->profile = profile;
		domain->quota_warned = false;
		mb(); /* Avoid out-of-order execution. */
		domain->is_deleted = false;
		goto out;
	}
	/* No memory reusable. Create using new memory. */
	domain = tomoyo_alloc_element(sizeof(*domain));
	if (domain) {
	domain = kmalloc(sizeof(*domain), GFP_KERNEL);
	if (tomoyo_memory_ok(domain)) {
		INIT_LIST_HEAD(&domain->acl_info_list);
		domain->domainname = saved_domainname;
		domain->profile = profile;
		list_add_tail_rcu(&domain->list, &tomoyo_domain_list);
	} else {
		kfree(domain);
		domain = NULL;
	}

 out:
	mutex_unlock(&tomoyo_policy_lock);
	return domain;
+24 −10
Original line number Diff line number Diff line
@@ -225,6 +225,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename,
	saved_filename = tomoyo_save_name(filename);
	if (!saved_filename)
		return -ENOMEM;
	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
	mutex_lock(&tomoyo_policy_lock);
	list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
		if (ptr->filename != saved_filename)
@@ -237,14 +238,15 @@ static int tomoyo_update_globally_readable_entry(const char *filename,
		error = -ENOENT;
		goto out;
	}
	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
	if (!new_entry)
	if (!tomoyo_memory_ok(new_entry))
		goto out;
	new_entry->filename = saved_filename;
	list_add_tail_rcu(&new_entry->list, &tomoyo_globally_readable_list);
	new_entry = NULL;
	error = 0;
 out:
	mutex_unlock(&tomoyo_policy_lock);
	kfree(new_entry);
	return error;
}

@@ -372,6 +374,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
	saved_pattern = tomoyo_save_name(pattern);
	if (!saved_pattern)
		return -ENOMEM;
	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
	mutex_lock(&tomoyo_policy_lock);
	list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
		if (saved_pattern != ptr->pattern)
@@ -384,14 +387,15 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
		error = -ENOENT;
		goto out;
	}
	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
	if (!new_entry)
	if (!tomoyo_memory_ok(new_entry))
		goto out;
	new_entry->pattern = saved_pattern;
	list_add_tail_rcu(&new_entry->list, &tomoyo_pattern_list);
	new_entry = NULL;
	error = 0;
 out:
	mutex_unlock(&tomoyo_policy_lock);
	kfree(new_entry);
	return error;
}

@@ -523,6 +527,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern,
	saved_pattern = tomoyo_save_name(pattern);
	if (!saved_pattern)
		return -ENOMEM;
	new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
	mutex_lock(&tomoyo_policy_lock);
	list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
		if (ptr->pattern != saved_pattern)
@@ -535,14 +540,15 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern,
		error = -ENOENT;
		goto out;
	}
	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
	if (!new_entry)
	if (!tomoyo_memory_ok(new_entry))
		goto out;
	new_entry->pattern = saved_pattern;
	list_add_tail_rcu(&new_entry->list, &tomoyo_no_rewrite_list);
	new_entry = NULL;
	error = 0;
 out:
	mutex_unlock(&tomoyo_policy_lock);
	kfree(new_entry);
	return error;
}

@@ -901,9 +907,13 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
		goto out;
	}
	/* Not found. Append it to the tail. */
	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
	if (!acl)
	acl = kmalloc(sizeof(*acl), GFP_KERNEL);
	if (!tomoyo_memory_ok(acl)) {
		kfree(acl);
		acl = NULL;
		goto out;
	}
	acl->head.type = TOMOYO_TYPE_SINGLE_PATH_ACL;
	if (perm <= 0xFFFF)
		acl->perm = perm;
	else
@@ -995,9 +1005,13 @@ static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
		goto out;
	}
	/* Not found. Append it to the tail. */
	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
	if (!acl)
	acl = kmalloc(sizeof(*acl), GFP_KERNEL);
	if (!tomoyo_memory_ok(acl)) {
		kfree(acl);
		acl = NULL;
		goto out;
	}
	acl->head.type = TOMOYO_TYPE_DOUBLE_PATH_ACL;
	acl->perm = perm;
	acl->filename1 = saved_filename1;
	acl->filename2 = saved_filename2;
+20 −45
Original line number Diff line number Diff line
@@ -212,57 +212,32 @@ static unsigned int tomoyo_allocated_memory_for_elements;
static unsigned int tomoyo_quota_for_elements;

/**
 * tomoyo_alloc_element - Allocate permanent memory for structures.
 * tomoyo_memory_ok - Check memory quota.
 *
 * @size: Size in bytes.
 * @ptr: Pointer to allocated memory.
 *
 * Returns pointer to allocated memory on success, NULL otherwise.
 * Returns true on success, false otherwise.
 *
 * Memory has to be zeroed.
 * The RAM is chunked, so NEVER try to kfree() the returned pointer.
 * Caller holds tomoyo_policy_lock.
 * Memory pointed by @ptr will be zeroed on success.
 */
void *tomoyo_alloc_element(const unsigned int size)
bool tomoyo_memory_ok(void *ptr)
{
	static char *buf;
	static DEFINE_MUTEX(lock);
	static unsigned int buf_used_len = PATH_MAX;
	char *ptr = NULL;
	/*Assumes sizeof(void *) >= sizeof(long) is true. */
	const unsigned int word_aligned_size
		= roundup(size, max(sizeof(void *), sizeof(long)));
	if (word_aligned_size > PATH_MAX)
		return NULL;
	mutex_lock(&lock);
	if (buf_used_len + word_aligned_size > PATH_MAX) {
		if (!tomoyo_quota_for_elements ||
	int allocated_len = ptr ? ksize(ptr) : 0;
	bool result = false;
	if (!ptr || (tomoyo_quota_for_elements &&
		     tomoyo_allocated_memory_for_elements
		    + PATH_MAX <= tomoyo_quota_for_elements)
			ptr = kzalloc(PATH_MAX, GFP_KERNEL);
		if (!ptr) {
		     + allocated_len > tomoyo_quota_for_elements)) {
		printk(KERN_WARNING "ERROR: Out of memory "
		       "for tomoyo_alloc_element().\n");
		if (!tomoyo_policy_loaded)
			panic("MAC Initialization failed.\n");
	} else {
			buf = ptr;
			tomoyo_allocated_memory_for_elements += PATH_MAX;
			buf_used_len = word_aligned_size;
			ptr = buf;
		result = true;
		tomoyo_allocated_memory_for_elements += allocated_len;
		memset(ptr, 0, allocated_len);
	}
	} else if (word_aligned_size) {
		int i;
		ptr = buf + buf_used_len;
		buf_used_len += word_aligned_size;
		for (i = 0; i < word_aligned_size; i++) {
			if (!ptr[i])
				continue;
			printk(KERN_ERR "WARNING: Reserved memory was tainted! "
			       "The system might go wrong.\n");
			ptr[i] = '\0';
		}
	}
	mutex_unlock(&lock);
	return ptr;
	return result;
}

/* Memory allocated for string data in bytes. */
Loading