]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - security/tomoyo/gc.c
TOMOYO: Fix make namespacecheck warnings.
[mirror_ubuntu-bionic-kernel.git] / security / tomoyo / gc.c
CommitLineData
847b173e
TH
1/*
2 * security/tomoyo/gc.c
3 *
0f2a55d5 4 * Copyright (C) 2005-2011 NTT DATA CORPORATION
847b173e
TH
5 */
6
7#include "common.h"
8#include <linux/kthread.h>
5a0e3ad6 9#include <linux/slab.h>
847b173e 10
2e503bbb
TH
11/* 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
16/* Size of an element. */
17static const u8 tomoyo_element_size[TOMOYO_MAX_POLICY] = {
18 [TOMOYO_ID_GROUP] = sizeof(struct tomoyo_group),
059d84db 19 [TOMOYO_ID_ADDRESS_GROUP] = sizeof(struct tomoyo_address_group),
2e503bbb
TH
20 [TOMOYO_ID_PATH_GROUP] = sizeof(struct tomoyo_path_group),
21 [TOMOYO_ID_NUMBER_GROUP] = sizeof(struct tomoyo_number_group),
22 [TOMOYO_ID_AGGREGATOR] = sizeof(struct tomoyo_aggregator),
23 [TOMOYO_ID_TRANSITION_CONTROL] =
24 sizeof(struct tomoyo_transition_control),
25 [TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager),
2066a361 26 /* [TOMOYO_ID_CONDITION] = "struct tomoyo_condition"->size, */
2e503bbb
TH
27 /* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */
28 /* [TOMOYO_ID_ACL] =
29 tomoyo_acl_size["struct tomoyo_acl_info"->type], */
30 [TOMOYO_ID_DOMAIN] = sizeof(struct tomoyo_domain_info),
31};
32
33/* Size of a domain ACL element. */
34static const u8 tomoyo_acl_size[] = {
35 [TOMOYO_TYPE_PATH_ACL] = sizeof(struct tomoyo_path_acl),
36 [TOMOYO_TYPE_PATH2_ACL] = sizeof(struct tomoyo_path2_acl),
37 [TOMOYO_TYPE_PATH_NUMBER_ACL] = sizeof(struct tomoyo_path_number_acl),
38 [TOMOYO_TYPE_MKDEV_ACL] = sizeof(struct tomoyo_mkdev_acl),
39 [TOMOYO_TYPE_MOUNT_ACL] = sizeof(struct tomoyo_mount_acl),
059d84db
TH
40 [TOMOYO_TYPE_INET_ACL] = sizeof(struct tomoyo_inet_acl),
41 [TOMOYO_TYPE_UNIX_ACL] = sizeof(struct tomoyo_unix_acl),
d58e0da8 42 [TOMOYO_TYPE_ENV_ACL] = sizeof(struct tomoyo_env_acl),
2e503bbb
TH
43};
44
45/**
46 * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not.
47 *
48 * @element: Pointer to "struct list_head".
49 *
50 * Returns true if @element is used by /sys/kernel/security/tomoyo/ users,
51 * false otherwise.
52 */
53static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element)
54{
55 struct tomoyo_io_buffer *head;
56 bool in_use = false;
57
58 spin_lock(&tomoyo_io_buffer_list_lock);
59 list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
60 head->users++;
61 spin_unlock(&tomoyo_io_buffer_list_lock);
62 if (mutex_lock_interruptible(&head->io_sem)) {
63 in_use = true;
64 goto out;
65 }
66 if (head->r.domain == element || head->r.group == element ||
67 head->r.acl == element || &head->w.domain->list == element)
68 in_use = true;
69 mutex_unlock(&head->io_sem);
70out:
71 spin_lock(&tomoyo_io_buffer_list_lock);
72 head->users--;
73 if (in_use)
74 break;
75 }
76 spin_unlock(&tomoyo_io_buffer_list_lock);
77 return in_use;
78}
79
80/**
81 * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not.
82 *
83 * @string: String to check.
84 * @size: Memory allocated for @string .
85 *
86 * Returns true if @string is used by /sys/kernel/security/tomoyo/ users,
87 * false otherwise.
88 */
89static bool tomoyo_name_used_by_io_buffer(const char *string,
90 const size_t size)
91{
92 struct tomoyo_io_buffer *head;
93 bool in_use = false;
94
95 spin_lock(&tomoyo_io_buffer_list_lock);
96 list_for_each_entry(head, &tomoyo_io_buffer_list, list) {
97 int i;
98 head->users++;
99 spin_unlock(&tomoyo_io_buffer_list_lock);
100 if (mutex_lock_interruptible(&head->io_sem)) {
101 in_use = true;
102 goto out;
103 }
104 for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) {
105 const char *w = head->r.w[i];
106 if (w < string || w > string + size)
107 continue;
108 in_use = true;
109 break;
110 }
111 mutex_unlock(&head->io_sem);
112out:
113 spin_lock(&tomoyo_io_buffer_list_lock);
114 head->users--;
115 if (in_use)
116 break;
117 }
118 spin_unlock(&tomoyo_io_buffer_list_lock);
119 return in_use;
120}
121
122/* Structure for garbage collection. */
e2bf6907 123struct tomoyo_gc {
847b173e 124 struct list_head list;
0df7e8b8 125 enum tomoyo_policy_id type;
2e503bbb 126 size_t size;
e79acf0e 127 struct list_head *element;
847b173e 128};
2e503bbb
TH
129/* List of entries to be deleted. */
130static LIST_HEAD(tomoyo_gc_list);
131/* Length of tomoyo_gc_list. */
132static int tomoyo_gc_list_len;
847b173e 133
0df7e8b8
TH
134/**
135 * tomoyo_add_to_gc - Add an entry to to be deleted list.
136 *
137 * @type: One of values in "enum tomoyo_policy_id".
138 * @element: Pointer to "struct list_head".
139 *
140 * Returns true on success, false otherwise.
141 *
142 * Caller holds tomoyo_policy_lock mutex.
143 *
144 * Adding an entry needs kmalloc(). Thus, if we try to add thousands of
145 * entries at once, it will take too long time. Thus, do not add more than 128
146 * entries per a scan. But to be able to handle worst case where all entries
147 * are in-use, we accept one more entry per a scan.
148 *
149 * If we use singly linked list using "struct list_head"->prev (which is
150 * LIST_POISON2), we can avoid kmalloc().
151 */
e79acf0e 152static bool tomoyo_add_to_gc(const int type, struct list_head *element)
847b173e 153{
e2bf6907 154 struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
847b173e
TH
155 if (!entry)
156 return false;
157 entry->type = type;
2e503bbb
TH
158 if (type == TOMOYO_ID_ACL)
159 entry->size = tomoyo_acl_size[
160 container_of(element,
161 typeof(struct tomoyo_acl_info),
162 list)->type];
163 else if (type == TOMOYO_ID_NAME)
164 entry->size = strlen(container_of(element,
165 typeof(struct tomoyo_name),
166 head.list)->entry.name) + 1;
2066a361
TH
167 else if (type == TOMOYO_ID_CONDITION)
168 entry->size =
169 container_of(element, typeof(struct tomoyo_condition),
170 head.list)->size;
2e503bbb
TH
171 else
172 entry->size = tomoyo_element_size[type];
847b173e 173 entry->element = element;
2e503bbb 174 list_add(&entry->list, &tomoyo_gc_list);
e79acf0e 175 list_del_rcu(element);
2e503bbb
TH
176 return tomoyo_gc_list_len++ < 128;
177}
178
179/**
180 * tomoyo_element_linked_by_gc - Validate next element of an entry.
181 *
182 * @element: Pointer to an element.
183 * @size: Size of @element in byte.
184 *
185 * Returns true if @element is linked by other elements in the garbage
186 * collector's queue, false otherwise.
187 */
188static bool tomoyo_element_linked_by_gc(const u8 *element, const size_t size)
189{
190 struct tomoyo_gc *p;
191 list_for_each_entry(p, &tomoyo_gc_list, list) {
192 const u8 *ptr = (const u8 *) p->element->next;
193 if (ptr < element || element + size < ptr)
194 continue;
195 return true;
196 }
197 return false;
847b173e
TH
198}
199
0df7e8b8
TH
200/**
201 * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
202 *
203 * @element: Pointer to "struct list_head".
204 *
205 * Returns nothing.
206 */
5448ec4f 207static void tomoyo_del_transition_control(struct list_head *element)
847b173e 208{
5448ec4f 209 struct tomoyo_transition_control *ptr =
e79acf0e 210 container_of(element, typeof(*ptr), head.list);
847b173e
TH
211 tomoyo_put_name(ptr->domainname);
212 tomoyo_put_name(ptr->program);
213}
214
0df7e8b8
TH
215/**
216 * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
217 *
218 * @element: Pointer to "struct list_head".
219 *
220 * Returns nothing.
221 */
e79acf0e 222static void tomoyo_del_aggregator(struct list_head *element)
1084307c 223{
e2bf6907 224 struct tomoyo_aggregator *ptr =
e79acf0e 225 container_of(element, typeof(*ptr), head.list);
1084307c
TH
226 tomoyo_put_name(ptr->original_name);
227 tomoyo_put_name(ptr->aggregated_name);
228}
229
0df7e8b8
TH
230/**
231 * tomoyo_del_manager - Delete members in "struct tomoyo_manager".
232 *
233 * @element: Pointer to "struct list_head".
234 *
235 * Returns nothing.
236 */
e79acf0e 237static void tomoyo_del_manager(struct list_head *element)
847b173e 238{
e2bf6907 239 struct tomoyo_manager *ptr =
e79acf0e 240 container_of(element, typeof(*ptr), head.list);
847b173e
TH
241 tomoyo_put_name(ptr->manager);
242}
243
0df7e8b8
TH
244/**
245 * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
246 *
247 * @element: Pointer to "struct list_head".
248 *
249 * Returns nothing.
250 */
e79acf0e 251static void tomoyo_del_acl(struct list_head *element)
847b173e 252{
e79acf0e
TH
253 struct tomoyo_acl_info *acl =
254 container_of(element, typeof(*acl), list);
2066a361 255 tomoyo_put_condition(acl->cond);
847b173e 256 switch (acl->type) {
7ef61233 257 case TOMOYO_TYPE_PATH_ACL:
847b173e 258 {
7ef61233 259 struct tomoyo_path_acl *entry
847b173e 260 = container_of(acl, typeof(*entry), head);
7762fbff 261 tomoyo_put_name_union(&entry->name);
847b173e
TH
262 }
263 break;
7ef61233 264 case TOMOYO_TYPE_PATH2_ACL:
847b173e 265 {
7ef61233 266 struct tomoyo_path2_acl *entry
847b173e 267 = container_of(acl, typeof(*entry), head);
7762fbff
TH
268 tomoyo_put_name_union(&entry->name1);
269 tomoyo_put_name_union(&entry->name2);
847b173e
TH
270 }
271 break;
a1f9bb6a
TH
272 case TOMOYO_TYPE_PATH_NUMBER_ACL:
273 {
274 struct tomoyo_path_number_acl *entry
275 = container_of(acl, typeof(*entry), head);
276 tomoyo_put_name_union(&entry->name);
277 tomoyo_put_number_union(&entry->number);
278 }
279 break;
75093152 280 case TOMOYO_TYPE_MKDEV_ACL:
a1f9bb6a 281 {
75093152 282 struct tomoyo_mkdev_acl *entry
a1f9bb6a
TH
283 = container_of(acl, typeof(*entry), head);
284 tomoyo_put_name_union(&entry->name);
285 tomoyo_put_number_union(&entry->mode);
286 tomoyo_put_number_union(&entry->major);
287 tomoyo_put_number_union(&entry->minor);
288 }
289 break;
2106ccd9
TH
290 case TOMOYO_TYPE_MOUNT_ACL:
291 {
292 struct tomoyo_mount_acl *entry
293 = container_of(acl, typeof(*entry), head);
294 tomoyo_put_name_union(&entry->dev_name);
295 tomoyo_put_name_union(&entry->dir_name);
296 tomoyo_put_name_union(&entry->fs_type);
297 tomoyo_put_number_union(&entry->flags);
298 }
299 break;
d58e0da8
TH
300 case TOMOYO_TYPE_ENV_ACL:
301 {
302 struct tomoyo_env_acl *entry =
303 container_of(acl, typeof(*entry), head);
304
305 tomoyo_put_name(entry->env);
306 }
307 break;
059d84db
TH
308 case TOMOYO_TYPE_INET_ACL:
309 {
310 struct tomoyo_inet_acl *entry =
311 container_of(acl, typeof(*entry), head);
312
313 tomoyo_put_group(entry->address.group);
314 tomoyo_put_number_union(&entry->port);
315 }
316 break;
317 case TOMOYO_TYPE_UNIX_ACL:
318 {
319 struct tomoyo_unix_acl *entry =
320 container_of(acl, typeof(*entry), head);
321
322 tomoyo_put_name_union(&entry->name);
323 }
324 break;
847b173e
TH
325 }
326}
327
2e503bbb
TH
328/**
329 * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info".
330 *
331 * @element: Pointer to "struct list_head".
332 *
333 * Returns true if deleted, false otherwise.
334 */
e79acf0e 335static bool tomoyo_del_domain(struct list_head *element)
847b173e 336{
e79acf0e
TH
337 struct tomoyo_domain_info *domain =
338 container_of(element, typeof(*domain), list);
847b173e
TH
339 struct tomoyo_acl_info *acl;
340 struct tomoyo_acl_info *tmp;
341 /*
342 * Since we don't protect whole execve() operation using SRCU,
343 * we need to recheck domain->users at this point.
344 *
345 * (1) Reader starts SRCU section upon execve().
346 * (2) Reader traverses tomoyo_domain_list and finds this domain.
347 * (3) Writer marks this domain as deleted.
348 * (4) Garbage collector removes this domain from tomoyo_domain_list
349 * because this domain is marked as deleted and used by nobody.
350 * (5) Reader saves reference to this domain into
351 * "struct linux_binprm"->cred->security .
352 * (6) Reader finishes SRCU section, although execve() operation has
353 * not finished yet.
354 * (7) Garbage collector waits for SRCU synchronization.
355 * (8) Garbage collector kfree() this domain because this domain is
356 * used by nobody.
357 * (9) Reader finishes execve() operation and restores this domain from
358 * "struct linux_binprm"->cred->security.
359 *
360 * By updating domain->users at (5), we can solve this race problem
361 * by rechecking domain->users at (8).
362 */
363 if (atomic_read(&domain->users))
364 return false;
365 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
e79acf0e 366 tomoyo_del_acl(&acl->list);
847b173e
TH
367 tomoyo_memory_free(acl);
368 }
369 tomoyo_put_name(domain->domainname);
370 return true;
371}
372
2066a361
TH
373/**
374 * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
375 *
376 * @element: Pointer to "struct list_head".
377 *
378 * Returns nothing.
379 */
380void tomoyo_del_condition(struct list_head *element)
381{
382 struct tomoyo_condition *cond = container_of(element, typeof(*cond),
383 head.list);
384 const u16 condc = cond->condc;
385 const u16 numbers_count = cond->numbers_count;
2ca9bf45 386 const u16 names_count = cond->names_count;
5b636857
TH
387 const u16 argc = cond->argc;
388 const u16 envc = cond->envc;
2066a361
TH
389 unsigned int i;
390 const struct tomoyo_condition_element *condp
391 = (const struct tomoyo_condition_element *) (cond + 1);
392 struct tomoyo_number_union *numbers_p
393 = (struct tomoyo_number_union *) (condp + condc);
2ca9bf45
TH
394 struct tomoyo_name_union *names_p
395 = (struct tomoyo_name_union *) (numbers_p + numbers_count);
5b636857
TH
396 const struct tomoyo_argv *argv
397 = (const struct tomoyo_argv *) (names_p + names_count);
398 const struct tomoyo_envp *envp
399 = (const struct tomoyo_envp *) (argv + argc);
2066a361
TH
400 for (i = 0; i < numbers_count; i++)
401 tomoyo_put_number_union(numbers_p++);
2ca9bf45
TH
402 for (i = 0; i < names_count; i++)
403 tomoyo_put_name_union(names_p++);
5b636857
TH
404 for (i = 0; i < argc; argv++, i++)
405 tomoyo_put_name(argv->value);
406 for (i = 0; i < envc; envp++, i++) {
407 tomoyo_put_name(envp->name);
408 tomoyo_put_name(envp->value);
409 }
2066a361 410}
847b173e 411
0df7e8b8
TH
412/**
413 * tomoyo_del_name - Delete members in "struct tomoyo_name".
414 *
415 * @element: Pointer to "struct list_head".
416 *
417 * Returns nothing.
418 */
e79acf0e 419static void tomoyo_del_name(struct list_head *element)
847b173e 420{
e2bf6907 421 const struct tomoyo_name *ptr =
0df7e8b8 422 container_of(element, typeof(*ptr), head.list);
847b173e
TH
423}
424
0df7e8b8
TH
425/**
426 * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
427 *
428 * @element: Pointer to "struct list_head".
429 *
430 * Returns nothing.
431 */
a98aa4de 432static void tomoyo_del_path_group(struct list_head *element)
7762fbff 433{
a98aa4de 434 struct tomoyo_path_group *member =
e79acf0e 435 container_of(element, typeof(*member), head.list);
7762fbff
TH
436 tomoyo_put_name(member->member_name);
437}
438
0df7e8b8
TH
439/**
440 * tomoyo_del_group - Delete "struct tomoyo_group".
441 *
442 * @element: Pointer to "struct list_head".
443 *
444 * Returns nothing.
445 */
a98aa4de 446static void tomoyo_del_group(struct list_head *element)
7762fbff 447{
a98aa4de 448 struct tomoyo_group *group =
0df7e8b8 449 container_of(element, typeof(*group), head.list);
7762fbff
TH
450 tomoyo_put_name(group->group_name);
451}
452
059d84db
TH
453/**
454 * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group".
455 *
456 * @element: Pointer to "struct list_head".
457 *
458 * Returns nothing.
459 */
460static inline void tomoyo_del_address_group(struct list_head *element)
461{
462 /* Nothing to do. */
463}
464
0df7e8b8
TH
465/**
466 * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
467 *
468 * @element: Pointer to "struct list_head".
469 *
470 * Returns nothing.
471 */
e79acf0e 472static void tomoyo_del_number_group(struct list_head *element)
4c3e9e2d 473{
a98aa4de
TH
474 struct tomoyo_number_group *member =
475 container_of(element, typeof(*member), head.list);
4c3e9e2d
TH
476}
477
0df7e8b8
TH
478/**
479 * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head".
480 *
481 * @id: One of values in "enum tomoyo_policy_id".
482 * @member_list: Pointer to "struct list_head".
483 *
484 * Returns true if some elements are deleted, false otherwise.
485 */
486static bool tomoyo_collect_member(const enum tomoyo_policy_id id,
487 struct list_head *member_list)
d2f8b234
TH
488{
489 struct tomoyo_acl_head *member;
490 list_for_each_entry(member, member_list, list) {
491 if (!member->is_deleted)
492 continue;
493 if (!tomoyo_add_to_gc(id, &member->list))
494 return false;
d2f8b234 495 }
0f2a55d5 496 return true;
d2f8b234
TH
497}
498
32997144
TH
499/**
500 * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info".
501 *
502 * @list: Pointer to "struct list_head".
503 *
504 * Returns true if some elements are deleted, false otherwise.
505 */
506static bool tomoyo_collect_acl(struct list_head *list)
d2f8b234
TH
507{
508 struct tomoyo_acl_info *acl;
32997144 509 list_for_each_entry(acl, list, list) {
d2f8b234
TH
510 if (!acl->is_deleted)
511 continue;
512 if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list))
513 return false;
d2f8b234
TH
514 }
515 return true;
516}
517
0df7e8b8
TH
518/**
519 * tomoyo_collect_entry - Scan lists for deleted elements.
520 *
521 * Returns nothing.
522 */
847b173e
TH
523static void tomoyo_collect_entry(void)
524{
d2f8b234 525 int i;
bd03a3e4
TH
526 enum tomoyo_policy_id id;
527 struct tomoyo_policy_namespace *ns;
528 int idx;
29282381
TH
529 if (mutex_lock_interruptible(&tomoyo_policy_lock))
530 return;
bd03a3e4 531 idx = tomoyo_read_lock();
847b173e
TH
532 {
533 struct tomoyo_domain_info *domain;
534 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
32997144 535 if (!tomoyo_collect_acl(&domain->acl_info_list))
d2f8b234 536 goto unlock;
847b173e
TH
537 if (!domain->is_deleted || atomic_read(&domain->users))
538 continue;
539 /*
540 * Nobody is referring this domain. But somebody may
541 * refer this domain after successful execve().
542 * We recheck domain->users after SRCU synchronization.
543 */
e79acf0e 544 if (!tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, &domain->list))
d2f8b234 545 goto unlock;
847b173e
TH
546 }
547 }
bd03a3e4
TH
548 list_for_each_entry_rcu(ns, &tomoyo_namespace_list, namespace_list) {
549 for (id = 0; id < TOMOYO_MAX_POLICY; id++)
550 if (!tomoyo_collect_member(id, &ns->policy_list[id]))
d2f8b234 551 goto unlock;
bd03a3e4
TH
552 for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++)
553 if (!tomoyo_collect_acl(&ns->acl_group[i]))
554 goto unlock;
555 for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
556 struct list_head *list = &ns->group_list[i];
557 struct tomoyo_group *group;
558 switch (i) {
559 case 0:
560 id = TOMOYO_ID_PATH_GROUP;
561 break;
059d84db 562 case 1:
bd03a3e4
TH
563 id = TOMOYO_ID_NUMBER_GROUP;
564 break;
059d84db
TH
565 default:
566 id = TOMOYO_ID_ADDRESS_GROUP;
567 break;
bd03a3e4
TH
568 }
569 list_for_each_entry(group, list, head.list) {
570 if (!tomoyo_collect_member
571 (id, &group->member_list))
572 goto unlock;
573 if (!list_empty(&group->member_list) ||
574 atomic_read(&group->head.users))
575 continue;
576 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
577 &group->head.list))
578 goto unlock;
579 }
847b173e
TH
580 }
581 }
2066a361
TH
582 id = TOMOYO_ID_CONDITION;
583 for (i = 0; i < TOMOYO_MAX_HASH + 1; i++) {
584 struct list_head *list = !i ?
585 &tomoyo_condition_list : &tomoyo_name_list[i - 1];
bd03a3e4
TH
586 struct tomoyo_shared_acl_head *ptr;
587 list_for_each_entry(ptr, list, list) {
588 if (atomic_read(&ptr->users))
4c3e9e2d 589 continue;
2066a361 590 if (!tomoyo_add_to_gc(id, &ptr->list))
d2f8b234 591 goto unlock;
4c3e9e2d 592 }
2066a361 593 id = TOMOYO_ID_NAME;
4c3e9e2d 594 }
bd03a3e4
TH
595unlock:
596 tomoyo_read_unlock(idx);
29282381 597 mutex_unlock(&tomoyo_policy_lock);
847b173e
TH
598}
599
2e503bbb
TH
600/**
601 * tomoyo_kfree_entry - Delete entries in tomoyo_gc_list.
602 *
603 * Returns true if some entries were kfree()d, false otherwise.
604 */
605static bool tomoyo_kfree_entry(void)
847b173e 606{
e2bf6907
TH
607 struct tomoyo_gc *p;
608 struct tomoyo_gc *tmp;
2e503bbb 609 bool result = false;
847b173e 610
2e503bbb 611 list_for_each_entry_safe(p, tmp, &tomoyo_gc_list, list) {
e79acf0e 612 struct list_head *element = p->element;
2e503bbb
TH
613
614 /*
615 * list_del_rcu() in tomoyo_add_to_gc() guarantees that the
616 * list element became no longer reachable from the list which
617 * the element was originally on (e.g. tomoyo_domain_list).
618 * Also, synchronize_srcu() in tomoyo_gc_thread() guarantees
619 * that the list element became no longer referenced by syscall
620 * users.
621 *
622 * However, there are three users which may still be using the
623 * list element. We need to defer until all of these users
624 * forget the list element.
625 *
626 * Firstly, defer until "struct tomoyo_io_buffer"->r.{domain,
627 * group,acl} and "struct tomoyo_io_buffer"->w.domain forget
628 * the list element.
629 */
630 if (tomoyo_struct_used_by_io_buffer(element))
631 continue;
632 /*
633 * Secondly, defer until all other elements in the
634 * tomoyo_gc_list list forget the list element.
635 */
636 if (tomoyo_element_linked_by_gc((const u8 *) element, p->size))
637 continue;
847b173e 638 switch (p->type) {
5448ec4f
TH
639 case TOMOYO_ID_TRANSITION_CONTROL:
640 tomoyo_del_transition_control(element);
847b173e 641 break;
1084307c 642 case TOMOYO_ID_AGGREGATOR:
e79acf0e 643 tomoyo_del_aggregator(element);
1084307c 644 break;
847b173e 645 case TOMOYO_ID_MANAGER:
e79acf0e 646 tomoyo_del_manager(element);
847b173e 647 break;
2066a361
TH
648 case TOMOYO_ID_CONDITION:
649 tomoyo_del_condition(element);
650 break;
847b173e 651 case TOMOYO_ID_NAME:
2e503bbb
TH
652 /*
653 * Thirdly, defer until all "struct tomoyo_io_buffer"
654 * ->r.w[] forget the list element.
655 */
656 if (tomoyo_name_used_by_io_buffer(
657 container_of(element, typeof(struct tomoyo_name),
658 head.list)->entry.name, p->size))
659 continue;
e79acf0e 660 tomoyo_del_name(element);
847b173e
TH
661 break;
662 case TOMOYO_ID_ACL:
e79acf0e 663 tomoyo_del_acl(element);
847b173e
TH
664 break;
665 case TOMOYO_ID_DOMAIN:
e79acf0e 666 if (!tomoyo_del_domain(element))
847b173e
TH
667 continue;
668 break;
7762fbff 669 case TOMOYO_ID_PATH_GROUP:
e79acf0e 670 tomoyo_del_path_group(element);
7762fbff 671 break;
059d84db
TH
672 case TOMOYO_ID_ADDRESS_GROUP:
673 tomoyo_del_address_group(element);
674 break;
a98aa4de
TH
675 case TOMOYO_ID_GROUP:
676 tomoyo_del_group(element);
4c3e9e2d
TH
677 break;
678 case TOMOYO_ID_NUMBER_GROUP:
e79acf0e 679 tomoyo_del_number_group(element);
847b173e 680 break;
0df7e8b8
TH
681 case TOMOYO_MAX_POLICY:
682 break;
847b173e 683 }
e79acf0e 684 tomoyo_memory_free(element);
847b173e
TH
685 list_del(&p->list);
686 kfree(p);
2e503bbb
TH
687 tomoyo_gc_list_len--;
688 result = true;
847b173e 689 }
2e503bbb 690 return result;
847b173e
TH
691}
692
0df7e8b8
TH
693/**
694 * tomoyo_gc_thread - Garbage collector thread function.
695 *
696 * @unused: Unused.
697 *
698 * In case OOM-killer choose this thread for termination, we create this thread
699 * as a short live thread whenever /sys/kernel/security/tomoyo/ interface was
700 * close()d.
701 *
702 * Returns 0.
703 */
847b173e
TH
704static int tomoyo_gc_thread(void *unused)
705{
2e503bbb
TH
706 /* Garbage collector thread is exclusive. */
707 static DEFINE_MUTEX(tomoyo_gc_mutex);
708 if (!mutex_trylock(&tomoyo_gc_mutex))
709 goto out;
09f464bf 710
2e503bbb
TH
711 do {
712 tomoyo_collect_entry();
713 if (list_empty(&tomoyo_gc_list))
714 break;
715 synchronize_srcu(&tomoyo_ss);
716 } while (tomoyo_kfree_entry());
717 {
718 struct tomoyo_io_buffer *head;
719 struct tomoyo_io_buffer *tmp;
720
721 spin_lock(&tomoyo_io_buffer_list_lock);
722 list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list,
723 list) {
724 if (head->users)
725 continue;
726 list_del(&head->list);
727 kfree(head->read_buf);
728 kfree(head->write_buf);
729 kfree(head);
847b173e 730 }
2e503bbb 731 spin_unlock(&tomoyo_io_buffer_list_lock);
847b173e 732 }
2e503bbb
TH
733 mutex_unlock(&tomoyo_gc_mutex);
734out:
735 /* This acts as do_exit(0). */
736 return 0;
847b173e
TH
737}
738
2e503bbb
TH
739/**
740 * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users.
741 *
742 * @head: Pointer to "struct tomoyo_io_buffer".
743 * @is_register: True if register, false if unregister.
744 *
745 * Returns nothing.
746 */
747void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register)
847b173e 748{
2e503bbb
TH
749 bool is_write = false;
750
751 spin_lock(&tomoyo_io_buffer_list_lock);
752 if (is_register) {
753 head->users = 1;
754 list_add(&head->list, &tomoyo_io_buffer_list);
755 } else {
756 is_write = head->write_buf != NULL;
757 if (!--head->users) {
758 list_del(&head->list);
759 kfree(head->read_buf);
760 kfree(head->write_buf);
761 kfree(head);
762 }
763 }
764 spin_unlock(&tomoyo_io_buffer_list_lock);
765 if (is_write) {
766 struct task_struct *task = kthread_create(tomoyo_gc_thread,
767 NULL,
768 "GC for TOMOYO");
769 if (!IS_ERR(task))
770 wake_up_process(task);
771 }
847b173e 772}