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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2943 - (hide annotations) (download) (as text)
Mon Aug 24 04:58:42 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: 9735 byte(s)


1 kumaneko 2864 /*
2     * security/ccsecurity/gc.c
3     *
4     * Copyright (C) 2005-2009 NTT DATA CORPORATION
5     *
6 kumaneko 2943 * Version: 1.7.0-pre 2009/08/24
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 kumaneko 2932 void ccs_warn_oom(const char *function)
16 kumaneko 2908 {
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 kumaneko 2903 static atomic_t ccs_policy_memory_size;
30     static unsigned int ccs_quota_for_policy;
31 kumaneko 2864
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 kumaneko 2900 size_t s = ccs_round2(size);
43 kumaneko 2903 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 kumaneko 2864 return true;
48 kumaneko 2903 atomic_sub(s, &ccs_policy_memory_size);
49 kumaneko 2908 ccs_warn_oom(__func__);
50 kumaneko 2864 return false;
51     }
52    
53     /**
54 kumaneko 2900 * ccs_commit_ok - Check memory quota.
55 kumaneko 2864 *
56 kumaneko 2900 * @ptr: Pointer to allocated memory.
57     * @data: Data to copy from.
58     * @size: Size in byte.
59 kumaneko 2864 *
60 kumaneko 2900 * Returns true if @ptr is not NULL and quota not exceeded, false otehrwise.
61 kumaneko 2864 */
62 kumaneko 2900 bool ccs_commit_ok(void *ptr, void *data, const unsigned int size)
63 kumaneko 2864 {
64 kumaneko 2900 if (ccs_memory_ok(ptr, size)) {
65     memmove(ptr, data, size);
66     memset(data, 0, size);
67     return true;
68 kumaneko 2864 }
69 kumaneko 2900 return false;
70 kumaneko 2864 }
71    
72    
73     /**
74 kumaneko 2900 * ccs_memory_free - Free memory for elements.
75 kumaneko 2864 *
76 kumaneko 2900 * @ptr: Pointer to allocated memory.
77     * @size: Size in byte.
78 kumaneko 2864 */
79 kumaneko 2900 void ccs_memory_free(const void *ptr, size_t size)
80 kumaneko 2864 {
81 kumaneko 2903 atomic_sub(ccs_round2(size), &ccs_policy_memory_size);
82 kumaneko 2900 kfree(ptr);
83 kumaneko 2864 }
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 kumaneko 2894 struct ccs_number_union *numbers_p;
155     struct ccs_name_union *names_p;
156 kumaneko 2864 const struct ccs_argv_entry *argv;
157     const struct ccs_envp_entry *envp;
158     u16 condc;
159 kumaneko 2894 u16 numbers_count;
160     u16 names_count;
161 kumaneko 2864 u16 argc;
162     u16 envc;
163     u16 i;
164     bool can_delete = false;
165     if (!cond)
166     return;
167 kumaneko 2900 BUG_ON(atomic_read(&cond->users) <= 0);
168 kumaneko 2864 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 kumaneko 2894 numbers_count = cond->numbers_count;
178     names_count = cond->names_count;
179 kumaneko 2864 argc = cond->argc;
180     envc = cond->envc;
181     condp = (const struct ccs_condition_element *) (cond + 1);
182 kumaneko 2894 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 kumaneko 2864 envp = (const struct ccs_envp_entry *) (argv + argc);
186 kumaneko 2900 for (i = 0; i < numbers_count; i++)
187 kumaneko 2894 ccs_put_number_union(numbers_p++);
188 kumaneko 2900 for (i = 0; i < names_count; i++)
189 kumaneko 2894 ccs_put_name_union(names_p++);
190 kumaneko 2864 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 kumaneko 2892 #define CCS_MAX_HASH 256
200 kumaneko 2864
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 kumaneko 2892 static struct list_head ccs_name_list[CCS_MAX_HASH];
211 kumaneko 2864 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 kumaneko 2892 list_for_each_entry(ptr, &ccs_name_list[hash % CCS_MAX_HASH], list) {
233 kumaneko 2864 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
234     continue;
235     atomic_inc(&ptr->users);
236     goto out;
237     }
238 kumaneko 2900 allocated_len = ccs_round2(sizeof(*ptr) + len);
239     ptr = kzalloc(allocated_len, GFP_KERNEL);
240 kumaneko 2903 if (!ptr || (ccs_quota_for_policy &&
241     atomic_read(&ccs_policy_memory_size) + allocated_len
242     > ccs_quota_for_policy)) {
243 kumaneko 2864 kfree(ptr);
244     ptr = NULL;
245 kumaneko 2908 ccs_warn_oom(__func__);
246 kumaneko 2864 goto out;
247     }
248 kumaneko 2903 atomic_add(allocated_len, &ccs_policy_memory_size);
249 kumaneko 2864 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 kumaneko 2892 list_add_tail(&ptr->list, &ccs_name_list[hash % CCS_MAX_HASH]);
255 kumaneko 2864 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 kumaneko 2903 if (can_delete) {
279     atomic_sub(ptr->size, &ccs_policy_memory_size);
280 kumaneko 2864 kfree(ptr);
281 kumaneko 2903 }
282 kumaneko 2864 }
283    
284     struct srcu_struct ccs_ss;
285    
286     /**
287     * ccs_realpath_init - Initialize realpath related code.
288     *
289     * Returns 0.
290     */
291     static int __init ccs_realpath_init(void)
292     {
293     int i;
294     if (init_srcu_struct(&ccs_ss))
295     panic("Out of memory.");
296 kumaneko 2892 for (i = 0; i < CCS_MAX_HASH; i++)
297 kumaneko 2864 INIT_LIST_HEAD(&ccs_name_list[i]);
298     INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
299     ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
300     list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
301     if (ccs_find_domain(ROOT_NAME) != &ccs_kernel_domain)
302     panic("Can't register ccs_kernel_domain");
303     #ifdef CONFIG_CCSECURITY_BUILTIN_INITIALIZERS
304     {
305     /* Load built-in policy. */
306     static char ccs_builtin_initializers[] __initdata
307     = CONFIG_CCSECURITY_BUILTIN_INITIALIZERS;
308     char *cp = ccs_builtin_initializers;
309     ccs_normalize_line(cp);
310     while (cp && *cp) {
311     char *cp2 = strchr(cp, ' ');
312     if (cp2)
313     *cp2++ = '\0';
314     ccs_write_domain_initializer_policy(cp, false, false);
315     cp = cp2;
316     }
317     }
318     #endif
319     return 0;
320     }
321    
322     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
323     __initcall(ccs_realpath_init);
324     #else
325     core_initcall(ccs_realpath_init);
326     #endif
327    
328     unsigned int ccs_audit_log_memory_size;
329     unsigned int ccs_quota_for_audit_log;
330    
331     unsigned int ccs_query_memory_size;
332     unsigned int ccs_quota_for_query;
333    
334     /**
335     * ccs_read_memory_counter - Check for memory usage.
336     *
337     * @head: Pointer to "struct ccs_io_buffer".
338     */
339 kumaneko 2943 void ccs_read_memory_counter(struct ccs_io_buffer *head)
340 kumaneko 2864 {
341 kumaneko 2943 const unsigned int usage[3] = {
342     atomic_read(&ccs_policy_memory_size),
343     ccs_audit_log_memory_size,
344     ccs_query_memory_size
345     };
346     const unsigned int quota[3] = {
347     ccs_quota_for_policy,
348     ccs_quota_for_audit_log,
349     ccs_quota_for_query
350     };
351     static const char *header[4] = {
352     "Policy: ",
353     "Audit logs: ",
354     "Query lists:",
355     "Total: "
356     };
357     unsigned int total = 0;
358     int i;
359     if (head->read_eof)
360     return;
361     for (i = 0; i < 3; i++) {
362     total += usage[i];
363     ccs_io_printf(head, "%s %10u", header[i], usage[i]);
364     if (quota[i])
365     ccs_io_printf(head, " (Quota: %10u)", quota[i]);
366     ccs_io_printf(head, "\n");
367 kumaneko 2864 }
368 kumaneko 2943 ccs_io_printf(head, "%s %10u\n", header[3], total);
369     head->read_eof = true;
370 kumaneko 2864 }
371    
372     /**
373     * ccs_write_memory_quota - Set memory quota.
374     *
375     * @head: Pointer to "struct ccs_io_buffer".
376     *
377     * Returns 0.
378     */
379     int ccs_write_memory_quota(struct ccs_io_buffer *head)
380     {
381     char *data = head->write_buf;
382     unsigned int size;
383 kumaneko 2903 if (sscanf(data, "Policy: %u", &size) == 1)
384     ccs_quota_for_policy = size;
385 kumaneko 2864 else if (sscanf(data, "Audit logs: %u", &size) == 1)
386     ccs_quota_for_audit_log = size;
387 kumaneko 2903 else if (sscanf(data, "Query lists: %u", &size) == 1)
388 kumaneko 2864 ccs_quota_for_query = size;
389     return 0;
390     }

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