^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 = ¶m->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 = ¶m->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) }