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