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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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