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

Subversion リポジトリの参照

Contents of /trunk/1.7.x/ccs-patch/security/ccsecurity/realpath.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2690 - (show annotations) (download) (as text)
Wed Jun 24 04:50:19 2009 UTC (14 years, 11 months ago) by kumaneko
Original Path: branches/ccs-patch/fs/realpath.c
File MIME type: text/x-csrc
File size: 42929 byte(s)


1 /*
2 * fs/realpath.c
3 *
4 * Get the canonicalized absolute pathnames. The basis for SAKURA and TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 1.6.8 2009/05/28
9 *
10 * This file is applicable to both 2.4.30 and 2.6.11 and later.
11 * See README.ccs for ChangeLog.
12 *
13 */
14 #include <linux/string.h>
15 #include <linux/mm.h>
16 #include <linux/utime.h>
17 #include <linux/file.h>
18 #include <linux/smp_lock.h>
19 #include <linux/module.h>
20 #include <linux/slab.h>
21 #include <asm/uaccess.h>
22 #include <asm/atomic.h>
23 #include <linux/version.h>
24 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
25 #include <linux/namei.h>
26 #include <linux/mount.h>
27 static const int ccs_lookup_flags = LOOKUP_FOLLOW;
28 #else
29 static const int ccs_lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE;
30 #endif
31 #include <linux/proc_fs.h>
32 #include <linux/ccs_common.h>
33 #include <linux/realpath.h>
34 #include <net/sock.h>
35
36 /**
37 * ccs_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
38 *
39 * @dentry: Pointer to "struct dentry".
40 * @vfsmnt: Pointer to "struct vfsmount".
41 * @buffer: Pointer to buffer to return value in.
42 * @buflen: Sizeof @buffer.
43 *
44 * Returns 0 on success, -ENOMEM otherwise.
45 *
46 * Caller holds the dcache_lock and vfsmount_lock.
47 * Based on __d_path() in fs/dcache.c
48 *
49 * If dentry is a directory, trailing '/' is appended.
50 * Characters out of 0x20 < c < 0x7F range are converted to
51 * \ooo style octal string.
52 * Character \ is converted to \\ string.
53 */
54 static int ccs_get_absolute_path(struct dentry *dentry, struct vfsmount *vfsmnt,
55 char *buffer, int buflen)
56 {
57 /***** CRITICAL SECTION START *****/
58 char *start = buffer;
59 char *end = buffer + buflen;
60 bool is_dir = (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode));
61
62 if (buflen < 256)
63 goto out;
64
65 *--end = '\0';
66 buflen--;
67
68 for (;;) {
69 struct dentry *parent;
70
71 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
72 /* Global root? */
73 if (vfsmnt->mnt_parent == vfsmnt)
74 break;
75 dentry = vfsmnt->mnt_mountpoint;
76 vfsmnt = vfsmnt->mnt_parent;
77 continue;
78 }
79 if (is_dir) {
80 is_dir = false;
81 *--end = '/';
82 buflen--;
83 }
84 parent = dentry->d_parent;
85 {
86 const char *sp = dentry->d_name.name;
87 const char *cp = sp + dentry->d_name.len - 1;
88 unsigned char c;
89
90 /*
91 * Exception: Use /proc/self/ rather than
92 * /proc/\$/ for current process.
93 */
94 if (IS_ROOT(parent) && *sp > '0' && *sp <= '9' &&
95 parent->d_sb &&
96 parent->d_sb->s_magic == PROC_SUPER_MAGIC) {
97 char *ep;
98 const pid_t pid
99 = (pid_t) simple_strtoul(sp, &ep, 10);
100 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
101 const pid_t tgid
102 = task_tgid_nr_ns(current,
103 dentry->d_sb->
104 s_fs_info);
105 if (!*ep && pid == tgid && tgid) {
106 sp = "self";
107 cp = sp + 3;
108 }
109 #else
110 if (!*ep && pid == sys_getpid()) {
111 sp = "self";
112 cp = sp + 3;
113 }
114 #endif
115 }
116
117 while (sp <= cp) {
118 c = *(unsigned char *) cp;
119 if (c == '\\') {
120 buflen -= 2;
121 if (buflen < 0)
122 goto out;
123 *--end = '\\';
124 *--end = '\\';
125 } else if (c > ' ' && c < 127) {
126 if (--buflen < 0)
127 goto out;
128 *--end = (char) c;
129 } else {
130 buflen -= 4;
131 if (buflen < 0)
132 goto out;
133 *--end = (c & 7) + '0';
134 *--end = ((c >> 3) & 7) + '0';
135 *--end = (c >> 6) + '0';
136 *--end = '\\';
137 }
138 cp--;
139 }
140 if (--buflen < 0)
141 goto out;
142 *--end = '/';
143 }
144 dentry = parent;
145 }
146 if (*end == '/') {
147 buflen++;
148 end++;
149 }
150 {
151 const char *sp = dentry->d_name.name;
152 const char *cp = sp + dentry->d_name.len - 1;
153 unsigned char c;
154 while (sp <= cp) {
155 c = *(unsigned char *) cp;
156 if (c == '\\') {
157 buflen -= 2;
158 if (buflen < 0)
159 goto out;
160 *--end = '\\';
161 *--end = '\\';
162 } else if (c > ' ' && c < 127) {
163 if (--buflen < 0)
164 goto out;
165 *--end = (char) c;
166 } else {
167 buflen -= 4;
168 if (buflen < 0)
169 goto out;
170 *--end = (c & 7) + '0';
171 *--end = ((c >> 3) & 7) + '0';
172 *--end = (c >> 6) + '0';
173 *--end = '\\';
174 }
175 cp--;
176 }
177 }
178 /* Move the pathname to the top of the buffer. */
179 memmove(start, end, strlen(end) + 1);
180 return 0;
181 out:
182 return -ENOMEM;
183 /***** CRITICAL SECTION END *****/
184 }
185
186 #define SOCKFS_MAGIC 0x534F434B
187
188 /**
189 * ccs_realpath_from_dentry2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
190 *
191 * @dentry: Pointer to "struct dentry".
192 * @mnt: Pointer to "struct vfsmount".
193 * @newname: Pointer to buffer to return value in.
194 * @newname_len: Size of @newname.
195 *
196 * Returns 0 on success, negative value otherwise.
197 */
198 int ccs_realpath_from_dentry2(struct dentry *dentry, struct vfsmount *mnt,
199 char *newname, int newname_len)
200 {
201 int error = -EINVAL;
202 struct dentry *d_dentry;
203 struct vfsmount *d_mnt;
204 if (!dentry || !newname || newname_len <= 2048)
205 goto out;
206 /* Get better name for socket. */
207 if (dentry->d_sb && dentry->d_sb->s_magic == SOCKFS_MAGIC) {
208 struct inode *inode = dentry->d_inode;
209 struct socket *sock = inode ? SOCKET_I(inode) : NULL;
210 struct sock *sk = sock ? sock->sk : NULL;
211 if (sk) {
212 snprintf(newname, newname_len - 1,
213 "socket:[family=%u:type=%u:protocol=%u]",
214 sk->sk_family, sk->sk_type, sk->sk_protocol);
215 } else {
216 snprintf(newname, newname_len - 1, "socket:[unknown]");
217 }
218 return 0;
219 }
220 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
221 if (dentry->d_op && dentry->d_op->d_dname) {
222 /* For "socket:[\$]" and "pipe:[\$]". */
223 static const int offset = 1536;
224 char *dp = newname;
225 char *sp = dentry->d_op->d_dname(dentry, newname + offset,
226 newname_len - offset);
227 if (IS_ERR(sp)) {
228 error = PTR_ERR(sp);
229 goto out;
230 }
231 error = -ENOMEM;
232 newname += offset;
233 while (1) {
234 const unsigned char c = *(unsigned char *) sp++;
235 if (c == '\\') {
236 if (dp + 2 >= newname)
237 break;
238 *dp++ = '\\';
239 *dp++ = '\\';
240 } else if (c > ' ' && c < 127) {
241 if (dp + 1 >= newname)
242 break;
243 *dp++ = (char) c;
244 } else if (c) {
245 if (dp + 4 >= newname)
246 break;
247 *dp++ = '\\';
248 *dp++ = (c >> 6) + '0';
249 *dp++ = ((c >> 3) & 7) + '0';
250 *dp++ = (c & 7) + '0';
251 } else {
252 *dp = '\0';
253 return 0;
254 }
255 }
256 goto out;
257 }
258 #endif
259 if (!mnt)
260 goto out;
261 d_dentry = dget(dentry);
262 d_mnt = mntget(mnt);
263 /***** CRITICAL SECTION START *****/
264 ccs_realpath_lock();
265 error = ccs_get_absolute_path(d_dentry, d_mnt, newname, newname_len);
266 ccs_realpath_unlock();
267 /***** CRITICAL SECTION END *****/
268 dput(d_dentry);
269 mntput(d_mnt);
270 out:
271 if (error)
272 printk(KERN_WARNING "ccs_realpath: Pathname too long. (%d)\n",
273 error);
274 return error;
275 }
276
277 /**
278 * ccs_realpath_from_dentry - Returns realpath(3) of the given pathname but ignores chroot'ed root.
279 *
280 * @dentry: Pointer to "struct dentry".
281 * @mnt: Pointer to "struct vfsmount".
282 *
283 * Returns the realpath of the given @dentry and @mnt on success,
284 * NULL otherwise.
285 *
286 * These functions use ccs_alloc(), so caller must ccs_free()
287 * if these functions didn't return NULL.
288 */
289 char *ccs_realpath_from_dentry(struct dentry *dentry, struct vfsmount *mnt)
290 {
291 char *buf = ccs_alloc(CCS_MAX_PATHNAME_LEN, false);
292 if (buf && ccs_realpath_from_dentry2(dentry, mnt, buf,
293 CCS_MAX_PATHNAME_LEN - 1) == 0)
294 return buf;
295 ccs_free(buf);
296 return NULL;
297 }
298
299 /**
300 * ccs_realpath - Get realpath of a pathname.
301 *
302 * @pathname: The pathname to solve.
303 *
304 * Returns the realpath of @pathname on success, NULL otherwise.
305 */
306 char *ccs_realpath(const char *pathname)
307 {
308 struct nameidata nd;
309 if (pathname && path_lookup(pathname, ccs_lookup_flags, &nd) == 0) {
310 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
311 char *buf = ccs_realpath_from_dentry(nd.path.dentry,
312 nd.path.mnt);
313 path_put(&nd.path);
314 #else
315 char *buf = ccs_realpath_from_dentry(nd.dentry, nd.mnt);
316 path_release(&nd);
317 #endif
318 return buf;
319 }
320 return NULL;
321 }
322
323 /**
324 * ccs_realpath_both - Get realpath of a pathname and symlink.
325 *
326 * @pathname: The pathname to solve.
327 * @ee: Pointer to "struct ccs_execve_entry".
328 *
329 * Returns 0 on success, negative value otherwise.
330 */
331 int ccs_realpath_both(const char *pathname, struct ccs_execve_entry *ee)
332 {
333 struct nameidata nd;
334 int ret;
335 bool is_symlink;
336 if (!pathname ||
337 path_lookup(pathname, ccs_lookup_flags ^ LOOKUP_FOLLOW, &nd))
338 return -ENOENT;
339 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
340 is_symlink = nd.path.dentry->d_inode &&
341 S_ISLNK(nd.path.dentry->d_inode->i_mode);
342 ret = ccs_realpath_from_dentry2(nd.path.dentry, nd.path.mnt,
343 ee->tmp, CCS_EXEC_TMPSIZE - 1);
344 path_put(&nd.path);
345 #else
346 is_symlink = nd.dentry->d_inode && S_ISLNK(nd.dentry->d_inode->i_mode);
347 ret = ccs_realpath_from_dentry2(nd.dentry, nd.mnt, ee->tmp,
348 CCS_EXEC_TMPSIZE - 1);
349 path_release(&nd);
350 #endif
351 if (ret)
352 return -ENOMEM;
353 if (strlen(ee->tmp) > CCS_MAX_PATHNAME_LEN - 1)
354 return -ENOMEM;
355 ee->program_path[CCS_MAX_PATHNAME_LEN - 1] = '\0';
356 if (!is_symlink) {
357 strncpy(ee->program_path, ee->tmp,
358 CCS_MAX_PATHNAME_LEN - 1);
359 return 0;
360 }
361 if (path_lookup(pathname, ccs_lookup_flags, &nd))
362 return -ENOENT;
363 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
364 ret = ccs_realpath_from_dentry2(nd.path.dentry, nd.path.mnt,
365 ee->program_path,
366 CCS_MAX_PATHNAME_LEN - 1);
367 path_put(&nd.path);
368 #else
369 ret = ccs_realpath_from_dentry2(nd.dentry, nd.mnt, ee->program_path,
370 CCS_MAX_PATHNAME_LEN - 1);
371 path_release(&nd);
372 #endif
373 return ret ? -ENOMEM : 0;
374 }
375
376 /**
377 * ccs_encode: Encode binary string to ascii string.
378 *
379 * @str: String in binary format.
380 *
381 * Returns pointer to @str in ascii format on success, NULL otherwise.
382 *
383 * This function uses ccs_alloc(), so caller must ccs_free() if this function
384 * didn't return NULL.
385 */
386 char *ccs_encode(const char *str)
387 {
388 int len = 0;
389 const char *p = str;
390 char *cp;
391 char *cp0;
392 if (!p)
393 return NULL;
394 while (*p) {
395 const unsigned char c = *p++;
396 if (c == '\\')
397 len += 2;
398 else if (c > ' ' && c < 127)
399 len++;
400 else
401 len += 4;
402 }
403 len++;
404 cp = ccs_alloc(len, false);
405 if (!cp)
406 return NULL;
407 cp0 = cp;
408 p = str;
409 while (*p) {
410 const unsigned char c = *p++;
411 if (c == '\\') {
412 *cp++ = '\\';
413 *cp++ = '\\';
414 } else if (c > ' ' && c < 127) {
415 *cp++ = c;
416 } else {
417 *cp++ = '\\';
418 *cp++ = (c >> 6) + '0';
419 *cp++ = ((c >> 3) & 7) + '0';
420 *cp++ = (c & 7) + '0';
421 }
422 }
423 return cp0;
424 }
425
426 /**
427 * ccs_round_up - Round up an integer so that the returned pointers are appropriately aligned.
428 *
429 * @size: Size in bytes.
430 *
431 * Returns rounded value of @size.
432 *
433 * FIXME: Are there more requirements that is needed for assigning value
434 * atomically?
435 */
436 static inline unsigned int ccs_round_up(const unsigned int size)
437 {
438 if (sizeof(void *) >= sizeof(long))
439 return ((size + sizeof(void *) - 1)
440 / sizeof(void *)) * sizeof(void *);
441 else
442 return ((size + sizeof(long) - 1)
443 / sizeof(long)) * sizeof(long);
444 }
445
446
447 static DEFINE_MUTEX(ccs_element_lock);
448 static unsigned int ccs_allocated_memory_for_elements;
449 static unsigned int ccs_quota_for_elements;
450
451 /**
452 * ccs_memory_ok - Check memory quota.
453 *
454 * @ptr: Pointer to allocated memory.
455 *
456 * Returns true if @ptr is not NULL and quota not exceeded, false otehrwise.
457 */
458 bool ccs_memory_ok(const void *ptr)
459 {
460 const unsigned int len = ptr ? ksize(ptr) : 0;
461 if (len && (!ccs_quota_for_elements ||
462 ccs_allocated_memory_for_elements + len
463 <= ccs_quota_for_elements)) {
464 ccs_allocated_memory_for_elements += len;
465 return true;
466 }
467 printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);
468 if (!ccs_policy_loaded)
469 panic("MAC Initialization failed.\n");
470 return false;
471 }
472
473 /**
474 * ccs_memory_free - Free memory for elements.
475 *
476 * @ptr: Pointer to allocated memory.
477 */
478 static void ccs_memory_free(const void *ptr)
479 {
480 ccs_allocated_memory_for_elements -= ksize(ptr);
481 kfree(ptr);
482 }
483
484 /**
485 * ccs_free_element - Delete memory for structures.
486 *
487 * @ptr: Memory to release.
488 */
489 static void ccs_free_element(void *ptr)
490 {
491 int len;
492 if (!ptr)
493 return;
494 len = ksize(ptr);
495 kfree(ptr);
496 /***** EXCLUSIVE SECTION START *****/
497 mutex_lock(&ccs_element_lock);
498 ccs_allocated_memory_for_elements -= len;
499 mutex_unlock(&ccs_element_lock);
500 /***** EXCLUSIVE SECTION END *****/
501 }
502
503 /**
504 * ccs_put_path_group - Delete memory for "struct ccs_path_group_entry".
505 *
506 * @group: Pointer to "struct ccs_path_group_entry".
507 */
508 void ccs_put_path_group(struct ccs_path_group_entry *group)
509 {
510 struct ccs_path_group_member *member;
511 struct ccs_path_group_member *next_member;
512 LIST_HEAD(q);
513 bool can_delete_group = false;
514 if (!group)
515 return;
516 mutex_lock(&ccs_policy_lock);
517 if (atomic_dec_and_test(&group->users)) {
518 list_for_each_entry_safe(member, next_member,
519 &group->path_group_member_list,
520 list) {
521 if (!member->is_deleted)
522 break;
523 list_del(&member->list);
524 list_add(&member->list, &q);
525 }
526 if (list_empty(&group->path_group_member_list)) {
527 list_del(&group->list);
528 can_delete_group = true;
529 }
530 }
531 mutex_unlock(&ccs_policy_lock);
532 list_for_each_entry_safe(member, next_member, &q, list) {
533 list_del(&member->list);
534 ccs_put_name(member->member_name);
535 ccs_free_element(member);
536 }
537 if (can_delete_group) {
538 ccs_put_name(group->group_name);
539 ccs_free_element(group);
540 }
541 }
542
543 /**
544 * ccs_put_address_group - Delete memory for "struct ccs_address_group_entry".
545 *
546 * @group: Pointer to "struct ccs_address_group_entry".
547 */
548 void ccs_put_address_group(struct ccs_address_group_entry *group)
549 {
550 struct ccs_address_group_member *member;
551 struct ccs_address_group_member *next_member;
552 LIST_HEAD(q);
553 bool can_delete_group = false;
554 if (!group)
555 return;
556 mutex_lock(&ccs_policy_lock);
557 if (atomic_dec_and_test(&group->users)) {
558 list_for_each_entry_safe(member, next_member,
559 &group->address_group_member_list,
560 list) {
561 if (!member->is_deleted)
562 break;
563 list_del(&member->list);
564 list_add(&member->list, &q);
565 }
566 if (list_empty(&group->address_group_member_list)) {
567 list_del(&group->list);
568 can_delete_group = true;
569 }
570 }
571 mutex_unlock(&ccs_policy_lock);
572 list_for_each_entry_safe(member, next_member, &q, list) {
573 list_del(&member->list);
574 if (member->is_ipv6) {
575 ccs_put_ipv6_address(member->min.ipv6);
576 ccs_put_ipv6_address(member->max.ipv6);
577 }
578 ccs_free_element(member);
579 }
580 if (can_delete_group) {
581 ccs_put_name(group->group_name);
582 ccs_free_element(group);
583 }
584 }
585
586 static LIST_HEAD(ccs_address_list);
587
588 /**
589 * ccs_get_ipv6_address - Keep the given IPv6 address on the RAM.
590 *
591 * @addr: Pointer to "struct in6_addr".
592 *
593 * Returns pointer to "struct in6_addr" on success, NULL otherwise.
594 *
595 * The RAM is shared, so NEVER try to modify or kfree() the returned address.
596 */
597 const struct in6_addr *ccs_get_ipv6_address(const struct in6_addr *addr)
598 {
599 struct ccs_ipv6addr_entry *entry;
600 struct ccs_ipv6addr_entry *ptr;
601 int error = -ENOMEM;
602 if (!addr)
603 return NULL;
604 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
605 mutex_lock(&ccs_policy_lock);
606 list_for_each_entry(ptr, &ccs_address_list, list) {
607 if (memcmp(&ptr->addr, addr, sizeof(*addr)))
608 continue;
609 atomic_inc(&ptr->users);
610 error = 0;
611 break;
612 }
613 if (error && ccs_memory_ok(entry)) {
614 ptr = entry;
615 ptr->addr = *addr;
616 atomic_set(&ptr->users, 1);
617 list_add_tail(&ptr->list, &ccs_address_list);
618 entry = NULL;
619 }
620 mutex_unlock(&ccs_policy_lock);
621 kfree(entry);
622 return ptr ? &ptr->addr : NULL;
623 }
624
625 /**
626 * ccs_put_ipv6_address - Delete the given IPv6 address on the RAM.
627 *
628 * @addr: Pointer to "struct in6_addr".
629 */
630 void ccs_put_ipv6_address(const struct in6_addr *addr)
631 {
632 struct ccs_ipv6addr_entry *ptr;
633 bool can_delete = false;
634 if (!addr)
635 return;
636 ptr = container_of(addr, struct ccs_ipv6addr_entry, addr);
637 mutex_lock(&ccs_policy_lock);
638 if (atomic_dec_and_test(&ptr->users)) {
639 list_del(&ptr->list);
640 can_delete = true;
641 }
642 mutex_unlock(&ccs_policy_lock);
643 if (can_delete)
644 ccs_free_element(ptr);
645 }
646
647 /**
648 * ccs_put_condition - Delete memory for "struct ccs_condition".
649 *
650 * @cond: Pointer to "struct ccs_condition".
651 */
652 void ccs_put_condition(struct ccs_condition *cond)
653 {
654 const unsigned long *ptr;
655 const struct ccs_argv_entry *argv;
656 const struct ccs_envp_entry *envp;
657 const struct ccs_symlinkp_entry *symlinkp;
658 u16 condc;
659 u16 argc;
660 u16 envc;
661 u16 symlinkc;
662 u16 i;
663 bool can_delete = false;
664 if (!cond)
665 return;
666 mutex_lock(&ccs_policy_lock);
667 if (atomic_dec_and_test(&cond->users)) {
668 list_del(&cond->list);
669 can_delete = true;
670 }
671 mutex_unlock(&ccs_policy_lock);
672 if (!can_delete)
673 return;
674 condc = cond->head.condc;
675 argc = cond->head.argc;
676 envc = cond->head.envc;
677 symlinkc = cond->head.symlinkc;
678 ptr = (const unsigned long *) (cond + 1);
679 argv = (const struct ccs_argv_entry *) (ptr + condc);
680 envp = (const struct ccs_envp_entry *) (argv + argc);
681 symlinkp = (const struct ccs_symlinkp_entry *) (envp + envc);
682 for (i = 0; i < argc; argv++, i++)
683 ccs_put_name(argv->value);
684 for (i = 0; i < envc; envp++, i++) {
685 ccs_put_name(envp->name);
686 ccs_put_name(envp->value);
687 }
688 for (i = 0; i < symlinkc; symlinkp++, i++)
689 ccs_put_name(symlinkp->value);
690 ccs_free_element(cond);
691 }
692
693 static unsigned int ccs_allocated_memory_for_savename;
694 static unsigned int ccs_quota_for_savename;
695
696 #define MAX_HASH 256
697
698 /* Structure for string data. */
699 struct ccs_name_entry {
700 struct list_head list;
701 atomic_t users;
702 struct ccs_path_info entry;
703 };
704
705 /* The list for "struct ccs_name_entry". */
706 static struct list_head ccs_name_list[MAX_HASH];
707 static DEFINE_MUTEX(ccs_name_list_lock);
708
709 /**
710 * ccs_get_name - Allocate memory for string data.
711 *
712 * @name: The string to store into the permernent memory.
713 *
714 * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
715 */
716 const struct ccs_path_info *ccs_get_name(const char *name)
717 {
718 struct ccs_name_entry *ptr;
719 unsigned int hash;
720 int len;
721 int allocated_len;
722
723 if (!name)
724 return NULL;
725 len = strlen(name) + 1;
726 if (len > CCS_MAX_PATHNAME_LEN) {
727 printk(KERN_WARNING "ERROR: Name too long. (%s)\n", __func__);
728 return NULL;
729 }
730 hash = full_name_hash((const unsigned char *) name, len - 1);
731 /***** EXCLUSIVE SECTION START *****/
732 mutex_lock(&ccs_name_list_lock);
733 list_for_each_entry(ptr, &ccs_name_list[hash % MAX_HASH], list) {
734 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
735 continue;
736 atomic_inc(&ptr->users);
737 goto out;
738 }
739 ptr = kmalloc(sizeof(*ptr) + len, GFP_KERNEL);
740 allocated_len = ptr ? ksize(ptr) : 0;
741 if (!allocated_len ||
742 (ccs_quota_for_savename &&
743 ccs_allocated_memory_for_savename + allocated_len
744 > ccs_quota_for_savename)) {
745 kfree(ptr);
746 ptr = NULL;
747 printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);
748 if (!ccs_policy_loaded)
749 panic("MAC Initialization failed.\n");
750 goto out;
751 }
752 ccs_allocated_memory_for_savename += allocated_len;
753 ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
754 memmove((char *) ptr->entry.name, name, len);
755 atomic_set(&ptr->users, 1);
756 ccs_fill_path_info(&ptr->entry);
757 list_add_tail(&ptr->list, &ccs_name_list[hash % MAX_HASH]);
758 out:
759 mutex_unlock(&ccs_name_list_lock);
760 /***** EXCLUSIVE SECTION END *****/
761 return ptr ? &ptr->entry : NULL;
762 }
763
764 /**
765 * ccs_put_name - Delete shared memory for string data.
766 *
767 * @name: Pointer to "struct ccs_path_info".
768 */
769 void ccs_put_name(const struct ccs_path_info *name)
770 {
771 struct ccs_name_entry *ptr;
772 bool can_delete = false;
773 if (!name)
774 return;
775 ptr = container_of(name, struct ccs_name_entry, entry);
776 /***** EXCLUSIVE SECTION START *****/
777 mutex_lock(&ccs_name_list_lock);
778 if (atomic_dec_and_test(&ptr->users)) {
779 list_del(&ptr->list);
780 can_delete = true;
781 }
782 mutex_unlock(&ccs_name_list_lock);
783 /***** EXCLUSIVE SECTION END *****/
784 if (can_delete) {
785 ccs_allocated_memory_for_savename -= ksize(ptr);
786 kfree(ptr);
787 }
788 }
789
790 /* Structure for temporarily allocated memory. */
791 struct ccs_cache_entry {
792 struct list_head list;
793 void *ptr;
794 int size;
795 };
796
797 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
798 static struct kmem_cache *ccs_cachep;
799 #else
800 static kmem_cache_t *ccs_cachep;
801 #endif
802
803 /**
804 * ccs_realpath_init - Initialize realpath related code.
805 *
806 * Returns 0.
807 */
808 static int __init ccs_realpath_init(void)
809 {
810 int i;
811 struct ccs_domain_info *domain;
812 /* Constraint for ccs_get_name(). */
813 if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE)
814 panic("Bad size.");
815 /* Constraint for "struct ccs_execve_entry"->tmp users. */
816 if (CCS_MAX_PATHNAME_LEN > CCS_EXEC_TMPSIZE)
817 panic("Bad size.");
818 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
819 ccs_cachep = kmem_cache_create("ccs_cache",
820 sizeof(struct ccs_cache_entry),
821 0, 0, NULL);
822 #else
823 ccs_cachep = kmem_cache_create("ccs_cache",
824 sizeof(struct ccs_cache_entry),
825 0, 0, NULL, NULL);
826 #endif
827 if (!ccs_cachep)
828 panic("Can't create cache.\n");
829 for (i = 0; i < MAX_HASH; i++)
830 INIT_LIST_HEAD(&ccs_name_list[i]);
831 INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
832 ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
833 list_add_tail(&ccs_kernel_domain.list, &ccs_domain_list);
834 domain = ccs_find_domain(ROOT_NAME);
835 if (domain != &ccs_kernel_domain)
836 panic("Can't register ccs_kernel_domain");
837 #ifdef CONFIG_TOMOYO_BUILTIN_INITIALIZERS
838 {
839 /* Load built-in policy. */
840 static char ccs_builtin_initializers[] __initdata
841 = CONFIG_TOMOYO_BUILTIN_INITIALIZERS;
842 char *cp = ccs_builtin_initializers;
843 ccs_normalize_line(cp);
844 while (cp && *cp) {
845 char *cp2 = strchr(cp, ' ');
846 if (cp2)
847 *cp2++ = '\0';
848 ccs_write_domain_initializer_policy(cp, false, false);
849 cp = cp2;
850 }
851 }
852 #endif
853 return 0;
854 }
855
856 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
857 __initcall(ccs_realpath_init);
858 #else
859 core_initcall(ccs_realpath_init);
860 #endif
861
862 /* The list for "struct ccs_cache_entry". */
863 static LIST_HEAD(ccs_audit_cache_list);
864 static LIST_HEAD(ccs_acl_cache_list);
865 static DEFINE_SPINLOCK(ccs_cache_list_lock);
866
867 static unsigned int ccs_dynamic_memory_size;
868 static unsigned int ccs_quota_for_dynamic;
869
870 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
871 /**
872 * ccs_round2 - Rounded up to power-of-two value.
873 *
874 * @size: Size in bytes.
875 *
876 * Returns power-of-two of @size.
877 */
878 static int ccs_round2(size_t size)
879 {
880 #if PAGE_SIZE == 4096
881 size_t bsize = 32;
882 #else
883 size_t bsize = 64;
884 #endif
885 while (size > bsize)
886 bsize <<= 1;
887 return bsize;
888 }
889 #endif
890
891 /**
892 * ccs_alloc - Allocate memory for temporary purpose.
893 *
894 * @size: Size in bytes.
895 *
896 * Returns pointer to allocated memory on success, NULL otherwise.
897 */
898 void *ccs_alloc(const size_t size, const _Bool check_quota)
899 {
900 struct ccs_cache_entry *new_entry;
901 void *ret = kzalloc(size, GFP_KERNEL);
902 if (!ret)
903 goto out;
904 new_entry = kmem_cache_alloc(ccs_cachep, GFP_KERNEL);
905 if (!new_entry) {
906 kfree(ret);
907 ret = NULL;
908 goto out;
909 }
910 INIT_LIST_HEAD(&new_entry->list);
911 new_entry->ptr = ret;
912 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
913 new_entry->size = ksize(ret);
914 #else
915 new_entry->size = ccs_round2(size);
916 #endif
917 if (check_quota) {
918 bool quota_exceeded = false;
919 /***** CRITICAL SECTION START *****/
920 spin_lock(&ccs_cache_list_lock);
921 if (!ccs_quota_for_dynamic ||
922 ccs_dynamic_memory_size + new_entry->size
923 <= ccs_quota_for_dynamic) {
924 list_add_tail(&new_entry->list, &ccs_audit_cache_list);
925 ccs_dynamic_memory_size += new_entry->size;
926 } else {
927 quota_exceeded = true;
928 }
929 spin_unlock(&ccs_cache_list_lock);
930 /***** CRITICAL SECTION END *****/
931 if (quota_exceeded) {
932 kfree(ret);
933 kmem_cache_free(ccs_cachep, new_entry);
934 ret = NULL;
935 }
936 } else {
937 /***** CRITICAL SECTION START *****/
938 spin_lock(&ccs_cache_list_lock);
939 list_add(&new_entry->list, &ccs_acl_cache_list);
940 ccs_dynamic_memory_size += new_entry->size;
941 spin_unlock(&ccs_cache_list_lock);
942 /***** CRITICAL SECTION END *****/
943 }
944 out:
945 return ret;
946 }
947
948 /**
949 * ccs_free - Release memory allocated by ccs_alloc().
950 *
951 * @p: Pointer returned by ccs_alloc(). May be NULL.
952 *
953 * Returns nothing.
954 */
955 void ccs_free(const void *p)
956 {
957 struct list_head *v;
958 struct ccs_cache_entry *entry = NULL;
959 if (!p)
960 return;
961 /***** CRITICAL SECTION START *****/
962 spin_lock(&ccs_cache_list_lock);
963 list_for_each(v, &ccs_acl_cache_list) {
964 entry = list_entry(v, struct ccs_cache_entry, list);
965 if (entry->ptr == p)
966 break;
967 entry = NULL;
968 }
969 if (!entry) {
970 list_for_each(v, &ccs_audit_cache_list) {
971 entry = list_entry(v, struct ccs_cache_entry, list);
972 if (entry->ptr == p)
973 break;
974 entry = NULL;
975 }
976 }
977 if (entry) {
978 list_del(&entry->list);
979 ccs_dynamic_memory_size -= entry->size;
980 }
981 spin_unlock(&ccs_cache_list_lock);
982 /***** CRITICAL SECTION END *****/
983 if (entry) {
984 kfree(p);
985 kmem_cache_free(ccs_cachep, entry);
986 } else {
987 printk(KERN_WARNING "BUG: ccs_free() with invalid pointer.\n");
988 dump_stack();
989 }
990 }
991
992 /**
993 * ccs_read_memory_counter - Check for memory usage.
994 *
995 * @head: Pointer to "struct ccs_io_buffer".
996 *
997 * Returns memory usage.
998 */
999 int ccs_read_memory_counter(struct ccs_io_buffer *head)
1000 {
1001 if (!head->read_eof) {
1002 const unsigned int shared = ccs_allocated_memory_for_savename;
1003 const unsigned int private = ccs_allocated_memory_for_elements;
1004 const unsigned int dynamic = ccs_dynamic_memory_size;
1005 char buffer[64];
1006 memset(buffer, 0, sizeof(buffer));
1007 if (ccs_quota_for_savename)
1008 snprintf(buffer, sizeof(buffer) - 1,
1009 " (Quota: %10u)", ccs_quota_for_savename);
1010 else
1011 buffer[0] = '\0';
1012 ccs_io_printf(head, "Shared: %10u%s\n", shared, buffer);
1013 if (ccs_quota_for_elements)
1014 snprintf(buffer, sizeof(buffer) - 1,
1015 " (Quota: %10u)", ccs_quota_for_elements);
1016 else
1017 buffer[0] = '\0';
1018 ccs_io_printf(head, "Private: %10u%s\n", private, buffer);
1019 if (ccs_quota_for_dynamic)
1020 snprintf(buffer, sizeof(buffer) - 1,
1021 " (Quota: %10u)", ccs_quota_for_dynamic);
1022 else
1023 buffer[0] = '\0';
1024 ccs_io_printf(head, "Dynamic: %10u%s\n", dynamic, buffer);
1025 ccs_io_printf(head, "Total: %10u\n",
1026 shared + private + dynamic);
1027 head->read_eof = true;
1028 }
1029 return 0;
1030 }
1031
1032 /**
1033 * ccs_write_memory_quota - Set memory quota.
1034 *
1035 * @head: Pointer to "struct ccs_io_buffer".
1036 *
1037 * Returns 0.
1038 */
1039 int ccs_write_memory_quota(struct ccs_io_buffer *head)
1040 {
1041 char *data = head->write_buf;
1042 unsigned int size;
1043 if (sscanf(data, "Shared: %u", &size) == 1)
1044 ccs_quota_for_savename = size;
1045 else if (sscanf(data, "Private: %u", &size) == 1)
1046 ccs_quota_for_elements = size;
1047 else if (sscanf(data, "Dynamic: %u", &size) == 1)
1048 ccs_quota_for_dynamic = size;
1049 return 0;
1050 }
1051
1052 /**
1053 * ccs_cleanup_allow_read - Clean up deleted "struct ccs_globally_readable_file_entry".
1054 */
1055 static void ccs_cleanup_allow_read(void)
1056 {
1057 struct ccs_globally_readable_file_entry *ptr;
1058 struct ccs_globally_readable_file_entry *tmp;
1059 LIST_HEAD(q);
1060 mutex_lock(&ccs_policy_lock);
1061 list_for_each_entry_safe(ptr, tmp, &ccs_globally_readable_list,
1062 list) {
1063 if (!ptr->is_deleted)
1064 continue;
1065 list_del(&ptr->list);
1066 list_add(&ptr->list, &q);
1067 }
1068 mutex_unlock(&ccs_policy_lock);
1069 list_for_each_entry_safe(ptr, tmp, &q, list) {
1070 ccs_put_name(ptr->filename);
1071 list_del(&ptr->list);
1072 ccs_memory_free(ptr);
1073 }
1074 }
1075
1076 /**
1077 * ccs_cleanup_allow_env - Clean up deleted "struct ccs_globally_usable_env_entry".
1078 */
1079 static void ccs_cleanup_allow_env(void)
1080 {
1081 struct ccs_globally_usable_env_entry *ptr;
1082 struct ccs_globally_usable_env_entry *tmp;
1083 LIST_HEAD(q);
1084 mutex_lock(&ccs_policy_lock);
1085 list_for_each_entry_safe(ptr, tmp, &ccs_globally_usable_env_list,
1086 list) {
1087 if (!ptr->is_deleted)
1088 continue;
1089 list_del(&ptr->list);
1090 list_add(&ptr->list, &q);
1091 }
1092 mutex_unlock(&ccs_policy_lock);
1093 list_for_each_entry_safe(ptr, tmp, &q, list) {
1094 ccs_put_name(ptr->env);
1095 list_del(&ptr->list);
1096 ccs_memory_free(ptr);
1097 }
1098 }
1099
1100 /**
1101 * ccs_cleanup_file_pattern - Clean up deleted "struct ccs_pattern_entry".
1102 */
1103 static void ccs_cleanup_file_pattern(void)
1104 {
1105 struct ccs_pattern_entry *ptr;
1106 struct ccs_pattern_entry *tmp;
1107 LIST_HEAD(q);
1108 mutex_lock(&ccs_policy_lock);
1109 list_for_each_entry_safe(ptr, tmp, &ccs_pattern_list, list) {
1110 if (!ptr->is_deleted)
1111 continue;
1112 list_del(&ptr->list);
1113 list_add(&ptr->list, &q);
1114 }
1115 mutex_unlock(&ccs_policy_lock);
1116 list_for_each_entry_safe(ptr, tmp, &q, list) {
1117 ccs_put_name(ptr->pattern);
1118 list_del(&ptr->list);
1119 ccs_memory_free(ptr);
1120 }
1121 }
1122
1123 /**
1124 * ccs_cleanup_no_rewrite - Clean up deleted "struct ccs_no_rewrite_entry".
1125 */
1126 static void ccs_cleanup_no_rewrite(void)
1127 {
1128 struct ccs_no_rewrite_entry *ptr;
1129 struct ccs_no_rewrite_entry *tmp;
1130 LIST_HEAD(q);
1131 mutex_lock(&ccs_policy_lock);
1132 list_for_each_entry_safe(ptr, tmp, &ccs_no_rewrite_list, list) {
1133 if (!ptr->is_deleted)
1134 continue;
1135 list_del(&ptr->list);
1136 list_add(&ptr->list, &q);
1137 }
1138 mutex_unlock(&ccs_policy_lock);
1139 list_for_each_entry_safe(ptr, tmp, &q, list) {
1140 ccs_put_name(ptr->pattern);
1141 list_del(&ptr->list);
1142 ccs_memory_free(ptr);
1143 }
1144 }
1145
1146 /**
1147 * ccs_cleanup_initializer - Clean up deleted "struct ccs_domain_initializer_entry".
1148 */
1149 static void ccs_cleanup_initializer(void)
1150 {
1151 struct ccs_domain_initializer_entry *ptr;
1152 struct ccs_domain_initializer_entry *tmp;
1153 LIST_HEAD(q);
1154 mutex_lock(&ccs_policy_lock);
1155 list_for_each_entry_safe(ptr, tmp, &ccs_domain_initializer_list,
1156 list) {
1157 if (!ptr->is_deleted)
1158 continue;
1159 list_del(&ptr->list);
1160 list_add(&ptr->list, &q);
1161 }
1162 mutex_unlock(&ccs_policy_lock);
1163 list_for_each_entry_safe(ptr, tmp, &q, list) {
1164 ccs_put_name(ptr->domainname);
1165 ccs_put_name(ptr->program);
1166 list_del(&ptr->list);
1167 ccs_memory_free(ptr);
1168 }
1169 }
1170
1171 /**
1172 * ccs_cleanup_keep_domain - Clean up deleted "struct ccs_domain_keeper_entry".
1173 */
1174 static void ccs_cleanup_keep_domain(void)
1175 {
1176 struct ccs_domain_keeper_entry *ptr;
1177 struct ccs_domain_keeper_entry *tmp;
1178 LIST_HEAD(q);
1179 mutex_lock(&ccs_policy_lock);
1180 list_for_each_entry_safe(ptr, tmp, &ccs_domain_keeper_list, list) {
1181 if (!ptr->is_deleted)
1182 continue;
1183 list_del(&ptr->list);
1184 list_add(&ptr->list, &q);
1185 }
1186 mutex_unlock(&ccs_policy_lock);
1187 list_for_each_entry_safe(ptr, tmp, &q, list) {
1188 ccs_put_name(ptr->domainname);
1189 ccs_put_name(ptr->program);
1190 list_del(&ptr->list);
1191 ccs_memory_free(ptr);
1192 }
1193 }
1194
1195 /**
1196 * ccs_cleanup_alias - Clean up deleted "struct ccs_alias_entry".
1197 */
1198 static void ccs_cleanup_alias(void)
1199 {
1200 struct ccs_alias_entry *ptr;
1201 struct ccs_alias_entry *tmp;
1202 LIST_HEAD(q);
1203 mutex_lock(&ccs_policy_lock);
1204 list_for_each_entry_safe(ptr, tmp, &ccs_alias_list, list) {
1205 if (!ptr->is_deleted)
1206 continue;
1207 list_del(&ptr->list);
1208 list_add(&ptr->list, &q);
1209 }
1210 mutex_unlock(&ccs_policy_lock);
1211 list_for_each_entry_safe(ptr, tmp, &q, list) {
1212 ccs_put_name(ptr->original_name);
1213 ccs_put_name(ptr->aliased_name);
1214 list_del(&ptr->list);
1215 ccs_memory_free(ptr);
1216 }
1217 }
1218
1219 /**
1220 * ccs_cleanup_aggregator - Clean up deleted "struct ccs_aggregator_entry".
1221 */
1222 static void ccs_cleanup_aggregator(void)
1223 {
1224 struct ccs_aggregator_entry *ptr;
1225 struct ccs_aggregator_entry *tmp;
1226 LIST_HEAD(q);
1227 mutex_lock(&ccs_policy_lock);
1228 list_for_each_entry_safe(ptr, tmp, &ccs_aggregator_list, list) {
1229 if (!ptr->is_deleted)
1230 continue;
1231 list_del(&ptr->list);
1232 list_add(&ptr->list, &q);
1233 }
1234 mutex_unlock(&ccs_policy_lock);
1235 list_for_each_entry_safe(ptr, tmp, &q, list) {
1236 ccs_put_name(ptr->original_name);
1237 ccs_put_name(ptr->aggregated_name);
1238 list_del(&ptr->list);
1239 ccs_memory_free(ptr);
1240 }
1241 }
1242
1243 /**
1244 * ccs_cleanup_manager - Clean up deleted "struct ccs_policy_manager_entry".
1245 */
1246 static void ccs_cleanup_manager(void)
1247 {
1248 struct ccs_policy_manager_entry *ptr;
1249 struct ccs_policy_manager_entry *tmp;
1250 LIST_HEAD(q);
1251 mutex_lock(&ccs_policy_lock);
1252 list_for_each_entry_safe(ptr, tmp, &ccs_policy_manager_list, list) {
1253 if (!ptr->is_deleted)
1254 continue;
1255 list_del(&ptr->list);
1256 list_add(&ptr->list, &q);
1257 }
1258 mutex_unlock(&ccs_policy_lock);
1259 list_for_each_entry_safe(ptr, tmp, &q, list) {
1260 ccs_put_name(ptr->manager);
1261 list_del(&ptr->list);
1262 ccs_memory_free(ptr);
1263 }
1264 }
1265
1266 /* For compatibility with older kernels. */
1267 #ifndef for_each_process
1268 #define for_each_process for_each_task
1269 #endif
1270
1271 /**
1272 * ccs_used_by_task - Check whether the given pointer is referenced by a task.
1273 *
1274 * @domain: Pointer to "struct ccs_domain_info".
1275 *
1276 * Returns true if @ptr is in use, false otherwise.
1277 */
1278 static bool ccs_used_by_task(struct ccs_domain_info *domain)
1279 {
1280 bool in_use = false;
1281 struct task_struct *p;
1282 /***** CRITICAL SECTION START *****/
1283 read_lock(&tasklist_lock);
1284 for_each_process(p) {
1285 if (p->ccs_domain_info != domain)
1286 continue;
1287 in_use = true;
1288 break;
1289 }
1290 read_unlock(&tasklist_lock);
1291 /***** CRITICAL SECTION END *****/
1292 return in_use;
1293 }
1294
1295 /**
1296 * ccs_cleanup_domain_policy - Clean up deleted domain policy.
1297 */
1298 static void ccs_cleanup_domain_policy(void)
1299 {
1300 struct ccs_domain_info *domain;
1301 struct ccs_domain_info *next_domain;
1302 struct ccs_acl_info *acl;
1303 struct ccs_acl_info *next_acl;
1304 LIST_HEAD(q_domain);
1305 LIST_HEAD(q_acl);
1306 mutex_lock(&ccs_policy_lock);
1307 list_for_each_entry_safe(domain, next_domain, &ccs_domain_list,
1308 list) {
1309 const bool can_delete_domain = domain->is_deleted &&
1310 !ccs_used_by_task(domain);
1311 if (can_delete_domain) {
1312 list_for_each_entry(acl, &domain->acl_info_list, list)
1313 acl->type |= ACL_DELETED;
1314 }
1315 list_for_each_entry_safe(acl, next_acl, &domain->acl_info_list,
1316 list) {
1317 if (!(acl->type & ACL_DELETED))
1318 continue;
1319 list_del(&acl->list);
1320 list_add(&acl->list, &q_acl);
1321 }
1322 if (can_delete_domain && list_empty(&domain->acl_info_list)) {
1323 list_del(&domain->list);
1324 list_add(&domain->list, &q_domain);
1325 }
1326 }
1327 mutex_unlock(&ccs_policy_lock);
1328 list_for_each_entry_safe(acl, next_acl, &q_acl, list) {
1329 ccs_put_condition(acl->cond);
1330 switch (ccs_acl_type1(acl)) {
1331 struct ccs_single_path_acl_record *acl1;
1332 struct ccs_double_path_acl_record *acl2;
1333 struct ccs_ip_network_acl_record *acl3;
1334 struct ccs_ioctl_acl_record *acl4;
1335 struct ccs_argv0_acl_record *acl5;
1336 struct ccs_env_acl_record *acl6;
1337 struct ccs_capability_acl_record *acl7;
1338 struct ccs_signal_acl_record *acl8;
1339 struct ccs_execute_handler_record *acl9;
1340 case TYPE_SINGLE_PATH_ACL:
1341 acl1 = container_of(acl,
1342 struct ccs_single_path_acl_record,
1343 head);
1344 if (acl1->u_is_group)
1345 ccs_put_path_group(acl1->u.group);
1346 else
1347 ccs_put_name(acl1->u.filename);
1348 break;
1349 case TYPE_DOUBLE_PATH_ACL:
1350 acl2 = container_of(acl,
1351 struct ccs_double_path_acl_record,
1352 head);
1353 if (acl2->u1_is_group)
1354 ccs_put_path_group(acl2->u1.group1);
1355 else
1356 ccs_put_name(acl2->u1.filename1);
1357 if (acl2->u2_is_group)
1358 ccs_put_path_group(acl2->u2.group2);
1359 else
1360 ccs_put_name(acl2->u2.filename2);
1361 break;
1362 case TYPE_IP_NETWORK_ACL:
1363 acl3 = container_of(acl,
1364 struct ccs_ip_network_acl_record,
1365 head);
1366 if (acl3->record_type == IP_RECORD_TYPE_ADDRESS_GROUP)
1367 ccs_put_address_group(acl3->u.group);
1368 else if (acl3->record_type == IP_RECORD_TYPE_IPv6) {
1369 ccs_put_ipv6_address(acl3->u.ipv6.min);
1370 ccs_put_ipv6_address(acl3->u.ipv6.max);
1371 }
1372 break;
1373 case TYPE_IOCTL_ACL:
1374 acl4 = container_of(acl, struct ccs_ioctl_acl_record,
1375 head);
1376 if (acl4->u_is_group)
1377 ccs_put_path_group(acl4->u.group);
1378 else
1379 ccs_put_name(acl4->u.filename);
1380 break;
1381 case TYPE_ARGV0_ACL:
1382 acl5 = container_of(acl, struct ccs_argv0_acl_record,
1383 head);
1384 ccs_put_name(acl5->argv0);
1385 break;
1386 case TYPE_ENV_ACL:
1387 acl6 = container_of(acl, struct ccs_env_acl_record,
1388 head);
1389 ccs_put_name(acl6->env);
1390 break;
1391 case TYPE_CAPABILITY_ACL:
1392 acl7 = container_of(acl,
1393 struct ccs_capability_acl_record,
1394 head);
1395 break;
1396 case TYPE_SIGNAL_ACL:
1397 acl8 = container_of(acl, struct ccs_signal_acl_record,
1398 head);
1399 ccs_put_name(acl8->domainname);
1400 break;
1401 case TYPE_EXECUTE_HANDLER:
1402 case TYPE_DENIED_EXECUTE_HANDLER:
1403 acl9 = container_of(acl,
1404 struct ccs_execute_handler_record,
1405 head);
1406 ccs_put_name(acl9->handler);
1407 break;
1408 }
1409 list_del(&acl->list);
1410 ccs_memory_free(acl);
1411 }
1412 list_for_each_entry_safe(domain, next_domain, &q_domain, list) {
1413 ccs_put_name(domain->domainname);
1414 list_del(&domain->list);
1415 ccs_memory_free(domain);
1416 }
1417 }
1418
1419 /**
1420 * ccs_cleanup_path_group - Clean up deleted "struct ccs_path_group_entry".
1421 */
1422 static void ccs_cleanup_path_group(void)
1423 {
1424 struct ccs_path_group_entry *group;
1425 struct ccs_path_group_entry *next_group;
1426 struct ccs_path_group_member *member;
1427 struct ccs_path_group_member *next_member;
1428 LIST_HEAD(q_group);
1429 LIST_HEAD(q_member);
1430 mutex_lock(&ccs_policy_lock);
1431 list_for_each_entry_safe(group, next_group, &ccs_path_group_list,
1432 list) {
1433 list_for_each_entry_safe(member, next_member,
1434 &group->path_group_member_list,
1435 list) {
1436 if (!member->is_deleted)
1437 break;
1438 list_del(&member->list);
1439 list_add(&member->list, &q_member);
1440 }
1441 if (list_empty(&group->path_group_member_list) &&
1442 !atomic_read(&group->users)) {
1443 list_del(&group->list);
1444 list_add(&group->list, &q_group);
1445 }
1446 }
1447 mutex_unlock(&ccs_policy_lock);
1448 list_for_each_entry_safe(member, next_member, &q_member, list) {
1449 ccs_put_name(member->member_name);
1450 list_del(&member->list);
1451 ccs_free_element(member);
1452 }
1453 list_for_each_entry_safe(group, next_group, &q_group, list) {
1454 ccs_put_name(group->group_name);
1455 list_del(&group->list);
1456 ccs_free_element(group);
1457 }
1458 }
1459
1460 /**
1461 * ccs_cleanup_address_group - Clean up deleted "struct ccs_address_group_entry".
1462 */
1463 static void ccs_cleanup_address_group(void)
1464 {
1465 struct ccs_address_group_entry *group;
1466 struct ccs_address_group_entry *next_group;
1467 struct ccs_address_group_member *member;
1468 struct ccs_address_group_member *next_member;
1469 LIST_HEAD(q_group);
1470 LIST_HEAD(q_member);
1471 mutex_lock(&ccs_policy_lock);
1472 list_for_each_entry_safe(group, next_group, &ccs_address_group_list,
1473 list) {
1474 list_for_each_entry_safe(member, next_member,
1475 &group->address_group_member_list,
1476 list) {
1477 if (!member->is_deleted)
1478 break;
1479 list_del(&member->list);
1480 list_add(&member->list, &q_member);
1481 }
1482 if (list_empty(&group->address_group_member_list) &&
1483 !atomic_read(&group->users)) {
1484 list_del(&group->list);
1485 list_add(&group->list, &q_group);
1486 }
1487 }
1488 mutex_unlock(&ccs_policy_lock);
1489 list_for_each_entry_safe(member, next_member, &q_member, list) {
1490 if (member->is_ipv6) {
1491 ccs_put_ipv6_address(member->min.ipv6);
1492 ccs_put_ipv6_address(member->max.ipv6);
1493 }
1494 list_del(&member->list);
1495 ccs_free_element(member);
1496 }
1497 list_for_each_entry_safe(group, next_group, &q_group, list) {
1498 ccs_put_name(group->group_name);
1499 list_del(&group->list);
1500 ccs_free_element(group);
1501 }
1502 }
1503
1504 /**
1505 * ccs_cleanup_mount - Clean up deleted "struct ccs_mount_entry".
1506 */
1507 static void ccs_cleanup_mount(void)
1508 {
1509 struct ccs_mount_entry *ptr;
1510 struct ccs_mount_entry *tmp;
1511 LIST_HEAD(q);
1512 mutex_lock(&ccs_policy_lock);
1513 list_for_each_entry_safe(ptr, tmp, &ccs_mount_list, list) {
1514 if (!ptr->is_deleted)
1515 continue;
1516 list_del(&ptr->list);
1517 list_add(&ptr->list, &q);
1518 }
1519 mutex_unlock(&ccs_policy_lock);
1520 list_for_each_entry_safe(ptr, tmp, &q, list) {
1521 ccs_put_name(ptr->dev_name);
1522 ccs_put_name(ptr->dir_name);
1523 ccs_put_name(ptr->fs_type);
1524 list_del(&ptr->list);
1525 ccs_memory_free(ptr);
1526 }
1527 }
1528
1529 /**
1530 * ccs_cleanup_no_umount - Clean up deleted "struct ccs_no_umount_entry".
1531 */
1532 static void ccs_cleanup_no_umount(void)
1533 {
1534 struct ccs_no_umount_entry *ptr;
1535 struct ccs_no_umount_entry *tmp;
1536 LIST_HEAD(q);
1537 mutex_lock(&ccs_policy_lock);
1538 list_for_each_entry_safe(ptr, tmp, &ccs_no_umount_list, list) {
1539 if (!ptr->is_deleted)
1540 continue;
1541 list_del(&ptr->list);
1542 list_add(&ptr->list, &q);
1543 }
1544 mutex_unlock(&ccs_policy_lock);
1545 list_for_each_entry_safe(ptr, tmp, &q, list) {
1546 ccs_put_name(ptr->dir);
1547 list_del(&ptr->list);
1548 ccs_memory_free(ptr);
1549 }
1550 }
1551
1552 /**
1553 * ccs_cleanup_pivot_root - Clean up deleted "struct ccs_pivot_root_entry".
1554 */
1555 static void ccs_cleanup_pivot_root(void)
1556 {
1557 struct ccs_pivot_root_entry *ptr;
1558 struct ccs_pivot_root_entry *tmp;
1559 LIST_HEAD(q);
1560 mutex_lock(&ccs_policy_lock);
1561 list_for_each_entry_safe(ptr, tmp, &ccs_pivot_root_list, list) {
1562 if (!ptr->is_deleted)
1563 continue;
1564 list_del(&ptr->list);
1565 list_add(&ptr->list, &q);
1566 }
1567 mutex_unlock(&ccs_policy_lock);
1568 list_for_each_entry_safe(ptr, tmp, &q, list) {
1569 ccs_put_name(ptr->old_root);
1570 ccs_put_name(ptr->new_root);
1571 list_del(&ptr->list);
1572 ccs_memory_free(ptr);
1573 }
1574 }
1575
1576 /**
1577 * ccs_cleanup_chroot - Clean up deleted "struct ccs_chroot_entry".
1578 */
1579 static void ccs_cleanup_chroot(void)
1580 {
1581 struct ccs_chroot_entry *ptr;
1582 struct ccs_chroot_entry *tmp;
1583 LIST_HEAD(q);
1584 mutex_lock(&ccs_policy_lock);
1585 list_for_each_entry_safe(ptr, tmp, &ccs_chroot_list, list) {
1586 if (!ptr->is_deleted)
1587 continue;
1588 list_del(&ptr->list);
1589 list_add(&ptr->list, &q);
1590 }
1591 mutex_unlock(&ccs_policy_lock);
1592 list_for_each_entry_safe(ptr, tmp, &q, list) {
1593 ccs_put_name(ptr->dir);
1594 list_del(&ptr->list);
1595 ccs_memory_free(ptr);
1596 }
1597 }
1598
1599 /**
1600 * ccs_cleanup_reservedport - Clean up deleted "struct ccs_reserved_entry".
1601 */
1602 static void ccs_cleanup_reservedport(void)
1603 {
1604 struct ccs_reserved_entry *ptr;
1605 struct ccs_reserved_entry *tmp;
1606 LIST_HEAD(q);
1607 mutex_lock(&ccs_policy_lock);
1608 list_for_each_entry_safe(ptr, tmp, &ccs_reservedport_list, list) {
1609 if (!ptr->is_deleted)
1610 continue;
1611 list_del(&ptr->list);
1612 list_add(&ptr->list, &q);
1613 }
1614 mutex_unlock(&ccs_policy_lock);
1615 list_for_each_entry_safe(ptr, tmp, &q, list) {
1616 list_del(&ptr->list);
1617 ccs_memory_free(ptr);
1618 }
1619 }
1620
1621 /**
1622 * ccs_cleanup_condition - Clean up deleted "struct ccs_condition".
1623 */
1624 static void ccs_cleanup_condition(void)
1625 {
1626 struct ccs_condition *ptr;
1627 struct ccs_condition *tmp;
1628 LIST_HEAD(q);
1629 mutex_lock(&ccs_policy_lock);
1630 list_for_each_entry_safe(ptr, tmp, &ccs_condition_list, list) {
1631 if (atomic_read(&ptr->users))
1632 continue;
1633 list_del(&ptr->list);
1634 list_add(&ptr->list, &q);
1635 }
1636 mutex_unlock(&ccs_policy_lock);
1637 list_for_each_entry_safe(ptr, tmp, &q, list) {
1638 int i;
1639 u16 condc = ptr->head.condc;
1640 u16 argc = ptr->head.argc;
1641 u16 envc = ptr->head.envc;
1642 u16 symlinkc = ptr->head.symlinkc;
1643 unsigned long *ptr2 = (unsigned long *) (ptr + 1);
1644 struct ccs_argv_entry *argv = (struct ccs_argv_entry *)
1645 (ptr2 + condc);
1646 struct ccs_envp_entry *envp = (struct ccs_envp_entry *)
1647 (argv + argc);
1648 struct ccs_symlinkp_entry *symlinkp
1649 = (struct ccs_symlinkp_entry *) (envp + envc);
1650 for (i = 0; i < argc; i++)
1651 ccs_put_name(argv[i].value);
1652 for (i = 0; i < envc; i++) {
1653 ccs_put_name(envp[i].name);
1654 ccs_put_name(envp[i].value);
1655 }
1656 for (i = 0; i < symlinkc; i++)
1657 ccs_put_name(symlinkp[i].value);
1658 list_del(&ptr->list);
1659 ccs_memory_free(ptr);
1660 }
1661 }
1662
1663 /**
1664 * ccs_run_garbage_collector - Run garbage collector.
1665 */
1666 static void ccs_run_garbage_collector(void)
1667 {
1668 ccs_cleanup_allow_read();
1669 ccs_cleanup_allow_env();
1670 ccs_cleanup_file_pattern();
1671 ccs_cleanup_no_rewrite();
1672 ccs_cleanup_initializer();
1673 ccs_cleanup_keep_domain();
1674 ccs_cleanup_alias();
1675 ccs_cleanup_aggregator();
1676 ccs_cleanup_manager();
1677 ccs_cleanup_domain_policy();
1678 ccs_cleanup_path_group();
1679 ccs_cleanup_address_group();
1680 ccs_cleanup_mount();
1681 ccs_cleanup_no_umount();
1682 ccs_cleanup_pivot_root();
1683 ccs_cleanup_chroot();
1684 ccs_cleanup_reservedport();
1685 ccs_cleanup_condition();
1686 }

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