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

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

TOMOYO: Use RCU primitives for list operation



Replace list operation with RCU primitives and replace
down_read()/up_read() with srcu_read_lock()/srcu_read_unlock().

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 86fc80f1
Loading
Loading
Loading
Loading
+50 −40
Original line number Diff line number Diff line
@@ -365,10 +365,9 @@ bool tomoyo_is_domain_def(const unsigned char *buffer)
 *
 * @domainname: The domainname to find.
 *
 * Caller must call down_read(&tomoyo_domain_list_lock); or
 * down_write(&tomoyo_domain_list_lock); .
 *
 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
{
@@ -377,7 +376,7 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)

	name.name = domainname;
	tomoyo_fill_path_info(&name);
	list_for_each_entry(domain, &tomoyo_domain_list, list) {
	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
		if (!domain->is_deleted &&
		    !tomoyo_pathcmp(&name, domain->domainname))
			return domain;
@@ -829,6 +828,8 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
 * @domain: Pointer to "struct tomoyo_domain_info".
 *
 * Returns true if the domain is not exceeded quota, false otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
{
@@ -837,8 +838,7 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)

	if (!domain)
		return true;
	down_read(&tomoyo_domain_acl_info_list_lock);
	list_for_each_entry(ptr, &domain->acl_info_list, list) {
	list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
		if (ptr->type & TOMOYO_ACL_DELETED)
			continue;
		switch (tomoyo_acl_type2(ptr)) {
@@ -866,7 +866,6 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
			break;
		}
	}
	up_read(&tomoyo_domain_acl_info_list_lock);
	if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
		return true;
	if (!domain->quota_warned) {
@@ -1096,6 +1095,8 @@ static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
 * @is_delete: True if it is a delete request.
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_update_manager_entry(const char *manager,
				       const bool is_delete)
@@ -1118,7 +1119,7 @@ static int tomoyo_update_manager_entry(const char *manager,
	if (!saved_manager)
		return -ENOMEM;
	down_write(&tomoyo_policy_manager_list_lock);
	list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
		if (ptr->manager != saved_manager)
			continue;
		ptr->is_deleted = is_delete;
@@ -1134,7 +1135,7 @@ static int tomoyo_update_manager_entry(const char *manager,
		goto out;
	new_entry->manager = saved_manager;
	new_entry->is_domain = is_domain;
	list_add_tail(&new_entry->list, &tomoyo_policy_manager_list);
	list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list);
	error = 0;
 out:
	up_write(&tomoyo_policy_manager_list_lock);
@@ -1147,6 +1148,8 @@ static int tomoyo_update_manager_entry(const char *manager,
 * @head: Pointer to "struct tomoyo_io_buffer".
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
{
@@ -1166,6 +1169,8 @@ static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
 * @head: Pointer to "struct tomoyo_io_buffer".
 *
 * Returns 0.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
{
@@ -1174,7 +1179,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)

	if (head->read_eof)
		return 0;
	down_read(&tomoyo_policy_manager_list_lock);
	list_for_each_cookie(pos, head->read_var2,
			     &tomoyo_policy_manager_list) {
		struct tomoyo_policy_manager_entry *ptr;
@@ -1186,7 +1190,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
		if (!done)
			break;
	}
	up_read(&tomoyo_policy_manager_list_lock);
	head->read_eof = done;
	return 0;
}
@@ -1196,6 +1199,8 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
 *
 * Returns true if the current process is permitted to modify policy
 * via /sys/kernel/security/tomoyo/ interface.
 *
 * Caller holds tomoyo_read_lock().
 */
static bool tomoyo_is_policy_manager(void)
{
@@ -1209,29 +1214,25 @@ static bool tomoyo_is_policy_manager(void)
		return true;
	if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
		return false;
	down_read(&tomoyo_policy_manager_list_lock);
	list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
		if (!ptr->is_deleted && ptr->is_domain
		    && !tomoyo_pathcmp(domainname, ptr->manager)) {
			found = true;
			break;
		}
	}
	up_read(&tomoyo_policy_manager_list_lock);
	if (found)
		return true;
	exe = tomoyo_get_exe();
	if (!exe)
		return false;
	down_read(&tomoyo_policy_manager_list_lock);
	list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
		if (!ptr->is_deleted && !ptr->is_domain
		    && !strcmp(exe, ptr->manager->name)) {
			found = true;
			break;
		}
	}
	up_read(&tomoyo_policy_manager_list_lock);
	if (!found) { /* Reduce error messages. */
		static pid_t last_pid;
		const pid_t pid = current->pid;
@@ -1252,6 +1253,8 @@ static bool tomoyo_is_policy_manager(void)
 * @data: String to parse.
 *
 * Returns true on success, false otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
				 const char *data)
@@ -1267,11 +1270,8 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
			domain = tomoyo_real_domain(p);
		read_unlock(&tasklist_lock);
	} else if (!strncmp(data, "domain=", 7)) {
		if (tomoyo_is_domain_def(data + 7)) {
			down_read(&tomoyo_domain_list_lock);
		if (tomoyo_is_domain_def(data + 7))
			domain = tomoyo_find_domain(data + 7);
			up_read(&tomoyo_domain_list_lock);
		}
	} else
		return false;
	head->write_var1 = domain;
@@ -1285,13 +1285,11 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
	if (domain) {
		struct tomoyo_domain_info *d;
		head->read_var1 = NULL;
		down_read(&tomoyo_domain_list_lock);
		list_for_each_entry(d, &tomoyo_domain_list, list) {
		list_for_each_entry_rcu(d, &tomoyo_domain_list, list) {
			if (d == domain)
				break;
			head->read_var1 = &d->list;
		}
		up_read(&tomoyo_domain_list_lock);
		head->read_var2 = NULL;
		head->read_bit = 0;
		head->read_step = 0;
@@ -1307,6 +1305,8 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
 * @domainname: The name of domain.
 *
 * Returns 0.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_delete_domain(char *domainname)
{
@@ -1317,7 +1317,7 @@ static int tomoyo_delete_domain(char *domainname)
	tomoyo_fill_path_info(&name);
	down_write(&tomoyo_domain_list_lock);
	/* Is there an active domain? */
	list_for_each_entry(domain, &tomoyo_domain_list, list) {
	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
		/* Never delete tomoyo_kernel_domain */
		if (domain == &tomoyo_kernel_domain)
			continue;
@@ -1337,6 +1337,8 @@ static int tomoyo_delete_domain(char *domainname)
 * @head: Pointer to "struct tomoyo_io_buffer".
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
{
@@ -1359,11 +1361,9 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
		domain = NULL;
		if (is_delete)
			tomoyo_delete_domain(data);
		else if (is_select) {
			down_read(&tomoyo_domain_list_lock);
		else if (is_select)
			domain = tomoyo_find_domain(data);
			up_read(&tomoyo_domain_list_lock);
		} else
		else
			domain = tomoyo_find_or_assign_new_domain(data, 0);
		head->write_var1 = domain;
		return 0;
@@ -1508,6 +1508,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
 * @head: Pointer to "struct tomoyo_io_buffer".
 *
 * Returns 0.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
{
@@ -1519,7 +1521,6 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
		return 0;
	if (head->read_step == 0)
		head->read_step = 1;
	down_read(&tomoyo_domain_list_lock);
	list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
		struct tomoyo_domain_info *domain;
		const char *quota_exceeded = "";
@@ -1552,7 +1553,6 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
		if (head->read_step == 3)
			goto tail_mark;
		/* Print ACL entries in the domain. */
		down_read(&tomoyo_domain_acl_info_list_lock);
		list_for_each_cookie(apos, head->read_var2,
				     &domain->acl_info_list) {
			struct tomoyo_acl_info *ptr
@@ -1562,7 +1562,6 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
			if (!done)
				break;
		}
		up_read(&tomoyo_domain_acl_info_list_lock);
		if (!done)
			break;
		head->read_step = 3;
@@ -1574,7 +1573,6 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
		if (head->read_single_domain)
			break;
	}
	up_read(&tomoyo_domain_list_lock);
	head->read_eof = done;
	return 0;
}
@@ -1590,6 +1588,8 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
 *
 *     ( echo "select " $domainname; echo "use_profile " $profile ) |
 *     /usr/lib/ccs/loadpolicy -d
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
{
@@ -1601,9 +1601,7 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
	if (!cp)
		return -EINVAL;
	*cp = '\0';
	down_read(&tomoyo_domain_list_lock);
	domain = tomoyo_find_domain(cp + 1);
	up_read(&tomoyo_domain_list_lock);
	if (strict_strtoul(data, 10, &profile))
		return -EINVAL;
	if (domain && profile < TOMOYO_MAX_PROFILES
@@ -1625,6 +1623,8 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
 *     awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
 *     domainname = $0; } else if ( $1 == "use_profile" ) {
 *     print $2 " " domainname; domainname = ""; } } ; '
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
{
@@ -1633,7 +1633,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)

	if (head->read_eof)
		return 0;
	down_read(&tomoyo_domain_list_lock);
	list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
		struct tomoyo_domain_info *domain;
		domain = list_entry(pos, struct tomoyo_domain_info, list);
@@ -1644,7 +1643,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
		if (!done)
			break;
	}
	up_read(&tomoyo_domain_list_lock);
	head->read_eof = done;
	return 0;
}
@@ -1701,6 +1699,8 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
 * @head: Pointer to "struct tomoyo_io_buffer".
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
{
@@ -1735,6 +1735,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
 * @head: Pointer to "struct tomoyo_io_buffer".
 *
 * Returns 0 on success, -EINVAL otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
{
@@ -1864,15 +1866,13 @@ void tomoyo_load_policy(const char *filename)
	tomoyo_policy_loaded = true;
	{ /* Check all profiles currently assigned to domains are defined. */
		struct tomoyo_domain_info *domain;
		down_read(&tomoyo_domain_list_lock);
		list_for_each_entry(domain, &tomoyo_domain_list, list) {
		list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
			const u8 profile = domain->profile;
			if (tomoyo_profile_ptr[profile])
				continue;
			panic("Profile %u (used by '%s') not defined.\n",
			      profile, domain->domainname->name);
		}
		up_read(&tomoyo_domain_list_lock);
	}
}

@@ -1920,6 +1920,8 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
 * @file: Pointer to "struct file".
 *
 * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
 *
 * Caller acquires tomoyo_read_lock().
 */
static int tomoyo_open_control(const u8 type, struct file *file)
{
@@ -2005,6 +2007,7 @@ static int tomoyo_open_control(const u8 type, struct file *file)
			return -ENOMEM;
		}
	}
	head->reader_idx = tomoyo_read_lock();
	file->private_data = head;
	/*
	 * Call the handler now if the file is
@@ -2026,6 +2029,8 @@ static int tomoyo_open_control(const u8 type, struct file *file)
 * @buffer_len: Size of @buffer.
 *
 * Returns bytes read on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_read_control(struct file *file, char __user *buffer,
			       const int buffer_len)
@@ -2069,6 +2074,8 @@ static int tomoyo_read_control(struct file *file, char __user *buffer,
 * @buffer_len: Size of @buffer.
 *
 * Returns @buffer_len on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_write_control(struct file *file, const char __user *buffer,
				const int buffer_len)
@@ -2119,11 +2126,14 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer,
 * @file: Pointer to "struct file".
 *
 * Releases memory and returns 0.
 *
 * Caller looses tomoyo_read_lock().
 */
static int tomoyo_close_control(struct file *file)
{
	struct tomoyo_io_buffer *head = file->private_data;

	tomoyo_read_unlock(head->reader_idx);
	/* Release memory used for policy I/O. */
	tomoyo_free(head->read_buf);
	head->read_buf = NULL;
+21 −7
Original line number Diff line number Diff line
@@ -269,6 +269,8 @@ struct tomoyo_io_buffer {
	int (*write) (struct tomoyo_io_buffer *);
	/* Exclusive lock for this structure.   */
	struct mutex io_sem;
	/* Index returned by tomoyo_read_lock(). */
	int reader_idx;
	/* The position currently reading from. */
	struct list_head *read_var1;
	/* Extra variables for reading.         */
@@ -446,7 +448,7 @@ extern struct tomoyo_domain_info tomoyo_kernel_domain;
 * @cookie:     the &struct list_head to use as a cookie.
 * @head:       the head for your list.
 *
 * Same with list_for_each() except that this primitive uses @cookie
 * Same with list_for_each_rcu() except that this primitive uses @cookie
 * so that we can continue iteration.
 * @cookie must be NULL when iteration starts, and @cookie will become
 * NULL when iteration finishes.
@@ -454,8 +456,20 @@ extern struct tomoyo_domain_info tomoyo_kernel_domain;
#define list_for_each_cookie(pos, cookie, head)				\
	for (({ if (!cookie)						\
				     cookie = head; }),			\
	     pos = (cookie)->next;                                    \
		     pos = rcu_dereference((cookie)->next);		\
	     prefetch(pos->next), pos != (head) || ((cookie) = NULL);	\
	     (cookie) = pos, pos = pos->next)
	     (cookie) = pos, pos = rcu_dereference(pos->next))

extern struct srcu_struct tomoyo_ss;

static inline int tomoyo_read_lock(void)
{
	return srcu_read_lock(&tomoyo_ss);
}

static inline void tomoyo_read_unlock(int idx)
{
	srcu_read_unlock(&tomoyo_ss, idx);
}

#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
+37 −26
Original line number Diff line number Diff line
@@ -217,6 +217,8 @@ static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
 * @is_delete:  True if it is a delete request.
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_update_domain_initializer_entry(const char *domainname,
						  const char *program,
@@ -246,7 +248,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
	if (!saved_program)
		return -ENOMEM;
	down_write(&tomoyo_domain_initializer_list_lock);
	list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
		if (ptr->is_not != is_not ||
		    ptr->domainname != saved_domainname ||
		    ptr->program != saved_program)
@@ -266,7 +268,7 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
	new_entry->program = saved_program;
	new_entry->is_not = is_not;
	new_entry->is_last_name = is_last_name;
	list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
	list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list);
	error = 0;
 out:
	up_write(&tomoyo_domain_initializer_list_lock);
@@ -279,13 +281,14 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
 * @head: Pointer to "struct tomoyo_io_buffer".
 *
 * Returns true on success, false otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
{
	struct list_head *pos;
	bool done = true;

	down_read(&tomoyo_domain_initializer_list_lock);
	list_for_each_cookie(pos, head->read_var2,
			     &tomoyo_domain_initializer_list) {
		const char *no;
@@ -308,7 +311,6 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
		if (!done)
			break;
	}
	up_read(&tomoyo_domain_initializer_list_lock);
	return done;
}

@@ -320,6 +322,8 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
 * @is_delete: True if it is a delete request.
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
					   const bool is_delete)
@@ -345,6 +349,8 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
 *
 * Returns true if executing @program reinitializes domain transition,
 * false otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
					 domainname,
@@ -355,8 +361,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
	struct tomoyo_domain_initializer_entry *ptr;
	bool flag = false;

	down_read(&tomoyo_domain_initializer_list_lock);
	list_for_each_entry(ptr,  &tomoyo_domain_initializer_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
		if (ptr->is_deleted)
			continue;
		if (ptr->domainname) {
@@ -376,7 +381,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
		}
		flag = true;
	}
	up_read(&tomoyo_domain_initializer_list_lock);
	return flag;
}

@@ -430,6 +434,8 @@ static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
 * @is_delete:  True if it is a delete request.
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_update_domain_keeper_entry(const char *domainname,
					     const char *program,
@@ -459,7 +465,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
	if (!saved_domainname)
		return -ENOMEM;
	down_write(&tomoyo_domain_keeper_list_lock);
	list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
		if (ptr->is_not != is_not ||
		    ptr->domainname != saved_domainname ||
		    ptr->program != saved_program)
@@ -479,7 +485,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
	new_entry->program = saved_program;
	new_entry->is_not = is_not;
	new_entry->is_last_name = is_last_name;
	list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
	list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list);
	error = 0;
 out:
	up_write(&tomoyo_domain_keeper_list_lock);
@@ -493,6 +499,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
 * @is_not:    True if it is "no_keep_domain" entry.
 * @is_delete: True if it is a delete request.
 *
 * Caller holds tomoyo_read_lock().
 */
int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
				      const bool is_delete)
@@ -513,13 +520,14 @@ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
 * @head: Pointer to "struct tomoyo_io_buffer".
 *
 * Returns true on success, false otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
{
	struct list_head *pos;
	bool done = true;

	down_read(&tomoyo_domain_keeper_list_lock);
	list_for_each_cookie(pos, head->read_var2,
			     &tomoyo_domain_keeper_list) {
		struct tomoyo_domain_keeper_entry *ptr;
@@ -542,7 +550,6 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
		if (!done)
			break;
	}
	up_read(&tomoyo_domain_keeper_list_lock);
	return done;
}

@@ -555,6 +562,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
 *
 * Returns true if executing @program supresses domain transition,
 * false otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
				    const struct tomoyo_path_info *program,
@@ -563,8 +572,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
	struct tomoyo_domain_keeper_entry *ptr;
	bool flag = false;

	down_read(&tomoyo_domain_keeper_list_lock);
	list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
		if (ptr->is_deleted)
			continue;
		if (!ptr->is_last_name) {
@@ -582,7 +590,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
		}
		flag = true;
	}
	up_read(&tomoyo_domain_keeper_list_lock);
	return flag;
}

@@ -627,6 +634,8 @@ static DECLARE_RWSEM(tomoyo_alias_list_lock);
 * @is_delete:     True if it is a delete request.
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
static int tomoyo_update_alias_entry(const char *original_name,
				     const char *aliased_name,
@@ -646,7 +655,7 @@ static int tomoyo_update_alias_entry(const char *original_name,
	if (!saved_original_name || !saved_aliased_name)
		return -ENOMEM;
	down_write(&tomoyo_alias_list_lock);
	list_for_each_entry(ptr, &tomoyo_alias_list, list) {
	list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
		if (ptr->original_name != saved_original_name ||
		    ptr->aliased_name != saved_aliased_name)
			continue;
@@ -663,7 +672,7 @@ static int tomoyo_update_alias_entry(const char *original_name,
		goto out;
	new_entry->original_name = saved_original_name;
	new_entry->aliased_name = saved_aliased_name;
	list_add_tail(&new_entry->list, &tomoyo_alias_list);
	list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list);
	error = 0;
 out:
	up_write(&tomoyo_alias_list_lock);
@@ -676,13 +685,14 @@ static int tomoyo_update_alias_entry(const char *original_name,
 * @head: Pointer to "struct tomoyo_io_buffer".
 *
 * Returns true on success, false otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
{
	struct list_head *pos;
	bool done = true;

	down_read(&tomoyo_alias_list_lock);
	list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
		struct tomoyo_alias_entry *ptr;

@@ -695,7 +705,6 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
		if (!done)
			break;
	}
	up_read(&tomoyo_alias_list_lock);
	return done;
}

@@ -706,6 +715,8 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
 * @is_delete: True if it is a delete request.
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
int tomoyo_write_alias_policy(char *data, const bool is_delete)
{
@@ -724,6 +735,8 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete)
 * @profile:    Profile number to assign if the domain was newly created.
 *
 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
							    domainname,
@@ -742,7 +755,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
	if (!saved_domainname)
		goto out;
	/* Can I reuse memory of deleted domain? */
	list_for_each_entry(domain, &tomoyo_domain_list, list) {
	list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
		struct task_struct *p;
		struct tomoyo_acl_info *ptr;
		bool flag;
@@ -760,7 +773,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
		read_unlock(&tasklist_lock);
		if (flag)
			continue;
		list_for_each_entry(ptr, &domain->acl_info_list, list) {
		list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
			ptr->type |= TOMOYO_ACL_DELETED;
		}
		tomoyo_set_domain_flag(domain, true, domain->flags);
@@ -776,7 +789,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
		INIT_LIST_HEAD(&domain->acl_info_list);
		domain->domainname = saved_domainname;
		domain->profile = profile;
		list_add_tail(&domain->list, &tomoyo_domain_list);
		list_add_tail_rcu(&domain->list, &tomoyo_domain_list);
	}
 out:
	up_write(&tomoyo_domain_list_lock);
@@ -789,6 +802,8 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
 * @bprm: Pointer to "struct linux_binprm".
 *
 * Returns 0 on success, negative value otherwise.
 *
 * Caller holds tomoyo_read_lock().
 */
int tomoyo_find_next_domain(struct linux_binprm *bprm)
{
@@ -849,8 +864,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
	if (tomoyo_pathcmp(&r, &s)) {
		struct tomoyo_alias_entry *ptr;
		/* Is this program allowed to be called via symbolic links? */
		down_read(&tomoyo_alias_list_lock);
		list_for_each_entry(ptr, &tomoyo_alias_list, list) {
		list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
			if (ptr->is_deleted ||
			    tomoyo_pathcmp(&r, ptr->original_name) ||
			    tomoyo_pathcmp(&s, ptr->aliased_name))
@@ -861,7 +875,6 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
			tomoyo_fill_path_info(&r);
			break;
		}
		up_read(&tomoyo_alias_list_lock);
	}

	/* Check execute permission. */
@@ -892,9 +905,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
	}
	if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
		goto done;
	down_read(&tomoyo_domain_list_lock);
	domain = tomoyo_find_domain(new_domain_name);
	up_read(&tomoyo_domain_list_lock);
	if (domain)
		goto done;
	if (is_enforce)
+77 −33

File changed.

Preview size limit exceeded, changes collapsed.

+5 −3
Original line number Diff line number Diff line
@@ -402,11 +402,13 @@ void __init tomoyo_realpath_init(void)
		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);
	list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
	down_read(&tomoyo_domain_list_lock);
	/*
	 * tomoyo_read_lock() is not needed because this function is
	 * called before the first "delete" request.
	 */
	list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
	if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
		panic("Can't register tomoyo_kernel_domain");
	up_read(&tomoyo_domain_list_lock);
}

/* Memory allocated for temporary purpose. */
Loading