Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * security/tomoyo/domain.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2005-2011  NTT DATA CORPORATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/binfmts.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/rculist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) /* Variables definitions.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) /* The initial domain. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) struct tomoyo_domain_info tomoyo_kernel_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * tomoyo_update_policy - Update an entry for exception policy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * @new_entry:       Pointer to "struct tomoyo_acl_info".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * @size:            Size of @new_entry in bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * @param:           Pointer to "struct tomoyo_acl_param".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * @check_duplicate: Callback function to find duplicated entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * Returns 0 on success, negative value otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 			 struct tomoyo_acl_param *param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 			 bool (*check_duplicate)(const struct tomoyo_acl_head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 						 *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 						 const struct tomoyo_acl_head
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 						 *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	int error = param->is_delete ? -ENOENT : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	struct tomoyo_acl_head *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct list_head *list = param->list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	list_for_each_entry_rcu(entry, list, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 				srcu_read_lock_held(&tomoyo_ss)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		if (!check_duplicate(entry, new_entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		entry->is_deleted = param->is_delete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	if (error && !param->is_delete) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		entry = tomoyo_commit_ok(new_entry, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		if (entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 			list_add_tail_rcu(&entry->list, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	mutex_unlock(&tomoyo_policy_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * @a: Pointer to "struct tomoyo_acl_info".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * @b: Pointer to "struct tomoyo_acl_info".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * Returns true if @a == @b, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 					const struct tomoyo_acl_info *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	return a->type == b->type && a->cond == b->cond;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * tomoyo_update_domain - Update an entry for domain policy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  * @new_entry:       Pointer to "struct tomoyo_acl_info".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * @size:            Size of @new_entry in bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * @param:           Pointer to "struct tomoyo_acl_param".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * @check_duplicate: Callback function to find duplicated entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  * @merge_duplicate: Callback function to merge duplicated entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * Returns 0 on success, negative value otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			 struct tomoyo_acl_param *param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 			 bool (*check_duplicate)(const struct tomoyo_acl_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 						 *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 						 const struct tomoyo_acl_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 						 *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 			 bool (*merge_duplicate)(struct tomoyo_acl_info *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 						 struct tomoyo_acl_info *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 						 const bool))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	const bool is_delete = param->is_delete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	int error = is_delete ? -ENOENT : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	struct tomoyo_acl_info *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	struct list_head * const list = param->list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (param->data[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		new_entry->cond = tomoyo_get_condition(param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		if (!new_entry->cond)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		 * Domain transition preference is allowed for only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		 * "file execute" entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		if (new_entry->cond->transit &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		    !(new_entry->type == TOMOYO_TYPE_PATH_ACL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		      container_of(new_entry, struct tomoyo_path_acl, head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		      ->perm == 1 << TOMOYO_TYPE_EXECUTE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	list_for_each_entry_rcu(entry, list, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 				srcu_read_lock_held(&tomoyo_ss)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		if (!tomoyo_same_acl_head(entry, new_entry) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		    !check_duplicate(entry, new_entry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		if (merge_duplicate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 			entry->is_deleted = merge_duplicate(entry, new_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 							    is_delete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 			entry->is_deleted = is_delete;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	if (error && !is_delete) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 		entry = tomoyo_commit_ok(new_entry, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		if (entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			list_add_tail_rcu(&entry->list, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	mutex_unlock(&tomoyo_policy_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	tomoyo_put_condition(new_entry->cond);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  * tomoyo_check_acl - Do permission check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  * @r:           Pointer to "struct tomoyo_request_info".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)  * @check_entry: Callback function to check type specific parameters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)  * Returns 0 on success, negative value otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void tomoyo_check_acl(struct tomoyo_request_info *r,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		      bool (*check_entry)(struct tomoyo_request_info *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 					  const struct tomoyo_acl_info *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	const struct tomoyo_domain_info *domain = r->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	struct tomoyo_acl_info *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	const struct list_head *list = &domain->acl_info_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	u16 i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	list_for_each_entry_rcu(ptr, list, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 				srcu_read_lock_held(&tomoyo_ss)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		if (ptr->is_deleted || ptr->type != r->param_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		if (!check_entry(r, ptr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		if (!tomoyo_condition(r, ptr->cond))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		r->matched_acl = ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		r->granted = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	for (; i < TOMOYO_MAX_ACL_GROUPS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		if (!test_bit(i, domain->group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		list = &domain->ns->acl_group[i++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	r->granted = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* The list for "struct tomoyo_domain_info". */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) LIST_HEAD(tomoyo_domain_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)  * tomoyo_last_word - Get last component of a domainname.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  * @name: Domainname to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  * Returns the last word of @domainname.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static const char *tomoyo_last_word(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	const char *cp = strrchr(name, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	if (cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		return cp + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	return name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  * @a: Pointer to "struct tomoyo_acl_head".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  * @b: Pointer to "struct tomoyo_acl_head".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  * Returns true if @a == @b, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 					   const struct tomoyo_acl_head *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	const struct tomoyo_transition_control *p1 = container_of(a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 								  typeof(*p1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 								  head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	const struct tomoyo_transition_control *p2 = container_of(b,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 								  typeof(*p2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 								  head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	return p1->type == p2->type && p1->is_last_name == p2->is_last_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		&& p1->domainname == p2->domainname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 		&& p1->program == p2->program;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)  * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  * @param: Pointer to "struct tomoyo_acl_param".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  * @type:  Type of this entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  * Returns 0 on success, negative value otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 				    const u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	struct tomoyo_transition_control e = { .type = type };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	int error = param->is_delete ? -ENOENT : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	char *program = param->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	char *domainname = strstr(program, " from ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	if (domainname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		*domainname = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		domainname += 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	} else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		   type == TOMOYO_TRANSITION_CONTROL_KEEP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		domainname = program;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		program = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	if (program && strcmp(program, "any")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		if (!tomoyo_correct_path(program))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		e.program = tomoyo_get_name(program);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		if (!e.program)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	if (domainname && strcmp(domainname, "any")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		if (!tomoyo_correct_domain(domainname)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			if (!tomoyo_correct_path(domainname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 				goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			e.is_last_name = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		e.domainname = tomoyo_get_name(domainname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		if (!e.domainname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	param->list = &param->ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	error = tomoyo_update_policy(&e.head, sizeof(e), param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 				     tomoyo_same_transition_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	tomoyo_put_name(e.domainname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	tomoyo_put_name(e.program);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)  * tomoyo_scan_transition - Try to find specific domain transition type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)  * @list:       Pointer to "struct list_head".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)  * @domainname: The name of current domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)  * @program:    The name of requested program.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)  * @last_name:  The last component of @domainname.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)  * @type:       One of values in "enum tomoyo_transition_type".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  * Returns true if found one, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) static inline bool tomoyo_scan_transition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) (const struct list_head *list, const struct tomoyo_path_info *domainname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)  const struct tomoyo_path_info *program, const char *last_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)  const enum tomoyo_transition_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	const struct tomoyo_transition_control *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	list_for_each_entry_rcu(ptr, list, head.list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 				srcu_read_lock_held(&tomoyo_ss)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		if (ptr->head.is_deleted || ptr->type != type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		if (ptr->domainname) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 			if (!ptr->is_last_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 				if (ptr->domainname != domainname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 				 * Use direct strcmp() since this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 				 * unlikely used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 				if (strcmp(ptr->domainname->name, last_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 					continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		if (ptr->program && tomoyo_pathcmp(ptr->program, program))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  * tomoyo_transition_type - Get domain transition type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)  * @ns:         Pointer to "struct tomoyo_policy_namespace".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  * @domainname: The name of current domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)  * @program:    The name of requested program.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  * Returns TOMOYO_TRANSITION_CONTROL_TRANSIT if executing @program causes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  * domain transition across namespaces, TOMOYO_TRANSITION_CONTROL_INITIALIZE if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)  * executing @program reinitializes domain transition within that namespace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)  * TOMOYO_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)  * others otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static enum tomoyo_transition_type tomoyo_transition_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) (const struct tomoyo_policy_namespace *ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)  const struct tomoyo_path_info *domainname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)  const struct tomoyo_path_info *program)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	const char *last_name = tomoyo_last_word(domainname->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 	while (type < TOMOYO_MAX_TRANSITION_TYPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		const struct list_head * const list =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 			&ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 		if (!tomoyo_scan_transition(list, domainname, program,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 					    last_name, type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 			type++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		if (type != TOMOYO_TRANSITION_CONTROL_NO_RESET &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		    type != TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		 * Do not check for reset_domain if no_reset_domain matched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 		 * Do not check for initialize_domain if no_initialize_domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 		 * matched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		type++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		type++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)  * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)  * @a: Pointer to "struct tomoyo_acl_head".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)  * @b: Pointer to "struct tomoyo_acl_head".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)  * Returns true if @a == @b, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 				   const struct tomoyo_acl_head *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 							  head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 							  head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	return p1->original_name == p2->original_name &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 		p1->aggregated_name == p2->aggregated_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)  * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)  * @param: Pointer to "struct tomoyo_acl_param".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)  * Returns 0 on success, negative value otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int tomoyo_write_aggregator(struct tomoyo_acl_param *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	struct tomoyo_aggregator e = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 	int error = param->is_delete ? -ENOENT : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 	const char *original_name = tomoyo_read_token(param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	const char *aggregated_name = tomoyo_read_token(param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) 	if (!tomoyo_correct_word(original_name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 	    !tomoyo_correct_path(aggregated_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) 	e.original_name = tomoyo_get_name(original_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) 	e.aggregated_name = tomoyo_get_name(aggregated_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	if (!e.original_name || !e.aggregated_name ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 	    e.aggregated_name->is_patterned) /* No patterns allowed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	param->list = &param->ns->policy_list[TOMOYO_ID_AGGREGATOR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 	error = tomoyo_update_policy(&e.head, sizeof(e), param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) 				     tomoyo_same_aggregator);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) 	tomoyo_put_name(e.original_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 	tomoyo_put_name(e.aggregated_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)  * tomoyo_find_namespace - Find specified namespace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)  * @name: Name of namespace to find.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)  * @len:  Length of @name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)  * Returns pointer to "struct tomoyo_policy_namespace" if found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)  * NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) static struct tomoyo_policy_namespace *tomoyo_find_namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) (const char *name, const unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) 	struct tomoyo_policy_namespace *ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 	list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) 		if (strncmp(name, ns->name, len) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) 		    (name[len] && name[len] != ' '))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) 		return ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)  * tomoyo_assign_namespace - Create a new namespace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)  * @domainname: Name of namespace to create.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)  * Returns pointer to "struct tomoyo_policy_namespace" on success,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)  * NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 	struct tomoyo_policy_namespace *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) 	struct tomoyo_policy_namespace *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) 	const char *cp = domainname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) 	unsigned int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 	while (*cp && *cp++ != ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) 		len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) 	ptr = tomoyo_find_namespace(domainname, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) 	if (ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) 		return ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) 	if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) 	entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) 	if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) 	ptr = tomoyo_find_namespace(domainname, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 	if (!ptr && tomoyo_memory_ok(entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) 		char *name = (char *) (entry + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 		ptr = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) 		memmove(name, domainname, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 		name[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) 		entry->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) 		tomoyo_init_policy_namespace(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) 		entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) 	mutex_unlock(&tomoyo_policy_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 	kfree(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) 	return ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)  * tomoyo_namespace_jump - Check for namespace jump.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)  * @domainname: Name of domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)  * Returns true if namespace differs, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static bool tomoyo_namespace_jump(const char *domainname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 	const char *namespace = tomoyo_current_namespace()->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) 	const int len = strlen(namespace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) 	return strncmp(domainname, namespace, len) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) 		(domainname[len] && domainname[len] != ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)  * tomoyo_assign_domain - Create a domain or a namespace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)  * @domainname: The name of domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)  * @transit:    True if transit to domain found or created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)  * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 						const bool transit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 	struct tomoyo_domain_info e = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) 	struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) 	bool created = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) 	if (entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) 		if (transit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) 			 * Since namespace is created at runtime, profiles may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 			 * not be created by the moment the process transits to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) 			 * that domain. Do not perform domain transition if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) 			 * profile for that domain is not yet created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) 			if (tomoyo_policy_loaded &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) 			    !entry->ns->profile_ptr[entry->profile])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) 				return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) 		return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) 	/* Requested domain does not exist. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) 	/* Don't create requested domain if domainname is invalid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) 	if (strlen(domainname) >= TOMOYO_EXEC_TMPSIZE - 10 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) 	    !tomoyo_correct_domain(domainname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) 	 * Since definition of profiles and acl_groups may differ across
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) 	 * namespaces, do not inherit "use_profile" and "use_group" settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) 	 * by automatically creating requested domain upon domain transition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) 	if (transit && tomoyo_namespace_jump(domainname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) 	e.ns = tomoyo_assign_namespace(domainname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) 	if (!e.ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) 	 * "use_profile" and "use_group" settings for automatically created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) 	 * domains are inherited from current domain. These are 0 for manually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) 	 * created domains.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) 	if (transit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 		const struct tomoyo_domain_info *domain = tomoyo_domain();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) 		e.profile = domain->profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) 		memcpy(e.group, domain->group, sizeof(e.group));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) 	e.domainname = tomoyo_get_name(domainname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) 	if (!e.domainname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) 	if (mutex_lock_interruptible(&tomoyo_policy_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) 	entry = tomoyo_find_domain(domainname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) 	if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) 		entry = tomoyo_commit_ok(&e, sizeof(e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) 		if (entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) 			INIT_LIST_HEAD(&entry->acl_info_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) 			list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) 			created = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) 	mutex_unlock(&tomoyo_policy_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) 	tomoyo_put_name(e.domainname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) 	if (entry && transit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) 		if (created) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) 			struct tomoyo_request_info r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) 			int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) 			tomoyo_init_request_info(&r, entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) 						 TOMOYO_MAC_FILE_EXECUTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) 			r.granted = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) 			tomoyo_write_log(&r, "use_profile %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) 					 entry->profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) 			for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) 				if (test_bit(i, entry->group))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) 					tomoyo_write_log(&r, "use_group %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) 							 i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) 			tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) 	return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)  * tomoyo_environ - Check permission for environment variable names.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)  * @ee: Pointer to "struct tomoyo_execve".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)  * Returns 0 on success, negative value otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) static int tomoyo_environ(struct tomoyo_execve *ee)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) 	struct tomoyo_request_info *r = &ee->r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) 	struct linux_binprm *bprm = ee->bprm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) 	/* env_page.data is allocated by tomoyo_dump_page(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) 	struct tomoyo_page_dump env_page = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) 	char *arg_ptr; /* Size is TOMOYO_EXEC_TMPSIZE bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) 	int arg_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) 	unsigned long pos = bprm->p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) 	int offset = pos % PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) 	int argv_count = bprm->argc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) 	int envp_count = bprm->envc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) 	int error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) 	ee->r.type = TOMOYO_MAC_ENVIRON;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) 	ee->r.profile = r->domain->profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) 	ee->r.mode = tomoyo_get_mode(r->domain->ns, ee->r.profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) 				     TOMOYO_MAC_ENVIRON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) 	if (!r->mode || !envp_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) 	arg_ptr = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) 	if (!arg_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) 	while (error == -ENOMEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) 		if (!tomoyo_dump_page(bprm, pos, &env_page))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) 		pos += PAGE_SIZE - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) 		/* Read. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) 		while (argv_count && offset < PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) 			if (!env_page.data[offset++])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) 				argv_count--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) 		if (argv_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) 			offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) 		while (offset < PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) 			const unsigned char c = env_page.data[offset++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) 			if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) 				if (c == '=') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) 					arg_ptr[arg_len++] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) 				} else if (c == '\\') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) 					arg_ptr[arg_len++] = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) 					arg_ptr[arg_len++] = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) 				} else if (c > ' ' && c < 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) 					arg_ptr[arg_len++] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) 					arg_ptr[arg_len++] = '\\';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) 					arg_ptr[arg_len++] = (c >> 6) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) 					arg_ptr[arg_len++]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) 						= ((c >> 3) & 7) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) 					arg_ptr[arg_len++] = (c & 7) + '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) 				arg_ptr[arg_len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) 			if (c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) 			if (tomoyo_env_perm(r, arg_ptr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) 				error = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) 			if (!--envp_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) 				error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) 			arg_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) 		offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) 	if (r->mode != TOMOYO_CONFIG_ENFORCING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) 		error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) 	kfree(env_page.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) 	kfree(arg_ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) 	return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)  * tomoyo_find_next_domain - Find a domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)  * @bprm: Pointer to "struct linux_binprm".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)  * Returns 0 on success, negative value otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)  * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int tomoyo_find_next_domain(struct linux_binprm *bprm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) 	struct tomoyo_domain_info *old_domain = tomoyo_domain();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) 	struct tomoyo_domain_info *domain = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) 	const char *original_name = bprm->filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) 	int retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) 	bool reject_on_transition_failure = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) 	const struct tomoyo_path_info *candidate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) 	struct tomoyo_path_info exename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) 	struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) 	if (!ee)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) 	ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) 	if (!ee->tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) 		kfree(ee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) 	/* ee->dump->data is allocated by tomoyo_dump_page(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) 	tomoyo_init_request_info(&ee->r, NULL, TOMOYO_MAC_FILE_EXECUTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) 	ee->r.ee = ee;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) 	ee->bprm = bprm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) 	ee->r.obj = &ee->obj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) 	ee->obj.path1 = bprm->file->f_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) 	/* Get symlink's pathname of program. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) 	retval = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) 	exename.name = tomoyo_realpath_nofollow(original_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) 	if (!exename.name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) 	tomoyo_fill_path_info(&exename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) 	/* Check 'aggregator' directive. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) 		struct tomoyo_aggregator *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) 		struct list_head *list =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) 			&old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) 		/* Check 'aggregator' directive. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) 		candidate = &exename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) 		list_for_each_entry_rcu(ptr, list, head.list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) 					srcu_read_lock_held(&tomoyo_ss)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) 			if (ptr->head.is_deleted ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) 			    !tomoyo_path_matches_pattern(&exename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) 							 ptr->original_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) 			candidate = ptr->aggregated_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) 	/* Check execute permission. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) 	retval = tomoyo_execute_permission(&ee->r, candidate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) 	if (retval == TOMOYO_RETRY_REQUEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) 		goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) 	if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) 	 * To be able to specify domainnames with wildcards, use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) 	 * pathname specified in the policy (which may contain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) 	 * wildcard) rather than the pathname passed to execve()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) 	 * (which never contains wildcard).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) 	if (ee->r.param.path.matched_path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) 		candidate = ee->r.param.path.matched_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) 	 * Check for domain transition preference if "file execute" matched.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) 	 * If preference is given, make execve() fail if domain transition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) 	 * has failed, for domain transition preference should be used with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) 	 * destination domain defined.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) 	if (ee->transition) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) 		const char *domainname = ee->transition->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) 		reject_on_transition_failure = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) 		if (!strcmp(domainname, "keep"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) 			goto force_keep_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) 		if (!strcmp(domainname, "child"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) 			goto force_child_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) 		if (!strcmp(domainname, "reset"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) 			goto force_reset_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) 		if (!strcmp(domainname, "initialize"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) 			goto force_initialize_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) 		if (!strcmp(domainname, "parent")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) 			char *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) 			strncpy(ee->tmp, old_domain->domainname->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) 				TOMOYO_EXEC_TMPSIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) 			cp = strrchr(ee->tmp, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) 			if (cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) 				*cp = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) 		} else if (*domainname == '<')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) 			strncpy(ee->tmp, domainname, TOMOYO_EXEC_TMPSIZE - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) 			snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) 				 old_domain->domainname->name, domainname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) 		goto force_jump_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) 	 * No domain transition preference specified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) 	 * Calculate domain to transit to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) 	switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) 				       candidate)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) 	case TOMOYO_TRANSITION_CONTROL_RESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) force_reset_domain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) 		/* Transit to the root of specified namespace. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) 		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) 			 candidate->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) 		 * Make execve() fail if domain transition across namespaces
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) 		 * has failed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) 		reject_on_transition_failure = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) 	case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) force_initialize_domain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) 		/* Transit to the child of current namespace's root. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) 		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) 			 old_domain->ns->name, candidate->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) 	case TOMOYO_TRANSITION_CONTROL_KEEP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) force_keep_domain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) 		/* Keep current domain. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) 		domain = old_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) 		if (old_domain == &tomoyo_kernel_domain &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) 		    !tomoyo_policy_loaded) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) 			 * Needn't to transit from kernel domain before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) 			 * starting /sbin/init. But transit from kernel domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) 			 * if executing initializers because they might start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) 			 * before /sbin/init.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) 			domain = old_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) force_child_domain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) 		/* Normal domain transition. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) 		snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) 			 old_domain->domainname->name, candidate->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) force_jump_domain:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) 	if (!domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) 		domain = tomoyo_assign_domain(ee->tmp, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) 	if (domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) 		retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) 	else if (reject_on_transition_failure) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) 		pr_warn("ERROR: Domain '%s' not ready.\n", ee->tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) 		retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) 	} else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) 		retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) 		retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) 		if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) 			old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) 			ee->r.granted = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) 			tomoyo_write_log(&ee->r, "%s", tomoyo_dif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) 					 [TOMOYO_DIF_TRANSITION_FAILED]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) 			pr_warn("ERROR: Domain '%s' not defined.\n", ee->tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) 	if (!domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) 		domain = old_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) 	/* Update reference count on "struct tomoyo_domain_info". */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) 		struct tomoyo_task *s = tomoyo_task(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) 		s->old_domain_info = s->domain_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) 		s->domain_info = domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) 		atomic_inc(&domain->users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) 	kfree(exename.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) 	if (!retval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) 		ee->r.domain = domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) 		retval = tomoyo_environ(ee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) 	kfree(ee->tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) 	kfree(ee->dump.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) 	kfree(ee);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) 	return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)  * tomoyo_dump_page - Dump a page to buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)  * @bprm: Pointer to "struct linux_binprm".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)  * @pos:  Location to dump.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)  * @dump: Poiner to "struct tomoyo_page_dump".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)  * Returns true on success, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) 		      struct tomoyo_page_dump *dump)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) 	struct page *page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) 	/* dump->data is released by tomoyo_find_next_domain(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) 	if (!dump->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) 		dump->data = kzalloc(PAGE_SIZE, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) 		if (!dump->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) 			return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 	/* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) #ifdef CONFIG_MMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) 	 * This is called at execve() time in order to dig around
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) 	 * in the argv/environment of the new proceess
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) 	 * (represented by bprm).  'current' is the process doing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) 	 * the execve().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) 	if (get_user_pages_remote(bprm->mm, pos, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) 				FOLL_FORCE, &page, NULL, NULL) <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) 		return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) 	page = bprm->page[pos / PAGE_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) 	if (page != dump->page) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) 		const unsigned int offset = pos % PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) 		 * Maybe kmap()/kunmap() should be used here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) 		 * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) 		 * So do I.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) 		char *kaddr = kmap_atomic(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) 		dump->page = page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) 		memcpy(dump->data + offset, kaddr + offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) 		       PAGE_SIZE - offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) 		kunmap_atomic(kaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) 	/* Same with put_arg_page(page) in fs/exec.c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) #ifdef CONFIG_MMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) 	put_page(page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) 	return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }