オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /trunk/1.8.x/ccs-patch/security/ccsecurity/memory.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2985 - (show annotations) (download) (as text)
Thu Sep 3 08:27:32 2009 UTC (14 years, 8 months ago) by kumaneko
Original Path: trunk/1.7.x/ccs-patch/security/ccsecurity/memory.c
File MIME type: text/x-csrc
File size: 9644 byte(s)
1.7.0-rc
1 /*
2 * security/ccsecurity/gc.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 *
6 * Version: 1.7.0 2009/09/03
7 *
8 * This file is applicable to both 2.4.30 and 2.6.11 and later.
9 * See README.ccs for ChangeLog.
10 *
11 */
12
13 #include "internal.h"
14
15 void ccs_warn_oom(const char *function)
16 {
17 /* Reduce error messages. */
18 static pid_t ccs_last_pid;
19 const pid_t pid = current->pid;
20 if (ccs_last_pid != pid) {
21 printk(KERN_WARNING "ERROR: Out of memory at %s.\n",
22 function);
23 ccs_last_pid = pid;
24 }
25 if (!ccs_policy_loaded)
26 panic("MAC Initialization failed.\n");
27 }
28
29 static atomic_t ccs_policy_memory_size;
30 static unsigned int ccs_quota_for_policy;
31
32 /**
33 * ccs_memory_ok - Check memory quota.
34 *
35 * @ptr: Pointer to allocated memory.
36 * @size: Size in byte.
37 *
38 * Returns true if @ptr is not NULL and quota not exceeded, false otehrwise.
39 */
40 bool ccs_memory_ok(const void *ptr, const unsigned int size)
41 {
42 size_t s = ccs_round2(size);
43 atomic_add(s, &ccs_policy_memory_size);
44 if (ptr && (!ccs_quota_for_policy ||
45 atomic_read(&ccs_policy_memory_size)
46 <= ccs_quota_for_policy))
47 return true;
48 atomic_sub(s, &ccs_policy_memory_size);
49 ccs_warn_oom(__func__);
50 return false;
51 }
52
53 /**
54 * ccs_commit_ok - Check memory quota.
55 *
56 * @ptr: Pointer to allocated memory.
57 * @data: Data to copy from.
58 * @size: Size in byte.
59 *
60 * Returns true if @ptr is not NULL and quota not exceeded, false otehrwise.
61 */
62 bool ccs_commit_ok(void *ptr, void *data, const unsigned int size)
63 {
64 if (ccs_memory_ok(ptr, size)) {
65 memmove(ptr, data, size);
66 memset(data, 0, size);
67 return true;
68 }
69 return false;
70 }
71
72
73 /**
74 * ccs_memory_free - Free memory for elements.
75 *
76 * @ptr: Pointer to allocated memory.
77 * @size: Size in byte.
78 */
79 void ccs_memory_free(const void *ptr, size_t size)
80 {
81 atomic_sub(ccs_round2(size), &ccs_policy_memory_size);
82 kfree(ptr);
83 }
84
85 static LIST_HEAD(ccs_address_list);
86
87 /**
88 * ccs_get_ipv6_address - Keep the given IPv6 address on the RAM.
89 *
90 * @addr: Pointer to "struct in6_addr".
91 *
92 * Returns pointer to "struct in6_addr" on success, NULL otherwise.
93 *
94 * The RAM is shared, so NEVER try to modify or kfree() the returned address.
95 */
96 const struct in6_addr *ccs_get_ipv6_address(const struct in6_addr *addr)
97 {
98 struct ccs_ipv6addr_entry *entry;
99 struct ccs_ipv6addr_entry *ptr;
100 int error = -ENOMEM;
101 if (!addr)
102 return NULL;
103 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
104 mutex_lock(&ccs_policy_lock);
105 list_for_each_entry(ptr, &ccs_address_list, list) {
106 if (memcmp(&ptr->addr, addr, sizeof(*addr)))
107 continue;
108 atomic_inc(&ptr->users);
109 error = 0;
110 break;
111 }
112 if (error && ccs_memory_ok(entry, sizeof(*entry))) {
113 ptr = entry;
114 ptr->addr = *addr;
115 atomic_set(&ptr->users, 1);
116 list_add_tail(&ptr->list, &ccs_address_list);
117 entry = NULL;
118 }
119 mutex_unlock(&ccs_policy_lock);
120 kfree(entry);
121 return ptr ? &ptr->addr : NULL;
122 }
123
124 /**
125 * ccs_put_ipv6_address - Delete the given IPv6 address on the RAM.
126 *
127 * @addr: Pointer to "struct in6_addr".
128 */
129 void ccs_put_ipv6_address(const struct in6_addr *addr)
130 {
131 struct ccs_ipv6addr_entry *ptr;
132 bool can_delete = false;
133 if (!addr)
134 return;
135 ptr = container_of(addr, struct ccs_ipv6addr_entry, addr);
136 mutex_lock(&ccs_policy_lock);
137 if (atomic_dec_and_test(&ptr->users)) {
138 list_del(&ptr->list);
139 can_delete = true;
140 }
141 mutex_unlock(&ccs_policy_lock);
142 if (can_delete)
143 ccs_memory_free(ptr, sizeof(*ptr));
144 }
145
146 /**
147 * ccs_put_condition - Delete memory for "struct ccs_condition".
148 *
149 * @cond: Pointer to "struct ccs_condition".
150 */
151 void ccs_put_condition(struct ccs_condition *cond)
152 {
153 const struct ccs_condition_element *condp;
154 struct ccs_number_union *numbers_p;
155 struct ccs_name_union *names_p;
156 const struct ccs_argv_entry *argv;
157 const struct ccs_envp_entry *envp;
158 u16 condc;
159 u16 numbers_count;
160 u16 names_count;
161 u16 argc;
162 u16 envc;
163 u16 i;
164 bool can_delete = false;
165 if (!cond)
166 return;
167 BUG_ON(atomic_read(&cond->users) <= 0);
168 mutex_lock(&ccs_policy_lock);
169 if (atomic_dec_and_test(&cond->users)) {
170 list_del(&cond->list);
171 can_delete = true;
172 }
173 mutex_unlock(&ccs_policy_lock);
174 if (!can_delete)
175 return;
176 condc = cond->condc;
177 numbers_count = cond->numbers_count;
178 names_count = cond->names_count;
179 argc = cond->argc;
180 envc = cond->envc;
181 condp = (const struct ccs_condition_element *) (cond + 1);
182 numbers_p = (struct ccs_number_union *) (condp + condc);
183 names_p = (struct ccs_name_union *) (numbers_p + numbers_count);
184 argv = (const struct ccs_argv_entry *) (names_p + names_count);
185 envp = (const struct ccs_envp_entry *) (argv + argc);
186 for (i = 0; i < numbers_count; i++)
187 ccs_put_number_union(numbers_p++);
188 for (i = 0; i < names_count; i++)
189 ccs_put_name_union(names_p++);
190 for (i = 0; i < argc; argv++, i++)
191 ccs_put_name(argv->value);
192 for (i = 0; i < envc; envp++, i++) {
193 ccs_put_name(envp->name);
194 ccs_put_name(envp->value);
195 }
196 ccs_memory_free(cond, cond->size);
197 }
198
199 #define CCS_MAX_HASH 256
200
201 /* Structure for string data. */
202 struct ccs_name_entry {
203 struct list_head list;
204 atomic_t users;
205 int size;
206 struct ccs_path_info entry;
207 };
208
209 /* The list for "struct ccs_name_entry". */
210 static struct list_head ccs_name_list[CCS_MAX_HASH];
211 static DEFINE_MUTEX(ccs_name_list_lock);
212
213 /**
214 * ccs_get_name - Allocate memory for string data.
215 *
216 * @name: The string to store into the permernent memory.
217 *
218 * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
219 */
220 const struct ccs_path_info *ccs_get_name(const char *name)
221 {
222 struct ccs_name_entry *ptr;
223 unsigned int hash;
224 int len;
225 int allocated_len;
226
227 if (!name)
228 return NULL;
229 len = strlen(name) + 1;
230 hash = full_name_hash((const unsigned char *) name, len - 1);
231 mutex_lock(&ccs_name_list_lock);
232 list_for_each_entry(ptr, &ccs_name_list[hash % CCS_MAX_HASH], list) {
233 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
234 continue;
235 atomic_inc(&ptr->users);
236 goto out;
237 }
238 allocated_len = ccs_round2(sizeof(*ptr) + len);
239 ptr = kzalloc(allocated_len, GFP_KERNEL);
240 if (!ptr || (ccs_quota_for_policy &&
241 atomic_read(&ccs_policy_memory_size) + allocated_len
242 > ccs_quota_for_policy)) {
243 kfree(ptr);
244 ptr = NULL;
245 ccs_warn_oom(__func__);
246 goto out;
247 }
248 atomic_add(allocated_len, &ccs_policy_memory_size);
249 ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
250 memmove((char *) ptr->entry.name, name, len);
251 atomic_set(&ptr->users, 1);
252 ccs_fill_path_info(&ptr->entry);
253 ptr->size = allocated_len;
254 list_add_tail(&ptr->list, &ccs_name_list[hash % CCS_MAX_HASH]);
255 out:
256 mutex_unlock(&ccs_name_list_lock);
257 return ptr ? &ptr->entry : NULL;
258 }
259
260 /**
261 * ccs_put_name - Delete shared memory for string data.
262 *
263 * @name: Pointer to "struct ccs_path_info".
264 */
265 void ccs_put_name(const struct ccs_path_info *name)
266 {
267 struct ccs_name_entry *ptr;
268 bool can_delete = false;
269 if (!name)
270 return;
271 ptr = container_of(name, struct ccs_name_entry, entry);
272 mutex_lock(&ccs_name_list_lock);
273 if (atomic_dec_and_test(&ptr->users)) {
274 list_del(&ptr->list);
275 can_delete = true;
276 }
277 mutex_unlock(&ccs_name_list_lock);
278 if (can_delete) {
279 atomic_sub(ptr->size, &ccs_policy_memory_size);
280 kfree(ptr);
281 }
282 }
283
284 /**
285 * ccs_realpath_init - Initialize realpath related code.
286 *
287 * Returns 0.
288 */
289 static int __init ccs_realpath_init(void)
290 {
291 int i;
292 for (i = 0; i < CCS_MAX_HASH; i++)
293 INIT_LIST_HEAD(&ccs_name_list[i]);
294 INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
295 ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
296 list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
297 if (ccs_find_domain(ROOT_NAME) != &ccs_kernel_domain)
298 panic("Can't register ccs_kernel_domain");
299 #ifdef CONFIG_CCSECURITY_BUILTIN_INITIALIZERS
300 {
301 /* Load built-in policy. */
302 static char ccs_builtin_initializers[] __initdata
303 = CONFIG_CCSECURITY_BUILTIN_INITIALIZERS;
304 char *cp = ccs_builtin_initializers;
305 ccs_normalize_line(cp);
306 while (cp && *cp) {
307 char *cp2 = strchr(cp, ' ');
308 if (cp2)
309 *cp2++ = '\0';
310 ccs_write_domain_initializer_policy(cp, false, false);
311 cp = cp2;
312 }
313 }
314 #endif
315 return 0;
316 }
317
318 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
319 __initcall(ccs_realpath_init);
320 #else
321 core_initcall(ccs_realpath_init);
322 #endif
323
324 unsigned int ccs_audit_log_memory_size;
325 unsigned int ccs_quota_for_audit_log;
326
327 unsigned int ccs_query_memory_size;
328 unsigned int ccs_quota_for_query;
329
330 /**
331 * ccs_read_memory_counter - Check for memory usage.
332 *
333 * @head: Pointer to "struct ccs_io_buffer".
334 */
335 void ccs_read_memory_counter(struct ccs_io_buffer *head)
336 {
337 const unsigned int usage[3] = {
338 atomic_read(&ccs_policy_memory_size),
339 ccs_audit_log_memory_size,
340 ccs_query_memory_size
341 };
342 const unsigned int quota[3] = {
343 ccs_quota_for_policy,
344 ccs_quota_for_audit_log,
345 ccs_quota_for_query
346 };
347 static const char *header[4] = {
348 "Policy: ",
349 "Audit logs: ",
350 "Query lists:",
351 "Total: "
352 };
353 unsigned int total = 0;
354 int i;
355 if (head->read_eof)
356 return;
357 for (i = 0; i < 3; i++) {
358 total += usage[i];
359 ccs_io_printf(head, "%s %10u", header[i], usage[i]);
360 if (quota[i])
361 ccs_io_printf(head, " (Quota: %10u)", quota[i]);
362 ccs_io_printf(head, "\n");
363 }
364 ccs_io_printf(head, "%s %10u\n", header[3], total);
365 head->read_eof = true;
366 }
367
368 /**
369 * ccs_write_memory_quota - Set memory quota.
370 *
371 * @head: Pointer to "struct ccs_io_buffer".
372 *
373 * Returns 0.
374 */
375 int ccs_write_memory_quota(struct ccs_io_buffer *head)
376 {
377 char *data = head->write_buf;
378 unsigned int size;
379 if (sscanf(data, "Policy: %u", &size) == 1)
380 ccs_quota_for_policy = size;
381 else if (sscanf(data, "Audit logs: %u", &size) == 1)
382 ccs_quota_for_audit_log = size;
383 else if (sscanf(data, "Query lists: %u", &size) == 1)
384 ccs_quota_for_query = size;
385 return 0;
386 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26