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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2575 - (show annotations) (download) (as text)
Thu May 21 04:56:02 2009 UTC (15 years ago) by kumaneko
Original Path: branches/ccs-patch/fs/realpath.c
File MIME type: text/x-csrc
File size: 45031 byte(s)


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

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