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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2894 - (hide annotations) (download) (as text)
Tue Aug 11 08:15:11 2009 UTC (14 years, 9 months ago) by kumaneko
Original Path: branches/ccs-patch/security/ccsecurity/memory.c
File MIME type: text/x-csrc
File size: 13810 byte(s)


1 kumaneko 2864 /*
2     * security/ccsecurity/gc.c
3     *
4     * Copyright (C) 2005-2009 NTT DATA CORPORATION
5     *
6 kumaneko 2869 * Version: 1.7.0-pre 2009/08/08
7 kumaneko 2864 *
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 kumaneko 2894 struct ccs_number_union *numbers_p;
244     struct ccs_name_union *names_p;
245 kumaneko 2864 const struct ccs_argv_entry *argv;
246     const struct ccs_envp_entry *envp;
247     u16 condc;
248 kumaneko 2894 u16 numbers_count;
249     u16 names_count;
250 kumaneko 2864 u16 argc;
251     u16 envc;
252     u16 i;
253     bool can_delete = false;
254     if (!cond)
255     return;
256     mutex_lock(&ccs_policy_lock);
257     if (atomic_dec_and_test(&cond->users)) {
258     list_del(&cond->list);
259     can_delete = true;
260     }
261     mutex_unlock(&ccs_policy_lock);
262     if (!can_delete)
263     return;
264     condc = cond->condc;
265 kumaneko 2894 numbers_count = cond->numbers_count;
266     names_count = cond->names_count;
267 kumaneko 2864 argc = cond->argc;
268     envc = cond->envc;
269     condp = (const struct ccs_condition_element *) (cond + 1);
270 kumaneko 2894 numbers_p = (struct ccs_number_union *) (condp + condc);
271     names_p = (struct ccs_name_union *) (numbers_p + numbers_count);
272     argv = (const struct ccs_argv_entry *) (names_p + names_count);
273 kumaneko 2864 envp = (const struct ccs_envp_entry *) (argv + argc);
274 kumaneko 2894 for (i = 0; i < cond->numbers_count; i++)
275     ccs_put_number_union(numbers_p++);
276     for (i = 0; i < cond->names_count; i++)
277     ccs_put_name_union(names_p++);
278 kumaneko 2864 for (i = 0; i < argc; argv++, i++)
279     ccs_put_name(argv->value);
280     for (i = 0; i < envc; envp++, i++) {
281     ccs_put_name(envp->name);
282     ccs_put_name(envp->value);
283     }
284     ccs_memory_free(cond, cond->size);
285     }
286    
287     static unsigned int ccs_string_memory_size;
288     static unsigned int ccs_quota_for_string;
289    
290 kumaneko 2892 #define CCS_MAX_HASH 256
291 kumaneko 2864
292     /* Structure for string data. */
293     struct ccs_name_entry {
294     struct list_head list;
295     atomic_t users;
296     int size;
297     struct ccs_path_info entry;
298     };
299    
300     /* The list for "struct ccs_name_entry". */
301 kumaneko 2892 static struct list_head ccs_name_list[CCS_MAX_HASH];
302 kumaneko 2864 static DEFINE_MUTEX(ccs_name_list_lock);
303    
304     /**
305     * ccs_get_name - Allocate memory for string data.
306     *
307     * @name: The string to store into the permernent memory.
308     *
309     * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
310     */
311     const struct ccs_path_info *ccs_get_name(const char *name)
312     {
313     struct ccs_name_entry *ptr;
314     unsigned int hash;
315     int len;
316     int allocated_len;
317    
318     if (!name)
319     return NULL;
320     len = strlen(name) + 1;
321     if (len > CCS_MAX_PATHNAME_LEN) {
322     printk(KERN_WARNING "ERROR: Name too long. (%s)\n", __func__);
323     return NULL;
324     }
325     hash = full_name_hash((const unsigned char *) name, len - 1);
326     /***** EXCLUSIVE SECTION START *****/
327     mutex_lock(&ccs_name_list_lock);
328 kumaneko 2892 list_for_each_entry(ptr, &ccs_name_list[hash % CCS_MAX_HASH], list) {
329 kumaneko 2864 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
330     continue;
331     atomic_inc(&ptr->users);
332     goto out;
333     }
334     ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL);
335     allocated_len = ptr ? sizeof(*ptr) + len : 0;
336     ccs_string_memory_size += allocated_len;
337     if (!allocated_len ||
338     (ccs_quota_for_string &&
339     ccs_string_memory_size > ccs_quota_for_string)) {
340     ccs_string_memory_size -= allocated_len;
341     kfree(ptr);
342     ptr = NULL;
343     printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);
344     if (!ccs_policy_loaded)
345     panic("MAC Initialization failed.\n");
346     goto out;
347     }
348     ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
349     memmove((char *) ptr->entry.name, name, len);
350     atomic_set(&ptr->users, 1);
351     ccs_fill_path_info(&ptr->entry);
352     ptr->size = allocated_len;
353 kumaneko 2892 list_add_tail(&ptr->list, &ccs_name_list[hash % CCS_MAX_HASH]);
354 kumaneko 2864 out:
355     mutex_unlock(&ccs_name_list_lock);
356     /***** EXCLUSIVE SECTION END *****/
357     return ptr ? &ptr->entry : NULL;
358     }
359    
360     /**
361     * ccs_put_name - Delete shared memory for string data.
362     *
363     * @name: Pointer to "struct ccs_path_info".
364     */
365     void ccs_put_name(const struct ccs_path_info *name)
366     {
367     struct ccs_name_entry *ptr;
368     bool can_delete = false;
369     if (!name)
370     return;
371     ptr = container_of(name, struct ccs_name_entry, entry);
372     /***** EXCLUSIVE SECTION START *****/
373     mutex_lock(&ccs_name_list_lock);
374     if (atomic_dec_and_test(&ptr->users)) {
375     list_del(&ptr->list);
376     ccs_string_memory_size -= ptr->size;
377     can_delete = true;
378     }
379     mutex_unlock(&ccs_name_list_lock);
380     /***** EXCLUSIVE SECTION END *****/
381     if (can_delete)
382     kfree(ptr);
383     }
384    
385     struct srcu_struct ccs_ss;
386    
387     /**
388     * ccs_realpath_init - Initialize realpath related code.
389     *
390     * Returns 0.
391     */
392     static int __init ccs_realpath_init(void)
393     {
394     int i;
395     /* Constraint for ccs_get_name(). */
396     if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE)
397     panic("Bad size.");
398     /* Constraint for "struct ccs_execve_entry"->tmp users. */
399     if (CCS_MAX_PATHNAME_LEN > CCS_EXEC_TMPSIZE)
400     panic("Bad size.");
401     if (init_srcu_struct(&ccs_ss))
402     panic("Out of memory.");
403 kumaneko 2892 for (i = 0; i < CCS_MAX_HASH; i++)
404 kumaneko 2864 INIT_LIST_HEAD(&ccs_name_list[i]);
405     INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
406     ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
407     list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
408     if (ccs_find_domain(ROOT_NAME) != &ccs_kernel_domain)
409     panic("Can't register ccs_kernel_domain");
410     #ifdef CONFIG_CCSECURITY_BUILTIN_INITIALIZERS
411     {
412     /* Load built-in policy. */
413     static char ccs_builtin_initializers[] __initdata
414     = CONFIG_CCSECURITY_BUILTIN_INITIALIZERS;
415     char *cp = ccs_builtin_initializers;
416     ccs_normalize_line(cp);
417     while (cp && *cp) {
418     char *cp2 = strchr(cp, ' ');
419     if (cp2)
420     *cp2++ = '\0';
421     ccs_write_domain_initializer_policy(cp, false, false);
422     cp = cp2;
423     }
424     }
425     #endif
426     return 0;
427     }
428    
429     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
430     __initcall(ccs_realpath_init);
431     #else
432     core_initcall(ccs_realpath_init);
433     #endif
434    
435     unsigned int ccs_audit_log_memory_size;
436     unsigned int ccs_quota_for_audit_log;
437    
438     unsigned int ccs_query_memory_size;
439     unsigned int ccs_quota_for_query;
440    
441     /**
442     * ccs_read_memory_counter - Check for memory usage.
443     *
444     * @head: Pointer to "struct ccs_io_buffer".
445     *
446     * Returns memory usage.
447     */
448     int ccs_read_memory_counter(struct ccs_io_buffer *head)
449     {
450     if (!head->read_eof) {
451     const unsigned int string = ccs_string_memory_size;
452     const unsigned int nonstring
453     = atomic_read(&ccs_non_string_memory_size);
454     const unsigned int audit_log = ccs_audit_log_memory_size;
455     const unsigned int query = ccs_query_memory_size;
456     char buffer[64];
457     memset(buffer, 0, sizeof(buffer));
458     if (ccs_quota_for_string)
459     snprintf(buffer, sizeof(buffer) - 1,
460     " (Quota: %10u)", ccs_quota_for_string);
461     else
462     buffer[0] = '\0';
463     ccs_io_printf(head, "Policy (string): %10u%s\n",
464     string, buffer);
465     if (ccs_quota_for_non_string)
466     snprintf(buffer, sizeof(buffer) - 1,
467     " (Quota: %10u)", ccs_quota_for_non_string);
468     else
469     buffer[0] = '\0';
470     ccs_io_printf(head, "Policy (non-string): %10u%s\n",
471     nonstring, buffer);
472     if (ccs_quota_for_audit_log)
473     snprintf(buffer, sizeof(buffer) - 1,
474     " (Quota: %10u)", ccs_quota_for_audit_log);
475     else
476     buffer[0] = '\0';
477     ccs_io_printf(head, "Audit logs: %10u%s\n",
478     audit_log, buffer);
479     if (ccs_quota_for_query)
480     snprintf(buffer, sizeof(buffer) - 1,
481     " (Quota: %10u)", ccs_quota_for_query);
482     else
483     buffer[0] = '\0';
484     ccs_io_printf(head, "Interactive enforcement: %10u%s\n",
485     query, buffer);
486     ccs_io_printf(head, "Total: %10u\n",
487     string + nonstring + audit_log + query);
488     head->read_eof = true;
489     }
490     return 0;
491     }
492    
493     /**
494     * ccs_write_memory_quota - Set memory quota.
495     *
496     * @head: Pointer to "struct ccs_io_buffer".
497     *
498     * Returns 0.
499     */
500     int ccs_write_memory_quota(struct ccs_io_buffer *head)
501     {
502     char *data = head->write_buf;
503     unsigned int size;
504     if (sscanf(data, "Policy (string): %u", &size) == 1)
505     ccs_quota_for_string = size;
506     else if (sscanf(data, "Policy (non-string): %u", &size) == 1)
507     ccs_quota_for_non_string = size;
508     else if (sscanf(data, "Audit logs: %u", &size) == 1)
509     ccs_quota_for_audit_log = size;
510     else if (sscanf(data, "Interactive enforcement: %u", &size) == 1)
511     ccs_quota_for_query = size;
512     return 0;
513     }

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