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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2864 - (hide annotations) (download) (as text)
Fri Aug 7 06:40:37 2009 UTC (14 years, 10 months ago) by kumaneko
Original Path: branches/ccs-patch/security/ccsecurity/memory.c
File MIME type: text/x-csrc
File size: 14249 byte(s)


1 kumaneko 2864 /*
2     * security/ccsecurity/gc.c
3     *
4     * Copyright (C) 2005-2009 NTT DATA CORPORATION
5     *
6     * Version: 1.7.0-pre 2009/07/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     static atomic_t ccs_non_string_memory_size;
16     static unsigned int ccs_quota_for_non_string;
17    
18     /**
19     * ccs_memory_ok - Check memory quota.
20     *
21     * @ptr: Pointer to allocated memory.
22     * @size: Size in byte.
23     *
24     * Returns true if @ptr is not NULL and quota not exceeded, false otehrwise.
25     */
26     bool ccs_memory_ok(const void *ptr, const unsigned int size)
27     {
28     atomic_add(size, &ccs_non_string_memory_size);
29     if (ptr && (!ccs_quota_for_non_string ||
30     atomic_read(&ccs_non_string_memory_size)
31     <= ccs_quota_for_non_string))
32     return true;
33     atomic_sub(size, &ccs_non_string_memory_size);
34     printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);
35     if (!ccs_policy_loaded)
36     panic("MAC Initialization failed.\n");
37     return false;
38     }
39    
40     /**
41     * ccs_memory_free - Free memory for elements.
42     *
43     * @ptr: Pointer to allocated memory.
44     * @size: Size in byte.
45     */
46     void ccs_memory_free(const void *ptr, size_t size)
47     {
48     atomic_sub(size, &ccs_non_string_memory_size);
49     kfree(ptr);
50     }
51    
52     /**
53     * ccs_put_path_group - Delete memory for "struct ccs_path_group".
54     *
55     * @group: Pointer to "struct ccs_path_group".
56     */
57     void ccs_put_path_group(struct ccs_path_group *group)
58     {
59     struct ccs_path_group_member *member;
60     struct ccs_path_group_member *next_member;
61     LIST_HEAD(q);
62     bool can_delete_group = false;
63     if (!group)
64     return;
65     mutex_lock(&ccs_policy_lock);
66     if (atomic_dec_and_test(&group->users)) {
67     list_for_each_entry_safe(member, next_member,
68     &group->path_group_member_list,
69     list) {
70     if (!member->is_deleted)
71     break;
72     list_del(&member->list);
73     list_add(&member->list, &q);
74     }
75     if (list_empty(&group->path_group_member_list)) {
76     list_del(&group->list);
77     can_delete_group = true;
78     }
79     }
80     mutex_unlock(&ccs_policy_lock);
81     list_for_each_entry_safe(member, next_member, &q, list) {
82     list_del(&member->list);
83     ccs_put_name(member->member_name);
84     ccs_memory_free(member, sizeof(*member));
85     }
86     if (can_delete_group) {
87     ccs_put_name(group->group_name);
88     ccs_memory_free(group, sizeof(*group));
89     }
90     }
91    
92     /**
93     * ccs_put_address_group - Delete memory for "struct ccs_address_group_entry".
94     *
95     * @group: Pointer to "struct ccs_address_group_entry".
96     */
97     void ccs_put_address_group(struct ccs_address_group_entry *group)
98     {
99     struct ccs_address_group_member *member;
100     struct ccs_address_group_member *next_member;
101     LIST_HEAD(q);
102     bool can_delete_group = false;
103     if (!group)
104     return;
105     mutex_lock(&ccs_policy_lock);
106     if (atomic_dec_and_test(&group->users)) {
107     list_for_each_entry_safe(member, next_member,
108     &group->address_group_member_list,
109     list) {
110     if (!member->is_deleted)
111     break;
112     list_del(&member->list);
113     list_add(&member->list, &q);
114     }
115     if (list_empty(&group->address_group_member_list)) {
116     list_del(&group->list);
117     can_delete_group = true;
118     }
119     }
120     mutex_unlock(&ccs_policy_lock);
121     list_for_each_entry_safe(member, next_member, &q, list) {
122     list_del(&member->list);
123     if (member->is_ipv6) {
124     ccs_put_ipv6_address(member->min.ipv6);
125     ccs_put_ipv6_address(member->max.ipv6);
126     }
127     ccs_memory_free(member, sizeof(*member));
128     }
129     if (can_delete_group) {
130     ccs_put_name(group->group_name);
131     ccs_memory_free(group, sizeof(*group));
132     }
133     }
134    
135     /**
136     * ccs_put_number_group - Delete memory for "struct ccs_number_group".
137     *
138     * @group: Pointer to "struct ccs_number_group".
139     */
140     void ccs_put_number_group(struct ccs_number_group *group)
141     {
142     struct ccs_number_group_member *member;
143     struct ccs_number_group_member *next_member;
144     LIST_HEAD(q);
145     bool can_delete_group = false;
146     if (!group)
147     return;
148     mutex_lock(&ccs_policy_lock);
149     if (atomic_dec_and_test(&group->users)) {
150     list_for_each_entry_safe(member, next_member,
151     &group->number_group_member_list,
152     list) {
153     if (!member->is_deleted)
154     break;
155     list_del(&member->list);
156     list_add(&member->list, &q);
157     }
158     if (list_empty(&group->number_group_member_list)) {
159     list_del(&group->list);
160     can_delete_group = true;
161     }
162     }
163     mutex_unlock(&ccs_policy_lock);
164     list_for_each_entry_safe(member, next_member, &q, list) {
165     list_del(&member->list);
166     ccs_memory_free(member, sizeof(*member));
167     }
168     if (can_delete_group) {
169     ccs_put_name(group->group_name);
170     ccs_memory_free(group, sizeof(*group));
171     }
172     }
173    
174     static LIST_HEAD(ccs_address_list);
175    
176     /**
177     * ccs_get_ipv6_address - Keep the given IPv6 address on the RAM.
178     *
179     * @addr: Pointer to "struct in6_addr".
180     *
181     * Returns pointer to "struct in6_addr" on success, NULL otherwise.
182     *
183     * The RAM is shared, so NEVER try to modify or kfree() the returned address.
184     */
185     const struct in6_addr *ccs_get_ipv6_address(const struct in6_addr *addr)
186     {
187     struct ccs_ipv6addr_entry *entry;
188     struct ccs_ipv6addr_entry *ptr;
189     int error = -ENOMEM;
190     if (!addr)
191     return NULL;
192     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
193     mutex_lock(&ccs_policy_lock);
194     list_for_each_entry(ptr, &ccs_address_list, list) {
195     if (memcmp(&ptr->addr, addr, sizeof(*addr)))
196     continue;
197     atomic_inc(&ptr->users);
198     error = 0;
199     break;
200     }
201     if (error && ccs_memory_ok(entry, sizeof(*entry))) {
202     ptr = entry;
203     ptr->addr = *addr;
204     atomic_set(&ptr->users, 1);
205     list_add_tail(&ptr->list, &ccs_address_list);
206     entry = NULL;
207     }
208     mutex_unlock(&ccs_policy_lock);
209     kfree(entry);
210     return ptr ? &ptr->addr : NULL;
211     }
212    
213     /**
214     * ccs_put_ipv6_address - Delete the given IPv6 address on the RAM.
215     *
216     * @addr: Pointer to "struct in6_addr".
217     */
218     void ccs_put_ipv6_address(const struct in6_addr *addr)
219     {
220     struct ccs_ipv6addr_entry *ptr;
221     bool can_delete = false;
222     if (!addr)
223     return;
224     ptr = container_of(addr, struct ccs_ipv6addr_entry, addr);
225     mutex_lock(&ccs_policy_lock);
226     if (atomic_dec_and_test(&ptr->users)) {
227     list_del(&ptr->list);
228     can_delete = true;
229     }
230     mutex_unlock(&ccs_policy_lock);
231     if (can_delete)
232     ccs_memory_free(ptr, sizeof(*ptr));
233     }
234    
235     /**
236     * ccs_put_condition - Delete memory for "struct ccs_condition".
237     *
238     * @cond: Pointer to "struct ccs_condition".
239     */
240     void ccs_put_condition(struct ccs_condition *cond)
241     {
242     const struct ccs_condition_element *condp;
243     const unsigned long *ulong_p;
244     struct ccs_number_group **number_group_p;
245     const struct ccs_path_info **path_info_p;
246     struct ccs_path_group **path_group_p;
247     const struct ccs_argv_entry *argv;
248     const struct ccs_envp_entry *envp;
249     u16 condc;
250     u16 number_group_count;
251     u16 path_info_count;
252     u16 path_group_count;
253     u16 argc;
254     u16 envc;
255     u16 i;
256     bool can_delete = false;
257     if (!cond)
258     return;
259     mutex_lock(&ccs_policy_lock);
260     if (atomic_dec_and_test(&cond->users)) {
261     list_del(&cond->list);
262     can_delete = true;
263     }
264     mutex_unlock(&ccs_policy_lock);
265     if (!can_delete)
266     return;
267     condc = cond->condc;
268     number_group_count = cond->number_group_count;
269     path_info_count = cond->path_info_count;
270     path_group_count = cond->path_group_count;
271     argc = cond->argc;
272     envc = cond->envc;
273     condp = (const struct ccs_condition_element *) (cond + 1);
274     ulong_p = (unsigned long *) (condp + condc);
275     number_group_p = (struct ccs_number_group **)
276     (ulong_p + cond->ulong_count);
277     path_info_p = (const struct ccs_path_info **)
278     (number_group_p + number_group_count);
279     path_group_p = (struct ccs_path_group **)
280     (path_info_p + path_info_count);
281     argv = (const struct ccs_argv_entry *)
282     (path_group_p + path_group_count);
283     envp = (const struct ccs_envp_entry *) (argv + argc);
284     for (i = 0; i < cond->number_group_count; i++)
285     ccs_put_number_group(*number_group_p++);
286     for (i = 0; i < cond->path_info_count; i++)
287     ccs_put_name(*path_info_p++);
288     for (i = 0; i < cond->path_group_count; i++)
289     ccs_put_path_group(*path_group_p++);
290     for (i = 0; i < argc; argv++, i++)
291     ccs_put_name(argv->value);
292     for (i = 0; i < envc; envp++, i++) {
293     ccs_put_name(envp->name);
294     ccs_put_name(envp->value);
295     }
296     ccs_memory_free(cond, cond->size);
297     }
298    
299     static unsigned int ccs_string_memory_size;
300     static unsigned int ccs_quota_for_string;
301    
302     #define MAX_HASH 256
303    
304     /* Structure for string data. */
305     struct ccs_name_entry {
306     struct list_head list;
307     atomic_t users;
308     int size;
309     struct ccs_path_info entry;
310     };
311    
312     /* The list for "struct ccs_name_entry". */
313     static struct list_head ccs_name_list[MAX_HASH];
314     static DEFINE_MUTEX(ccs_name_list_lock);
315    
316     /**
317     * ccs_get_name - Allocate memory for string data.
318     *
319     * @name: The string to store into the permernent memory.
320     *
321     * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
322     */
323     const struct ccs_path_info *ccs_get_name(const char *name)
324     {
325     struct ccs_name_entry *ptr;
326     unsigned int hash;
327     int len;
328     int allocated_len;
329    
330     if (!name)
331     return NULL;
332     len = strlen(name) + 1;
333     if (len > CCS_MAX_PATHNAME_LEN) {
334     printk(KERN_WARNING "ERROR: Name too long. (%s)\n", __func__);
335     return NULL;
336     }
337     hash = full_name_hash((const unsigned char *) name, len - 1);
338     /***** EXCLUSIVE SECTION START *****/
339     mutex_lock(&ccs_name_list_lock);
340     list_for_each_entry(ptr, &ccs_name_list[hash % MAX_HASH], list) {
341     if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
342     continue;
343     atomic_inc(&ptr->users);
344     goto out;
345     }
346     ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL);
347     allocated_len = ptr ? sizeof(*ptr) + len : 0;
348     ccs_string_memory_size += allocated_len;
349     if (!allocated_len ||
350     (ccs_quota_for_string &&
351     ccs_string_memory_size > ccs_quota_for_string)) {
352     ccs_string_memory_size -= allocated_len;
353     kfree(ptr);
354     ptr = NULL;
355     printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);
356     if (!ccs_policy_loaded)
357     panic("MAC Initialization failed.\n");
358     goto out;
359     }
360     ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
361     memmove((char *) ptr->entry.name, name, len);
362     atomic_set(&ptr->users, 1);
363     ccs_fill_path_info(&ptr->entry);
364     ptr->size = allocated_len;
365     list_add_tail(&ptr->list, &ccs_name_list[hash % MAX_HASH]);
366     out:
367     mutex_unlock(&ccs_name_list_lock);
368     /***** EXCLUSIVE SECTION END *****/
369     return ptr ? &ptr->entry : NULL;
370     }
371    
372     /**
373     * ccs_put_name - Delete shared memory for string data.
374     *
375     * @name: Pointer to "struct ccs_path_info".
376     */
377     void ccs_put_name(const struct ccs_path_info *name)
378     {
379     struct ccs_name_entry *ptr;
380     bool can_delete = false;
381     if (!name)
382     return;
383     ptr = container_of(name, struct ccs_name_entry, entry);
384     /***** EXCLUSIVE SECTION START *****/
385     mutex_lock(&ccs_name_list_lock);
386     if (atomic_dec_and_test(&ptr->users)) {
387     list_del(&ptr->list);
388     ccs_string_memory_size -= ptr->size;
389     can_delete = true;
390     }
391     mutex_unlock(&ccs_name_list_lock);
392     /***** EXCLUSIVE SECTION END *****/
393     if (can_delete)
394     kfree(ptr);
395     }
396    
397     struct srcu_struct ccs_ss;
398    
399     /**
400     * ccs_realpath_init - Initialize realpath related code.
401     *
402     * Returns 0.
403     */
404     static int __init ccs_realpath_init(void)
405     {
406     int i;
407     /* Constraint for ccs_get_name(). */
408     if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE)
409     panic("Bad size.");
410     /* Constraint for "struct ccs_execve_entry"->tmp users. */
411     if (CCS_MAX_PATHNAME_LEN > CCS_EXEC_TMPSIZE)
412     panic("Bad size.");
413     if (init_srcu_struct(&ccs_ss))
414     panic("Out of memory.");
415     for (i = 0; i < MAX_HASH; i++)
416     INIT_LIST_HEAD(&ccs_name_list[i]);
417     INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
418     ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
419     list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
420     if (ccs_find_domain(ROOT_NAME) != &ccs_kernel_domain)
421     panic("Can't register ccs_kernel_domain");
422     #ifdef CONFIG_CCSECURITY_BUILTIN_INITIALIZERS
423     {
424     /* Load built-in policy. */
425     static char ccs_builtin_initializers[] __initdata
426     = CONFIG_CCSECURITY_BUILTIN_INITIALIZERS;
427     char *cp = ccs_builtin_initializers;
428     ccs_normalize_line(cp);
429     while (cp && *cp) {
430     char *cp2 = strchr(cp, ' ');
431     if (cp2)
432     *cp2++ = '\0';
433     ccs_write_domain_initializer_policy(cp, false, false);
434     cp = cp2;
435     }
436     }
437     #endif
438     return 0;
439     }
440    
441     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
442     __initcall(ccs_realpath_init);
443     #else
444     core_initcall(ccs_realpath_init);
445     #endif
446    
447     unsigned int ccs_audit_log_memory_size;
448     unsigned int ccs_quota_for_audit_log;
449    
450     unsigned int ccs_query_memory_size;
451     unsigned int ccs_quota_for_query;
452    
453     /**
454     * ccs_read_memory_counter - Check for memory usage.
455     *
456     * @head: Pointer to "struct ccs_io_buffer".
457     *
458     * Returns memory usage.
459     */
460     int ccs_read_memory_counter(struct ccs_io_buffer *head)
461     {
462     if (!head->read_eof) {
463     const unsigned int string = ccs_string_memory_size;
464     const unsigned int nonstring
465     = atomic_read(&ccs_non_string_memory_size);
466     const unsigned int audit_log = ccs_audit_log_memory_size;
467     const unsigned int query = ccs_query_memory_size;
468     char buffer[64];
469     memset(buffer, 0, sizeof(buffer));
470     if (ccs_quota_for_string)
471     snprintf(buffer, sizeof(buffer) - 1,
472     " (Quota: %10u)", ccs_quota_for_string);
473     else
474     buffer[0] = '\0';
475     ccs_io_printf(head, "Policy (string): %10u%s\n",
476     string, buffer);
477     if (ccs_quota_for_non_string)
478     snprintf(buffer, sizeof(buffer) - 1,
479     " (Quota: %10u)", ccs_quota_for_non_string);
480     else
481     buffer[0] = '\0';
482     ccs_io_printf(head, "Policy (non-string): %10u%s\n",
483     nonstring, buffer);
484     if (ccs_quota_for_audit_log)
485     snprintf(buffer, sizeof(buffer) - 1,
486     " (Quota: %10u)", ccs_quota_for_audit_log);
487     else
488     buffer[0] = '\0';
489     ccs_io_printf(head, "Audit logs: %10u%s\n",
490     audit_log, buffer);
491     if (ccs_quota_for_query)
492     snprintf(buffer, sizeof(buffer) - 1,
493     " (Quota: %10u)", ccs_quota_for_query);
494     else
495     buffer[0] = '\0';
496     ccs_io_printf(head, "Interactive enforcement: %10u%s\n",
497     query, buffer);
498     ccs_io_printf(head, "Total: %10u\n",
499     string + nonstring + audit_log + query);
500     head->read_eof = true;
501     }
502     return 0;
503     }
504    
505     /**
506     * ccs_write_memory_quota - Set memory quota.
507     *
508     * @head: Pointer to "struct ccs_io_buffer".
509     *
510     * Returns 0.
511     */
512     int ccs_write_memory_quota(struct ccs_io_buffer *head)
513     {
514     char *data = head->write_buf;
515     unsigned int size;
516     if (sscanf(data, "Policy (string): %u", &size) == 1)
517     ccs_quota_for_string = size;
518     else if (sscanf(data, "Policy (non-string): %u", &size) == 1)
519     ccs_quota_for_non_string = size;
520     else if (sscanf(data, "Audit logs: %u", &size) == 1)
521     ccs_quota_for_audit_log = size;
522     else if (sscanf(data, "Interactive enforcement: %u", &size) == 1)
523     ccs_quota_for_query = size;
524     return 0;
525     }

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