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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2948 - (show annotations) (download) (as text)
Mon Aug 24 11:59:18 2009 UTC (14 years, 9 months ago) by kumaneko
Original Path: trunk/1.7.x/ccs-patch/security/ccsecurity/memory.c
File MIME type: text/x-csrc
File size: 9754 byte(s)


1 /*
2 * security/ccsecurity/gc.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 *
6 * Version: 1.7.0-pre 2009/08/24
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 /* Lock for GC. */
285 struct srcu_struct ccs_ss;
286
287 /**
288 * ccs_realpath_init - Initialize realpath related code.
289 *
290 * Returns 0.
291 */
292 static int __init ccs_realpath_init(void)
293 {
294 int i;
295 if (init_srcu_struct(&ccs_ss))
296 panic("Out of memory.");
297 for (i = 0; i < CCS_MAX_HASH; i++)
298 INIT_LIST_HEAD(&ccs_name_list[i]);
299 INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
300 ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
301 list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
302 if (ccs_find_domain(ROOT_NAME) != &ccs_kernel_domain)
303 panic("Can't register ccs_kernel_domain");
304 #ifdef CONFIG_CCSECURITY_BUILTIN_INITIALIZERS
305 {
306 /* Load built-in policy. */
307 static char ccs_builtin_initializers[] __initdata
308 = CONFIG_CCSECURITY_BUILTIN_INITIALIZERS;
309 char *cp = ccs_builtin_initializers;
310 ccs_normalize_line(cp);
311 while (cp && *cp) {
312 char *cp2 = strchr(cp, ' ');
313 if (cp2)
314 *cp2++ = '\0';
315 ccs_write_domain_initializer_policy(cp, false, false);
316 cp = cp2;
317 }
318 }
319 #endif
320 return 0;
321 }
322
323 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
324 __initcall(ccs_realpath_init);
325 #else
326 core_initcall(ccs_realpath_init);
327 #endif
328
329 unsigned int ccs_audit_log_memory_size;
330 unsigned int ccs_quota_for_audit_log;
331
332 unsigned int ccs_query_memory_size;
333 unsigned int ccs_quota_for_query;
334
335 /**
336 * ccs_read_memory_counter - Check for memory usage.
337 *
338 * @head: Pointer to "struct ccs_io_buffer".
339 */
340 void ccs_read_memory_counter(struct ccs_io_buffer *head)
341 {
342 const unsigned int usage[3] = {
343 atomic_read(&ccs_policy_memory_size),
344 ccs_audit_log_memory_size,
345 ccs_query_memory_size
346 };
347 const unsigned int quota[3] = {
348 ccs_quota_for_policy,
349 ccs_quota_for_audit_log,
350 ccs_quota_for_query
351 };
352 static const char *header[4] = {
353 "Policy: ",
354 "Audit logs: ",
355 "Query lists:",
356 "Total: "
357 };
358 unsigned int total = 0;
359 int i;
360 if (head->read_eof)
361 return;
362 for (i = 0; i < 3; i++) {
363 total += usage[i];
364 ccs_io_printf(head, "%s %10u", header[i], usage[i]);
365 if (quota[i])
366 ccs_io_printf(head, " (Quota: %10u)", quota[i]);
367 ccs_io_printf(head, "\n");
368 }
369 ccs_io_printf(head, "%s %10u\n", header[3], total);
370 head->read_eof = true;
371 }
372
373 /**
374 * ccs_write_memory_quota - Set memory quota.
375 *
376 * @head: Pointer to "struct ccs_io_buffer".
377 *
378 * Returns 0.
379 */
380 int ccs_write_memory_quota(struct ccs_io_buffer *head)
381 {
382 char *data = head->write_buf;
383 unsigned int size;
384 if (sscanf(data, "Policy: %u", &size) == 1)
385 ccs_quota_for_policy = size;
386 else if (sscanf(data, "Audit logs: %u", &size) == 1)
387 ccs_quota_for_audit_log = size;
388 else if (sscanf(data, "Query lists: %u", &size) == 1)
389 ccs_quota_for_query = size;
390 return 0;
391 }

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