memory.c revision 32997144fd9925fc4d506a16990a0c405f766526
1/* 2 * security/tomoyo/memory.c 3 * 4 * Memory management functions for TOMOYO. 5 * 6 * Copyright (C) 2005-2010 NTT DATA CORPORATION 7 */ 8 9#include <linux/hash.h> 10#include <linux/slab.h> 11#include "common.h" 12 13/** 14 * tomoyo_warn_oom - Print out of memory warning message. 15 * 16 * @function: Function's name. 17 */ 18void tomoyo_warn_oom(const char *function) 19{ 20 /* Reduce error messages. */ 21 static pid_t tomoyo_last_pid; 22 const pid_t pid = current->pid; 23 if (tomoyo_last_pid != pid) { 24 printk(KERN_WARNING "ERROR: Out of memory at %s.\n", 25 function); 26 tomoyo_last_pid = pid; 27 } 28 if (!tomoyo_policy_loaded) 29 panic("MAC Initialization failed.\n"); 30} 31 32/* Memoy currently used by policy/audit log/query. */ 33unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; 34/* Memory quota for "policy"/"audit log"/"query". */ 35unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; 36 37/* Memory allocated for policy. */ 38static atomic_t tomoyo_policy_memory_size; 39/* Quota for holding policy. */ 40static unsigned int tomoyo_quota_for_policy; 41 42/** 43 * tomoyo_memory_ok - Check memory quota. 44 * 45 * @ptr: Pointer to allocated memory. 46 * 47 * Returns true on success, false otherwise. 48 * 49 * Returns true if @ptr is not NULL and quota not exceeded, false otherwise. 50 */ 51bool tomoyo_memory_ok(void *ptr) 52{ 53 size_t s = ptr ? ksize(ptr) : 0; 54 atomic_add(s, &tomoyo_policy_memory_size); 55 if (ptr && (!tomoyo_quota_for_policy || 56 atomic_read(&tomoyo_policy_memory_size) 57 <= tomoyo_quota_for_policy)) { 58 memset(ptr, 0, s); 59 return true; 60 } 61 atomic_sub(s, &tomoyo_policy_memory_size); 62 tomoyo_warn_oom(__func__); 63 return false; 64} 65 66/** 67 * tomoyo_commit_ok - Check memory quota. 68 * 69 * @data: Data to copy from. 70 * @size: Size in byte. 71 * 72 * Returns pointer to allocated memory on success, NULL otherwise. 73 * @data is zero-cleared on success. 74 */ 75void *tomoyo_commit_ok(void *data, const unsigned int size) 76{ 77 void *ptr = kzalloc(size, GFP_NOFS); 78 if (tomoyo_memory_ok(ptr)) { 79 memmove(ptr, data, size); 80 memset(data, 0, size); 81 return ptr; 82 } 83 kfree(ptr); 84 return NULL; 85} 86 87/** 88 * tomoyo_memory_free - Free memory for elements. 89 * 90 * @ptr: Pointer to allocated memory. 91 */ 92void tomoyo_memory_free(void *ptr) 93{ 94 atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); 95 kfree(ptr); 96} 97 98/** 99 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". 100 * 101 * @param: Pointer to "struct tomoyo_acl_param". 102 * @idx: Index number. 103 * 104 * Returns pointer to "struct tomoyo_group" on success, NULL otherwise. 105 */ 106struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, 107 const u8 idx) 108{ 109 struct tomoyo_group e = { }; 110 struct tomoyo_group *group = NULL; 111 struct list_head *list; 112 const char *group_name = tomoyo_read_token(param); 113 bool found = false; 114 if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) 115 return NULL; 116 e.group_name = tomoyo_get_name(group_name); 117 if (!e.group_name) 118 return NULL; 119 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 120 goto out; 121 list = &tomoyo_group_list[idx]; 122 list_for_each_entry(group, list, head.list) { 123 if (e.group_name != group->group_name) 124 continue; 125 atomic_inc(&group->head.users); 126 found = true; 127 break; 128 } 129 if (!found) { 130 struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); 131 if (entry) { 132 INIT_LIST_HEAD(&entry->member_list); 133 atomic_set(&entry->head.users, 1); 134 list_add_tail_rcu(&entry->head.list, list); 135 group = entry; 136 found = true; 137 } 138 } 139 mutex_unlock(&tomoyo_policy_lock); 140out: 141 tomoyo_put_name(e.group_name); 142 return found ? group : NULL; 143} 144 145/* 146 * tomoyo_name_list is used for holding string data used by TOMOYO. 147 * Since same string data is likely used for multiple times (e.g. 148 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of 149 * "const struct tomoyo_path_info *". 150 */ 151struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; 152 153/** 154 * tomoyo_get_name - Allocate permanent memory for string data. 155 * 156 * @name: The string to store into the permernent memory. 157 * 158 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 159 */ 160const struct tomoyo_path_info *tomoyo_get_name(const char *name) 161{ 162 struct tomoyo_name *ptr; 163 unsigned int hash; 164 int len; 165 int allocated_len; 166 struct list_head *head; 167 168 if (!name) 169 return NULL; 170 len = strlen(name) + 1; 171 hash = full_name_hash((const unsigned char *) name, len - 1); 172 head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; 173 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 174 return NULL; 175 list_for_each_entry(ptr, head, head.list) { 176 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) 177 continue; 178 atomic_inc(&ptr->head.users); 179 goto out; 180 } 181 ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); 182 allocated_len = ptr ? ksize(ptr) : 0; 183 if (!ptr || (tomoyo_quota_for_policy && 184 atomic_read(&tomoyo_policy_memory_size) + allocated_len 185 > tomoyo_quota_for_policy)) { 186 kfree(ptr); 187 ptr = NULL; 188 tomoyo_warn_oom(__func__); 189 goto out; 190 } 191 atomic_add(allocated_len, &tomoyo_policy_memory_size); 192 ptr->entry.name = ((char *) ptr) + sizeof(*ptr); 193 memmove((char *) ptr->entry.name, name, len); 194 atomic_set(&ptr->head.users, 1); 195 tomoyo_fill_path_info(&ptr->entry); 196 list_add_tail(&ptr->head.list, head); 197 out: 198 mutex_unlock(&tomoyo_policy_lock); 199 return ptr ? &ptr->entry : NULL; 200} 201 202/** 203 * tomoyo_mm_init - Initialize mm related code. 204 */ 205void __init tomoyo_mm_init(void) 206{ 207 int idx; 208 209 for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) 210 INIT_LIST_HEAD(&tomoyo_policy_list[idx]); 211 for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++) 212 INIT_LIST_HEAD(&tomoyo_group_list[idx]); 213 for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) 214 INIT_LIST_HEAD(&tomoyo_name_list[idx]); 215 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); 216 for (idx = 0; idx < TOMOYO_MAX_ACL_GROUPS; idx++) 217 INIT_LIST_HEAD(&tomoyo_acl_group[idx]); 218 tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); 219 list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); 220 idx = tomoyo_read_lock(); 221 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) 222 panic("Can't register tomoyo_kernel_domain"); 223#if 0 224 /* Will be replaced with tomoyo_load_builtin_policy(). */ 225 { 226 /* Load built-in policy. */ 227 tomoyo_write_transition_control("/sbin/hotplug", false, 228 TOMOYO_TRANSITION_CONTROL_INITIALIZE); 229 tomoyo_write_transition_control("/sbin/modprobe", false, 230 TOMOYO_TRANSITION_CONTROL_INITIALIZE); 231 } 232#endif 233 tomoyo_read_unlock(idx); 234} 235 236 237/* Memory allocated for query lists. */ 238unsigned int tomoyo_query_memory_size; 239/* Quota for holding query lists. */ 240unsigned int tomoyo_quota_for_query; 241 242/** 243 * tomoyo_read_memory_counter - Check for memory usage in bytes. 244 * 245 * @head: Pointer to "struct tomoyo_io_buffer". 246 * 247 * Returns memory usage. 248 */ 249void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) 250{ 251 if (!head->r.eof) { 252 const unsigned int policy 253 = atomic_read(&tomoyo_policy_memory_size); 254 const unsigned int query = tomoyo_query_memory_size; 255 char buffer[64]; 256 257 memset(buffer, 0, sizeof(buffer)); 258 if (tomoyo_quota_for_policy) 259 snprintf(buffer, sizeof(buffer) - 1, 260 " (Quota: %10u)", 261 tomoyo_quota_for_policy); 262 else 263 buffer[0] = '\0'; 264 tomoyo_io_printf(head, "Policy: %10u%s\n", policy, 265 buffer); 266 if (tomoyo_quota_for_query) 267 snprintf(buffer, sizeof(buffer) - 1, 268 " (Quota: %10u)", 269 tomoyo_quota_for_query); 270 else 271 buffer[0] = '\0'; 272 tomoyo_io_printf(head, "Query lists: %10u%s\n", query, 273 buffer); 274 tomoyo_io_printf(head, "Total: %10u\n", policy + query); 275 head->r.eof = true; 276 } 277} 278 279/** 280 * tomoyo_write_memory_quota - Set memory quota. 281 * 282 * @head: Pointer to "struct tomoyo_io_buffer". 283 * 284 * Returns 0. 285 */ 286int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) 287{ 288 char *data = head->write_buf; 289 unsigned int size; 290 291 if (sscanf(data, "Policy: %u", &size) == 1) 292 tomoyo_quota_for_policy = size; 293 else if (sscanf(data, "Query lists: %u", &size) == 1) 294 tomoyo_quota_for_query = size; 295 return 0; 296} 297