^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/memory.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 <linux/hash.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * tomoyo_warn_oom - Print out of memory warning message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * @function: Function's name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) void tomoyo_warn_oom(const char *function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* Reduce error messages. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static pid_t tomoyo_last_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) const pid_t pid = current->pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if (tomoyo_last_pid != pid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) pr_warn("ERROR: Out of memory at %s.\n", function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) tomoyo_last_pid = pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (!tomoyo_policy_loaded)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) panic("MAC Initialization failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Memoy currently used by policy/audit log/query. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) /* Memory quota for "policy"/"audit log"/"query". */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * tomoyo_memory_ok - Check memory quota.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * @ptr: Pointer to allocated memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * Returns true on success, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Returns true if @ptr is not NULL and quota not exceeded, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Caller holds tomoyo_policy_lock mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) bool tomoyo_memory_ok(void *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (ptr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) const size_t s = ksize(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (!tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) tomoyo_memory_quota[TOMOYO_MEMORY_POLICY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) tomoyo_warn_oom(__func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * tomoyo_commit_ok - Check memory quota.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * @data: Data to copy from.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * @size: Size in byte.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * Returns pointer to allocated memory on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * @data is zero-cleared on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * Caller holds tomoyo_policy_lock mutex.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) void *tomoyo_commit_ok(void *data, const unsigned int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) void *ptr = kzalloc(size, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (tomoyo_memory_ok(ptr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) memmove(ptr, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) memset(data, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) kfree(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * @param: Pointer to "struct tomoyo_acl_param".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * @idx: Index number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) const u8 idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct tomoyo_group e = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct tomoyo_group *group = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct list_head *list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) const char *group_name = tomoyo_read_token(param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) bool found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) e.group_name = tomoyo_get_name(group_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!e.group_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (mutex_lock_interruptible(&tomoyo_policy_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) list = ¶m->ns->group_list[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) list_for_each_entry(group, list, head.list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (e.group_name != group->group_name ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) atomic_read(&group->head.users) == TOMOYO_GC_IN_PROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) atomic_inc(&group->head.users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (!found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) INIT_LIST_HEAD(&entry->member_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) atomic_set(&entry->head.users, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) list_add_tail_rcu(&entry->head.list, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) group = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) mutex_unlock(&tomoyo_policy_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) tomoyo_put_name(e.group_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return found ? group : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * tomoyo_name_list is used for holding string data used by TOMOYO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * Since same string data is likely used for multiple times (e.g.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * "const struct tomoyo_path_info *".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * tomoyo_get_name - Allocate permanent memory for string data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @name: The string to store into the permernent memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) const struct tomoyo_path_info *tomoyo_get_name(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct tomoyo_name *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) unsigned int hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct list_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) len = strlen(name) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) hash = full_name_hash(NULL, (const unsigned char *) name, len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (mutex_lock_interruptible(&tomoyo_policy_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) list_for_each_entry(ptr, head, head.list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) atomic_inc(&ptr->head.users);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (tomoyo_memory_ok(ptr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) memmove((char *) ptr->entry.name, name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) atomic_set(&ptr->head.users, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) tomoyo_fill_path_info(&ptr->entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) list_add_tail(&ptr->head.list, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) kfree(ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) mutex_unlock(&tomoyo_policy_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return ptr ? &ptr->entry : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* Initial namespace.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct tomoyo_policy_namespace tomoyo_kernel_namespace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * tomoyo_mm_init - Initialize mm related code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) void __init tomoyo_mm_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) for (idx = 0; idx < TOMOYO_MAX_HASH; idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) INIT_LIST_HEAD(&tomoyo_name_list[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) tomoyo_kernel_namespace.name = "<kernel>";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) tomoyo_init_policy_namespace(&tomoyo_kernel_namespace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) tomoyo_kernel_domain.ns = &tomoyo_kernel_namespace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) tomoyo_kernel_domain.domainname = tomoyo_get_name("<kernel>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }