diff options
Diffstat (limited to 'security/tomoyo/memory.c')
-rw-r--r-- | security/tomoyo/memory.c | 173 |
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. */ |
33 | static atomic_t tomoyo_policy_memory_size; | 31 | static DEFINE_SPINLOCK(tomoyo_policy_memory_lock); |
34 | /* Quota for holding policy. */ | 32 | /* Memoy currently used by policy/audit log/query. */ |
35 | static unsigned int tomoyo_quota_for_policy; | 33 | unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; |
34 | /* Memory quota for "policy"/"audit log"/"query". */ | ||
35 | unsigned 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 | */ |
46 | bool tomoyo_memory_ok(void *ptr) | 46 | bool 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 | */ |
87 | void tomoyo_memory_free(void *ptr) | 92 | void 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 | */ |
101 | struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) | 109 | struct 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 = ¶m->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: | 143 | out: |
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); | 194 | out: |
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.*/ | ||
200 | struct 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 | */ |
197 | void __init tomoyo_mm_init(void) | 205 | void __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. */ | ||
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 | } | 216 | } |