aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2011-06-26 10:20:55 -0400
committerJames Morris <jmorris@namei.org>2011-06-28 19:31:21 -0400
commit2e503bbb435ae418aebbe4aeede1c6f2a33d6f74 (patch)
treec6b783c245716cf87b337b2a855e742133afb7ac /security/tomoyo
parent5625f2e3266319fd29fe4f1c76ccd3f550c79ac4 (diff)
TOMOYO: Fix lockdep warning.
Currently TOMOYO holds SRCU lock upon open() and releases it upon close() because list elements stored in the "struct tomoyo_io_buffer" instances are accessed until close() is called. However, such SRCU usage causes lockdep to complain about leaving the kernel with SRCU lock held. This patch solves the warning by holding/releasing SRCU upon each read()/write(). This patch is doing something similar to calling kfree() without calling synchronize_srcu(), by selectively deferring kfree() by keeping track of the "struct tomoyo_io_buffer" instances. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo')
-rw-r--r--security/tomoyo/common.c41
-rw-r--r--security/tomoyo/common.h8
-rw-r--r--security/tomoyo/gc.c278
3 files changed, 276 insertions, 51 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 50481d2cf970..691c34025a4a 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -1820,9 +1820,7 @@ static void tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
1820 * @type: Type of interface. 1820 * @type: Type of interface.
1821 * @file: Pointer to "struct file". 1821 * @file: Pointer to "struct file".
1822 * 1822 *
1823 * Associates policy handler and returns 0 on success, -ENOMEM otherwise. 1823 * Returns 0 on success, negative value otherwise.
1824 *
1825 * Caller acquires tomoyo_read_lock().
1826 */ 1824 */
1827int tomoyo_open_control(const u8 type, struct file *file) 1825int tomoyo_open_control(const u8 type, struct file *file)
1828{ 1826{
@@ -1921,9 +1919,6 @@ int tomoyo_open_control(const u8 type, struct file *file)
1921 return -ENOMEM; 1919 return -ENOMEM;
1922 } 1920 }
1923 } 1921 }
1924 if (type != TOMOYO_QUERY && type != TOMOYO_AUDIT)
1925 head->reader_idx = tomoyo_read_lock();
1926 file->private_data = head;
1927 /* 1922 /*
1928 * If the file is /sys/kernel/security/tomoyo/query , increment the 1923 * If the file is /sys/kernel/security/tomoyo/query , increment the
1929 * observer counter. 1924 * observer counter.
@@ -1932,6 +1927,8 @@ int tomoyo_open_control(const u8 type, struct file *file)
1932 */ 1927 */
1933 if (type == TOMOYO_QUERY) 1928 if (type == TOMOYO_QUERY)
1934 atomic_inc(&tomoyo_query_observers); 1929 atomic_inc(&tomoyo_query_observers);
1930 file->private_data = head;
1931 tomoyo_notify_gc(head, true);
1935 return 0; 1932 return 0;
1936} 1933}
1937 1934
@@ -2000,13 +1997,12 @@ static inline bool tomoyo_has_more_namespace(struct tomoyo_io_buffer *head)
2000 * @buffer_len: Size of @buffer. 1997 * @buffer_len: Size of @buffer.
2001 * 1998 *
2002 * Returns bytes read on success, negative value otherwise. 1999 * Returns bytes read on success, negative value otherwise.
2003 *
2004 * Caller holds tomoyo_read_lock().
2005 */ 2000 */
2006int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, 2001int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
2007 const int buffer_len) 2002 const int buffer_len)
2008{ 2003{
2009 int len; 2004 int len;
2005 int idx;
2010 2006
2011 if (!head->read) 2007 if (!head->read)
2012 return -ENOSYS; 2008 return -ENOSYS;
@@ -2014,6 +2010,7 @@ int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
2014 return -EINTR; 2010 return -EINTR;
2015 head->read_user_buf = buffer; 2011 head->read_user_buf = buffer;
2016 head->read_user_buf_avail = buffer_len; 2012 head->read_user_buf_avail = buffer_len;
2013 idx = tomoyo_read_lock();
2017 if (tomoyo_flush(head)) 2014 if (tomoyo_flush(head))
2018 /* Call the policy handler. */ 2015 /* Call the policy handler. */
2019 do { 2016 do {
@@ -2021,6 +2018,7 @@ int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
2021 head->read(head); 2018 head->read(head);
2022 } while (tomoyo_flush(head) && 2019 } while (tomoyo_flush(head) &&
2023 tomoyo_has_more_namespace(head)); 2020 tomoyo_has_more_namespace(head));
2021 tomoyo_read_unlock(idx);
2024 len = head->read_user_buf - buffer; 2022 len = head->read_user_buf - buffer;
2025 mutex_unlock(&head->io_sem); 2023 mutex_unlock(&head->io_sem);
2026 return len; 2024 return len;
@@ -2071,8 +2069,6 @@ static int tomoyo_parse_policy(struct tomoyo_io_buffer *head, char *line)
2071 * @buffer_len: Size of @buffer. 2069 * @buffer_len: Size of @buffer.
2072 * 2070 *
2073 * Returns @buffer_len on success, negative value otherwise. 2071 * Returns @buffer_len on success, negative value otherwise.
2074 *
2075 * Caller holds tomoyo_read_lock().
2076 */ 2072 */
2077int tomoyo_write_control(struct tomoyo_io_buffer *head, 2073int tomoyo_write_control(struct tomoyo_io_buffer *head,
2078 const char __user *buffer, const int buffer_len) 2074 const char __user *buffer, const int buffer_len)
@@ -2080,12 +2076,14 @@ int tomoyo_write_control(struct tomoyo_io_buffer *head,
2080 int error = buffer_len; 2076 int error = buffer_len;
2081 size_t avail_len = buffer_len; 2077 size_t avail_len = buffer_len;
2082 char *cp0 = head->write_buf; 2078 char *cp0 = head->write_buf;
2079 int idx;
2083 if (!head->write) 2080 if (!head->write)
2084 return -ENOSYS; 2081 return -ENOSYS;
2085 if (!access_ok(VERIFY_READ, buffer, buffer_len)) 2082 if (!access_ok(VERIFY_READ, buffer, buffer_len))
2086 return -EFAULT; 2083 return -EFAULT;
2087 if (mutex_lock_interruptible(&head->io_sem)) 2084 if (mutex_lock_interruptible(&head->io_sem))
2088 return -EINTR; 2085 return -EINTR;
2086 idx = tomoyo_read_lock();
2089 /* Read a line and dispatch it to the policy handler. */ 2087 /* Read a line and dispatch it to the policy handler. */
2090 while (avail_len > 0) { 2088 while (avail_len > 0) {
2091 char c; 2089 char c;
@@ -2148,6 +2146,7 @@ int tomoyo_write_control(struct tomoyo_io_buffer *head,
2148 } 2146 }
2149 } 2147 }
2150out: 2148out:
2149 tomoyo_read_unlock(idx);
2151 mutex_unlock(&head->io_sem); 2150 mutex_unlock(&head->io_sem);
2152 return error; 2151 return error;
2153} 2152}
@@ -2157,30 +2156,18 @@ out:
2157 * 2156 *
2158 * @head: Pointer to "struct tomoyo_io_buffer". 2157 * @head: Pointer to "struct tomoyo_io_buffer".
2159 * 2158 *
2160 * Releases memory and returns 0. 2159 * Returns 0.
2161 *
2162 * Caller looses tomoyo_read_lock().
2163 */ 2160 */
2164int tomoyo_close_control(struct tomoyo_io_buffer *head) 2161int tomoyo_close_control(struct tomoyo_io_buffer *head)
2165{ 2162{
2166 const bool is_write = !!head->write_buf;
2167
2168 /* 2163 /*
2169 * If the file is /sys/kernel/security/tomoyo/query , decrement the 2164 * If the file is /sys/kernel/security/tomoyo/query , decrement the
2170 * observer counter. 2165 * observer counter.
2171 */ 2166 */
2172 if (head->type == TOMOYO_QUERY) 2167 if (head->type == TOMOYO_QUERY &&
2173 atomic_dec(&tomoyo_query_observers); 2168 atomic_dec_and_test(&tomoyo_query_observers))
2174 else if (head->type != TOMOYO_AUDIT) 2169 wake_up_all(&tomoyo_answer_wait);
2175 tomoyo_read_unlock(head->reader_idx); 2170 tomoyo_notify_gc(head, false);
2176 /* Release memory used for policy I/O. */
2177 kfree(head->read_buf);
2178 head->read_buf = NULL;
2179 kfree(head->write_buf);
2180 head->write_buf = NULL;
2181 kfree(head);
2182 if (is_write)
2183 tomoyo_run_gc();
2184 return 0; 2171 return 0;
2185} 2172}
2186 2173
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 53c8798e38b7..a5eeabcc0738 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -441,8 +441,6 @@ struct tomoyo_io_buffer {
441 int (*poll) (struct file *file, poll_table *wait); 441 int (*poll) (struct file *file, poll_table *wait);
442 /* Exclusive lock for this structure. */ 442 /* Exclusive lock for this structure. */
443 struct mutex io_sem; 443 struct mutex io_sem;
444 /* Index returned by tomoyo_read_lock(). */
445 int reader_idx;
446 char __user *read_user_buf; 444 char __user *read_user_buf;
447 int read_user_buf_avail; 445 int read_user_buf_avail;
448 struct { 446 struct {
@@ -480,6 +478,10 @@ struct tomoyo_io_buffer {
480 int writebuf_size; 478 int writebuf_size;
481 /* Type of this interface. */ 479 /* Type of this interface. */
482 u8 type; 480 u8 type;
481 /* Users counter protected by tomoyo_io_buffer_list_lock. */
482 u8 users;
483 /* List for telling GC not to kfree() elements. */
484 struct list_head list;
483}; 485};
484 486
485/* 487/*
@@ -651,7 +653,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm);
651void tomoyo_print_ulong(char *buffer, const int buffer_len, 653void tomoyo_print_ulong(char *buffer, const int buffer_len,
652 const unsigned long value, const u8 type); 654 const unsigned long value, const u8 type);
653void tomoyo_put_name_union(struct tomoyo_name_union *ptr); 655void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
654void tomoyo_run_gc(void); 656void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register);
655void tomoyo_memory_free(void *ptr); 657void tomoyo_memory_free(void *ptr);
656int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 658int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
657 struct tomoyo_acl_param *param, 659 struct tomoyo_acl_param *param,
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index 782e844dca7f..1e1a6c8c832c 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -11,13 +11,123 @@
11#include <linux/kthread.h> 11#include <linux/kthread.h>
12#include <linux/slab.h> 12#include <linux/slab.h>
13 13
14/* The list for "struct tomoyo_io_buffer". */
15static LIST_HEAD(tomoyo_io_buffer_list);
16/* Lock for protecting tomoyo_io_buffer_list. */
17static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock);
18
19/* Size of an element. */
20static const u8 tomoyo_element_size[TOMOYO_MAX_POLICY] = {
21 [TOMOYO_ID_GROUP] = sizeof(struct tomoyo_group),
22 [TOMOYO_ID_PATH_GROUP] = sizeof(struct tomoyo_path_group),
23 [TOMOYO_ID_NUMBER_GROUP] = sizeof(struct tomoyo_number_group),
24 [TOMOYO_ID_AGGREGATOR] = sizeof(struct tomoyo_aggregator),
25 [TOMOYO_ID_TRANSITION_CONTROL] =
26 sizeof(struct tomoyo_transition_control),
27 [TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager),
28 /* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */
29 /* [TOMOYO_ID_ACL] =
30 tomoyo_acl_size["struct tomoyo_acl_info"->type], */
31 [TOMOYO_ID_DOMAIN] = sizeof(struct tomoyo_domain_info),
32};
33
34/* Size of a domain ACL element. */
35static const u8 tomoyo_acl_size[] = {
36 [TOMOYO_TYPE_PATH_ACL] = sizeof(struct tomoyo_path_acl),
37 [TOMOYO_TYPE_PATH2_ACL] = sizeof(struct tomoyo_path2_acl),
38 [TOMOYO_TYPE_PATH_NUMBER_ACL] = sizeof(struct tomoyo_path_number_acl),
39 [TOMOYO_TYPE_MKDEV_ACL] = sizeof(struct tomoyo_mkdev_acl),
40 [TOMOYO_TYPE_MOUNT_ACL] = sizeof(struct tomoyo_mount_acl),
41};
42
43/**
44 * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not.
45 *
46 * @element: Pointer to "struct list_head".
47 *
48 * Returns true if @element is used by /sys/kernel/security/tomoyo/ users,
49 * false otherwise.
50 */
51static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element)
52{
53 struct tomoyo_io_buffer *head;
54 bool in_use = false;
55
56 spin_lock(&tomoyo_io_buffer_list_lock);
57 list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
58 head->users++;
59 spin_unlock(&tomoyo_io_buffer_list_lock);
60 if (mutex_lock_interruptible(&head->io_sem)) {
61 in_use = true;
62 goto out;
63 }
64 if (head->r.domain == element || head->r.group == element ||
65 head->r.acl == element || &head->w.domain->list == element)
66 in_use = true;
67 mutex_unlock(&head->io_sem);
68out:
69 spin_lock(&tomoyo_io_buffer_list_lock);
70 head->users--;
71 if (in_use)
72 break;
73 }
74 spin_unlock(&tomoyo_io_buffer_list_lock);
75 return in_use;
76}
77
78/**
79 * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not.
80 *
81 * @string: String to check.
82 * @size: Memory allocated for @string .
83 *
84 * Returns true if @string is used by /sys/kernel/security/tomoyo/ users,
85 * false otherwise.
86 */
87static bool tomoyo_name_used_by_io_buffer(const char *string,
88 const size_t size)
89{
90 struct tomoyo_io_buffer *head;
91 bool in_use = false;
92
93 spin_lock(&tomoyo_io_buffer_list_lock);
94 list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
95 int i;
96 head->users++;
97 spin_unlock(&tomoyo_io_buffer_list_lock);
98 if (mutex_lock_interruptible(&head->io_sem)) {
99 in_use = true;
100 goto out;
101 }
102 for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
103 const char *w = head->r.w[i];
104 if (w < string || w > string + size)
105 continue;
106 in_use = true;
107 break;
108 }
109 mutex_unlock(&head->io_sem);
110out:
111 spin_lock(&tomoyo_io_buffer_list_lock);
112 head->users--;
113 if (in_use)
114 break;
115 }
116 spin_unlock(&tomoyo_io_buffer_list_lock);
117 return in_use;
118}
119
120/* Structure for garbage collection. */
14struct tomoyo_gc { 121struct tomoyo_gc {
15 struct list_head list; 122 struct list_head list;
16 enum tomoyo_policy_id type; 123 enum tomoyo_policy_id type;
124 size_t size;
17 struct list_head *element; 125 struct list_head *element;
18}; 126};
19static LIST_HEAD(tomoyo_gc_queue); 127/* List of entries to be deleted. */
20static DEFINE_MUTEX(tomoyo_gc_mutex); 128static LIST_HEAD(tomoyo_gc_list);
129/* Length of tomoyo_gc_list. */
130static int tomoyo_gc_list_len;
21 131
22/** 132/**
23 * tomoyo_add_to_gc - Add an entry to to be deleted list. 133 * tomoyo_add_to_gc - Add an entry to to be deleted list.
@@ -43,10 +153,42 @@ static bool tomoyo_add_to_gc(const int type, struct list_head *element)
43 if (!entry) 153 if (!entry)
44 return false; 154 return false;
45 entry->type = type; 155 entry->type = type;
156 if (type == TOMOYO_ID_ACL)
157 entry->size = tomoyo_acl_size[
158 container_of(element,
159 typeof(struct tomoyo_acl_info),
160 list)->type];
161 else if (type == TOMOYO_ID_NAME)
162 entry->size = strlen(container_of(element,
163 typeof(struct tomoyo_name),
164 head.list)->entry.name) + 1;
165 else
166 entry->size = tomoyo_element_size[type];
46 entry->element = element; 167 entry->element = element;
47 list_add(&entry->list, &tomoyo_gc_queue); 168 list_add(&entry->list, &tomoyo_gc_list);
48 list_del_rcu(element); 169 list_del_rcu(element);
49 return true; 170 return tomoyo_gc_list_len++ < 128;
171}
172
173/**
174 * tomoyo_element_linked_by_gc - Validate next element of an entry.
175 *
176 * @element: Pointer to an element.
177 * @size: Size of @element in byte.
178 *
179 * Returns true if @element is linked by other elements in the garbage
180 * collector's queue, false otherwise.
181 */
182static bool tomoyo_element_linked_by_gc(const u8 *element, const size_t size)
183{
184 struct tomoyo_gc *p;
185 list_for_each_entry(p, &tomoyo_gc_list, list) {
186 const u8 *ptr = (const u8 *) p->element->next;
187 if (ptr < element || element + size < ptr)
188 continue;
189 return true;
190 }
191 return false;
50} 192}
51 193
52/** 194/**
@@ -151,6 +293,13 @@ static void tomoyo_del_acl(struct list_head *element)
151 } 293 }
152} 294}
153 295
296/**
297 * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info".
298 *
299 * @element: Pointer to "struct list_head".
300 *
301 * Returns true if deleted, false otherwise.
302 */
154static bool tomoyo_del_domain(struct list_head *element) 303static bool tomoyo_del_domain(struct list_head *element)
155{ 304{
156 struct tomoyo_domain_info *domain = 305 struct tomoyo_domain_info *domain =
@@ -360,13 +509,44 @@ unlock:
360 mutex_unlock(&tomoyo_policy_lock); 509 mutex_unlock(&tomoyo_policy_lock);
361} 510}
362 511
363static void tomoyo_kfree_entry(void) 512/**
513 * tomoyo_kfree_entry - Delete entries in tomoyo_gc_list.
514 *
515 * Returns true if some entries were kfree()d, false otherwise.
516 */
517static bool tomoyo_kfree_entry(void)
364{ 518{
365 struct tomoyo_gc *p; 519 struct tomoyo_gc *p;
366 struct tomoyo_gc *tmp; 520 struct tomoyo_gc *tmp;
521 bool result = false;
367 522
368 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { 523 list_for_each_entry_safe(p, tmp, &tomoyo_gc_list, list) {
369 struct list_head *element = p->element; 524 struct list_head *element = p->element;
525
526 /*
527 * list_del_rcu() in tomoyo_add_to_gc() guarantees that the
528 * list element became no longer reachable from the list which
529 * the element was originally on (e.g. tomoyo_domain_list).
530 * Also, synchronize_srcu() in tomoyo_gc_thread() guarantees
531 * that the list element became no longer referenced by syscall
532 * users.
533 *
534 * However, there are three users which may still be using the
535 * list element. We need to defer until all of these users
536 * forget the list element.
537 *
538 * Firstly, defer until "struct tomoyo_io_buffer"->r.{domain,
539 * group,acl} and "struct tomoyo_io_buffer"->w.domain forget
540 * the list element.
541 */
542 if (tomoyo_struct_used_by_io_buffer(element))
543 continue;
544 /*
545 * Secondly, defer until all other elements in the
546 * tomoyo_gc_list list forget the list element.
547 */
548 if (tomoyo_element_linked_by_gc((const u8 *) element, p->size))
549 continue;
370 switch (p->type) { 550 switch (p->type) {
371 case TOMOYO_ID_TRANSITION_CONTROL: 551 case TOMOYO_ID_TRANSITION_CONTROL:
372 tomoyo_del_transition_control(element); 552 tomoyo_del_transition_control(element);
@@ -378,6 +558,14 @@ static void tomoyo_kfree_entry(void)
378 tomoyo_del_manager(element); 558 tomoyo_del_manager(element);
379 break; 559 break;
380 case TOMOYO_ID_NAME: 560 case TOMOYO_ID_NAME:
561 /*
562 * Thirdly, defer until all "struct tomoyo_io_buffer"
563 * ->r.w[] forget the list element.
564 */
565 if (tomoyo_name_used_by_io_buffer(
566 container_of(element, typeof(struct tomoyo_name),
567 head.list)->entry.name, p->size))
568 continue;
381 tomoyo_del_name(element); 569 tomoyo_del_name(element);
382 break; 570 break;
383 case TOMOYO_ID_ACL: 571 case TOMOYO_ID_ACL:
@@ -402,7 +590,10 @@ static void tomoyo_kfree_entry(void)
402 tomoyo_memory_free(element); 590 tomoyo_memory_free(element);
403 list_del(&p->list); 591 list_del(&p->list);
404 kfree(p); 592 kfree(p);
593 tomoyo_gc_list_len--;
594 result = true;
405 } 595 }
596 return result;
406} 597}
407 598
408/** 599/**
@@ -418,25 +609,70 @@ static void tomoyo_kfree_entry(void)
418 */ 609 */
419static int tomoyo_gc_thread(void *unused) 610static int tomoyo_gc_thread(void *unused)
420{ 611{
612 /* Garbage collector thread is exclusive. */
613 static DEFINE_MUTEX(tomoyo_gc_mutex);
614 if (!mutex_trylock(&tomoyo_gc_mutex))
615 goto out;
421 daemonize("GC for TOMOYO"); 616 daemonize("GC for TOMOYO");
422 if (mutex_trylock(&tomoyo_gc_mutex)) { 617 do {
423 int i; 618 tomoyo_collect_entry();
424 for (i = 0; i < 10; i++) { 619 if (list_empty(&tomoyo_gc_list))
425 tomoyo_collect_entry(); 620 break;
426 if (list_empty(&tomoyo_gc_queue)) 621 synchronize_srcu(&tomoyo_ss);
427 break; 622 } while (tomoyo_kfree_entry());
428 synchronize_srcu(&tomoyo_ss); 623 {
429 tomoyo_kfree_entry(); 624 struct tomoyo_io_buffer *head;
625 struct tomoyo_io_buffer *tmp;
626
627 spin_lock(&tomoyo_io_buffer_list_lock);
628 list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list,
629 list) {
630 if (head->users)
631 continue;
632 list_del(&head->list);
633 kfree(head->read_buf);
634 kfree(head->write_buf);
635 kfree(head);
430 } 636 }
431 mutex_unlock(&tomoyo_gc_mutex); 637 spin_unlock(&tomoyo_io_buffer_list_lock);
432 } 638 }
433 do_exit(0); 639 mutex_unlock(&tomoyo_gc_mutex);
640out:
641 /* This acts as do_exit(0). */
642 return 0;
434} 643}
435 644
436void tomoyo_run_gc(void) 645/**
646 * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users.
647 *
648 * @head: Pointer to "struct tomoyo_io_buffer".
649 * @is_register: True if register, false if unregister.
650 *
651 * Returns nothing.
652 */
653void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register)
437{ 654{
438 struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL, 655 bool is_write = false;
439 "GC for TOMOYO"); 656
440 if (!IS_ERR(task)) 657 spin_lock(&tomoyo_io_buffer_list_lock);
441 wake_up_process(task); 658 if (is_register) {
659 head->users = 1;
660 list_add(&head->list, &tomoyo_io_buffer_list);
661 } else {
662 is_write = head->write_buf != NULL;
663 if (!--head->users) {
664 list_del(&head->list);
665 kfree(head->read_buf);
666 kfree(head->write_buf);
667 kfree(head);
668 }
669 }
670 spin_unlock(&tomoyo_io_buffer_list_lock);
671 if (is_write) {
672 struct task_struct *task = kthread_create(tomoyo_gc_thread,
673 NULL,
674 "GC for TOMOYO");
675 if (!IS_ERR(task))
676 wake_up_process(task);
677 }
442} 678}