aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo/memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo/memory.c')
-rw-r--r--security/tomoyo/memory.c173
1 files changed, 53 insertions, 120 deletions
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c
index 42a7b1ba8cbf..7a56051146c2 100644
--- a/security/tomoyo/memory.c
+++ b/security/tomoyo/memory.c
@@ -1,9 +1,7 @@
1/* 1/*
2 * security/tomoyo/memory.c 2 * security/tomoyo/memory.c
3 * 3 *
4 * Memory management functions for TOMOYO. 4 * Copyright (C) 2005-2011 NTT DATA CORPORATION
5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 */ 5 */
8 6
9#include <linux/hash.h> 7#include <linux/hash.h>
@@ -29,10 +27,12 @@ void tomoyo_warn_oom(const char *function)
29 panic("MAC Initialization failed.\n"); 27 panic("MAC Initialization failed.\n");
30} 28}
31 29
32/* Memory allocated for policy. */ 30/* Lock for protecting tomoyo_memory_used. */
33static atomic_t tomoyo_policy_memory_size; 31static DEFINE_SPINLOCK(tomoyo_policy_memory_lock);
34/* Quota for holding policy. */ 32/* Memoy currently used by policy/audit log/query. */
35static unsigned int tomoyo_quota_for_policy; 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 36
37/** 37/**
38 * tomoyo_memory_ok - Check memory quota. 38 * tomoyo_memory_ok - Check memory quota.
@@ -45,15 +45,20 @@ static unsigned int tomoyo_quota_for_policy;
45 */ 45 */
46bool tomoyo_memory_ok(void *ptr) 46bool tomoyo_memory_ok(void *ptr)
47{ 47{
48 size_t s = ptr ? ksize(ptr) : 0; 48 if (ptr) {
49 atomic_add(s, &tomoyo_policy_memory_size); 49 const size_t s = ksize(ptr);
50 if (ptr && (!tomoyo_quota_for_policy || 50 bool result;
51 atomic_read(&tomoyo_policy_memory_size) 51 spin_lock(&tomoyo_policy_memory_lock);
52 <= tomoyo_quota_for_policy)) { 52 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s;
53 memset(ptr, 0, s); 53 result = !tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] ||
54 return true; 54 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <=
55 tomoyo_memory_quota[TOMOYO_MEMORY_POLICY];
56 if (!result)
57 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;
58 spin_unlock(&tomoyo_policy_memory_lock);
59 if (result)
60 return true;
55 } 61 }
56 atomic_sub(s, &tomoyo_policy_memory_size);
57 tomoyo_warn_oom(__func__); 62 tomoyo_warn_oom(__func__);
58 return false; 63 return false;
59} 64}
@@ -86,22 +91,28 @@ void *tomoyo_commit_ok(void *data, const unsigned int size)
86 */ 91 */
87void tomoyo_memory_free(void *ptr) 92void tomoyo_memory_free(void *ptr)
88{ 93{
89 atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); 94 size_t s = ksize(ptr);
95 spin_lock(&tomoyo_policy_memory_lock);
96 tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s;
97 spin_unlock(&tomoyo_policy_memory_lock);
90 kfree(ptr); 98 kfree(ptr);
91} 99}
92 100
93/** 101/**
94 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". 102 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
95 * 103 *
96 * @group_name: The name of address group. 104 * @param: Pointer to "struct tomoyo_acl_param".
97 * @idx: Index number. 105 * @idx: Index number.
98 * 106 *
99 * Returns pointer to "struct tomoyo_group" on success, NULL otherwise. 107 * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.
100 */ 108 */
101struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) 109struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
110 const u8 idx)
102{ 111{
103 struct tomoyo_group e = { }; 112 struct tomoyo_group e = { };
104 struct tomoyo_group *group = NULL; 113 struct tomoyo_group *group = NULL;
114 struct list_head *list;
115 const char *group_name = tomoyo_read_token(param);
105 bool found = false; 116 bool found = false;
106 if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) 117 if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
107 return NULL; 118 return NULL;
@@ -110,10 +121,11 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
110 return NULL; 121 return NULL;
111 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 122 if (mutex_lock_interruptible(&tomoyo_policy_lock))
112 goto out; 123 goto out;
113 list_for_each_entry(group, &tomoyo_group_list[idx], list) { 124 list = &param->ns->group_list[idx];
125 list_for_each_entry(group, list, head.list) {
114 if (e.group_name != group->group_name) 126 if (e.group_name != group->group_name)
115 continue; 127 continue;
116 atomic_inc(&group->users); 128 atomic_inc(&group->head.users);
117 found = true; 129 found = true;
118 break; 130 break;
119 } 131 }
@@ -121,15 +133,14 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
121 struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); 133 struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e));
122 if (entry) { 134 if (entry) {
123 INIT_LIST_HEAD(&entry->member_list); 135 INIT_LIST_HEAD(&entry->member_list);
124 atomic_set(&entry->users, 1); 136 atomic_set(&entry->head.users, 1);
125 list_add_tail_rcu(&entry->list, 137 list_add_tail_rcu(&entry->head.list, list);
126 &tomoyo_group_list[idx]);
127 group = entry; 138 group = entry;
128 found = true; 139 found = true;
129 } 140 }
130 } 141 }
131 mutex_unlock(&tomoyo_policy_lock); 142 mutex_unlock(&tomoyo_policy_lock);
132 out: 143out:
133 tomoyo_put_name(e.group_name); 144 tomoyo_put_name(e.group_name);
134 return found ? group : NULL; 145 return found ? group : NULL;
135} 146}
@@ -154,7 +165,6 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
154 struct tomoyo_name *ptr; 165 struct tomoyo_name *ptr;
155 unsigned int hash; 166 unsigned int hash;
156 int len; 167 int len;
157 int allocated_len;
158 struct list_head *head; 168 struct list_head *head;
159 169
160 if (!name) 170 if (!name)
@@ -164,120 +174,43 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
164 head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; 174 head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
165 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 175 if (mutex_lock_interruptible(&tomoyo_policy_lock))
166 return NULL; 176 return NULL;
167 list_for_each_entry(ptr, head, list) { 177 list_for_each_entry(ptr, head, head.list) {
168 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) 178 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
169 continue; 179 continue;
170 atomic_inc(&ptr->users); 180 atomic_inc(&ptr->head.users);
171 goto out; 181 goto out;
172 } 182 }
173 ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); 183 ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
174 allocated_len = ptr ? ksize(ptr) : 0; 184 if (tomoyo_memory_ok(ptr)) {
175 if (!ptr || (tomoyo_quota_for_policy && 185 ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
176 atomic_read(&tomoyo_policy_memory_size) + allocated_len 186 memmove((char *) ptr->entry.name, name, len);
177 > tomoyo_quota_for_policy)) { 187 atomic_set(&ptr->head.users, 1);
188 tomoyo_fill_path_info(&ptr->entry);
189 list_add_tail(&ptr->head.list, head);
190 } else {
178 kfree(ptr); 191 kfree(ptr);
179 ptr = NULL; 192 ptr = NULL;
180 tomoyo_warn_oom(__func__);
181 goto out;
182 } 193 }
183 atomic_add(allocated_len, &tomoyo_policy_memory_size); 194out:
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); 195 mutex_unlock(&tomoyo_policy_lock);
191 return ptr ? &ptr->entry : NULL; 196 return ptr ? &ptr->entry : NULL;
192} 197}
193 198
199/* Initial namespace.*/
200struct tomoyo_policy_namespace tomoyo_kernel_namespace;
201
194/** 202/**
195 * tomoyo_mm_init - Initialize mm related code. 203 * tomoyo_mm_init - Initialize mm related code.
196 */ 204 */
197void __init tomoyo_mm_init(void) 205void __init tomoyo_mm_init(void)
198{ 206{
199 int idx; 207 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++) 208 for (idx = 0; idx < TOMOYO_MAX_HASH; idx++)
206 INIT_LIST_HEAD(&tomoyo_name_list[idx]); 209 INIT_LIST_HEAD(&tomoyo_name_list[idx]);
210 tomoyo_kernel_namespace.name = "<kernel>";
211 tomoyo_init_policy_namespace(&tomoyo_kernel_namespace);
212 tomoyo_kernel_domain.ns = &tomoyo_kernel_namespace;
207 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); 213 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
208 tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); 214 tomoyo_kernel_domain.domainname = tomoyo_get_name("<kernel>");
209 list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); 215 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. */
225unsigned int tomoyo_query_memory_size;
226/* Quota for holding query lists. */
227unsigned 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 */
236void 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 */
273int 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} 216}