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 */ 18 void 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 /* Memory allocated for policy. */ 33 static atomic_t tomoyo_policy_memory_size; 34 /* Quota for holding policy. */ 35 static unsigned int tomoyo_quota_for_policy; 36 37 /** 38 * tomoyo_memory_ok - Check memory quota. 39 * 40 * @ptr: Pointer to allocated memory. 41 * 42 * Returns true on success, false otherwise. 43 * 44 * Returns true if @ptr is not NULL and quota not exceeded, false otherwise. 45 */ 46 bool tomoyo_memory_ok(void *ptr) 47 { 48 size_t s = ptr ? ksize(ptr) : 0; 49 atomic_add(s, &tomoyo_policy_memory_size); 50 if (ptr && (!tomoyo_quota_for_policy || 51 atomic_read(&tomoyo_policy_memory_size) 52 <= tomoyo_quota_for_policy)) { 53 memset(ptr, 0, s); 54 return true; 55 } 56 atomic_sub(s, &tomoyo_policy_memory_size); 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 void *tomoyo_commit_ok(void *data, const unsigned int size) 71 { 72 void *ptr = kzalloc(size, GFP_NOFS); 73 if (tomoyo_memory_ok(ptr)) { 74 memmove(ptr, data, size); 75 memset(data, 0, size); 76 return ptr; 77 } 78 kfree(ptr); 79 return NULL; 80 } 81 82 /** 83 * tomoyo_memory_free - Free memory for elements. 84 * 85 * @ptr: Pointer to allocated memory. 86 */ 87 void tomoyo_memory_free(void *ptr) 88 { 89 atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); 90 kfree(ptr); 91 } 92 93 /** 94 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". 95 * 96 * @group_name: The name of address group. 97 * @idx: Index number. 98 * 99 * Returns pointer to "struct tomoyo_group" on success, NULL otherwise. 100 */ 101 struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) 102 { 103 struct tomoyo_group e = { }; 104 struct tomoyo_group *group = NULL; 105 bool found = false; 106 if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) 107 return NULL; 108 e.group_name = tomoyo_get_name(group_name); 109 if (!e.group_name) 110 return NULL; 111 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 112 goto out; 113 list_for_each_entry(group, &tomoyo_group_list[idx], list) { 114 if (e.group_name != group->group_name) 115 continue; 116 atomic_inc(&group->users); 117 found = true; 118 break; 119 } 120 if (!found) { 121 struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); 122 if (entry) { 123 INIT_LIST_HEAD(&entry->member_list); 124 atomic_set(&entry->users, 1); 125 list_add_tail_rcu(&entry->list, 126 &tomoyo_group_list[idx]); 127 group = entry; 128 found = true; 129 } 130 } 131 mutex_unlock(&tomoyo_policy_lock); 132 out: 133 tomoyo_put_name(e.group_name); 134 return found ? group : NULL; 135 } 136 137 /* 138 * tomoyo_name_list is used for holding string data used by TOMOYO. 139 * Since same string data is likely used for multiple times (e.g. 140 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of 141 * "const struct tomoyo_path_info *". 142 */ 143 struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; 144 145 /** 146 * tomoyo_get_name - Allocate permanent memory for string data. 147 * 148 * @name: The string to store into the permernent memory. 149 * 150 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 151 */ 152 const struct tomoyo_path_info *tomoyo_get_name(const char *name) 153 { 154 struct tomoyo_name *ptr; 155 unsigned int hash; 156 int len; 157 int allocated_len; 158 struct list_head *head; 159 160 if (!name) 161 return NULL; 162 len = strlen(name) + 1; 163 hash = full_name_hash((const unsigned char *) name, len - 1); 164 head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; 165 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 166 return NULL; 167 list_for_each_entry(ptr, head, list) { 168 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) 169 continue; 170 atomic_inc(&ptr->users); 171 goto out; 172 } 173 ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); 174 allocated_len = ptr ? ksize(ptr) : 0; 175 if (!ptr || (tomoyo_quota_for_policy && 176 atomic_read(&tomoyo_policy_memory_size) + allocated_len 177 > tomoyo_quota_for_policy)) { 178 kfree(ptr); 179 ptr = NULL; 180 tomoyo_warn_oom(__func__); 181 goto out; 182 } 183 atomic_add(allocated_len, &tomoyo_policy_memory_size); 184 ptr->entry.name = ((char *) ptr) + sizeof(*ptr); 185 memmove((char *) ptr->entry.name, name, len); 186 atomic_set(&ptr->users, 1); 187 tomoyo_fill_path_info(&ptr->entry); 188 list_add_tail(&ptr->list, head); 189 out: 190 mutex_unlock(&tomoyo_policy_lock); 191 return ptr ? &ptr->entry : NULL; 192 } 193 194 /** 195 * tomoyo_mm_init - Initialize mm related code. 196 */ 197 void __init tomoyo_mm_init(void) 198 { 199 int idx; 200 201 for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) 202 INIT_LIST_HEAD(&tomoyo_policy_list[idx]); 203 for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++) 204 INIT_LIST_HEAD(&tomoyo_group_list[idx]); 205 for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) 206 INIT_LIST_HEAD(&tomoyo_name_list[idx]); 207 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); 208 tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); 209 list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); 210 idx = tomoyo_read_lock(); 211 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) 212 panic("Can't register tomoyo_kernel_domain"); 213 { 214 /* Load built-in policy. */ 215 tomoyo_write_transition_control("/sbin/hotplug", false, 216 TOMOYO_TRANSITION_CONTROL_INITIALIZE); 217 tomoyo_write_transition_control("/sbin/modprobe", false, 218 TOMOYO_TRANSITION_CONTROL_INITIALIZE); 219 } 220 tomoyo_read_unlock(idx); 221 } 222 223 224 /* Memory allocated for query lists. */ 225 unsigned int tomoyo_query_memory_size; 226 /* Quota for holding query lists. */ 227 unsigned int tomoyo_quota_for_query; 228 229 /** 230 * tomoyo_read_memory_counter - Check for memory usage in bytes. 231 * 232 * @head: Pointer to "struct tomoyo_io_buffer". 233 * 234 * Returns memory usage. 235 */ 236 void tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) 237 { 238 if (!head->r.eof) { 239 const unsigned int policy 240 = atomic_read(&tomoyo_policy_memory_size); 241 const unsigned int query = tomoyo_query_memory_size; 242 char buffer[64]; 243 244 memset(buffer, 0, sizeof(buffer)); 245 if (tomoyo_quota_for_policy) 246 snprintf(buffer, sizeof(buffer) - 1, 247 " (Quota: %10u)", 248 tomoyo_quota_for_policy); 249 else 250 buffer[0] = '\0'; 251 tomoyo_io_printf(head, "Policy: %10u%s\n", policy, 252 buffer); 253 if (tomoyo_quota_for_query) 254 snprintf(buffer, sizeof(buffer) - 1, 255 " (Quota: %10u)", 256 tomoyo_quota_for_query); 257 else 258 buffer[0] = '\0'; 259 tomoyo_io_printf(head, "Query lists: %10u%s\n", query, 260 buffer); 261 tomoyo_io_printf(head, "Total: %10u\n", policy + query); 262 head->r.eof = true; 263 } 264 } 265 266 /** 267 * tomoyo_write_memory_quota - Set memory quota. 268 * 269 * @head: Pointer to "struct tomoyo_io_buffer". 270 * 271 * Returns 0. 272 */ 273 int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) 274 { 275 char *data = head->write_buf; 276 unsigned int size; 277 278 if (sscanf(data, "Policy: %u", &size) == 1) 279 tomoyo_quota_for_policy = size; 280 else if (sscanf(data, "Query lists: %u", &size) == 1) 281 tomoyo_quota_for_query = size; 282 return 0; 283 } 284