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 return NULL; 79 } 80 81 /** 82 * tomoyo_memory_free - Free memory for elements. 83 * 84 * @ptr: Pointer to allocated memory. 85 */ 86 void tomoyo_memory_free(void *ptr) 87 { 88 atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); 89 kfree(ptr); 90 } 91 92 /* 93 * tomoyo_name_list is used for holding string data used by TOMOYO. 94 * Since same string data is likely used for multiple times (e.g. 95 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of 96 * "const struct tomoyo_path_info *". 97 */ 98 struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; 99 100 /** 101 * tomoyo_get_name - Allocate permanent memory for string data. 102 * 103 * @name: The string to store into the permernent memory. 104 * 105 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 106 */ 107 const struct tomoyo_path_info *tomoyo_get_name(const char *name) 108 { 109 struct tomoyo_name_entry *ptr; 110 unsigned int hash; 111 int len; 112 int allocated_len; 113 struct list_head *head; 114 115 if (!name) 116 return NULL; 117 len = strlen(name) + 1; 118 hash = full_name_hash((const unsigned char *) name, len - 1); 119 head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; 120 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 121 return NULL; 122 list_for_each_entry(ptr, head, list) { 123 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) 124 continue; 125 atomic_inc(&ptr->users); 126 goto out; 127 } 128 ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); 129 allocated_len = ptr ? ksize(ptr) : 0; 130 if (!ptr || (tomoyo_quota_for_policy && 131 atomic_read(&tomoyo_policy_memory_size) + allocated_len 132 > tomoyo_quota_for_policy)) { 133 kfree(ptr); 134 ptr = NULL; 135 tomoyo_warn_oom(__func__); 136 goto out; 137 } 138 atomic_add(allocated_len, &tomoyo_policy_memory_size); 139 ptr->entry.name = ((char *) ptr) + sizeof(*ptr); 140 memmove((char *) ptr->entry.name, name, len); 141 atomic_set(&ptr->users, 1); 142 tomoyo_fill_path_info(&ptr->entry); 143 list_add_tail(&ptr->list, head); 144 out: 145 mutex_unlock(&tomoyo_policy_lock); 146 return ptr ? &ptr->entry : NULL; 147 } 148 149 /** 150 * tomoyo_mm_init - Initialize mm related code. 151 */ 152 void __init tomoyo_mm_init(void) 153 { 154 int idx; 155 156 BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX); 157 for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) 158 INIT_LIST_HEAD(&tomoyo_name_list[idx]); 159 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); 160 tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); 161 list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); 162 idx = tomoyo_read_lock(); 163 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) 164 panic("Can't register tomoyo_kernel_domain"); 165 { 166 /* Load built-in policy. */ 167 tomoyo_write_domain_initializer_policy("/sbin/hotplug", 168 false, false); 169 tomoyo_write_domain_initializer_policy("/sbin/modprobe", 170 false, false); 171 } 172 tomoyo_read_unlock(idx); 173 } 174 175 176 /* Memory allocated for query lists. */ 177 unsigned int tomoyo_query_memory_size; 178 /* Quota for holding query lists. */ 179 unsigned int tomoyo_quota_for_query; 180 181 /** 182 * tomoyo_read_memory_counter - Check for memory usage in bytes. 183 * 184 * @head: Pointer to "struct tomoyo_io_buffer". 185 * 186 * Returns memory usage. 187 */ 188 int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) 189 { 190 if (!head->read_eof) { 191 const unsigned int policy 192 = atomic_read(&tomoyo_policy_memory_size); 193 const unsigned int query = tomoyo_query_memory_size; 194 char buffer[64]; 195 196 memset(buffer, 0, sizeof(buffer)); 197 if (tomoyo_quota_for_policy) 198 snprintf(buffer, sizeof(buffer) - 1, 199 " (Quota: %10u)", 200 tomoyo_quota_for_policy); 201 else 202 buffer[0] = '\0'; 203 tomoyo_io_printf(head, "Policy: %10u%s\n", policy, 204 buffer); 205 if (tomoyo_quota_for_query) 206 snprintf(buffer, sizeof(buffer) - 1, 207 " (Quota: %10u)", 208 tomoyo_quota_for_query); 209 else 210 buffer[0] = '\0'; 211 tomoyo_io_printf(head, "Query lists: %10u%s\n", query, 212 buffer); 213 tomoyo_io_printf(head, "Total: %10u\n", policy + query); 214 head->read_eof = true; 215 } 216 return 0; 217 } 218 219 /** 220 * tomoyo_write_memory_quota - Set memory quota. 221 * 222 * @head: Pointer to "struct tomoyo_io_buffer". 223 * 224 * Returns 0. 225 */ 226 int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) 227 { 228 char *data = head->write_buf; 229 unsigned int size; 230 231 if (sscanf(data, "Policy: %u", &size) == 1) 232 tomoyo_quota_for_policy = size; 233 else if (sscanf(data, "Query lists: %u", &size) == 1) 234 tomoyo_quota_for_query = size; 235 return 0; 236 } 237