blob: f2295c65f1e42eaa0b61c14143bbd8bc33cd1fae [file] [log] [blame]
Tetsuo Handa847b1732010-02-11 09:43:54 +09001/*
2 * security/tomoyo/gc.c
3 *
Tetsuo Handa0f2a55d2011-07-14 14:46:51 +09004 * Copyright (C) 2005-2011 NTT DATA CORPORATION
Tetsuo Handa847b1732010-02-11 09:43:54 +09005 */
6
7#include "common.h"
8#include <linux/kthread.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09009#include <linux/slab.h>
Tetsuo Handa847b1732010-02-11 09:43:54 +090010
Tetsuo Handa2e503bb2011-06-26 23:20:55 +090011/* The list for "struct tomoyo_io_buffer". */
12static LIST_HEAD(tomoyo_io_buffer_list);
13/* Lock for protecting tomoyo_io_buffer_list. */
14static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock);
15
Tetsuo Handa2e503bb2011-06-26 23:20:55 +090016/**
17 * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not.
18 *
19 * @element: Pointer to "struct list_head".
20 *
21 * Returns true if @element is used by /sys/kernel/security/tomoyo/ users,
22 * false otherwise.
23 */
24static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element)
25{
26 struct tomoyo_io_buffer *head;
27 bool in_use = false;
28
29 spin_lock(&tomoyo_io_buffer_list_lock);
30 list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
31 head->users++;
32 spin_unlock(&tomoyo_io_buffer_list_lock);
Tetsuo Handaf9732ea2011-09-25 17:50:23 +090033 mutex_lock(&head->io_sem);
Tetsuo Handa2e503bb2011-06-26 23:20:55 +090034 if (head->r.domain == element || head->r.group == element ||
35 head->r.acl == element || &head->w.domain->list == element)
36 in_use = true;
37 mutex_unlock(&head->io_sem);
Tetsuo Handa2e503bb2011-06-26 23:20:55 +090038 spin_lock(&tomoyo_io_buffer_list_lock);
39 head->users--;
40 if (in_use)
41 break;
42 }
43 spin_unlock(&tomoyo_io_buffer_list_lock);
44 return in_use;
45}
46
47/**
48 * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not.
49 *
50 * @string: String to check.
Tetsuo Handa2e503bb2011-06-26 23:20:55 +090051 *
52 * Returns true if @string is used by /sys/kernel/security/tomoyo/ users,
53 * false otherwise.
54 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +090055static bool tomoyo_name_used_by_io_buffer(const char *string)
Tetsuo Handa2e503bb2011-06-26 23:20:55 +090056{
57 struct tomoyo_io_buffer *head;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +090058 const size_t size = strlen(string) + 1;
Tetsuo Handa2e503bb2011-06-26 23:20:55 +090059 bool in_use = false;
60
61 spin_lock(&tomoyo_io_buffer_list_lock);
62 list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
63 int i;
64 head->users++;
65 spin_unlock(&tomoyo_io_buffer_list_lock);
Tetsuo Handaf9732ea2011-09-25 17:50:23 +090066 mutex_lock(&head->io_sem);
Tetsuo Handa2e503bb2011-06-26 23:20:55 +090067 for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
68 const char *w = head->r.w[i];
69 if (w < string || w > string + size)
70 continue;
71 in_use = true;
72 break;
73 }
74 mutex_unlock(&head->io_sem);
Tetsuo Handa2e503bb2011-06-26 23:20:55 +090075 spin_lock(&tomoyo_io_buffer_list_lock);
76 head->users--;
77 if (in_use)
78 break;
79 }
80 spin_unlock(&tomoyo_io_buffer_list_lock);
81 return in_use;
82}
83
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +090084/**
85 * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
86 *
87 * @element: Pointer to "struct list_head".
88 *
89 * Returns nothing.
90 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +090091static inline void tomoyo_del_transition_control(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +090092{
Tetsuo Handa5448ec42010-06-21 11:14:39 +090093 struct tomoyo_transition_control *ptr =
Tetsuo Handae79acf02010-06-16 16:31:50 +090094 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa847b1732010-02-11 09:43:54 +090095 tomoyo_put_name(ptr->domainname);
96 tomoyo_put_name(ptr->program);
97}
98
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +090099/**
100 * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
101 *
102 * @element: Pointer to "struct list_head".
103 *
104 * Returns nothing.
105 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900106static inline void tomoyo_del_aggregator(struct list_head *element)
Tetsuo Handa10843072010-06-03 20:38:03 +0900107{
Tetsuo Handae2bf6902010-06-25 11:16:00 +0900108 struct tomoyo_aggregator *ptr =
Tetsuo Handae79acf02010-06-16 16:31:50 +0900109 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa10843072010-06-03 20:38:03 +0900110 tomoyo_put_name(ptr->original_name);
111 tomoyo_put_name(ptr->aggregated_name);
112}
113
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900114/**
115 * tomoyo_del_manager - Delete members in "struct tomoyo_manager".
116 *
117 * @element: Pointer to "struct list_head".
118 *
119 * Returns nothing.
120 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900121static inline void tomoyo_del_manager(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +0900122{
Tetsuo Handae2bf6902010-06-25 11:16:00 +0900123 struct tomoyo_manager *ptr =
Tetsuo Handae79acf02010-06-16 16:31:50 +0900124 container_of(element, typeof(*ptr), head.list);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900125 tomoyo_put_name(ptr->manager);
126}
127
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900128/**
129 * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
130 *
131 * @element: Pointer to "struct list_head".
132 *
133 * Returns nothing.
134 */
Tetsuo Handae79acf02010-06-16 16:31:50 +0900135static void tomoyo_del_acl(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +0900136{
Tetsuo Handae79acf02010-06-16 16:31:50 +0900137 struct tomoyo_acl_info *acl =
138 container_of(element, typeof(*acl), list);
Tetsuo Handa2066a362011-07-08 13:21:37 +0900139 tomoyo_put_condition(acl->cond);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900140 switch (acl->type) {
Tetsuo Handa7ef61232010-02-16 08:03:30 +0900141 case TOMOYO_TYPE_PATH_ACL:
Tetsuo Handa847b1732010-02-11 09:43:54 +0900142 {
Tetsuo Handa7ef61232010-02-16 08:03:30 +0900143 struct tomoyo_path_acl *entry
Tetsuo Handa847b1732010-02-11 09:43:54 +0900144 = container_of(acl, typeof(*entry), head);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900145 tomoyo_put_name_union(&entry->name);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900146 }
147 break;
Tetsuo Handa7ef61232010-02-16 08:03:30 +0900148 case TOMOYO_TYPE_PATH2_ACL:
Tetsuo Handa847b1732010-02-11 09:43:54 +0900149 {
Tetsuo Handa7ef61232010-02-16 08:03:30 +0900150 struct tomoyo_path2_acl *entry
Tetsuo Handa847b1732010-02-11 09:43:54 +0900151 = container_of(acl, typeof(*entry), head);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900152 tomoyo_put_name_union(&entry->name1);
153 tomoyo_put_name_union(&entry->name2);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900154 }
155 break;
Tetsuo Handaa1f9bb62010-05-17 10:09:15 +0900156 case TOMOYO_TYPE_PATH_NUMBER_ACL:
157 {
158 struct tomoyo_path_number_acl *entry
159 = container_of(acl, typeof(*entry), head);
160 tomoyo_put_name_union(&entry->name);
161 tomoyo_put_number_union(&entry->number);
162 }
163 break;
Tetsuo Handa75093152010-06-16 16:23:55 +0900164 case TOMOYO_TYPE_MKDEV_ACL:
Tetsuo Handaa1f9bb62010-05-17 10:09:15 +0900165 {
Tetsuo Handa75093152010-06-16 16:23:55 +0900166 struct tomoyo_mkdev_acl *entry
Tetsuo Handaa1f9bb62010-05-17 10:09:15 +0900167 = container_of(acl, typeof(*entry), head);
168 tomoyo_put_name_union(&entry->name);
169 tomoyo_put_number_union(&entry->mode);
170 tomoyo_put_number_union(&entry->major);
171 tomoyo_put_number_union(&entry->minor);
172 }
173 break;
Tetsuo Handa2106ccd2010-05-17 10:10:31 +0900174 case TOMOYO_TYPE_MOUNT_ACL:
175 {
176 struct tomoyo_mount_acl *entry
177 = container_of(acl, typeof(*entry), head);
178 tomoyo_put_name_union(&entry->dev_name);
179 tomoyo_put_name_union(&entry->dir_name);
180 tomoyo_put_name_union(&entry->fs_type);
181 tomoyo_put_number_union(&entry->flags);
182 }
183 break;
Tetsuo Handad58e0da2011-09-10 15:22:48 +0900184 case TOMOYO_TYPE_ENV_ACL:
185 {
186 struct tomoyo_env_acl *entry =
187 container_of(acl, typeof(*entry), head);
188
189 tomoyo_put_name(entry->env);
190 }
191 break;
Tetsuo Handa059d84d2011-09-10 15:23:54 +0900192 case TOMOYO_TYPE_INET_ACL:
193 {
194 struct tomoyo_inet_acl *entry =
195 container_of(acl, typeof(*entry), head);
196
197 tomoyo_put_group(entry->address.group);
198 tomoyo_put_number_union(&entry->port);
199 }
200 break;
201 case TOMOYO_TYPE_UNIX_ACL:
202 {
203 struct tomoyo_unix_acl *entry =
204 container_of(acl, typeof(*entry), head);
205
206 tomoyo_put_name_union(&entry->name);
207 }
208 break;
Tetsuo Handa847b1732010-02-11 09:43:54 +0900209 }
210}
211
Tetsuo Handa2e503bb2011-06-26 23:20:55 +0900212/**
213 * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info".
214 *
215 * @element: Pointer to "struct list_head".
216 *
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900217 * Returns nothing.
Tetsuo Handa2e503bb2011-06-26 23:20:55 +0900218 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900219static inline void tomoyo_del_domain(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +0900220{
Tetsuo Handae79acf02010-06-16 16:31:50 +0900221 struct tomoyo_domain_info *domain =
222 container_of(element, typeof(*domain), list);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900223 struct tomoyo_acl_info *acl;
224 struct tomoyo_acl_info *tmp;
225 /*
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900226 * Since this domain is referenced from neither
227 * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete
228 * elements without checking for is_deleted flag.
Tetsuo Handa847b1732010-02-11 09:43:54 +0900229 */
Tetsuo Handa847b1732010-02-11 09:43:54 +0900230 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
Tetsuo Handae79acf02010-06-16 16:31:50 +0900231 tomoyo_del_acl(&acl->list);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900232 tomoyo_memory_free(acl);
233 }
234 tomoyo_put_name(domain->domainname);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900235}
236
Tetsuo Handa2066a362011-07-08 13:21:37 +0900237/**
238 * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
239 *
240 * @element: Pointer to "struct list_head".
241 *
242 * Returns nothing.
243 */
244void tomoyo_del_condition(struct list_head *element)
245{
246 struct tomoyo_condition *cond = container_of(element, typeof(*cond),
247 head.list);
248 const u16 condc = cond->condc;
249 const u16 numbers_count = cond->numbers_count;
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900250 const u16 names_count = cond->names_count;
Tetsuo Handa5b636852011-07-08 13:24:54 +0900251 const u16 argc = cond->argc;
252 const u16 envc = cond->envc;
Tetsuo Handa2066a362011-07-08 13:21:37 +0900253 unsigned int i;
254 const struct tomoyo_condition_element *condp
255 = (const struct tomoyo_condition_element *) (cond + 1);
256 struct tomoyo_number_union *numbers_p
257 = (struct tomoyo_number_union *) (condp + condc);
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900258 struct tomoyo_name_union *names_p
259 = (struct tomoyo_name_union *) (numbers_p + numbers_count);
Tetsuo Handa5b636852011-07-08 13:24:54 +0900260 const struct tomoyo_argv *argv
261 = (const struct tomoyo_argv *) (names_p + names_count);
262 const struct tomoyo_envp *envp
263 = (const struct tomoyo_envp *) (argv + argc);
Tetsuo Handa2066a362011-07-08 13:21:37 +0900264 for (i = 0; i < numbers_count; i++)
265 tomoyo_put_number_union(numbers_p++);
Tetsuo Handa2ca9bf42011-07-08 13:23:44 +0900266 for (i = 0; i < names_count; i++)
267 tomoyo_put_name_union(names_p++);
Tetsuo Handa5b636852011-07-08 13:24:54 +0900268 for (i = 0; i < argc; argv++, i++)
269 tomoyo_put_name(argv->value);
270 for (i = 0; i < envc; envp++, i++) {
271 tomoyo_put_name(envp->name);
272 tomoyo_put_name(envp->value);
273 }
Tetsuo Handa2066a362011-07-08 13:21:37 +0900274}
Tetsuo Handa847b1732010-02-11 09:43:54 +0900275
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900276/**
277 * tomoyo_del_name - Delete members in "struct tomoyo_name".
278 *
279 * @element: Pointer to "struct list_head".
280 *
281 * Returns nothing.
282 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900283static inline void tomoyo_del_name(struct list_head *element)
Tetsuo Handa847b1732010-02-11 09:43:54 +0900284{
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900285 /* Nothing to do. */
Tetsuo Handa847b1732010-02-11 09:43:54 +0900286}
287
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900288/**
289 * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
290 *
291 * @element: Pointer to "struct list_head".
292 *
293 * Returns nothing.
294 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900295static inline void tomoyo_del_path_group(struct list_head *element)
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900296{
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900297 struct tomoyo_path_group *member =
Tetsuo Handae79acf02010-06-16 16:31:50 +0900298 container_of(element, typeof(*member), head.list);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900299 tomoyo_put_name(member->member_name);
300}
301
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900302/**
303 * tomoyo_del_group - Delete "struct tomoyo_group".
304 *
305 * @element: Pointer to "struct list_head".
306 *
307 * Returns nothing.
308 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900309static inline void tomoyo_del_group(struct list_head *element)
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900310{
Tetsuo Handaa98aa4d2010-06-17 16:52:29 +0900311 struct tomoyo_group *group =
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900312 container_of(element, typeof(*group), head.list);
Tetsuo Handa7762fbf2010-05-10 17:30:26 +0900313 tomoyo_put_name(group->group_name);
314}
315
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900316/**
Tetsuo Handa059d84d2011-09-10 15:23:54 +0900317 * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group".
318 *
319 * @element: Pointer to "struct list_head".
320 *
321 * Returns nothing.
322 */
323static inline void tomoyo_del_address_group(struct list_head *element)
324{
325 /* Nothing to do. */
326}
327
328/**
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900329 * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
330 *
331 * @element: Pointer to "struct list_head".
332 *
333 * Returns nothing.
334 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900335static inline void tomoyo_del_number_group(struct list_head *element)
Tetsuo Handa4c3e9e22010-05-17 10:06:58 +0900336{
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900337 /* Nothing to do. */
338}
339
340/**
341 * tomoyo_try_to_gc - Try to kfree() an entry.
342 *
343 * @type: One of values in "enum tomoyo_policy_id".
344 * @element: Pointer to "struct list_head".
345 *
346 * Returns nothing.
347 *
348 * Caller holds tomoyo_policy_lock mutex.
349 */
350static void tomoyo_try_to_gc(const enum tomoyo_policy_id type,
351 struct list_head *element)
352{
353 /*
354 * __list_del_entry() guarantees that the list element became no longer
355 * reachable from the list which the element was originally on (e.g.
356 * tomoyo_domain_list). Also, synchronize_srcu() guarantees that the
357 * list element became no longer referenced by syscall users.
358 */
359 __list_del_entry(element);
360 mutex_unlock(&tomoyo_policy_lock);
361 synchronize_srcu(&tomoyo_ss);
362 /*
363 * However, there are two users which may still be using the list
364 * element. We need to defer until both users forget this element.
365 *
366 * Don't kfree() until "struct tomoyo_io_buffer"->r.{domain,group,acl}
367 * and "struct tomoyo_io_buffer"->w.domain forget this element.
368 */
369 if (tomoyo_struct_used_by_io_buffer(element))
370 goto reinject;
371 switch (type) {
372 case TOMOYO_ID_TRANSITION_CONTROL:
373 tomoyo_del_transition_control(element);
374 break;
375 case TOMOYO_ID_MANAGER:
376 tomoyo_del_manager(element);
377 break;
378 case TOMOYO_ID_AGGREGATOR:
379 tomoyo_del_aggregator(element);
380 break;
381 case TOMOYO_ID_GROUP:
382 tomoyo_del_group(element);
383 break;
384 case TOMOYO_ID_PATH_GROUP:
385 tomoyo_del_path_group(element);
386 break;
387 case TOMOYO_ID_ADDRESS_GROUP:
388 tomoyo_del_address_group(element);
389 break;
390 case TOMOYO_ID_NUMBER_GROUP:
391 tomoyo_del_number_group(element);
392 break;
393 case TOMOYO_ID_CONDITION:
394 tomoyo_del_condition(element);
395 break;
396 case TOMOYO_ID_NAME:
397 /*
398 * Don't kfree() until all "struct tomoyo_io_buffer"->r.w[]
399 * forget this element.
400 */
401 if (tomoyo_name_used_by_io_buffer
402 (container_of(element, typeof(struct tomoyo_name),
403 head.list)->entry.name))
404 goto reinject;
405 tomoyo_del_name(element);
406 break;
407 case TOMOYO_ID_ACL:
408 tomoyo_del_acl(element);
409 break;
410 case TOMOYO_ID_DOMAIN:
411 /*
412 * Don't kfree() until all "struct cred"->security forget this
413 * element.
414 */
415 if (atomic_read(&container_of
416 (element, typeof(struct tomoyo_domain_info),
417 list)->users))
418 goto reinject;
419 tomoyo_del_domain(element);
420 break;
421 case TOMOYO_MAX_POLICY:
422 break;
423 }
424 mutex_lock(&tomoyo_policy_lock);
425 tomoyo_memory_free(element);
426 return;
427reinject:
428 /*
429 * We can safely reinject this element here bacause
430 * (1) Appending list elements and removing list elements are protected
431 * by tomoyo_policy_lock mutex.
432 * (2) Only this function removes list elements and this function is
433 * exclusively executed by tomoyo_gc_mutex mutex.
434 * are true.
435 */
436 mutex_lock(&tomoyo_policy_lock);
437 list_add_rcu(element, element->prev);
Tetsuo Handa4c3e9e22010-05-17 10:06:58 +0900438}
439
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900440/**
441 * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head".
442 *
443 * @id: One of values in "enum tomoyo_policy_id".
444 * @member_list: Pointer to "struct list_head".
445 *
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900446 * Returns nothing.
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900447 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900448static void tomoyo_collect_member(const enum tomoyo_policy_id id,
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900449 struct list_head *member_list)
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900450{
451 struct tomoyo_acl_head *member;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900452 struct tomoyo_acl_head *tmp;
453 list_for_each_entry_safe(member, tmp, member_list, list) {
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900454 if (!member->is_deleted)
455 continue;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900456 member->is_deleted = TOMOYO_GC_IN_PROGRESS;
457 tomoyo_try_to_gc(id, &member->list);
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900458 }
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900459}
460
Tetsuo Handa32997142011-06-26 23:19:28 +0900461/**
462 * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info".
463 *
464 * @list: Pointer to "struct list_head".
465 *
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900466 * Returns nothing.
Tetsuo Handa32997142011-06-26 23:19:28 +0900467 */
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900468static void tomoyo_collect_acl(struct list_head *list)
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900469{
470 struct tomoyo_acl_info *acl;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900471 struct tomoyo_acl_info *tmp;
472 list_for_each_entry_safe(acl, tmp, list, list) {
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900473 if (!acl->is_deleted)
474 continue;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900475 acl->is_deleted = TOMOYO_GC_IN_PROGRESS;
476 tomoyo_try_to_gc(TOMOYO_ID_ACL, &acl->list);
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900477 }
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900478}
479
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900480/**
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900481 * tomoyo_collect_entry - Try to kfree() deleted elements.
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900482 *
483 * Returns nothing.
484 */
Tetsuo Handa847b1732010-02-11 09:43:54 +0900485static void tomoyo_collect_entry(void)
486{
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900487 int i;
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900488 enum tomoyo_policy_id id;
489 struct tomoyo_policy_namespace *ns;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900490 mutex_lock(&tomoyo_policy_lock);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900491 {
492 struct tomoyo_domain_info *domain;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900493 struct tomoyo_domain_info *tmp;
494 list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list,
495 list) {
496 tomoyo_collect_acl(&domain->acl_info_list);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900497 if (!domain->is_deleted || atomic_read(&domain->users))
498 continue;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900499 tomoyo_try_to_gc(TOMOYO_ID_DOMAIN, &domain->list);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900500 }
501 }
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900502 list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900503 for (id = 0; id < TOMOYO_MAX_POLICY; id++)
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900504 tomoyo_collect_member(id, &ns->policy_list[id]);
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900505 for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900506 tomoyo_collect_acl(&ns->acl_group[i]);
507 }
508 {
509 struct tomoyo_shared_acl_head *ptr;
510 struct tomoyo_shared_acl_head *tmp;
511 list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list,
512 list) {
513 if (atomic_read(&ptr->users) > 0)
514 continue;
515 atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
516 tomoyo_try_to_gc(TOMOYO_ID_CONDITION, &ptr->list);
517 }
518 }
519 list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) {
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900520 for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
521 struct list_head *list = &ns->group_list[i];
522 struct tomoyo_group *group;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900523 struct tomoyo_group *tmp;
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900524 switch (i) {
525 case 0:
526 id = TOMOYO_ID_PATH_GROUP;
527 break;
Tetsuo Handa059d84d2011-09-10 15:23:54 +0900528 case 1:
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900529 id = TOMOYO_ID_NUMBER_GROUP;
530 break;
Tetsuo Handa059d84d2011-09-10 15:23:54 +0900531 default:
532 id = TOMOYO_ID_ADDRESS_GROUP;
533 break;
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900534 }
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900535 list_for_each_entry_safe(group, tmp, list, head.list) {
536 tomoyo_collect_member(id, &group->member_list);
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900537 if (!list_empty(&group->member_list) ||
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900538 atomic_read(&group->head.users) > 0)
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900539 continue;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900540 atomic_set(&group->head.users,
541 TOMOYO_GC_IN_PROGRESS);
542 tomoyo_try_to_gc(TOMOYO_ID_GROUP,
543 &group->head.list);
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900544 }
545 }
546 }
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900547 for (i = 0; i < TOMOYO_MAX_HASH; i++) {
548 struct list_head *list = &tomoyo_name_list[i];
Tetsuo Handabd03a3e2011-06-26 23:19:52 +0900549 struct tomoyo_shared_acl_head *ptr;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900550 struct tomoyo_shared_acl_head *tmp;
551 list_for_each_entry_safe(ptr, tmp, list, list) {
552 if (atomic_read(&ptr->users) > 0)
Tetsuo Handad2f8b232010-06-15 10:10:37 +0900553 continue;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900554 atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS);
555 tomoyo_try_to_gc(TOMOYO_ID_NAME, &ptr->list);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900556 }
557 }
Tetsuo Handa29282382010-05-06 00:18:15 +0900558 mutex_unlock(&tomoyo_policy_lock);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900559}
560
Tetsuo Handa2e503bb2011-06-26 23:20:55 +0900561/**
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900562 * tomoyo_gc_thread - Garbage collector thread function.
563 *
564 * @unused: Unused.
565 *
Tetsuo Handa0df7e8b2011-06-26 23:16:36 +0900566 * Returns 0.
567 */
Tetsuo Handa847b1732010-02-11 09:43:54 +0900568static int tomoyo_gc_thread(void *unused)
569{
Tetsuo Handa2e503bb2011-06-26 23:20:55 +0900570 /* Garbage collector thread is exclusive. */
571 static DEFINE_MUTEX(tomoyo_gc_mutex);
572 if (!mutex_trylock(&tomoyo_gc_mutex))
573 goto out;
Tetsuo Handaf9732ea2011-09-25 17:50:23 +0900574 tomoyo_collect_entry();
Tetsuo Handa2e503bb2011-06-26 23:20:55 +0900575 {
576 struct tomoyo_io_buffer *head;
577 struct tomoyo_io_buffer *tmp;
578
579 spin_lock(&tomoyo_io_buffer_list_lock);
580 list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list,
581 list) {
582 if (head->users)
583 continue;
584 list_del(&head->list);
585 kfree(head->read_buf);
586 kfree(head->write_buf);
587 kfree(head);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900588 }
Tetsuo Handa2e503bb2011-06-26 23:20:55 +0900589 spin_unlock(&tomoyo_io_buffer_list_lock);
Tetsuo Handa847b1732010-02-11 09:43:54 +0900590 }
Tetsuo Handa2e503bb2011-06-26 23:20:55 +0900591 mutex_unlock(&tomoyo_gc_mutex);
592out:
593 /* This acts as do_exit(0). */
594 return 0;
Tetsuo Handa847b1732010-02-11 09:43:54 +0900595}
596
Tetsuo Handa2e503bb2011-06-26 23:20:55 +0900597/**
598 * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users.
599 *
600 * @head: Pointer to "struct tomoyo_io_buffer".
601 * @is_register: True if register, false if unregister.
602 *
603 * Returns nothing.
604 */
605void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register)
Tetsuo Handa847b1732010-02-11 09:43:54 +0900606{
Tetsuo Handa2e503bb2011-06-26 23:20:55 +0900607 bool is_write = false;
608
609 spin_lock(&tomoyo_io_buffer_list_lock);
610 if (is_register) {
611 head->users = 1;
612 list_add(&head->list, &tomoyo_io_buffer_list);
613 } else {
614 is_write = head->write_buf != NULL;
615 if (!--head->users) {
616 list_del(&head->list);
617 kfree(head->read_buf);
618 kfree(head->write_buf);
619 kfree(head);
620 }
621 }
622 spin_unlock(&tomoyo_io_buffer_list_lock);
623 if (is_write) {
624 struct task_struct *task = kthread_create(tomoyo_gc_thread,
625 NULL,
626 "GC for TOMOYO");
627 if (!IS_ERR(task))
628 wake_up_process(task);
629 }
Tetsuo Handa847b1732010-02-11 09:43:54 +0900630}