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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2546 - (hide annotations) (download) (as text)
Thu May 14 08:30:20 2009 UTC (15 years ago) by kumaneko
Original Path: branches/ccs-patch/fs/realpath.c
File MIME type: text/x-csrc
File size: 38216 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     struct ccs_addr_entry *entry;
604     struct ccs_addr_entry *ptr;
605     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     struct ccs_addr_entry *ptr;
639     bool can_delete = false;
640     if (!addr)
641     return;
642     ptr = container_of(addr, struct ccs_addr_entry, addr);
643     /***** 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 2002 static unsigned int ccs_allocated_memory_for_savename;
656     static unsigned int ccs_quota_for_savename;
657 kumaneko 111
658     #define MAX_HASH 256
659    
660 kumaneko 1052 /* Structure for string data. */
661 kumaneko 2002 struct ccs_name_entry {
662 kumaneko 2540 struct list_head list;
663     atomic_t users;
664 kumaneko 2002 struct ccs_path_info entry;
665 kumaneko 214 };
666 kumaneko 111
667 kumaneko 1052 /* Structure for available memory region. */
668 kumaneko 2002 struct ccs_free_memory_block_list {
669 kumaneko 731 struct list_head list;
670 kumaneko 1052 char *ptr; /* Pointer to a free area. */
671     int len; /* Length of the area. */
672 kumaneko 214 };
673 kumaneko 111
674 kumaneko 2002 /* The list for "struct ccs_name_entry". */
675 kumaneko 2540 static struct list_head ccs_name_list[MAX_HASH];
676     static DEFINE_MUTEX(ccs_name_list_lock);
677 kumaneko 731
678 kumaneko 1052 /**
679 kumaneko 2540 * ccs_get_name - Allocate memory for string data.
680 kumaneko 1052 *
681     * @name: The string to store into the permernent memory.
682     *
683 kumaneko 2002 * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
684 kumaneko 1052 */
685 kumaneko 2540 const struct ccs_path_info *ccs_get_name(const char *name)
686 kumaneko 111 {
687 kumaneko 2002 struct ccs_name_entry *ptr;
688 kumaneko 111 unsigned int hash;
689     int len;
690 kumaneko 2540 int allocated_len;
691    
692 kumaneko 1052 if (!name)
693     return NULL;
694 kumaneko 111 len = strlen(name) + 1;
695     if (len > CCS_MAX_PATHNAME_LEN) {
696 kumaneko 1052 printk(KERN_WARNING "ERROR: Name too long "
697 kumaneko 2540 "for %s().\n", __func__);
698 kumaneko 111 return NULL;
699     }
700     hash = full_name_hash((const unsigned char *) name, len - 1);
701 kumaneko 2540 /***** EXCLUSIVE SECTION START *****/
702     mutex_lock(&ccs_name_list_lock);
703     list_for_each_entry(ptr, &ccs_name_list[hash % MAX_HASH], list) {
704     if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
705     continue;
706     atomic_inc(&ptr->users);
707     goto out;
708 kumaneko 111 }
709 kumaneko 2540 ptr = kmalloc(sizeof(*ptr) + len, GFP_KERNEL);
710     allocated_len = ptr ? ksize(ptr) : 0;
711     if (!allocated_len ||
712     (ccs_quota_for_savename &&
713     ccs_allocated_memory_for_savename + allocated_len
714     > ccs_quota_for_savename)) {
715     kfree(ptr);
716     ptr = NULL;
717     printk(KERN_WARNING "ERROR: Out of memory for %s().\n",
718     __func__);
719 kumaneko 2040 if (!ccs_policy_loaded)
720 kumaneko 1052 panic("MAC Initialization failed.\n");
721 kumaneko 731 goto out;
722     }
723 kumaneko 2540 ccs_allocated_memory_for_savename += allocated_len;
724     ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
725     memmove((char *) ptr->entry.name, name, len);
726     atomic_set(&ptr->users, 1);
727 kumaneko 1052 ccs_fill_path_info(&ptr->entry);
728 kumaneko 2540 list_add_tail(&ptr->list, &ccs_name_list[hash % MAX_HASH]);
729 kumaneko 111 out:
730 kumaneko 2540 mutex_unlock(&ccs_name_list_lock);
731     /***** EXCLUSIVE SECTION END *****/
732 kumaneko 111 return ptr ? &ptr->entry : NULL;
733     }
734    
735 kumaneko 2540 /**
736     * ccs_put_name - Delete shared memory for string data.
737     *
738     * @name: Pointer to "struct ccs_path_info".
739     */
740     void ccs_put_name(const struct ccs_path_info *name)
741     {
742     struct ccs_name_entry *ptr;
743     bool can_delete = false;
744     if (!name)
745     return;
746     ptr = container_of(name, struct ccs_name_entry, entry);
747     /***** EXCLUSIVE SECTION START *****/
748     mutex_lock(&ccs_name_list_lock);
749     if (atomic_dec_and_test(&ptr->users)) {
750     list_del(&ptr->list);
751     can_delete = true;
752     }
753     mutex_unlock(&ccs_name_list_lock);
754     /***** EXCLUSIVE SECTION END *****/
755     if (can_delete) {
756     ccs_allocated_memory_for_savename -= ksize(ptr);
757     kfree(ptr);
758     }
759     }
760    
761 kumaneko 1052 /* Structure for temporarily allocated memory. */
762 kumaneko 2002 struct ccs_cache_entry {
763 kumaneko 111 struct list_head list;
764     void *ptr;
765     int size;
766 kumaneko 214 };
767 kumaneko 111
768 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
769     static struct kmem_cache *ccs_cachep;
770 kumaneko 111 #else
771 kumaneko 1052 static kmem_cache_t *ccs_cachep;
772 kumaneko 111 #endif
773    
774 kumaneko 1052 /**
775     * ccs_realpath_init - Initialize realpath related code.
776     *
777     * Returns 0.
778     */
779     static int __init ccs_realpath_init(void)
780 kumaneko 111 {
781 kumaneko 731 int i;
782 kumaneko 2540 struct ccs_cookie cookie;
783     /* Constraint for ccs_get_name(). */
784 kumaneko 1052 if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE)
785     panic("Bad size.");
786 kumaneko 2037 /* Constraint for "struct ccs_execve_entry"->tmp users. */
787     if (CCS_MAX_PATHNAME_LEN > CCS_EXEC_TMPSIZE)
788     panic("Bad size.");
789 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
790 kumaneko 2002 ccs_cachep = kmem_cache_create("ccs_cache",
791     sizeof(struct ccs_cache_entry),
792 kumaneko 1052 0, 0, NULL);
793 kumaneko 316 #else
794 kumaneko 2002 ccs_cachep = kmem_cache_create("ccs_cache",
795     sizeof(struct ccs_cache_entry),
796 kumaneko 1052 0, 0, NULL, NULL);
797 kumaneko 316 #endif
798 kumaneko 1052 if (!ccs_cachep)
799     panic("Can't create cache.\n");
800     for (i = 0; i < MAX_HASH; i++)
801 kumaneko 2540 INIT_LIST_HEAD(&ccs_name_list[i]);
802     INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
803     ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
804     list_add_tail(&ccs_kernel_domain.list, &ccs_domain_list);
805     if (!ccs_find_domain(ROOT_NAME, &cookie) ||
806     cookie.u.domain != &ccs_kernel_domain)
807 kumaneko 2282 panic("Can't register ccs_kernel_domain");
808 kumaneko 2308 #ifdef CONFIG_TOMOYO_BUILTIN_INITIALIZERS
809     {
810     /* Load built-in policy. */
811 kumaneko 2392 static char ccs_builtin_initializers[] __initdata
812     = CONFIG_TOMOYO_BUILTIN_INITIALIZERS;
813     char *cp = ccs_builtin_initializers;
814     ccs_normalize_line(cp);
815     while (cp && *cp) {
816     char *cp2 = strchr(cp, ' ');
817     if (cp2)
818     *cp2++ = '\0';
819     ccs_write_domain_initializer_policy(cp, false, false);
820     cp = cp2;
821 kumaneko 2308 }
822     }
823     #endif
824 kumaneko 1052 return 0;
825 kumaneko 111 }
826    
827 kumaneko 1084 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
828 kumaneko 1052 __initcall(ccs_realpath_init);
829 kumaneko 1084 #else
830 kumaneko 1106 core_initcall(ccs_realpath_init);
831 kumaneko 1084 #endif
832 kumaneko 1052
833 kumaneko 2002 /* The list for "struct ccs_cache_entry". */
834     static LIST_HEAD(ccs_audit_cache_list);
835     static LIST_HEAD(ccs_acl_cache_list);
836     static DEFINE_SPINLOCK(ccs_cache_list_lock);
837 kumaneko 1052
838 kumaneko 2002 static unsigned int ccs_dynamic_memory_size;
839     static unsigned int ccs_quota_for_dynamic;
840 kumaneko 1052
841     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
842     /**
843 kumaneko 2002 * ccs_round2 - Rounded up to power-of-two value.
844 kumaneko 1052 *
845     * @size: Size in bytes.
846     *
847     * Returns power-of-two of @size.
848     */
849 kumaneko 2002 static int ccs_round2(size_t size)
850 kumaneko 581 {
851     #if PAGE_SIZE == 4096
852     size_t bsize = 32;
853     #else
854     size_t bsize = 64;
855     #endif
856 kumaneko 1064 while (size > bsize)
857     bsize <<= 1;
858 kumaneko 581 return bsize;
859     }
860     #endif
861    
862 kumaneko 1052 /**
863 kumaneko 1793 * ccs_alloc - Allocate memory for temporary purpose.
864 kumaneko 1052 *
865     * @size: Size in bytes.
866     *
867     * Returns pointer to allocated memory on success, NULL otherwise.
868     */
869 kumaneko 1907 void *ccs_alloc(const size_t size, const _Bool check_quota)
870 kumaneko 111 {
871 kumaneko 2002 struct ccs_cache_entry *new_entry;
872 kumaneko 1055 void *ret = kzalloc(size, GFP_KERNEL);
873 kumaneko 1052 if (!ret)
874     goto out;
875 kumaneko 1031 new_entry = kmem_cache_alloc(ccs_cachep, GFP_KERNEL);
876     if (!new_entry) {
877 kumaneko 1064 kfree(ret);
878     ret = NULL;
879 kumaneko 1031 goto out;
880     }
881     INIT_LIST_HEAD(&new_entry->list);
882     new_entry->ptr = ret;
883 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
884 kumaneko 1031 new_entry->size = ksize(ret);
885     #else
886 kumaneko 2002 new_entry->size = ccs_round2(size);
887 kumaneko 1031 #endif
888 kumaneko 1903 if (check_quota) {
889     bool quota_exceeded = false;
890     /***** CRITICAL SECTION START *****/
891 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
892     if (!ccs_quota_for_dynamic ||
893     ccs_dynamic_memory_size + new_entry->size
894     <= ccs_quota_for_dynamic) {
895     list_add_tail(&new_entry->list, &ccs_audit_cache_list);
896     ccs_dynamic_memory_size += new_entry->size;
897 kumaneko 1903 } else {
898     quota_exceeded = true;
899     }
900 kumaneko 2002 spin_unlock(&ccs_cache_list_lock);
901 kumaneko 1903 /***** CRITICAL SECTION END *****/
902     if (quota_exceeded) {
903     kfree(ret);
904     kmem_cache_free(ccs_cachep, new_entry);
905     ret = NULL;
906     }
907     } else {
908     /***** CRITICAL SECTION START *****/
909 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
910     list_add(&new_entry->list, &ccs_acl_cache_list);
911     ccs_dynamic_memory_size += new_entry->size;
912     spin_unlock(&ccs_cache_list_lock);
913 kumaneko 1903 /***** CRITICAL SECTION END *****/
914     }
915 kumaneko 1031 out:
916 kumaneko 214 return ret;
917 kumaneko 111 }
918    
919 kumaneko 1052 /**
920     * ccs_free - Release memory allocated by ccs_alloc().
921     *
922     * @p: Pointer returned by ccs_alloc(). May be NULL.
923     *
924     * Returns nothing.
925     */
926 kumaneko 111 void ccs_free(const void *p)
927     {
928     struct list_head *v;
929 kumaneko 2002 struct ccs_cache_entry *entry = NULL;
930 kumaneko 1052 if (!p)
931     return;
932     /***** CRITICAL SECTION START *****/
933 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
934     list_for_each(v, &ccs_acl_cache_list) {
935     entry = list_entry(v, struct ccs_cache_entry, list);
936 kumaneko 1903 if (entry->ptr == p)
937     break;
938     entry = NULL;
939     }
940     if (!entry) {
941 kumaneko 2002 list_for_each(v, &ccs_audit_cache_list) {
942     entry = list_entry(v, struct ccs_cache_entry, list);
943 kumaneko 1903 if (entry->ptr == p)
944     break;
945 kumaneko 1064 entry = NULL;
946 kumaneko 111 }
947 kumaneko 1903 }
948     if (entry) {
949 kumaneko 111 list_del(&entry->list);
950 kumaneko 2002 ccs_dynamic_memory_size -= entry->size;
951 kumaneko 111 }
952 kumaneko 2002 spin_unlock(&ccs_cache_list_lock);
953 kumaneko 1052 /***** CRITICAL SECTION END *****/
954 kumaneko 111 if (entry) {
955     kfree(p);
956     kmem_cache_free(ccs_cachep, entry);
957     } else {
958 kumaneko 1052 printk(KERN_WARNING "BUG: ccs_free() with invalid pointer.\n");
959 kumaneko 2546 dump_stack();
960 kumaneko 111 }
961     }
962 kumaneko 1180
963     /**
964     * ccs_read_memory_counter - Check for memory usage.
965     *
966     * @head: Pointer to "struct ccs_io_buffer".
967     *
968     * Returns memory usage.
969     */
970     int ccs_read_memory_counter(struct ccs_io_buffer *head)
971     {
972     if (!head->read_eof) {
973 kumaneko 2002 const unsigned int shared = ccs_allocated_memory_for_savename;
974     const unsigned int private = ccs_allocated_memory_for_elements;
975     const unsigned int dynamic = ccs_dynamic_memory_size;
976 kumaneko 1180 char buffer[64];
977     memset(buffer, 0, sizeof(buffer));
978 kumaneko 2002 if (ccs_quota_for_savename)
979 kumaneko 1180 snprintf(buffer, sizeof(buffer) - 1,
980 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_savename);
981 kumaneko 1180 else
982     buffer[0] = '\0';
983     ccs_io_printf(head, "Shared: %10u%s\n", shared, buffer);
984 kumaneko 2002 if (ccs_quota_for_elements)
985 kumaneko 1180 snprintf(buffer, sizeof(buffer) - 1,
986 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_elements);
987 kumaneko 1180 else
988     buffer[0] = '\0';
989     ccs_io_printf(head, "Private: %10u%s\n", private, buffer);
990 kumaneko 2002 if (ccs_quota_for_dynamic)
991 kumaneko 1903 snprintf(buffer, sizeof(buffer) - 1,
992 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_dynamic);
993 kumaneko 1903 else
994     buffer[0] = '\0';
995     ccs_io_printf(head, "Dynamic: %10u%s\n", dynamic, buffer);
996 kumaneko 1180 ccs_io_printf(head, "Total: %10u\n",
997     shared + private + dynamic);
998     head->read_eof = true;
999     }
1000     return 0;
1001     }
1002    
1003     /**
1004     * ccs_write_memory_quota - Set memory quota.
1005     *
1006     * @head: Pointer to "struct ccs_io_buffer".
1007     *
1008     * Returns 0.
1009     */
1010     int ccs_write_memory_quota(struct ccs_io_buffer *head)
1011     {
1012     char *data = head->write_buf;
1013     unsigned int size;
1014     if (sscanf(data, "Shared: %u", &size) == 1)
1015 kumaneko 2002 ccs_quota_for_savename = size;
1016 kumaneko 1180 else if (sscanf(data, "Private: %u", &size) == 1)
1017 kumaneko 2002 ccs_quota_for_elements = size;
1018 kumaneko 1903 else if (sscanf(data, "Dynamic: %u", &size) == 1)
1019 kumaneko 2002 ccs_quota_for_dynamic = size;
1020 kumaneko 1180 return 0;
1021     }
1022 kumaneko 2540
1023     /* List of pointers referenced by cookies. */
1024     static LIST_HEAD(ccs_cookie_list);
1025     static DEFINE_RWLOCK(ccs_cookie_list_lock);
1026    
1027     /**
1028     * ccs_add_cookie - Add a cookie to cookie list.
1029     *
1030     * @cookie: Pointer to "struct ccs_cookie".
1031     * @ptr: Pointer to assign.
1032     */
1033     void ccs_add_cookie(struct ccs_cookie *cookie, const void *ptr)
1034     {
1035     if (!cookie)
1036     return;
1037 kumaneko 2544 cookie->u.ptr = ptr;
1038 kumaneko 2540 write_lock(&ccs_cookie_list_lock);
1039     list_add_tail(&cookie->list, &ccs_cookie_list);
1040     write_unlock(&ccs_cookie_list_lock);
1041     }
1042    
1043     /**
1044     * ccs_del_cookie - Delete a cookie from cookie list.
1045     *
1046     * @cookie: Pointer to "struct ccs_cookie".
1047     */
1048     void ccs_del_cookie(struct ccs_cookie *cookie)
1049     {
1050     if (!cookie)
1051     return;
1052     write_lock(&ccs_cookie_list_lock);
1053     list_del(&cookie->list);
1054     write_unlock(&ccs_cookie_list_lock);
1055     }
1056    
1057     /**
1058     * ccs_used_by_cookie - Check whether the given pointer is referenced by a cookie or not.
1059     *
1060     * @ptr: Pointer to check.
1061     *
1062     * Returns true if @ptr is in use, false otherwise.
1063     *
1064     * Caller must hold ccs_policy_lock for writing.
1065     */
1066     static bool ccs_used_by_cookie(const void *ptr)
1067     {
1068     struct ccs_cookie *cookie;
1069     bool in_use = false;
1070     read_lock(&ccs_cookie_list_lock);
1071     list_for_each_entry(cookie, &ccs_cookie_list, list) {
1072     if (ptr != cookie->u.ptr)
1073     continue;
1074     in_use = true;
1075     break;
1076     }
1077     read_unlock(&ccs_cookie_list_lock);
1078     return in_use;
1079     }
1080    
1081     /**
1082     * ccs_cleanup_allow_read - Clean up deleted "struct ccs_globally_readable_file_entry".
1083     */
1084     static void ccs_cleanup_allow_read(void)
1085     {
1086     struct ccs_globally_readable_file_entry *ptr;
1087     struct ccs_globally_readable_file_entry *tmp;
1088     LIST_HEAD(q);
1089     /***** WRITER SECTION START *****/
1090     down_write(&ccs_policy_lock);
1091     list_for_each_entry_safe(ptr, tmp, &ccs_globally_readable_list,
1092     list) {
1093     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1094     continue;
1095     list_del(&ptr->list);
1096     list_add(&ptr->list, &q);
1097     }
1098     up_write(&ccs_policy_lock);
1099     /***** WRITER SECTION END *****/
1100     list_for_each_entry_safe(ptr, tmp, &q, list) {
1101     ccs_put_name(ptr->filename);
1102     list_del(&ptr->list);
1103     ccs_memory_free(ptr);
1104     }
1105     }
1106    
1107     /**
1108     * ccs_cleanup_allow_env - Clean up deleted "struct ccs_globally_usable_env_entry".
1109     */
1110     static void ccs_cleanup_allow_env(void)
1111     {
1112     struct ccs_globally_usable_env_entry *ptr;
1113     struct ccs_globally_usable_env_entry *tmp;
1114     LIST_HEAD(q);
1115     /***** WRITER SECTION START *****/
1116     down_write(&ccs_policy_lock);
1117     list_for_each_entry_safe(ptr, tmp, &ccs_globally_usable_env_list,
1118     list) {
1119     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1120     continue;
1121     list_del(&ptr->list);
1122     list_add(&ptr->list, &q);
1123     }
1124     up_write(&ccs_policy_lock);
1125     /***** WRITER SECTION END *****/
1126     list_for_each_entry_safe(ptr, tmp, &q, list) {
1127     ccs_put_name(ptr->env);
1128     list_del(&ptr->list);
1129     ccs_memory_free(ptr);
1130     }
1131     }
1132    
1133     /**
1134     * ccs_cleanup_file_pattern - Clean up deleted "struct ccs_pattern_entry".
1135     */
1136     static void ccs_cleanup_file_pattern(void)
1137     {
1138     struct ccs_pattern_entry *ptr;
1139     struct ccs_pattern_entry *tmp;
1140     LIST_HEAD(q);
1141     /***** WRITER SECTION START *****/
1142     down_write(&ccs_policy_lock);
1143     list_for_each_entry_safe(ptr, tmp, &ccs_pattern_list, list) {
1144     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1145     continue;
1146     list_del(&ptr->list);
1147     list_add(&ptr->list, &q);
1148     }
1149     up_write(&ccs_policy_lock);
1150     /***** WRITER SECTION END *****/
1151     list_for_each_entry_safe(ptr, tmp, &q, list) {
1152     ccs_put_name(ptr->pattern);
1153     list_del(&ptr->list);
1154     ccs_memory_free(ptr);
1155     }
1156     }
1157    
1158     /**
1159     * ccs_cleanup_no_rewrite - Clean up deleted "struct ccs_no_rewrite_entry".
1160     */
1161     static void ccs_cleanup_no_rewrite(void)
1162     {
1163     struct ccs_no_rewrite_entry *ptr;
1164     struct ccs_no_rewrite_entry *tmp;
1165     LIST_HEAD(q);
1166     /***** WRITER SECTION START *****/
1167     down_write(&ccs_policy_lock);
1168     list_for_each_entry_safe(ptr, tmp, &ccs_no_rewrite_list, list) {
1169     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1170     continue;
1171     list_del(&ptr->list);
1172     list_add(&ptr->list, &q);
1173     }
1174     up_write(&ccs_policy_lock);
1175     /***** WRITER SECTION END *****/
1176     list_for_each_entry_safe(ptr, tmp, &q, list) {
1177     ccs_put_name(ptr->pattern);
1178     list_del(&ptr->list);
1179     ccs_memory_free(ptr);
1180     }
1181     }
1182    
1183     /**
1184     * ccs_cleanup_initializer - Clean up deleted "struct ccs_domain_initializer_entry".
1185     */
1186     static void ccs_cleanup_initializer(void)
1187     {
1188     struct ccs_domain_initializer_entry *ptr;
1189     struct ccs_domain_initializer_entry *tmp;
1190     LIST_HEAD(q);
1191     /***** WRITER SECTION START *****/
1192     down_write(&ccs_policy_lock);
1193     list_for_each_entry_safe(ptr, tmp, &ccs_domain_initializer_list,
1194     list) {
1195     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1196     continue;
1197     list_del(&ptr->list);
1198     list_add(&ptr->list, &q);
1199     }
1200     up_write(&ccs_policy_lock);
1201     /***** WRITER SECTION END *****/
1202     list_for_each_entry_safe(ptr, tmp, &q, list) {
1203     ccs_put_name(ptr->domainname);
1204     ccs_put_name(ptr->program);
1205     list_del(&ptr->list);
1206     ccs_memory_free(ptr);
1207     }
1208     }
1209    
1210     /**
1211     * ccs_cleanup_keep_domain - Clean up deleted "struct ccs_domain_keeper_entry".
1212     */
1213     static void ccs_cleanup_keep_domain(void)
1214     {
1215     struct ccs_domain_keeper_entry *ptr;
1216     struct ccs_domain_keeper_entry *tmp;
1217     LIST_HEAD(q);
1218     /***** WRITER SECTION START *****/
1219     down_write(&ccs_policy_lock);
1220     list_for_each_entry_safe(ptr, tmp, &ccs_domain_keeper_list, list) {
1221     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1222     continue;
1223     list_del(&ptr->list);
1224     list_add(&ptr->list, &q);
1225     }
1226     up_write(&ccs_policy_lock);
1227     /***** WRITER SECTION END *****/
1228     list_for_each_entry_safe(ptr, tmp, &q, list) {
1229     ccs_put_name(ptr->domainname);
1230     ccs_put_name(ptr->program);
1231     list_del(&ptr->list);
1232     ccs_memory_free(ptr);
1233     }
1234     }
1235    
1236     /**
1237     * ccs_cleanup_alias - Clean up deleted "struct ccs_alias_entry".
1238     */
1239     static void ccs_cleanup_alias(void)
1240     {
1241     struct ccs_alias_entry *ptr;
1242     struct ccs_alias_entry *tmp;
1243     LIST_HEAD(q);
1244     /***** WRITER SECTION START *****/
1245     down_write(&ccs_policy_lock);
1246     list_for_each_entry_safe(ptr, tmp, &ccs_alias_list, list) {
1247     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1248     continue;
1249     list_del(&ptr->list);
1250     list_add(&ptr->list, &q);
1251     }
1252     up_write(&ccs_policy_lock);
1253     /***** WRITER SECTION END *****/
1254     list_for_each_entry_safe(ptr, tmp, &q, list) {
1255     ccs_put_name(ptr->original_name);
1256     ccs_put_name(ptr->aliased_name);
1257     list_del(&ptr->list);
1258     ccs_memory_free(ptr);
1259     }
1260     }
1261    
1262     /**
1263     * ccs_cleanup_aggregator - Clean up deleted "struct ccs_aggregator_entry".
1264     */
1265     static void ccs_cleanup_aggregator(void)
1266     {
1267     struct ccs_aggregator_entry *ptr;
1268     struct ccs_aggregator_entry *tmp;
1269     LIST_HEAD(q);
1270     /***** WRITER SECTION START *****/
1271     down_write(&ccs_policy_lock);
1272     list_for_each_entry_safe(ptr, tmp, &ccs_aggregator_list, list) {
1273     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1274     continue;
1275     list_del(&ptr->list);
1276     list_add(&ptr->list, &q);
1277     }
1278     up_write(&ccs_policy_lock);
1279     /***** WRITER SECTION END *****/
1280     list_for_each_entry_safe(ptr, tmp, &q, list) {
1281     ccs_put_name(ptr->original_name);
1282     ccs_put_name(ptr->aggregated_name);
1283     list_del(&ptr->list);
1284     ccs_memory_free(ptr);
1285     }
1286     }
1287    
1288     /**
1289     * ccs_cleanup_manager - Clean up deleted "struct ccs_policy_manager_entry".
1290     */
1291     static void ccs_cleanup_manager(void)
1292     {
1293     struct ccs_policy_manager_entry *ptr;
1294     struct ccs_policy_manager_entry *tmp;
1295     LIST_HEAD(q);
1296     /***** WRITER SECTION START *****/
1297     down_write(&ccs_policy_lock);
1298     list_for_each_entry_safe(ptr, tmp, &ccs_policy_manager_list, list) {
1299     if (!ptr->is_deleted || ccs_used_by_cookie(ptr))
1300     continue;
1301     list_del(&ptr->list);
1302     list_add(&ptr->list, &q);
1303     }
1304     up_write(&ccs_policy_lock);
1305     /***** WRITER SECTION END *****/
1306     list_for_each_entry_safe(ptr, tmp, &q, list) {
1307     ccs_put_name(ptr->manager);
1308     list_del(&ptr->list);
1309     ccs_memory_free(ptr);
1310     }
1311     }
1312    
1313     /* For compatibility with older kernels. */
1314     #ifndef for_each_process
1315     #define for_each_process for_each_task
1316     #endif
1317    
1318     /**
1319     * ccs_used_by_task - Check whether the given pointer is referenced by a task.
1320     *
1321     * @domain: Pointer to "struct ccs_domain_info".
1322     *
1323     * Returns true if @ptr is in use, false otherwise.
1324     */
1325     static bool ccs_used_by_task(struct ccs_domain_info *domain)
1326     {
1327     bool in_use = false;
1328     struct task_struct *p;
1329     /***** CRITICAL SECTION START *****/
1330     read_lock(&tasklist_lock);
1331     for_each_process(p) {
1332     if (p->ccs_domain_info != domain)
1333     continue;
1334     in_use = true;
1335     break;
1336     }
1337     read_unlock(&tasklist_lock);
1338     /***** CRITICAL SECTION END *****/
1339     return in_use;
1340     }
1341    
1342     /**
1343     * ccs_cleanup_domain_policy - Clean up deleted domain policy.
1344     */
1345     static void ccs_cleanup_domain_policy(void)
1346     {
1347     struct ccs_domain_info *domain;
1348     struct ccs_domain_info *next_domain;
1349     struct ccs_acl_info *acl;
1350     struct ccs_acl_info *next_acl;
1351     LIST_HEAD(q_domain);
1352     LIST_HEAD(q_acl);
1353     /***** WRITER SECTION START *****/
1354     down_write(&ccs_policy_lock);
1355     list_for_each_entry_safe(domain, next_domain, &ccs_domain_list,
1356     list) {
1357     const bool can_delete_domain = domain->is_deleted &&
1358     !ccs_used_by_cookie(domain) &&
1359     !ccs_used_by_task(domain);
1360     if (can_delete_domain) {
1361     list_for_each_entry(acl, &domain->acl_info_list, list)
1362     acl->type |= ACL_DELETED;
1363     }
1364     list_for_each_entry_safe(acl, next_acl, &domain->acl_info_list,
1365     list) {
1366     if (!(acl->type & ACL_DELETED)
1367     || ccs_used_by_cookie(acl))
1368     continue;
1369     list_del(&acl->list);
1370     list_add(&acl->list, &q_acl);
1371     }
1372     if (can_delete_domain && list_empty(&domain->acl_info_list)) {
1373     list_del(&domain->list);
1374     list_add(&domain->list, &q_domain);
1375     }
1376     }
1377     up_write(&ccs_policy_lock);
1378     /***** WRITER SECTION END *****/
1379     list_for_each_entry_safe(acl, next_acl, &q_acl, list) {
1380     switch (ccs_acl_type1(acl)) {
1381     struct ccs_single_path_acl_record *acl1;
1382     struct ccs_double_path_acl_record *acl2;
1383     struct ccs_ip_network_acl_record *acl3;
1384     struct ccs_ioctl_acl_record *acl4;
1385     struct ccs_argv0_acl_record *acl5;
1386     struct ccs_env_acl_record *acl6;
1387     struct ccs_capability_acl_record *acl7;
1388     struct ccs_signal_acl_record *acl8;
1389     struct ccs_execute_handler_record *acl9;
1390     case TYPE_SINGLE_PATH_ACL:
1391     acl1 = container_of(acl,
1392     struct ccs_single_path_acl_record,
1393     head);
1394     if (acl1->u_is_group)
1395     ccs_put_path_group(acl1->u.group);
1396     else
1397     ccs_put_name(acl1->u.filename);
1398     break;
1399     case TYPE_DOUBLE_PATH_ACL:
1400     acl2 = container_of(acl,
1401     struct ccs_double_path_acl_record,
1402     head);
1403     if (acl2->u1_is_group)
1404     ccs_put_path_group(acl2->u1.group1);
1405     else
1406     ccs_put_name(acl2->u1.filename1);
1407     if (acl2->u2_is_group)
1408     ccs_put_path_group(acl2->u2.group2);
1409     else
1410     ccs_put_name(acl2->u2.filename2);
1411     break;
1412     case TYPE_IP_NETWORK_ACL:
1413     acl3 = container_of(acl,
1414     struct ccs_ip_network_acl_record,
1415     head);
1416     if (acl3->record_type == IP_RECORD_TYPE_ADDRESS_GROUP)
1417     ccs_put_address_group(acl3->u.group);
1418     else if (acl3->record_type == IP_RECORD_TYPE_IPv6) {
1419     ccs_put_ipv6_address(acl3->u.ipv6.min);
1420     ccs_put_ipv6_address(acl3->u.ipv6.max);
1421     }
1422     break;
1423     case TYPE_IOCTL_ACL:
1424     acl4 = container_of(acl, struct ccs_ioctl_acl_record,
1425     head);
1426     if (acl4->u_is_group)
1427     ccs_put_path_group(acl4->u.group);
1428     else
1429     ccs_put_name(acl4->u.filename);
1430     break;
1431     case TYPE_ARGV0_ACL:
1432     acl5 = container_of(acl, struct ccs_argv0_acl_record,
1433     head);
1434     ccs_put_name(acl5->argv0);
1435     break;
1436     case TYPE_ENV_ACL:
1437     acl6 = container_of(acl, struct ccs_env_acl_record,
1438     head);
1439     ccs_put_name(acl6->env);
1440     break;
1441     case TYPE_CAPABILITY_ACL:
1442     acl7 = container_of(acl,
1443     struct ccs_capability_acl_record,
1444     head);
1445     break;
1446     case TYPE_SIGNAL_ACL:
1447     acl8 = container_of(acl, struct ccs_signal_acl_record,
1448     head);
1449     ccs_put_name(acl8->domainname);
1450     break;
1451     case TYPE_EXECUTE_HANDLER:
1452     case TYPE_DENIED_EXECUTE_HANDLER:
1453     acl9 = container_of(acl,
1454     struct ccs_execute_handler_record,
1455     head);
1456     ccs_put_name(acl9->handler);
1457     break;
1458     }
1459     list_del(&acl->list);
1460     ccs_memory_free(acl);
1461     }
1462     list_for_each_entry_safe(domain, next_domain, &q_domain, list) {
1463     ccs_put_name(domain->domainname);
1464     list_del(&domain->list);
1465     ccs_memory_free(domain);
1466     }
1467     }
1468    
1469     /**
1470     * ccs_run_garbage_collector - Run garbage collector.
1471     */
1472     void ccs_run_garbage_collector(void)
1473     {
1474     ccs_cleanup_allow_read();
1475     ccs_cleanup_allow_env();
1476     ccs_cleanup_file_pattern();
1477     ccs_cleanup_no_rewrite();
1478     ccs_cleanup_initializer();
1479     ccs_cleanup_keep_domain();
1480     ccs_cleanup_alias();
1481     ccs_cleanup_aggregator();
1482     ccs_cleanup_manager();
1483     ccs_cleanup_domain_policy();
1484     }
1485     /*
1486     extern struct list_head ccs_address_group_list;
1487     extern struct list_head ccs_path_group_list;
1488     extern struct list_head ccs_condition_list;
1489     extern struct list_head ccs_mount_list;
1490     extern struct list_head ccs_no_umount_list;
1491     extern struct list_head ccs_pivot_root_list;
1492     extern struct list_head ccs_chroot_list;
1493     extern struct list_head ccs_reservedport_list;
1494     */

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