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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2576 - (hide annotations) (download) (as text)
Thu May 21 06:28:42 2009 UTC (15 years ago) by kumaneko
Original Path: branches/ccs-patch/fs/realpath.c
File MIME type: text/x-csrc
File size: 46263 byte(s)


1 kumaneko 111 /*
2     * fs/realpath.c
3     *
4     * Get the canonicalized absolute pathnames. The basis for SAKURA and TOMOYO.
5     *
6 kumaneko 2030 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 kumaneko 111 *
8 kumaneko 2519 * Version: 1.6.8-pre 2009/05/08
9 kumaneko 111 *
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 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
25 kumaneko 111 #include <linux/namei.h>
26     #include <linux/mount.h>
27 kumaneko 2002 static const int ccs_lookup_flags = LOOKUP_FOLLOW;
28 kumaneko 111 #else
29 kumaneko 2002 static const int ccs_lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE;
30 kumaneko 111 #endif
31     #include <linux/proc_fs.h>
32     #include <linux/ccs_common.h>
33 kumaneko 2540 #include <linux/realpath.h>
34 kumaneko 2271 #include <net/sock.h>
35 kumaneko 111
36 kumaneko 1052 /**
37 kumaneko 2002 * ccs_get_absolute_path - Get the path of a dentry but ignores chroot'ed root.
38 kumaneko 111 *
39 kumaneko 1052 * @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 kumaneko 1064 * Caller holds the dcache_lock and vfsmount_lock.
47 kumaneko 111 * Based on __d_path() in fs/dcache.c
48     *
49     * If dentry is a directory, trailing '/' is appended.
50 kumaneko 1052 * Characters out of 0x20 < c < 0x7F range are converted to
51     * \ooo style octal string.
52 kumaneko 111 * Character \ is converted to \\ string.
53     */
54 kumaneko 2002 static int ccs_get_absolute_path(struct dentry *dentry, struct vfsmount *vfsmnt,
55     char *buffer, int buflen)
56 kumaneko 111 {
57 kumaneko 1052 /***** CRITICAL SECTION START *****/
58 kumaneko 111 char *start = buffer;
59     char *end = buffer + buflen;
60 kumaneko 621 bool is_dir = (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode));
61 kumaneko 111
62 kumaneko 1052 if (buflen < 256)
63     goto out;
64 kumaneko 111
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 kumaneko 1052 if (vfsmnt->mnt_parent == vfsmnt)
74 kumaneko 111 break;
75     dentry = vfsmnt->mnt_mountpoint;
76     vfsmnt = vfsmnt->mnt_parent;
77     continue;
78     }
79     if (is_dir) {
80 kumaneko 1052 is_dir = false;
81     *--end = '/';
82     buflen--;
83 kumaneko 111 }
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 kumaneko 1052 /*
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 kumaneko 111 char *ep;
98 kumaneko 1052 const pid_t pid
99     = (pid_t) simple_strtoul(sp, &ep, 10);
100 kumaneko 1778 #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 kumaneko 1052 sp = "self";
107     cp = sp + 3;
108     }
109 kumaneko 111 #else
110 kumaneko 1778 if (!*ep && pid == sys_getpid()) {
111 kumaneko 1052 sp = "self";
112     cp = sp + 3;
113     }
114 kumaneko 111 #endif
115     }
116    
117     while (sp <= cp) {
118 kumaneko 1052 c = *(unsigned char *) cp;
119 kumaneko 111 if (c == '\\') {
120     buflen -= 2;
121 kumaneko 1052 if (buflen < 0)
122     goto out;
123 kumaneko 111 *--end = '\\';
124     *--end = '\\';
125     } else if (c > ' ' && c < 127) {
126 kumaneko 1052 if (--buflen < 0)
127     goto out;
128 kumaneko 111 *--end = (char) c;
129     } else {
130     buflen -= 4;
131 kumaneko 1052 if (buflen < 0)
132     goto out;
133 kumaneko 111 *--end = (c & 7) + '0';
134     *--end = ((c >> 3) & 7) + '0';
135     *--end = (c >> 6) + '0';
136     *--end = '\\';
137     }
138     cp--;
139     }
140 kumaneko 1052 if (--buflen < 0)
141     goto out;
142 kumaneko 111 *--end = '/';
143     }
144     dentry = parent;
145     }
146 kumaneko 1052 if (*end == '/') {
147     buflen++;
148     end++;
149     }
150 kumaneko 111 {
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 kumaneko 1052 c = *(unsigned char *) cp;
156 kumaneko 111 if (c == '\\') {
157     buflen -= 2;
158 kumaneko 1052 if (buflen < 0)
159     goto out;
160 kumaneko 111 *--end = '\\';
161     *--end = '\\';
162     } else if (c > ' ' && c < 127) {
163 kumaneko 1052 if (--buflen < 0)
164     goto out;
165 kumaneko 111 *--end = (char) c;
166     } else {
167     buflen -= 4;
168 kumaneko 1052 if (buflen < 0)
169     goto out;
170 kumaneko 111 *--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 kumaneko 1052 /***** CRITICAL SECTION END *****/
184 kumaneko 111 }
185    
186 kumaneko 2271 #define SOCKFS_MAGIC 0x534F434B
187    
188 kumaneko 1052 /**
189 kumaneko 1054 * ccs_realpath_from_dentry2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
190 kumaneko 1052 *
191     * @dentry: Pointer to "struct dentry".
192     * @mnt: Pointer to "struct vfsmount".
193     * @newname: Pointer to buffer to return value in.
194 kumaneko 1064 * @newname_len: Size of @newname.
195 kumaneko 1052 *
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 kumaneko 111 {
201 kumaneko 1379 int error = -EINVAL;
202 kumaneko 111 struct dentry *d_dentry;
203     struct vfsmount *d_mnt;
204 kumaneko 1379 if (!dentry || !newname || newname_len <= 2048)
205     goto out;
206 kumaneko 2271 /* 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 kumaneko 2284 struct socket *sock = inode ? SOCKET_I(inode) : NULL;
210     struct sock *sk = sock ? sock->sk : NULL;
211     if (sk) {
212 kumaneko 2271 snprintf(newname, newname_len - 1,
213 kumaneko 2284 "socket:[family=%u:type=%u:protocol=%u]",
214     sk->sk_family, sk->sk_type, sk->sk_protocol);
215 kumaneko 2271 } else {
216     snprintf(newname, newname_len - 1, "socket:[unknown]");
217     }
218     return 0;
219     }
220 kumaneko 1259 #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 kumaneko 1379 if (!mnt)
260     goto out;
261 kumaneko 111 d_dentry = dget(dentry);
262     d_mnt = mntget(mnt);
263     /***** CRITICAL SECTION START *****/
264 kumaneko 1474 ccs_realpath_lock();
265 kumaneko 2002 error = ccs_get_absolute_path(d_dentry, d_mnt, newname, newname_len);
266 kumaneko 1474 ccs_realpath_unlock();
267 kumaneko 111 /***** CRITICAL SECTION END *****/
268     dput(d_dentry);
269     mntput(d_mnt);
270 kumaneko 1259 out:
271 kumaneko 1056 if (error)
272 kumaneko 1379 printk(KERN_WARNING "ccs_realpath: Pathname too long. (%d)\n",
273     error);
274 kumaneko 111 return error;
275     }
276    
277 kumaneko 1052 /**
278 kumaneko 1054 * ccs_realpath_from_dentry - Returns realpath(3) of the given pathname but ignores chroot'ed root.
279 kumaneko 1052 *
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 kumaneko 111 {
291 kumaneko 2037 char *buf = ccs_alloc(CCS_MAX_PATHNAME_LEN, false);
292 kumaneko 1052 if (buf && ccs_realpath_from_dentry2(dentry, mnt, buf,
293     CCS_MAX_PATHNAME_LEN - 1) == 0)
294     return buf;
295 kumaneko 111 ccs_free(buf);
296     return NULL;
297     }
298    
299 kumaneko 1052 /**
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 kumaneko 111 {
308     struct nameidata nd;
309 kumaneko 2002 if (pathname && path_lookup(pathname, ccs_lookup_flags, &nd) == 0) {
310 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
311     char *buf = ccs_realpath_from_dentry(nd.path.dentry,
312     nd.path.mnt);
313 kumaneko 990 path_put(&nd.path);
314     #else
315 kumaneko 1052 char *buf = ccs_realpath_from_dentry(nd.dentry, nd.mnt);
316 kumaneko 111 path_release(&nd);
317 kumaneko 990 #endif
318 kumaneko 111 return buf;
319     }
320     return NULL;
321     }
322    
323 kumaneko 1052 /**
324 kumaneko 2037 * ccs_realpath_both - Get realpath of a pathname and symlink.
325 kumaneko 1052 *
326     * @pathname: The pathname to solve.
327 kumaneko 2037 * @ee: Pointer to "struct ccs_execve_entry".
328 kumaneko 1052 *
329 kumaneko 2075 * Returns 0 on success, negative value otherwise.
330 kumaneko 1052 */
331 kumaneko 2075 int ccs_realpath_both(const char *pathname, struct ccs_execve_entry *ee)
332 kumaneko 111 {
333     struct nameidata nd;
334 kumaneko 2037 int ret;
335     bool is_symlink;
336     if (!pathname ||
337     path_lookup(pathname, ccs_lookup_flags ^ LOOKUP_FOLLOW, &nd))
338 kumaneko 2075 return -ENOENT;
339 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
340 kumaneko 2037 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 kumaneko 990 #else
346 kumaneko 2037 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 kumaneko 990 #endif
351 kumaneko 2037 if (ret)
352 kumaneko 2075 return -ENOMEM;
353 kumaneko 2044 if (strlen(ee->tmp) > CCS_MAX_PATHNAME_LEN - 1)
354 kumaneko 2075 return -ENOMEM;
355 kumaneko 2037 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 kumaneko 2075 return 0;
360 kumaneko 111 }
361 kumaneko 2037 if (path_lookup(pathname, ccs_lookup_flags, &nd))
362 kumaneko 2075 return -ENOENT;
363 kumaneko 2037 #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 kumaneko 2075 return ret ? -ENOMEM : 0;
374 kumaneko 111 }
375    
376 kumaneko 1052 /**
377 kumaneko 2519 * 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 kumaneko 2002 * ccs_round_up - Round up an integer so that the returned pointers are appropriately aligned.
428 kumaneko 1052 *
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 kumaneko 111 */
436 kumaneko 2002 static inline unsigned int ccs_round_up(const unsigned int size)
437 kumaneko 1052 {
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 kumaneko 111 }
445    
446 kumaneko 2540
447     static DEFINE_MUTEX(ccs_element_lock);
448 kumaneko 2002 static unsigned int ccs_allocated_memory_for_elements;
449     static unsigned int ccs_quota_for_elements;
450 kumaneko 111
451 kumaneko 1052 /**
452 kumaneko 2540 * ccs_memory_ok - Check memory quota.
453 kumaneko 1052 *
454 kumaneko 2540 * @ptr: Pointer to allocated memory.
455 kumaneko 1052 *
456 kumaneko 2540 * 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 kumaneko 1052 *
476 kumaneko 2540 * @ptr: Pointer to allocated memory.
477 kumaneko 1052 */
478 kumaneko 2540 static void ccs_memory_free(const void *ptr)
479 kumaneko 111 {
480 kumaneko 2540 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 kumaneko 2545 if (!group)
515     return;
516 kumaneko 2540 /***** WRITER SECTION START *****/
517     down_write(&ccs_policy_lock);
518     if (atomic_dec_and_test(&group->users)) {
519     list_for_each_entry_safe(member, next_member,
520     &group->path_group_member_list,
521     list) {
522     if (!member->is_deleted)
523     break;
524     list_del(&member->list);
525     list_add(&member->list, &q);
526 kumaneko 111 }
527 kumaneko 2540 if (list_empty(&group->path_group_member_list)) {
528     list_del(&group->list);
529     can_delete_group = true;
530 kumaneko 111 }
531     }
532 kumaneko 2540 up_write(&ccs_policy_lock);
533     /***** WRITER SECTION END *****/
534     list_for_each_entry_safe(member, next_member, &q, list) {
535     list_del(&member->list);
536     ccs_put_name(member->member_name);
537     ccs_free_element(member);
538     }
539     if (can_delete_group) {
540     ccs_put_name(group->group_name);
541     ccs_free_element(group);
542     }
543 kumaneko 111 }
544    
545 kumaneko 2540 /**
546     * ccs_put_address_group - Delete memory for "struct ccs_address_group_entry".
547     *
548     * @group: Pointer to "struct ccs_address_group_entry".
549     */
550     void ccs_put_address_group(struct ccs_address_group_entry *group)
551     {
552     struct ccs_address_group_member *member;
553     struct ccs_address_group_member *next_member;
554     LIST_HEAD(q);
555     bool can_delete_group = false;
556 kumaneko 2545 if (!group)
557     return;
558 kumaneko 2540 /***** WRITER SECTION START *****/
559     down_write(&ccs_policy_lock);
560     if (atomic_dec_and_test(&group->users)) {
561     list_for_each_entry_safe(member, next_member,
562     &group->address_group_member_list,
563     list) {
564     if (!member->is_deleted)
565     break;
566     list_del(&member->list);
567     list_add(&member->list, &q);
568     }
569     if (list_empty(&group->address_group_member_list)) {
570     list_del(&group->list);
571     can_delete_group = true;
572     }
573     }
574     up_write(&ccs_policy_lock);
575     /***** WRITER SECTION END *****/
576     list_for_each_entry_safe(member, next_member, &q, list) {
577     list_del(&member->list);
578     if (member->is_ipv6) {
579     ccs_put_ipv6_address(member->min.ipv6);
580     ccs_put_ipv6_address(member->max.ipv6);
581     }
582     ccs_free_element(member);
583     }
584     if (can_delete_group) {
585     ccs_put_name(group->group_name);
586     ccs_free_element(group);
587     }
588     }
589    
590     static LIST_HEAD(ccs_address_list);
591    
592     /**
593     * ccs_get_ipv6_address - Keep the given IPv6 address on the RAM.
594     *
595     * @addr: Pointer to "struct in6_addr".
596     *
597     * Returns pointer to "struct in6_addr" on success, NULL otherwise.
598     *
599     * The RAM is shared, so NEVER try to modify or kfree() the returned address.
600     */
601     const struct in6_addr *ccs_get_ipv6_address(const struct in6_addr *addr)
602     {
603 kumaneko 2575 struct ccs_ipv6addr_entry *entry;
604     struct ccs_ipv6addr_entry *ptr;
605 kumaneko 2540 int error = -ENOMEM;
606     if (!addr)
607     return NULL;
608     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
609     /***** WRITER SECTION START *****/
610     down_write(&ccs_policy_lock);
611     list_for_each_entry(ptr, &ccs_address_list, list) {
612     if (memcmp(&ptr->addr, addr, sizeof(*addr)))
613     continue;
614     atomic_inc(&ptr->users);
615     error = 0;
616     break;
617     }
618     if (error && ccs_memory_ok(entry)) {
619     ptr = entry;
620     ptr->addr = *addr;
621     atomic_set(&ptr->users, 1);
622     list_add_tail(&ptr->list, &ccs_address_list);
623     entry = NULL;
624     }
625     up_write(&ccs_policy_lock);
626     /***** WRITER SECTION END *****/
627     kfree(entry);
628     return ptr ? &ptr->addr : NULL;
629     }
630    
631     /**
632     * ccs_put_ipv6_address - Delete the given IPv6 address on the RAM.
633     *
634     * @addr: Pointer to "struct in6_addr".
635     */
636     void ccs_put_ipv6_address(const struct in6_addr *addr)
637     {
638 kumaneko 2575 struct ccs_ipv6addr_entry *ptr;
639 kumaneko 2540 bool can_delete = false;
640     if (!addr)
641     return;
642 kumaneko 2575 ptr = container_of(addr, struct ccs_ipv6addr_entry, addr);
643 kumaneko 2540 /***** WRITER SECTION START *****/
644     down_write(&ccs_policy_lock);
645     if (atomic_dec_and_test(&ptr->users)) {
646     list_del(&ptr->list);
647     can_delete = true;
648     }
649     up_write(&ccs_policy_lock);
650     /***** WRITER SECTION END *****/
651 kumaneko 2546 if (can_delete)
652     ccs_free_element(ptr);
653 kumaneko 2540 }
654    
655 kumaneko 2553 /**
656 kumaneko 2576 * ccs_put_condition - Delete memory for "struct ccs_condition".
657 kumaneko 2553 *
658 kumaneko 2576 * @cond: Pointer to "struct ccs_condition".
659 kumaneko 2553 */
660 kumaneko 2576 void ccs_put_condition(struct ccs_condition *cond)
661 kumaneko 2553 {
662     const unsigned long *ptr;
663     const struct ccs_argv_entry *argv;
664     const struct ccs_envp_entry *envp;
665     const struct ccs_symlinkp_entry *symlinkp;
666     u16 condc;
667     u16 argc;
668     u16 envc;
669     u16 symlinkc;
670     u16 i;
671     bool can_delete = false;
672     if (!cond)
673     return;
674     /***** WRITER SECTION START *****/
675     down_write(&ccs_policy_lock);
676     if (atomic_dec_and_test(&cond->users)) {
677     list_del(&cond->list);
678     can_delete = true;
679     }
680     up_write(&ccs_policy_lock);
681     /***** WRITER SECTION END *****/
682     if (!can_delete)
683     return;
684     condc = cond->head.condc;
685     argc = cond->head.argc;
686     envc = cond->head.envc;
687     symlinkc = cond->head.symlinkc;
688     ptr = (const unsigned long *) (cond + 1);
689     argv = (const struct ccs_argv_entry *) (ptr + condc);
690     envp = (const struct ccs_envp_entry *) (argv + argc);
691     symlinkp = (const struct ccs_symlinkp_entry *) (envp + envc);
692     for (i = 0; i < argc; argv++, i++)
693     ccs_put_name(argv->value);
694     for (i = 0; i < envc; envp++, i++) {
695     ccs_put_name(envp->name);
696     ccs_put_name(envp->value);
697     }
698     for (i = 0; i < symlinkc; symlinkp++, i++)
699     ccs_put_name(symlinkp->value);
700     ccs_free_element(cond);
701     }
702    
703 kumaneko 2002 static unsigned int ccs_allocated_memory_for_savename;
704     static unsigned int ccs_quota_for_savename;
705 kumaneko 111
706     #define MAX_HASH 256
707    
708 kumaneko 1052 /* Structure for string data. */
709 kumaneko 2002 struct ccs_name_entry {
710 kumaneko 2540 struct list_head list;
711     atomic_t users;
712 kumaneko 2002 struct ccs_path_info entry;
713 kumaneko 214 };
714 kumaneko 111
715 kumaneko 2002 /* The list for "struct ccs_name_entry". */
716 kumaneko 2540 static struct list_head ccs_name_list[MAX_HASH];
717     static DEFINE_MUTEX(ccs_name_list_lock);
718 kumaneko 731
719 kumaneko 1052 /**
720 kumaneko 2540 * ccs_get_name - Allocate memory for string data.
721 kumaneko 1052 *
722     * @name: The string to store into the permernent memory.
723     *
724 kumaneko 2002 * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
725 kumaneko 1052 */
726 kumaneko 2540 const struct ccs_path_info *ccs_get_name(const char *name)
727 kumaneko 111 {
728 kumaneko 2002 struct ccs_name_entry *ptr;
729 kumaneko 111 unsigned int hash;
730     int len;
731 kumaneko 2540 int allocated_len;
732    
733 kumaneko 1052 if (!name)
734     return NULL;
735 kumaneko 111 len = strlen(name) + 1;
736     if (len > CCS_MAX_PATHNAME_LEN) {
737 kumaneko 2551 printk(KERN_WARNING "ERROR: Name too long. (%s)\n", __func__);
738 kumaneko 111 return NULL;
739     }
740     hash = full_name_hash((const unsigned char *) name, len - 1);
741 kumaneko 2540 /***** EXCLUSIVE SECTION START *****/
742     mutex_lock(&ccs_name_list_lock);
743     list_for_each_entry(ptr, &ccs_name_list[hash % MAX_HASH], list) {
744     if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
745     continue;
746     atomic_inc(&ptr->users);
747     goto out;
748 kumaneko 111 }
749 kumaneko 2540 ptr = kmalloc(sizeof(*ptr) + len, GFP_KERNEL);
750     allocated_len = ptr ? ksize(ptr) : 0;
751     if (!allocated_len ||
752     (ccs_quota_for_savename &&
753     ccs_allocated_memory_for_savename + allocated_len
754     > ccs_quota_for_savename)) {
755     kfree(ptr);
756     ptr = NULL;
757 kumaneko 2551 printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);
758 kumaneko 2040 if (!ccs_policy_loaded)
759 kumaneko 1052 panic("MAC Initialization failed.\n");
760 kumaneko 731 goto out;
761     }
762 kumaneko 2540 ccs_allocated_memory_for_savename += allocated_len;
763     ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
764     memmove((char *) ptr->entry.name, name, len);
765     atomic_set(&ptr->users, 1);
766 kumaneko 1052 ccs_fill_path_info(&ptr->entry);
767 kumaneko 2540 list_add_tail(&ptr->list, &ccs_name_list[hash % MAX_HASH]);
768 kumaneko 111 out:
769 kumaneko 2540 mutex_unlock(&ccs_name_list_lock);
770     /***** EXCLUSIVE SECTION END *****/
771 kumaneko 111 return ptr ? &ptr->entry : NULL;
772     }
773    
774 kumaneko 2540 /**
775     * ccs_put_name - Delete shared memory for string data.
776     *
777     * @name: Pointer to "struct ccs_path_info".
778     */
779     void ccs_put_name(const struct ccs_path_info *name)
780     {
781     struct ccs_name_entry *ptr;
782     bool can_delete = false;
783     if (!name)
784     return;
785     ptr = container_of(name, struct ccs_name_entry, entry);
786     /***** EXCLUSIVE SECTION START *****/
787     mutex_lock(&ccs_name_list_lock);
788     if (atomic_dec_and_test(&ptr->users)) {
789     list_del(&ptr->list);
790     can_delete = true;
791     }
792     mutex_unlock(&ccs_name_list_lock);
793     /***** EXCLUSIVE SECTION END *****/
794     if (can_delete) {
795     ccs_allocated_memory_for_savename -= ksize(ptr);
796     kfree(ptr);
797     }
798     }
799    
800 kumaneko 1052 /* Structure for temporarily allocated memory. */
801 kumaneko 2002 struct ccs_cache_entry {
802 kumaneko 111 struct list_head list;
803     void *ptr;
804     int size;
805 kumaneko 214 };
806 kumaneko 111
807 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
808     static struct kmem_cache *ccs_cachep;
809 kumaneko 111 #else
810 kumaneko 1052 static kmem_cache_t *ccs_cachep;
811 kumaneko 111 #endif
812    
813 kumaneko 1052 /**
814     * ccs_realpath_init - Initialize realpath related code.
815     *
816     * Returns 0.
817     */
818     static int __init ccs_realpath_init(void)
819 kumaneko 111 {
820 kumaneko 731 int i;
821 kumaneko 2540 struct ccs_cookie cookie;
822     /* Constraint for ccs_get_name(). */
823 kumaneko 1052 if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE)
824     panic("Bad size.");
825 kumaneko 2037 /* Constraint for "struct ccs_execve_entry"->tmp users. */
826     if (CCS_MAX_PATHNAME_LEN > CCS_EXEC_TMPSIZE)
827     panic("Bad size.");
828 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
829 kumaneko 2002 ccs_cachep = kmem_cache_create("ccs_cache",
830     sizeof(struct ccs_cache_entry),
831 kumaneko 1052 0, 0, NULL);
832 kumaneko 316 #else
833 kumaneko 2002 ccs_cachep = kmem_cache_create("ccs_cache",
834     sizeof(struct ccs_cache_entry),
835 kumaneko 1052 0, 0, NULL, NULL);
836 kumaneko 316 #endif
837 kumaneko 1052 if (!ccs_cachep)
838     panic("Can't create cache.\n");
839     for (i = 0; i < MAX_HASH; i++)
840 kumaneko 2540 INIT_LIST_HEAD(&ccs_name_list[i]);
841     INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
842     ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
843     list_add_tail(&ccs_kernel_domain.list, &ccs_domain_list);
844     if (!ccs_find_domain(ROOT_NAME, &cookie) ||
845     cookie.u.domain != &ccs_kernel_domain)
846 kumaneko 2282 panic("Can't register ccs_kernel_domain");
847 kumaneko 2308 #ifdef CONFIG_TOMOYO_BUILTIN_INITIALIZERS
848     {
849     /* Load built-in policy. */
850 kumaneko 2392 static char ccs_builtin_initializers[] __initdata
851     = CONFIG_TOMOYO_BUILTIN_INITIALIZERS;
852     char *cp = ccs_builtin_initializers;
853     ccs_normalize_line(cp);
854     while (cp && *cp) {
855     char *cp2 = strchr(cp, ' ');
856     if (cp2)
857     *cp2++ = '\0';
858     ccs_write_domain_initializer_policy(cp, false, false);
859     cp = cp2;
860 kumaneko 2308 }
861     }
862     #endif
863 kumaneko 1052 return 0;
864 kumaneko 111 }
865    
866 kumaneko 1084 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
867 kumaneko 1052 __initcall(ccs_realpath_init);
868 kumaneko 1084 #else
869 kumaneko 1106 core_initcall(ccs_realpath_init);
870 kumaneko 1084 #endif
871 kumaneko 1052
872 kumaneko 2002 /* The list for "struct ccs_cache_entry". */
873     static LIST_HEAD(ccs_audit_cache_list);
874     static LIST_HEAD(ccs_acl_cache_list);
875     static DEFINE_SPINLOCK(ccs_cache_list_lock);
876 kumaneko 1052
877 kumaneko 2002 static unsigned int ccs_dynamic_memory_size;
878     static unsigned int ccs_quota_for_dynamic;
879 kumaneko 1052
880     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
881     /**
882 kumaneko 2002 * ccs_round2 - Rounded up to power-of-two value.
883 kumaneko 1052 *
884     * @size: Size in bytes.
885     *
886     * Returns power-of-two of @size.
887     */
888 kumaneko 2002 static int ccs_round2(size_t size)
889 kumaneko 581 {
890     #if PAGE_SIZE == 4096
891     size_t bsize = 32;
892     #else
893     size_t bsize = 64;
894     #endif
895 kumaneko 1064 while (size > bsize)
896     bsize <<= 1;
897 kumaneko 581 return bsize;
898     }
899     #endif
900    
901 kumaneko 1052 /**
902 kumaneko 1793 * ccs_alloc - Allocate memory for temporary purpose.
903 kumaneko 1052 *
904     * @size: Size in bytes.
905     *
906     * Returns pointer to allocated memory on success, NULL otherwise.
907     */
908 kumaneko 1907 void *ccs_alloc(const size_t size, const _Bool check_quota)
909 kumaneko 111 {
910 kumaneko 2002 struct ccs_cache_entry *new_entry;
911 kumaneko 1055 void *ret = kzalloc(size, GFP_KERNEL);
912 kumaneko 1052 if (!ret)
913     goto out;
914 kumaneko 1031 new_entry = kmem_cache_alloc(ccs_cachep, GFP_KERNEL);
915     if (!new_entry) {
916 kumaneko 1064 kfree(ret);
917     ret = NULL;
918 kumaneko 1031 goto out;
919     }
920     INIT_LIST_HEAD(&new_entry->list);
921     new_entry->ptr = ret;
922 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
923 kumaneko 1031 new_entry->size = ksize(ret);
924     #else
925 kumaneko 2002 new_entry->size = ccs_round2(size);
926 kumaneko 1031 #endif
927 kumaneko 1903 if (check_quota) {
928     bool quota_exceeded = false;
929     /***** CRITICAL SECTION START *****/
930 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
931     if (!ccs_quota_for_dynamic ||
932     ccs_dynamic_memory_size + new_entry->size
933     <= ccs_quota_for_dynamic) {
934     list_add_tail(&new_entry->list, &ccs_audit_cache_list);
935     ccs_dynamic_memory_size += new_entry->size;
936 kumaneko 1903 } else {
937     quota_exceeded = true;
938     }
939 kumaneko 2002 spin_unlock(&ccs_cache_list_lock);
940 kumaneko 1903 /***** CRITICAL SECTION END *****/
941     if (quota_exceeded) {
942     kfree(ret);
943     kmem_cache_free(ccs_cachep, new_entry);
944     ret = NULL;
945     }
946     } else {
947     /***** CRITICAL SECTION START *****/
948 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
949     list_add(&new_entry->list, &ccs_acl_cache_list);
950     ccs_dynamic_memory_size += new_entry->size;
951     spin_unlock(&ccs_cache_list_lock);
952 kumaneko 1903 /***** CRITICAL SECTION END *****/
953     }
954 kumaneko 1031 out:
955 kumaneko 214 return ret;
956 kumaneko 111 }
957    
958 kumaneko 1052 /**
959     * ccs_free - Release memory allocated by ccs_alloc().
960     *
961     * @p: Pointer returned by ccs_alloc(). May be NULL.
962     *
963     * Returns nothing.
964     */
965 kumaneko 111 void ccs_free(const void *p)
966     {
967     struct list_head *v;
968 kumaneko 2002 struct ccs_cache_entry *entry = NULL;
969 kumaneko 1052 if (!p)
970     return;
971     /***** CRITICAL SECTION START *****/
972 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
973     list_for_each(v, &ccs_acl_cache_list) {
974     entry = list_entry(v, struct ccs_cache_entry, list);
975 kumaneko 1903 if (entry->ptr == p)
976     break;
977     entry = NULL;
978     }
979     if (!entry) {
980 kumaneko 2002 list_for_each(v, &ccs_audit_cache_list) {
981     entry = list_entry(v, struct ccs_cache_entry, list);
982 kumaneko 1903 if (entry->ptr == p)
983     break;
984 kumaneko 1064 entry = NULL;
985 kumaneko 111 }
986 kumaneko 1903 }
987     if (entry) {
988 kumaneko 111 list_del(&entry->list);
989 kumaneko 2002 ccs_dynamic_memory_size -= entry->size;
990 kumaneko 111 }
991 kumaneko 2002 spin_unlock(&ccs_cache_list_lock);
992 kumaneko 1052 /***** CRITICAL SECTION END *****/
993 kumaneko 111 if (entry) {
994     kfree(p);
995     kmem_cache_free(ccs_cachep, entry);
996     } else {
997 kumaneko 1052 printk(KERN_WARNING "BUG: ccs_free() with invalid pointer.\n");
998 kumaneko 2546 dump_stack();
999 kumaneko 111 }
1000     }
1001 kumaneko 1180
1002     /**
1003     * ccs_read_memory_counter - Check for memory usage.
1004     *
1005     * @head: Pointer to "struct ccs_io_buffer".
1006     *
1007     * Returns memory usage.
1008     */
1009     int ccs_read_memory_counter(struct ccs_io_buffer *head)
1010     {
1011     if (!head->read_eof) {
1012 kumaneko 2002 const unsigned int shared = ccs_allocated_memory_for_savename;
1013     const unsigned int private = ccs_allocated_memory_for_elements;
1014     const unsigned int dynamic = ccs_dynamic_memory_size;
1015 kumaneko 1180 char buffer[64];
1016     memset(buffer, 0, sizeof(buffer));
1017 kumaneko 2002 if (ccs_quota_for_savename)
1018 kumaneko 1180 snprintf(buffer, sizeof(buffer) - 1,
1019 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_savename);
1020 kumaneko 1180 else
1021     buffer[0] = '\0';
1022     ccs_io_printf(head, "Shared: %10u%s\n", shared, buffer);
1023 kumaneko 2002 if (ccs_quota_for_elements)
1024 kumaneko 1180 snprintf(buffer, sizeof(buffer) - 1,
1025 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_elements);
1026 kumaneko 1180 else
1027     buffer[0] = '\0';
1028     ccs_io_printf(head, "Private: %10u%s\n", private, buffer);
1029 kumaneko 2002 if (ccs_quota_for_dynamic)
1030 kumaneko 1903 snprintf(buffer, sizeof(buffer) - 1,
1031 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_dynamic);
1032 kumaneko 1903 else
1033     buffer[0] = '\0';
1034     ccs_io_printf(head, "Dynamic: %10u%s\n", dynamic, buffer);
1035 kumaneko 1180 ccs_io_printf(head, "Total: %10u\n",
1036     shared + private + dynamic);
1037     head->read_eof = true;
1038     }
1039     return 0;
1040     }
1041    
1042     /**
1043     * ccs_write_memory_quota - Set memory quota.
1044     *
1045     * @head: Pointer to "struct ccs_io_buffer".
1046     *
1047     * Returns 0.
1048     */
1049     int ccs_write_memory_quota(struct ccs_io_buffer *head)
1050     {
1051     char *data = head->write_buf;
1052     unsigned int size;
1053     if (sscanf(data, "Shared: %u", &size) == 1)
1054 kumaneko 2002 ccs_quota_for_savename = size;
1055 kumaneko 1180 else if (sscanf(data, "Private: %u", &size) == 1)
1056 kumaneko 2002 ccs_quota_for_elements = size;
1057 kumaneko 1903 else if (sscanf(data, "Dynamic: %u", &size) == 1)
1058 kumaneko 2002 ccs_quota_for_dynamic = size;
1059 kumaneko 1180 return 0;
1060     }
1061 kumaneko 2540
1062     /* List of pointers referenced by cookies. */
1063     static LIST_HEAD(ccs_cookie_list);
1064     static DEFINE_RWLOCK(ccs_cookie_list_lock);
1065    
1066     /**
1067     * ccs_add_cookie - Add a cookie to cookie list.
1068     *
1069     * @cookie: Pointer to "struct ccs_cookie".
1070     * @ptr: Pointer to assign.
1071     */
1072     void ccs_add_cookie(struct ccs_cookie *cookie, const void *ptr)
1073     {
1074     if (!cookie)
1075     return;
1076 kumaneko 2544 cookie->u.ptr = ptr;
1077 kumaneko 2540 write_lock(&ccs_cookie_list_lock);
1078     list_add_tail(&cookie->list, &ccs_cookie_list);
1079     write_unlock(&ccs_cookie_list_lock);
1080     }
1081    
1082     /**
1083     * ccs_del_cookie - Delete a cookie from cookie list.
1084     *
1085     * @cookie: Pointer to "struct ccs_cookie".
1086     */
1087     void ccs_del_cookie(struct ccs_cookie *cookie)
1088     {
1089     if (!cookie)
1090     return;
1091     write_lock(&ccs_cookie_list_lock);
1092     list_del(&cookie->list);
1093     write_unlock(&ccs_cookie_list_lock);
1094     }
1095    
1096     /**
1097     * ccs_used_by_cookie - Check whether the given pointer is referenced by a cookie or not.
1098     *
1099     * @ptr: Pointer to check.
1100     *
1101     * Returns true if @ptr is in use, false otherwise.
1102     *
1103     * Caller must hold ccs_policy_lock for writing.
1104     */
1105     static bool ccs_used_by_cookie(const void *ptr)
1106     {
1107     struct ccs_cookie *cookie;
1108     bool in_use = false;
1109     read_lock(&ccs_cookie_list_lock);
1110     list_for_each_entry(cookie, &ccs_cookie_list, list) {
1111     if (ptr != cookie->u.ptr)
1112     continue;
1113     in_use = true;
1114     break;
1115     }
1116     read_unlock(&ccs_cookie_list_lock);
1117     return in_use;
1118     }
1119    
1120     /**
1121     * ccs_cleanup_allow_read - Clean up deleted "struct ccs_globally_readable_file_entry".
1122     */
1123     static void ccs_cleanup_allow_read(void)
1124     {
1125     struct ccs_globally_readable_file_entry *ptr;
1126     struct ccs_globally_readable_file_entry *tmp;
1127     LIST_HEAD(q);
1128     /***** WRITER SECTION START *****/
1129     down_write(&ccs_policy_lock);
1130     list_for_each_entry_safe(ptr, tmp, &ccs_globally_readable_list,
1131     list) {
1132     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1133     continue;
1134     list_del(&ptr->list);
1135     list_add(&ptr->list, &q);
1136     }
1137     up_write(&ccs_policy_lock);
1138     /***** WRITER SECTION END *****/
1139     list_for_each_entry_safe(ptr, tmp, &q, list) {
1140     ccs_put_name(ptr->filename);
1141     list_del(&ptr->list);
1142     ccs_memory_free(ptr);
1143     }
1144     }
1145    
1146     /**
1147     * ccs_cleanup_allow_env - Clean up deleted "struct ccs_globally_usable_env_entry".
1148     */
1149     static void ccs_cleanup_allow_env(void)
1150     {
1151     struct ccs_globally_usable_env_entry *ptr;
1152     struct ccs_globally_usable_env_entry *tmp;
1153     LIST_HEAD(q);
1154     /***** WRITER SECTION START *****/
1155     down_write(&ccs_policy_lock);
1156     list_for_each_entry_safe(ptr, tmp, &ccs_globally_usable_env_list,
1157     list) {
1158     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1159     continue;
1160     list_del(&ptr->list);
1161     list_add(&ptr->list, &q);
1162     }
1163     up_write(&ccs_policy_lock);
1164     /***** WRITER SECTION END *****/
1165     list_for_each_entry_safe(ptr, tmp, &q, list) {
1166     ccs_put_name(ptr->env);
1167     list_del(&ptr->list);
1168     ccs_memory_free(ptr);
1169     }
1170     }
1171    
1172     /**
1173     * ccs_cleanup_file_pattern - Clean up deleted "struct ccs_pattern_entry".
1174     */
1175     static void ccs_cleanup_file_pattern(void)
1176     {
1177     struct ccs_pattern_entry *ptr;
1178     struct ccs_pattern_entry *tmp;
1179     LIST_HEAD(q);
1180     /***** WRITER SECTION START *****/
1181     down_write(&ccs_policy_lock);
1182     list_for_each_entry_safe(ptr, tmp, &ccs_pattern_list, list) {
1183     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1184     continue;
1185     list_del(&ptr->list);
1186     list_add(&ptr->list, &q);
1187     }
1188     up_write(&ccs_policy_lock);
1189     /***** WRITER SECTION END *****/
1190     list_for_each_entry_safe(ptr, tmp, &q, list) {
1191     ccs_put_name(ptr->pattern);
1192     list_del(&ptr->list);
1193     ccs_memory_free(ptr);
1194     }
1195     }
1196    
1197     /**
1198     * ccs_cleanup_no_rewrite - Clean up deleted "struct ccs_no_rewrite_entry".
1199     */
1200     static void ccs_cleanup_no_rewrite(void)
1201     {
1202     struct ccs_no_rewrite_entry *ptr;
1203     struct ccs_no_rewrite_entry *tmp;
1204     LIST_HEAD(q);
1205     /***** WRITER SECTION START *****/
1206     down_write(&ccs_policy_lock);
1207     list_for_each_entry_safe(ptr, tmp, &ccs_no_rewrite_list, list) {
1208     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1209     continue;
1210     list_del(&ptr->list);
1211     list_add(&ptr->list, &q);
1212     }
1213     up_write(&ccs_policy_lock);
1214     /***** WRITER SECTION END *****/
1215     list_for_each_entry_safe(ptr, tmp, &q, list) {
1216     ccs_put_name(ptr->pattern);
1217     list_del(&ptr->list);
1218     ccs_memory_free(ptr);
1219     }
1220     }
1221    
1222     /**
1223     * ccs_cleanup_initializer - Clean up deleted "struct ccs_domain_initializer_entry".
1224     */
1225     static void ccs_cleanup_initializer(void)
1226     {
1227     struct ccs_domain_initializer_entry *ptr;
1228     struct ccs_domain_initializer_entry *tmp;
1229     LIST_HEAD(q);
1230     /***** WRITER SECTION START *****/
1231     down_write(&ccs_policy_lock);
1232     list_for_each_entry_safe(ptr, tmp, &ccs_domain_initializer_list,
1233     list) {
1234     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1235     continue;
1236     list_del(&ptr->list);
1237     list_add(&ptr->list, &q);
1238     }
1239     up_write(&ccs_policy_lock);
1240     /***** WRITER SECTION END *****/
1241     list_for_each_entry_safe(ptr, tmp, &q, list) {
1242     ccs_put_name(ptr->domainname);
1243     ccs_put_name(ptr->program);
1244     list_del(&ptr->list);
1245     ccs_memory_free(ptr);
1246     }
1247     }
1248    
1249     /**
1250     * ccs_cleanup_keep_domain - Clean up deleted "struct ccs_domain_keeper_entry".
1251     */
1252     static void ccs_cleanup_keep_domain(void)
1253     {
1254     struct ccs_domain_keeper_entry *ptr;
1255     struct ccs_domain_keeper_entry *tmp;
1256     LIST_HEAD(q);
1257     /***** WRITER SECTION START *****/
1258     down_write(&ccs_policy_lock);
1259     list_for_each_entry_safe(ptr, tmp, &ccs_domain_keeper_list, list) {
1260     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1261     continue;
1262     list_del(&ptr->list);
1263     list_add(&ptr->list, &q);
1264     }
1265     up_write(&ccs_policy_lock);
1266     /***** WRITER SECTION END *****/
1267     list_for_each_entry_safe(ptr, tmp, &q, list) {
1268     ccs_put_name(ptr->domainname);
1269     ccs_put_name(ptr->program);
1270     list_del(&ptr->list);
1271     ccs_memory_free(ptr);
1272     }
1273     }
1274    
1275     /**
1276     * ccs_cleanup_alias - Clean up deleted "struct ccs_alias_entry".
1277     */
1278     static void ccs_cleanup_alias(void)
1279     {
1280     struct ccs_alias_entry *ptr;
1281     struct ccs_alias_entry *tmp;
1282     LIST_HEAD(q);
1283     /***** WRITER SECTION START *****/
1284     down_write(&ccs_policy_lock);
1285     list_for_each_entry_safe(ptr, tmp, &ccs_alias_list, list) {
1286     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1287     continue;
1288     list_del(&ptr->list);
1289     list_add(&ptr->list, &q);
1290     }
1291     up_write(&ccs_policy_lock);
1292     /***** WRITER SECTION END *****/
1293     list_for_each_entry_safe(ptr, tmp, &q, list) {
1294     ccs_put_name(ptr->original_name);
1295     ccs_put_name(ptr->aliased_name);
1296     list_del(&ptr->list);
1297     ccs_memory_free(ptr);
1298     }
1299     }
1300    
1301     /**
1302     * ccs_cleanup_aggregator - Clean up deleted "struct ccs_aggregator_entry".
1303     */
1304     static void ccs_cleanup_aggregator(void)
1305     {
1306     struct ccs_aggregator_entry *ptr;
1307     struct ccs_aggregator_entry *tmp;
1308     LIST_HEAD(q);
1309     /***** WRITER SECTION START *****/
1310     down_write(&ccs_policy_lock);
1311     list_for_each_entry_safe(ptr, tmp, &ccs_aggregator_list, list) {
1312     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1313     continue;
1314     list_del(&ptr->list);
1315     list_add(&ptr->list, &q);
1316     }
1317     up_write(&ccs_policy_lock);
1318     /***** WRITER SECTION END *****/
1319     list_for_each_entry_safe(ptr, tmp, &q, list) {
1320     ccs_put_name(ptr->original_name);
1321     ccs_put_name(ptr->aggregated_name);
1322     list_del(&ptr->list);
1323     ccs_memory_free(ptr);
1324     }
1325     }
1326    
1327     /**
1328     * ccs_cleanup_manager - Clean up deleted "struct ccs_policy_manager_entry".
1329     */
1330     static void ccs_cleanup_manager(void)
1331     {
1332     struct ccs_policy_manager_entry *ptr;
1333     struct ccs_policy_manager_entry *tmp;
1334     LIST_HEAD(q);
1335     /***** WRITER SECTION START *****/
1336     down_write(&ccs_policy_lock);
1337     list_for_each_entry_safe(ptr, tmp, &ccs_policy_manager_list, list) {
1338     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1339     continue;
1340     list_del(&ptr->list);
1341     list_add(&ptr->list, &q);
1342     }
1343     up_write(&ccs_policy_lock);
1344     /***** WRITER SECTION END *****/
1345     list_for_each_entry_safe(ptr, tmp, &q, list) {
1346     ccs_put_name(ptr->manager);
1347     list_del(&ptr->list);
1348     ccs_memory_free(ptr);
1349     }
1350     }
1351    
1352     /* For compatibility with older kernels. */
1353     #ifndef for_each_process
1354     #define for_each_process for_each_task
1355     #endif
1356    
1357     /**
1358     * ccs_used_by_task - Check whether the given pointer is referenced by a task.
1359     *
1360     * @domain: Pointer to "struct ccs_domain_info".
1361     *
1362     * Returns true if @ptr is in use, false otherwise.
1363     */
1364     static bool ccs_used_by_task(struct ccs_domain_info *domain)
1365     {
1366     bool in_use = false;
1367     struct task_struct *p;
1368     /***** CRITICAL SECTION START *****/
1369     read_lock(&tasklist_lock);
1370     for_each_process(p) {
1371     if (p->ccs_domain_info != domain)
1372     continue;
1373     in_use = true;
1374     break;
1375     }
1376     read_unlock(&tasklist_lock);
1377     /***** CRITICAL SECTION END *****/
1378     return in_use;
1379     }
1380    
1381     /**
1382     * ccs_cleanup_domain_policy - Clean up deleted domain policy.
1383     */
1384     static void ccs_cleanup_domain_policy(void)
1385     {
1386     struct ccs_domain_info *domain;
1387     struct ccs_domain_info *next_domain;
1388     struct ccs_acl_info *acl;
1389     struct ccs_acl_info *next_acl;
1390     LIST_HEAD(q_domain);
1391     LIST_HEAD(q_acl);
1392     /***** WRITER SECTION START *****/
1393     down_write(&ccs_policy_lock);
1394     list_for_each_entry_safe(domain, next_domain, &ccs_domain_list,
1395     list) {
1396     const bool can_delete_domain = domain->is_deleted &&
1397     !ccs_used_by_cookie(domain) &&
1398     !ccs_used_by_task(domain);
1399     if (can_delete_domain) {
1400     list_for_each_entry(acl, &domain->acl_info_list, list)
1401     acl->type |= ACL_DELETED;
1402     }
1403     list_for_each_entry_safe(acl, next_acl, &domain->acl_info_list,
1404     list) {
1405     if (!(acl->type & ACL_DELETED)
1406     || ccs_used_by_cookie(acl))
1407     continue;
1408     list_del(&acl->list);
1409     list_add(&acl->list, &q_acl);
1410     }
1411     if (can_delete_domain && list_empty(&domain->acl_info_list)) {
1412     list_del(&domain->list);
1413     list_add(&domain->list, &q_domain);
1414     }
1415     }
1416     up_write(&ccs_policy_lock);
1417     /***** WRITER SECTION END *****/
1418     list_for_each_entry_safe(acl, next_acl, &q_acl, list) {
1419 kumaneko 2553 ccs_put_condition(acl->cond);
1420 kumaneko 2540 switch (ccs_acl_type1(acl)) {
1421     struct ccs_single_path_acl_record *acl1;
1422     struct ccs_double_path_acl_record *acl2;
1423     struct ccs_ip_network_acl_record *acl3;
1424     struct ccs_ioctl_acl_record *acl4;
1425     struct ccs_argv0_acl_record *acl5;
1426     struct ccs_env_acl_record *acl6;
1427     struct ccs_capability_acl_record *acl7;
1428     struct ccs_signal_acl_record *acl8;
1429     struct ccs_execute_handler_record *acl9;
1430     case TYPE_SINGLE_PATH_ACL:
1431     acl1 = container_of(acl,
1432     struct ccs_single_path_acl_record,
1433     head);
1434     if (acl1->u_is_group)
1435     ccs_put_path_group(acl1->u.group);
1436     else
1437     ccs_put_name(acl1->u.filename);
1438     break;
1439     case TYPE_DOUBLE_PATH_ACL:
1440     acl2 = container_of(acl,
1441     struct ccs_double_path_acl_record,
1442     head);
1443     if (acl2->u1_is_group)
1444     ccs_put_path_group(acl2->u1.group1);
1445     else
1446     ccs_put_name(acl2->u1.filename1);
1447     if (acl2->u2_is_group)
1448     ccs_put_path_group(acl2->u2.group2);
1449     else
1450     ccs_put_name(acl2->u2.filename2);
1451     break;
1452     case TYPE_IP_NETWORK_ACL:
1453     acl3 = container_of(acl,
1454     struct ccs_ip_network_acl_record,
1455     head);
1456     if (acl3->record_type == IP_RECORD_TYPE_ADDRESS_GROUP)
1457     ccs_put_address_group(acl3->u.group);
1458     else if (acl3->record_type == IP_RECORD_TYPE_IPv6) {
1459     ccs_put_ipv6_address(acl3->u.ipv6.min);
1460     ccs_put_ipv6_address(acl3->u.ipv6.max);
1461     }
1462     break;
1463     case TYPE_IOCTL_ACL:
1464     acl4 = container_of(acl, struct ccs_ioctl_acl_record,
1465     head);
1466     if (acl4->u_is_group)
1467     ccs_put_path_group(acl4->u.group);
1468     else
1469     ccs_put_name(acl4->u.filename);
1470     break;
1471     case TYPE_ARGV0_ACL:
1472     acl5 = container_of(acl, struct ccs_argv0_acl_record,
1473     head);
1474     ccs_put_name(acl5->argv0);
1475     break;
1476     case TYPE_ENV_ACL:
1477     acl6 = container_of(acl, struct ccs_env_acl_record,
1478     head);
1479     ccs_put_name(acl6->env);
1480     break;
1481     case TYPE_CAPABILITY_ACL:
1482     acl7 = container_of(acl,
1483     struct ccs_capability_acl_record,
1484     head);
1485     break;
1486     case TYPE_SIGNAL_ACL:
1487     acl8 = container_of(acl, struct ccs_signal_acl_record,
1488     head);
1489     ccs_put_name(acl8->domainname);
1490     break;
1491     case TYPE_EXECUTE_HANDLER:
1492     case TYPE_DENIED_EXECUTE_HANDLER:
1493     acl9 = container_of(acl,
1494     struct ccs_execute_handler_record,
1495     head);
1496     ccs_put_name(acl9->handler);
1497     break;
1498     }
1499     list_del(&acl->list);
1500     ccs_memory_free(acl);
1501     }
1502     list_for_each_entry_safe(domain, next_domain, &q_domain, list) {
1503     ccs_put_name(domain->domainname);
1504     list_del(&domain->list);
1505     ccs_memory_free(domain);
1506     }
1507     }
1508    
1509     /**
1510 kumaneko 2575 * ccs_cleanup_path_group - Clean up deleted "struct ccs_path_group_entry".
1511     */
1512     static void ccs_cleanup_path_group(void)
1513     {
1514     struct ccs_path_group_entry *group;
1515     struct ccs_path_group_entry *next_group;
1516     struct ccs_path_group_member *member;
1517     struct ccs_path_group_member *next_member;
1518     LIST_HEAD(q_group);
1519     LIST_HEAD(q_member);
1520     /***** WRITER SECTION START *****/
1521     down_write(&ccs_policy_lock);
1522     list_for_each_entry_safe(group, next_group, &ccs_path_group_list,
1523     list) {
1524     list_for_each_entry_safe(member, next_member,
1525     &group->path_group_member_list,
1526     list) {
1527     if (!member->is_deleted)
1528     break;
1529     list_del(&member->list);
1530     list_add(&member->list, &q_member);
1531     }
1532     if (list_empty(&group->path_group_member_list) &&
1533     !atomic_read(&group->users)) {
1534     list_del(&group->list);
1535     list_add(&group->list, &q_group);
1536     }
1537     }
1538     up_write(&ccs_policy_lock);
1539     /***** WRITER SECTION END *****/
1540     list_for_each_entry_safe(member, next_member, &q_member, list) {
1541     ccs_put_name(member->member_name);
1542     list_del(&member->list);
1543     ccs_free_element(member);
1544     }
1545     list_for_each_entry_safe(group, next_group, &q_group, list) {
1546     ccs_put_name(group->group_name);
1547     list_del(&group->list);
1548     ccs_free_element(group);
1549     }
1550     }
1551    
1552     /**
1553     * ccs_cleanup_address_group - Clean up deleted "struct ccs_address_group_entry".
1554     */
1555     static void ccs_cleanup_address_group(void)
1556     {
1557     struct ccs_address_group_entry *group;
1558     struct ccs_address_group_entry *next_group;
1559     struct ccs_address_group_member *member;
1560     struct ccs_address_group_member *next_member;
1561     LIST_HEAD(q_group);
1562     LIST_HEAD(q_member);
1563     /***** WRITER SECTION START *****/
1564     down_write(&ccs_policy_lock);
1565     list_for_each_entry_safe(group, next_group, &ccs_address_group_list,
1566     list) {
1567     list_for_each_entry_safe(member, next_member,
1568     &group->address_group_member_list,
1569     list) {
1570     if (!member->is_deleted)
1571     break;
1572     list_del(&member->list);
1573     list_add(&member->list, &q_member);
1574     }
1575     if (list_empty(&group->address_group_member_list) &&
1576     !atomic_read(&group->users)) {
1577     list_del(&group->list);
1578     list_add(&group->list, &q_group);
1579     }
1580     }
1581     up_write(&ccs_policy_lock);
1582     /***** WRITER SECTION END *****/
1583     list_for_each_entry_safe(member, next_member, &q_member, list) {
1584     if (member->is_ipv6) {
1585     ccs_put_ipv6_address(member->min.ipv6);
1586     ccs_put_ipv6_address(member->max.ipv6);
1587     }
1588     list_del(&member->list);
1589     ccs_free_element(member);
1590     }
1591     list_for_each_entry_safe(group, next_group, &q_group, list) {
1592     ccs_put_name(group->group_name);
1593     list_del(&group->list);
1594     ccs_free_element(group);
1595     }
1596     }
1597    
1598     /**
1599     * ccs_cleanup_mount - Clean up deleted "struct ccs_mount_entry".
1600     */
1601     static void ccs_cleanup_mount(void)
1602     {
1603     struct ccs_mount_entry *ptr;
1604     struct ccs_mount_entry *tmp;
1605     LIST_HEAD(q);
1606     /***** WRITER SECTION START *****/
1607     down_write(&ccs_policy_lock);
1608     list_for_each_entry_safe(ptr, tmp, &ccs_mount_list, list) {
1609     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1610     continue;
1611     list_del(&ptr->list);
1612     list_add(&ptr->list, &q);
1613     }
1614     up_write(&ccs_policy_lock);
1615     /***** WRITER SECTION END *****/
1616     list_for_each_entry_safe(ptr, tmp, &q, list) {
1617     ccs_put_name(ptr->dev_name);
1618     ccs_put_name(ptr->dir_name);
1619     ccs_put_name(ptr->fs_type);
1620     list_del(&ptr->list);
1621     ccs_memory_free(ptr);
1622     }
1623     }
1624    
1625     /**
1626     * ccs_cleanup_no_umount - Clean up deleted "struct ccs_no_umount_entry".
1627     */
1628     static void ccs_cleanup_no_umount(void)
1629     {
1630     struct ccs_no_umount_entry *ptr;
1631     struct ccs_no_umount_entry *tmp;
1632     LIST_HEAD(q);
1633     /***** WRITER SECTION START *****/
1634     down_write(&ccs_policy_lock);
1635     list_for_each_entry_safe(ptr, tmp, &ccs_no_umount_list, list) {
1636     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1637     continue;
1638     list_del(&ptr->list);
1639     list_add(&ptr->list, &q);
1640     }
1641     up_write(&ccs_policy_lock);
1642     /***** WRITER SECTION END *****/
1643     list_for_each_entry_safe(ptr, tmp, &q, list) {
1644     ccs_put_name(ptr->dir);
1645     list_del(&ptr->list);
1646     ccs_memory_free(ptr);
1647     }
1648     }
1649    
1650     /**
1651     * ccs_cleanup_pivot_root - Clean up deleted "struct ccs_pivot_root_entry".
1652     */
1653     static void ccs_cleanup_pivot_root(void)
1654     {
1655     struct ccs_pivot_root_entry *ptr;
1656     struct ccs_pivot_root_entry *tmp;
1657     LIST_HEAD(q);
1658     /***** WRITER SECTION START *****/
1659     down_write(&ccs_policy_lock);
1660     list_for_each_entry_safe(ptr, tmp, &ccs_pivot_root_list, list) {
1661     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1662     continue;
1663     list_del(&ptr->list);
1664     list_add(&ptr->list, &q);
1665     }
1666     up_write(&ccs_policy_lock);
1667     /***** WRITER SECTION END *****/
1668     list_for_each_entry_safe(ptr, tmp, &q, list) {
1669     ccs_put_name(ptr->old_root);
1670     ccs_put_name(ptr->new_root);
1671     list_del(&ptr->list);
1672     ccs_memory_free(ptr);
1673     }
1674     }
1675    
1676     /**
1677     * ccs_cleanup_chroot - Clean up deleted "struct ccs_chroot_entry".
1678     */
1679     static void ccs_cleanup_chroot(void)
1680     {
1681     struct ccs_chroot_entry *ptr;
1682     struct ccs_chroot_entry *tmp;
1683     LIST_HEAD(q);
1684     /***** WRITER SECTION START *****/
1685     down_write(&ccs_policy_lock);
1686     list_for_each_entry_safe(ptr, tmp, &ccs_chroot_list, list) {
1687     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1688     continue;
1689     list_del(&ptr->list);
1690     list_add(&ptr->list, &q);
1691     }
1692     up_write(&ccs_policy_lock);
1693     /***** WRITER SECTION END *****/
1694     list_for_each_entry_safe(ptr, tmp, &q, list) {
1695     ccs_put_name(ptr->dir);
1696     list_del(&ptr->list);
1697     ccs_memory_free(ptr);
1698     }
1699     }
1700    
1701     /**
1702     * ccs_cleanup_reservedport - Clean up deleted "struct ccs_reserved_entry".
1703     */
1704     static void ccs_cleanup_reservedport(void)
1705     {
1706     struct ccs_reserved_entry *ptr;
1707     struct ccs_reserved_entry *tmp;
1708     LIST_HEAD(q);
1709     /***** WRITER SECTION START *****/
1710     down_write(&ccs_policy_lock);
1711     list_for_each_entry_safe(ptr, tmp, &ccs_reservedport_list, list) {
1712     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1713     continue;
1714     list_del(&ptr->list);
1715     list_add(&ptr->list, &q);
1716     }
1717     up_write(&ccs_policy_lock);
1718     /***** WRITER SECTION END *****/
1719     list_for_each_entry_safe(ptr, tmp, &q, list) {
1720     list_del(&ptr->list);
1721     ccs_memory_free(ptr);
1722     }
1723     }
1724    
1725     /**
1726 kumaneko 2576 * ccs_cleanup_condition - Clean up deleted "struct ccs_condition".
1727     */
1728     static void ccs_cleanup_condition(void)
1729     {
1730     struct ccs_condition *ptr;
1731     struct ccs_condition *tmp;
1732     LIST_HEAD(q);
1733     /***** WRITER SECTION START *****/
1734     down_write(&ccs_policy_lock);
1735     list_for_each_entry_safe(ptr, tmp, &ccs_condition_list, list) {
1736     if (atomic_read(&ptr->users) || ccs_used_by_cookie(ptr))
1737     continue;
1738     list_del(&ptr->list);
1739     list_add(&ptr->list, &q);
1740     }
1741     up_write(&ccs_policy_lock);
1742     /***** WRITER SECTION END *****/
1743     list_for_each_entry_safe(ptr, tmp, &q, list) {
1744     int i;
1745     u16 condc = ptr->head.condc;
1746     u16 argc = ptr->head.argc;
1747     u16 envc = ptr->head.envc;
1748     u16 symlinkc = ptr->head.symlinkc;
1749     unsigned long *ptr2 = (unsigned long *) (ptr + 1);
1750     struct ccs_argv_entry *argv = (struct ccs_argv_entry *)
1751     (ptr2 + condc);
1752     struct ccs_envp_entry *envp = (struct ccs_envp_entry *)
1753     (argv + argc);
1754     struct ccs_symlinkp_entry *symlinkp
1755     = (struct ccs_symlinkp_entry *) (envp + envc);
1756     for (i = 0; i < argc; i++)
1757     ccs_put_name(argv[i].value);
1758     for (i = 0; i < envc; i++) {
1759     ccs_put_name(envp[i].name);
1760     ccs_put_name(envp[i].value);
1761     }
1762     for (i = 0; i < symlinkc; i++)
1763     ccs_put_name(symlinkp[i].value);
1764     list_del(&ptr->list);
1765     ccs_memory_free(ptr);
1766     }
1767     }
1768    
1769     /**
1770 kumaneko 2540 * ccs_run_garbage_collector - Run garbage collector.
1771     */
1772     void ccs_run_garbage_collector(void)
1773     {
1774     ccs_cleanup_allow_read();
1775     ccs_cleanup_allow_env();
1776     ccs_cleanup_file_pattern();
1777     ccs_cleanup_no_rewrite();
1778     ccs_cleanup_initializer();
1779     ccs_cleanup_keep_domain();
1780     ccs_cleanup_alias();
1781     ccs_cleanup_aggregator();
1782     ccs_cleanup_manager();
1783     ccs_cleanup_domain_policy();
1784 kumaneko 2575 ccs_cleanup_path_group();
1785     ccs_cleanup_address_group();
1786     ccs_cleanup_mount();
1787     ccs_cleanup_no_umount();
1788     ccs_cleanup_pivot_root();
1789     ccs_cleanup_chroot();
1790     ccs_cleanup_reservedport();
1791 kumaneko 2576 ccs_cleanup_condition();
1792 kumaneko 2540 }
1793 kumaneko 2576

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