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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2707 - (hide annotations) (download) (as text)
Tue Jun 30 06:17:04 2009 UTC (14 years, 10 months ago) by kumaneko
Original Path: branches/ccs-patch/fs/realpath.c
File MIME type: text/x-csrc
File size: 41502 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 2704 * Version: 1.7.0-pre 2009/05/28
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 2701 static atomic_t ccs_allocated_memory_for_elements;
447 kumaneko 2002 static unsigned int ccs_quota_for_elements;
448 kumaneko 111
449 kumaneko 1052 /**
450 kumaneko 2540 * ccs_memory_ok - Check memory quota.
451 kumaneko 1052 *
452 kumaneko 2540 * @ptr: Pointer to allocated memory.
453 kumaneko 1052 *
454 kumaneko 2540 * Returns true if @ptr is not NULL and quota not exceeded, false otehrwise.
455     */
456     bool ccs_memory_ok(const void *ptr)
457     {
458     const unsigned int len = ptr ? ksize(ptr) : 0;
459     if (len && (!ccs_quota_for_elements ||
460 kumaneko 2701 atomic_read(&ccs_allocated_memory_for_elements) + len
461 kumaneko 2540 <= ccs_quota_for_elements)) {
462 kumaneko 2701 atomic_add(len, &ccs_allocated_memory_for_elements);
463 kumaneko 2540 return true;
464     }
465     printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);
466     if (!ccs_policy_loaded)
467     panic("MAC Initialization failed.\n");
468     return false;
469     }
470    
471     /**
472     * ccs_memory_free - Free memory for elements.
473 kumaneko 1052 *
474 kumaneko 2540 * @ptr: Pointer to allocated memory.
475 kumaneko 1052 */
476 kumaneko 2540 static void ccs_memory_free(const void *ptr)
477 kumaneko 111 {
478 kumaneko 2701 atomic_sub(ksize(ptr), &ccs_allocated_memory_for_elements);
479 kumaneko 2540 kfree(ptr);
480     }
481    
482     /**
483     * ccs_free_element - Delete memory for structures.
484     *
485     * @ptr: Memory to release.
486     */
487     static void ccs_free_element(void *ptr)
488     {
489     if (!ptr)
490     return;
491 kumaneko 2701 atomic_sub(ksize(ptr), &ccs_allocated_memory_for_elements);
492 kumaneko 2540 kfree(ptr);
493     }
494    
495     /**
496     * ccs_put_path_group - Delete memory for "struct ccs_path_group_entry".
497     *
498     * @group: Pointer to "struct ccs_path_group_entry".
499     */
500     void ccs_put_path_group(struct ccs_path_group_entry *group)
501     {
502     struct ccs_path_group_member *member;
503     struct ccs_path_group_member *next_member;
504     LIST_HEAD(q);
505     bool can_delete_group = false;
506 kumaneko 2545 if (!group)
507     return;
508 kumaneko 2690 mutex_lock(&ccs_policy_lock);
509 kumaneko 2540 if (atomic_dec_and_test(&group->users)) {
510     list_for_each_entry_safe(member, next_member,
511     &group->path_group_member_list,
512     list) {
513     if (!member->is_deleted)
514     break;
515     list_del(&member->list);
516     list_add(&member->list, &q);
517 kumaneko 111 }
518 kumaneko 2540 if (list_empty(&group->path_group_member_list)) {
519     list_del(&group->list);
520     can_delete_group = true;
521 kumaneko 111 }
522     }
523 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
524 kumaneko 2540 list_for_each_entry_safe(member, next_member, &q, list) {
525     list_del(&member->list);
526     ccs_put_name(member->member_name);
527     ccs_free_element(member);
528     }
529     if (can_delete_group) {
530     ccs_put_name(group->group_name);
531     ccs_free_element(group);
532     }
533 kumaneko 111 }
534    
535 kumaneko 2540 /**
536     * ccs_put_address_group - Delete memory for "struct ccs_address_group_entry".
537     *
538     * @group: Pointer to "struct ccs_address_group_entry".
539     */
540     void ccs_put_address_group(struct ccs_address_group_entry *group)
541     {
542     struct ccs_address_group_member *member;
543     struct ccs_address_group_member *next_member;
544     LIST_HEAD(q);
545     bool can_delete_group = false;
546 kumaneko 2545 if (!group)
547     return;
548 kumaneko 2690 mutex_lock(&ccs_policy_lock);
549 kumaneko 2540 if (atomic_dec_and_test(&group->users)) {
550     list_for_each_entry_safe(member, next_member,
551     &group->address_group_member_list,
552     list) {
553     if (!member->is_deleted)
554     break;
555     list_del(&member->list);
556     list_add(&member->list, &q);
557     }
558     if (list_empty(&group->address_group_member_list)) {
559     list_del(&group->list);
560     can_delete_group = true;
561     }
562     }
563 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
564 kumaneko 2540 list_for_each_entry_safe(member, next_member, &q, list) {
565     list_del(&member->list);
566     if (member->is_ipv6) {
567     ccs_put_ipv6_address(member->min.ipv6);
568     ccs_put_ipv6_address(member->max.ipv6);
569     }
570     ccs_free_element(member);
571     }
572     if (can_delete_group) {
573     ccs_put_name(group->group_name);
574     ccs_free_element(group);
575     }
576     }
577    
578     static LIST_HEAD(ccs_address_list);
579    
580     /**
581     * ccs_get_ipv6_address - Keep the given IPv6 address on the RAM.
582     *
583     * @addr: Pointer to "struct in6_addr".
584     *
585     * Returns pointer to "struct in6_addr" on success, NULL otherwise.
586     *
587     * The RAM is shared, so NEVER try to modify or kfree() the returned address.
588     */
589     const struct in6_addr *ccs_get_ipv6_address(const struct in6_addr *addr)
590     {
591 kumaneko 2575 struct ccs_ipv6addr_entry *entry;
592     struct ccs_ipv6addr_entry *ptr;
593 kumaneko 2540 int error = -ENOMEM;
594     if (!addr)
595     return NULL;
596     entry = kzalloc(sizeof(*entry), GFP_KERNEL);
597 kumaneko 2690 mutex_lock(&ccs_policy_lock);
598 kumaneko 2540 list_for_each_entry(ptr, &ccs_address_list, list) {
599     if (memcmp(&ptr->addr, addr, sizeof(*addr)))
600     continue;
601     atomic_inc(&ptr->users);
602     error = 0;
603     break;
604     }
605     if (error && ccs_memory_ok(entry)) {
606     ptr = entry;
607     ptr->addr = *addr;
608     atomic_set(&ptr->users, 1);
609     list_add_tail(&ptr->list, &ccs_address_list);
610     entry = NULL;
611     }
612 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
613 kumaneko 2540 kfree(entry);
614     return ptr ? &ptr->addr : NULL;
615     }
616    
617     /**
618     * ccs_put_ipv6_address - Delete the given IPv6 address on the RAM.
619     *
620     * @addr: Pointer to "struct in6_addr".
621     */
622     void ccs_put_ipv6_address(const struct in6_addr *addr)
623     {
624 kumaneko 2575 struct ccs_ipv6addr_entry *ptr;
625 kumaneko 2540 bool can_delete = false;
626     if (!addr)
627     return;
628 kumaneko 2575 ptr = container_of(addr, struct ccs_ipv6addr_entry, addr);
629 kumaneko 2690 mutex_lock(&ccs_policy_lock);
630 kumaneko 2540 if (atomic_dec_and_test(&ptr->users)) {
631     list_del(&ptr->list);
632     can_delete = true;
633     }
634 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
635 kumaneko 2546 if (can_delete)
636     ccs_free_element(ptr);
637 kumaneko 2540 }
638    
639 kumaneko 2553 /**
640 kumaneko 2576 * ccs_put_condition - Delete memory for "struct ccs_condition".
641 kumaneko 2553 *
642 kumaneko 2576 * @cond: Pointer to "struct ccs_condition".
643 kumaneko 2553 */
644 kumaneko 2576 void ccs_put_condition(struct ccs_condition *cond)
645 kumaneko 2553 {
646     const unsigned long *ptr;
647     const struct ccs_argv_entry *argv;
648     const struct ccs_envp_entry *envp;
649     const struct ccs_symlinkp_entry *symlinkp;
650     u16 condc;
651     u16 argc;
652     u16 envc;
653     u16 symlinkc;
654     u16 i;
655     bool can_delete = false;
656     if (!cond)
657     return;
658 kumaneko 2690 mutex_lock(&ccs_policy_lock);
659 kumaneko 2553 if (atomic_dec_and_test(&cond->users)) {
660     list_del(&cond->list);
661     can_delete = true;
662     }
663 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
664 kumaneko 2553 if (!can_delete)
665     return;
666 kumaneko 2698 condc = cond->condc;
667     argc = cond->argc;
668     envc = cond->envc;
669     symlinkc = cond->symlinkc;
670 kumaneko 2553 ptr = (const unsigned long *) (cond + 1);
671     argv = (const struct ccs_argv_entry *) (ptr + condc);
672     envp = (const struct ccs_envp_entry *) (argv + argc);
673     symlinkp = (const struct ccs_symlinkp_entry *) (envp + envc);
674     for (i = 0; i < argc; argv++, i++)
675     ccs_put_name(argv->value);
676     for (i = 0; i < envc; envp++, i++) {
677     ccs_put_name(envp->name);
678     ccs_put_name(envp->value);
679     }
680     for (i = 0; i < symlinkc; symlinkp++, i++)
681     ccs_put_name(symlinkp->value);
682     ccs_free_element(cond);
683     }
684    
685 kumaneko 2701 static atomic_t ccs_allocated_memory_for_savename;
686 kumaneko 2002 static unsigned int ccs_quota_for_savename;
687 kumaneko 111
688     #define MAX_HASH 256
689    
690 kumaneko 1052 /* Structure for string data. */
691 kumaneko 2002 struct ccs_name_entry {
692 kumaneko 2540 struct list_head list;
693     atomic_t users;
694 kumaneko 2002 struct ccs_path_info entry;
695 kumaneko 214 };
696 kumaneko 111
697 kumaneko 2002 /* The list for "struct ccs_name_entry". */
698 kumaneko 2540 static struct list_head ccs_name_list[MAX_HASH];
699     static DEFINE_MUTEX(ccs_name_list_lock);
700 kumaneko 731
701 kumaneko 1052 /**
702 kumaneko 2540 * ccs_get_name - Allocate memory for string data.
703 kumaneko 1052 *
704     * @name: The string to store into the permernent memory.
705     *
706 kumaneko 2002 * Returns pointer to "struct ccs_path_info" on success, NULL otherwise.
707 kumaneko 1052 */
708 kumaneko 2540 const struct ccs_path_info *ccs_get_name(const char *name)
709 kumaneko 111 {
710 kumaneko 2002 struct ccs_name_entry *ptr;
711 kumaneko 111 unsigned int hash;
712     int len;
713 kumaneko 2540 int allocated_len;
714    
715 kumaneko 1052 if (!name)
716     return NULL;
717 kumaneko 111 len = strlen(name) + 1;
718     if (len > CCS_MAX_PATHNAME_LEN) {
719 kumaneko 2551 printk(KERN_WARNING "ERROR: Name too long. (%s)\n", __func__);
720 kumaneko 111 return NULL;
721     }
722     hash = full_name_hash((const unsigned char *) name, len - 1);
723 kumaneko 2540 /***** EXCLUSIVE SECTION START *****/
724     mutex_lock(&ccs_name_list_lock);
725     list_for_each_entry(ptr, &ccs_name_list[hash % MAX_HASH], list) {
726     if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
727     continue;
728     atomic_inc(&ptr->users);
729     goto out;
730 kumaneko 111 }
731 kumaneko 2540 ptr = kmalloc(sizeof(*ptr) + len, GFP_KERNEL);
732     allocated_len = ptr ? ksize(ptr) : 0;
733     if (!allocated_len ||
734     (ccs_quota_for_savename &&
735 kumaneko 2701 atomic_read(&ccs_allocated_memory_for_savename) + allocated_len
736 kumaneko 2540 > ccs_quota_for_savename)) {
737     kfree(ptr);
738     ptr = NULL;
739 kumaneko 2551 printk(KERN_WARNING "ERROR: Out of memory. (%s)\n", __func__);
740 kumaneko 2040 if (!ccs_policy_loaded)
741 kumaneko 1052 panic("MAC Initialization failed.\n");
742 kumaneko 731 goto out;
743     }
744 kumaneko 2701 atomic_add(allocated_len, &ccs_allocated_memory_for_savename);
745 kumaneko 2540 ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
746     memmove((char *) ptr->entry.name, name, len);
747     atomic_set(&ptr->users, 1);
748 kumaneko 1052 ccs_fill_path_info(&ptr->entry);
749 kumaneko 2540 list_add_tail(&ptr->list, &ccs_name_list[hash % MAX_HASH]);
750 kumaneko 111 out:
751 kumaneko 2540 mutex_unlock(&ccs_name_list_lock);
752     /***** EXCLUSIVE SECTION END *****/
753 kumaneko 111 return ptr ? &ptr->entry : NULL;
754     }
755    
756 kumaneko 2540 /**
757     * ccs_put_name - Delete shared memory for string data.
758     *
759     * @name: Pointer to "struct ccs_path_info".
760     */
761     void ccs_put_name(const struct ccs_path_info *name)
762     {
763     struct ccs_name_entry *ptr;
764     bool can_delete = false;
765     if (!name)
766     return;
767     ptr = container_of(name, struct ccs_name_entry, entry);
768     /***** EXCLUSIVE SECTION START *****/
769     mutex_lock(&ccs_name_list_lock);
770     if (atomic_dec_and_test(&ptr->users)) {
771     list_del(&ptr->list);
772     can_delete = true;
773     }
774     mutex_unlock(&ccs_name_list_lock);
775     /***** EXCLUSIVE SECTION END *****/
776     if (can_delete) {
777 kumaneko 2701 atomic_sub(ksize(ptr), &ccs_allocated_memory_for_savename);
778 kumaneko 2540 kfree(ptr);
779     }
780     }
781    
782 kumaneko 1052 /* Structure for temporarily allocated memory. */
783 kumaneko 2002 struct ccs_cache_entry {
784 kumaneko 111 struct list_head list;
785     void *ptr;
786     int size;
787 kumaneko 214 };
788 kumaneko 111
789 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
790     static struct kmem_cache *ccs_cachep;
791 kumaneko 111 #else
792 kumaneko 1052 static kmem_cache_t *ccs_cachep;
793 kumaneko 111 #endif
794    
795 kumaneko 2702 struct srcu_struct ccs_ss;
796    
797 kumaneko 1052 /**
798     * ccs_realpath_init - Initialize realpath related code.
799     *
800     * Returns 0.
801     */
802     static int __init ccs_realpath_init(void)
803 kumaneko 111 {
804 kumaneko 731 int i;
805 kumaneko 2540 /* Constraint for ccs_get_name(). */
806 kumaneko 1052 if (CCS_MAX_PATHNAME_LEN > PAGE_SIZE)
807     panic("Bad size.");
808 kumaneko 2037 /* Constraint for "struct ccs_execve_entry"->tmp users. */
809     if (CCS_MAX_PATHNAME_LEN > CCS_EXEC_TMPSIZE)
810     panic("Bad size.");
811 kumaneko 2702 if (init_srcu_struct(&ccs_ss))
812     panic("Out of memory.");
813 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
814 kumaneko 2002 ccs_cachep = kmem_cache_create("ccs_cache",
815     sizeof(struct ccs_cache_entry),
816 kumaneko 1052 0, 0, NULL);
817 kumaneko 316 #else
818 kumaneko 2002 ccs_cachep = kmem_cache_create("ccs_cache",
819     sizeof(struct ccs_cache_entry),
820 kumaneko 1052 0, 0, NULL, NULL);
821 kumaneko 316 #endif
822 kumaneko 1052 if (!ccs_cachep)
823     panic("Can't create cache.\n");
824     for (i = 0; i < MAX_HASH; i++)
825 kumaneko 2540 INIT_LIST_HEAD(&ccs_name_list[i]);
826     INIT_LIST_HEAD(&ccs_kernel_domain.acl_info_list);
827     ccs_kernel_domain.domainname = ccs_get_name(ROOT_NAME);
828 kumaneko 2692 list_add_tail_rcu(&ccs_kernel_domain.list, &ccs_domain_list);
829     if (ccs_find_domain(ROOT_NAME) != &ccs_kernel_domain)
830 kumaneko 2282 panic("Can't register ccs_kernel_domain");
831 kumaneko 2703 #ifdef CONFIG_CCSECURITY_BUILTIN_INITIALIZERS
832 kumaneko 2308 {
833     /* Load built-in policy. */
834 kumaneko 2392 static char ccs_builtin_initializers[] __initdata
835 kumaneko 2703 = CONFIG_CCSECURITY_BUILTIN_INITIALIZERS;
836 kumaneko 2392 char *cp = ccs_builtin_initializers;
837     ccs_normalize_line(cp);
838     while (cp && *cp) {
839     char *cp2 = strchr(cp, ' ');
840     if (cp2)
841     *cp2++ = '\0';
842     ccs_write_domain_initializer_policy(cp, false, false);
843     cp = cp2;
844 kumaneko 2308 }
845     }
846     #endif
847 kumaneko 1052 return 0;
848 kumaneko 111 }
849    
850 kumaneko 1084 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
851 kumaneko 1052 __initcall(ccs_realpath_init);
852 kumaneko 1084 #else
853 kumaneko 1106 core_initcall(ccs_realpath_init);
854 kumaneko 1084 #endif
855 kumaneko 1052
856 kumaneko 2002 /* The list for "struct ccs_cache_entry". */
857     static LIST_HEAD(ccs_audit_cache_list);
858     static LIST_HEAD(ccs_acl_cache_list);
859     static DEFINE_SPINLOCK(ccs_cache_list_lock);
860 kumaneko 1052
861 kumaneko 2002 static unsigned int ccs_dynamic_memory_size;
862     static unsigned int ccs_quota_for_dynamic;
863 kumaneko 1052
864     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
865     /**
866 kumaneko 2002 * ccs_round2 - Rounded up to power-of-two value.
867 kumaneko 1052 *
868     * @size: Size in bytes.
869     *
870     * Returns power-of-two of @size.
871     */
872 kumaneko 2002 static int ccs_round2(size_t size)
873 kumaneko 581 {
874     #if PAGE_SIZE == 4096
875     size_t bsize = 32;
876     #else
877     size_t bsize = 64;
878     #endif
879 kumaneko 1064 while (size > bsize)
880     bsize <<= 1;
881 kumaneko 581 return bsize;
882     }
883     #endif
884    
885 kumaneko 1052 /**
886 kumaneko 1793 * ccs_alloc - Allocate memory for temporary purpose.
887 kumaneko 1052 *
888     * @size: Size in bytes.
889     *
890     * Returns pointer to allocated memory on success, NULL otherwise.
891     */
892 kumaneko 1907 void *ccs_alloc(const size_t size, const _Bool check_quota)
893 kumaneko 111 {
894 kumaneko 2002 struct ccs_cache_entry *new_entry;
895 kumaneko 1055 void *ret = kzalloc(size, GFP_KERNEL);
896 kumaneko 1052 if (!ret)
897     goto out;
898 kumaneko 1031 new_entry = kmem_cache_alloc(ccs_cachep, GFP_KERNEL);
899     if (!new_entry) {
900 kumaneko 1064 kfree(ret);
901     ret = NULL;
902 kumaneko 1031 goto out;
903     }
904     INIT_LIST_HEAD(&new_entry->list);
905     new_entry->ptr = ret;
906 kumaneko 1052 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
907 kumaneko 1031 new_entry->size = ksize(ret);
908     #else
909 kumaneko 2002 new_entry->size = ccs_round2(size);
910 kumaneko 1031 #endif
911 kumaneko 1903 if (check_quota) {
912     bool quota_exceeded = false;
913     /***** CRITICAL SECTION START *****/
914 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
915     if (!ccs_quota_for_dynamic ||
916     ccs_dynamic_memory_size + new_entry->size
917     <= ccs_quota_for_dynamic) {
918     list_add_tail(&new_entry->list, &ccs_audit_cache_list);
919     ccs_dynamic_memory_size += new_entry->size;
920 kumaneko 1903 } else {
921     quota_exceeded = true;
922     }
923 kumaneko 2002 spin_unlock(&ccs_cache_list_lock);
924 kumaneko 1903 /***** CRITICAL SECTION END *****/
925     if (quota_exceeded) {
926     kfree(ret);
927     kmem_cache_free(ccs_cachep, new_entry);
928     ret = NULL;
929     }
930     } else {
931     /***** CRITICAL SECTION START *****/
932 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
933     list_add(&new_entry->list, &ccs_acl_cache_list);
934     ccs_dynamic_memory_size += new_entry->size;
935     spin_unlock(&ccs_cache_list_lock);
936 kumaneko 1903 /***** CRITICAL SECTION END *****/
937     }
938 kumaneko 1031 out:
939 kumaneko 214 return ret;
940 kumaneko 111 }
941    
942 kumaneko 1052 /**
943     * ccs_free - Release memory allocated by ccs_alloc().
944     *
945     * @p: Pointer returned by ccs_alloc(). May be NULL.
946     *
947     * Returns nothing.
948     */
949 kumaneko 111 void ccs_free(const void *p)
950     {
951     struct list_head *v;
952 kumaneko 2002 struct ccs_cache_entry *entry = NULL;
953 kumaneko 1052 if (!p)
954     return;
955     /***** CRITICAL SECTION START *****/
956 kumaneko 2002 spin_lock(&ccs_cache_list_lock);
957     list_for_each(v, &ccs_acl_cache_list) {
958     entry = list_entry(v, struct ccs_cache_entry, list);
959 kumaneko 1903 if (entry->ptr == p)
960     break;
961     entry = NULL;
962     }
963     if (!entry) {
964 kumaneko 2002 list_for_each(v, &ccs_audit_cache_list) {
965     entry = list_entry(v, struct ccs_cache_entry, list);
966 kumaneko 1903 if (entry->ptr == p)
967     break;
968 kumaneko 1064 entry = NULL;
969 kumaneko 111 }
970 kumaneko 1903 }
971     if (entry) {
972 kumaneko 111 list_del(&entry->list);
973 kumaneko 2002 ccs_dynamic_memory_size -= entry->size;
974 kumaneko 111 }
975 kumaneko 2002 spin_unlock(&ccs_cache_list_lock);
976 kumaneko 1052 /***** CRITICAL SECTION END *****/
977 kumaneko 111 if (entry) {
978     kfree(p);
979     kmem_cache_free(ccs_cachep, entry);
980     } else {
981 kumaneko 1052 printk(KERN_WARNING "BUG: ccs_free() with invalid pointer.\n");
982 kumaneko 111 }
983     }
984 kumaneko 1180
985     /**
986     * ccs_read_memory_counter - Check for memory usage.
987     *
988     * @head: Pointer to "struct ccs_io_buffer".
989     *
990     * Returns memory usage.
991     */
992     int ccs_read_memory_counter(struct ccs_io_buffer *head)
993     {
994     if (!head->read_eof) {
995 kumaneko 2701 const unsigned int shared
996     = atomic_read(&ccs_allocated_memory_for_savename);
997     const unsigned int private
998     = atomic_read(&ccs_allocated_memory_for_elements);
999 kumaneko 2002 const unsigned int dynamic = ccs_dynamic_memory_size;
1000 kumaneko 1180 char buffer[64];
1001     memset(buffer, 0, sizeof(buffer));
1002 kumaneko 2002 if (ccs_quota_for_savename)
1003 kumaneko 1180 snprintf(buffer, sizeof(buffer) - 1,
1004 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_savename);
1005 kumaneko 1180 else
1006     buffer[0] = '\0';
1007     ccs_io_printf(head, "Shared: %10u%s\n", shared, buffer);
1008 kumaneko 2002 if (ccs_quota_for_elements)
1009 kumaneko 1180 snprintf(buffer, sizeof(buffer) - 1,
1010 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_elements);
1011 kumaneko 1180 else
1012     buffer[0] = '\0';
1013     ccs_io_printf(head, "Private: %10u%s\n", private, buffer);
1014 kumaneko 2002 if (ccs_quota_for_dynamic)
1015 kumaneko 1903 snprintf(buffer, sizeof(buffer) - 1,
1016 kumaneko 2002 " (Quota: %10u)", ccs_quota_for_dynamic);
1017 kumaneko 1903 else
1018     buffer[0] = '\0';
1019     ccs_io_printf(head, "Dynamic: %10u%s\n", dynamic, buffer);
1020 kumaneko 1180 ccs_io_printf(head, "Total: %10u\n",
1021     shared + private + dynamic);
1022     head->read_eof = true;
1023     }
1024     return 0;
1025     }
1026    
1027     /**
1028     * ccs_write_memory_quota - Set memory quota.
1029     *
1030     * @head: Pointer to "struct ccs_io_buffer".
1031     *
1032     * Returns 0.
1033     */
1034     int ccs_write_memory_quota(struct ccs_io_buffer *head)
1035     {
1036     char *data = head->write_buf;
1037     unsigned int size;
1038     if (sscanf(data, "Shared: %u", &size) == 1)
1039 kumaneko 2002 ccs_quota_for_savename = size;
1040 kumaneko 1180 else if (sscanf(data, "Private: %u", &size) == 1)
1041 kumaneko 2002 ccs_quota_for_elements = size;
1042 kumaneko 1903 else if (sscanf(data, "Dynamic: %u", &size) == 1)
1043 kumaneko 2002 ccs_quota_for_dynamic = size;
1044 kumaneko 1180 return 0;
1045     }
1046 kumaneko 2540
1047 kumaneko 2701 /* Garbage collector functions */
1048    
1049     enum ccs_gc_id {
1050     CCS_ID_CONDITION,
1051     CCS_ID_RESERVEDPORT,
1052     CCS_ID_ADDRESS_GROUP,
1053     CCS_ID_ADDRESS_GROUP_MEMBER,
1054     CCS_ID_PATH_GROUP,
1055     CCS_ID_PATH_GROUP_MEMBER,
1056     CCS_ID_GLOBAL_ENV,
1057     CCS_ID_AGGREGATOR,
1058     CCS_ID_DOMAIN_INITIALIZER,
1059     CCS_ID_DOMAIN_KEEPER,
1060     CCS_ID_ALIAS,
1061     CCS_ID_GLOBALLY_READABLE,
1062     CCS_ID_PATTERN,
1063     CCS_ID_NO_REWRITE,
1064     CCS_ID_MANAGER,
1065     CCS_ID_ACL,
1066     CCS_ID_DOMAIN
1067     };
1068    
1069     struct ccs_gc_entry {
1070     struct list_head list;
1071     int type;
1072     void *element;
1073     };
1074    
1075     /* Caller holds ccs_policy_lock mutex. */
1076     static bool ccs_add_to_gc(const int type, void *element, struct list_head *head)
1077 kumaneko 2540 {
1078 kumaneko 2701 struct ccs_gc_entry *entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
1079     if (!entry)
1080     return false;
1081     entry->type = type;
1082     entry->element = element;
1083     list_add(&entry->list, head);
1084     return true;
1085 kumaneko 2540 }
1086    
1087 kumaneko 2701 static inline void ccs_gc_del_domain_initializer
1088     (struct ccs_domain_initializer_entry *ptr)
1089 kumaneko 2540 {
1090 kumaneko 2701 ccs_put_name(ptr->domainname);
1091     ccs_put_name(ptr->program);
1092 kumaneko 2540 }
1093    
1094 kumaneko 2701 static inline void ccs_gc_del_domain_keeper
1095     (struct ccs_domain_keeper_entry *ptr)
1096 kumaneko 2540 {
1097 kumaneko 2701 ccs_put_name(ptr->domainname);
1098     ccs_put_name(ptr->program);
1099 kumaneko 2540 }
1100    
1101 kumaneko 2701 static void ccs_del_allow_read(struct ccs_globally_readable_file_entry *ptr)
1102 kumaneko 2540 {
1103 kumaneko 2701 ccs_put_name(ptr->filename);
1104     ccs_memory_free(ptr);
1105 kumaneko 2540 }
1106    
1107 kumaneko 2701 static void ccs_del_allow_env(struct ccs_globally_usable_env_entry *ptr)
1108 kumaneko 2540 {
1109 kumaneko 2701 ccs_put_name(ptr->env);
1110     ccs_memory_free(ptr);
1111 kumaneko 2540 }
1112    
1113 kumaneko 2701 static void ccs_del_file_pattern(struct ccs_pattern_entry *ptr)
1114 kumaneko 2540 {
1115 kumaneko 2701 ccs_put_name(ptr->pattern);
1116     ccs_memory_free(ptr);
1117 kumaneko 2540 }
1118    
1119 kumaneko 2701 static void ccs_del_no_rewrite(struct ccs_no_rewrite_entry *ptr)
1120 kumaneko 2540 {
1121 kumaneko 2701 ccs_put_name(ptr->pattern);
1122     ccs_memory_free(ptr);
1123 kumaneko 2540 }
1124    
1125 kumaneko 2701 static void ccs_del_domain_initializer(struct ccs_domain_initializer_entry *ptr)
1126 kumaneko 2540 {
1127 kumaneko 2701 ccs_put_name(ptr->domainname);
1128     ccs_put_name(ptr->program);
1129     ccs_memory_free(ptr);
1130 kumaneko 2540 }
1131    
1132 kumaneko 2701 static void ccs_del_domain_keeper(struct ccs_domain_keeper_entry *ptr)
1133 kumaneko 2540 {
1134 kumaneko 2701 ccs_put_name(ptr->domainname);
1135     ccs_put_name(ptr->program);
1136     ccs_memory_free(ptr);
1137 kumaneko 2540 }
1138    
1139 kumaneko 2701 static void ccs_del_alias(struct ccs_alias_entry *ptr)
1140     {
1141     ccs_put_name(ptr->original_name);
1142     ccs_put_name(ptr->aliased_name);
1143     ccs_memory_free(ptr);
1144     }
1145    
1146     static void ccs_del_aggregator(struct ccs_aggregator_entry *ptr)
1147     {
1148     ccs_put_name(ptr->original_name);
1149     ccs_put_name(ptr->aggregated_name);
1150     ccs_memory_free(ptr);
1151     }
1152    
1153     static void ccs_del_manager(struct ccs_policy_manager_entry *ptr)
1154     {
1155     ccs_put_name(ptr->manager);
1156     ccs_memory_free(ptr);
1157     }
1158    
1159 kumaneko 2540 /* For compatibility with older kernels. */
1160     #ifndef for_each_process
1161     #define for_each_process for_each_task
1162     #endif
1163    
1164     /**
1165     * ccs_used_by_task - Check whether the given pointer is referenced by a task.
1166     *
1167     * @domain: Pointer to "struct ccs_domain_info".
1168     *
1169     * Returns true if @ptr is in use, false otherwise.
1170     */
1171     static bool ccs_used_by_task(struct ccs_domain_info *domain)
1172     {
1173     bool in_use = false;
1174     struct task_struct *p;
1175     /***** CRITICAL SECTION START *****/
1176     read_lock(&tasklist_lock);
1177     for_each_process(p) {
1178     if (p->ccs_domain_info != domain)
1179     continue;
1180     in_use = true;
1181     break;
1182     }
1183     read_unlock(&tasklist_lock);
1184     /***** CRITICAL SECTION END *****/
1185     return in_use;
1186     }
1187    
1188 kumaneko 2701 static void ccs_del_acl(struct ccs_acl_info *acl)
1189 kumaneko 2540 {
1190 kumaneko 2701 struct ccs_single_path_acl_record *acl1;
1191     struct ccs_double_path_acl_record *acl2;
1192     struct ccs_ip_network_acl_record *acl3;
1193     struct ccs_ioctl_acl_record *acl4;
1194     struct ccs_argv0_acl_record *acl5;
1195     struct ccs_env_acl_record *acl6;
1196     struct ccs_capability_acl_record *acl7;
1197     struct ccs_signal_acl_record *acl8;
1198     struct ccs_execute_handler_record *acl9;
1199 kumaneko 2707 struct ccs_mount_acl_record *acl10;
1200     struct ccs_umount_acl_record *acl11;
1201     struct ccs_chroot_acl_record *acl12;
1202     struct ccs_pivot_root_acl_record *acl13;
1203 kumaneko 2701 ccs_put_condition(acl->cond);
1204     switch (ccs_acl_type1(acl)) {
1205     case TYPE_SINGLE_PATH_ACL:
1206     acl1 = container_of(acl, struct ccs_single_path_acl_record,
1207     head);
1208     if (acl1->u_is_group)
1209     ccs_put_path_group(acl1->u.group);
1210     else
1211     ccs_put_name(acl1->u.filename);
1212     break;
1213     case TYPE_DOUBLE_PATH_ACL:
1214     acl2 = container_of(acl, struct ccs_double_path_acl_record,
1215     head);
1216     if (acl2->u1_is_group)
1217     ccs_put_path_group(acl2->u1.group1);
1218     else
1219     ccs_put_name(acl2->u1.filename1);
1220     if (acl2->u2_is_group)
1221     ccs_put_path_group(acl2->u2.group2);
1222     else
1223     ccs_put_name(acl2->u2.filename2);
1224     break;
1225     case TYPE_IP_NETWORK_ACL:
1226     acl3 = container_of(acl, struct ccs_ip_network_acl_record,
1227     head);
1228     if (acl3->record_type == IP_RECORD_TYPE_ADDRESS_GROUP)
1229     ccs_put_address_group(acl3->u.group);
1230     else if (acl3->record_type == IP_RECORD_TYPE_IPv6) {
1231     ccs_put_ipv6_address(acl3->u.ipv6.min);
1232     ccs_put_ipv6_address(acl3->u.ipv6.max);
1233     }
1234     break;
1235     case TYPE_IOCTL_ACL:
1236     acl4 = container_of(acl, struct ccs_ioctl_acl_record, head);
1237     if (acl4->u_is_group)
1238     ccs_put_path_group(acl4->u.group);
1239     else
1240     ccs_put_name(acl4->u.filename);
1241     break;
1242     case TYPE_ARGV0_ACL:
1243     acl5 = container_of(acl, struct ccs_argv0_acl_record, head);
1244     ccs_put_name(acl5->argv0);
1245     break;
1246     case TYPE_ENV_ACL:
1247     acl6 = container_of(acl, struct ccs_env_acl_record, head);
1248     ccs_put_name(acl6->env);
1249     break;
1250     case TYPE_CAPABILITY_ACL:
1251     acl7 = container_of(acl, struct ccs_capability_acl_record,
1252     head);
1253     break;
1254     case TYPE_SIGNAL_ACL:
1255     acl8 = container_of(acl, struct ccs_signal_acl_record,
1256     head);
1257     ccs_put_name(acl8->domainname);
1258     break;
1259     case TYPE_EXECUTE_HANDLER:
1260     case TYPE_DENIED_EXECUTE_HANDLER:
1261     acl9 = container_of(acl, struct ccs_execute_handler_record,
1262     head);
1263     ccs_put_name(acl9->handler);
1264     break;
1265 kumaneko 2707 case TYPE_MOUNT_ACL:
1266     acl10 = container_of(acl, struct ccs_mount_acl_record, head);
1267     ccs_put_name(acl10->dev_name);
1268     ccs_put_name(acl10->dir_name);
1269     ccs_put_name(acl10->fs_type);
1270     break;
1271     case TYPE_UMOUNT_ACL:
1272     acl11 = container_of(acl, struct ccs_umount_acl_record, head);
1273     ccs_put_name(acl11->dir);
1274     break;
1275     case TYPE_CHROOT_ACL:
1276     acl12 = container_of(acl, struct ccs_chroot_acl_record, head);
1277     ccs_put_name(acl12->dir);
1278     break;
1279     case TYPE_PIVOT_ROOT_ACL:
1280     acl13 = container_of(acl, struct ccs_pivot_root_acl_record,
1281     head);
1282     ccs_put_name(acl13->old_root);
1283     ccs_put_name(acl13->new_root);
1284     break;
1285    
1286 kumaneko 2701 }
1287     ccs_memory_free(acl);
1288     }
1289    
1290     static bool ccs_del_domain(struct ccs_domain_info *domain)
1291     {
1292     if (ccs_used_by_task(domain))
1293     return false;
1294     ccs_put_name(domain->domainname);
1295     ccs_memory_free(domain);
1296     return true;
1297     }
1298    
1299     static void ccs_del_path_group_member(struct ccs_path_group_member *member)
1300     {
1301     ccs_put_name(member->member_name);
1302     ccs_free_element(member);
1303     }
1304    
1305     static void ccs_del_path_group(struct ccs_path_group_entry *group)
1306     {
1307     ccs_put_name(group->group_name);
1308     ccs_free_element(group);
1309     }
1310    
1311     static void ccs_del_address_group_member
1312     (struct ccs_address_group_member *member)
1313     {
1314     if (member->is_ipv6) {
1315     ccs_put_ipv6_address(member->min.ipv6);
1316     ccs_put_ipv6_address(member->max.ipv6);
1317     }
1318     ccs_free_element(member);
1319     }
1320    
1321     static void ccs_del_address_group(struct ccs_address_group_entry *group)
1322     {
1323     ccs_put_name(group->group_name);
1324     ccs_free_element(group);
1325     }
1326    
1327     static void ccs_del_reservedport(struct ccs_reserved_entry *ptr)
1328     {
1329     ccs_memory_free(ptr);
1330     }
1331    
1332     static void ccs_del_condition(struct ccs_condition *ptr)
1333     {
1334     int i;
1335     u16 condc = ptr->condc;
1336     u16 argc = ptr->argc;
1337     u16 envc = ptr->envc;
1338     u16 symlinkc = ptr->symlinkc;
1339     unsigned long *ptr2 = (unsigned long *) (ptr + 1);
1340     struct ccs_argv_entry *argv = (struct ccs_argv_entry *) (ptr2 + condc);
1341     struct ccs_envp_entry *envp = (struct ccs_envp_entry *) (argv + argc);
1342     struct ccs_symlinkp_entry *symlinkp
1343     = (struct ccs_symlinkp_entry *) (envp + envc);
1344     for (i = 0; i < argc; i++)
1345     ccs_put_name(argv[i].value);
1346     for (i = 0; i < envc; i++) {
1347     ccs_put_name(envp[i].name);
1348     ccs_put_name(envp[i].value);
1349     }
1350     for (i = 0; i < symlinkc; i++)
1351     ccs_put_name(symlinkp[i].value);
1352     ccs_memory_free(ptr);
1353     }
1354    
1355     static int ccs_gc_thread(void *unused)
1356     {
1357     static DEFINE_MUTEX(ccs_gc_mutex);
1358     static LIST_HEAD(ccs_gc_queue);
1359     if (!mutex_trylock(&ccs_gc_mutex))
1360     return 0;
1361 kumaneko 2690 mutex_lock(&ccs_policy_lock);
1362 kumaneko 2701 {
1363     struct ccs_globally_readable_file_entry *ptr;
1364     list_for_each_entry_rcu(ptr, &ccs_globally_readable_list,
1365     list) {
1366     if (!ptr->is_deleted)
1367     continue;
1368     if (ccs_add_to_gc(CCS_ID_GLOBALLY_READABLE, ptr,
1369     &ccs_gc_queue))
1370     list_del_rcu(&ptr->list);
1371     else
1372     break;
1373 kumaneko 2540 }
1374 kumaneko 2701 }
1375     {
1376     struct ccs_globally_usable_env_entry *ptr;
1377     list_for_each_entry_rcu(ptr, &ccs_globally_usable_env_list,
1378     list) {
1379     if (!ptr->is_deleted)
1380 kumaneko 2540 continue;
1381 kumaneko 2701 if (ccs_add_to_gc(CCS_ID_GLOBAL_ENV, ptr,
1382     &ccs_gc_queue))
1383     list_del_rcu(&ptr->list);
1384     else
1385     break;
1386 kumaneko 2540 }
1387 kumaneko 2701 }
1388     {
1389     struct ccs_pattern_entry *ptr;
1390     list_for_each_entry_rcu(ptr, &ccs_pattern_list, list) {
1391     if (!ptr->is_deleted)
1392     continue;
1393     if (ccs_add_to_gc(CCS_ID_PATTERN, ptr,
1394     &ccs_gc_queue))
1395     list_del_rcu(&ptr->list);
1396     else
1397     break;
1398 kumaneko 2540 }
1399     }
1400 kumaneko 2701 {
1401     struct ccs_no_rewrite_entry *ptr;
1402     list_for_each_entry_rcu(ptr, &ccs_no_rewrite_list, list) {
1403     if (!ptr->is_deleted)
1404     continue;
1405     if (ccs_add_to_gc(CCS_ID_NO_REWRITE, ptr,
1406     &ccs_gc_queue))
1407     list_del_rcu(&ptr->list);
1408 kumaneko 2540 else
1409 kumaneko 2701 break;
1410     }
1411     }
1412     {
1413     struct ccs_domain_initializer_entry *ptr;
1414     list_for_each_entry_rcu(ptr, &ccs_domain_initializer_list,
1415     list) {
1416     if (!ptr->is_deleted)
1417     continue;
1418     if (ccs_add_to_gc(CCS_ID_DOMAIN_INITIALIZER,
1419     ptr, &ccs_gc_queue))
1420     list_del_rcu(&ptr->list);
1421 kumaneko 2540 else
1422 kumaneko 2701 break;
1423     }
1424     }
1425     {
1426     struct ccs_domain_keeper_entry *ptr;
1427     list_for_each_entry_rcu(ptr, &ccs_domain_keeper_list, list) {
1428     if (!ptr->is_deleted)
1429     continue;
1430     if (ccs_add_to_gc(CCS_ID_DOMAIN_KEEPER, ptr,
1431     &ccs_gc_queue))
1432     list_del_rcu(&ptr->list);
1433 kumaneko 2540 else
1434 kumaneko 2701 break;
1435     }
1436     }
1437     {
1438     struct ccs_alias_entry *ptr;
1439     list_for_each_entry_rcu(ptr, &ccs_alias_list, list) {
1440     if (!ptr->is_deleted)
1441     continue;
1442     if (ccs_add_to_gc(CCS_ID_ALIAS, ptr, &ccs_gc_queue))
1443     list_del_rcu(&ptr->list);
1444 kumaneko 2540 else
1445 kumaneko 2701 break;
1446 kumaneko 2540 }
1447     }
1448 kumaneko 2701 {
1449     struct ccs_policy_manager_entry *ptr;
1450     list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1451     if (!ptr->is_deleted)
1452     continue;
1453     if (ccs_add_to_gc(CCS_ID_MANAGER, ptr, &ccs_gc_queue))
1454     list_del_rcu(&ptr->list);
1455     else
1456     break;
1457     }
1458 kumaneko 2540 }
1459 kumaneko 2701 {
1460     struct ccs_aggregator_entry *ptr;
1461     list_for_each_entry_rcu(ptr, &ccs_aggregator_list, list) {
1462     if (!ptr->is_deleted)
1463     continue;
1464     if (ccs_add_to_gc(CCS_ID_AGGREGATOR, ptr,
1465     &ccs_gc_queue))
1466     list_del_rcu(&ptr->list);
1467     else
1468 kumaneko 2575 break;
1469     }
1470     }
1471 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
1472 kumaneko 2701 {
1473     struct ccs_domain_info *domain;
1474     list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
1475     struct ccs_acl_info *acl;
1476     list_for_each_entry_rcu(acl, &domain->acl_info_list,
1477     list) {
1478     if (!(acl->type & ACL_DELETED))
1479     continue;
1480     if (ccs_add_to_gc(CCS_ID_ACL, acl,
1481     &ccs_gc_queue))
1482     list_del_rcu(&acl->list);
1483     else
1484     break;
1485     }
1486     if (!domain->is_deleted ||
1487     ccs_used_by_task(domain))
1488     continue;
1489     if (ccs_add_to_gc(CCS_ID_DOMAIN, domain, &ccs_gc_queue))
1490     list_del_rcu(&domain->list);
1491     else
1492     break;
1493     }
1494 kumaneko 2575 }
1495 kumaneko 2701 {
1496     struct ccs_path_group_entry *group;
1497     list_for_each_entry_rcu(group, &ccs_path_group_list, list) {
1498     struct ccs_path_group_member *member;
1499     list_for_each_entry_rcu(member,
1500     &group->path_group_member_list,
1501     list) {
1502     if (!member->is_deleted)
1503     continue;
1504     if (ccs_add_to_gc(CCS_ID_PATH_GROUP_MEMBER,
1505     member, &ccs_gc_queue))
1506     list_del_rcu(&member->list);
1507     else
1508     break;
1509     }
1510     if (!list_empty(&group->path_group_member_list) ||
1511     atomic_read(&group->users))
1512     continue;
1513     if (ccs_add_to_gc(CCS_ID_PATH_GROUP, group,
1514     &ccs_gc_queue))
1515     list_del_rcu(&group->list);
1516     else
1517     break;
1518     }
1519 kumaneko 2575 }
1520 kumaneko 2701 {
1521     struct ccs_address_group_entry *group;
1522     list_for_each_entry_rcu(group, &ccs_address_group_list, list) {
1523     struct ccs_address_group_member *member;
1524     list_for_each_entry_rcu(member,
1525     &group->address_group_member_list,
1526     list) {
1527     if (!member->is_deleted)
1528     break;
1529     if (ccs_add_to_gc(CCS_ID_ADDRESS_GROUP_MEMBER,
1530     member, &ccs_gc_queue))
1531     list_del_rcu(&member->list);
1532     else
1533     break;
1534     }
1535     if (!list_empty(&group->address_group_member_list) ||
1536     atomic_read(&group->users))
1537     continue;
1538     if (ccs_add_to_gc(CCS_ID_ADDRESS_GROUP, group,
1539     &ccs_gc_queue))
1540     list_del_rcu(&group->list);
1541     else
1542 kumaneko 2575 break;
1543     }
1544 kumaneko 2701 }
1545     {
1546     struct ccs_reserved_entry *ptr;
1547     list_for_each_entry_rcu(ptr, &ccs_reservedport_list, list) {
1548     if (!ptr->is_deleted)
1549     continue;
1550     if (ccs_add_to_gc(CCS_ID_RESERVEDPORT, ptr,
1551     &ccs_gc_queue))
1552     list_del_rcu(&ptr->list);
1553     else
1554     break;
1555     }
1556 kumaneko 2575 }
1557 kumaneko 2701 {
1558     struct ccs_condition *ptr;
1559     list_for_each_entry_rcu(ptr, &ccs_condition_list, list) {
1560     if (atomic_read(&ptr->users))
1561     continue;
1562     if (ccs_add_to_gc(CCS_ID_CONDITION, ptr, &ccs_gc_queue))
1563     list_del_rcu(&ptr->list);
1564     else
1565     break;
1566     }
1567 kumaneko 2575 }
1568 kumaneko 2690 mutex_unlock(&ccs_policy_lock);
1569 kumaneko 2701 if (list_empty(&ccs_gc_queue))
1570     goto done;
1571     synchronize_srcu(&ccs_ss);
1572     {
1573     struct ccs_gc_entry *p;
1574     struct ccs_gc_entry *tmp;
1575     list_for_each_entry_safe(p, tmp, &ccs_gc_queue, list) {
1576     switch (p->type) {
1577     case CCS_ID_DOMAIN_INITIALIZER:
1578     ccs_del_domain_initializer(p->element);
1579     break;
1580     case CCS_ID_DOMAIN_KEEPER:
1581     ccs_del_domain_keeper(p->element);
1582     break;
1583     case CCS_ID_ALIAS:
1584     ccs_del_alias(p->element);
1585     break;
1586     case CCS_ID_GLOBALLY_READABLE:
1587     ccs_del_allow_read(p->element);
1588     break;
1589     case CCS_ID_PATTERN:
1590     ccs_del_file_pattern(p->element);
1591     break;
1592     case CCS_ID_NO_REWRITE:
1593     ccs_del_no_rewrite(p->element);
1594     break;
1595     case CCS_ID_MANAGER:
1596     ccs_del_manager(p->element);
1597     break;
1598     case CCS_ID_GLOBAL_ENV:
1599     ccs_del_allow_env(p->element);
1600     break;
1601     case CCS_ID_AGGREGATOR:
1602     ccs_del_aggregator(p->element);
1603     break;
1604     case CCS_ID_PATH_GROUP_MEMBER:
1605     ccs_del_path_group_member(p->element);
1606     break;
1607     case CCS_ID_PATH_GROUP:
1608     ccs_del_path_group(p->element);
1609     break;
1610     case CCS_ID_ADDRESS_GROUP_MEMBER:
1611     ccs_del_address_group_member(p->element);
1612     break;
1613     case CCS_ID_ADDRESS_GROUP:
1614     ccs_del_address_group(p->element);
1615     break;
1616     case CCS_ID_RESERVEDPORT:
1617     ccs_del_reservedport(p->element);
1618     break;
1619     case CCS_ID_CONDITION:
1620     ccs_del_condition(p->element);
1621     break;
1622     case CCS_ID_ACL:
1623     ccs_del_acl(p->element);
1624     break;
1625     case CCS_ID_DOMAIN:
1626     if (!ccs_del_domain(p->element))
1627     continue;
1628     break;
1629     }
1630     ccs_free_element(p->element);
1631     list_del(&p->list);
1632     kfree(p);
1633     }
1634 kumaneko 2575 }
1635 kumaneko 2701 done:
1636     mutex_unlock(&ccs_gc_mutex);
1637     return 0;
1638 kumaneko 2575 }
1639    
1640 kumaneko 2701 #if 0 && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
1641 kumaneko 2575
1642 kumaneko 2701 static struct srcu_struct {
1643     int counter_idx;
1644     int counter[2];
1645     } ccs_ss;
1646     static DEFINE_SPINLOCK(ccs_counter_lock);
1647    
1648     int ccs_read_lock(struct srcu_struct *sp)
1649 kumaneko 2575 {
1650 kumaneko 2701 int idx;
1651     spin_lock(&ccs_counter_lock);
1652     idx = sp->counter_idx;
1653     sp->counter[idx]++;
1654     spin_unlock(&ccs_counter_lock);
1655     return idx;
1656 kumaneko 2575 }
1657    
1658 kumaneko 2701 void ccs_read_unlock(struct srcu_struct *sp, const int idx)
1659 kumaneko 2575 {
1660 kumaneko 2701 spin_lock(&ccs_counter_lock);
1661     sp->counter[idx]--;
1662     spin_unlock(&ccs_counter_lock);
1663 kumaneko 2575 }
1664    
1665 kumaneko 2701 void ccs_wait_readers(struct srcu_struct *sp)
1666 kumaneko 2576 {
1667 kumaneko 2701 int idx;
1668     int v;
1669     spin_lock(&ccs_counter_lock);
1670     idx = sp->counter_idx;
1671     sp->counter_idx ^= 1;
1672     v = sp->counter[idx];
1673     spin_unlock(&ccs_counter_lock);
1674     while (v) {
1675     msleep(1000);
1676     spin_lock(&ccs_counter_lock);
1677     v = sp->counter[idx];
1678     spin_unlock(&ccs_counter_lock);
1679 kumaneko 2576 }
1680     }
1681    
1682 kumaneko 2701 #endif

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